check basic contsraint CA flag before adding as signer even if explicit add

This commit is contained in:
toddouska 2011-11-02 14:57:14 -07:00
parent 8ddd2185c2
commit 11d15f32b9
5 changed files with 90 additions and 5 deletions

View File

@ -1017,6 +1017,7 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
cert->extensions = 0;
cert->extensionsSz = 0;
cert->extensionsIdx = 0;
cert->isCA = 0;
#ifdef CYASSL_CERT_GEN
cert->subjectSN = 0;
cert->subjectSNLen = 0;
@ -1970,6 +1971,78 @@ int ParseCert(DecodedCert* cert, int type, int verify,
}
/* If extension CA basic constraint is turned on, flag it, not error if not */
static void IsCa(DecodedCert* cert)
{
if (cert->extensions) {
byte b;
int length;
word32 maxExtensionsIdx;
cert->srcIdx = cert->extensionsIdx;
b = cert->source[cert->srcIdx++];
if (b != ASN_EXTENSIONS)
return;
if (GetLength(cert->source, &cert->srcIdx, &length,
cert->maxIdx) < 0)
return;
if (GetSequence(cert->source, &cert->srcIdx, &length,
cert->maxIdx) < 0)
return;
maxExtensionsIdx = cert->srcIdx + length;
while (cert->srcIdx < maxExtensionsIdx) {
word32 oid;
word32 startIdx = cert->srcIdx;
word32 tmpIdx;
if (GetSequence(cert->source, &cert->srcIdx, &length,
cert->maxIdx) < 0)
return;
tmpIdx = cert->srcIdx;
cert->srcIdx = startIdx;
if (GetAlgoId(cert->source, &cert->srcIdx, &oid,
cert->maxIdx) < 0)
return;
if (oid == BASIC_CA_OID) {
b = cert->source[cert->srcIdx++];
if (b != ASN_OCTET_STRING)
return;
if (GetLength(cert->source, &cert->srcIdx, &length,
cert->maxIdx) < 0)
return;
if (GetSequence(cert->source, &cert->srcIdx, &length,
cert->maxIdx) < 0)
return;
b = cert->source[cert->srcIdx++];
if (b != ASN_BOOLEAN)
return;
if (GetLength(cert->source, &cert->srcIdx, &length,
cert->maxIdx) < 0)
return;
b = cert->source[cert->srcIdx++];
if (b)
cert->isCA = 1;
return; /* we're done checking */
}
cert->srcIdx = tmpIdx + length;
}
}
}
/* from SSL proper, for locking can't do find here anymore */
CYASSL_LOCAL Signer* GetCA(Signer* signers, byte* hash);
@ -1995,6 +2068,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify,
cert->extensionsSz = cert->sigIndex - cert->srcIdx;
cert->extensionsIdx = cert->srcIdx; /* for potential later use */
}
IsCa(cert); /* turn on ca flag if there */
/* advance past extensions */
cert->srcIdx = cert->sigIndex;
}

View File

@ -50,6 +50,7 @@ enum {
/* ASN Tags */
enum ASN_Tags {
ASN_BOOLEAN = 0x01,
ASN_INTEGER = 0x02,
ASN_BIT_STRING = 0x03,
ASN_OCTET_STRING = 0x04,
@ -167,6 +168,7 @@ enum KDF_Sum {
enum Extensions_Sum {
BASIC_CA_OID = 133,
ALT_NAMES_OID = 131
};
@ -207,6 +209,7 @@ struct DecodedCert {
byte* extensions; /* not owned, points into raw cert */
int extensionsSz; /* length of cert extensions */
word32 extensionsIdx; /* if want to go back and parse later */
byte isCA; /* CA basic constraint true */
#ifdef CYASSL_CERT_GEN
/* easy access to subject info for other sign */
char* subjectSN;

View File

@ -617,7 +617,7 @@ int ProcessOldClientHello(CYASSL* ssl, const byte* input, word32* inOutIdx,
CYASSL_LOCAL
int AddCA(CYASSL_CTX* ctx, buffer der);
CYASSL_LOCAL
int IsCA(CYASSL_CTX* ctx, byte* hash);
int AlreadySigner(CYASSL_CTX* ctx, byte* hash);
/* All cipher suite related info */
typedef struct CipherSpecs {

View File

@ -1511,7 +1511,11 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx)
InitDecodedCert(&dCert, myCert.buffer, myCert.length, ssl->heap);
ret = ParseCertRelative(&dCert, CERT_TYPE, !ssl->options.verifyNone,
ssl->ctx->caList);
if (ret == 0 && !IsCA(ssl->ctx, dCert.subjectHash)) {
if (ret == 0 && dCert.isCA == 0) {
CYASSL_MSG("Chain cert is not a CA, not adding as one");
(void)ret;
}
else if (ret == 0 && !AlreadySigner(ssl->ctx, dCert.subjectHash)) {
buffer add;
add.length = myCert.length;
add.buffer = (byte*)XMALLOC(myCert.length, ssl->heap,

View File

@ -367,8 +367,8 @@ int CyaSSL_pending(CYASSL* ssl)
static CyaSSL_Mutex ca_mutex; /* CA signers mutex */
/* does CA already exist on list */
int IsCA(CYASSL_CTX* ctx, byte* hash)
/* does CA already exist on signer list */
int AlreadySigner(CYASSL_CTX* ctx, byte* hash)
{
Signer* signers;
int ret = 0;
@ -421,7 +421,11 @@ int AddCA(CYASSL_CTX* ctx, buffer der)
ret = ParseCert(&cert, CA_TYPE, ctx->verifyPeer, 0);
CYASSL_MSG(" Parsed new CA");
if (ret == 0 && IsCA(ctx, cert.subjectHash)) {
if (ret == 0 && cert.isCA == 0) {
CYASSL_MSG(" Can't add as CA if not actually one");
ret = -1;
}
else if (ret == 0 && AlreadySigner(ctx, cert.subjectHash)) {
CYASSL_MSG(" Already have this CA, not adding again");
(void)ret;
}