5
5
package tls
6
6
7
7
import (
8
+ "bytes"
8
9
"crypto"
9
10
"crypto/rsa"
10
11
"crypto/subtle"
11
12
"crypto/x509"
12
13
"errors"
13
14
"io"
15
+ "strconv"
14
16
)
15
17
16
18
func (c * Conn ) clientHandshake () error {
@@ -162,10 +164,23 @@ func (c *Conn) clientHandshake() error {
162
164
}
163
165
}
164
166
165
- transmitCert := false
167
+ var certToSend * Certificate
166
168
certReq , ok := msg .(* certificateRequestMsg )
167
169
if ok {
168
- // We only accept certificates with RSA keys.
170
+ // RFC 4346 on the certificateAuthorities field:
171
+ // A list of the distinguished names of acceptable certificate
172
+ // authorities. These distinguished names may specify a desired
173
+ // distinguished name for a root CA or for a subordinate CA;
174
+ // thus, this message can be used to describe both known roots
175
+ // and a desired authorization space. If the
176
+ // certificate_authorities list is empty then the client MAY
177
+ // send any certificate of the appropriate
178
+ // ClientCertificateType, unless there is some external
179
+ // arrangement to the contrary.
180
+
181
+ finishedHash .Write (certReq .marshal ())
182
+
183
+ // For now, we only know how to sign challenges with RSA
169
184
rsaAvail := false
170
185
for _ , certType := range certReq .certificateTypes {
171
186
if certType == certTypeRSASign {
@@ -174,23 +189,41 @@ func (c *Conn) clientHandshake() error {
174
189
}
175
190
}
176
191
177
- // For now, only send a certificate back if the server gives us an
178
- // empty list of certificateAuthorities.
179
- //
180
- // RFC 4346 on the certificateAuthorities field:
181
- // A list of the distinguished names of acceptable certificate
182
- // authorities. These distinguished names may specify a desired
183
- // distinguished name for a root CA or for a subordinate CA; thus,
184
- // this message can be used to describe both known roots and a
185
- // desired authorization space. If the certificate_authorities
186
- // list is empty then the client MAY send any certificate of the
187
- // appropriate ClientCertificateType, unless there is some
188
- // external arrangement to the contrary.
189
- if rsaAvail && len (certReq .certificateAuthorities ) == 0 {
190
- transmitCert = true
191
- }
192
+ // We need to search our list of client certs for one
193
+ // where SignatureAlgorithm is RSA and the Issuer is in
194
+ // certReq.certificateAuthorities
195
+ findCert:
196
+ for i , cert := range c .config .Certificates {
197
+ if ! rsaAvail {
198
+ continue
199
+ }
192
200
193
- finishedHash .Write (certReq .marshal ())
201
+ leaf := cert .Leaf
202
+ if leaf == nil {
203
+ if leaf , err = x509 .ParseCertificate (cert .Certificate [0 ]); err != nil {
204
+ c .sendAlert (alertInternalError )
205
+ return errors .New ("tls: failed to parse client certificate #" + strconv .Itoa (i ) + ": " + err .Error ())
206
+ }
207
+ }
208
+
209
+ if leaf .PublicKeyAlgorithm != x509 .RSA {
210
+ continue
211
+ }
212
+
213
+ if len (certReq .certificateAuthorities ) == 0 {
214
+ // they gave us an empty list, so just take the
215
+ // first RSA cert from c.config.Certificates
216
+ certToSend = & cert
217
+ break
218
+ }
219
+
220
+ for _ , ca := range certReq .certificateAuthorities {
221
+ if bytes .Equal (leaf .RawIssuer , ca ) {
222
+ certToSend = & cert
223
+ break findCert
224
+ }
225
+ }
226
+ }
194
227
195
228
msg , err = c .readHandshake ()
196
229
if err != nil {
@@ -204,17 +237,9 @@ func (c *Conn) clientHandshake() error {
204
237
}
205
238
finishedHash .Write (shd .marshal ())
206
239
207
- var cert * x509.Certificate
208
- if transmitCert {
240
+ if certToSend != nil {
209
241
certMsg = new (certificateMsg )
210
- if len (c .config .Certificates ) > 0 {
211
- cert , err = x509 .ParseCertificate (c .config .Certificates [0 ].Certificate [0 ])
212
- if err == nil && cert .PublicKeyAlgorithm == x509 .RSA {
213
- certMsg .certificates = c .config .Certificates [0 ].Certificate
214
- } else {
215
- cert = nil
216
- }
217
- }
242
+ certMsg .certificates = certToSend .Certificate
218
243
finishedHash .Write (certMsg .marshal ())
219
244
c .writeRecord (recordTypeHandshake , certMsg .marshal ())
220
245
}
@@ -229,7 +254,7 @@ func (c *Conn) clientHandshake() error {
229
254
c .writeRecord (recordTypeHandshake , ckx .marshal ())
230
255
}
231
256
232
- if cert != nil {
257
+ if certToSend != nil {
233
258
certVerify := new (certificateVerifyMsg )
234
259
digest := make ([]byte , 0 , 36 )
235
260
digest = finishedHash .serverMD5 .Sum (digest )
0 commit comments