1
18
19 package credentials
20
21 import (
22 "context"
23 "crypto/tls"
24 "crypto/x509"
25 "fmt"
26 "net"
27 "net/url"
28 "os"
29
30 credinternal "google.golang.org/grpc/internal/credentials"
31 )
32
33
34
35 type TLSInfo struct {
36 State tls.ConnectionState
37 CommonAuthInfo
38
39 SPIFFEID *url.URL
40 }
41
42
43 func (t TLSInfo) AuthType() string {
44 return "tls"
45 }
46
47
48 func cipherSuiteLookup(cipherSuiteID uint16) string {
49 for _, s := range tls.CipherSuites() {
50 if s.ID == cipherSuiteID {
51 return s.Name
52 }
53 }
54 for _, s := range tls.InsecureCipherSuites() {
55 if s.ID == cipherSuiteID {
56 return s.Name
57 }
58 }
59 return fmt.Sprintf("unknown ID: %v", cipherSuiteID)
60 }
61
62
63 func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
64 v := &TLSChannelzSecurityValue{
65 StandardName: cipherSuiteLookup(t.State.CipherSuite),
66 }
67
68 if len(t.State.PeerCertificates) > 0 {
69 v.RemoteCertificate = t.State.PeerCertificates[0].Raw
70 }
71 return v
72 }
73
74
75 type tlsCreds struct {
76
77 config *tls.Config
78 }
79
80 func (c tlsCreds) Info() ProtocolInfo {
81 return ProtocolInfo{
82 SecurityProtocol: "tls",
83 SecurityVersion: "1.2",
84 ServerName: c.config.ServerName,
85 }
86 }
87
88 func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
89
90 cfg := credinternal.CloneTLSConfig(c.config)
91 if cfg.ServerName == "" {
92 serverName, _, err := net.SplitHostPort(authority)
93 if err != nil {
94
95 serverName = authority
96 }
97 cfg.ServerName = serverName
98 }
99 conn := tls.Client(rawConn, cfg)
100 errChannel := make(chan error, 1)
101 go func() {
102 errChannel <- conn.Handshake()
103 close(errChannel)
104 }()
105 select {
106 case err := <-errChannel:
107 if err != nil {
108 conn.Close()
109 return nil, nil, err
110 }
111 case <-ctx.Done():
112 conn.Close()
113 return nil, nil, ctx.Err()
114 }
115 tlsInfo := TLSInfo{
116 State: conn.ConnectionState(),
117 CommonAuthInfo: CommonAuthInfo{
118 SecurityLevel: PrivacyAndIntegrity,
119 },
120 }
121 id := credinternal.SPIFFEIDFromState(conn.ConnectionState())
122 if id != nil {
123 tlsInfo.SPIFFEID = id
124 }
125 return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil
126 }
127
128 func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
129 conn := tls.Server(rawConn, c.config)
130 if err := conn.Handshake(); err != nil {
131 conn.Close()
132 return nil, nil, err
133 }
134 tlsInfo := TLSInfo{
135 State: conn.ConnectionState(),
136 CommonAuthInfo: CommonAuthInfo{
137 SecurityLevel: PrivacyAndIntegrity,
138 },
139 }
140 id := credinternal.SPIFFEIDFromState(conn.ConnectionState())
141 if id != nil {
142 tlsInfo.SPIFFEID = id
143 }
144 return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil
145 }
146
147 func (c *tlsCreds) Clone() TransportCredentials {
148 return NewTLS(c.config)
149 }
150
151 func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
152 c.config.ServerName = serverNameOverride
153 return nil
154 }
155
156
157
158 var tls12ForbiddenCipherSuites = map[uint16]struct{}{
159 tls.TLS_RSA_WITH_AES_128_CBC_SHA: {},
160 tls.TLS_RSA_WITH_AES_256_CBC_SHA: {},
161 tls.TLS_RSA_WITH_AES_128_GCM_SHA256: {},
162 tls.TLS_RSA_WITH_AES_256_GCM_SHA384: {},
163 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {},
164 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {},
165 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {},
166 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {},
167 }
168
169
170 func NewTLS(c *tls.Config) TransportCredentials {
171 tc := &tlsCreds{credinternal.CloneTLSConfig(c)}
172 tc.config.NextProtos = credinternal.AppendH2ToNextProtos(tc.config.NextProtos)
173
174
175
176 if tc.config.MinVersion == 0 && (tc.config.MaxVersion == 0 || tc.config.MaxVersion >= tls.VersionTLS12) {
177 tc.config.MinVersion = tls.VersionTLS12
178 }
179
180
181
182 if tc.config.CipherSuites == nil {
183 for _, cs := range tls.CipherSuites() {
184 if _, ok := tls12ForbiddenCipherSuites[cs.ID]; !ok {
185 tc.config.CipherSuites = append(tc.config.CipherSuites, cs.ID)
186 }
187 }
188 }
189 return tc
190 }
191
192
193
194
195
196
197
198
199
200 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
201 return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
202 }
203
204
205
206
207
208
209
210
211
212 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
213 b, err := os.ReadFile(certFile)
214 if err != nil {
215 return nil, err
216 }
217 cp := x509.NewCertPool()
218 if !cp.AppendCertsFromPEM(b) {
219 return nil, fmt.Errorf("credentials: failed to append certificates")
220 }
221 return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil
222 }
223
224
225 func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials {
226 return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}})
227 }
228
229
230
231 func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) {
232 cert, err := tls.LoadX509KeyPair(certFile, keyFile)
233 if err != nil {
234 return nil, err
235 }
236 return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil
237 }
238
239
240
241
242
243
244
245
246 type TLSChannelzSecurityValue struct {
247 ChannelzSecurityValue
248 StandardName string
249 LocalCertificate []byte
250 RemoteCertificate []byte
251 }
252
View as plain text