| OLD | NEW |
| (Empty) |
| 1 diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h | |
| 2 index 9e57220..aa4a3e5 100644 | |
| 3 --- a/lib/ssl/ssl.h | |
| 4 +++ b/lib/ssl/ssl.h | |
| 5 @@ -516,6 +516,11 @@ SSL_IMPORT SECStatus SSL_ForceHandshake(PRFileDesc *fd); | |
| 6 SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, | |
| 7 PRIntervalTime timeout); | |
| 8 | |
| 9 +SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd, | |
| 10 + CERTCertificate *cert, | |
| 11 + SECKEYPrivateKey *key, | |
| 12 + CERTCertificateList *cert
Chain); | |
| 13 + | |
| 14 /* | |
| 15 ** Query security status of socket. *on is set to one if security is | |
| 16 ** enabled. *keySize will contain the stream key size used. *issuer will | |
| 17 diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c | |
| 18 index 784f59b..2a2e644 100644 | |
| 19 --- a/lib/ssl/ssl3con.c | |
| 20 +++ b/lib/ssl/ssl3con.c | |
| 21 @@ -7803,6 +7803,85 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss, SECI
tem *algorithms, | |
| 22 return rv; | |
| 23 } | |
| 24 | |
| 25 +/* | |
| 26 + * attempt to restart the handshake after asynchronously handling | |
| 27 + * a request for the client's certificate. | |
| 28 + * | |
| 29 + * inputs: | |
| 30 + * cert Client cert chosen by application. | |
| 31 + * Note: ssl takes this reference, and does not bump the | |
| 32 + * reference count. The caller should drop its reference | |
| 33 + * without calling CERT_DestroyCert after calling this function. | |
| 34 + * | |
| 35 + * key Private key associated with cert. This function takes | |
| 36 + * ownership of the private key, so the caller should drop its | |
| 37 + * reference without destroying the private key after this | |
| 38 + * function returns. | |
| 39 + * | |
| 40 + * certChain DER-encoded certs, client cert and its signers. | |
| 41 + * Note: ssl takes this reference, and does not copy the chain. | |
| 42 + * The caller should drop its reference without destroying the | |
| 43 + * chain. SSL will free the chain when it is done with it. | |
| 44 + * | |
| 45 + * Return value: XXX | |
| 46 + * | |
| 47 + * XXX This code only works on the initial handshake on a connection, XXX | |
| 48 + * It does not work on a subsequent handshake (redo). | |
| 49 + * | |
| 50 + * Caller holds 1stHandshakeLock. | |
| 51 + */ | |
| 52 +SECStatus | |
| 53 +ssl3_RestartHandshakeAfterCertReq(sslSocket *ss, | |
| 54 + CERTCertificate *cert, | |
| 55 + SECKEYPrivateKey *key, | |
| 56 + CERTCertificateList *certChain) | |
| 57 +{ | |
| 58 + SECStatus rv = SECSuccess; | |
| 59 + | |
| 60 + /* XXX This code only works on the initial handshake on a connection, | |
| 61 + ** XXX It does not work on a subsequent handshake (redo). | |
| 62 + */ | |
| 63 + if (ss->handshake != 0) { | |
| 64 + ss->handshake = ssl_GatherRecord1stHandshake; | |
| 65 + ss->ssl3.clientCertificate = cert; | |
| 66 + ss->ssl3.clientPrivateKey = key; | |
| 67 + ss->ssl3.clientCertChain = certChain; | |
| 68 + if (!cert || !key || !certChain) { | |
| 69 + /* we are missing the key, cert, or cert chain */ | |
| 70 + if (ss->ssl3.clientCertificate) { | |
| 71 + CERT_DestroyCertificate(ss->ssl3.clientCertificate); | |
| 72 + ss->ssl3.clientCertificate = NULL; | |
| 73 + } | |
| 74 + if (ss->ssl3.clientPrivateKey) { | |
| 75 + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); | |
| 76 + ss->ssl3.clientPrivateKey = NULL; | |
| 77 + } | |
| 78 + if (ss->ssl3.clientCertChain != NULL) { | |
| 79 + CERT_DestroyCertificateList(ss->ssl3.clientCertChain); | |
| 80 + ss->ssl3.clientCertChain = NULL; | |
| 81 + } | |
| 82 + if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { | |
| 83 + ss->ssl3.sendEmptyCert = PR_TRUE; | |
| 84 + } else { | |
| 85 + (void)SSL3_SendAlert(ss, alert_warning, no_certificate); | |
| 86 + } | |
| 87 + } | |
| 88 + } else { | |
| 89 + if (cert) { | |
| 90 + CERT_DestroyCertificate(cert); | |
| 91 + } | |
| 92 + if (key) { | |
| 93 + SECKEY_DestroyPrivateKey(key); | |
| 94 + } | |
| 95 + if (certChain) { | |
| 96 + CERT_DestroyCertificateList(certChain); | |
| 97 + } | |
| 98 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 99 + rv = SECFailure; | |
| 100 + } | |
| 101 + return rv; | |
| 102 +} | |
| 103 + | |
| 104 static SECStatus | |
| 105 ssl3_CheckFalseStart(sslSocket *ss) | |
| 106 { | |
| 107 diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h | |
| 108 index 5f0e6c9..dad75b2 100644 | |
| 109 --- a/lib/ssl/sslimpl.h | |
| 110 +++ b/lib/ssl/sslimpl.h | |
| 111 @@ -1702,16 +1702,16 @@ extern SECStatus ssl3_MasterSecretDeriveBypass(ssl3Ciphe
rSpec *pwSpec, | |
| 112 /* These functions are called from secnav, even though they're "private". */ | |
| 113 | |
| 114 extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error); | |
| 115 -extern int SSL_RestartHandshakeAfterCertReq(struct sslSocketStr *ss, | |
| 116 - CERTCertificate *cert, | |
| 117 - SECKEYPrivateKey *key, | |
| 118 - CERTCertificateList *certChain); | |
| 119 extern sslSocket *ssl_FindSocket(PRFileDesc *fd); | |
| 120 extern void ssl_FreeSocket(struct sslSocketStr *ssl); | |
| 121 extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, | |
| 122 SSL3AlertDescription desc); | |
| 123 extern SECStatus ssl3_DecodeError(sslSocket *ss); | |
| 124 | |
| 125 +extern SECStatus ssl3_RestartHandshakeAfterCertReq(struct sslSocketStr *ss, | |
| 126 + CERTCertificate *cert, | |
| 127 + SECKEYPrivateKey *key, | |
| 128 + CERTCertificateList *certCha
in); | |
| 129 extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
; | |
| 130 | |
| 131 /* | |
| 132 diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c | |
| 133 index 5773748..a087ffc 100644 | |
| 134 --- a/lib/ssl/sslsecur.c | |
| 135 +++ b/lib/ssl/sslsecur.c | |
| 136 @@ -1535,17 +1535,70 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *db
Handle) | |
| 137 return SECSuccess; | |
| 138 } | |
| 139 | |
| 140 -/* DO NOT USE. This function was exported in ssl.def with the wrong signature; | |
| 141 - * this implementation exists to maintain link-time compatibility. | |
| 142 - */ | |
| 143 -int | |
| 144 -SSL_RestartHandshakeAfterCertReq(sslSocket *ss, | |
| 145 +/* | |
| 146 + * attempt to restart the handshake after asynchronously handling | |
| 147 + * a request for the client's certificate. | |
| 148 + * | |
| 149 + * inputs: | |
| 150 + * cert Client cert chosen by application. | |
| 151 + * Note: ssl takes this reference, and does not bump the | |
| 152 + * reference count. The caller should drop its reference | |
| 153 + * without calling CERT_DestroyCertificate after calling this | |
| 154 + * function. | |
| 155 + * | |
| 156 + * key Private key associated with cert. This function takes | |
| 157 + * ownership of the private key, so the caller should drop its | |
| 158 + * reference without destroying the private key after this | |
| 159 + * function returns. | |
| 160 + * | |
| 161 + * certChain Chain of signers for cert. | |
| 162 + * Note: ssl takes this reference, and does not copy the chain. | |
| 163 + * The caller should drop its reference without destroying the | |
| 164 + * chain. SSL will free the chain when it is done with it. | |
| 165 + * | |
| 166 + * Return value: XXX | |
| 167 + * | |
| 168 + * XXX This code only works on the initial handshake on a connection, XXX | |
| 169 + * It does not work on a subsequent handshake (redo). | |
| 170 + */ | |
| 171 +SECStatus | |
| 172 +SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd, | |
| 173 CERTCertificate *cert, | |
| 174 SECKEYPrivateKey *key, | |
| 175 CERTCertificateList *certChain) | |
| 176 { | |
| 177 - PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 178 - return -1; | |
| 179 + sslSocket *ss = ssl_FindSocket(fd); | |
| 180 + SECStatus ret; | |
| 181 + | |
| 182 + if (!ss) { | |
| 183 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq", | |
| 184 + SSL_GETPID(), fd)); | |
| 185 + if (cert) { | |
| 186 + CERT_DestroyCertificate(cert); | |
| 187 + } | |
| 188 + if (key) { | |
| 189 + SECKEY_DestroyPrivateKey(key); | |
| 190 + } | |
| 191 + if (certChain) { | |
| 192 + CERT_DestroyCertificateList(certChain); | |
| 193 + } | |
| 194 + return SECFailure; | |
| 195 + } | |
| 196 + | |
| 197 + ssl_Get1stHandshakeLock(ss); /************************************/ | |
| 198 + | |
| 199 + if (ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 200 + ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain); | |
| 201 + } else { | |
| 202 + if (certChain != NULL) { | |
| 203 + CERT_DestroyCertificateList(certChain); | |
| 204 + } | |
| 205 + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 206 + ret = SECFailure; | |
| 207 + } | |
| 208 + | |
| 209 + ssl_Release1stHandshakeLock(ss); /************************************/ | |
| 210 + return ret; | |
| 211 } | |
| 212 | |
| 213 /* DO NOT USE. This function was exported in ssl.def with the wrong signature; | |
| OLD | NEW |