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

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

Issue 2956123002: [wpr-go] Match NegotiatedProtocol (Closed)
Patch Set: self Created 3 years, 5 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/rand" 8 "crypto/rand"
9 "crypto/tls" 9 "crypto/tls"
10 "crypto/x509" 10 "crypto/x509"
11 "fmt" 11 "fmt"
12 "io" 12 "io"
13 "time" 13 "time"
14 ) 14 )
15 15
16 // Returns a TLS configuration that serves a recorded server leaf cert signed by 16 // Returns a TLS configuration that serves a recorded server leaf cert signed by
17 // root CA. 17 // root CA.
18 func ReplayTLSConfig(root tls.Certificate, a *Archive) (*tls.Config, error) { 18 func ReplayTLSConfig(root tls.Certificate, a *Archive) (*tls.Config, error) {
19 root_cert, err := getRootCert(root) 19 root_cert, err := getRootCert(root)
20 if err != nil { 20 if err != nil {
21 return nil, fmt.Errorf("bad local cert: %v", err) 21 return nil, fmt.Errorf("bad local cert: %v", err)
22 } 22 }
23 tp := &tlsProxy{&root, root_cert, a, nil} 23 tp := &tlsProxy{&root, root_cert, a, nil}
24 return &tls.Config{ 24 return &tls.Config{
25 » » Certificates: []tls.Certificate{*tp.root}, 25 » » GetConfigForClient: tp.getReplayConfigForClient,
26 » » GetCertificate: tp.getReplayCertificate,
27 }, nil 26 }, nil
28 } 27 }
29 28
30 // Returns a TLS configuration that serves a server leaf cert fetched over the 29 // Returns a TLS configuration that serves a server leaf cert fetched over the
31 // network on demand. 30 // network on demand.
32 func RecordTLSConfig(root tls.Certificate, w *WritableArchive) (*tls.Config, err or) { 31 func RecordTLSConfig(root tls.Certificate, w *WritableArchive) (*tls.Config, err or) {
33 root_cert, err := getRootCert(root) 32 root_cert, err := getRootCert(root)
34 if err != nil { 33 if err != nil {
35 return nil, fmt.Errorf("bad local cert: %v", err) 34 return nil, fmt.Errorf("bad local cert: %v", err)
36 } 35 }
37 tp := &tlsProxy{&root, root_cert, nil, w} 36 tp := &tlsProxy{&root, root_cert, nil, w}
38 return &tls.Config{ 37 return &tls.Config{
39 » » Certificates: []tls.Certificate{*tp.root}, 38 » » GetConfigForClient: tp.getRecordConfigForClient,
40 » » GetCertificate: tp.getCertificate,
41 }, nil 39 }, nil
42 } 40 }
43 41
44 func getRootCert(root tls.Certificate) (*x509.Certificate, error) { 42 func getRootCert(root tls.Certificate) (*x509.Certificate, error) {
45 root_cert, err := x509.ParseCertificate(root.Certificate[0]) 43 root_cert, err := x509.ParseCertificate(root.Certificate[0])
46 if err != nil { 44 if err != nil {
47 return nil, err 45 return nil, err
48 } 46 }
49 root_cert.IsCA = true 47 root_cert.IsCA = true
50 root_cert.BasicConstraintsValid = true 48 root_cert.BasicConstraintsValid = true
51 return root_cert, nil 49 return root_cert, nil
52 } 50 }
53 51
54 type tlsProxy struct { 52 type tlsProxy struct {
55 root *tls.Certificate 53 root *tls.Certificate
56 root_cert *x509.Certificate 54 root_cert *x509.Certificate
57 archive *Archive 55 archive *Archive
58 writable_archive *WritableArchive 56 writable_archive *WritableArchive
59 } 57 }
60 58
61 // TODO: For now, this just returns a self-signed cert using the given ServerNam e. 59 // TODO: For now, this just returns a self-signed cert using the given ServerNam e.
62 // In the future, for better HTTP/2 support, we may want to record host equivale nce 60 // In the future, for better HTTP/2 support, we may want to record host equivale nce
63 // classes in the archive, where an equivalence class contains all hosts that ca n be 61 // classes in the archive, where an equivalence class contains all hosts that ca n be
64 // served by the same IP. We can then run a DNS proxy that maps all hostnames in the 62 // served by the same IP. We can then run a DNS proxy that maps all hostnames in the
65 // same equivalence class to the same local port, which models the possibility t hat 63 // same equivalence class to the same local port, which models the possibility t hat
66 // every equivalence class of hostnames can be served over the same HTTP/2 conne ction. 64 // every equivalence class of hostnames can be served over the same HTTP/2 conne ction.
67 // 65 func (tp *tlsProxy) getReplayConfigForClient(clientHello *tls.ClientHelloInfo) ( *tls.Config, error) {
68 // getCertificate implements a callback for tls.Config.GetCertificate.
69 func (tp *tlsProxy) getReplayCertificate(clientHello *tls.ClientHelloInfo) (*tls .Certificate, error) {
70 h := clientHello.ServerName 66 h := clientHello.ServerName
71 if h == "" { 67 if h == "" {
72 » » return tp.root, nil 68 » » return &tls.Config{
69 » » » Certificates: []tls.Certificate{*tp.root},
70 » » }, nil
73 } 71 }
74 72
75 » der_bytes, err := tp.archive.FindHostCert(h) 73 » der_bytes, negotiatedProtocol, err := tp.archive.FindHostTlsConfig(h)
76 if err != nil || der_bytes == nil { 74 if err != nil || der_bytes == nil {
77 return nil, fmt.Errorf("No archived cert for %s", h) 75 return nil, fmt.Errorf("No archived cert for %s", h)
78 } 76 }
79 » return &tls.Certificate{ 77 » return &tls.Config{
80 » » Certificate: [][]byte{der_bytes}, 78 » » Certificates: []tls.Certificate{
81 » » PrivateKey: tp.root.PrivateKey, 79 » » » tls.Certificate{
80 » » » » Certificate: [][]byte{der_bytes},
81 » » » » PrivateKey: tp.root.PrivateKey,
82 » » » }},
83 » » NextProtos: []string{negotiatedProtocol},
82 }, nil 84 }, nil
83 } 85 }
84 86
85 func (tp *tlsProxy) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certi ficate, error) { 87 func (tp *tlsProxy) getRecordConfigForClient(clientHello *tls.ClientHelloInfo) ( *tls.Config, error) {
86 h := clientHello.ServerName 88 h := clientHello.ServerName
87 if h == "" { 89 if h == "" {
88 » » return tp.root, nil 90 » » return &tls.Config{
91 » » » Certificates: []tls.Certificate{*tp.root},
92 » » }, nil
89 } 93 }
90 94 » der_bytes, negotiatedProtocol, err := tp.writable_archive.Archive.FindHo stTlsConfig(h)
91 » der_bytes, err := tp.writable_archive.FindHostCert(h)
92 if err == nil && der_bytes != nil { 95 if err == nil && der_bytes != nil {
93 » » return &tls.Certificate{ 96 » » return &tls.Config{
94 » » » Certificate: [][]byte{der_bytes}, 97 » » » Certificates: []tls.Certificate{
95 » » » PrivateKey: tp.root.PrivateKey, 98 » » » » tls.Certificate{
99 » » » » » Certificate: [][]byte{der_bytes},
100 » » » » » PrivateKey: tp.root.PrivateKey,
101 » » » » }},
102 » » » NextProtos: []string{negotiatedProtocol},
96 }, nil 103 }, nil
97 } 104 }
98 105
99 » conn, err := tls.Dial("tcp", fmt.Sprintf("%s:443", h), nil) 106 » conn, err := tls.Dial("tcp", fmt.Sprintf("%s:443", h), &tls.Config{
107 » » NextProtos: []string{"h2", "http/1.1"},
108 » })
100 if err != nil { 109 if err != nil {
101 return nil, fmt.Errorf("Couldn't reach host %s: %v", h, err) 110 return nil, fmt.Errorf("Couldn't reach host %s: %v", h, err)
102 } 111 }
103 defer conn.Close() 112 defer conn.Close()
104 conn.Handshake() 113 conn.Handshake()
105 template := conn.ConnectionState().PeerCertificates[0] 114 template := conn.ConnectionState().PeerCertificates[0]
106 115
107 template.Subject.CommonName = h 116 template.Subject.CommonName = h
108 template.NotBefore = time.Now() 117 template.NotBefore = time.Now()
109 template.NotAfter = template.NotBefore.Add(87658 * time.Hour) 118 template.NotAfter = template.NotBefore.Add(87658 * time.Hour)
110 template.PublicKey = tp.root_cert.PublicKey 119 template.PublicKey = tp.root_cert.PublicKey
111 var buf [20]byte 120 var buf [20]byte
112 if _, err := io.ReadFull(rand.Reader, buf[:]); err != nil { 121 if _, err := io.ReadFull(rand.Reader, buf[:]); err != nil {
113 return nil, err 122 return nil, err
114 } 123 }
115 template.SerialNumber.SetBytes(buf[:]) 124 template.SerialNumber.SetBytes(buf[:])
116 template.Issuer = tp.root_cert.Subject 125 template.Issuer = tp.root_cert.Subject
117 template.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCRLSign 126 template.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCRLSign
118 template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x5 09.ExtKeyUsageServerAuth} 127 template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x5 09.ExtKeyUsageServerAuth}
119 128
120 der_bytes, err = x509.CreateCertificate(rand.Reader, template, tp.root_c ert, template.PublicKey, tp.root.PrivateKey) 129 der_bytes, err = x509.CreateCertificate(rand.Reader, template, tp.root_c ert, template.PublicKey, tp.root.PrivateKey)
121 if err != nil { 130 if err != nil {
122 return nil, fmt.Errorf("create cert failed: %v", err) 131 return nil, fmt.Errorf("create cert failed: %v", err)
123 } 132 }
124 » tp.writable_archive.RecordCert(h, der_bytes) 133
125 » return &tls.Certificate{ 134 » negotiatedProtocol = conn.ConnectionState().NegotiatedProtocol
126 » » Certificate: [][]byte{der_bytes}, 135 » tp.writable_archive.RecordTlsConfig(h, der_bytes, negotiatedProtocol)
127 » » PrivateKey: tp.root.PrivateKey, 136
137 » return &tls.Config{
138 » » Certificates: []tls.Certificate{
139 » » » tls.Certificate{
140 » » » » Certificate: [][]byte{der_bytes},
141 » » » » PrivateKey: tp.root.PrivateKey}},
142 » » NextProtos: []string{negotiatedProtocol},
128 }, nil 143 }, nil
129 } 144 }
OLDNEW
« no previous file with comments | « web_page_replay_go/src/webpagereplay/archive.go ('k') | web_page_replay_go/src/webpagereplay/proxy.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698