-
Notifications
You must be signed in to change notification settings - Fork 36
/
memconn_example_unbuffered_tls_test.go
176 lines (157 loc) · 7.28 KB
/
memconn_example_unbuffered_tls_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package memconn_test
import (
"crypto/tls"
"crypto/x509"
"io"
"io/ioutil"
"os"
"github.com/akutz/memconn"
)
// ExampleUnbufferedTLS illustrates a server and client that
// communicate over an unbuffered, in-memory connection using TLS.
func Example_unbufferedTLS() {
// Create the cert pool for the CA.
rootCAs := x509.NewCertPool()
rootCAs.AppendCertsFromPEM([]byte(tlsUnbufferedCACrt))
// Load the host certificate and key.
hostKeyPair, _ := tls.X509KeyPair(
[]byte(tlsUnbufferedCrt), []byte(tlsUnbufferedKey))
// Announce a new listener named "localhost" on MemConn's
// unbuffered network, "memu".
lis, _ := memconn.Listen("memu", "localhost")
// Create a new TLS listener with the MemConn listener.
lis = tls.NewListener(lis, &tls.Config{
Certificates: []tls.Certificate{hostKeyPair},
RootCAs: rootCAs,
})
// Ensure the listener is closed.
defer lis.Close()
// Start a goroutine that will wait for a client to dial the
// listener and then echo back any data sent to the remote
// connection.
go func() {
conn, _ := lis.Accept()
// Ensure the connection is drained then closed.
//
// When TLS is enabled on an unbuffered connection, the
// connection's Close function results in a Write event --
// the TLS "close_notify" record. This event causes the Close
// function to hang as there is no matching read on the remote
// side of the connection.
//
// Please see https://security.stackexchange.com/q/82028 for
// more information on TLS "close_notify".
defer func() {
go io.Copy(ioutil.Discard, conn)
conn.Close()
}()
// Echo the data back to the client. It is necessary to use
// an intermediate buffer to do the copy instead of using
// io.CopyN(conn, conn, 13). This is because all writes must
// be matched by reads when using an unbuffered connection,
// and without the intermediate buffer, the copy would hang.
io.CopyBuffer(conn, conn, make([]byte, 13))
}()
// Dial the unbuffered, in-memory network named "localhost".
conn, _ := memconn.Dial("memu", "localhost")
// Wrap the connection in TLS. It's necessary to set the "ServerName"
// field in the TLS configuration in order to match one of the host
// certificate's Subject Alternate Name values.
conn = tls.Client(conn, &tls.Config{
RootCAs: rootCAs,
ServerName: "localhost",
})
// Ensure the connection is drained then closed.
//
// When TLS is enabled on an unbuffered connection, the
// connection's Close function results in a Write event --
// the TLS "close_notify" record. This event causes the Close
// function to hang as there is no matching read on the remote
// side of the connection.
//
// Please see https://security.stackexchange.com/q/82028 for
// more information on TLS "close_notify".
defer func() {
go io.Copy(ioutil.Discard, conn)
conn.Close()
}()
// Write the data to the server.
conn.Write([]byte("Hello, world."))
// Read the data from the server.
io.CopyN(os.Stdout, conn, 13)
// Output: Hello, world.
}
const (
tlsUnbufferedCrt = `-----BEGIN CERTIFICATE-----
MIIDvjCCAqagAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMx
DjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0aW4xDzANBgNVBAoMBkdpdEh1
YjEOMAwGA1UECwwFYWt1dHoxEDAOBgNVBAMMB01lbUNvbm4xHzAdBgkqhkiG9w0B
CQEWEGFrdXR6QGdpdGh1Yi5jb20wIBcNMTgwNDI0MTUwMzQ2WhgPMjExODAzMzEx
NTAzNDZaMFExCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UECgwG
R2l0SHViMSEwHwYDVQQDDBhtZW1jb25uLmFrdXR6LmdpdGh1Yi5jb20wggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJVRieeIQCb4RpXiDL8cPs6QYxRzZX
fHxTFK8GOhr08fBbW+HJbHCVlbQa/iLwJyjUc98oBiWmdNyZBLJDmEPxcjFGdD8C
N6EArKto9R1NC1vEMdm3nMYzveQ0/4O9RqLxk12papCMZEomv0Wv4ZsqhWTSl+gQ
MLt5uI51AAbpNmzO2eUHGHX7TDb73dcAiH77p5mrqDnFR+vd1a6wJNeLIRoUBzeR
peKO+gTTgWgLfqYEk/eOL3ymA3IxPadWGleeQZl0el+2fau5Z+L0Rlo4Tbdj2Gb2
VG3r/GKBIB7ALW10JJloyi5sTn4cpPUJp8FX6RZAZ9gGcwJtdJ38hqXLAgMBAAGj
bTBrMAkGA1UdEwQCMAAwPwYDVR0RBDgwNoIEaG9zdIIHbWVtY29uboIJbG9jYWxo
b3N0ghoqLm1lbWNvbm4uYWt1dHouZ2l0aHViLmNvbTAdBgNVHQ4EFgQU1W1W6BhC
tL7bMLitcLEnkAVE0TUwDQYJKoZIhvcNAQEFBQADggEBAGnGW3xwU/8rHlYoQY9e
lQHq6MQaJrzdQOnFNEKbejmQ8birctWiT6zmich+Aqr2FYqFSz1OKdFJXtoCyzLv
qe2sAQlBh5Anqy6v3TYzOM4+yEH5IzYL+1VGHhbe6mZmzHUnentf9/va9htDeagT
DjoZPFPxF/u+TKyzapq4fdo7tBgKRZC61SnKjEq3vw3bLw+zQgzGnVb2aE3LFY34
qh8U5LoNtOu7JawryW8yT7d5W6UqKTN2BLCH0i2UrN9pkNTGwuHGJl33jH9Q6NuZ
zrU/OFhPR4fyk5N0PZ2MbMQkEC0JqxJUkoTs1aWYDiWTRLsk7tiWsNWKKPxhObWo
ZcU=
-----END CERTIFICATE-----`
tlsUnbufferedKey = `-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJVRieeIQCb4Rp
XiDL8cPs6QYxRzZXfHxTFK8GOhr08fBbW+HJbHCVlbQa/iLwJyjUc98oBiWmdNyZ
BLJDmEPxcjFGdD8CN6EArKto9R1NC1vEMdm3nMYzveQ0/4O9RqLxk12papCMZEom
v0Wv4ZsqhWTSl+gQMLt5uI51AAbpNmzO2eUHGHX7TDb73dcAiH77p5mrqDnFR+vd
1a6wJNeLIRoUBzeRpeKO+gTTgWgLfqYEk/eOL3ymA3IxPadWGleeQZl0el+2fau5
Z+L0Rlo4Tbdj2Gb2VG3r/GKBIB7ALW10JJloyi5sTn4cpPUJp8FX6RZAZ9gGcwJt
dJ38hqXLAgMBAAECggEBAK5otlQJqKoHexhgP18NSCICV6f2vb+aCoVaRKjLSzDo
KcSq2vTHqNwcfJJpl1CdS8SHwEiG0rTZRYSVSew+ipUtzDvxVegQ0run2TGqLUDh
1xQl7yodeKG4HWo/8xrThzJo69lohGHqO0ZHqhHMCcQTHJ1GlPT5kl7GnzoB1PrO
7qovfzFrvMgNat+NdqdHy0lAZt35cbshAK50TukYG+P85oow4Lt8+uth3+dh2pNE
tSDhPOfSGLU9kufImBdK6UVoTdxLQOWtdXf9tVtO2ehRuvlPm2virzGmyY2y8Gax
t+Tcw2XmvffVOATvcjRu44bXFAxhPCHAlTYhuepz0KkCgYEA4wmsPiZF0ff2fdzi
ttVhyrisvhIy3QCsxlchHUbmvpIv0KW26MJprMmLGa/wTIXJEa0PQX4sGNObgqGl
+K/Uq7uolooc4Y9PneVr/H/GaogtXLiursTNY6XluU0r6iq8aoqKJMT+vr1mN9Ez
FK3HaNGqgGqkRdVCVXzTwdOfSDcCgYEA4wP3z3vaezJjJt2fkNKcfruevTcA5DUz
nK3q0iXNl+tKJsgrvkLrbj9ElJocIom9PkgKjcXQiG9Z+F2g4/rrJ++YV8Mbk58g
jGBXMjWWLwJ9AMqUkgQ3/mZLD69+j2+9VxitIIJKcUyn5KJSOvU/Mlr4ur/pQavz
EjsoDd9sXQ0CgYEAuwWiz2dzqG0crb2hPH82GWpbUg9nusntiU0IyDc5qM5/eN6p
d79+kYlMfpKB3mdupJLsuESZSrI1rjw+nkcpZ3YkgC2xcNU+/pCYjd0rs2IODA1O
SEVx854bSLObc0BVCWaqOXPVbYZTh7Na4rPsSho825/9RlFQXV+AiHAtC60CgYAj
m/O7MApNWNIEvq7Q4Lh7iKKVu5MAOPgnk4BKBnQBaH7xJmT2KzkSygnP5XyUTlbI
9jPxmR3kyNKsCsO5/xnz4blbytcAiO1qF5KV5aHxLcq93QkA/nhqB1Gu3DBV/4kL
qGs/tjBHJWcQjgWoCeAn3e02HfRQwNAYA/98bZdp4QKBgDo6P0VWVFjVCkWgyFay
rUliOMnNbwVLh7E1HwRM9DN7j6YFVnkhP6uhGcDiZjQHCKjGVX/INOdDvm6ck55h
iKGJnYJ6BdQGeUd+42vE5md+f5jujt46oK36eMyT7j52NUp/7cWpOW6c16O1wchy
P+eS2Jh9T9rdxcFOY9Myr6zt
-----END PRIVATE KEY-----`
tlsUnbufferedCACrt = `-----BEGIN CERTIFICATE-----
MIIDgjCCAmoCCQChm2IAOP7tiTANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMC
VVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0aW4xDzANBgNVBAoMBkdp
dEh1YjEOMAwGA1UECwwFYWt1dHoxEDAOBgNVBAMMB01lbUNvbm4xHzAdBgkqhkiG
9w0BCQEWEGFrdXR6QGdpdGh1Yi5jb20wHhcNMTgwNDI0MTQ0NTA4WhcNMTgwNTI0
MTQ0NTA4WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQH
DAZBdXN0aW4xDzANBgNVBAoMBkdpdEh1YjEOMAwGA1UECwwFYWt1dHoxEDAOBgNV
BAMMB01lbUNvbm4xHzAdBgkqhkiG9w0BCQEWEGFrdXR6QGdpdGh1Yi5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDltHl9NfNDQoSqoOVe1zXiNjz
monSFCK3mOZXepFxJFrGZ+h8BuPZfW78HRFgCO7JH2iFHFEJg5ZJPlA4bMzH0Qqs
12dEmKEW1L9FPyTadtYv74RGdpPuIyC+PXGSUVEtrcCNaKdlGqoDl3zATWwprx2t
lXJUsuaSvlpsAwJmpkFMgVlkYCd3u3pbad8Fx7mFwP/3YsD0ksj/ffGQCMCIGBEG
bOxYRZAiurwlB4JkoJHMz5i5sUYDBqC0mRGHX0+W5LGQf79bfJFkmHwDhJJbeG2h
SzODVtO/60GV6QWJ/FR9ofv+PxCh0LUxJ42SfKMI8apciCYwgGWDRaNjYS/xAgMB
AAEwDQYJKoZIhvcNAQELBQADggEBAGcv4AoCNhboqX/Eiaa0hBZjw51jDP85dzHC
ZqY3eJQImRQGkEHIPHW7vEARrUDoL6HayLAfUBx2fZ4FAbVroH1SbDKPqeXFfxb+
Wp6DZOlEgmsfYyLBdBJNkF0wl3an09h9m0Lj0JAgKqeoyPWV2SfFw2zDOllgXFix
rPB8FHEVFK8nMKOY2XP0JnnWzbo4zcUW72ytDPquvFsN42dPmCNsdwPUXP2gFs1h
AMLe58rnDDT1dQpAO/n8kiyGGzQhktMIFtmuW/OzCMSC2xLAgrlN6tIVNAAzVnFK
590tG24h1m+iHeOKEB4NZDhWagzkM2OT9bs6gHx9FAK7+NzfgnM=
-----END CERTIFICATE-----`
)