| diff -pu -r a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c |
| --- a/net/third_party/nss/ssl/ssl3con.c 2012-11-09 15:48:41.260860199 -0800 |
| +++ b/net/third_party/nss/ssl/ssl3con.c 2012-11-09 15:49:25.751511020 -0800 |
| @@ -6148,6 +6148,85 @@ done: |
| return rv; |
| } |
| |
| +/* |
| + * attempt to restart the handshake after asynchronously handling |
| + * a request for the client's certificate. |
| + * |
| + * inputs: |
| + * cert Client cert chosen by application. |
| + * Note: ssl takes this reference, and does not bump the |
| + * reference count. The caller should drop its reference |
| + * without calling CERT_DestroyCert after calling this function. |
| + * |
| + * key Private key associated with cert. This function takes |
| + * ownership of the private key, so the caller should drop its |
| + * reference without destroying the private key after this |
| + * function returns. |
| + * |
| + * certChain DER-encoded certs, client cert and its signers. |
| + * Note: ssl takes this reference, and does not copy the chain. |
| + * The caller should drop its reference without destroying the |
| + * chain. SSL will free the chain when it is done with it. |
| + * |
| + * Return value: XXX |
| + * |
| + * XXX This code only works on the initial handshake on a connection, XXX |
| + * It does not work on a subsequent handshake (redo). |
| + * |
| + * Caller holds 1stHandshakeLock. |
| + */ |
| +SECStatus |
| +ssl3_RestartHandshakeAfterCertReq(sslSocket * ss, |
| + CERTCertificate * cert, |
| + SECKEYPrivateKey * key, |
| + CERTCertificateList *certChain) |
| +{ |
| + SECStatus rv = SECSuccess; |
| + |
| + /* XXX This code only works on the initial handshake on a connection, |
| + ** XXX It does not work on a subsequent handshake (redo). |
| + */ |
| + if (ss->handshake != 0) { |
| + ss->handshake = ssl_GatherRecord1stHandshake; |
| + ss->ssl3.clientCertificate = cert; |
| + ss->ssl3.clientPrivateKey = key; |
| + ss->ssl3.clientCertChain = certChain; |
| + if (!cert || !key || !certChain) { |
| + /* we are missing the key, cert, or cert chain */ |
| + if (ss->ssl3.clientCertificate) { |
| + CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
| + ss->ssl3.clientCertificate = NULL; |
| + } |
| + if (ss->ssl3.clientPrivateKey) { |
| + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
| + ss->ssl3.clientPrivateKey = NULL; |
| + } |
| + if (ss->ssl3.clientCertChain != NULL) { |
| + CERT_DestroyCertificateList(ss->ssl3.clientCertChain); |
| + ss->ssl3.clientCertChain = NULL; |
| + } |
| + if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { |
| + ss->ssl3.sendEmptyCert = PR_TRUE; |
| + } else { |
| + (void)SSL3_SendAlert(ss, alert_warning, no_certificate); |
| + } |
| + } |
| + } else { |
| + if (cert) { |
| + CERT_DestroyCertificate(cert); |
| + } |
| + if (key) { |
| + SECKEY_DestroyPrivateKey(key); |
| + } |
| + if (certChain) { |
| + CERT_DestroyCertificateList(certChain); |
| + } |
| + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
| + rv = SECFailure; |
| + } |
| + return rv; |
| +} |
| + |
| PRBool |
| ssl3_CanFalseStart(sslSocket *ss) { |
| PRBool rv; |
| diff -pu -r a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h |
| --- a/net/third_party/nss/ssl/ssl.h 2012-11-09 15:48:41.260860199 -0800 |
| +++ b/net/third_party/nss/ssl/ssl.h 2012-11-09 15:49:25.751511020 -0800 |
| @@ -367,6 +367,11 @@ SSL_IMPORT SECStatus SSL_ForceHandshake( |
| SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, |
| PRIntervalTime timeout); |
| |
| +SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd, |
| + CERTCertificate *cert, |
| + SECKEYPrivateKey *key, |
| + CERTCertificateList *certChain); |
| + |
| /* |
| ** Query security status of socket. *on is set to one if security is |
| ** enabled. *keySize will contain the stream key size used. *issuer will |
| diff -pu -r a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h |
| --- a/net/third_party/nss/ssl/sslimpl.h 2012-11-09 15:48:41.260860199 -0800 |
| +++ b/net/third_party/nss/ssl/sslimpl.h 2012-11-09 15:51:26.623278555 -0800 |
| @@ -1484,16 +1484,17 @@ extern SECStatus ssl3_MasterKeyDeriveBy |
| /* These functions are called from secnav, even though they're "private". */ |
| |
| extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error); |
| -extern int SSL_RestartHandshakeAfterCertReq(struct sslSocketStr *ss, |
| - CERTCertificate *cert, |
| - SECKEYPrivateKey *key, |
| - CERTCertificateList *certChain); |
| extern sslSocket *ssl_FindSocket(PRFileDesc *fd); |
| extern void ssl_FreeSocket(struct sslSocketStr *ssl); |
| extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, |
| SSL3AlertDescription desc); |
| extern SECStatus ssl3_DecodeError(sslSocket *ss); |
| |
| +extern SECStatus ssl3_RestartHandshakeAfterCertReq(sslSocket * ss, |
| + CERTCertificate * cert, |
| + SECKEYPrivateKey * key, |
| + CERTCertificateList *certChain); |
| + |
| extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error); |
| |
| /* |
| diff -pu -r a/net/third_party/nss/ssl/sslsecur.c b/net/third_party/nss/ssl/sslsecur.c |
| --- a/net/third_party/nss/ssl/sslsecur.c 2012-11-09 15:17:00.432983977 -0800 |
| +++ b/net/third_party/nss/ssl/sslsecur.c 2012-11-09 15:49:25.751511020 -0800 |
| @@ -1437,17 +1437,70 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERT |
| return SECSuccess; |
| } |
| |
| -/* DO NOT USE. This function was exported in ssl.def with the wrong signature; |
| - * this implementation exists to maintain link-time compatibility. |
| +/* |
| + * attempt to restart the handshake after asynchronously handling |
| + * a request for the client's certificate. |
| + * |
| + * inputs: |
| + * cert Client cert chosen by application. |
| + * Note: ssl takes this reference, and does not bump the |
| + * reference count. The caller should drop its reference |
| + * without calling CERT_DestroyCertificate after calling this |
| + * function. |
| + * |
| + * key Private key associated with cert. This function takes |
| + * ownership of the private key, so the caller should drop its |
| + * reference without destroying the private key after this |
| + * function returns. |
| + * |
| + * certChain Chain of signers for cert. |
| + * Note: ssl takes this reference, and does not copy the chain. |
| + * The caller should drop its reference without destroying the |
| + * chain. SSL will free the chain when it is done with it. |
| + * |
| + * Return value: XXX |
| + * |
| + * XXX This code only works on the initial handshake on a connection, XXX |
| + * It does not work on a subsequent handshake (redo). |
| */ |
| -int |
| -SSL_RestartHandshakeAfterCertReq(sslSocket * ss, |
| +SECStatus |
| +SSL_RestartHandshakeAfterCertReq(PRFileDesc * fd, |
| CERTCertificate * cert, |
| SECKEYPrivateKey * key, |
| CERTCertificateList *certChain) |
| { |
| - PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
| - return -1; |
| + sslSocket * ss = ssl_FindSocket(fd); |
| + SECStatus ret; |
| + |
| + if (!ss) { |
| + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq", |
| + SSL_GETPID(), fd)); |
| + if (cert) { |
| + CERT_DestroyCertificate(cert); |
| + } |
| + if (key) { |
| + SECKEY_DestroyPrivateKey(key); |
| + } |
| + if (certChain) { |
| + CERT_DestroyCertificateList(certChain); |
| + } |
| + return SECFailure; |
| + } |
| + |
| + ssl_Get1stHandshakeLock(ss); /************************************/ |
| + |
| + if (ss->version >= SSL_LIBRARY_VERSION_3_0) { |
| + ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain); |
| + } else { |
| + if (certChain != NULL) { |
| + CERT_DestroyCertificateList(certChain); |
| + } |
| + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); |
| + ret = SECFailure; |
| + } |
| + |
| + ssl_Release1stHandshakeLock(ss); /************************************/ |
| + return ret; |
| } |
| |
| /* DO NOT USE. This function was exported in ssl.def with the wrong signature; |