Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: web_page_replay_go/src/webpagereplay/certs.go

Issue 2992253002: [wpr-go] Use a dummy cert if no cert is recorded (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package webpagereplay 5 package webpagereplay
6 6
7 import ( 7 import (
8 "crypto" 8 "crypto"
9 "crypto/rand" 9 "crypto/rand"
10 "crypto/tls" 10 "crypto/tls"
11 "crypto/x509" 11 "crypto/x509"
12 "fmt" 12 "fmt"
13 "io" 13 "io"
14 "net"
14 "time" 15 "time"
15 ) 16 )
16 17
17 // Returns a TLS configuration that serves a recorded server leaf cert signed by 18 // Returns a TLS configuration that serves a recorded server leaf cert signed by
18 // root CA. 19 // root CA.
19 func ReplayTLSConfig(root tls.Certificate, a *Archive) (*tls.Config, error) { 20 func ReplayTLSConfig(root tls.Certificate, a *Archive) (*tls.Config, error) {
20 root_cert, err := getRootCert(root) 21 root_cert, err := getRootCert(root)
21 if err != nil { 22 if err != nil {
22 return nil, fmt.Errorf("bad local cert: %v", err) 23 return nil, fmt.Errorf("bad local cert: %v", err)
23 } 24 }
24 » tp := &tlsProxy{&root, root_cert, a, nil} 25 » tp := &tlsProxy{&root, root_cert, a, nil, make(map[string][]byte)}
25 return &tls.Config{ 26 return &tls.Config{
26 GetConfigForClient: tp.getReplayConfigForClient, 27 GetConfigForClient: tp.getReplayConfigForClient,
27 }, nil 28 }, nil
28 } 29 }
29 30
30 // Returns a TLS configuration that serves a server leaf cert fetched over the 31 // Returns a TLS configuration that serves a server leaf cert fetched over the
31 // network on demand. 32 // network on demand.
32 func RecordTLSConfig(root tls.Certificate, w *WritableArchive) (*tls.Config, err or) { 33 func RecordTLSConfig(root tls.Certificate, w *WritableArchive) (*tls.Config, err or) {
33 root_cert, err := getRootCert(root) 34 root_cert, err := getRootCert(root)
34 if err != nil { 35 if err != nil {
35 return nil, fmt.Errorf("bad local cert: %v", err) 36 return nil, fmt.Errorf("bad local cert: %v", err)
36 } 37 }
37 » tp := &tlsProxy{&root, root_cert, nil, w} 38 » tp := &tlsProxy{&root, root_cert, nil, w, nil}
38 return &tls.Config{ 39 return &tls.Config{
39 GetConfigForClient: tp.getRecordConfigForClient, 40 GetConfigForClient: tp.getRecordConfigForClient,
40 }, nil 41 }, nil
41 } 42 }
42 43
43 func getRootCert(root tls.Certificate) (*x509.Certificate, error) { 44 func getRootCert(root tls.Certificate) (*x509.Certificate, error) {
44 root_cert, err := x509.ParseCertificate(root.Certificate[0]) 45 root_cert, err := x509.ParseCertificate(root.Certificate[0])
45 if err != nil { 46 if err != nil {
46 return nil, err 47 return nil, err
47 } 48 }
48 root_cert.IsCA = true 49 root_cert.IsCA = true
49 root_cert.BasicConstraintsValid = true 50 root_cert.BasicConstraintsValid = true
50 return root_cert, nil 51 return root_cert, nil
51 } 52 }
52 53
54 // Mints a dummy server cert when the real one is not recorded.
55 func MintDummyCertificate(serverName string, rootCert *x509.Certificate, rootKey crypto.PrivateKey) ([]byte, string, error) {
56 template := rootCert
57 if ip := net.ParseIP(serverName); ip != nil {
58 template.IPAddresses = []net.IP{ip}
59 } else {
60 template.DNSNames = []string{serverName}
61 }
62 var buf [20]byte
63 if _, err := io.ReadFull(rand.Reader, buf[:]); err != nil {
64 return nil, "", fmt.Errorf("create cert failed: %v", err)
65 }
66 template.SerialNumber.SetBytes(buf[:])
67 template.Issuer = template.Subject
68 derBytes, err := x509.CreateCertificate(rand.Reader, template, template, template.PublicKey, rootKey)
69 if err != nil {
70 return nil, "", fmt.Errorf("create cert failed: %v", err)
71 }
72 return derBytes, "", err
73 }
74
53 // Returns DER encoded server cert. 75 // Returns DER encoded server cert.
54 func MintServerCert(serverName string, rootCert *x509.Certificate, rootKey crypt o.PrivateKey) ([]byte, string, error) { 76 func MintServerCert(serverName string, rootCert *x509.Certificate, rootKey crypt o.PrivateKey) ([]byte, string, error) {
55 conn, err := tls.Dial("tcp", fmt.Sprintf("%s:443", serverName), &tls.Con fig{ 77 conn, err := tls.Dial("tcp", fmt.Sprintf("%s:443", serverName), &tls.Con fig{
56 NextProtos: []string{"h2", "http/1.1"}, 78 NextProtos: []string{"h2", "http/1.1"},
57 }) 79 })
58 if err != nil { 80 if err != nil {
59 return nil, "", fmt.Errorf("Couldn't reach host %s: %v", serverN ame, err) 81 return nil, "", fmt.Errorf("Couldn't reach host %s: %v", serverN ame, err)
60 } 82 }
61 defer conn.Close() 83 defer conn.Close()
62 conn.Handshake() 84 conn.Handshake()
(...skipping 15 matching lines...) Expand all
78 negotiatedProtocol := conn.ConnectionState().NegotiatedProtocol 100 negotiatedProtocol := conn.ConnectionState().NegotiatedProtocol
79 derBytes, err := x509.CreateCertificate(rand.Reader, template, rootCert, template.PublicKey, rootKey) 101 derBytes, err := x509.CreateCertificate(rand.Reader, template, rootCert, template.PublicKey, rootKey)
80 return derBytes, negotiatedProtocol, err 102 return derBytes, negotiatedProtocol, err
81 } 103 }
82 104
83 type tlsProxy struct { 105 type tlsProxy struct {
84 root *tls.Certificate 106 root *tls.Certificate
85 root_cert *x509.Certificate 107 root_cert *x509.Certificate
86 archive *Archive 108 archive *Archive
87 writable_archive *WritableArchive 109 writable_archive *WritableArchive
110 dummy_certs_map map[string][]byte
88 } 111 }
89 112
90 // TODO: For now, this just returns a self-signed cert using the given ServerNam e. 113 // TODO: For now, this just returns a self-signed cert using the given ServerNam e.
91 // In the future, for better HTTP/2 support, we may want to record host equivale nce 114 // In the future, for better HTTP/2 support, we may want to record host equivale nce
92 // classes in the archive, where an equivalence class contains all hosts that ca n be 115 // classes in the archive, where an equivalence class contains all hosts that ca n be
93 // served by the same IP. We can then run a DNS proxy that maps all hostnames in the 116 // served by the same IP. We can then run a DNS proxy that maps all hostnames in the
94 // same equivalence class to the same local port, which models the possibility t hat 117 // same equivalence class to the same local port, which models the possibility t hat
95 // every equivalence class of hostnames can be served over the same HTTP/2 conne ction. 118 // every equivalence class of hostnames can be served over the same HTTP/2 conne ction.
96 func (tp *tlsProxy) getReplayConfigForClient(clientHello *tls.ClientHelloInfo) ( *tls.Config, error) { 119 func (tp *tlsProxy) getReplayConfigForClient(clientHello *tls.ClientHelloInfo) ( *tls.Config, error) {
97 h := clientHello.ServerName 120 h := clientHello.ServerName
98 if h == "" { 121 if h == "" {
99 return &tls.Config{ 122 return &tls.Config{
100 Certificates: []tls.Certificate{*tp.root}, 123 Certificates: []tls.Certificate{*tp.root},
101 }, nil 124 }, nil
102 } 125 }
103 126
104 derBytes, negotiatedProtocol, err := tp.archive.FindHostTlsConfig(h) 127 derBytes, negotiatedProtocol, err := tp.archive.FindHostTlsConfig(h)
105 if err != nil || derBytes == nil { 128 if err != nil || derBytes == nil {
106 » » return nil, fmt.Errorf("No archived cert for %s", h) 129 » » if _, ok := tp.dummy_certs_map[h]; !ok {
130 » » » derBytes, negotiatedProtocol, err = MintDummyCertificate (h, tp.root_cert, tp.root.PrivateKey)
131 » » » if err != nil {
132 » » » » return nil, err
133 » » » }
134 » » » tp.dummy_certs_map[h] = derBytes
135 » » }
136 » » derBytes = tp.dummy_certs_map[h]
107 } 137 }
108 return &tls.Config{ 138 return &tls.Config{
109 Certificates: []tls.Certificate{ 139 Certificates: []tls.Certificate{
110 tls.Certificate{ 140 tls.Certificate{
111 Certificate: [][]byte{derBytes}, 141 Certificate: [][]byte{derBytes},
112 PrivateKey: tp.root.PrivateKey, 142 PrivateKey: tp.root.PrivateKey,
113 }}, 143 }},
114 » » NextProtos: []string{negotiatedProtocol}, 144 » » NextProtos: buildNextProtos(negotiatedProtocol),
115 }, nil 145 }, nil
116 } 146 }
117 147
118 func buildNextProtos(negotiatedProtocol string) []string { 148 func buildNextProtos(negotiatedProtocol string) []string {
119 if negotiatedProtocol == "h2" { 149 if negotiatedProtocol == "h2" {
120 return []string{"h2", "http/1.1"} 150 return []string{"h2", "http/1.1"}
121 } 151 }
122 return []string{"http/1.1"} 152 return []string{"http/1.1"}
123 } 153 }
124 154
(...skipping 24 matching lines...) Expand all
149 tp.writable_archive.RecordTlsConfig(h, derBytes, negotiatedProtocol) 179 tp.writable_archive.RecordTlsConfig(h, derBytes, negotiatedProtocol)
150 180
151 return &tls.Config{ 181 return &tls.Config{
152 Certificates: []tls.Certificate{ 182 Certificates: []tls.Certificate{
153 tls.Certificate{ 183 tls.Certificate{
154 Certificate: [][]byte{derBytes}, 184 Certificate: [][]byte{derBytes},
155 PrivateKey: tp.root.PrivateKey}}, 185 PrivateKey: tp.root.PrivateKey}},
156 NextProtos: buildNextProtos(negotiatedProtocol), 186 NextProtos: buildNextProtos(negotiatedProtocol),
157 }, nil 187 }, nil
158 } 188 }
OLDNEW
« no previous file with comments | « telemetry/telemetry/internal/binary_dependencies.json ('k') | web_page_replay_go/src/webpagereplay/legacyformatconvertor.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698