Skip to content

Commit 2683ab6

Browse files
committed
wip
1 parent 519ed17 commit 2683ab6

File tree

2 files changed

+155
-69
lines changed

2 files changed

+155
-69
lines changed

main.go

Lines changed: 153 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type sessionRecord struct {
4646

4747
type chain struct {
4848
isValid bool
49+
isSS bool
4950
s string
5051
}
5152

@@ -77,38 +78,72 @@ func main() {
7778
}
7879

7980
} else {
80-
jsonPath = "./test.json"
81-
82-
// read corresponding json file
83-
dat, err := ioutil.ReadFile(jsonPath)
81+
var path []string
82+
path = append(path, "./sessions")
83+
path = append(path, "")
84+
files, err := ioutil.ReadDir(path[0])
8485
if err != nil {
8586
log.Fatal(err)
8687
}
87-
// Unmarshal JSON file
88-
s := sessionRecord{}
89-
_ = json.Unmarshal([]byte(dat), &s)
9088

91-
// Insert Session
92-
ids, err := insertSession(&s)
93-
if err != nil {
94-
log.Fatal(fmt.Sprintf("Insert Sessions into DB failed: %q", err))
95-
}
96-
// Attempt to roughly build a chain of trust
97-
session := buildChain(&s)
89+
for _, f := range files {
9890

99-
// Insert Certificates
100-
idc, err := insertCertificates(session)
101-
if err != nil {
102-
log.Fatal(fmt.Sprintf("Insert Certificate into DB failed: %q", err))
103-
}
104-
// Create the relationship between certificates and sessions
105-
err = linkSessionCerts(ids, idc)
106-
if err != nil {
107-
log.Fatal(fmt.Sprintf("Could not link Certs and Session into DB: %q", err))
91+
path[1] = f.Name()
92+
jsonPath = strings.Join(path, "/")
93+
94+
// read corresponding json file
95+
dat, err := ioutil.ReadFile(jsonPath)
96+
if err != nil {
97+
log.Fatal(err)
98+
}
99+
// Unmarshal JSON file
100+
s := sessionRecord{}
101+
_ = json.Unmarshal([]byte(dat), &s)
102+
103+
if len(s.Certificates) > 0 {
104+
// Insert Session
105+
ids, err := insertSession(&s)
106+
if err != nil {
107+
log.Fatal(fmt.Sprintf("Insert Sessions into DB failed: %q", err))
108+
}
109+
// Attempt to roughly build a chain of trust
110+
session := buildChain(&s)
111+
112+
// Insert Certificates
113+
idc, err := insertCertificates(session)
114+
if err != nil {
115+
log.Fatal(fmt.Sprintf("Insert Certificate into DB failed: %q", err))
116+
}
117+
// Create the relationship between certificates and sessions
118+
err = linkSessionCerts(ids, idc)
119+
if err != nil {
120+
log.Fatal(fmt.Sprintf("Could not link Certs and Session into DB: %q", err))
121+
}
122+
123+
// Create ja3* records
124+
err = insertJA3(session)
125+
if err != nil {
126+
log.Fatal(fmt.Sprintf("Could not insert JA3 into DB: %q", err))
127+
}
128+
}
108129
}
109130
}
110131
}
111132

133+
func insertJA3(s *sessionRecord) error {
134+
q := `INSERT INTO "ja3" (hash, raw, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`
135+
_, err := db.Exec(q, s.JA3Digest, s.JA3, "ja3")
136+
if err != nil {
137+
return err
138+
}
139+
q = `INSERT INTO "ja3" (hash, raw, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`
140+
_, err = db.Exec(q, s.JA3SDigest, s.JA3S, "ja3s")
141+
if err != nil {
142+
return err
143+
}
144+
return nil
145+
}
146+
112147
// insertPublicKeys insert each public key of each certificate of a session
113148
func insertPublicKey(c x509.Certificate) (string, error) {
114149
pub, err := x509.ParsePKIXPublicKey(c.RawSubjectPublicKeyInfo)
@@ -119,22 +154,22 @@ func insertPublicKey(c x509.Certificate) (string, error) {
119154

120155
switch pub := pub.(type) {
121156
case *rsa.PublicKey:
122-
q := `INSERT INTO "public_key" (hash, type, modulus, exponent, modulus_size) VALUES ($1, $2, $3, $4, $5)`
123-
_, err := db.Query(q, hash, "RSA", (*BigNumber)(pub.N), pub.E, pub.Size())
157+
q := `INSERT INTO "public_key" (hash, type, modulus, exponent, modulus_size) VALUES ($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING`
158+
_, err := db.Exec(q, hash, "RSA", (*BigNumber)(pub.N), pub.E, pub.Size())
124159
if err != nil {
125-
return hash, nil
160+
return hash, err
126161
}
127162
case *dsa.PublicKey:
128-
q := `INSERT INTO "public_key" (hash, type, "G", "P", "Q", "Y") VALUES ($1, $2, $3, $4, $5, $6)`
129-
_, err := db.Query(q, hash, "DSA", (*BigNumber)(pub.Parameters.G), (*BigNumber)(pub.Parameters.P), (*BigNumber)(pub.Parameters.Q), (*BigNumber)(pub.Y))
163+
q := `INSERT INTO "public_key" (hash, type, "G", "P", "Q", "Y") VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT DO NOTHING`
164+
_, err := db.Exec(q, hash, "DSA", (*BigNumber)(pub.Parameters.G), (*BigNumber)(pub.Parameters.P), (*BigNumber)(pub.Parameters.Q), (*BigNumber)(pub.Y))
130165
if err != nil {
131-
return hash, nil
166+
return hash, err
132167
}
133168
case *ecdsa.PublicKey:
134-
q := `INSERT INTO "public_key" (hash, type, "Y", "X", "P", "N", "B", "bitsize", "Gx", "Gy") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
135-
_, err := db.Query(q, hash, "ECDSA", pub.Y, pub.X, pub.Curve.Params().P, pub.Curve.Params().N, pub.Curve.Params().B, pub.Curve.Params().BitSize, pub.Curve.Params().Gx, pub.Curve.Params().Gy)
169+
q := `INSERT INTO "public_key" (hash, type, "Y", "X", "P", "N", "B", "bitsize", "Gx", "Gy", "curve_name") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) ON CONFLICT DO NOTHING`
170+
_, err := db.Exec(q, hash, "ECDSA", (*BigNumber)(pub.Y), (*BigNumber)(pub.X), (*BigNumber)(pub.Curve.Params().P), (*BigNumber)(pub.Curve.Params().N), (*BigNumber)(pub.Curve.Params().B), pub.Curve.Params().BitSize, (*BigNumber)(pub.Curve.Params().Gx), (*BigNumber)(pub.Curve.Params().Gy), pub.Params().Name)
136171
if err != nil {
137-
return hash, nil
172+
return hash, err
138173
}
139174
default:
140175
return hash, fmt.Errorf("PKIx: could not determine the type of key %g", pub)
@@ -149,8 +184,8 @@ func (bn *BigNumber) Value() (driver.Value, error) {
149184
// linkSessionCerts creates the link between a session and its certificates
150185
func linkSessionCerts(ids int64, idc []string) error {
151186
for _, i := range idc {
152-
q := `INSERT INTO "many_sessionRecord_has_many_certificate" ("id_sessionRecord", "hash_certificate") VALUES ($1, $2)`
153-
_, err := db.Query(q, ids, i)
187+
q := `INSERT INTO "many_sessionRecord_has_many_certificate" ("id_sessionRecord", "hash_certificate") VALUES ($1, $2) ON CONFLICT DO NOTHING `
188+
_, err := db.Exec(q, ids, i)
154189
if err != nil {
155190
return err
156191
}
@@ -164,57 +199,107 @@ func linkSessionCerts(ids int64, idc []string) error {
164199
// does not touch the original slice and mark the chain as invalid.
165200
func buildChain(s *sessionRecord) *sessionRecord {
166201
certChain := make([]certMapElm, 0)
202+
// First find if there are any duplicates certificate
203+
dedup := unique(s.Certificates)
204+
deduplen := len(dedup)
205+
206+
if deduplen > 1 {
207+
// Then we find the leaf
208+
removed := 0
209+
for i, c := range dedup {
210+
if !c.Certificate.IsCA {
211+
certChain = append(certChain, c)
212+
// Remove this element from the list
213+
dedup = append(dedup[:i-removed], dedup[i+1-removed:]...)
214+
removed++
215+
}
216+
}
167217

168-
// First we find the leaf
169-
for _, c := range s.Certificates {
170-
fmt.Println(c.Certificate.Issuer.String())
171-
fmt.Println(c.Certificate.Subject.String())
172-
fmt.Println(c.Certificate.Subject.String() == c.Certificate.Issuer.String())
173-
if !c.Certificate.IsCA {
174-
certChain = append(certChain, c)
218+
cursor := len(certChain)
219+
// Find the parent of each certificate
220+
for i := 0; i < cursor; i++ {
221+
p, success, isSS := findParent(dedup, certChain[i])
222+
// if we found a root, no need to go any further
223+
if isSS {
224+
p.chain.isSS = true
225+
certChain = append(certChain, p)
226+
break
227+
}
228+
if success {
229+
p.chain.isSS = false
230+
certChain = append(certChain, p)
231+
}
232+
cursor = len(certChain)
175233
}
176-
}
177-
// Find the parent of each certificate
178-
for _, _ = range s.Certificates {
179-
for i, _ := range s.Certificates {
180-
if s.Certificates[i].Certificate.Subject.String() == certChain[len(certChain)-1].Issuer.String() {
181-
certChain = append(certChain, s.Certificates[i])
234+
235+
// Write the new chain if it's valid
236+
if len(certChain) >= deduplen-1 {
237+
cstr := make([]string, 0)
238+
for i := len(certChain) - 1; i >= 0; i-- {
239+
certChain[i].chain.isValid = true
240+
if !certChain[i].chain.isSS {
241+
cstr = append(cstr, certChain[i].CertHash)
242+
certChain[i].chain.s = strings.Join(cstr, ".")
243+
}
182244
}
245+
tmp := s
246+
tmp.Certificates = certChain
247+
return tmp
183248
}
249+
// Only one cert in the chain
250+
} else {
251+
s.Certificates[0].chain = chain{true, s.Certificates[0].Certificate.Issuer.String() == s.Certificates[0].Certificate.Subject.String(), s.Certificates[0].CertHash}
184252
}
185-
// Write the new chain
186-
if len(certChain) == len(s.Certificates) {
187-
cstr := make([]string, 0)
188-
for i := len(certChain) - 1; i >= 0; i-- {
189-
certChain[i].chain.isValid = true
190-
cstr = append(cstr, certChain[i].CertHash)
191-
certChain[i].chain.s = strings.Join(cstr, ".")
253+
254+
return s
255+
}
256+
257+
func findParent(dedup []certMapElm, c certMapElm) (certMapElm, bool, bool) {
258+
// A Root or SSC signs itself
259+
if c.Certificate.Subject.String() == c.Certificate.Issuer.String() {
260+
return c, true, true
261+
}
262+
263+
// A leaf or a node has a parent
264+
for _, candidate := range dedup {
265+
if candidate.Certificate.Subject.String() == c.Certificate.Issuer.String() {
266+
return candidate, true, false
192267
}
193-
tmp := s
194-
tmp.Certificates = certChain
195-
return tmp
196268
}
197-
return s
269+
270+
return c, false, false
271+
}
272+
273+
func unique(s []certMapElm) []certMapElm {
274+
keys := make(map[string]bool)
275+
var list []certMapElm
276+
for _, entry := range s {
277+
if _, value := keys[entry.CertHash]; !value {
278+
keys[entry.CertHash] = true
279+
list = append(list, entry)
280+
}
281+
}
282+
return list
198283
}
199284

200285
func insertCertificate(c certMapElm) (string, error) {
201-
q := `INSERT INTO "certificate" (hash, "is_CA", issuer, subject, cert_chain, is_valid_chain, file_path) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING hash`
202-
var hash string
203-
err := db.QueryRow(q, c.CertHash, c.Certificate.IsCA, c.Certificate.Issuer.String(), c.Certificate.Subject.String(), c.chain.s, c.chain.isValid, getFullPath(c.CertHash)).Scan(&hash)
286+
q := `INSERT INTO "certificate" (hash, "is_CA", "is_SS", issuer, subject, cert_chain, is_valid_chain, file_path) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT DO NOTHING`
287+
_, err := db.Exec(q, c.CertHash, c.Certificate.IsCA, c.chain.isSS, c.Certificate.Issuer.String(), c.Certificate.Subject.String(), c.chain.s, c.chain.isValid, getFullPath(c.CertHash))
204288
if err != nil {
205-
return hash, err
289+
return c.CertHash, err
206290
}
207291
key, err := insertPublicKey(*c.Certificate)
208292
if err != nil {
209-
return hash, err
293+
return c.CertHash, err
210294
}
211-
212-
q = `INSERT INTO "many_certificate_has_many_public_key" ("hash_certificate", "hash_public_key") VALUES ($1, $2)`
213-
_, err = db.Query(q, hash, key)
295+
fmt.Println(c.CertHash)
296+
fmt.Println(key)
297+
q = `INSERT INTO "many_certificate_has_many_public_key" ("hash_certificate", "hash_public_key") VALUES ($1, $2) ON CONFLICT DO NOTHING `
298+
_, err = db.Exec(q, c.CertHash, key)
214299
if err != nil {
215-
return hash, err
300+
return c.CertHash, err
216301
}
217-
return hash, nil
302+
return c.CertHash, nil
218303
}
219304

220305
// getFullPath takes a certificate's hash and return the full path to

passivessl.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ CREATE TABLE public.certificate(
6464
is_valid_chain bool NOT NULL DEFAULT false,
6565
"notBefore" time,
6666
"notAfter" time,
67+
"isSS" bool NOT NULL DEFAULT false,
6768
CONSTRAINT certificate_pk PRIMARY KEY (hash)
6869

6970
);
@@ -117,7 +118,7 @@ ALTER TABLE public."sessionRecord" OWNER TO postgres;
117118
CREATE TABLE public.ja3(
118119
hash bytea NOT NULL,
119120
raw text,
120-
type smallint NOT NULL,
121+
type varchar(16) NOT NULL,
121122
CONSTRAINT j3a_pk PRIMARY KEY (hash)
122123

123124
);

0 commit comments

Comments
 (0)