michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * certhtml.c --- convert a cert to html michael@0: */ michael@0: michael@0: #include "seccomon.h" michael@0: #include "secitem.h" michael@0: #include "sechash.h" michael@0: #include "cert.h" michael@0: #include "keyhi.h" michael@0: #include "secder.h" michael@0: #include "prprf.h" michael@0: #include "secport.h" michael@0: #include "secasn1.h" michael@0: #include "pk11func.h" michael@0: michael@0: static char *hex = "0123456789ABCDEF"; michael@0: michael@0: /* michael@0: ** Convert a der-encoded integer to a hex printable string form michael@0: */ michael@0: char *CERT_Hexify (SECItem *i, int do_colon) michael@0: { michael@0: unsigned char *cp, *end; michael@0: char *rv, *o; michael@0: michael@0: if (!i->len) { michael@0: return PORT_Strdup("00"); michael@0: } michael@0: michael@0: rv = o = (char*) PORT_Alloc(i->len * 3); michael@0: if (!rv) return rv; michael@0: michael@0: cp = i->data; michael@0: end = cp + i->len; michael@0: while (cp < end) { michael@0: unsigned char ch = *cp++; michael@0: *o++ = hex[(ch >> 4) & 0xf]; michael@0: *o++ = hex[ch & 0xf]; michael@0: if (cp != end) { michael@0: if (do_colon) { michael@0: *o++ = ':'; michael@0: } michael@0: } michael@0: } michael@0: *o = 0; /* Null terminate the string */ michael@0: return rv; michael@0: } michael@0: michael@0: #define BREAK "
" michael@0: #define BREAKLEN 4 michael@0: #define COMMA ", " michael@0: #define COMMALEN 2 michael@0: michael@0: #define MAX_OUS 20 michael@0: #define MAX_DC MAX_OUS michael@0: michael@0: michael@0: char *CERT_FormatName (CERTName *name) michael@0: { michael@0: CERTRDN** rdns; michael@0: CERTRDN * rdn; michael@0: CERTAVA** avas; michael@0: CERTAVA* ava; michael@0: char * buf = 0; michael@0: char * tmpbuf = 0; michael@0: SECItem * cn = 0; michael@0: SECItem * email = 0; michael@0: SECItem * org = 0; michael@0: SECItem * loc = 0; michael@0: SECItem * state = 0; michael@0: SECItem * country = 0; michael@0: SECItem * dq = 0; michael@0: michael@0: unsigned len = 0; michael@0: int tag; michael@0: int i; michael@0: int ou_count = 0; michael@0: int dc_count = 0; michael@0: PRBool first; michael@0: SECItem * orgunit[MAX_OUS]; michael@0: SECItem * dc[MAX_DC]; michael@0: michael@0: /* Loop over name components and gather the interesting ones */ michael@0: rdns = name->rdns; michael@0: while ((rdn = *rdns++) != 0) { michael@0: avas = rdn->avas; michael@0: while ((ava = *avas++) != 0) { michael@0: tag = CERT_GetAVATag(ava); michael@0: switch(tag) { michael@0: case SEC_OID_AVA_COMMON_NAME: michael@0: if (cn) { michael@0: break; michael@0: } michael@0: cn = CERT_DecodeAVAValue(&ava->value); michael@0: if (!cn) { michael@0: goto loser; michael@0: } michael@0: len += cn->len; michael@0: break; michael@0: case SEC_OID_AVA_COUNTRY_NAME: michael@0: if (country) { michael@0: break; michael@0: } michael@0: country = CERT_DecodeAVAValue(&ava->value); michael@0: if (!country) { michael@0: goto loser; michael@0: } michael@0: len += country->len; michael@0: break; michael@0: case SEC_OID_AVA_LOCALITY: michael@0: if (loc) { michael@0: break; michael@0: } michael@0: loc = CERT_DecodeAVAValue(&ava->value); michael@0: if (!loc) { michael@0: goto loser; michael@0: } michael@0: len += loc->len; michael@0: break; michael@0: case SEC_OID_AVA_STATE_OR_PROVINCE: michael@0: if (state) { michael@0: break; michael@0: } michael@0: state = CERT_DecodeAVAValue(&ava->value); michael@0: if (!state) { michael@0: goto loser; michael@0: } michael@0: len += state->len; michael@0: break; michael@0: case SEC_OID_AVA_ORGANIZATION_NAME: michael@0: if (org) { michael@0: break; michael@0: } michael@0: org = CERT_DecodeAVAValue(&ava->value); michael@0: if (!org) { michael@0: goto loser; michael@0: } michael@0: len += org->len; michael@0: break; michael@0: case SEC_OID_AVA_DN_QUALIFIER: michael@0: if (dq) { michael@0: break; michael@0: } michael@0: dq = CERT_DecodeAVAValue(&ava->value); michael@0: if (!dq) { michael@0: goto loser; michael@0: } michael@0: len += dq->len; michael@0: break; michael@0: case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME: michael@0: if (ou_count < MAX_OUS) { michael@0: orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value); michael@0: if (!orgunit[ou_count]) { michael@0: goto loser; michael@0: } michael@0: len += orgunit[ou_count++]->len; michael@0: } michael@0: break; michael@0: case SEC_OID_AVA_DC: michael@0: if (dc_count < MAX_DC) { michael@0: dc[dc_count] = CERT_DecodeAVAValue(&ava->value); michael@0: if (!dc[dc_count]) { michael@0: goto loser; michael@0: } michael@0: len += dc[dc_count++]->len; michael@0: } michael@0: break; michael@0: case SEC_OID_PKCS9_EMAIL_ADDRESS: michael@0: case SEC_OID_RFC1274_MAIL: michael@0: if (email) { michael@0: break; michael@0: } michael@0: email = CERT_DecodeAVAValue(&ava->value); michael@0: if (!email) { michael@0: goto loser; michael@0: } michael@0: len += email->len; michael@0: break; michael@0: default: michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* XXX - add some for formatting */ michael@0: len += 128; michael@0: michael@0: /* allocate buffer */ michael@0: buf = (char *)PORT_Alloc(len); michael@0: if ( !buf ) { michael@0: goto loser; michael@0: } michael@0: michael@0: tmpbuf = buf; michael@0: michael@0: if ( cn ) { michael@0: PORT_Memcpy(tmpbuf, cn->data, cn->len); michael@0: tmpbuf += cn->len; michael@0: PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); michael@0: tmpbuf += BREAKLEN; michael@0: } michael@0: if ( email ) { michael@0: PORT_Memcpy(tmpbuf, email->data, email->len); michael@0: tmpbuf += ( email->len ); michael@0: PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); michael@0: tmpbuf += BREAKLEN; michael@0: } michael@0: for (i=ou_count-1; i >= 0; i--) { michael@0: PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len); michael@0: tmpbuf += ( orgunit[i]->len ); michael@0: PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); michael@0: tmpbuf += BREAKLEN; michael@0: } michael@0: if ( dq ) { michael@0: PORT_Memcpy(tmpbuf, dq->data, dq->len); michael@0: tmpbuf += ( dq->len ); michael@0: PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); michael@0: tmpbuf += BREAKLEN; michael@0: } michael@0: if ( org ) { michael@0: PORT_Memcpy(tmpbuf, org->data, org->len); michael@0: tmpbuf += ( org->len ); michael@0: PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); michael@0: tmpbuf += BREAKLEN; michael@0: } michael@0: for (i=dc_count-1; i >= 0; i--) { michael@0: PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len); michael@0: tmpbuf += ( dc[i]->len ); michael@0: PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); michael@0: tmpbuf += BREAKLEN; michael@0: } michael@0: first = PR_TRUE; michael@0: if ( loc ) { michael@0: PORT_Memcpy(tmpbuf, loc->data, loc->len); michael@0: tmpbuf += ( loc->len ); michael@0: first = PR_FALSE; michael@0: } michael@0: if ( state ) { michael@0: if ( !first ) { michael@0: PORT_Memcpy(tmpbuf, COMMA, COMMALEN); michael@0: tmpbuf += COMMALEN; michael@0: } michael@0: PORT_Memcpy(tmpbuf, state->data, state->len); michael@0: tmpbuf += ( state->len ); michael@0: first = PR_FALSE; michael@0: } michael@0: if ( country ) { michael@0: if ( !first ) { michael@0: PORT_Memcpy(tmpbuf, COMMA, COMMALEN); michael@0: tmpbuf += COMMALEN; michael@0: } michael@0: PORT_Memcpy(tmpbuf, country->data, country->len); michael@0: tmpbuf += ( country->len ); michael@0: first = PR_FALSE; michael@0: } michael@0: if ( !first ) { michael@0: PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); michael@0: tmpbuf += BREAKLEN; michael@0: } michael@0: michael@0: *tmpbuf = 0; michael@0: michael@0: /* fall through and clean */ michael@0: loser: michael@0: if ( cn ) { michael@0: SECITEM_FreeItem(cn, PR_TRUE); michael@0: } michael@0: if ( email ) { michael@0: SECITEM_FreeItem(email, PR_TRUE); michael@0: } michael@0: for (i=ou_count-1; i >= 0; i--) { michael@0: SECITEM_FreeItem(orgunit[i], PR_TRUE); michael@0: } michael@0: if ( dq ) { michael@0: SECITEM_FreeItem(dq, PR_TRUE); michael@0: } michael@0: if ( org ) { michael@0: SECITEM_FreeItem(org, PR_TRUE); michael@0: } michael@0: for (i=dc_count-1; i >= 0; i--) { michael@0: SECITEM_FreeItem(dc[i], PR_TRUE); michael@0: } michael@0: if ( loc ) { michael@0: SECITEM_FreeItem(loc, PR_TRUE); michael@0: } michael@0: if ( state ) { michael@0: SECITEM_FreeItem(state, PR_TRUE); michael@0: } michael@0: if ( country ) { michael@0: SECITEM_FreeItem(country, PR_TRUE); michael@0: } michael@0: michael@0: return(buf); michael@0: } michael@0: