Merge pull request #929 from dgarske/fix_asn_perm_dirname

Fix for parsing permitted name constraint for subject directory name
This commit is contained in:
toddouska
2017-05-22 09:55:49 -07:00
committed by GitHub
2 changed files with 114 additions and 84 deletions

View File

@ -4818,34 +4818,44 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
Base_entry* base = signer->excludedNames;
while (base != NULL) {
if (base->type == ASN_DNS_TYPE) {
DNS_entry* name = cert->altNames;
while (name != NULL) {
if (MatchBaseName(ASN_DNS_TYPE,
switch (base->type) {
case ASN_DNS_TYPE:
{
DNS_entry* name = cert->altNames;
while (name != NULL) {
if (MatchBaseName(ASN_DNS_TYPE,
name->name, (int)XSTRLEN(name->name),
base->name, base->nameSz))
return 0;
name = name->next;
base->name, base->nameSz)) {
return 0;
}
name = name->next;
}
break;
}
}
else if (base->type == ASN_RFC822_TYPE) {
DNS_entry* name = cert->altEmailNames;
while (name != NULL) {
if (MatchBaseName(ASN_RFC822_TYPE,
case ASN_RFC822_TYPE:
{
DNS_entry* name = cert->altEmailNames;
while (name != NULL) {
if (MatchBaseName(ASN_RFC822_TYPE,
name->name, (int)XSTRLEN(name->name),
base->name, base->nameSz))
base->name, base->nameSz)) {
return 0;
}
name = name->next;
}
break;
}
case ASN_DIR_TYPE:
{
/* allow permitted dirName smaller than actual subject */
if (cert->subjectRawLen >= base->nameSz &&
XMEMCMP(cert->subjectRaw, base->name,
base->nameSz) == 0) {
return 0;
name = name->next;
}
break;
}
}
else if (base->type == ASN_DIR_TYPE) {
if (cert->subjectRawLen == base->nameSz &&
XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
return 0;
}
}
}; /* switch */
base = base->next;
}
}
@ -4861,47 +4871,56 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
Base_entry* base = signer->permittedNames;
while (base != NULL) {
if (base->type == ASN_DNS_TYPE) {
DNS_entry* name = cert->altNames;
switch (base->type) {
case ASN_DNS_TYPE:
{
DNS_entry* name = cert->altNames;
if (name != NULL)
needDns = 1;
if (name != NULL)
needDns = 1;
while (name != NULL) {
matchDns = MatchBaseName(ASN_DNS_TYPE,
while (name != NULL) {
matchDns = MatchBaseName(ASN_DNS_TYPE,
name->name, (int)XSTRLEN(name->name),
base->name, base->nameSz);
name = name->next;
name = name->next;
}
break;
}
}
else if (base->type == ASN_RFC822_TYPE) {
DNS_entry* name = cert->altEmailNames;
case ASN_RFC822_TYPE:
{
DNS_entry* name = cert->altEmailNames;
if (name != NULL)
needEmail = 1;
if (name != NULL)
needEmail = 1;
while (name != NULL) {
matchEmail = MatchBaseName(ASN_DNS_TYPE,
while (name != NULL) {
matchEmail = MatchBaseName(ASN_DNS_TYPE,
name->name, (int)XSTRLEN(name->name),
base->name, base->nameSz);
name = name->next;
name = name->next;
}
break;
}
}
else if (base->type == ASN_DIR_TYPE) {
needDir = 1;
if (cert->subjectRaw != NULL &&
cert->subjectRawLen == base->nameSz &&
XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
matchDir = 1;
case ASN_DIR_TYPE:
{
/* allow permitted dirName smaller than actual subject */
needDir = 1;
if (cert->subjectRaw != NULL &&
cert->subjectRawLen >= base->nameSz &&
XMEMCMP(cert->subjectRaw, base->name,
base->nameSz) == 0) {
matchDir = 1;
}
break;
}
}
} /* switch */
base = base->next;
}
if ((needDns && !matchDns) || (needEmail && !matchEmail) ||
(needDir && !matchDir)) {
if ((needDns && !matchDns) ||
(needEmail && !matchEmail) ||
(needDir && !matchDir)) {
return 0;
}
}
@ -5410,6 +5429,7 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
#ifndef IGNORE_NAME_CONSTRAINTS
#define ASN_TYPE_MASK 0xF
static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
{
word32 idx = 0;
@ -5419,27 +5439,37 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
while (idx < (word32)sz) {
int seqLength, strLength;
word32 nameIdx;
byte b;
byte b, bType;
if (GetSequence(input, &idx, &seqLength, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
nameIdx = idx;
b = input[nameIdx++];
if (GetLength(input, &nameIdx, &strLength, sz) <= 0) {
WOLFSSL_MSG("\tinvalid length");
return ASN_PARSE_E;
}
if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE) ||
b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE) ||
b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) {
/* Get type, LSB 4-bits */
bType = (b & ASN_TYPE_MASK);
Base_entry* entry = (Base_entry*)XMALLOC(sizeof(Base_entry),
heap, DYNAMIC_TYPE_ALTNAME);
if (bType == ASN_DNS_TYPE || bType == ASN_RFC822_TYPE ||
bType == ASN_DIR_TYPE) {
Base_entry* entry;
/* if constructed has leading sequence */
if (b & ASN_CONSTRUCTED) {
if (GetSequence(input, &nameIdx, &strLength, sz) < 0) {
WOLFSSL_MSG("\tfail: constructed be a SEQUENCE");
return ASN_PARSE_E;
}
}
entry = (Base_entry*)XMALLOC(sizeof(Base_entry), heap,
DYNAMIC_TYPE_ALTNAME);
if (entry == NULL) {
WOLFSSL_MSG("allocate error");
return MEMORY_E;
@ -5454,7 +5484,7 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
XMEMCPY(entry->name, &input[nameIdx], strLength);
entry->nameSz = strLength;
entry->type = b & 0x0F;
entry->type = bType;
entry->next = *head;
*head = entry;
@ -5614,8 +5644,8 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz)
return ASN_PARSE_E;
}
/* Validate total length (2 is the CERT_POLICY_OID+SEQ) */
if ((total_length + 2) != sz) {
/* Validate total length */
if (total_length > (sz - (int)idx)) {
WOLFSSL_MSG("\tCertPolicy length mismatch");
return ASN_PARSE_E;
}
@ -5640,7 +5670,7 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz)
return ASN_PARSE_E;
}
#if defined(WOLFSSL_SEP)
#if defined(WOLFSSL_SEP)
cert->deviceType = (byte*)XMALLOC(length, cert->heap,
DYNAMIC_TYPE_X509_EXT);
if (cert->deviceType == NULL) {
@ -5650,14 +5680,14 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz)
cert->deviceTypeSz = length;
XMEMCPY(cert->deviceType, input + idx, length);
break;
#elif defined(WOLFSSL_CERT_EXT)
#elif defined(WOLFSSL_CERT_EXT)
/* decode cert policy */
if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], MAX_CERTPOL_SZ,
input + idx, length) != 0) {
WOLFSSL_MSG("\tCouldn't decode CertPolicy");
return ASN_PARSE_E;
}
#ifndef WOLFSSL_DUP_CERTPOL
#ifndef WOLFSSL_DUP_CERTPOL
/* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST
* NOT appear more than once in a certificate policies
* extension". This is a sanity check for duplicates.
@ -5672,12 +5702,12 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz)
return CERTPOLICIES_E;
}
}
#endif /* !defined(WOLFSSL_DUP_CERTPOL) */
#endif /* !WOLFSSL_DUP_CERTPOL */
cert->extCertPoliciesNb++;
#else
#else
WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0);
return 0;
#endif
#endif
}
idx += policy_length;
} while((int)idx < total_length
@ -5987,7 +6017,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
/* save extensions */
cert->extensions = &cert->source[cert->srcIdx];
cert->extensionsSz = cert->sigIndex - cert->srcIdx;
cert->extensionsSz = cert->sigIndex - cert->srcIdx;
cert->extensionsIdx = cert->srcIdx; /* for potential later use */
if ((ret = DecodeCertExtensions(cert)) < 0) {
@ -6141,10 +6171,10 @@ Signer* MakeSigner(void* heap)
signer->publicKey = NULL;
signer->nameLen = 0;
signer->name = NULL;
#ifndef IGNORE_NAME_CONSTRAINTS
signer->permittedNames = NULL;
signer->excludedNames = NULL;
#endif /* IGNORE_NAME_CONSTRAINTS */
#ifndef IGNORE_NAME_CONSTRAINTS
signer->permittedNames = NULL;
signer->excludedNames = NULL;
#endif /* IGNORE_NAME_CONSTRAINTS */
signer->pathLengthSet = 0;
signer->pathLength = 0;
signer->next = NULL;
@ -6160,12 +6190,12 @@ void FreeSigner(Signer* signer, void* heap)
{
XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
#ifndef IGNORE_NAME_CONSTRAINTS
if (signer->permittedNames)
FreeNameSubtrees(signer->permittedNames, heap);
if (signer->excludedNames)
FreeNameSubtrees(signer->excludedNames, heap);
#endif
#ifndef IGNORE_NAME_CONSTRAINTS
if (signer->permittedNames)
FreeNameSubtrees(signer->permittedNames, heap);
if (signer->excludedNames)
FreeNameSubtrees(signer->excludedNames, heap);
#endif
XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
(void)heap;
@ -6203,12 +6233,12 @@ void FreeTrustedPeer(TrustedPeerCert* tp, void* heap)
if (tp->sig) {
XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE);
}
#ifndef IGNORE_NAME_CONSTRAINTS
if (tp->permittedNames)
FreeNameSubtrees(tp->permittedNames, heap);
if (tp->excludedNames)
FreeNameSubtrees(tp->excludedNames, heap);
#endif
#ifndef IGNORE_NAME_CONSTRAINTS
if (tp->permittedNames)
FreeNameSubtrees(tp->permittedNames, heap);
if (tp->excludedNames)
FreeNameSubtrees(tp->excludedNames, heap);
#endif
XFREE(tp, heap, DYNAMIC_TYPE_CERT);
(void)heap;

View File

@ -87,7 +87,7 @@ enum ASN_Tags {
ASN_LONG_LENGTH = 0x80
};
enum ASN_Flags{
enum ASN_Flags {
ASN_CONSTRUCTED = 0x20,
ASN_CONTEXT_SPECIFIC = 0x80
};