Bug 858231: Update NSS to NSS 3.15 Beta 5. r=wtc.

Inclues fixes for bug 869262, bug 863947, bug 866362, bug 863871,
and bug 808217.
This commit is contained in:
Wan-Teh Chang 2013-05-20 15:28:12 -07:00
parent bf68457834
commit fe7a4f9783
21 changed files with 285 additions and 201 deletions

View File

@ -1 +1 @@
NSS_3_15_BETA4
NSS_3_15_BETA5

View File

@ -1033,8 +1033,7 @@ misalignBuffer(PLArenaPool *arena, bltestIO *io, int off)
ptrdiff_t offset = (ptrdiff_t)io->buf.data % WORDSIZE;
int length = io->buf.len;
if (offset != off) {
SECITEM_ReallocItem(arena, &io->buf, length, length + 2*WORDSIZE);
io->buf.len = length + 2*WORDSIZE; /* why doesn't realloc do this? */
SECITEM_ReallocItemV2(arena, &io->buf, length + 2*WORDSIZE);
/* offset may have changed? */
offset = (ptrdiff_t)io->buf.data % WORDSIZE;
if (offset != off) {

View File

@ -530,7 +530,7 @@ SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
}
} else {
/* need one additional byte for zero terminator */
rv = SECITEM_ReallocItem(NULL, &filedata, filedata.len, filedata.len+1);
rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len+1);
if (rv != SECSuccess) {
PORT_Free(filedata.data);
return rv;

View File

@ -92,7 +92,7 @@ static enum ocspStaplingModeEnum {
} ocspStaplingMode = osm_disabled;
typedef enum ocspStaplingModeEnum ocspStaplingModeType;
static char *ocspStaplingCA = NULL;
CERTCertificate * certForStatusWeakReference = NULL;
static SECItemArray *certStatus[kt_kea_size] = { NULL };
const int ssl2CipherSuites[] = {
SSL_EN_RC4_128_WITH_MD5, /* A */
@ -1108,7 +1108,7 @@ makeCorruptedOCSPResponse(PLArenaPool *arena)
SECItemArray *
makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm,
PRFileDesc *model_sock, CERTCertificate *cert)
CERTCertificate *cert, secuPWData *pwdata)
{
SECItemArray *result = NULL;
SECItem *ocspResponse = NULL;
@ -1118,9 +1118,8 @@ makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm,
CERTCertificate *ca;
PRTime now = PR_Now();
PRTime nextUpdate;
secuPWData *pwdata;
PORT_Assert(model_sock != NULL && cert != NULL);
PORT_Assert(cert != NULL);
ca = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), ocspStaplingCA);
if (!ca)
@ -1164,8 +1163,6 @@ makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm,
singleResponses[0] = sr;
singleResponses[1] = NULL;
pwdata = SSL_RevealPinArg(model_sock);
ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena,
(osm == osm_badsig) ? NULL : ca,
ocspResponderID_byName, now, singleResponses,
@ -1189,6 +1186,53 @@ makeSignedOCSPResponse(PLArenaPool *arena, ocspStaplingModeType osm,
return result;
}
void
setupCertStatus(PLArenaPool *arena, enum ocspStaplingModeEnum ocspStaplingMode,
CERTCertificate *cert, SSLKEAType kea, secuPWData *pwdata)
{
if (ocspStaplingMode == osm_random) {
/* 6 different responses */
int r = rand() % 6;
switch (r) {
case 0: ocspStaplingMode = osm_good; break;
case 1: ocspStaplingMode = osm_revoked; break;
case 2: ocspStaplingMode = osm_unknown; break;
case 3: ocspStaplingMode = osm_badsig; break;
case 4: ocspStaplingMode = osm_corrupted; break;
case 5: ocspStaplingMode = osm_failure; break;
default: PORT_Assert(0); break;
}
}
if (ocspStaplingMode != osm_disabled) {
SECItemArray *multiOcspResponses = NULL;
switch (ocspStaplingMode) {
case osm_good:
case osm_revoked:
case osm_unknown:
case osm_badsig:
multiOcspResponses =
makeSignedOCSPResponse(arena, ocspStaplingMode, cert,
pwdata);
break;
case osm_corrupted:
multiOcspResponses = makeCorruptedOCSPResponse(arena);
break;
case osm_failure:
multiOcspResponses = makeTryLaterOCSPResponse(arena);
break;
case osm_ocsp:
errExit("stapling mode \"ocsp\" not implemented");
break;
break;
default:
break;
}
if (multiOcspResponses) {
certStatus[kea] = multiOcspResponses;
}
}
}
int
handle_connection(
PRFileDesc *tcp_sock,
@ -1216,8 +1260,7 @@ handle_connection(
char fileName[513];
char proto[128];
PRDescIdentity aboveLayer = PR_INVALID_IO_LAYER;
PLArenaPool *arena = NULL;
ocspStaplingModeType osm;
SSLKEAType kea;
pBuf = buf;
bufRem = sizeof buf;
@ -1244,57 +1287,11 @@ handle_connection(
ssl_sock = tcp_sock;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena)
errExit("cannot allocate arena");
osm = ocspStaplingMode;
if (osm == osm_random) {
/* 6 different responses */
int r = rand() % 6;
switch (r) {
case 0: osm = osm_good; break;
case 1: osm = osm_revoked; break;
case 2: osm = osm_unknown; break;
case 3: osm = osm_badsig; break;
case 4: osm = osm_corrupted; break;
case 5: osm = osm_failure; break;
default: PORT_Assert(0); break;
}
for (kea = kt_rsa; kea < kt_kea_size; kea++) {
if (certStatus[kea] != NULL) {
SSL_SetStapledOCSPResponses(ssl_sock, certStatus[kea], kea);
}
}
if (osm != osm_disabled) {
SECItemArray *multiOcspResponses = NULL;
switch (osm) {
case osm_good:
case osm_revoked:
case osm_unknown:
case osm_badsig:
multiOcspResponses =
makeSignedOCSPResponse(arena, osm, ssl_sock,
certForStatusWeakReference);
break;
case osm_corrupted:
multiOcspResponses = makeCorruptedOCSPResponse(arena);
break;
case osm_failure:
multiOcspResponses = makeTryLaterOCSPResponse(arena);
break;
case osm_ocsp:
errExit("stapling mode \"ocsp\" not implemented");
break;
break;
default:
break;
}
if (multiOcspResponses) {
SSL_SetStapledOCSPResponses(ssl_sock, multiOcspResponses,
PR_FALSE /* no ownership transfer */);
}
}
PORT_FreeArena(arena, PR_FALSE);
arena = NULL;
if (loggingLayer) {
/* find the layer where our new layer is to be pushed */
@ -1910,9 +1907,6 @@ server_main(
for (kea = kt_rsa; kea < kt_kea_size; kea++) {
if (cert[kea] != NULL) {
if (!certForStatusWeakReference)
certForStatusWeakReference = cert[kea];
secStatus = SSL_ConfigSecureServer(model_sock,
cert[kea], privKey[kea], kea);
if (secStatus != SECSuccess)
@ -2172,6 +2166,7 @@ main(int argc, char **argv)
PRUint32 i;
secuPWData pwdata = { PW_NONE, 0 };
char *expectedHostNameVal = NULL;
PLArenaPool *certStatusArena = NULL;
tmp = strrchr(argv[0], '/');
tmp = tmp ? tmp + 1 : argv[0];
@ -2569,6 +2564,10 @@ main(int argc, char **argv)
}
}
certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!certStatusArena)
errExit("cannot allocate certStatusArena");
if (nickName) {
cert[kt_rsa] = PK11_FindCertFromNickname(nickName, &pwdata);
if (cert[kt_rsa] == NULL) {
@ -2591,6 +2590,8 @@ main(int argc, char **argv)
fprintf(stderr, "selfserv: %s can%s bypass\n", nickName,
bypassOK ? "" : "not");
}
setupCertStatus(certStatusArena, ocspStaplingMode, cert[kt_rsa], kt_rsa,
&pwdata);
}
#ifdef NSS_ENABLE_ECC
if (ecNickName) {
@ -2615,7 +2616,9 @@ main(int argc, char **argv)
}
fprintf(stderr, "selfserv: %s can%s bypass\n", ecNickName,
bypassOK ? "" : "not");
}
}
setupCertStatus(certStatusArena, ocspStaplingMode, cert[kt_ecdh], kt_ecdh,
&pwdata);
}
#endif /* NSS_ENABLE_ECC */
@ -2697,6 +2700,9 @@ cleanup:
if (hasSidCache) {
SSL_ShutdownServerSessionIDCache();
}
if (certStatusArena) {
PORT_FreeArena(certStatusArena, PR_FALSE);
}
if (NSS_Shutdown() != SECSuccess) {
SECU_PrintError(progName, "NSS_Shutdown");
if (loggerThread) {
@ -2709,4 +2715,3 @@ cleanup:
printf("selfserv: normal termination\n");
return 0;
}

View File

@ -10,4 +10,3 @@
*/
#error "Do not include this header file."

View File

@ -1036,8 +1036,10 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava, CertStrictnessLevel strict)
} else {
/* must truncate the escaped and quoted value */
char bigTmpBuf[TMPBUF_LEN * 3 + 3];
PORT_Assert(valueLen < sizeof tmpBuf);
rv = escapeAndQuote(bigTmpBuf, sizeof bigTmpBuf,
(char *)avaValue->data, valueLen, &mode);
(char *)avaValue->data,
PR_MIN(avaValue->len, valueLen), &mode);
bigTmpBuf[valueLen--] = '\0'; /* hard stop here */
/* See if we're in the middle of a multi-byte UTF8 character */

View File

@ -3,7 +3,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
my $cvs_id = '@(#) $RCSfile$ $Revision$ $Date$';
use strict;
my %constants;
@ -11,7 +10,6 @@ my $count = 0;
my $o;
my @objects = ();
my @objsize;
my $cvsid;
$constants{CKO_DATA} = "static const CK_OBJECT_CLASS cko_data = CKO_DATA;\n";
$constants{CK_TRUE} = "static const CK_BBOOL ck_true = CK_TRUE;\n";
@ -24,21 +22,6 @@ while(<>) {
s/^((?:[^"#]+|"[^"]*")*)(\s*#.*$)/$1/;
next if (/^\s*$/);
if( /(^CVS_ID\s+)(.*)/ ) {
$cvsid = $2 . "\"; $cvs_id\"";
my $scratch = $cvsid;
$size = 1 + $scratch =~ s/[^"\n]//g;
@{$objects[0][0]} = ( "CKA_CLASS", "&cko_data", "sizeof(CK_OBJECT_CLASS)" );
@{$objects[0][1]} = ( "CKA_TOKEN", "&ck_true", "sizeof(CK_BBOOL)" );
@{$objects[0][2]} = ( "CKA_PRIVATE", "&ck_false", "sizeof(CK_BBOOL)" );
@{$objects[0][3]} = ( "CKA_MODIFIABLE", "&ck_false", "sizeof(CK_BBOOL)" );
@{$objects[0][4]} = ( "CKA_LABEL", "\"CVS ID\"", "7" );
@{$objects[0][5]} = ( "CKA_APPLICATION", "\"NSS\"", "4" );
@{$objects[0][6]} = ( "CKA_VALUE", $cvsid, "$size" );
$objsize[0] = 7;
next;
}
# This was taken from the perl faq #4.
my $text = $_;
push(@fields, $+) while $text =~ m{
@ -110,7 +93,7 @@ doprint();
sub dudump {
my $i;
for( $i = 0; $i <= $count; $i++ ) {
for( $i = 1; $i <= $count; $i++ ) {
print "\n";
$o = $objects[$i];
my @ob = @{$o};
@ -133,9 +116,6 @@ print <<EOD
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef DEBUG
static const char CVS_ID[] = $cvsid;
#endif /* DEBUG */
#ifndef BUILTINS_H
#include "builtins.h"
@ -148,11 +128,7 @@ foreach $b (sort values(%constants)) {
print $b;
}
for( $i = 0; $i <= $count; $i++ ) {
if( 0 == $i ) {
print "#ifdef DEBUG\n";
}
for( $i = 1; $i <= $count; $i++ ) {
print "static const CK_ATTRIBUTE_TYPE nss_builtins_types_$i [] = {\n";
$o = $objects[$i];
my @ob = @{$o};
@ -166,17 +142,9 @@ for( $i = 0; $i <= $count; $i++ ) {
}
}
print "\n};\n";
if( 0 == $i ) {
print "#endif /* DEBUG */\n";
}
}
for( $i = 0; $i <= $count; $i++ ) {
if( 0 == $i ) {
print "#ifdef DEBUG\n";
}
for( $i = 1; $i <= $count; $i++ ) {
print "static const NSSItem nss_builtins_items_$i [] = {\n";
$o = $objects[$i];
my @ob = @{$o};
@ -192,40 +160,22 @@ for( $i = 0; $i <= $count; $i++ ) {
}
}
print "};\n";
if( 0 == $i ) {
print "#endif /* DEBUG */\n";
}
}
print "\nbuiltinsInternalObject\n";
print "nss_builtins_data[] = {\n";
for( $i = 0; $i <= $count; $i++ ) {
if( 0 == $i ) {
print "#ifdef DEBUG\n";
}
for( $i = 1; $i <= $count; $i++ ) {
print " { $objsize[$i], nss_builtins_types_$i, nss_builtins_items_$i, {NULL} }";
if( $i == $count ) {
print "\n";
} else {
print ",\n";
}
if( 0 == $i ) {
print "#endif /* DEBUG */\n";
}
}
print "};\n";
print "const PRUint32\n";
print "#ifdef DEBUG\n";
print " nss_builtins_nObjects = $count+1;\n";
print "#else\n";
print " nss_builtins_nObjects = $count;\n";
print "#endif /* DEBUG */\n";
print "nss_builtins_nObjects = $count;\n";
}

View File

@ -2,7 +2,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
CVS_ID "@(#) $RCSfile$ $Revision$ $Date$"
#
# certdata.txt

View File

@ -6,8 +6,6 @@
# This file is in part derived from a file "pkcs11f.h" made available
# by RSA Security at ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/pkcs11f.h
CVS_ID "@(#) $RCSfile$ $Revision$ $Date$"
# Fields
# FUNCTION introduces a Cryptoki function
# CK_type specifies and introduces an argument

View File

@ -74,10 +74,6 @@ print <<EOD
#ifndef NSSCKG_H
#define NSSCKG_H
#ifdef DEBUG
static const char NSSCKG_CVS_ID[] = "$g{CVS_ID} ; $cvs_id";
#endif /* DEBUG */
/*
* nssckg.h
*
@ -118,10 +114,6 @@ print <<EOD
#ifndef NSSCKFT_H
#define NSSCKFT_H
#ifdef DEBUG
static const char NSSCKFT_CVS_ID[] = "$g{CVS_ID} ; $cvs_id";
#endif /* DEBUG */
/*
* nssckft.h
*
@ -162,10 +154,6 @@ print <<EOD
#ifndef NSSCKEPV_H
#define NSSCKEPV_H
#ifdef DEBUG
static const char NSSCKEPV_CVS_ID[] = "$g{CVS_ID} ; $cvs_id";
#endif /* DEBUG */
/*
* nssckepv.h
*
@ -206,10 +194,6 @@ select API;
print $copyright;
print <<EOD
#ifdef DEBUG
static const char NSSCKAPI_CVS_ID[] = "$g{CVS_ID} ; $cvs_id";
#endif /* DEBUG */
/*
* nssck.api
*

View File

@ -1488,6 +1488,32 @@ PKIX_PL_Cert_VerifySignature(
PKIX_PL_PublicKey *pubKey,
void *plContext);
/* A set of flags to indicate how explicitly configured trust anchors should be
* handled by PKIX_PL_Cert_IsCertTrusted
*/
typedef enum PKIX_PL_TrustAnchorModeEnum {
/* Indicates trust anchors should be ignored; only the underlying
* platform's trust settings should be used.
*/
PKIX_PL_TrustAnchorMode_Ignore,
/* Indicates that explicitly configured trust anchors may be considered
* trustworthy, if present.
* Note: If the underlying platform supports marking a certificate as
* explicitly untrustworthy, explicitly configured trust anchors
* MAY be ignored/rejected.
*/
PKIX_PL_TrustAnchorMode_Additive,
/* Indicates that ONLY trust anchors should be considered as
* trustworthy.
* Note: If the underlying platform supports marking a certificate as
* explicitly untrustworthy, explicitly configured trust anchors
* MAY be ignored/rejected.
*/
PKIX_PL_TrustAnchorMode_Exclusive,
} PKIX_PL_TrustAnchorMode;
/*
* FUNCTION: PKIX_PL_Cert_IsCertTrusted
* DESCRIPTION:
@ -1509,8 +1535,9 @@ PKIX_PL_Cert_VerifySignature(
* "cert"
* Address of Cert whose trustworthiness is to be determined. Must be
* non-NULL.
* "trustOnlyUserAnchors"
* States that we can only trust explicitly defined user trust anchors.
* "trustAnchorMode"
* A PKIX_PL_TrustAnchorMode that indicates how explicitly defined user
* trust anchors should be handled.
* "pTrusted"
* Address where the Boolean value will be stored. Must be non-NULL.
* "plContext"
@ -1525,7 +1552,7 @@ PKIX_PL_Cert_VerifySignature(
PKIX_Error *
PKIX_PL_Cert_IsCertTrusted(
PKIX_PL_Cert *cert,
PKIX_Boolean trustOnlyUserAnchors,
PKIX_PL_TrustAnchorMode trustAnchorMode,
PKIX_Boolean *pTrusted,
void *plContext);

View File

@ -836,7 +836,8 @@ pkix_Build_VerifyCertificate(
PKIX_PL_PublicKey *candidatePubKey = NULL;
PKIX_CertChainChecker *userChecker = NULL;
PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
PKIX_Boolean trustOnlyUserAnchors = PKIX_FALSE;
PKIX_PL_TrustAnchorMode trustAnchorMode =
PKIX_PL_TrustAnchorMode_Ignore;
void *nbioContext = NULL;
PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate");
@ -850,12 +851,17 @@ pkix_Build_VerifyCertificate(
candidateCert = state->candidateCert;
if (state->buildConstants.numAnchors) {
trustOnlyUserAnchors = state->buildConstants.trustOnlyUserAnchors;
if (state->buildConstants.trustOnlyUserAnchors) {
trustAnchorMode = PKIX_PL_TrustAnchorMode_Exclusive;
} else {
trustAnchorMode = PKIX_PL_TrustAnchorMode_Additive;
}
} else {
trustAnchorMode = PKIX_PL_TrustAnchorMode_Ignore;
}
PKIX_CHECK(
PKIX_PL_Cert_IsCertTrusted(candidateCert,
trustOnlyUserAnchors,
PKIX_PL_Cert_IsCertTrusted(candidateCert, trustAnchorMode,
&trusted, plContext),
PKIX_CERTISCERTTRUSTEDFAILED);
@ -3041,19 +3047,27 @@ pkix_Build_CheckInCache(
(matchingAnchor, &trustedCert, plContext),
PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
if (state->buildConstants.anchors &&
state->buildConstants.anchors->length) {
if (anchors && state->buildConstants.numAnchors) {
/* Check if it is one of the trust anchors */
PKIX_CHECK(
pkix_List_Contains(state->buildConstants.anchors,
pkix_List_Contains(anchors,
(PKIX_PL_Object *)matchingAnchor,
&trusted,
plContext),
PKIX_LISTCONTAINSFAILED);
} else {
PKIX_CHECK(PKIX_PL_Cert_IsCertTrusted
(trustedCert, PKIX_FALSE, &trusted, plContext),
PKIX_CERTISCERTTRUSTEDFAILED);
}
if ((!trusted && !state->buildConstants.trustOnlyUserAnchors) ||
!state->buildConstants.numAnchors) {
/* If it is not one of the trust anchors and the trust anchors
* are supplemental, or if there are no trust anchors, then check
* if the cert is trusted directly.
*/
PKIX_CHECK(
PKIX_PL_Cert_IsCertTrusted(trustedCert,
PKIX_PL_TrustAnchorMode_Ignore,
&trusted, plContext),
PKIX_CERTISCERTTRUSTEDFAILED);
}
if (!trusted) {

View File

@ -3294,7 +3294,7 @@ pkix_pl_Cert_GetTrusted(void *plContext,
PKIX_Error *
PKIX_PL_Cert_IsCertTrusted(
PKIX_PL_Cert *cert,
PKIX_Boolean trustOnlyUserAnchors,
PKIX_PL_TrustAnchorMode trustAnchorMode,
PKIX_Boolean *pTrusted,
void *plContext)
{
@ -3315,8 +3315,10 @@ PKIX_PL_Cert_IsCertTrusted(
PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
}
if (trustOnlyUserAnchors || cert->isUserTrustAnchor) {
/* discard our |trusted| value since we are using the anchors */
if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive ||
(trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive &&
cert->isUserTrustAnchor)) {
/* Use the trust anchor's |trusted| value */
*pTrusted = cert->isUserTrustAnchor;
goto cleanup;
}

View File

@ -417,14 +417,13 @@ SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
/* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses
* in the fd's data, which may be sent as part of a server side cert_status
* handshake message.
* If takeOwnership is false, the function will duplicate the responses.
* If takeOwnership is true, the ownership of responses is transfered into the
* SSL library, and the caller must stop using it.
* handshake message. Parameter |responses| is for the server certificate of
* the key exchange type |kea|.
* The function will duplicate the responses array.
*/
SSL_IMPORT SECStatus
SSL_SetStapledOCSPResponses(PRFileDesc *fd, SECItemArray *responses,
PRBool takeOwnership);
SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
SSLKEAType kea);
/*
** Authenticate certificate hook. Called when a certificate comes in

View File

@ -8444,23 +8444,36 @@ ssl3_SendCertificate(sslSocket *ss)
static SECStatus
ssl3_SendCertificateStatus(sslSocket *ss)
{
SECStatus rv;
int len = 0;
SECStatus rv;
int len = 0;
SECItemArray *statusToSend = NULL;
SSL3KEAType certIndex;
SSL_TRC(3, ("%d: SSL3[%d]: send certificate status handshake",
SSL_GETPID(), ss->fd));
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert( ss->sec.isServer);
if (!ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn))
return SECSuccess;
if (!ss->certStatusArray || !ss->certStatusArray->len)
/* Use certStatus based on the cert being used. */
if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
(ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
certIndex = kt_rsa;
} else {
certIndex = ss->ssl3.hs.kea_def->exchKeyType;
}
if (ss->certStatusArray[certIndex] && ss->certStatusArray[certIndex]->len) {
statusToSend = ss->certStatusArray[certIndex];
}
if (!statusToSend)
return SECSuccess;
/* Use the array's first item only (single stapling) */
len = 1 + ss->certStatusArray->items[0].len + 3;
len = 1 + statusToSend->items[0].len + 3;
rv = ssl3_AppendHandshakeHeader(ss, certificate_status, len);
if (rv != SECSuccess) {
@ -8471,8 +8484,8 @@ ssl3_SendCertificateStatus(sslSocket *ss)
return rv; /* err set by AppendHandshake. */
rv = ssl3_AppendHandshakeVariable(ss,
ss->certStatusArray->items[0].data,
ss->certStatusArray->items[0].len,
statusToSend->items[0].data,
statusToSend->items[0].len,
3);
if (rv != SECSuccess)
return rv; /* err set by AppendHandshake. */

View File

@ -681,8 +681,21 @@ ssl3_ServerSendStatusRequestXtn(
{
PRInt32 extension_length;
SECStatus rv;
int i;
PRBool haveStatus = PR_FALSE;
if (!ss->certStatusArray || !ss->certStatusArray->len)
for (i = kt_null; i < kt_kea_size; i++) {
/* TODO: This is a temporary workaround.
* The correct code needs to see if we have an OCSP response for
* the server certificate being used, rather than if we have any
* OCSP response. See also ssl3_SendCertificateStatus.
*/
if (ss->certStatusArray[i] && ss->certStatusArray[i]->len) {
haveStatus = PR_TRUE;
break;
}
}
if (!haveStatus)
return 0;
extension_length = 2 + 2;

View File

@ -1175,7 +1175,8 @@ const unsigned char * preferredCipher;
/* Configuration state for server sockets */
/* server cert and key for each KEA type */
sslServerCerts serverCerts[kt_kea_size];
SECItemArray * certStatusArray;
/* each cert needs its own status */
SECItemArray * certStatusArray[kt_kea_size];
ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED];
ssl3KeyPair * ephemeralECDHKeyPair; /* for ECDHE-* handshake */

View File

@ -321,13 +321,13 @@ ssl_DupSocket(sslSocket *os)
if (oc->serverKeyPair && !sc->serverKeyPair)
goto loser;
sc->serverKeyBits = oc->serverKeyBits;
ss->certStatusArray[i] = !os->certStatusArray[i] ? NULL :
SECITEM_DupArray(NULL, os->certStatusArray[i]);
}
ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL :
ssl3_GetKeyPairRef(os->stepDownKeyPair);
ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL :
ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair);
ss->certStatusArray = !os->certStatusArray ? NULL :
SECITEM_DupArray(NULL, os->certStatusArray);
/*
* XXX the preceding CERT_ and SECKEY_ functions can fail and return NULL.
* XXX We should detect this, and not just march on with NULL pointers.
@ -430,6 +430,10 @@ ssl_DestroySocketContents(sslSocket *ss)
CERT_DestroyCertificateList(sc->serverCertChain);
if (sc->serverKeyPair != NULL)
ssl3_FreeKeyPair(sc->serverKeyPair);
if (ss->certStatusArray[i] != NULL) {
SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE);
ss->certStatusArray[i] = NULL;
}
}
if (ss->stepDownKeyPair) {
ssl3_FreeKeyPair(ss->stepDownKeyPair);
@ -439,10 +443,6 @@ ssl_DestroySocketContents(sslSocket *ss)
ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
ss->ephemeralECDHKeyPair = NULL;
}
if (ss->certStatusArray) {
SECITEM_FreeArray(ss->certStatusArray, PR_TRUE);
ss->certStatusArray = NULL;
}
SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE);
PORT_Assert(!ss->xtnData.sniNameArr);
if (ss->xtnData.sniNameArr) {
@ -1668,6 +1668,15 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
sc->serverCertChain = CERT_DupCertList(mc->serverCertChain);
if (!sc->serverCertChain)
goto loser;
if (sm->certStatusArray[i]) {
if (ss->certStatusArray[i]) {
SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE);
ss->certStatusArray[i] = NULL;
}
ss->certStatusArray[i] = SECITEM_DupArray(NULL, sm->certStatusArray[i]);
if (!ss->certStatusArray[i])
goto loser;
}
}
if (mc->serverKeyPair) {
if (sc->serverKeyPair) {
@ -1690,13 +1699,6 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
ss->ephemeralECDHKeyPair =
ssl3_GetKeyPairRef(sm->ephemeralECDHKeyPair);
}
if (sm->certStatusArray) {
if (ss->certStatusArray) {
SECITEM_FreeArray(ss->certStatusArray, PR_TRUE);
ss->certStatusArray = NULL;
}
ss->certStatusArray = SECITEM_DupArray(NULL, sm->certStatusArray);
}
/* copy trust anchor names */
if (sm->ssl3.ca_list) {
if (ss->ssl3.ca_list) {
@ -2229,8 +2231,8 @@ ssl_GetSockName(PRFileDesc *fd, PRNetAddr *name)
}
SECStatus
SSL_SetStapledOCSPResponses(PRFileDesc *fd, SECItemArray *responses,
PRBool takeOwnership)
SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
SSLKEAType kea)
{
sslSocket *ss;
@ -2241,19 +2243,20 @@ SSL_SetStapledOCSPResponses(PRFileDesc *fd, SECItemArray *responses,
return SECFailure;
}
if (ss->certStatusArray) {
SECITEM_FreeArray(ss->certStatusArray, PR_TRUE);
ss->certStatusArray = NULL;
if ( kea <= 0 || kea >= kt_kea_size) {
SSL_DBG(("%d: SSL[%d]: invalid key in SSL_SetStapledOCSPResponses",
SSL_GETPID(), fd));
return SECFailure;
}
if (ss->certStatusArray[kea]) {
SECITEM_FreeArray(ss->certStatusArray[kea], PR_TRUE);
ss->certStatusArray[kea] = NULL;
}
if (responses) {
if (takeOwnership) {
ss->certStatusArray = responses;
}
else {
ss->certStatusArray = SECITEM_DupArray(NULL, responses);
}
ss->certStatusArray[kea] = SECITEM_DupArray(NULL, responses);
}
return (ss->certStatusArray || !responses) ? SECSuccess : SECFailure;
return (ss->certStatusArray[kea] || !responses) ? SECSuccess : SECFailure;
}
SECStatus
@ -2953,10 +2956,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
sc->serverCertChain = NULL;
sc->serverKeyPair = NULL;
sc->serverKeyBits = 0;
ss->certStatusArray[i] = NULL;
}
ss->stepDownKeyPair = NULL;
ss->dbHandle = CERT_GetDefaultCertDB();
ss->certStatusArray = NULL;
/* Provide default implementation of hooks */
ss->authCertificate = SSL_AuthCertificate;

View File

@ -266,6 +266,7 @@ NSSUTIL_QuoteSize;
SECITEM_AllocArray;
SECITEM_DupArray;
SECITEM_FreeArray;
SECITEM_ReallocItemV2;
SECITEM_ZfreeArray;
;+ local:
;+ *;

View File

@ -115,6 +115,63 @@ SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item, unsigned int oldlen,
return SECSuccess;
}
SECStatus
SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item, unsigned int newlen)
{
unsigned char *newdata = NULL;
PORT_Assert(item);
if (!item) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (item->len == newlen) {
return SECSuccess;
}
if (!newlen) {
SECITEM_FreeItem(item, PR_FALSE);
return SECSuccess;
}
if (!item->len) {
/* allocate fresh block of memory */
PORT_Assert(!item->data);
if (arena) {
newdata = PORT_ArenaAlloc(arena, newlen);
} else {
newdata = PORT_Alloc(newlen);
}
} else {
/* reallocate or adjust existing block of memory */
if (arena) {
if (item->len > newlen) {
/* There's no need to realloc a shorter block from the arena,
* because it would result in using even more memory!
* Therefore we'll continue to use the old block and
* set the item to the shorter size.
*/
item->len = newlen;
return SECSuccess;
} else {
newdata = PORT_ArenaGrow(arena, item->data, item->len, newlen);
}
} else {
newdata = PORT_Realloc(item->data, newlen);
}
}
if (!newdata) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
item->len = newlen;
item->data = newdata;
return SECSuccess;
}
SECComparison
SECITEM_CompareItem(const SECItem *a, const SECItem *b)
{

View File

@ -36,6 +36,11 @@ extern SECItem *SECITEM_AllocItem(PLArenaPool *arena, SECItem *item,
unsigned int len);
/*
** This is a legacy function containing bugs. It doesn't update item->len,
** and it has other issues as described in bug 298649 and bug 298938.
** However, the function is kept unchanged for consumers that might depend
** on the broken behaviour. New code should call SECITEM_ReallocItemV2.
**
** Reallocate the data for the specified "item". If "arena" is not NULL,
** then reallocate from there, otherwise reallocate from the heap.
** In the case where oldlen is 0, the data is allocated (not reallocated).
@ -43,9 +48,22 @@ extern SECItem *SECITEM_AllocItem(PLArenaPool *arena, SECItem *item,
** SECFailure is returned if it is not. If the allocation succeeds,
** SECSuccess is returned.
*/
extern SECStatus SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item,
extern SECStatus SECITEM_ReallocItem( /* deprecated function */
PLArenaPool *arena, SECItem *item,
unsigned int oldlen, unsigned int newlen);
/*
** Reallocate the data for the specified "item". If "arena" is not NULL,
** then reallocate from there, otherwise reallocate from the heap.
** If the item already has at least the request new size,
** then the item is kept unchanged and SECSuccess is returned.
** In any case, "item" is expected to be a valid SECItem pointer;
** SECFailure is returned if it is not, and the item will remain unchanged.
** If the allocation succeeds, the item is updated and SECSuccess is returned.
*/
extern SECStatus SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item,
unsigned int newlen);
/*
** Compare two items returning the difference between them.
*/