/* Go through hello extensions in |b| and deserialize * them into the list in |ss->ssl3.hs.remoteExtensions|. * The only checking we do in this point is for duplicates. * * IMPORTANT: This list just contains pointers to the incoming * buffer so they can only be used during ClientHello processing. */ SECStatus ssl3_ParseExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length) { /* Clean out the extensions list. */ ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); while (*length) { SECStatus rv; PRUint32 extension_type; SECItem extension_data = { siBuffer, NULL, 0 }; TLSExtension *extension; PRCList *cursor; /* Get the extension's type field */ rv = ssl3_ConsumeHandshakeNumber(ss, &extension_type, 2, b, length); if (rv != SECSuccess) { return SECFailure; /* alert already sent */ } /* Check whether an extension has been sent multiple times. */ for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions); cursor != &ss->ssl3.hs.remoteExtensions; cursor = PR_NEXT_LINK(cursor)) { if (((TLSExtension *)cursor)->type == extension_type) { (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION); return SECFailure; } } /* Get the data for this extension, so we can pass it or skip it. */ rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length); if (rv != SECSuccess) { return rv; /* alert already sent */ } SSL_TRC(10, ("%d: SSL3[%d]: parsed extension %d len=%u", SSL_GETPID(), ss->fd, extension_type, extension_data.len)); extension = PORT_ZNew(TLSExtension); if (!extension) { return SECFailure; } extension->type = (PRUint16)extension_type; extension->data = extension_data; PR_APPEND_LINK(&extension->link, &ss->ssl3.hs.remoteExtensions); } return SECSuccess; }
/* Syntactic sugar around ssl3_ParseExtensions and * ssl3_HandleParsedExtensions. */ SECStatus ssl3_HandleExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length, SSLHandshakeType handshakeMessage) { SECStatus rv; rv = ssl3_ParseExtensions(ss, b, length); if (rv != SECSuccess) return rv; rv = ssl3_HandleParsedExtensions(ss, handshakeMessage); if (rv != SECSuccess) return rv; ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); return SECSuccess; }
/* Acquires and releases HandshakeLock. */ SECStatus SSL_ResetHandshake(PRFileDesc *s, PRBool asServer) { sslSocket *ss; SECStatus status; PRNetAddr addr; ss = ssl_FindSocket(s); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s)); return SECFailure; } /* Don't waste my time */ if (!ss->opt.useSecurity) return SECSuccess; SSL_LOCK_READER(ss); SSL_LOCK_WRITER(ss); /* Reset handshake state */ ssl_Get1stHandshakeLock(ss); ss->firstHsDone = PR_FALSE; ss->enoughFirstHsDone = PR_FALSE; if (asServer) { ss->handshake = ssl_BeginServerHandshake; ss->handshaking = sslHandshakingAsServer; } else { ss->handshake = ssl_BeginClientHandshake; ss->handshaking = sslHandshakingAsClient; } ssl_GetRecvBufLock(ss); status = ssl3_InitGather(&ss->gs); ssl_ReleaseRecvBufLock(ss); if (status != SECSuccess) goto loser; ssl_GetSSL3HandshakeLock(ss); ss->ssl3.hs.canFalseStart = PR_FALSE; ss->ssl3.hs.restartTarget = NULL; /* ** Blow away old security state and get a fresh setup. */ ssl_GetXmitBufLock(ss); ssl_ResetSecurityInfo(&ss->sec, PR_TRUE); status = ssl_CreateSecurityInfo(ss); ssl_ReleaseXmitBufLock(ss); ssl_ReleaseSSL3HandshakeLock(ss); ssl_Release1stHandshakeLock(ss); ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); if (!ss->TCPconnected) ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr)); loser: SSL_UNLOCK_WRITER(ss); SSL_UNLOCK_READER(ss); return status; }