mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
1077 lines
37 KiB
Diff
1077 lines
37 KiB
Diff
Index: mozilla/security/nss/lib/ssl/SSLerrs.h
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/SSLerrs.h,v
|
|
retrieving revision 1.15
|
|
diff -u -8 -p -r1.15 SSLerrs.h
|
|
--- mozilla/security/nss/lib/ssl/SSLerrs.h 11 Nov 2011 19:06:51 -0000 1.15
|
|
+++ mozilla/security/nss/lib/ssl/SSLerrs.h 16 Nov 2011 08:21:01 -0000
|
|
@@ -406,8 +406,14 @@ ER3(SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED
|
|
ER3(SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY, (SSL_ERROR_BASE + 115),
|
|
"SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message.")
|
|
|
|
ER3(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, (SSL_ERROR_BASE + 116),
|
|
"SSL received invalid NPN extension data.")
|
|
|
|
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2, (SSL_ERROR_BASE + 117),
|
|
"SSL feature not supported for SSL 2.0 connections.")
|
|
+
|
|
+ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS, (SSL_ERROR_BASE + 118),
|
|
+"SSL feature not supported for servers.")
|
|
+
|
|
+ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS, (SSL_ERROR_BASE + 119),
|
|
+"SSL feature not supported for clients.")
|
|
Index: mozilla/security/nss/lib/ssl/ssl.def
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl.def,v
|
|
retrieving revision 1.27
|
|
diff -u -8 -p -r1.27 ssl.def
|
|
--- mozilla/security/nss/lib/ssl/ssl.def 29 Oct 2011 00:29:11 -0000 1.27
|
|
+++ mozilla/security/nss/lib/ssl/ssl.def 16 Nov 2011 08:21:01 -0000
|
|
@@ -164,11 +164,12 @@ NSSSSL_GetVersion;
|
|
;+ local:
|
|
;+ *;
|
|
;+};
|
|
;+NSS_3.13.2 { # NSS 3.13.2 release
|
|
;+ global:
|
|
SSL_SetNextProtoCallback;
|
|
SSL_SetNextProtoNego;
|
|
SSL_GetNextProto;
|
|
+SSL_RestartHandshakeAfterAuthCertificate;
|
|
;+ local:
|
|
;+ *;
|
|
;+};
|
|
Index: mozilla/security/nss/lib/ssl/ssl.h
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl.h,v
|
|
retrieving revision 1.45
|
|
diff -u -8 -p -r1.45 ssl.h
|
|
--- mozilla/security/nss/lib/ssl/ssl.h 29 Oct 2011 00:29:11 -0000 1.45
|
|
+++ mozilla/security/nss/lib/ssl/ssl.h 16 Nov 2011 08:21:01 -0000
|
|
@@ -334,16 +334,29 @@ SSL_IMPORT SECStatus SSL_SecurityStatus(
|
|
** "fd" the socket "file" descriptor
|
|
*/
|
|
SSL_IMPORT CERTCertificate *SSL_PeerCertificate(PRFileDesc *fd);
|
|
|
|
/*
|
|
** Authenticate certificate hook. Called when a certificate comes in
|
|
** (because of SSL_REQUIRE_CERTIFICATE in SSL_Enable) to authenticate the
|
|
** certificate.
|
|
+**
|
|
+** The authenticate certificate hook must return SECSuccess to indicate the
|
|
+** certificate is valid, SECFailure to indicate the certificate is invalid,
|
|
+** or SECWouldBlock if the application will authenticate the certificate
|
|
+** asynchronously.
|
|
+**
|
|
+** If the authenticate certificate hook returns SECFailure, then the bad cert
|
|
+** hook will be called. The bad cert handler is NEVER called if the
|
|
+** authenticate certificate hook returns SECWouldBlock.
|
|
+**
|
|
+** See the documentation for SSL_RestartHandshakeAfterAuthCertificate for more
|
|
+** information about the asynchronous behavior that occurs when the
|
|
+** authenticate certificate hook returns SECWouldBlock.
|
|
*/
|
|
typedef SECStatus (PR_CALLBACK *SSLAuthCertificate)(void *arg, PRFileDesc *fd,
|
|
PRBool checkSig,
|
|
PRBool isServer);
|
|
|
|
SSL_IMPORT SECStatus SSL_AuthCertificateHook(PRFileDesc *fd,
|
|
SSLAuthCertificate f,
|
|
void *arg);
|
|
@@ -437,16 +450,25 @@ SSL_IMPORT PRFileDesc *SSL_ReconfigFD(PR
|
|
* a - pkcs11 application specific data
|
|
*/
|
|
SSL_IMPORT SECStatus SSL_SetPKCS11PinArg(PRFileDesc *fd, void *a);
|
|
|
|
/*
|
|
** This is a callback for dealing with server certs that are not authenticated
|
|
** by the client. The client app can decide that it actually likes the
|
|
** cert by some external means and restart the connection.
|
|
+**
|
|
+** The bad cert hook must return SECSuccess to override the result of the
|
|
+** authenticate certificate hook, SECFailure if the certificate should still be
|
|
+** considered invalid, or SECWouldBlock if the application will authenticate
|
|
+** the certificate asynchronously.
|
|
+**
|
|
+** See the documentation for SSL_RestartHandshakeAfterAuthCertificate for more
|
|
+** information about the asynchronous behavior that occurs when the bad cert
|
|
+** hook returns SECWouldBlock.
|
|
*/
|
|
typedef SECStatus (PR_CALLBACK *SSLBadCertHandler)(void *arg, PRFileDesc *fd);
|
|
SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f,
|
|
void *arg);
|
|
|
|
/*
|
|
** Configure SSL socket for running a secure server. Needs the
|
|
** certificate for the server and the servers private key. The arguments
|
|
@@ -735,11 +757,58 @@ SSL_IMPORT SECStatus SSL_HandshakeNegoti
|
|
*/
|
|
extern PRBool NSSSSL_VersionCheck(const char *importedVersion);
|
|
|
|
/*
|
|
* Returns a const string of the SSL library version.
|
|
*/
|
|
extern const char *NSSSSL_GetVersion(void);
|
|
|
|
+/* Restart an SSL connection that was paused to do asynchronous certificate
|
|
+ * chain validation (when the auth certificate hook or bad cert handler
|
|
+ * returned SECWouldBlock).
|
|
+ *
|
|
+ * Currently, this function works only for the client role of a connection; it
|
|
+ * does not work for the server role.
|
|
+ *
|
|
+ * The application MUST call SSL_RestartHandshakeAfterAuthCertificate after it
|
|
+ * has successfully validated the peer's certificate to continue the SSL
|
|
+ * handshake.
|
|
+ *
|
|
+ * The application MUST NOT call SSL_RestartHandshakeAfterAuthCertificate when
|
|
+ * certificate validation fails; instead, it should just close the connection.
|
|
+ *
|
|
+ * This function will not complete the entire handshake. The application must
|
|
+ * call SSL_ForceHandshake, PR_Recv, PR_Send, etc. after calling this function
|
|
+ * to force the handshake to complete.
|
|
+ *
|
|
+ * libssl will wait for the peer's certificate to be authenticated before
|
|
+ * calling the handshake callback, sending a client certificate,
|
|
+ * sending any application data, or returning any application data to the
|
|
+ * application (on the first handshake on a connection only).
|
|
+ *
|
|
+ * However, libssl may send and receive handshake messages while waiting for
|
|
+ * the application to call SSL_RestartHandshakeAfterAuthCertificate, and it may
|
|
+ * call other callbacks (e.g, the client auth data hook) before
|
|
+ * SSL_RestartHandshakeAfterAuthCertificate has been called.
|
|
+ *
|
|
+ * An application that uses this asynchronous mechanism will usually have lower
|
|
+ * handshake latency if it has to do public key operations on the certificate
|
|
+ * chain during the authentication, especially if it does so in parallel on
|
|
+ * another thread. However, if the application can authenticate the peer's
|
|
+ * certificate quickly then it may be more efficient to use the synchronous
|
|
+ * mechanism (i.e. returning SECFailure/SECSuccess instead of SECWouldBlock
|
|
+ * from the authenticate certificate hook).
|
|
+ *
|
|
+ * Be careful about converting an application from synchronous cert validation
|
|
+ * to asynchronous certificate validation. A naive conversion is likely to
|
|
+ * result in deadlocks; e.g. the application will wait in PR_Poll for network
|
|
+ * I/O on the connection while all network I/O on the connection is blocked
|
|
+ * waiting for this function to be called.
|
|
+ *
|
|
+ * Returns SECFailure on failure, SECSuccess on success. Never returns
|
|
+ * SECWouldBlock.
|
|
+ */
|
|
+SSL_IMPORT SECStatus SSL_RestartHandshakeAfterAuthCertificate(PRFileDesc *fd);
|
|
+
|
|
SEC_END_PROTOS
|
|
|
|
#endif /* __ssl_h_ */
|
|
Index: mozilla/security/nss/lib/ssl/ssl3con.c
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3con.c,v
|
|
retrieving revision 1.155
|
|
diff -u -8 -p -r1.155 ssl3con.c
|
|
--- mozilla/security/nss/lib/ssl/ssl3con.c 11 Nov 2011 19:06:52 -0000 1.155
|
|
+++ mozilla/security/nss/lib/ssl/ssl3con.c 16 Nov 2011 08:21:02 -0000
|
|
@@ -5644,153 +5644,161 @@ loser:
|
|
PORT_SetError(errCode);
|
|
rv = SECFailure;
|
|
done:
|
|
if (arena != NULL)
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
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 makes a
|
|
- * copy of the private key, so the caller remains responsible
|
|
- * for destroying its copy 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;
|
|
-
|
|
- if (MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0)) {
|
|
- /* 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.clientCertChain = certChain;
|
|
- if (key == NULL) {
|
|
- (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
|
|
- ss->ssl3.clientPrivateKey = NULL;
|
|
- } else {
|
|
- ss->ssl3.clientPrivateKey = SECKEY_CopyPrivateKey(key);
|
|
- }
|
|
- ssl_GetRecvBufLock(ss);
|
|
- if (ss->ssl3.hs.msgState.buf != NULL) {
|
|
- rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
|
|
- }
|
|
- ssl_ReleaseRecvBufLock(ss);
|
|
- }
|
|
- }
|
|
- return rv;
|
|
-}
|
|
-
|
|
PRBool
|
|
ssl3_CanFalseStart(sslSocket *ss) {
|
|
PRBool rv;
|
|
|
|
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
|
|
|
+ /* XXX: does not take into account whether we are waiting for
|
|
+ * SSL_RestartHandshakeAfterAuthCertificate or
|
|
+ * SSL_RestartHandshakeAfterCertReq. If/when that is done, this function
|
|
+ * could return different results each time it would be called.
|
|
+ */
|
|
+
|
|
ssl_GetSpecReadLock(ss);
|
|
rv = ss->opt.enableFalseStart &&
|
|
!ss->sec.isServer &&
|
|
!ss->ssl3.hs.isResuming &&
|
|
ss->ssl3.cwSpec &&
|
|
ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
|
|
(ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa ||
|
|
ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh ||
|
|
ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh);
|
|
ssl_ReleaseSpecReadLock(ss);
|
|
return rv;
|
|
}
|
|
|
|
+static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
|
|
+
|
|
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
|
|
* ssl3 Server Hello Done message.
|
|
* Caller must hold Handshake and RecvBuf locks.
|
|
*/
|
|
static SECStatus
|
|
ssl3_HandleServerHelloDone(sslSocket *ss)
|
|
{
|
|
SECStatus rv;
|
|
SSL3WaitState ws = ss->ssl3.hs.ws;
|
|
- PRBool send_verify = PR_FALSE;
|
|
|
|
SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake",
|
|
SSL_GETPID(), ss->fd));
|
|
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
|
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
|
|
|
if (ws != wait_hello_done &&
|
|
ws != wait_server_cert &&
|
|
ws != wait_server_key &&
|
|
ws != wait_cert_request) {
|
|
SSL3_SendAlert(ss, alert_fatal, unexpected_message);
|
|
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
|
|
return SECFailure;
|
|
}
|
|
|
|
+ rv = ssl3_SendClientSecondRound(ss);
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+/* Called from ssl3_HandleServerHelloDone and
|
|
+ * ssl3_RestartHandshakeAfterServerCert.
|
|
+ *
|
|
+ * Caller must hold Handshake and RecvBuf locks.
|
|
+ */
|
|
+static SECStatus
|
|
+ssl3_SendClientSecondRound(sslSocket *ss)
|
|
+{
|
|
+ SECStatus rv;
|
|
+ PRBool sendClientCert;
|
|
+
|
|
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
|
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
|
+
|
|
+ sendClientCert = !ss->ssl3.sendEmptyCert &&
|
|
+ ss->ssl3.clientCertChain != NULL &&
|
|
+ ss->ssl3.clientPrivateKey != NULL;
|
|
+
|
|
+ /* We must wait for the server's certificate to be authenticated before
|
|
+ * sending the client certificate in order to disclosing the client
|
|
+ * certificate to an attacker that does not have a valid cert for the
|
|
+ * domain we are connecting to.
|
|
+ *
|
|
+ * XXX: We should do the same for the NPN extension, but for that we
|
|
+ * need an option to give the application the ability to leak the NPN
|
|
+ * information to get better performance.
|
|
+ *
|
|
+ * During the initial handshake on a connection, we never send/receive
|
|
+ * application data until we have authenticated the server's certificate;
|
|
+ * i.e. we have fully authenticated the handshake before using the cipher
|
|
+ * specs agreed upon for that handshake. During a renegotiation, we may
|
|
+ * continue sending and receiving application data during the handshake
|
|
+ * interleaved with the handshake records. If we were to send the client's
|
|
+ * second round for a renegotiation before the server's certificate was
|
|
+ * authenticated, then the application data sent/received after this point
|
|
+ * would be using cipher spec that hadn't been authenticated. By waiting
|
|
+ * until the server's certificate has been authenticated during
|
|
+ * renegotiations, we ensure that renegotiations have the same property
|
|
+ * as initial handshakes; i.e. we have fully authenticated the handshake
|
|
+ * before using the cipher specs agreed upon for that handshake for
|
|
+ * application data.
|
|
+ */
|
|
+ if (ss->ssl3.hs.restartTarget) {
|
|
+ PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
|
|
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
|
+ return SECFailure;
|
|
+ }
|
|
+ if (ss->ssl3.hs.authCertificatePending &&
|
|
+ (sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) {
|
|
+ ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
|
|
+ return SECWouldBlock;
|
|
+ }
|
|
+
|
|
ssl_GetXmitBufLock(ss); /*******************************/
|
|
|
|
if (ss->ssl3.sendEmptyCert) {
|
|
ss->ssl3.sendEmptyCert = PR_FALSE;
|
|
rv = ssl3_SendEmptyCertificate(ss);
|
|
/* Don't send verify */
|
|
if (rv != SECSuccess) {
|
|
goto loser; /* error code is set. */
|
|
}
|
|
- } else
|
|
- if (ss->ssl3.clientCertChain != NULL &&
|
|
- ss->ssl3.clientPrivateKey != NULL) {
|
|
- send_verify = PR_TRUE;
|
|
+ } else if (sendClientCert) {
|
|
rv = ssl3_SendCertificate(ss);
|
|
if (rv != SECSuccess) {
|
|
goto loser; /* error code is set. */
|
|
}
|
|
}
|
|
|
|
rv = ssl3_SendClientKeyExchange(ss);
|
|
if (rv != SECSuccess) {
|
|
goto loser; /* err is set. */
|
|
}
|
|
|
|
- if (send_verify) {
|
|
+ if (sendClientCert) {
|
|
rv = ssl3_SendCertificateVerify(ss);
|
|
if (rv != SECSuccess) {
|
|
goto loser; /* err is set. */
|
|
}
|
|
}
|
|
+
|
|
rv = ssl3_SendChangeCipherSpecs(ss);
|
|
if (rv != SECSuccess) {
|
|
goto loser; /* err code was set. */
|
|
}
|
|
|
|
+ /* XXX: If the server's certificate hasn't been authenticated by this
|
|
+ * point, then we may be leaking this NPN message to an attacker.
|
|
+ */
|
|
if (!ss->firstHsDone) {
|
|
rv = ssl3_SendNextProto(ss);
|
|
if (rv != SECSuccess) {
|
|
goto loser; /* err code was set. */
|
|
}
|
|
}
|
|
|
|
rv = ssl3_SendFinished(ss, 0);
|
|
@@ -7809,18 +7817,16 @@ ssl3_CleanupPeerCerts(sslSocket *ss)
|
|
* ssl3 Certificate message.
|
|
* Caller must hold Handshake and RecvBuf locks.
|
|
*/
|
|
static SECStatus
|
|
ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
|
{
|
|
ssl3CertNode * c;
|
|
ssl3CertNode * lastCert = NULL;
|
|
- ssl3CertNode * certs = NULL;
|
|
- PRArenaPool * arena = NULL;
|
|
PRInt32 remaining = 0;
|
|
PRInt32 size;
|
|
SECStatus rv;
|
|
PRBool isServer = (PRBool)(!!ss->sec.isServer);
|
|
PRBool trusted = PR_FALSE;
|
|
PRBool isTLS;
|
|
SSL3AlertDescription desc = bad_certificate;
|
|
int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
|
|
@@ -7867,21 +7873,21 @@ ssl3_HandleCertificate(sslSocket *ss, SS
|
|
goto alert_loser;
|
|
/* This is TLS's version of a no_certificate alert. */
|
|
/* I'm a server. I've requested a client cert. He hasn't got one. */
|
|
rv = ssl3_HandleNoCertificate(ss);
|
|
if (rv != SECSuccess) {
|
|
errCode = PORT_GetError();
|
|
goto loser;
|
|
}
|
|
- goto cert_block;
|
|
+ goto server_no_cert;
|
|
}
|
|
|
|
- ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
- if ( arena == NULL ) {
|
|
+ ss->ssl3.peerCertArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
+ if (ss->ssl3.peerCertArena == NULL) {
|
|
goto loser; /* don't send alerts on memory errors */
|
|
}
|
|
|
|
/* First get the peer cert. */
|
|
remaining -= 3;
|
|
if (remaining < 0)
|
|
goto decode_loser;
|
|
|
|
@@ -7921,17 +7927,17 @@ ssl3_HandleCertificate(sslSocket *ss, SS
|
|
goto decode_loser;
|
|
|
|
certItem.data = b;
|
|
certItem.len = size;
|
|
b += size;
|
|
length -= size;
|
|
remaining -= size;
|
|
|
|
- c = PORT_ArenaNew(arena, ssl3CertNode);
|
|
+ c = PORT_ArenaNew(ss->ssl3.peerCertArena, ssl3CertNode);
|
|
if (c == NULL) {
|
|
goto loser; /* don't send alerts on memory errors */
|
|
}
|
|
|
|
c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
|
|
PR_FALSE, PR_TRUE);
|
|
if (c->cert == NULL) {
|
|
goto ambiguous_err;
|
|
@@ -7939,51 +7945,55 @@ ssl3_HandleCertificate(sslSocket *ss, SS
|
|
|
|
if (c->cert->trust)
|
|
trusted = PR_TRUE;
|
|
|
|
c->next = NULL;
|
|
if (lastCert) {
|
|
lastCert->next = c;
|
|
} else {
|
|
- certs = c;
|
|
+ ss->ssl3.peerCertChain = c;
|
|
}
|
|
lastCert = c;
|
|
}
|
|
|
|
if (remaining != 0)
|
|
goto decode_loser;
|
|
|
|
SECKEY_UpdateCertPQG(ss->sec.peerCert);
|
|
|
|
+ ss->ssl3.hs.authCertificatePending = PR_FALSE;
|
|
+
|
|
/*
|
|
* Ask caller-supplied callback function to validate cert chain.
|
|
*/
|
|
rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd,
|
|
PR_TRUE, isServer);
|
|
if (rv) {
|
|
errCode = PORT_GetError();
|
|
- if (!ss->handleBadCert) {
|
|
- goto bad_cert;
|
|
+ if (rv != SECWouldBlock) {
|
|
+ if (ss->handleBadCert) {
|
|
+ rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
|
|
+ }
|
|
}
|
|
- rv = (SECStatus)(*ss->handleBadCert)(ss->badCertArg, ss->fd);
|
|
- if ( rv ) {
|
|
- if ( rv == SECWouldBlock ) {
|
|
- /* someone will handle this connection asynchronously*/
|
|
- SSL_DBG(("%d: SSL3[%d]: go to async cert handler",
|
|
- SSL_GETPID(), ss->fd));
|
|
- ss->ssl3.peerCertChain = certs;
|
|
- certs = NULL;
|
|
- ssl3_SetAlwaysBlock(ss);
|
|
- goto cert_block;
|
|
+
|
|
+ if (rv == SECWouldBlock) {
|
|
+ if (ss->sec.isServer) {
|
|
+ errCode = SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS;
|
|
+ rv = SECFailure;
|
|
+ goto loser;
|
|
}
|
|
- /* cert is bad */
|
|
+
|
|
+ ss->ssl3.hs.authCertificatePending = PR_TRUE;
|
|
+ rv = SECSuccess;
|
|
+ }
|
|
+
|
|
+ if (rv != SECSuccess) {
|
|
goto bad_cert;
|
|
}
|
|
- /* cert is good */
|
|
}
|
|
|
|
ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
|
|
|
|
if (!ss->sec.isServer) {
|
|
CERTCertificate *cert = ss->sec.peerCert;
|
|
|
|
/* set the server authentication and key exchange types and sizes
|
|
@@ -8021,39 +8031,38 @@ ssl3_HandleCertificate(sslSocket *ss, SS
|
|
* destroy pubKey and goto bad_cert
|
|
*/
|
|
}
|
|
}
|
|
#endif /* NSS_ENABLE_ECC */
|
|
SECKEY_DestroyPublicKey(pubKey);
|
|
pubKey = NULL;
|
|
}
|
|
- }
|
|
|
|
- ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL;
|
|
-
|
|
-cert_block:
|
|
- if (ss->sec.isServer) {
|
|
- ss->ssl3.hs.ws = wait_client_key;
|
|
- } else {
|
|
ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
|
|
if (ss->ssl3.hs.kea_def->is_limited ||
|
|
/* XXX OR server cert is signing only. */
|
|
#ifdef NSS_ENABLE_ECC
|
|
ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
|
|
ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
|
|
#endif /* NSS_ENABLE_ECC */
|
|
ss->ssl3.hs.kea_def->exchKeyType == kt_dh) {
|
|
ss->ssl3.hs.ws = wait_server_key; /* allow server_key_exchange */
|
|
}
|
|
+ } else {
|
|
+server_no_cert:
|
|
+ ss->ssl3.hs.ws = wait_client_key;
|
|
}
|
|
|
|
- /* rv must normally be equal to SECSuccess here. If we called
|
|
- * handleBadCert, it can also be SECWouldBlock.
|
|
- */
|
|
+ PORT_Assert(rv == SECSuccess);
|
|
+ if (rv != SECSuccess) {
|
|
+ errCode = SEC_ERROR_LIBRARY_FAILURE;
|
|
+ rv = SECFailure;
|
|
+ goto loser;
|
|
+ }
|
|
return rv;
|
|
|
|
ambiguous_err:
|
|
errCode = PORT_GetError();
|
|
switch (errCode) {
|
|
case PR_OUT_OF_MEMORY_ERROR:
|
|
case SEC_ERROR_BAD_DATABASE:
|
|
case SEC_ERROR_NO_MEMORY:
|
|
@@ -8094,64 +8103,69 @@ bad_cert: /* caller has set errCode. */
|
|
|
|
decode_loser:
|
|
desc = isTLS ? decode_error : bad_certificate;
|
|
|
|
alert_loser:
|
|
(void)SSL3_SendAlert(ss, alert_fatal, desc);
|
|
|
|
loser:
|
|
- ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL;
|
|
ssl3_CleanupPeerCerts(ss);
|
|
|
|
if (ss->sec.peerCert != NULL) {
|
|
CERT_DestroyCertificate(ss->sec.peerCert);
|
|
ss->sec.peerCert = NULL;
|
|
}
|
|
(void)ssl_MapLowLevelError(errCode);
|
|
return SECFailure;
|
|
}
|
|
|
|
+static SECStatus ssl3_FinishHandshake(sslSocket *ss);
|
|
|
|
-/* restart an SSL connection that we stopped to run certificate dialogs
|
|
-** XXX Need to document here how an application marks a cert to show that
|
|
-** the application has accepted it (overridden CERT_VerifyCert).
|
|
- *
|
|
- * XXX This code only works on the initial handshake on a connection, XXX
|
|
- * It does not work on a subsequent handshake (redo).
|
|
- *
|
|
- * Return value: XXX
|
|
- *
|
|
- * Caller holds 1stHandshakeLock.
|
|
+/* Caller must hold 1stHandshakeLock.
|
|
*/
|
|
-int
|
|
-ssl3_RestartHandshakeAfterServerCert(sslSocket *ss)
|
|
+SECStatus
|
|
+ssl3_RestartHandshakeAfterAuthCertificate(sslSocket *ss)
|
|
{
|
|
- int rv = SECSuccess;
|
|
+ SECStatus rv;
|
|
|
|
- if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) {
|
|
- SET_ERROR_CODE
|
|
- return SECFailure;
|
|
- }
|
|
- if (!ss->ssl3.initialized) {
|
|
- SET_ERROR_CODE
|
|
- return SECFailure;
|
|
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
|
|
+
|
|
+ if (ss->sec.isServer) {
|
|
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS);
|
|
+ return SECFailure;
|
|
}
|
|
|
|
- if (ss->handshake != NULL) {
|
|
- ss->handshake = ssl_GatherRecord1stHandshake;
|
|
- ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
|
|
+ ssl_GetRecvBufLock(ss);
|
|
+ ssl_GetSSL3HandshakeLock(ss);
|
|
|
|
- ssl_GetRecvBufLock(ss);
|
|
- if (ss->ssl3.hs.msgState.buf != NULL) {
|
|
- rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
|
|
- }
|
|
- ssl_ReleaseRecvBufLock(ss);
|
|
+ if (!ss->ssl3.hs.authCertificatePending) {
|
|
+ PORT_SetError(PR_INVALID_STATE_ERROR);
|
|
+ rv = SECFailure;
|
|
+ } else {
|
|
+ ss->ssl3.hs.authCertificatePending = PR_FALSE;
|
|
+ if (ss->ssl3.hs.restartTarget != NULL) {
|
|
+ sslRestartTarget target = ss->ssl3.hs.restartTarget;
|
|
+ ss->ssl3.hs.restartTarget = NULL;
|
|
+ rv = target(ss);
|
|
+ /* Even if we blocked here, we have accomplished enough to claim
|
|
+ * success. Any remaining work will be taken care of by subsequent
|
|
+ * calls to SSL_ForceHandshake/PR_Send/PR_Read/etc.
|
|
+ */
|
|
+ if (rv == SECWouldBlock) {
|
|
+ rv = SECSuccess;
|
|
+ }
|
|
+ } else {
|
|
+ rv = SECSuccess;
|
|
+ }
|
|
}
|
|
|
|
+ ssl_ReleaseSSL3HandshakeLock(ss);
|
|
+ ssl_ReleaseRecvBufLock(ss);
|
|
+
|
|
return rv;
|
|
}
|
|
|
|
static SECStatus
|
|
ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
|
|
PRBool isServer,
|
|
const SSL3Finished * hashes,
|
|
TLSFinished * tlsFinished)
|
|
@@ -8494,19 +8508,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3O
|
|
}
|
|
|
|
xmit_loser:
|
|
ssl_ReleaseXmitBufLock(ss); /*************************************/
|
|
if (rv != SECSuccess) {
|
|
return rv;
|
|
}
|
|
|
|
- /* The first handshake is now completed. */
|
|
- ss->handshake = NULL;
|
|
- ss->firstHsDone = PR_TRUE;
|
|
ss->gs.writeOffset = 0;
|
|
ss->gs.readOffset = 0;
|
|
|
|
if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
|
|
effectiveExchKeyType = kt_rsa;
|
|
} else {
|
|
effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
|
|
}
|
|
@@ -8546,20 +8557,52 @@ xmit_loser:
|
|
effectiveExchKeyType);
|
|
sid->u.ssl3.keys.msIsWrapped = PR_TRUE;
|
|
}
|
|
ssl_ReleaseSpecReadLock(ss); /*************************************/
|
|
|
|
/* If the wrap failed, we don't cache the sid.
|
|
* The connection continues normally however.
|
|
*/
|
|
- if (rv == SECSuccess) {
|
|
- (*ss->sec.cache)(sid);
|
|
- }
|
|
+ ss->ssl3.hs.cacheSID = rv == SECSuccess;
|
|
}
|
|
+
|
|
+ if (ss->ssl3.hs.authCertificatePending) {
|
|
+ if (ss->ssl3.hs.restartTarget) {
|
|
+ PR_NOT_REACHED("ssl3_HandleFinished: unexpected restartTarget");
|
|
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
|
+ return SECFailure;
|
|
+ }
|
|
+
|
|
+ ss->ssl3.hs.restartTarget = ssl3_FinishHandshake;
|
|
+ return SECWouldBlock;
|
|
+ }
|
|
+
|
|
+ rv = ssl3_FinishHandshake(ss);
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+SECStatus
|
|
+ssl3_FinishHandshake(sslSocket * ss)
|
|
+{
|
|
+ SECStatus rv;
|
|
+
|
|
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
|
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
|
+ PORT_Assert( ss->ssl3.hs.restartTarget == NULL );
|
|
+
|
|
+ /* The first handshake is now completed. */
|
|
+ ss->handshake = NULL;
|
|
+ ss->firstHsDone = PR_TRUE;
|
|
+
|
|
+ if (ss->sec.ci.sid->cached == never_cached &&
|
|
+ !ss->opt.noCache && ss->sec.cache && ss->ssl3.hs.cacheSID) {
|
|
+ (*ss->sec.cache)(ss->sec.ci.sid);
|
|
+ }
|
|
+
|
|
ss->ssl3.hs.ws = idle_handshake;
|
|
|
|
/* Do the handshake callback for sslv3 here, if we cannot false start. */
|
|
if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
|
|
(ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
|
}
|
|
|
|
return SECSuccess;
|
|
Index: mozilla/security/nss/lib/ssl/ssl3gthr.c
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3gthr.c,v
|
|
retrieving revision 1.10
|
|
diff -u -8 -p -r1.10 ssl3gthr.c
|
|
--- mozilla/security/nss/lib/ssl/ssl3gthr.c 30 Jul 2010 03:00:17 -0000 1.10
|
|
+++ mozilla/security/nss/lib/ssl/ssl3gthr.c 16 Nov 2011 08:21:02 -0000
|
|
@@ -187,31 +187,63 @@ int
|
|
ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
|
|
{
|
|
SSL3Ciphertext cText;
|
|
int rv;
|
|
PRBool canFalseStart = PR_FALSE;
|
|
|
|
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
|
do {
|
|
- /* bring in the next sslv3 record. */
|
|
- rv = ssl3_GatherData(ss, &ss->gs, flags);
|
|
- if (rv <= 0) {
|
|
- return rv;
|
|
- }
|
|
-
|
|
- /* decipher it, and handle it if it's a handshake.
|
|
- * If it's application data, ss->gs.buf will not be empty upon return.
|
|
- * If it's a change cipher spec, alert, or handshake message,
|
|
- * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
|
|
- */
|
|
- cText.type = (SSL3ContentType)ss->gs.hdr[0];
|
|
- cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
|
|
- cText.buf = &ss->gs.inbuf;
|
|
- rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
|
|
+ /* Without this, we may end up wrongly reporting
|
|
+ * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
|
|
+ * peer while we are waiting to be restarted.
|
|
+ */
|
|
+ ssl_GetSSL3HandshakeLock(ss);
|
|
+ rv = ss->ssl3.hs.restartTarget == NULL ? SECSuccess : SECFailure;
|
|
+ ssl_ReleaseSSL3HandshakeLock(ss);
|
|
+ if (rv != SECSuccess) {
|
|
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
|
|
+ return (int) SECFailure;
|
|
+ }
|
|
+
|
|
+ /* Treat an empty msgState like a NULL msgState. (Most of the time
|
|
+ * when ssl3_HandleHandshake returns SECWouldBlock, it leaves
|
|
+ * behind a non-NULL but zero-length msgState).
|
|
+ * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
|
|
+ */
|
|
+ if (ss->ssl3.hs.msgState.buf != NULL) {
|
|
+ if (ss->ssl3.hs.msgState.len == 0) {
|
|
+ ss->ssl3.hs.msgState.buf = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ss->ssl3.hs.msgState.buf != NULL) {
|
|
+ /* ssl3_HandleHandshake previously returned SECWouldBlock and the
|
|
+ * as-yet-unprocessed plaintext of that previous handshake record.
|
|
+ * We need to process it now before we overwrite it with the next
|
|
+ * handshake record.
|
|
+ */
|
|
+ rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
|
|
+ } else {
|
|
+ /* bring in the next sslv3 record. */
|
|
+ rv = ssl3_GatherData(ss, &ss->gs, flags);
|
|
+ if (rv <= 0) {
|
|
+ return rv;
|
|
+ }
|
|
+
|
|
+ /* decipher it, and handle it if it's a handshake.
|
|
+ * If it's application data, ss->gs.buf will not be empty upon return.
|
|
+ * If it's a change cipher spec, alert, or handshake message,
|
|
+ * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
|
|
+ */
|
|
+ cText.type = (SSL3ContentType)ss->gs.hdr[0];
|
|
+ cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
|
|
+ cText.buf = &ss->gs.inbuf;
|
|
+ rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
|
|
+ }
|
|
if (rv < 0) {
|
|
return ss->recvdCloseNotify ? 0 : rv;
|
|
}
|
|
|
|
/* If we kicked off a false start in ssl3_HandleServerHelloDone, break
|
|
* out of this loop early without finishing the handshake.
|
|
*/
|
|
if (ss->opt.enableFalseStart) {
|
|
Index: mozilla/security/nss/lib/ssl/sslerr.h
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslerr.h,v
|
|
retrieving revision 1.16
|
|
diff -u -8 -p -r1.16 sslerr.h
|
|
--- mozilla/security/nss/lib/ssl/sslerr.h 11 Nov 2011 19:06:52 -0000 1.16
|
|
+++ mozilla/security/nss/lib/ssl/sslerr.h 16 Nov 2011 08:21:02 -0000
|
|
@@ -203,14 +203,16 @@ SSL_ERROR_UNSAFE_NEGOTIATION
|
|
|
|
SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BASE + 114),
|
|
|
|
SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY = (SSL_ERROR_BASE + 115),
|
|
|
|
SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID = (SSL_ERROR_BASE + 116),
|
|
|
|
SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2 = (SSL_ERROR_BASE + 117),
|
|
+SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS = (SSL_ERROR_BASE + 118),
|
|
+SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS = (SSL_ERROR_BASE + 119),
|
|
|
|
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
|
|
} SSLErrorCodes;
|
|
#endif /* NO_SECURITY_ERROR_ENUM */
|
|
|
|
#endif /* __SSL_ERR_H_ */
|
|
Index: mozilla/security/nss/lib/ssl/sslimpl.h
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslimpl.h,v
|
|
retrieving revision 1.87
|
|
diff -u -8 -p -r1.87 sslimpl.h
|
|
--- mozilla/security/nss/lib/ssl/sslimpl.h 11 Nov 2011 19:06:52 -0000 1.87
|
|
+++ mozilla/security/nss/lib/ssl/sslimpl.h 16 Nov 2011 08:21:02 -0000
|
|
@@ -745,16 +745,18 @@ struct TLSExtensionDataStr {
|
|
/* SNI Extension related data
|
|
* Names data is not coppied from the input buffer. It can not be
|
|
* used outside the scope where input buffer is defined and that
|
|
* is beyond ssl3_HandleClientHello function. */
|
|
SECItem *sniNameArr;
|
|
PRUint32 sniNameArrSize;
|
|
};
|
|
|
|
+typedef SECStatus (*sslRestartTarget)(sslSocket *);
|
|
+
|
|
/*
|
|
** This is the "hs" member of the "ssl3" struct.
|
|
** This entire struct is protected by ssl3HandshakeLock
|
|
*/
|
|
typedef struct SSL3HandshakeStateStr {
|
|
SSL3Random server_random;
|
|
SSL3Random client_random;
|
|
SSL3WaitState ws;
|
|
@@ -784,16 +786,23 @@ const ssl3CipherSuiteDef *suite_def;
|
|
union {
|
|
TLSFinished tFinished[2]; /* client, then server */
|
|
SSL3Hashes sFinished[2];
|
|
SSL3Opaque data[72];
|
|
} finishedMsgs;
|
|
#ifdef NSS_ENABLE_ECC
|
|
PRUint32 negotiatedECCurves; /* bit mask */
|
|
#endif /* NSS_ENABLE_ECC */
|
|
+
|
|
+ PRBool authCertificatePending;
|
|
+ /* Which function should SSL_RestartHandshake* call if we're blocked?
|
|
+ * One of NULL, ssl3_SendClientSecondRound, or ssl3_FinishHandshake. */
|
|
+ sslRestartTarget restartTarget;
|
|
+ /* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */
|
|
+ PRBool cacheSID;
|
|
} SSL3HandshakeState;
|
|
|
|
|
|
|
|
/*
|
|
** This is the "ssl3" struct, as in "ss->ssl3".
|
|
** note:
|
|
** usually, crSpec == cwSpec and prSpec == pwSpec.
|
|
@@ -1335,32 +1344,26 @@ extern SECStatus ssl3_KeyAndMacDeriveByp
|
|
PRBool isTLS, PRBool isExport);
|
|
extern SECStatus ssl3_MasterKeyDeriveBypass( ssl3CipherSpec * pwSpec,
|
|
const unsigned char * cr, const unsigned char * sr,
|
|
const SECItem * pms, PRBool isTLS, PRBool isRSA);
|
|
|
|
/* These functions are called from secnav, even though they're "private". */
|
|
|
|
extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error);
|
|
-extern int SSL_RestartHandshakeAfterServerCert(struct sslSocketStr *ss);
|
|
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_RestartHandshakeAfterCertReq(sslSocket * ss,
|
|
- CERTCertificate * cert,
|
|
- SECKEYPrivateKey * key,
|
|
- CERTCertificateList *certChain);
|
|
-
|
|
-extern int ssl3_RestartHandshakeAfterServerCert(sslSocket *ss);
|
|
+extern SECStatus ssl3_RestartHandshakeAfterAuthCertificate(sslSocket *ss);
|
|
|
|
/*
|
|
* for dealing with SSL 3.0 clients sending SSL 2.0 format hellos
|
|
*/
|
|
extern SECStatus ssl3_HandleV2ClientHello(
|
|
sslSocket *ss, unsigned char *buffer, int length);
|
|
extern SECStatus ssl3_StartHandshakeHash(
|
|
sslSocket *ss, unsigned char *buf, int length);
|
|
Index: mozilla/security/nss/lib/ssl/sslsecur.c
|
|
===================================================================
|
|
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslsecur.c,v
|
|
retrieving revision 1.51
|
|
diff -u -8 -p -r1.51 sslsecur.c
|
|
--- mozilla/security/nss/lib/ssl/sslsecur.c 11 Nov 2011 19:06:52 -0000 1.51
|
|
+++ mozilla/security/nss/lib/ssl/sslsecur.c 16 Nov 2011 08:21:02 -0000
|
|
@@ -1458,86 +1458,66 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERT
|
|
if (!dbHandle) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
return SECFailure;
|
|
}
|
|
ss->dbHandle = dbHandle;
|
|
return SECSuccess;
|
|
}
|
|
|
|
-/*
|
|
- * 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 makes a
|
|
- * copy of the private key, so the caller remains responsible
|
|
- * for destroying its copy 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).
|
|
+/* DO NOT USE. This function was exported in ssl.def with the wrong signature;
|
|
+ * this implementation exists to maintain link-time compatibility.
|
|
*/
|
|
int
|
|
SSL_RestartHandshakeAfterCertReq(sslSocket * ss,
|
|
CERTCertificate * cert,
|
|
SECKEYPrivateKey * key,
|
|
CERTCertificateList *certChain)
|
|
{
|
|
- int ret;
|
|
-
|
|
- ssl_Get1stHandshakeLock(ss); /************************************/
|
|
-
|
|
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
|
|
- ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
|
|
- } else {
|
|
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
|
|
- ret = SECFailure;
|
|
- }
|
|
-
|
|
- ssl_Release1stHandshakeLock(ss); /************************************/
|
|
- return ret;
|
|
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
|
+ return -1;
|
|
}
|
|
|
|
-
|
|
-/* restart an SSL connection that we stopped to run certificate dialogs
|
|
-** XXX Need to document here how an application marks a cert to show that
|
|
-** the application has accepted it (overridden CERT_VerifyCert).
|
|
- *
|
|
- * XXX This code only works on the initial handshake on a connection, XXX
|
|
- * It does not work on a subsequent handshake (redo).
|
|
- *
|
|
- * Return value: XXX
|
|
-*/
|
|
+/* DO NOT USE. This function was exported in ssl.def with the wrong signature;
|
|
+ * this implementation exists to maintain link-time compatibility.
|
|
+ */
|
|
int
|
|
-SSL_RestartHandshakeAfterServerCert(sslSocket *ss)
|
|
+SSL_RestartHandshakeAfterServerCert(sslSocket * ss)
|
|
+{
|
|
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/* See documentation in ssl.h */
|
|
+SECStatus
|
|
+SSL_RestartHandshakeAfterAuthCertificate(PRFileDesc *fd)
|
|
{
|
|
- int rv = SECSuccess;
|
|
+ SECStatus rv = SECSuccess;
|
|
+ sslSocket *ss = ssl_FindSocket(fd);
|
|
+
|
|
+ if (!ss) {
|
|
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterPeerCert",
|
|
+ SSL_GETPID(), fd));
|
|
+ return SECFailure;
|
|
+ }
|
|
|
|
- ssl_Get1stHandshakeLock(ss);
|
|
+ ssl_Get1stHandshakeLock(ss);
|
|
|
|
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
|
|
- rv = ssl3_RestartHandshakeAfterServerCert(ss);
|
|
+ if (!ss->ssl3.initialized) {
|
|
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
+ rv = SECFailure;
|
|
+ } else if (ss->version < SSL_LIBRARY_VERSION_3_0) {
|
|
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
|
|
+ rv = SECFailure;
|
|
} else {
|
|
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
|
|
- rv = SECFailure;
|
|
+ rv = ssl3_RestartHandshakeAfterAuthCertificate(ss);
|
|
}
|
|
|
|
ssl_Release1stHandshakeLock(ss);
|
|
+
|
|
return rv;
|
|
}
|
|
|
|
/* For more info see ssl.h */
|
|
SECStatus
|
|
SSL_SNISocketConfigHook(PRFileDesc *fd, SSLSNISocketConfig func,
|
|
void *arg)
|
|
{
|