char *nussl_ssl_readable_dname(const nussl_ssl_dname * name) { int n, flag = 0; nussl_buffer *dump = nussl_buffer_create(); const ASN1_OBJECT *const cname = OBJ_nid2obj(NID_commonName), *const email = OBJ_nid2obj(NID_pkcs9_emailAddress); for (n = X509_NAME_entry_count(name->dn); n > 0; n--) { X509_NAME_ENTRY *ent = X509_NAME_get_entry(name->dn, n - 1); /* Skip commonName or emailAddress except if there is no other * attribute in dname. */ if ((OBJ_cmp(ent->object, cname) && OBJ_cmp(ent->object, email)) || (!flag && n == 1)) { if (flag++) nussl_buffer_append(dump, ", ", 2); if (append_dirstring(dump, ent->value)) nussl_buffer_czappend(dump, "???"); } } return nussl_buffer_finish(dump); }
void OpenSSLCertificate::parse() { if (!cert) { return; } // Subject name X509_NAME* subjectName = X509_get_subject_name(cert.get()); if (subjectName) { // Subject name ByteArray subjectNameData; subjectNameData.resize(256); X509_NAME_oneline(X509_get_subject_name(cert.get()), reinterpret_cast<char*>(subjectNameData.getData()), subjectNameData.getSize()); this->subjectName = std::string(reinterpret_cast<const char*>(subjectNameData.getData())); // Common name int cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, -1); while (cnLoc != -1) { X509_NAME_ENTRY* cnEntry = X509_NAME_get_entry(subjectName, cnLoc); ASN1_STRING* cnData = X509_NAME_ENTRY_get_data(cnEntry); commonNames.push_back(ByteArray(cnData->data, cnData->length).toString()); cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, cnLoc); } } // subjectAltNames int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); if(subjectAltNameLoc != -1) { X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); boost::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); boost::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); boost::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); if (generalName->type == GEN_OTHERNAME) { OTHERNAME* otherName = generalName->d.otherName; if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { // XmppAddr if (otherName->value->type != V_ASN1_UTF8STRING) { continue; } ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; addXMPPAddress(ByteArray(ASN1_STRING_data(xmppAddrValue), ASN1_STRING_length(xmppAddrValue)).toString()); } else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { // SRVName if (otherName->value->type != V_ASN1_IA5STRING) { continue; } ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; addSRVName(ByteArray(ASN1_STRING_data(srvNameValue), ASN1_STRING_length(srvNameValue)).toString()); } } else if (generalName->type == GEN_DNS) { // DNSName addDNSName(ByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)).toString()); } } } }
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { int i,j; X509_NAME_ENTRY *na,*nb; if (sk_X509_NAME_ENTRY_num(a->entries) != sk_X509_NAME_ENTRY_num(b->entries)) return sk_X509_NAME_ENTRY_num(a->entries) -sk_X509_NAME_ENTRY_num(b->entries); for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { na=sk_X509_NAME_ENTRY_value(a->entries,i); nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=na->value->length-nb->value->length; if (j) return(j); j=memcmp(na->value->data,nb->value->data, na->value->length); if (j) return(j); j=na->set-nb->set; if (j) return(j); } /* We will check the object types after checking the values * since the values will more often be different than the object * types. */ for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { na=sk_X509_NAME_ENTRY_value(a->entries,i); nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=OBJ_cmp(na->object,nb->object); if (j) return(j); } return(0); }
int PKI_OID_cmp( PKI_OID *a, PKI_OID *b ) { if ( !a || !b ) { return(-1); } return ( OBJ_cmp ( a, b )); }
EXPORT_C int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b) { int ret; ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm); if (ret) return ret; ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash); if (ret) return ret; return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash); }
/* * X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. */ int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) { int rv; rv = OBJ_cmp(a->algorithm, b->algorithm); if (rv) return rv; if (!a->parameter && !b->parameter) return 0; return ASN1_TYPE_cmp(a->parameter, b->parameter); }
/* Returns 0 if they are equal, != 0 otherwise. */ int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) { int rv = OBJ_cmp(a->algorithm, b->algorithm); if (!rv) { if (!a->parameter && !b->parameter) rv = 0; else rv = ASN1_TYPE_cmp(a->parameter, b->parameter); } return(rv); }
/* Returns 0 if they are equal, != 0 otherwise. */ int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) { int result = -1; if (!a || !b) return -1; /* Check their type first. */ if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) return result; /* Check the value. */ result = ASN1_TYPE_cmp(a->value, b->value); return result; }
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { int i,j; X509_NAME_ENTRY *na,*nb; unsigned long nabit, nbbit; j = sk_X509_NAME_ENTRY_num(a->entries) - sk_X509_NAME_ENTRY_num(b->entries); if (j) return j; for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { na=sk_X509_NAME_ENTRY_value(a->entries,i); nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=na->value->type-nb->value->type; if (j) { nabit = ASN1_tag2bit(na->value->type); nbbit = ASN1_tag2bit(nb->value->type); if (!(nabit & STR_TYPE_CMP) || !(nbbit & STR_TYPE_CMP)) return j; if (!asn1_string_memcmp(na->value, nb->value)) j = 0; } else if (na->value->type == V_ASN1_PRINTABLESTRING) j=nocase_spacenorm_cmp(na->value, nb->value); else if (na->value->type == V_ASN1_IA5STRING && OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress) j=nocase_cmp(na->value, nb->value); else j = asn1_string_memcmp(na->value, nb->value); if (j) return(j); j=na->set-nb->set; if (j) return(j); } /* We will check the object types after checking the values * since the values will more often be different than the object * types. */ for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { na=sk_X509_NAME_ENTRY_value(a->entries,i); nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=OBJ_cmp(na->object,nb->object); if (j) return(j); } return(0); }
/* Returns 0 if they are equal, != 0 otherwise. */ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) { int result = -1; if (!a || !b || a->type != b->type) return -1; switch (a->type) { case V_ASN1_OBJECT: result = OBJ_cmp(a->value.object, b->value.object); break; case V_ASN1_NULL: result = 0; /* They do not have content. */ break; case V_ASN1_BOOLEAN: result = a->value.boolean - b->value.boolean; break; case V_ASN1_INTEGER: case V_ASN1_NEG_INTEGER: case V_ASN1_ENUMERATED: case V_ASN1_NEG_ENUMERATED: case V_ASN1_BIT_STRING: case V_ASN1_OCTET_STRING: case V_ASN1_SEQUENCE: case V_ASN1_SET: case V_ASN1_NUMERICSTRING: case V_ASN1_PRINTABLESTRING: case V_ASN1_T61STRING: case V_ASN1_VIDEOTEXSTRING: case V_ASN1_IA5STRING: case V_ASN1_UTCTIME: case V_ASN1_GENERALIZEDTIME: case V_ASN1_GRAPHICSTRING: case V_ASN1_VISIBLESTRING: case V_ASN1_GENERALSTRING: case V_ASN1_UNIVERSALSTRING: case V_ASN1_BMPSTRING: case V_ASN1_UTF8STRING: case V_ASN1_OTHER: default: result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr, (ASN1_STRING *)b->value.ptr); break; } return result; }
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { int i,j; X509_NAME_ENTRY *na,*nb; if (sk_X509_NAME_ENTRY_num(a->entries) != sk_X509_NAME_ENTRY_num(b->entries)) return sk_X509_NAME_ENTRY_num(a->entries) -sk_X509_NAME_ENTRY_num(b->entries); for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { na=sk_X509_NAME_ENTRY_value(a->entries,i); nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=na->value->type-nb->value->type; if (j) return(j); if (na->value->type == V_ASN1_PRINTABLESTRING) j=nocase_spacenorm_cmp(na->value, nb->value); else if (na->value->type == V_ASN1_IA5STRING && OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress) j=nocase_cmp(na->value, nb->value); else { j=na->value->length-nb->value->length; if (j) return(j); j=memcmp(na->value->data,nb->value->data, na->value->length); } if (j) return(j); j=na->set-nb->set; if (j) return(j); } /* We will check the object types after checking the values * since the values will more often be different than the object * types. */ for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { na=sk_X509_NAME_ENTRY_value(a->entries,i); nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=OBJ_cmp(na->object,nb->object); if (j) return(j); } return(0); }
/* NOTE: you should be passsing -1, not 0 as lastpos */ int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos) { int n; X509_NAME_ENTRY *ne; STACK_OF(X509_NAME_ENTRY) *sk; if (name == NULL) return(-1); if (lastpos < 0) lastpos= -1; sk=name->entries; n=sk_X509_NAME_ENTRY_num(sk); for (lastpos++; lastpos < n; lastpos++) { ne=sk_X509_NAME_ENTRY_value(sk,lastpos); if (OBJ_cmp(ne->object,obj) == 0) return(lastpos); } return(-1); }
static int X509_NAME_wildcmp(const X509_NAME *a, const X509_NAME *b) { int i,j; X509_NAME_ENTRY *na,*nb; if (sk_X509_NAME_ENTRY_num(a->entries) != sk_X509_NAME_ENTRY_num(b->entries)) return sk_X509_NAME_ENTRY_num(a->entries) -sk_X509_NAME_ENTRY_num(b->entries); for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { na=sk_X509_NAME_ENTRY_value(a->entries,i); nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=OBJ_cmp(na->object,nb->object); if (j) return(j); if ((na->value->length == 1 && na->value->data[0] == '*') || (nb->value->length == 1 && nb->value->data[0] == '*')) continue; j=na->value->type-nb->value->type; if (j) return(j); if (na->value->type == V_ASN1_PRINTABLESTRING) j=nocase_spacenorm_cmp(na->value, nb->value); else if (na->value->type == V_ASN1_IA5STRING && OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress) j=nocase_cmp(na->value, nb->value); else { j=na->value->length-nb->value->length; if (j) return(j); j=memcmp(na->value->data,nb->value->data, na->value->length); } if (j) return(j); j=na->set-nb->set; if (j) return(j); } return(0); }
/* Returns 0 if they are equal, != 0 otherwise. */ int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) { int result = -1; if (!a || !b || a->type != b->type) return -1; switch (a->type) { case GEN_X400: case GEN_EDIPARTY: result = ASN1_TYPE_cmp(a->d.other, b->d.other); break; case GEN_OTHERNAME: result = OTHERNAME_cmp(a->d.otherName, b->d.otherName); break; case GEN_EMAIL: case GEN_DNS: case GEN_URI: result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5); break; case GEN_DIRNAME: result = X509_NAME_cmp(a->d.dirn, b->d.dirn); break; case GEN_IPADD: result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); break; case GEN_RID: result = OBJ_cmp(a->d.rid, b->d.rid); break; } return result; }
static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si) { STACK_OF(CMS_SignerInfo) *sinfos; CMS_SignerInfo *sitmp; int i; sinfos = CMS_get0_SignerInfos(cms); for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { ASN1_OCTET_STRING *messageDigest; sitmp = sk_CMS_SignerInfo_value(sinfos, i); if (sitmp == si) continue; if (CMS_signed_get_attr_count(sitmp) < 0) continue; if (OBJ_cmp(si->digestAlgorithm->algorithm, sitmp->digestAlgorithm->algorithm)) continue; messageDigest = CMS_signed_get0_data_by_OBJ(sitmp, OBJ_nid2obj(NID_pkcs9_messageDigest), -3, V_ASN1_OCTET_STRING); if (!messageDigest) { CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); return 0; } if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING, messageDigest, -1)) return 1; else return 0; } CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST); return 0; }
static int node_cmp(const X509_POLICY_NODE *const *a, const X509_POLICY_NODE *const *b) { return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy); }
LiteralValue_Priv::LiteralValue_Priv(GENERAL_NAME *gen) : LiteralValue() { char oline[256], htmp[5]; unsigned char *p = NULL; int nid = 0; int i; ASN1_OBJECT *id_ms_san_upn; ASN1_OBJECT *id_pkinit_san; #define CREATE_OBJ_IF_NEEDED(oid, vn, sn, ln) \ nid = OBJ_txt2nid(oid); \ if (nid == NID_undef) { \ nid = OBJ_create(oid, sn, ln); \ if (nid == NID_undef) { \ LOGIT_ERROR("Error creating oid object for " << oid); \ return; \ } \ } \ vn = OBJ_nid2obj(nid); CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.2", id_pkinit_san, "id-pkinit-san", "KRB5PrincipalName"); CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.3", id_ms_san_upn, "id-ms-san-upn", "Microsoft Universal Principal Name"); switch (gen->type) { case GEN_EMAIL: setLiteral("email", asn1string2string(gen->d.ia5)); break; case GEN_DNS: setLiteral("DNS", asn1string2string(gen->d.ia5)); break; case GEN_URI: setLiteral("URI", asn1string2string(gen->d.ia5)); break; case GEN_DIRNAME: X509_NAME_oneline(gen->d.dirn, oline, 256); setLiteral("DirName", oline); break; case GEN_IPADD: p = gen->d.ip->data; /* BUG: doesn't support IPV6 */ if(gen->d.ip->length == 4) { BIO_snprintf(oline, sizeof oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); } else if(gen->d.ip->length == 16) { oline[0] = 0; for (i = 0; i < 8; i++) { BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]); p += 2; strcat(oline, htmp); if (i != 7) strcat(oline, ":"); } } else { LOGIT_ERROR("Invalid IP Address"); CA_MGM_THROW(ca_mgm::SyntaxException, "Invalid IP Address"); break; } setLiteral("IP", oline); break; case GEN_RID: i2t_ASN1_OBJECT(oline, 256, gen->d.rid); setLiteral("RID", oline); break; case GEN_OTHERNAME: // krb5PrincipalName || Microsoft Universal Principal Name if(OBJ_cmp(id_pkinit_san, gen->d.otherName->type_id) == 0) { decode_krb5_principal_name(gen->d.otherName->value->value.sequence->data, gen->d.otherName->value->value.sequence->length); } else if (OBJ_cmp(id_ms_san_upn, gen->d.otherName->type_id) == 0) { setLiteral("1.3.6.1.4.1.311.20.2.3", (char*)gen->d.otherName->value->value.sequence->data); } else { setLiteral("othername", std::string("unsupported(") + str::numstring(OBJ_obj2nid(gen->d.otherName->type_id)) + ")"); } break; case GEN_X400: setLiteral("X400Name", "unsupported"); break; case GEN_EDIPARTY: setLiteral("EdiPartyName", "unsupported"); break; } }
ASN1_OCTET_STRING *sigattr_asn1_octet(scep_t *scep, char *attrname) { STACK_OF(X509_ATTRIBUTE) *sig_attribs; ASN1_OBJECT *asn1_obj; ASN1_TYPE *asn1_type; X509_ATTRIBUTE *attr; int i; scepmsg_t *msg; int single; if (debug) BIO_printf(bio_err, "%s:%d: looking for attribute '%s'\n", __FILE__, __LINE__, attrname); /* decide which message to study: client reads attrs from reply */ if (scep->client) msg = &scep->reply; else msg = &scep->request; /* find the object we by name */ asn1_obj = OBJ_nid2obj(OBJ_sn2nid(attrname)); asn1_type = NULL; /* retrieve the stack of signed attributes */ if (NULL == (sig_attribs = PKCS7_get_signed_attributes(msg->si))) { BIO_printf(bio_err, "%s:%d: signed attributes not found\n", __FILE__, __LINE__); return NULL; } /* scan all attributes for the one we are looking for */ for (i = 0; i < sk_X509_ATTRIBUTE_num(sig_attribs); i++) { attr = sk_X509_ATTRIBUTE_value(sig_attribs, i); if (OBJ_cmp(attr->object, asn1_obj) == 0) { #if OPENSSL_VERSION_NUMBER < 0x00907000L /* attr->set was replaced with attr->single (with opposite meaning) somewhere between 0.9.6m-engine and 0.9.7d */ single = !attr->set; #else single = attr->single; #endif if (single || (sk_ASN1_TYPE_num(attr->value.set) == 0)) { BIO_printf(bio_err, "%s:%d: attr has no val\n",__FILE__, __LINE__); goto err; BIO_printf(bio_err, "%s:%d: attr has no val\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: found matching " "attribute with %d values\n", __FILE__, __LINE__, sk_ASN1_TYPE_num(attr->value.set)); asn1_type = sk_ASN1_TYPE_value(attr->value.set, 0); if (debug) BIO_printf(bio_err, "%s:%d: type found: %p\n", __FILE__, __LINE__, asn1_type); break; } } /* if we cannot find the required argument, we just return NULL */ if (debug) BIO_printf(bio_err, "%s:%d: checking for attribute\n", __FILE__, __LINE__); if (asn1_type == NULL) { BIO_printf(bio_err, "%s:%d: attribute has no type\n", __FILE__, __LINE__); goto err; } if (ASN1_TYPE_get(asn1_type) != V_ASN1_OCTET_STRING) { BIO_printf(bio_err, "%s:%d: attribute has wrong type\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: found attribute '%s'\n", __FILE__, __LINE__, attrname); /* this is an ASN1_OCTET_STRING, so we can retrieve the */ /* appropriate element of the union */ return asn1_type->value.octet_string; /* error return, or attribute not found */ err: if (debug) BIO_printf(bio_err, "%s:%d: attribute not found or error\n", __FILE__, __LINE__); ERR_print_errors(bio_err); return NULL; }
/* * read an attribute of type string */ char *sigattr_string(scep_t *scep, char *attrname) { STACK_OF(X509_ATTRIBUTE) *sig_attribs; ASN1_OBJECT *asn1_obj; ASN1_TYPE *asn1_type; X509_ATTRIBUTE *attr; int len, i; char *data = NULL; scepmsg_t *msg; if (debug) BIO_printf(bio_err, "%s:%d: looking for attribute '%s'\n", __FILE__, __LINE__, attrname); /* decide which message to study: client reads attrs from reply */ if (scep->client) msg = &scep->reply; else msg = &scep->request; /* find the object we by name */ asn1_obj = OBJ_nid2obj(OBJ_sn2nid(attrname)); asn1_type = NULL; /* retrieve the stack of signed attributes */ if (NULL == (sig_attribs = PKCS7_get_signed_attributes(msg->si))) { BIO_printf(bio_err, "%s:%d: no signed attributes\n", __FILE__, __LINE__); return NULL; } /* scan all attributes for the one we are looking for */ for (i = 0; i < sk_X509_ATTRIBUTE_num(sig_attribs); i++) { attr = sk_X509_ATTRIBUTE_value(sig_attribs, i); if (OBJ_cmp(attr->object, asn1_obj) == 0) { if (debug) BIO_printf(bio_err, "%s:%d: found attribute\n", __FILE__, __LINE__); asn1_type = sk_ASN1_TYPE_value(attr->value.set, 0); break; } } /* if we cannot find the required argument, we just return NULL */ if (asn1_type == NULL) { BIO_printf(bio_err, "%s:%d: cannot find attribute\n", __FILE__, __LINE__); goto err; } if (ASN1_TYPE_get(asn1_type) != V_ASN1_PRINTABLESTRING) { BIO_printf(bio_err, "%s:%d: attribute has wrong type\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: found attribute '%s'\n", __FILE__, __LINE__, attrname); /* unpack the ASN1_STRING into a C-String (0-terminated) */ len = ASN1_STRING_length(asn1_type->value.asn1_string); data = (char *)malloc(1 + len); memcpy(data, ASN1_STRING_data(asn1_type->value.asn1_string), len); data[len] = '\0'; if (debug) BIO_printf(bio_err, "%s:%d: value of %d bytes retrieved\n", __FILE__, __LINE__, len); /* return the data */ return data; err: ERR_print_errors(bio_err); return NULL; }
int ndn_verify_signature(const unsigned char *msg, size_t size, const struct ndn_parsed_ContentObject *co, const struct ndn_pkey *verification_pubkey) { EVP_MD_CTX verc; EVP_MD_CTX *ver_ctx = &verc; X509_SIG *digest_info = NULL; const unsigned char *dd = NULL; MP_info *merkle_path_info = NULL; unsigned char *root_hash = NULL; size_t root_hash_size; int res; const EVP_MD *digest = NULL; const EVP_MD *merkle_path_digest = NULL; const unsigned char *signature_bits = NULL; size_t signature_bits_size = 0; const unsigned char *witness = NULL; size_t witness_size = 0; const unsigned char *digest_algorithm = NULL; size_t digest_algorithm_size; EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey; res = ndn_ref_tagged_BLOB(NDN_DTAG_SignatureBits, msg, co->offset[NDN_PCO_B_SignatureBits], co->offset[NDN_PCO_E_SignatureBits], &signature_bits, &signature_bits_size); if (res < 0) return (-1); if (co->offset[NDN_PCO_B_DigestAlgorithm] == co->offset[NDN_PCO_E_DigestAlgorithm]) { digest_algorithm = (const unsigned char *)NDN_SIGNING_DEFAULT_DIGEST_ALGORITHM; } else { /* figure out what algorithm the OID represents */ res = ndn_ref_tagged_string(NDN_DTAG_DigestAlgorithm, msg, co->offset[NDN_PCO_B_DigestAlgorithm], co->offset[NDN_PCO_E_DigestAlgorithm], &digest_algorithm, &digest_algorithm_size); if (res < 0) return (-1); /* NOTE: since the element closer is a 0, and the element is well formed, * the string will be null terminated */ } digest = md_from_digest_and_pkey((const char *)digest_algorithm, verification_pubkey); EVP_MD_CTX_init(ver_ctx); res = EVP_VerifyInit_ex(ver_ctx, digest, NULL); if (!res) { EVP_MD_CTX_cleanup(ver_ctx); return (-1); } if (co->offset[NDN_PCO_B_Witness] != co->offset[NDN_PCO_E_Witness]) { /* The witness is a DigestInfo, where the octet-string therein encapsulates * a sequence of [integer (origin 1 node#), sequence of [octet-string]] * where the inner octet-string is the concatenated hashes on the merkle-path */ res = ndn_ref_tagged_BLOB(NDN_DTAG_Witness, msg, co->offset[NDN_PCO_B_Witness], co->offset[NDN_PCO_E_Witness], &witness, &witness_size); if (res < 0) { EVP_MD_CTX_cleanup(ver_ctx); return (-1); } digest_info = d2i_X509_SIG(NULL, &witness, witness_size); /* digest_info->algor->algorithm->{length, data} * digest_info->digest->{length, type, data} */ /* ...2.2 is an MHT w/ SHA256 */ ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1); if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) { fprintf(stderr, "A witness is present without an MHT OID!\n"); EVP_MD_CTX_cleanup(ver_ctx); ASN1_OBJECT_free(merkle_hash_tree_oid); return (-1); } /* we're doing an MHT */ ASN1_OBJECT_free(merkle_hash_tree_oid); merkle_path_digest = EVP_sha256(); /* DER-encoded in the digest_info's digest ASN.1 octet string is the Merkle path info */ dd = digest_info->digest->data; merkle_path_info = d2i_MP_info(NULL, &dd, digest_info->digest->length); X509_SIG_free(digest_info); #ifdef DEBUG int x,h; int node = ASN1_INTEGER_get(merkle_path_info->node); int hash_count = sk_ASN1_OCTET_STRING_num(merkle_path_info->hashes); ASN1_OCTET_STRING *hash; fprintf(stderr, "A witness is present with an MHT OID\n"); fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count); for (h = 0; h < hash_count; h++) { hash = sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, h); fprintf(stderr, " hashes[%d] len = %d data = ", h, hash->length); for (x = 0; x < hash->length; x++) { fprintf(stderr, "%02x", hash->data[x]); } fprintf(stderr, "\n"); } #endif /* In the MHT signature case, we signed/verify the root hash */ root_hash_size = EVP_MD_size(merkle_path_digest); root_hash = calloc(1, root_hash_size); res = ndn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size); MP_info_free(merkle_path_info); if (res < 0) { EVP_MD_CTX_cleanup(ver_ctx); free(root_hash); return(-1); } res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size); free(root_hash); if (res == 0) { EVP_MD_CTX_cleanup(ver_ctx); return(-1); } res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey); EVP_MD_CTX_cleanup(ver_ctx); } else { /* * In the simple signature case, we signed/verify from the name through * the end of the content. */ size_t signed_size = co->offset[NDN_PCO_E_Content] - co->offset[NDN_PCO_B_Name]; res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[NDN_PCO_B_Name], signed_size); if (res == 0) { EVP_MD_CTX_cleanup(ver_ctx); return(-1); } res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey); EVP_MD_CTX_cleanup(ver_ctx); } return (res); }
inline int compare(const object& lhs, const object& rhs) { return OBJ_cmp(lhs.raw(), rhs.raw()); }
static int ref_cmp(const X509_POLICY_REF * const *a, const X509_POLICY_REF * const *b) { return OBJ_cmp((*a)->subjectDomainPolicy, (*b)->subjectDomainPolicy); }
int ccn_verify_signature(const unsigned char *msg, size_t size, const struct ccn_parsed_ContentObject *co, const struct ccn_pkey *verification_pubkey) { EVP_MD_CTX verc; EVP_MD_CTX *ver_ctx = &verc; X509_SIG *digest_info = NULL; MP_info *merkle_path_info = NULL; unsigned char *root_hash; size_t root_hash_size; int res; const EVP_MD *digest = EVP_md_null(); const EVP_MD *merkle_path_digest = EVP_md_null(); const unsigned char *signature_bits = NULL; size_t signature_bits_size = 0; const unsigned char *witness = NULL; size_t witness_size = 0; EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey; #ifdef DEBUG int x, h; #endif res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, msg, co->offset[CCN_PCO_B_SignatureBits], co->offset[CCN_PCO_E_SignatureBits], &signature_bits, &signature_bits_size); if (res < 0) return (-1); if (co->offset[CCN_PCO_B_DigestAlgorithm] == co->offset[CCN_PCO_E_DigestAlgorithm]) { digest = EVP_sha256(); } else { /* XXX - figure out what algorithm the OID represents */ fprintf(stderr, "not a DigestAlgorithm I understand right now\n"); return (-1); } EVP_MD_CTX_init(ver_ctx); res = EVP_VerifyInit_ex(ver_ctx, digest, NULL); if (!res) return (-1); if (co->offset[CCN_PCO_B_Witness] != co->offset[CCN_PCO_E_Witness]) { /* The witness is a DigestInfo, where the octet-string therein encapsulates * a sequence of [integer (origin 1 node#), sequence of [octet-string]] * where the inner octet-string is the concatenated hashes on the merkle-path */ res = ccn_ref_tagged_BLOB(CCN_DTAG_Witness, msg, co->offset[CCN_PCO_B_Witness], co->offset[CCN_PCO_E_Witness], &witness, &witness_size); if (res < 0) return (-1); digest_info = d2i_X509_SIG(NULL, &witness, witness_size); /* digest_info->algor->algorithm->{length, data} * digest_info->digest->{length, type, data} */ /* ...2.2 is an MHT w/ SHA256 */ ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1); if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) { fprintf(stderr, "A witness is present without an MHT OID!\n"); ASN1_OBJECT_free(merkle_hash_tree_oid); return (-1); } /* we're doing an MHT */ ASN1_OBJECT_free(merkle_hash_tree_oid); merkle_path_digest = EVP_sha256(); /* DER-encoded in the digest_info's digest ASN.1 octet string is the Merkle path info */ merkle_path_info = d2i_MP_info(NULL, (const unsigned char **)&(digest_info->digest->data), digest_info->digest->length); #ifdef DEBUG int node = ASN1_INTEGER_get(merkle_path_info->node); int hash_count = merkle_path_info->hashes->num; ASN1_OCTET_STRING *hash; fprintf(stderr, "A witness is present with an MHT OID\n"); fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count); for (h = 0; h < hash_count; h++) { hash = (ASN1_OCTET_STRING *)merkle_path_info->hashes->data[h]; fprintf(stderr, " hashes[%d] len = %d data = ", h, hash->length); for (x = 0; x < hash->length; x++) { fprintf(stderr, "%02x", hash->data[x]); } fprintf(stderr, "\n"); } #endif /* In the MHT signature case, we signed/verify the root hash */ root_hash_size = EVP_MD_size(merkle_path_digest); root_hash = calloc(1, root_hash_size); res = ccn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size); res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size); res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey); EVP_MD_CTX_cleanup(ver_ctx); } else { /* * In the simple signature case, we signed/verify from the name through * the end of the content. */ size_t signed_size = co->offset[CCN_PCO_E_Content] - co->offset[CCN_PCO_B_Name]; res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[CCN_PCO_B_Name], signed_size); res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey); EVP_MD_CTX_cleanup(ver_ctx); } if (res == 1) return (1); else return (0); }
int main(int argc, char **argv) { int debug=0; int verify=0; int mismatch=0; char *program; int badops=0; char *certfile=NULL; char *out1file=NULL; char *out2file=NULL; char *home=NULL; char *pin=NULL; char *argp; char *ss; BIO *bio_err; X509 *ucert; FILE *fp; FILE *fpout; #ifdef USE_PKCS11 CK_SESSION_HANDLE hSession = 0; #endif #ifdef WIN32 CRYPTO_malloc_init(); #endif ERR_load_prxyerr_strings(0); SSLeay_add_ssl_algorithms(); if ((bio_err=BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_err,stderr,BIO_NOCLOSE); } program=argv[0]; argc--; argv++; while (argc >= 1) { argp = *argv; if ( *argp == '-' && *(argp+1) == '-') { argp++; } if (strcmp(argp,"-debug") == 0) { debug++; } else if (strcmp(argp,"-cert") == 0) { if (--argc < 1) goto bad; certfile=*(++argv); } else if (strcmp(argp,"-out1") == 0) { if (--argc < 1) goto bad; out1file=*(++argv); } else if (strcmp(argp,"-out2") == 0) { if (--argc < 1) goto bad; out2file=*(++argv); } else if (strcmp(argp,"-help") == 0) { badops=1; break; } else { fprintf(stderr,_GGSL("unknown option %s\n"),*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: fprintf(stderr,_GGSL("%s [options]\n"),program); fprintf(stderr,_GGSL("where options are\n")); fprintf(stderr,_GGSL(" --help show this list\n")); fprintf(stderr,_GGSL(" --debug set debugging on\n")); fprintf(stderr,_GGSL(" --cert file name of long term certificate\n")); fprintf(stderr,_GGSL(" --out1 file name for name\n")); fprintf(stderr,_GGSL(" --out2 file name for commonName\n"); exit(1); } home = (char *)getenv("HOME"); if (home == NULL) { #ifndef WIN32 fprintf(stderr,_GGSL("$HOME not defined")); exit(1); #else home = "c:\\windows"; #endif } if (!strncmp(certfile,"SC:",3)) { #ifdef USE_PKCS11 char *cp; char *kp; int rc; cp = certfile + 3; kp = strchr(cp,':'); if (kp == NULL) { fprintf(stderr,_GGSL("Bad format of cert name, SC:card:cert\n")); exit (2); } kp++; /* skip the : */ if (hSession == 0) { rc = sc_init(&hSession, cp, NULL, pin, CKU_USER, 0); if (rc) { fprintf(stderr,_GGSL("Failed to open card session\n")); ERR_print_errors_fp (stderr); exit(2); } } rc = sc_get_cert_obj_by_label(hSession,kp,&ucert); if (rc) { fprintf(stderr,_GGSL("Failed to find certificate on card \n")); ERR_print_errors_fp (stderr); exit(2); } #else fprintf(stderr,_GGSL("Smart card support not compiled with this program\n")); exit (2); #endif /* USE_PKCS11 */ } else { fp = fopen (certfile, "r"); if (fp == NULL) { fprintf(stderr,_GGSL(" failed to open %s\n",certfile)); exit (1); } ucert = PEM_read_X509 (fp, NULL, OPENSSL_PEM_CB(NULL, NULL)); fclose (fp); } if (ucert == NULL) { ERR_print_errors_fp (stderr); exit (1); } if (out1file) { if (strcmp("-",out1file)) { fpout=fopen(out1file,"w"); } else { fpout = stdout; } if (fpout == NULL) { fprintf (stderr,"Unable to open out1 file:%s\n", out1file); exit(4); } ss = X509_NAME_oneline(ucert->cert_info->subject,NULL,0); while (1) { if (!strcmp(ss+strlen(ss)-strlen("/CN=limited proxy"), "/CN=limited proxy")) { *(ss+strlen(ss)-strlen("/CN=limited proxy"))= '\0'; } else if (!strcmp(ss+strlen(ss)-strlen("/CN=proxy"), "/CN=proxy")) { *(ss+strlen(ss)-strlen("/CN=proxy")) = '\0'; } else { break; } } fprintf(fpout,"%s\n",ss); OPENSSL_free(ss); if (fpout != stdout) { fclose(fpout); } } if (out2file) { if (strcmp("-",out2file)) { fpout=fopen(out2file,"w"); } else { fpout = stdout; } if (fpout == NULL) { fprintf (stderr,"Unable to open out2 file:%s\n", out2file); exit(4); } { X509_NAME *subject; X509_NAME_ENTRY *ne; ASN1_STRING *data; X509_NAME_ENTRY *o = NULL; X509_NAME_ENTRY *ou1 = NULL; X509_NAME_ENTRY *ou2 = NULL; int i; subject=X509_get_subject_name(ucert); i = X509_NAME_entry_count(subject)-1; while (i > 0) { ne=X509_NAME_get_entry(subject,i); if (!OBJ_cmp(ne->object, OBJ_nid2obj(NID_organizationName))) { if (!o) { o = ne; } } if (!OBJ_cmp(ne->object, OBJ_nid2obj(NID_organizationalUnitName))) { if (ou2) { ou1 = ne; } else { ou2 = ne; } } if (!OBJ_cmp(ne->object, OBJ_nid2obj(NID_commonName))) { data=X509_NAME_ENTRY_get_data(ne); if ((data->length == 5 && !memcmp(data->data,"proxy",5)) || (data->length == 13 && !memcmp(data->data,"limited proxy",13))) { i--; continue; } fprintf(fpout,"%.*s\n",data->length,data->data); /* break; */ } i--; } if (o) { data=X509_NAME_ENTRY_get_data(o); fprintf(fpout,"%.*s\n",data->length,data->data); } if (ou1) { data=X509_NAME_ENTRY_get_data(ou1); fprintf(fpout,"%.*s\n",data->length,data->data); } if (ou2) { data=X509_NAME_ENTRY_get_data(ou2); fprintf(fpout,"%.*s\n",data->length,data->data); } } /* inline section */ if (fpout != stdout) { fclose(fpout); } } /* out2file */ return 0; }
static int tlso_session_chkhost( LDAP *ld, tls_session *sess, const char *name_in ) { tlso_session *s = (tlso_session *)sess; int i, ret = LDAP_LOCAL_ERROR; X509 *x; const char *name; char *ptr; int ntype = IS_DNS, nlen; #ifdef LDAP_PF_INET6 struct in6_addr addr; #else struct in_addr addr; #endif if( ldap_int_hostname && ( !name_in || !strcasecmp( name_in, "localhost" ) ) ) { name = ldap_int_hostname; } else { name = name_in; } nlen = strlen(name); x = tlso_get_cert(s); if (!x) { Debug( LDAP_DEBUG_ANY, "TLS: unable to get peer certificate.\n", 0, 0, 0 ); /* If this was a fatal condition, things would have * aborted long before now. */ return LDAP_SUCCESS; } #ifdef LDAP_PF_INET6 if (inet_pton(AF_INET6, name, &addr)) { ntype = IS_IP6; } else #endif if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) { if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4; } i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1); if (i >= 0) { X509_EXTENSION *ex; STACK_OF(GENERAL_NAME) *alt; ex = X509_get_ext(x, i); alt = X509V3_EXT_d2i(ex); if (alt) { int n, len2 = 0; char *domain = NULL; GENERAL_NAME *gn; if (ntype == IS_DNS) { domain = strchr(name, '.'); if (domain) { len2 = nlen - (domain-name); } } n = sk_GENERAL_NAME_num(alt); for (i=0; i<n; i++) { char *sn; int sl; gn = sk_GENERAL_NAME_value(alt, i); if (gn->type == GEN_DNS) { if (ntype != IS_DNS) continue; sn = (char *) ASN1_STRING_data(gn->d.ia5); sl = ASN1_STRING_length(gn->d.ia5); /* ignore empty */ if (sl == 0) continue; /* Is this an exact match? */ if ((nlen == sl) && !strncasecmp(name, sn, nlen)) { break; } /* Is this a wildcard match? */ if (domain && (sn[0] == '*') && (sn[1] == '.') && (len2 == sl-1) && !strncasecmp(domain, &sn[1], len2)) { break; } } else if (gn->type == GEN_IPADD) { if (ntype == IS_DNS) continue; sn = (char *) ASN1_STRING_data(gn->d.ia5); sl = ASN1_STRING_length(gn->d.ia5); #ifdef LDAP_PF_INET6 if (ntype == IS_IP6 && sl != sizeof(struct in6_addr)) { continue; } else #endif if (ntype == IS_IP4 && sl != sizeof(struct in_addr)) { continue; } if (!memcmp(sn, &addr, sl)) { break; } } } GENERAL_NAMES_free(alt); if (i < n) { /* Found a match */ ret = LDAP_SUCCESS; } } } if (ret != LDAP_SUCCESS) { X509_NAME *xn; X509_NAME_ENTRY *ne; ASN1_OBJECT *obj; ASN1_STRING *cn = NULL; int navas; /* find the last CN */ obj = OBJ_nid2obj( NID_commonName ); if ( !obj ) goto no_cn; /* should never happen */ xn = X509_get_subject_name(x); navas = X509_NAME_entry_count( xn ); for ( i=navas-1; i>=0; i-- ) { ne = X509_NAME_get_entry( xn, i ); if ( !OBJ_cmp( X509_NAME_ENTRY_get_object(ne), obj )) { cn = X509_NAME_ENTRY_get_data( ne ); break; } } if( !cn ) { no_cn: Debug( LDAP_DEBUG_ANY, "TLS: unable to get common name from peer certificate.\n", 0, 0, 0 ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: unable to get CN from peer certificate")); } else if ( cn->length == nlen && strncasecmp( name, (char *) cn->data, nlen ) == 0 ) { ret = LDAP_SUCCESS; } else if (( cn->data[0] == '*' ) && ( cn->data[1] == '.' )) { char *domain = strchr(name, '.'); if( domain ) { int dlen; dlen = nlen - (domain-name); /* Is this a wildcard match? */ if ((dlen == cn->length-1) && !strncasecmp(domain, (char *) &cn->data[1], dlen)) { ret = LDAP_SUCCESS; } } } if( ret == LDAP_LOCAL_ERROR ) { Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " "common name in certificate (%.*s).\n", name, cn->length, cn->data ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: hostname does not match CN in peer certificate")); } } X509_free(x); return ret; }
static int obj_cmp(const ASN1_OBJECT * const *a, const ASN1_OBJECT * const *b) { return OBJ_cmp(*a, *b); }
static void CheckEKU(X509 *x509, CertType type) { int idx = -1; bool first = true; do { int critical = -1; EXTENDED_KEY_USAGE *ekus = X509_get_ext_d2i(x509, NID_ext_key_usage, &critical, &idx); if (ekus == NULL) { if (critical >= 0) { /* Found but fails to parse */ SetError(ERR_INVALID); continue; } /* Not found */ if (first) { SetCertInfo(CERT_INFO_NO_EKU); if (type == SubscriberCertificate) { SetWarning(WARN_NO_EKU); } } break; } first = false; if (type == RootCA) { /* CAB 7.1.2.1d */ SetError(ERR_ROOT_CA_WITH_EKU); } for (int i = 0; i < sk_ASN1_OBJECT_num(ekus); i++) { ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(ekus, i); int nid = OBJ_obj2nid(oid); if (OBJ_cmp(oid, obj_anyEKU) == 0) { SetCertInfo(CERT_INFO_ANY_EKU); } else if (nid == NID_server_auth) { SetCertInfo(CERT_INFO_SERV_AUTH); } else if (nid == NID_client_auth) { SetCertInfo(CERT_INFO_CLIENT_AUTH); } else if (nid == NID_code_sign) { SetCertInfo(CERT_INFO_CODE_SIGN); } else if (nid == NID_email_protect) { SetCertInfo(CERT_INFO_EMAIL); } else if (nid == NID_time_stamp) { SetCertInfo(CERT_INFO_TIME_STAMP); } else if (nid == NID_OCSP_sign) { SetCertInfo(CERT_INFO_OCSP_SIGN); } else if (OBJ_cmp(oid, obj_IntelAMTvProEKU) == 0) { SetCertInfo(CERT_INFO_AMTVPRO_EKU); } else { SetWarning(WARN_UNKNOWN_EKU); } } if (GetBit(cert_info, CERT_INFO_AMTVPRO_EKU) && !GetBit(cert_info, CERT_INFO_SERV_AUTH)) { SetError(ERR_MISSING_EKU); } if (sk_ASN1_OBJECT_num(ekus) == 0) { SetError(ERR_EMPTY_EKU); } sk_ASN1_OBJECT_pop_free(ekus, ASN1_OBJECT_free); } while (1); }
static int policy_data_cmp(const X509_POLICY_DATA **a, const X509_POLICY_DATA **b) { return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy); }
static void CheckNameEntryValid(X509_NAME_ENTRY *ne) { ASN1_STRING *data = X509_NAME_ENTRY_get_data(ne); ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object(ne); int nid = OBJ_obj2nid(obj); size_t char_len; if (CheckStringValid(data, &char_len)) { bool bChecked = false; for (size_t i = 0; i < sizeof(size_limits)/sizeof(size_limits[0]); i++) { if (OBJ_cmp(*size_limits[i].obj, obj) == 0) { if (char_len > size_limits[i].max || char_len < size_limits[i].min) { SetError(size_limits[i].error); } bChecked = true; break; } } if (!bChecked) { SetInfo(INF_NAME_ENTRY_LENGTH_NOT_CHECKED); } } if (nid == NID_pkcs9_emailAddress || nid == NID_domainComponent) { if (data->type != V_ASN1_IA5STRING) { SetError(ERR_INVALID_NAME_ENTRY_TYPE); } } else if (nid == NID_pkcs9_unstructuredName && data->type == V_ASN1_IA5STRING) { /* PKCS#9 unstructuredName may be IA5String or DirectoryString */ } else { /* It should be a DirectoryString, which is one of the below */ if ((data->type != V_ASN1_PRINTABLESTRING) && (data->type != V_ASN1_UTF8STRING) && (data->type != V_ASN1_T61STRING) && (data->type != V_ASN1_UNIVERSALSTRING) && (data->type != V_ASN1_BMPSTRING)) { SetError(ERR_INVALID_NAME_ENTRY_TYPE); } else if ((data->type != V_ASN1_PRINTABLESTRING) && (data->type != V_ASN1_UTF8STRING)) { /* RFC5280 says it MUST be PrintableString or UTF8String, with exceptions. */ SetWarning(WARN_NON_PRINTABLE_STRING); } } if (nid == NID_countryName && data->type != V_ASN1_PRINTABLESTRING) { SetError(ERR_INVALID_NAME_ENTRY_TYPE); } if (nid == NID_dnQualifier && data->type != V_ASN1_PRINTABLESTRING) { SetError(ERR_INVALID_NAME_ENTRY_TYPE); } if (nid == NID_serialNumber && data->type != V_ASN1_PRINTABLESTRING) { SetError(ERR_INVALID_NAME_ENTRY_TYPE); } return; }
static void CheckSAN(X509 *x509, CertType type) { int idx = -1; bool bSanFound = false; bool bSanName = false; bool bSanRequired = false; bool bCommonNameFound = false; ASN1_STRING *commonName = NULL; enum { SAN_TYPE_NOT_ALLOWED, SAN_TYPE_ALLOWED, SAN_TYPE_WARN } name_type_allowed[GEN_RID+1]; for (int i = 0; i < GEN_RID+1; i++) { name_type_allowed[i] = SAN_TYPE_NOT_ALLOWED; } if (GetBit(cert_info, CERT_INFO_SERV_AUTH) || GetBit(cert_info, CERT_INFO_ANY_EKU) || GetBit(cert_info, CERT_INFO_NO_EKU)) { name_type_allowed[GEN_DNS] = SAN_TYPE_ALLOWED; name_type_allowed[GEN_IPADD] = SAN_TYPE_ALLOWED; bSanRequired = true; } if (GetBit(cert_info, CERT_INFO_EMAIL) || GetBit(cert_info, CERT_INFO_ANY_EKU) || GetBit(cert_info, CERT_INFO_NO_EKU)) { name_type_allowed[GEN_EMAIL] = SAN_TYPE_ALLOWED; bSanRequired = true; } if (GetBit(cert_info, CERT_INFO_CLIENT_AUTH)) { /* * DNS and IP address doesn't make sense for a TLS client that * doesn't also do server authentication. */ if (name_type_allowed[GEN_DNS] == SAN_TYPE_NOT_ALLOWED) { name_type_allowed[GEN_DNS] = SAN_TYPE_WARN; name_type_allowed[GEN_IPADD] = SAN_TYPE_WARN; } name_type_allowed[GEN_EMAIL] = SAN_TYPE_ALLOWED; } if (GetBit(warnings, WARN_UNKNOWN_EKU) && !GetBit(cert_info, CERT_INFO_SERV_AUTH) && !GetBit(cert_info, CERT_INFO_ANY_EKU)) { /* * If it's a certificate with an unknown EKU that isn't * also valid for server auth, allow the other types */ name_type_allowed[GEN_OTHERNAME] = SAN_TYPE_ALLOWED; name_type_allowed[GEN_X400] = SAN_TYPE_ALLOWED; name_type_allowed[GEN_EDIPARTY] = SAN_TYPE_ALLOWED; name_type_allowed[GEN_URI] = SAN_TYPE_ALLOWED; } X509_NAME *subject = X509_get_subject_name(x509); for (int i = 0; i < X509_NAME_entry_count(subject); i++) { X509_NAME_ENTRY *ne = X509_NAME_get_entry(subject, i); ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object(ne); if (OBJ_cmp(obj_commonName, obj) == 0) { commonName = X509_NAME_ENTRY_get_data(ne); break; } } do { int critical = -1; GENERAL_NAMES *names = X509_get_ext_d2i(x509, NID_subject_alt_name, &critical, &idx); if (names == NULL) { if (critical >= 0) { /* Found but fails to parse */ SetError(ERR_INVALID); bSanFound = true; continue; } /* Not found */ break; } for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) { GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i); int type; ASN1_STRING *name_s = GENERAL_NAME_get0_value(name, &type); if (type > GEN_RID || type < 0) { SetError(ERR_INVALID); } else if (name_type_allowed[type] == SAN_TYPE_NOT_ALLOWED) { SetError(ERR_SAN_TYPE); } else if (name_type_allowed[type] == SAN_TYPE_WARN) { SetWarning(WARN_TLS_CLIENT_DNS); } if (type == GEN_DNS) { for (int j = i+1; j < sk_GENERAL_NAME_num(names); j++) { GENERAL_NAME *name2 = sk_GENERAL_NAME_value(names, j); int type2; ASN1_STRING *name2_s = GENERAL_NAME_get0_value(name2, &type2); if (type == type2 && ASN1_STRING_cmpcase(name_s, name2_s) == 0) { SetWarning(WARN_DUPLICATE_SAN); } } char *s = malloc(name_s->length + 1); strncpy(s, (char *)name_s->data, name_s->length); s[name_s->length] = '\0'; unsigned char buf[sizeof(struct in6_addr)]; if (inet_pton(AF_INET, s, buf) == 1 || inet_pton(AF_INET6, s, buf) == 1) { SetError(ERR_IP_IN_DNSNAME); } free(s); } if ((type == GEN_DNS || type == GEN_EMAIL) && commonName != NULL) { if (ASN1_STRING_cmpcase(name_s, commonName) == 0) { bCommonNameFound = true; } } if (type == GEN_IPADD) { int af = AF_UNSPEC; if (name_s->length == 4) { af = AF_INET; } else if (name_s->length == 16) { af = AF_INET6; } else { SetError(ERR_IP_FAMILY); } if (af != AF_UNSPEC && commonName != NULL) { unsigned char buf[sizeof(struct in6_addr)]; char *s = malloc(commonName->length + 1); strncpy(s, (char *)commonName->data, commonName->length); s[commonName->length] = '\0'; inet_pton(af, s, buf); /* We want to compare them binary, the string version is not standard. */ if (memcmp(buf, name_s->data, name_s->length) == 0) { bCommonNameFound = true; } free(s); } } CheckGeneralNameType(name); bSanName = true; } sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); bSanFound = true; } while (1); if (!bSanFound && bSanRequired) { /* Required by CAB base 7.1.4.2.1 */ if (type == SubscriberCertificate) { SetError(ERR_NO_SUBJECT_ALT_NAME); } } if (bSanFound && !bSanName) { SetError(ERR_SAN_WITHOUT_NAME); } if (commonName != NULL && bSanFound && !bCommonNameFound) { // SetError(ERR_CN_NOT_IN_SAN); } }