123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- * certhtml.c --- convert a cert to html
- */
- #include "seccomon.h"
- #include "secitem.h"
- #include "sechash.h"
- #include "cert.h"
- #include "keyhi.h"
- #include "secder.h"
- #include "prprf.h"
- #include "secport.h"
- #include "secasn1.h"
- #include "pk11func.h"
- static char *hex = "0123456789ABCDEF";
- /*
- ** Convert a der-encoded integer to a hex printable string form
- */
- char *
- CERT_Hexify(SECItem *i, int do_colon)
- {
- unsigned char *cp, *end;
- char *rv, *o;
- if (!i->len) {
- return PORT_Strdup("00");
- }
- rv = o = (char *)PORT_Alloc(i->len * 3);
- if (!rv)
- return rv;
- cp = i->data;
- end = cp + i->len;
- while (cp < end) {
- unsigned char ch = *cp++;
- *o++ = hex[(ch >> 4) & 0xf];
- *o++ = hex[ch & 0xf];
- if (cp != end) {
- if (do_colon) {
- *o++ = ':';
- }
- }
- }
- *o = 0; /* Null terminate the string */
- return rv;
- }
- #define BREAK "<br>"
- #define BREAKLEN 4
- #define COMMA ", "
- #define COMMALEN 2
- #define MAX_OUS 20
- #define MAX_DC MAX_OUS
- 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;
- // cn will always have BREAK after it
- len += BREAKLEN;
- break;
- case SEC_OID_AVA_COUNTRY_NAME:
- if (country) {
- break;
- }
- country = CERT_DecodeAVAValue(&ava->value);
- if (!country) {
- goto loser;
- }
- len += country->len;
- // country may have COMMA after it (if we over-count len,
- // that's fine - we'll just allocate a buffer larger than we
- // need)
- len += COMMALEN;
- break;
- case SEC_OID_AVA_LOCALITY:
- if (loc) {
- break;
- }
- loc = CERT_DecodeAVAValue(&ava->value);
- if (!loc) {
- goto loser;
- }
- len += loc->len;
- // loc may have COMMA after it
- len += COMMALEN;
- break;
- case SEC_OID_AVA_STATE_OR_PROVINCE:
- if (state) {
- break;
- }
- state = CERT_DecodeAVAValue(&ava->value);
- if (!state) {
- goto loser;
- }
- len += state->len;
- // state currently won't have COMMA after it, but this is a
- // (probably vain) attempt to future-proof this code
- len += COMMALEN;
- break;
- case SEC_OID_AVA_ORGANIZATION_NAME:
- if (org) {
- break;
- }
- org = CERT_DecodeAVAValue(&ava->value);
- if (!org) {
- goto loser;
- }
- len += org->len;
- // org will have BREAK after it
- len += BREAKLEN;
- break;
- case SEC_OID_AVA_DN_QUALIFIER:
- if (dq) {
- break;
- }
- dq = CERT_DecodeAVAValue(&ava->value);
- if (!dq) {
- goto loser;
- }
- len += dq->len;
- // dq will have BREAK after it
- len += BREAKLEN;
- 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;
- // each ou will have BREAK after it
- len += BREAKLEN;
- }
- 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;
- // each dc will have BREAK after it
- len += BREAKLEN;
- }
- 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;
- // email will have BREAK after it
- len += BREAKLEN;
- break;
- default:
- break;
- }
- }
- }
- // there may be a final BREAK
- len += BREAKLEN;
- /* 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);
- }
|