X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) { X509V3_EXT_METHOD *method; if(!(method = X509V3_EXT_get_nid(ext_nid))) { X509V3err(X509V3_F_X509V3_EXT_I2D,X509V3_R_UNKNOWN_EXTENSION); return NULL; } return do_ext_i2d(method, ext_nid, crit, ext_struc); }
int X509_PURPOSE_set(int *p, int purpose) { if(X509_PURPOSE_get_by_id(purpose) == -1) { X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE); return 0; } *p = purpose; return 1; }
int X509V3_EXT_add_alias(int nid_to, int nid_from) { const X509V3_EXT_METHOD *ext; X509V3_EXT_METHOD *tmpext; if(!(ext = X509V3_EXT_get_nid(nid_from))) { X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,X509V3_R_EXTENSION_NOT_FOUND); return 0; } if(!(tmpext = (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) { X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,ERR_R_MALLOC_FAILURE); return 0; } *tmpext = *ext; tmpext->ext_nid = nid_to; tmpext->ext_flags |= X509V3_EXT_DYNAMIC; return X509V3_EXT_add(tmpext); }
static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str) { ASN1_OCTET_STRING *oct; ASN1_BIT_STRING *pk; unsigned char pkey_dig[EVP_MAX_MD_SIZE]; unsigned int diglen; if(TINYCLR_SSL_STRCMP(str, "hash")) return s2i_ASN1_OCTET_STRING(method, ctx, str); if(!(oct = M_ASN1_OCTET_STRING_new())) { X509V3err(X509V3_F_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE); return NULL; } if(ctx && (ctx->flags == CTX_TEST)) return oct; if(!ctx || (!ctx->subject_req && !ctx->subject_cert)) { X509V3err(X509V3_F_S2I_SKEY_ID,X509V3_R_NO_PUBLIC_KEY); goto err; } if(ctx->subject_req) pk = ctx->subject_req->req_info->pubkey->public_key; else pk = ctx->subject_cert->cert_info->key->public_key; if(!pk) { X509V3err(X509V3_F_S2I_SKEY_ID,X509V3_R_NO_PUBLIC_KEY); goto err; } EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL); if(!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { X509V3err(X509V3_F_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE); goto err; } return oct; err: M_ASN1_OCTET_STRING_free(oct); return NULL; }
static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str) { ASN1_IA5STRING *ia5; if(!str) { X509V3err(X509V3_F_S2I_ASN1_IA5STRING,X509V3_R_INVALID_NULL_ARGUMENT); return NULL; } if(!(ia5 = M_ASN1_IA5STRING_new())) goto err; if(!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str, strlen(str))) { M_ASN1_IA5STRING_free(ia5); goto err; } return ia5; err: X509V3err(X509V3_F_S2I_ASN1_IA5STRING,ERR_R_MALLOC_FAILURE); return NULL; }
/* Create a generic extension: for now just handle DER type */ static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type) { unsigned char *ext_der=NULL; long ext_len; ASN1_OBJECT *obj=NULL; ASN1_OCTET_STRING *oct=NULL; X509_EXTENSION *extension=NULL; if (!(obj = OBJ_txt2obj(ext, 0))) { X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_NAME_ERROR); ERR_add_error_data(2, "name=", ext); goto err; } if (!(ext_der = string_to_hex(value, &ext_len))) { X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_VALUE_ERROR); ERR_add_error_data(2, "value=", value); goto err; } if (!(oct = M_ASN1_OCTET_STRING_new())) { X509V3err(X509V3_F_V3_GENERIC_EXTENSION,ERR_R_MALLOC_FAILURE); goto err; } oct->data = ext_der; oct->length = ext_len; ext_der = NULL; extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); err: ASN1_OBJECT_free(obj); M_ASN1_OCTET_STRING_free(oct); if(ext_der) OPENSSL_free(ext_der); return extension; }
int X509V3_EXT_free(int nid, void *ext_data) { const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid); if (ext_method == NULL) { X509V3err(X509V3_F_X509V3_EXT_FREE, X509V3_R_CANNOT_FIND_FREE_FUNCTION); return 0; } if (ext_method->it != NULL) ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it)); else if (ext_method->ext_free != NULL) ext_method->ext_free(ext_data); else { X509V3err(X509V3_F_X509V3_EXT_FREE, X509V3_R_CANNOT_FIND_FREE_FUNCTION); return 0; } return 1; }
static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str) { ASN1_IA5STRING *ia5; if(!str) { X509V3err(X509V3_F_S2I_ASN1_IA5STRING,X509V3_R_INVALID_NULL_ARGUMENT); return NULL; } if(!(ia5 = M_ASN1_IA5STRING_new())) goto err; if(!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str, strlen(str))) { M_ASN1_IA5STRING_free(ia5); goto err; } #ifdef CHARSET_EBCDIC ebcdic2ascii(ia5->data, ia5->data, ia5->length); #endif /*CHARSET_EBCDIC*/ return ia5; err: X509V3err(X509V3_F_S2I_ASN1_IA5STRING,ERR_R_MALLOC_FAILURE); return NULL; }
static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5) { char *tmp; if(!ia5 || !ia5->length) return NULL; if(!(tmp = OPENSSL_malloc(ia5->length + 1))) { X509V3err(X509V3_F_I2S_ASN1_IA5STRING,ERR_R_MALLOC_FAILURE); return NULL; } memcpy(tmp, ia5->data, ia5->length); tmp[ia5->length] = 0; return tmp; }
/* char *value: Value */ X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value) { int crit; int ext_type; X509_EXTENSION *ret; crit = v3_check_critical(&value); if ((ext_type = v3_check_generic(&value))) return v3_generic_extension(name, value, crit, ext_type, ctx); ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); if (!ret) { X509V3err(X509V3_F_X509V3_EXT_NCONF, X509V3_R_ERROR_IN_EXTENSION); ERR_add_error_data(4, "name=", name, ", value=", value); } return ret; }
static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, int crit, void *ext_struc) { unsigned char *ext_der = NULL; int ext_len; ASN1_OCTET_STRING *ext_oct = NULL; X509_EXTENSION *ext; /* Convert internal representation to DER */ if (method->it) { ext_der = NULL; ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); if (ext_len < 0) goto merr; } else { unsigned char *p; ext_len = method->i2d(ext_struc, NULL); if ((ext_der = OPENSSL_malloc(ext_len)) == NULL) goto merr; p = ext_der; method->i2d(ext_struc, &p); } if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL) goto merr; ext_oct->data = ext_der; ext_der = NULL; ext_oct->length = ext_len; ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); if (!ext) goto merr; ASN1_OCTET_STRING_free(ext_oct); return ext; merr: X509V3err(X509V3_F_DO_EXT_I2D, ERR_R_MALLOC_FAILURE); OPENSSL_free(ext_der); ASN1_OCTET_STRING_free(ext_oct); return NULL; }
static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, char *sect) { STACK_OF(CONF_VALUE) *gnsect; STACK_OF(GENERAL_NAME) *gens; if (*sect == '@') gnsect = X509V3_get_section(ctx, sect + 1); else gnsect = X509V3_parse_list(sect); if (!gnsect) { X509V3err(X509V3_F_GNAMES_FROM_SECTNAME, X509V3_R_SECTION_NOT_FOUND); return NULL; } gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); if (*sect == '@') X509V3_section_free(ctx, gnsect); else sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); return gens; }
ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str) { ASN1_OCTET_STRING *oct; long length; if (!(oct = ASN1_OCTET_STRING_new())) { X509V3err(X509V3_F_S2I_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE); return NULL; } if (!(oct->data = string_to_hex(str, &length))) { ASN1_OCTET_STRING_free(oct); return NULL; } oct->length = length; return oct; }
ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) { ASN1_OCTET_STRING *oct; long length; if ((oct = ASN1_OCTET_STRING_new()) == NULL) { X509V3err(X509V3_F_S2I_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE); return NULL; } if ((oct->data = OPENSSL_hexstr2buf(str, &length)) == NULL) { ASN1_OCTET_STRING_free(oct); return NULL; } oct->length = length; return oct; }
static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value) { PROXY_CERT_INFO_EXTENSION *pci = NULL; STACK_OF(CONF_VALUE) *vals; ASN1_OBJECT *language = NULL; ASN1_INTEGER *pathlen = NULL; ASN1_OCTET_STRING *policy = NULL; int i, j; vals = X509V3_parse_list(value); for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i); if (!cnf->name || (*cnf->name != '@' && !cnf->value)) { X509V3err(X509V3_F_R2I_PCI, X509V3_R_INVALID_PROXY_POLICY_SETTING); X509V3_conf_err(cnf); goto err; } if (*cnf->name == '@') { STACK_OF(CONF_VALUE) *sect; int success_p = 1; sect = X509V3_get_section(ctx, cnf->name + 1); if (!sect) { X509V3err(X509V3_F_R2I_PCI, X509V3_R_INVALID_SECTION); X509V3_conf_err(cnf); goto err; } for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) { success_p = process_pci_value(sk_CONF_VALUE_value(sect, j), &language, &pathlen, &policy); } X509V3_section_free(ctx, sect); if (!success_p) goto err; } else { if (!process_pci_value(cnf, &language, &pathlen, &policy)) { X509V3_conf_err(cnf); goto err; } } } /* Language is mandatory */ if (!language) { X509V3err(X509V3_F_R2I_PCI, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED); goto err; } i = OBJ_obj2nid(language); if ((i == NID_Independent || i == NID_id_ppl_inheritAll) && policy) { X509V3err(X509V3_F_R2I_PCI, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY); goto err; } pci = PROXY_CERT_INFO_EXTENSION_new(); if (pci == NULL) { X509V3err(X509V3_F_R2I_PCI, ERR_R_MALLOC_FAILURE); goto err; } pci->proxyPolicy->policyLanguage = language; language = NULL; pci->proxyPolicy->policy = policy; policy = NULL; pci->pcPathLengthConstraint = pathlen; pathlen = NULL; goto end; err: ASN1_OBJECT_free(language); ASN1_INTEGER_free(pathlen); pathlen = NULL; ASN1_OCTET_STRING_free(policy); policy = NULL; PROXY_CERT_INFO_EXTENSION_free(pci); pci = NULL; end: sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); return pci; }
static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, CONF_VALUE *cnf) { STACK_OF(GENERAL_NAME) *fnm = NULL; STACK_OF(X509_NAME_ENTRY) *rnm = NULL; if (!strncmp(cnf->name, "fullname", 9)) { fnm = gnames_from_sectname(ctx, cnf->value); if (!fnm) goto err; } else if (!strcmp(cnf->name, "relativename")) { int ret; STACK_OF(CONF_VALUE) *dnsect; X509_NAME *nm; nm = X509_NAME_new(); if (!nm) return -1; dnsect = X509V3_get_section(ctx, cnf->value); if (!dnsect) { X509V3err(X509V3_F_SET_DIST_POINT_NAME, X509V3_R_SECTION_NOT_FOUND); return -1; } ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); X509V3_section_free(ctx, dnsect); rnm = nm->entries; nm->entries = NULL; X509_NAME_free(nm); if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) goto err; /* Since its a name fragment can't have more than one * RDNSequence */ if (sk_X509_NAME_ENTRY_value(rnm, sk_X509_NAME_ENTRY_num(rnm) - 1)->set) { X509V3err(X509V3_F_SET_DIST_POINT_NAME, X509V3_R_INVALID_MULTIPLE_RDNS); goto err; } } else return 0; if (*pdp) { X509V3err(X509V3_F_SET_DIST_POINT_NAME, X509V3_R_DISTPOINT_ALREADY_SET); goto err; } *pdp = DIST_POINT_NAME_new(); if (!*pdp) goto err; if (fnm) { (*pdp)->type = 0; (*pdp)->name.fullname = fnm; } else { (*pdp)->type = 1; (*pdp)->name.relativename = rnm; } return 1; err: if (fnm) sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); if (rnm) sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); return -1; }
/* * Whack an ASIdentifierChoice into canonical form. */ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) { ASN1_INTEGER *a_max_plus_one = NULL; BIGNUM *bn = NULL; int i, ret = 0; /* * Nothing to do for empty element or inheritance. */ if (choice == NULL || choice->type == ASIdentifierChoice_inherit) return 1; /* * If not a list, or if empty list, it's broken. */ if (choice->type != ASIdentifierChoice_asIdsOrRanges || sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, X509V3_R_EXTENSION_VALUE_ERROR); return 0; } /* * We have a non-empty list. Sort it. */ sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); /* * Now check for errors and suboptimal encoding, rejecting the * former and fixing the latter. */ 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 = NULL, *a_max = NULL, *b_min = NULL, *b_max = NULL; if (!extract_min_max(a, &a_min, &a_max) || !extract_min_max(b, &b_min, &b_max)) goto done; /* * Make sure we're properly sorted (paranoia). */ if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0)) goto done; /* * Punt inverted ranges. */ if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || ASN1_INTEGER_cmp(b_min, b_max) > 0) goto done; /* * Check for overlaps. */ if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, X509V3_R_EXTENSION_VALUE_ERROR); goto done; } /* * Calculate a_max + 1 to check for adjacency. */ if ((bn == NULL && (bn = BN_new()) == NULL) || 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_ASIDENTIFIERCHOICE_CANONIZE, ERR_R_MALLOC_FAILURE); goto done; } /* * If a and b are adjacent, merge them. */ if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { ASRange *r; switch (a->type) { case ASIdOrRange_id: if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) { X509V3err(X509V3_F_ASIDENTIFIERCHOICE_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); (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); i--; continue; } } /* * Check for final inverted range. */ i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; { ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); ASN1_INTEGER *a_min, *a_max; if (a != NULL && a->type == ASIdOrRange_range) { if (!extract_min_max(a, &a_min, &a_max) || ASN1_INTEGER_cmp(a_min, a_max) > 0) goto done; } } /* Paranoia */ if (!ossl_assert(ASIdentifierChoice_is_canonical(choice))) goto done; ret = 1; done: ASN1_INTEGER_free(a_max_plus_one); BN_free(bn); return ret; }
/* * Check whether an ASIdentifierChoice is in canonical form. */ static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) { ASN1_INTEGER *a_max_plus_one = NULL; BIGNUM *bn = NULL; int i, ret = 0; /* * Empty element or inheritance is canonical. */ if (choice == NULL || choice->type == ASIdentifierChoice_inherit) return 1; /* * If not a list, or if empty list, it's broken. */ if (choice->type != ASIdentifierChoice_asIdsOrRanges || sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) return 0; /* * 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); ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max = NULL; if (!extract_min_max(a, &a_min, &a_max) || !extract_min_max(b, &b_min, &b_max)) goto done; /* * Punt misordered list, overlapping start, or inverted range. */ 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. */ if ((bn == NULL && (bn = BN_new()) == NULL) || 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_ASIDENTIFIERCHOICE_IS_CANONICAL, ERR_R_MALLOC_FAILURE); goto done; } /* * Punt if adjacent or overlapping. */ if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) goto done; } /* * Check for inverted range. */ i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; { ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); ASN1_INTEGER *a_min, *a_max; if (a != NULL && a->type == ASIdOrRange_range) { if (!extract_min_max(a, &a_min, &a_max) || ASN1_INTEGER_cmp(a_min, a_max) > 0) goto done; } } ret = 1; done: ASN1_INTEGER_free(a_max_plus_one); BN_free(bn); return ret; }
STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value) { STACK_OF(POLICYINFO) *pols = NULL; char *pstr; POLICYINFO *pol; ASN1_OBJECT *pobj; STACK_OF(CONF_VALUE) *vals; CONF_VALUE *cnf; int i, ia5org; pols = sk_POLICYINFO_new_null(); if (pols == NULL) { X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE); return NULL; } vals = X509V3_parse_list(value); if (vals == NULL) { X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB); goto err; } ia5org = 0; for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { cnf = sk_CONF_VALUE_value(vals, i); if (cnf->value || !cnf->name ) { X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_POLICY_IDENTIFIER); X509V3_conf_err(cnf); goto err; } pstr = cnf->name; if (!strcmp(pstr, "ia5org")) { ia5org = 1; continue; } else if (*pstr == '@') { STACK_OF(CONF_VALUE) *polsect; polsect = X509V3_get_section(ctx, pstr + 1); if (!polsect) { X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION); X509V3_conf_err(cnf); goto err; } pol = policy_section(ctx, polsect, ia5org); X509V3_section_free(ctx, polsect); if (!pol) goto err; } else { if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_OBJECT_IDENTIFIER); X509V3_conf_err(cnf); goto err; } pol = POLICYINFO_new(); pol->policyid = pobj; } if (!sk_POLICYINFO_push(pols, pol)){ POLICYINFO_free(pol); X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE); goto err; } } sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); return pols; err: sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); sk_POLICYINFO_pop_free(pols, POLICYINFO_free); return NULL; }
int X509_PURPOSE_add(int id, int trust, int flags, int (*ck) (const X509_PURPOSE *, const X509 *, int), const char *name, const char *sname, void *arg) { int idx; X509_PURPOSE *ptmp; /* * This is set according to what we change: application can't set it */ flags &= ~X509_PURPOSE_DYNAMIC; /* This will always be set for application modified trust entries */ flags |= X509_PURPOSE_DYNAMIC_NAME; /* Get existing entry if any */ idx = X509_PURPOSE_get_by_id(id); /* Need a new entry */ if (idx == -1) { if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) { X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); return 0; } ptmp->flags = X509_PURPOSE_DYNAMIC; } else ptmp = X509_PURPOSE_get0(idx); /* OPENSSL_free existing name if dynamic */ if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { OPENSSL_free(ptmp->name); OPENSSL_free(ptmp->sname); } /* dup supplied name */ ptmp->name = OPENSSL_strdup(name); ptmp->sname = OPENSSL_strdup(sname); if (!ptmp->name || !ptmp->sname) { X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); goto err; } /* Keep the dynamic flag of existing entry */ ptmp->flags &= X509_PURPOSE_DYNAMIC; /* Set all other flags */ ptmp->flags |= flags; ptmp->purpose = id; ptmp->trust = trust; ptmp->check_purpose = ck; ptmp->usr_data = arg; /* If its a new entry manage the dynamic table */ if (idx == -1) { if (xptable == NULL && (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) { X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); goto err; } if (!sk_X509_PURPOSE_push(xptable, ptmp)) { X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); goto err; } } return 1; err: if (idx == -1) { OPENSSL_free(ptmp->name); OPENSSL_free(ptmp->sname); OPENSSL_free(ptmp); } return 0; }
static int process_pci_value(CONF_VALUE *val, ASN1_OBJECT **language, ASN1_INTEGER **pathlen, ASN1_OCTET_STRING **policy) { int free_policy = 0; if (strcmp(val->name, "language") == 0) { if (*language) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED); X509V3_conf_err(val); return 0; } if ((*language = OBJ_txt2obj(val->value, 0)) == NULL) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, X509V3_R_INVALID_OBJECT_IDENTIFIER); X509V3_conf_err(val); return 0; } } else if (strcmp(val->name, "pathlen") == 0) { if (*pathlen) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED); X509V3_conf_err(val); return 0; } if (!X509V3_get_value_int(val, pathlen)) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, X509V3_R_POLICY_PATH_LENGTH); X509V3_conf_err(val); return 0; } } else if (strcmp(val->name, "policy") == 0) { unsigned char *tmp_data = NULL; long val_len; if (!*policy) { *policy = ASN1_OCTET_STRING_new(); if (*policy == NULL) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); return 0; } free_policy = 1; } if (strncmp(val->value, "hex:", 4) == 0) { unsigned char *tmp_data2 = OPENSSL_hexstr2buf(val->value + 4, &val_len); if (!tmp_data2) { X509V3_conf_err(val); goto err; } tmp_data = OPENSSL_realloc((*policy)->data, (*policy)->length + val_len + 1); if (tmp_data) { (*policy)->data = tmp_data; memcpy(&(*policy)->data[(*policy)->length], tmp_data2, val_len); (*policy)->length += val_len; (*policy)->data[(*policy)->length] = '\0'; } else { OPENSSL_free(tmp_data2); /* * realloc failure implies the original data space is b0rked * too! */ OPENSSL_free((*policy)->data); (*policy)->data = NULL; (*policy)->length = 0; X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } OPENSSL_free(tmp_data2); } else if (strncmp(val->value, "file:", 5) == 0) { unsigned char buf[2048]; int n; BIO *b = BIO_new_file(val->value + 5, "r"); if (!b) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB); X509V3_conf_err(val); goto err; } while ((n = BIO_read(b, buf, sizeof(buf))) > 0 || (n == 0 && BIO_should_retry(b))) { if (!n) continue; tmp_data = OPENSSL_realloc((*policy)->data, (*policy)->length + n + 1); if (!tmp_data) { OPENSSL_free((*policy)->data); (*policy)->data = NULL; (*policy)->length = 0; X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); BIO_free_all(b); goto err; } (*policy)->data = tmp_data; memcpy(&(*policy)->data[(*policy)->length], buf, n); (*policy)->length += n; (*policy)->data[(*policy)->length] = '\0'; } BIO_free_all(b); if (n < 0) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB); X509V3_conf_err(val); goto err; } } else if (strncmp(val->value, "text:", 5) == 0) { val_len = strlen(val->value + 5); tmp_data = OPENSSL_realloc((*policy)->data, (*policy)->length + val_len + 1); if (tmp_data) { (*policy)->data = tmp_data; memcpy(&(*policy)->data[(*policy)->length], val->value + 5, val_len); (*policy)->length += val_len; (*policy)->data[(*policy)->length] = '\0'; } else { /* * realloc failure implies the original data space is b0rked * too! */ OPENSSL_free((*policy)->data); (*policy)->data = NULL; (*policy)->length = 0; X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } } else { X509V3err(X509V3_F_PROCESS_PCI_VALUE, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG); X509V3_conf_err(val); goto err; } if (!tmp_data) { X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } } return 1; err: if (free_policy) { ASN1_OCTET_STRING_free(*policy); *policy = NULL; } return 0; }
/* char *value: Value */ static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, const char *value) { const X509V3_EXT_METHOD *method; X509_EXTENSION *ext; STACK_OF(CONF_VALUE) *nval; void *ext_struc; if (ext_nid == NID_undef) { X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION_NAME); return NULL; } if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) { X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION); return NULL; } /* Now get internal extension representation based on type */ if (method->v2i) { if (*value == '@') nval = NCONF_get_section(conf, value + 1); else nval = X509V3_parse_list(value); if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) { X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_INVALID_EXTENSION_STRING); ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value); if (*value != '@') sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); return NULL; } ext_struc = method->v2i(method, ctx, nval); if (*value != '@') sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); if (!ext_struc) return NULL; } else if (method->s2i) { if ((ext_struc = method->s2i(method, ctx, value)) == NULL) return NULL; } else if (method->r2i) { if (!ctx->db || !ctx->db_meth) { X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_NO_CONFIG_DATABASE); return NULL; } if ((ext_struc = method->r2i(method, ctx, value)) == NULL) return NULL; } else { X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); return NULL; } ext = do_ext_i2d(method, ext_nid, crit, ext_struc); if (method->it) ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); else method->ext_free(ext_struc); return ext; }