Commit b55eb698 authored by Heiko Reese's avatar Heiko Reese
Browse files

Added first prototype for emailIndex and /mailtocert-Handler

parent 3ce51e8a
......@@ -137,9 +137,14 @@ func downloadHandler(w http.ResponseWriter, r *http.Request) {
}
}
func mailtocertHandler(w http.ResponseWriter, r *http.Request) {
//serial := mux.Vars(r)["serial"]
http.Error(w, "not implemented", http.StatusBadRequest)
func emailtocertHandler(w http.ResponseWriter, r *http.Request) {
email := mux.Vars(r)["email"]
results := ccache.IndexEmail.Get(email)
// TODO: check expiration and revocation
//c.NotAfter.After(time.Now())
w.Header().Set("cache-control", "no-store")
w.Header().Set("Content-Type", "application/json")
w.Write(results.JSONString(AllWatchers))
}
func main() {
......@@ -182,10 +187,10 @@ func main() {
Methods("GET").
HandlerFunc(downloadHandler)
// add mailtocert handler
r.Path("/mailtocert/v1/{serial:[0-9]+}").
// add emailtocert handler
r.Path("/emailtocert/v1/{email:[0-9]+}").
Methods("GET").
HandlerFunc(mailtocertHandler)
HandlerFunc(emailtocertHandler)
// add request dumping handler
r.Path("/dumpreq").
......
......@@ -2,8 +2,7 @@ package websearch
import (
"crypto/x509"
_ "encoding/gob"
_ "log"
"strings"
"sync"
)
......@@ -11,6 +10,7 @@ import (
type CertCache struct {
certs map[string]*SearchableCert
sync.RWMutex
IndexEmail CertIndex
}
// SCFilter functions implement a selection criteria for a SearchableCert
......@@ -18,7 +18,8 @@ type SCFilter func(*SearchableCert) bool
func NewCertCache() CertCache {
return CertCache{
certs: make(map[string]*SearchableCert),
certs: make(map[string]*SearchableCert),
IndexEmail: NewCertIndex(),
}
}
......@@ -32,6 +33,13 @@ func (cc *CertCache) Add(cert *x509.Certificate) (*SearchableCert, bool) {
cc.certs[searchableCert.Serial] = &searchableCert
cc.Unlock()
// add certificate to email index
for _, email := range searchableCert.EmailAddresses {
if FilterEncryptionEmail(&searchableCert) {
cc.IndexEmail.Add(strings.ToLower(email), &searchableCert)
}
}
return &searchableCert, isPresent
}
......@@ -64,7 +72,7 @@ func (cc *CertCache) Get(serial string) *SearchableCert {
// Filter returns all SearchableCerts that match the filter's criteria
func (cc *CertCache) Filter(filter SCFilter) Searchresults {
var matches []*SearchableCert
var matches Searchresults
cc.RLock()
for _, c := range cc.certs {
......
package websearch
import (
"sync"
)
// CertIndex provides a mapping between a string and a set of
// certificates in a thread-safe way
type CertIndex struct {
certs map[string]map[string]*SearchableCert
sync.RWMutex
}
func NewCertIndex() CertIndex {
return CertIndex{
certs: make(map[string]map[string]*SearchableCert),
}
}
// Add cert to the set which is associated with key
func (ci *CertIndex) Add(key string, cert *SearchableCert) {
ci.Lock()
keyMap, present := ci.certs[key]
if present {
// assume Serial is unique
keyMap[cert.Serial] = cert
} else {
ci.certs[key] = map[string]*SearchableCert{
cert.Serial: cert,
}
}
ci.Unlock()
}
// Get returns an array of all certificates for a key
func (ci *CertIndex) Get(key string) Searchresults {
var matches Searchresults
ci.RLock()
serialMap, present := ci.certs[key]
if present {
matches = make(Searchresults, len(serialMap))
var idx = 0
for _, c := range serialMap {
matches[idx] = c
idx++
}
} else {
matches = make(Searchresults, 0)
}
ci.RUnlock()
return matches
}
......@@ -280,6 +280,32 @@ func MakePublicSearchFilter(query string, visibilityWatcher *AttributeState) SCF
}
}
func FilterEncryptionEmail(c *SearchableCert) bool {
// only match certificates that contain at least one email address
if len(c.EmailAddresses) < 1 {
return false
}
// check if the KeyEncipherment KeyUsage bit is set
if c.rawCertificate.KeyUsage&x509.KeyUsageKeyEncipherment != x509.KeyUsageKeyEncipherment {
return false
}
// check if ExtendedKeyUsage contains EmailProtection
foundEmailProtection := false
for _, extension := range c.rawCertificate.ExtKeyUsage {
if extension == x509.ExtKeyUsageEmailProtection {
foundEmailProtection = true
}
}
if !foundEmailProtection {
return false
}
// filter RA-Ops
if strings.HasPrefix(c.rawCertificate.Subject.CommonName, "PN") && (strings.Contains(c.rawCertificate.Subject.CommonName, "Teilnehmerservice") || strings.HasSuffix(c.rawCertificate.Subject.CommonName, "RA-Operator")) {
return false
}
return true
}
// DnToString turns a DistinguishedName into a readable string
// According to the relevant RFCs, there is no canonical form.
// The returned format is designed to be sortable and have good
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment