static SECComparison _NSSCPY_CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b) { SECComparison rv; rv = SECITEM_CompareItem(&a->type, &b->type); if (SECEqual != rv) return rv; /* Attribute types don't match. */ /* Let's be optimistic. Maybe the values will just compare equal. */ rv = SECITEM_CompareItem(&a->value, &b->value); if (SECEqual == rv) return rv; /* values compared exactly. */ if (a->value.len && a->value.data && b->value.len && b->value.data) { /* Here, the values did not match. ** If the values had different encodings, convert them to the same ** encoding and compare that way. */ if (a->value.data[0] != b->value.data[0]) { /* encodings differ. Convert both to UTF-8 and compare. */ SECItem * aVal = CERT_DecodeAVAValue(&a->value); SECItem * bVal = CERT_DecodeAVAValue(&b->value); if (aVal && aVal->len && aVal->data && bVal && bVal->len && bVal->data) { rv = SECITEM_CompareItem(aVal, bVal); } SECITEM_FreeItem(aVal, PR_TRUE); SECITEM_FreeItem(bVal, PR_TRUE); } else if (a->value.data[0] == 0x13) { /* both are printable strings. */ /* printable strings */ rv = _NSSCPY_CERT_CompareDERPrintableStrings(&a->value, &b->value); } } return rv; }
/* SECItems a and b contain DER-encoded printable strings. */ static SECComparison _NSSCPY_CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b) { SECComparison rv = SECLessThan; SECItem * aVal = CERT_DecodeAVAValue(a); SECItem * bVal = CERT_DecodeAVAValue(b); if (aVal && aVal->len && aVal->data && bVal && bVal->len && bVal->data) { _NSSCPY_canonicalize(aVal); _NSSCPY_canonicalize(bVal); rv = SECITEM_CompareItem(aVal, bVal); } SECITEM_FreeItem(aVal, PR_TRUE); SECITEM_FreeItem(bVal, PR_TRUE); return rv; }
/* helper functions */ static void BIO_printf_CERTName(BIO *out, CERTName *cn, const char *msg) { CERTRDN **rdns; if (!cn) return; rdns = cn->rdns; if (!rdns) return; for (; *rdns; rdns++) { CERTAVA **avas = (*rdns)->avas; if (!avas) continue; for (; *avas; avas++) { CERTAVA *ava = *avas; BIO_printf(out, "%s", msg); { int tag = /*SECOidTag*/ CERT_GetAVATag(ava); const char* code; switch (tag) { case -1: code = "<unknown>"; break; case 31: code = "E"; break; case 41: code = "CN"; break; case 42: code = "C"; break; case 43: code = "L"; break; case 44: code = "ST"; break; case 45: code = "O"; break; case 46: code = "OU"; break; case 261: code = "SN"; break; case 262: code = "serialNumber"; break; case 268: code = "givenName"; break; default: code = "<?>"; break; } BIO_printf(out, "%s = ", code); } { SECItem *si_utf8; si_utf8 = CERT_DecodeAVAValue(&ava->value); BIO_printf(out, "'%.*s'\n", si_utf8->len, si_utf8->data); SECITEM_FreeItem(si_utf8, PR_TRUE); } } } }
char *CERT_FormatName (CERTName *name) { CERTRDN** rdns; CERTRDN * rdn; CERTAVA** avas; CERTAVA* ava; char * buf = 0; char * tmpbuf = 0; SECItem * cn = 0; SECItem * email = 0; SECItem * org = 0; SECItem * loc = 0; SECItem * state = 0; SECItem * country = 0; SECItem * dq = 0; unsigned len = 0; int tag; int i; int ou_count = 0; int dc_count = 0; PRBool first; SECItem * orgunit[MAX_OUS]; SECItem * dc[MAX_DC]; /* Loop over name components and gather the interesting ones */ rdns = name->rdns; while ((rdn = *rdns++) != 0) { avas = rdn->avas; while ((ava = *avas++) != 0) { tag = CERT_GetAVATag(ava); switch(tag) { case SEC_OID_AVA_COMMON_NAME: if (cn) { break; } cn = CERT_DecodeAVAValue(&ava->value); if (!cn) { goto loser; } len += cn->len; break; case SEC_OID_AVA_COUNTRY_NAME: if (country) { break; } country = CERT_DecodeAVAValue(&ava->value); if (!country) { goto loser; } len += country->len; break; case SEC_OID_AVA_LOCALITY: if (loc) { break; } loc = CERT_DecodeAVAValue(&ava->value); if (!loc) { goto loser; } len += loc->len; break; case SEC_OID_AVA_STATE_OR_PROVINCE: if (state) { break; } state = CERT_DecodeAVAValue(&ava->value); if (!state) { goto loser; } len += state->len; break; case SEC_OID_AVA_ORGANIZATION_NAME: if (org) { break; } org = CERT_DecodeAVAValue(&ava->value); if (!org) { goto loser; } len += org->len; break; case SEC_OID_AVA_DN_QUALIFIER: if (dq) { break; } dq = CERT_DecodeAVAValue(&ava->value); if (!dq) { goto loser; } len += dq->len; break; case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME: if (ou_count < MAX_OUS) { orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value); if (!orgunit[ou_count]) { goto loser; } len += orgunit[ou_count++]->len; } break; case SEC_OID_AVA_DC: if (dc_count < MAX_DC) { dc[dc_count] = CERT_DecodeAVAValue(&ava->value); if (!dc[dc_count]) { goto loser; } len += dc[dc_count++]->len; } break; case SEC_OID_PKCS9_EMAIL_ADDRESS: case SEC_OID_RFC1274_MAIL: if (email) { break; } email = CERT_DecodeAVAValue(&ava->value); if (!email) { goto loser; } len += email->len; break; default: break; } } } /* XXX - add some for formatting */ len += 128; /* allocate buffer */ buf = (char *)PORT_Alloc(len); if ( !buf ) { goto loser; } tmpbuf = buf; if ( cn ) { PORT_Memcpy(tmpbuf, cn->data, cn->len); tmpbuf += cn->len; PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } if ( email ) { PORT_Memcpy(tmpbuf, email->data, email->len); tmpbuf += ( email->len ); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } for (i=ou_count-1; i >= 0; i--) { PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len); tmpbuf += ( orgunit[i]->len ); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } if ( dq ) { PORT_Memcpy(tmpbuf, dq->data, dq->len); tmpbuf += ( dq->len ); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } if ( org ) { PORT_Memcpy(tmpbuf, org->data, org->len); tmpbuf += ( org->len ); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } for (i=dc_count-1; i >= 0; i--) { PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len); tmpbuf += ( dc[i]->len ); PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } first = PR_TRUE; if ( loc ) { PORT_Memcpy(tmpbuf, loc->data, loc->len); tmpbuf += ( loc->len ); first = PR_FALSE; } if ( state ) { if ( !first ) { PORT_Memcpy(tmpbuf, COMMA, COMMALEN); tmpbuf += COMMALEN; } PORT_Memcpy(tmpbuf, state->data, state->len); tmpbuf += ( state->len ); first = PR_FALSE; } if ( country ) { if ( !first ) { PORT_Memcpy(tmpbuf, COMMA, COMMALEN); tmpbuf += COMMALEN; } PORT_Memcpy(tmpbuf, country->data, country->len); tmpbuf += ( country->len ); first = PR_FALSE; } if ( !first ) { PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); tmpbuf += BREAKLEN; } *tmpbuf = 0; /* fall through and clean */ loser: if ( cn ) { SECITEM_FreeItem(cn, PR_TRUE); } if ( email ) { SECITEM_FreeItem(email, PR_TRUE); } for (i=ou_count-1; i >= 0; i--) { SECITEM_FreeItem(orgunit[i], PR_TRUE); } if ( dq ) { SECITEM_FreeItem(dq, PR_TRUE); } if ( org ) { SECITEM_FreeItem(org, PR_TRUE); } for (i=dc_count-1; i >= 0; i--) { SECITEM_FreeItem(dc[i], PR_TRUE); } if ( loc ) { SECITEM_FreeItem(loc, PR_TRUE); } if ( state ) { SECITEM_FreeItem(state, PR_TRUE); } if ( country ) { SECITEM_FreeItem(country, PR_TRUE); } return(buf); }