diff options
Diffstat (limited to 'openssl/trunk')
-rw-r--r-- | openssl/trunk/crypto/x509v3/v3_asid.c | 188 |
1 files changed, 76 insertions, 112 deletions
diff --git a/openssl/trunk/crypto/x509v3/v3_asid.c b/openssl/trunk/crypto/x509v3/v3_asid.c index 1d070c7e..ba0c0edf 100644 --- a/openssl/trunk/crypto/x509v3/v3_asid.c +++ b/openssl/trunk/crypto/x509v3/v3_asid.c @@ -237,29 +237,28 @@ static void extract_min_max(ASIdOrRange *aor, } /* - * Whack an ASIdentifierChoice into canonical form. + * Check whether an ASIdentifierChoice is in canonical form. */ -static int asid_canonize(ASIdentifierChoice *choice) +static int asid_is_canonical(ASIdentifierChoice *choice) { ASN1_INTEGER *a_max_plus_one = NULL; BIGNUM *bn = NULL; int i, ret = 0; /* - * Nothing to do for empty element or inheritance. + * Empty element or inheritance is canonical. */ if (choice == NULL || choice->type == ASIdentifierChoice_inherit) return 1; /* - * We have a list. Sort it. + * If it's not a list at this point, it's broken. */ - assert(choice->type == ASIdentifierChoice_asIdsOrRanges); - sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); + if (choice->type != ASIdentifierChoice_asIdsOrRanges) + return 0; /* - * Now check for errors and suboptimal encoding, rejecting the - * former and fixing the latter. + * It's a list, check it. */ for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); @@ -270,17 +269,12 @@ static int asid_canonize(ASIdentifierChoice *choice) extract_min_max(b, &b_min, &b_max); /* - * Make sure we're properly sorted (paranoia). - */ - assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); - - /* - * Check for overlaps. + * Punt misordered list, overlapping start, or inverted range. */ - if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { - X509V3err(X509V3_F_ASID_CANONIZE, X509V3_R_EXTENSION_VALUE_ERROR); + if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 || + ASN1_INTEGER_cmp(a_min, a_max) > 0 || + ASN1_INTEGER_cmp(b_min, b_max) > 0) goto done; - } /* * Calculate a_max + 1 to check for adjacency. @@ -289,44 +283,15 @@ static int asid_canonize(ASIdentifierChoice *choice) ASN1_INTEGER_to_BN(a_max, bn) == NULL || !BN_add_word(bn, 1) || (a_max_plus_one = BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { - X509V3err(X509V3_F_ASID_CANONIZE, ERR_R_MALLOC_FAILURE); + X509V3err(X509V3_F_ASID_IS_CANONICAL, ERR_R_MALLOC_FAILURE); goto done; } /* - * If a and b are adjacent, merge them. + * Punt if adjacent or overlapping. */ - if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { - ASRange *r; - switch (a->type) { - case ASIdOrRange_id: - if ((r = OPENSSL_malloc(sizeof(ASRange))) == NULL) { - X509V3err(X509V3_F_ASID_CANONIZE, ERR_R_MALLOC_FAILURE); - goto done; - } - r->min = a_min; - r->max = b_max; - a->type = ASIdOrRange_range; - a->u.range = r; - break; - case ASIdOrRange_range: - ASN1_INTEGER_free(a->u.range->max); - a->u.range->max = b_max; - break; - } - switch (b->type) { - case ASIdOrRange_id: - b->u.id = NULL; - break; - case ASIdOrRange_range: - b->u.range->max = NULL; - break; - } - ASIdOrRange_free(b); - sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); - i--; - continue; - } + if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) + goto done; } ret = 1; @@ -337,59 +302,34 @@ static int asid_canonize(ASIdentifierChoice *choice) return ret; } -#if 0 /* - * Check whether an ASIdentifierChoice is in canonical form. + * Whack an ASIdentifierChoice into canonical form. */ -static int asid_is_canonical(ASIdentifierChoice *choice, - int (*cb)(ASIdentifierChoice *, void *), - void *cookie) +static int asid_canonize(ASIdentifierChoice *choice) { ASN1_INTEGER *a_max_plus_one = NULL; - ASIdOrRanges *aors = NULL; BIGNUM *bn = NULL; int i, ret = 0; - assert(cb != 0); - /* - * Empty element or inheritance is canonical. + * Nothing to do for empty element or inheritance. */ if (choice == NULL || choice->type == ASIdentifierChoice_inherit) return 1; /* - * If it's not a list at this point, it's broken. - */ - if (choice->type != ASIdentifierChoice_asIdsOrRanges) - return cb(choice, cookie); - - /* - * It's a list, we need a copy to sort. - */ - if ((aors = sk_ASIdOrRange_dup(choice->u.asIdsOrRanges)) == NULL) { - X509V3err(X509V3_F_ASID_IS_CANONICAL, ERR_R_MALLOC_FAILURE); - return 0; - } - sk_ASIdOrRange_set_cmp_func(aors, ASIdOrRange_cmp); - sk_ASIdOrRange_sort(aors); - - /* - * Check to see if it was misordered. + * We have a list. Sort it. */ - for (i = 0; i < sk_ASIdOrRange_num(aors); i++) { - if (sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i) != - sk_ASIdOrRange_value(aors, i) && - !cb(choice, cookie)) - goto done; - } + assert(choice->type == ASIdentifierChoice_asIdsOrRanges); + sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); /* - * Now check for duplicates and overlaps in the sorted copy. + * Now check for errors and suboptimal encoding, rejecting the + * former and fixing the latter. */ - for (i = 0; i < sk_ASIdOrRange_num(aors) - 1; i++) { - ASIdOrRange *a = sk_ASIdOrRange_value(aors, i); - ASIdOrRange *b = sk_ASIdOrRange_value(aors, i + 1); + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); ASN1_INTEGER *a_min, *a_max, *b_min, *b_max; extract_min_max(a, &a_min, &a_max); @@ -401,22 +341,11 @@ static int asid_is_canonical(ASIdentifierChoice *choice, assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); /* - * Does a contain b? - */ - if (ASN1_INTEGER_cmp(a_max, b_max) >= 0) { - if (!cb(choice, cookie)) - goto done; - continue; - } - - /* - * Does b contain a? + * Check for overlaps. */ - if (ASN1_INTEGER_cmp(a_min, b_min) == 0 && - ASN1_INTEGER_cmp(a_max, b_max) <= 0) { - if (!cb(choice, cookie)) - goto done; - continue; + if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { + X509V3err(X509V3_F_ASID_CANONIZE, X509V3_R_EXTENSION_VALUE_ERROR); + goto done; } /* @@ -426,29 +355,55 @@ static int asid_is_canonical(ASIdentifierChoice *choice, ASN1_INTEGER_to_BN(a_max, bn) == NULL || !BN_add_word(bn, 1) || (a_max_plus_one = BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { - X509V3err(X509V3_F_ASID_IS_CANONICAL, ERR_R_MALLOC_FAILURE); + X509V3err(X509V3_F_ASID_CANONIZE, ERR_R_MALLOC_FAILURE); goto done; } /* - * Are a and b adjacent or overlapping? + * If a and b are adjacent, merge them. */ - if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) { - if (!cb(choice, cookie)) - goto done; + if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { + ASRange *r; + switch (a->type) { + case ASIdOrRange_id: + if ((r = OPENSSL_malloc(sizeof(ASRange))) == NULL) { + X509V3err(X509V3_F_ASID_CANONIZE, ERR_R_MALLOC_FAILURE); + goto done; + } + r->min = a_min; + r->max = b_max; + a->type = ASIdOrRange_range; + a->u.range = r; + break; + case ASIdOrRange_range: + ASN1_INTEGER_free(a->u.range->max); + a->u.range->max = b_max; + break; + } + switch (b->type) { + case ASIdOrRange_id: + b->u.id = NULL; + break; + case ASIdOrRange_range: + b->u.range->max = NULL; + break; + } + ASIdOrRange_free(b); + sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); + i--; continue; } } + assert(asid_is_canonical(choice)); /* Paranoia */ + ret = 1; done: - sk_ASIdOrRange_free(aors); ASN1_INTEGER_free(a_max_plus_one); BN_free(bn); return ret; } -#endif /* 0 */ /* * v2i method for an ASIdentifier extension. @@ -640,14 +595,20 @@ int v3_asid_validate_path(X509_STORE_CTX *ctx) * Start with the target certificate. If it doesn't have the extension, * we're done. */ - x = sk_X509_value(ctx->chain, 0); + i = 0; + x = sk_X509_value(ctx->chain, i); assert(x != NULL); if (x->rfc3779_asid == NULL) goto done; /* - * Has extension, have to check the whole chain. + * Has extension, have to check the whole chain. Make sure the + * extension is in canonical form, then pull its resource lists + * so we can check whether its parents had them to grant. */ + if (!asid_is_canonical(x->rfc3779_asid->asnum) || + !asid_is_canonical(x->rfc3779_asid->rdi)) + validation_err(X509_V_ERR_INVALID_EXTENSION); if (x->rfc3779_asid->asnum != NULL) { switch (x->rfc3779_asid->asnum->type) { case ASIdentifierChoice_inherit: @@ -670,12 +631,15 @@ int v3_asid_validate_path(X509_STORE_CTX *ctx) } /* - * Now walk up the chain. No cert may list resources that its - * parent doesn't list. + * Now walk up the chain. Extensions must be in canonical form, and + * no cert may list resources that its parent doesn't list. */ for (i = 1; i < sk_X509_num(ctx->chain); i++) { x = sk_X509_value(ctx->chain, i); assert(x != NULL); + if (!asid_is_canonical(x->rfc3779_asid->asnum) || + !asid_is_canonical(x->rfc3779_asid->rdi)) + validation_err(X509_V_ERR_INVALID_EXTENSION); if (x->rfc3779_asid == NULL) { if (child_as != NULL || child_rdi != NULL) validation_err(X509_V_ERR_UNNESTED_RESOURCE); |