Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
KIT-CA
websearch
Commits
26ad720e
Commit
26ad720e
authored
Mar 18, 2017
by
Heiko Reese
Browse files
More documentation, little refactoring
parent
42b72864
Changes
6
Hide whitespace changes
Inline
Side-by-side
ca-websearch/daemon.go
View file @
26ad720e
...
...
@@ -13,6 +13,7 @@ import (
"net/http"
"net/http/fcgi"
"path/filepath"
"sort"
"strings"
)
...
...
@@ -29,7 +30,7 @@ var (
ccache
CertCache
allCertDir
string
watcherDone
chan
bool
newFileChan
chan
string
=
make
(
chan
string
,
64
)
newFileChan
chan
string
)
func
init
()
{
...
...
@@ -85,6 +86,7 @@ func searchHandler(w http.ResponseWriter, r *http.Request) {
)
filter
:=
MakeSimpleFilter
(
query
)
results
:=
ccache
.
Filter
(
filter
)
sort
.
Sort
(
DefaultResultOrder
(
results
))
switch
format
{
case
"json"
:
case
"html"
:
...
...
@@ -102,7 +104,7 @@ func main() {
// create watcher for new certificates
log
.
Println
(
"Starting filewatcher for directory"
,
allCertDir
)
NewDirectoryWatcher
(
allCertDir
,
watcherDone
,
newFileChan
)
_
,
newFileChan
,
watcherDone
=
NewDirectoryWatcher
(
allCertDir
)
go
func
(
newFileChan
chan
string
)
{
for
newcert
:=
range
newFileChan
{
for
_
,
c
:=
range
ReadCertificates
(
newcert
)
{
...
...
certcache.go
View file @
26ad720e
...
...
@@ -7,11 +7,13 @@ import (
"sync"
)
// CertCache provides a map[string]*SearchableCert that is thread-safe
type
CertCache
struct
{
certs
map
[
string
]
*
SearchableCert
sync
.
RWMutex
}
// SCFilter functions implement a selection criteria for a SearchableCert
type
SCFilter
func
(
*
SearchableCert
)
bool
func
NewCertCache
()
CertCache
{
...
...
@@ -20,6 +22,7 @@ func NewCertCache() CertCache {
}
}
// Add a certificate to a CertCache
func
(
cc
*
CertCache
)
Add
(
cert
*
x509
.
Certificate
)
(
*
SearchableCert
,
bool
)
{
searchableCert
:=
CertToSearchable
(
cert
)
...
...
@@ -31,12 +34,14 @@ func (cc *CertCache) Add(cert *x509.Certificate) (*SearchableCert, bool) {
return
&
searchableCert
,
isPresent
}
// Delete a certificate from a CertCache
func
(
cc
*
CertCache
)
Delete
(
serial
string
)
{
cc
.
Lock
()
delete
(
cc
.
certs
,
serial
)
cc
.
Unlock
()
}
// Len returns the number of SearchableCerts in a CertCache
func
(
cc
*
CertCache
)
Len
()
int
{
cc
.
RLock
()
l
:=
len
(
cc
.
certs
)
...
...
@@ -44,6 +49,7 @@ func (cc *CertCache) Len() int {
return
l
}
// Get retrieves a SearchableCert by serial number, return nil on failure
func
(
cc
*
CertCache
)
Get
(
serial
string
)
*
SearchableCert
{
cc
.
RLock
()
cert
,
present
:=
cc
.
certs
[
serial
]
...
...
@@ -55,6 +61,7 @@ func (cc *CertCache) Get(serial string) *SearchableCert {
}
}
// Filter returns all SearchableCerts that match the filter's criteria
func
(
cc
*
CertCache
)
Filter
(
filter
SCFilter
)
[]
*
SearchableCert
{
var
matches
[]
*
SearchableCert
...
...
@@ -67,3 +74,32 @@ func (cc *CertCache) Filter(filter SCFilter) []*SearchableCert {
cc
.
RUnlock
()
return
matches
}
// sort search results in a "helpful" way
type
DefaultResultOrder
[]
*
SearchableCert
func
(
r
DefaultResultOrder
)
Len
()
int
{
return
len
(
r
)
}
func
(
r
DefaultResultOrder
)
Swap
(
i
,
j
int
)
{
r
[
i
],
r
[
j
]
=
r
[
j
],
r
[
i
]
}
func
(
r
DefaultResultOrder
)
Less
(
i
,
j
int
)
bool
{
switch
{
case
r
[
i
]
.
sortingKeyType
<
r
[
j
]
.
sortingKeyType
:
return
true
case
r
[
i
]
.
sortingKeyType
>
r
[
j
]
.
sortingKeyType
:
return
false
default
:
switch
{
case
r
[
i
]
.
RawCertificate
.
Subject
.
CommonName
<
r
[
j
]
.
RawCertificate
.
Subject
.
CommonName
:
return
true
case
r
[
i
]
.
RawCertificate
.
Subject
.
CommonName
>
r
[
j
]
.
RawCertificate
.
Subject
.
CommonName
:
return
false
default
:
return
r
[
i
]
.
RawCertificate
.
NotBefore
.
Before
(
r
[
j
]
.
RawCertificate
.
NotBefore
)
}
}
}
certreader.go
View file @
26ad720e
...
...
@@ -7,6 +7,7 @@ import (
"log"
)
// ReadCertificates reads alls x509 certificates from a list of input files. Errors are logged and skipped.
func
ReadCertificates
(
filenames
...
string
)
[]
*
x509
.
Certificate
{
var
(
allcerts
[]
*
x509
.
Certificate
=
make
([]
*
x509
.
Certificate
,
0
,
len
(
filenames
))
...
...
@@ -36,7 +37,7 @@ func ReadCertificates(filenames ...string) []*x509.Certificate {
}
}
}
else
{
log
.
Print
ln
(
err
)
log
.
Print
f
(
"Error reading file %s: %s"
,
filename
,
err
)
}
}
return
allcerts
...
...
filewatcher.go
View file @
26ad720e
...
...
@@ -5,7 +5,17 @@ import (
"log"
)
func
NewDirectoryWatcher
(
path
string
,
watcherDone
chan
bool
,
newFileChan
chan
string
)
*
fsnotify
.
Watcher
{
// NewDirectoryWatcher watches path for newly written files. It returns three values
// * the underlying fsnotify.Watcher
// * a chan string that receives the filename of newly written files and
// * a chan bool. Send any value in to stop the watching goroutines.
func
NewDirectoryWatcher
(
path
string
)
(
*
fsnotify
.
Watcher
,
chan
string
,
chan
bool
)
{
var
(
watcherDone
chan
bool
exitEventRoutine
chan
bool
newFileChan
chan
string
=
make
(
chan
string
,
64
)
)
watcher
,
err
:=
fsnotify
.
NewWatcher
()
if
err
!=
nil
{
log
.
Fatal
(
err
)
...
...
@@ -19,7 +29,9 @@ func NewDirectoryWatcher(path string, watcherDone chan bool, newFileChan chan st
newFileChan
<-
event
.
Name
}
case
err
:=
<-
watcher
.
Errors
:
log
.
Println
(
"error:"
,
err
)
log
.
Printf
(
"Error watching path %s: %s"
,
path
,
err
)
case
<-
watcherDone
:
return
}
}
}()
...
...
@@ -30,8 +42,11 @@ func NewDirectoryWatcher(path string, watcherDone chan bool, newFileChan chan st
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
// wait for stop signal
<-
watcherDone
// stop the other goroutine
exitEventRoutine
<-
true
}()
return
watcher
return
watcher
,
newFileChan
,
watcherDone
}
redirect.go
View file @
26ad720e
...
...
@@ -7,8 +7,8 @@ import (
)
var
(
serialG2
Star
t
big
.
Int
serialG1
Cutoff
big
.
Int
serialG2
Firs
t
big
.
Int
serialG1
Final
big
.
Int
errorCannotConvert
=
errors
.
New
(
"Unable to convert serial number to bigint"
)
errorUnknownCA
=
errors
.
New
(
"Unable to determine CA generation"
)
RedirTemplates
=
map
[
string
]
string
{
...
...
@@ -18,8 +18,10 @@ var (
)
func
init
()
{
serialG2Start
.
SetString
(
"8926168349745120614054526923"
,
10
)
serialG1Cutoff
.
SetString
(
"99000000000000000000000000000"
,
10
)
// TODO: anpassen sobald bekannt
// this is the serial of the first certificate of KIT-CA G2
serialG2First
.
SetString
(
"8926168349745120614054526923"
,
10
)
// this is the serial of the last certificate of KIT-CA G1
serialG1Final
.
SetString
(
"9999999999999999999999999999"
,
10
)
// TODO: anpassen sobald bekannt
}
...
...
@@ -30,13 +32,13 @@ func GetIssuer(serial string, ccache *CertCache) (string, error) {
if
!
ok
{
return
""
,
errorCannotConvert
}
/* das erlaubt dann nicht-legale seriennummern an den gesicherten enden
/*
auskommentiert, weil:
das erlaubt dann nicht-legale seriennummern an den gesicherten enden
// alte CA (kurze nummern, serial kleiner als erstes g2)
if len(serial) == 8 || len(serial) == 14 || sernum.Cmp(&serialG2
Star
t) < 1 {
if len(serial) == 8 || len(serial) == 14 || sernum.Cmp(&serialG2
Firs
t) < 1 {
return kitcag1, nil
}
// neue CA (seriennummer größer als letztes g1)
if sernum.Cmp(&serialG1
Cutoff
) == 1 {
if sernum.Cmp(&serialG1
Final
) == 1 {
return kitcag2, nil
}
*/
...
...
searchablecert.go
View file @
26ad720e
...
...
@@ -5,6 +5,7 @@ import (
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"git.scc.kit.edu/heiko.reese/CertificateStats"
"log"
"reflect"
"regexp"
...
...
@@ -12,25 +13,37 @@ import (
"time"
)
var
(
Benutzer
=
"benutzer"
Server
=
"server"
Pseudonym
=
"pseudonym"
Gruppe
=
"gruppe"
Extern
=
"extern"
)
type
SearchableCert
struct
{
Serial
string
`json:serial`
HexSerial
string
`json:hexserial`
SignatureAlgorithm
string
`json:sigalg`
Subject
string
`json:subject`
Issuer
string
`json:issuer`
KeyLength
int
`json:keylength`
NotBefore
time
.
Time
`json:notbefore`
NotAfter
time
.
Time
`json:notafter`
DNSNames
[]
string
`json:san`
EmailAddresses
[]
string
`json:email`
IPAddresses
[]
string
`json:ip`
CAGeneration
*
string
searchablestring
string
// TODO
RawCertificate
*
x509
.
Certificate
Serial
string
`json:serial`
HexSerial
string
`json:hexserial`
SignatureAlgorithm
string
`json:sigalg`
Subject
string
`json:subject`
Issuer
string
`json:issuer`
KeyLength
int
`json:keylength`
NotBefore
time
.
Time
`json:notbefore`
NotAfter
time
.
Time
`json:notafter`
DNSNames
[]
string
`json:dnsnames`
EmailAddresses
[]
string
`json:emails`
IPAddresses
[]
string
`json:ipaddresses`
CAGeneration
*
string
`json:whichca`
Type
*
string
`json:type`
sortingKeyType
int
`json:-`
searchablestring
string
`json:-`
RawCertificate
*
x509
.
Certificate
`json:-`
}
// NeverMatch does not match any SearchableCert
func
NeverMatch
(
c
*
SearchableCert
)
bool
{
return
false
}
// MakeSimpleFilter creates a SCFilter that based on a simple substring match
func
MakeSimpleFilter
(
query
string
)
SCFilter
{
// TODO: better cleanup of query string
quoted
:=
strings
.
ToLower
(
regexp
.
QuoteMeta
(
query
))
...
...
@@ -49,6 +62,10 @@ func MakeSimpleFilter(query string) SCFilter {
}
}
// 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
// readability.
func
DnToString
(
n
pkix
.
Name
)
string
{
var
parts
[]
string
// CN
...
...
@@ -83,6 +100,7 @@ func DnToString(n pkix.Name) string {
return
strings
.
Join
(
parts
,
","
)
}
// CertToSearchable converts an x509.Certificate into a SearchableCert
func
CertToSearchable
(
c
*
x509
.
Certificate
)
SearchableCert
{
cert
:=
SearchableCert
{
Serial
:
c
.
SerialNumber
.
Text
(
10
),
...
...
@@ -112,6 +130,7 @@ func CertToSearchable(c *x509.Certificate) SearchableCert {
cert
.
CAGeneration
=
&
kitcag2
}
// build string used for simple search
var
buffer
bytes
.
Buffer
buffer
.
WriteString
(
cert
.
Serial
)
buffer
.
WriteString
(
" "
)
...
...
@@ -125,5 +144,24 @@ func CertToSearchable(c *x509.Certificate) SearchableCert {
buffer
.
WriteString
(
strings
.
Join
(
cert
.
IPAddresses
,
" "
))
cert
.
searchablestring
=
strings
.
ToLower
(
buffer
.
String
())
// Sorting order: Group > User > Ext > Server > Pseudonym
switch
{
case
CertificateStats
.
FilterIsPseudonym
(
c
)
:
cert
.
Type
=
&
Pseudonym
cert
.
sortingKeyType
=
16
case
CertificateStats
.
FilterIsGroup
(
c
)
:
cert
.
Type
=
&
Gruppe
cert
.
sortingKeyType
=
1
case
CertificateStats
.
FilterIsExternal
(
c
)
:
cert
.
Type
=
&
Extern
cert
.
sortingKeyType
=
4
case
CertificateStats
.
FilterIsNutzer
(
c
)
:
cert
.
Type
=
&
Benutzer
cert
.
sortingKeyType
=
2
default
:
cert
.
Type
=
&
Server
cert
.
sortingKeyType
=
8
}
return
cert
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment