certhtml.c (9177B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * certhtml.c --- convert a cert to html 7 */ 8 9 #include "seccomon.h" 10 #include "secitem.h" 11 #include "sechash.h" 12 #include "cert.h" 13 #include "keyhi.h" 14 #include "secder.h" 15 #include "prprf.h" 16 #include "secport.h" 17 #include "secasn1.h" 18 #include "pk11func.h" 19 20 static char *hex = "0123456789ABCDEF"; 21 22 /* 23 ** Convert a der-encoded integer to a hex printable string form 24 */ 25 char * 26 CERT_Hexify(SECItem *i, int do_colon) 27 { 28 unsigned char *cp, *end; 29 char *rv, *o; 30 31 if (!i->len) { 32 return PORT_Strdup("00"); 33 } 34 35 rv = o = (char *)PORT_Alloc(i->len * 3); 36 if (!rv) 37 return rv; 38 39 cp = i->data; 40 end = cp + i->len; 41 while (cp < end) { 42 unsigned char ch = *cp++; 43 *o++ = hex[(ch >> 4) & 0xf]; 44 *o++ = hex[ch & 0xf]; 45 if (cp != end) { 46 if (do_colon) { 47 *o++ = ':'; 48 } 49 } 50 } 51 *o = 0; /* Null terminate the string */ 52 return rv; 53 } 54 55 #define BREAK "<br>" 56 #define BREAKLEN 4 57 #define COMMA ", " 58 #define COMMALEN 2 59 60 #define MAX_OUS 20 61 #define MAX_DC MAX_OUS 62 63 char * 64 CERT_FormatName(CERTName *name) 65 { 66 CERTRDN **rdns; 67 CERTRDN *rdn; 68 CERTAVA **avas; 69 CERTAVA *ava; 70 char *buf = 0; 71 char *tmpbuf = 0; 72 SECItem *cn = 0; 73 SECItem *email = 0; 74 SECItem *org = 0; 75 SECItem *loc = 0; 76 SECItem *state = 0; 77 SECItem *country = 0; 78 SECItem *dq = 0; 79 80 unsigned len = 0; 81 int tag; 82 int i; 83 int ou_count = 0; 84 int dc_count = 0; 85 PRBool first; 86 SECItem *orgunit[MAX_OUS]; 87 SECItem *dc[MAX_DC]; 88 89 /* Loop over name components and gather the interesting ones */ 90 rdns = name->rdns; 91 while ((rdn = *rdns++) != 0) { 92 avas = rdn->avas; 93 while ((ava = *avas++) != 0) { 94 tag = CERT_GetAVATag(ava); 95 switch (tag) { 96 case SEC_OID_AVA_COMMON_NAME: 97 if (cn) { 98 break; 99 } 100 cn = CERT_DecodeAVAValue(&ava->value); 101 if (!cn) { 102 goto loser; 103 } 104 len += cn->len; 105 // cn will always have BREAK after it 106 len += BREAKLEN; 107 break; 108 case SEC_OID_AVA_COUNTRY_NAME: 109 if (country) { 110 break; 111 } 112 country = CERT_DecodeAVAValue(&ava->value); 113 if (!country) { 114 goto loser; 115 } 116 len += country->len; 117 // country may have COMMA after it (if we over-count len, 118 // that's fine - we'll just allocate a buffer larger than we 119 // need) 120 len += COMMALEN; 121 break; 122 case SEC_OID_AVA_LOCALITY: 123 if (loc) { 124 break; 125 } 126 loc = CERT_DecodeAVAValue(&ava->value); 127 if (!loc) { 128 goto loser; 129 } 130 len += loc->len; 131 // loc may have COMMA after it 132 len += COMMALEN; 133 break; 134 case SEC_OID_AVA_STATE_OR_PROVINCE: 135 if (state) { 136 break; 137 } 138 state = CERT_DecodeAVAValue(&ava->value); 139 if (!state) { 140 goto loser; 141 } 142 len += state->len; 143 // state currently won't have COMMA after it, but this is a 144 // (probably vain) attempt to future-proof this code 145 len += COMMALEN; 146 break; 147 case SEC_OID_AVA_ORGANIZATION_NAME: 148 if (org) { 149 break; 150 } 151 org = CERT_DecodeAVAValue(&ava->value); 152 if (!org) { 153 goto loser; 154 } 155 len += org->len; 156 // org will have BREAK after it 157 len += BREAKLEN; 158 break; 159 case SEC_OID_AVA_DN_QUALIFIER: 160 if (dq) { 161 break; 162 } 163 dq = CERT_DecodeAVAValue(&ava->value); 164 if (!dq) { 165 goto loser; 166 } 167 len += dq->len; 168 // dq will have BREAK after it 169 len += BREAKLEN; 170 break; 171 case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME: 172 if (ou_count < MAX_OUS) { 173 orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value); 174 if (!orgunit[ou_count]) { 175 goto loser; 176 } 177 len += orgunit[ou_count++]->len; 178 // each ou will have BREAK after it 179 len += BREAKLEN; 180 } 181 break; 182 case SEC_OID_AVA_DC: 183 if (dc_count < MAX_DC) { 184 dc[dc_count] = CERT_DecodeAVAValue(&ava->value); 185 if (!dc[dc_count]) { 186 goto loser; 187 } 188 len += dc[dc_count++]->len; 189 // each dc will have BREAK after it 190 len += BREAKLEN; 191 } 192 break; 193 case SEC_OID_PKCS9_EMAIL_ADDRESS: 194 case SEC_OID_RFC1274_MAIL: 195 if (email) { 196 break; 197 } 198 email = CERT_DecodeAVAValue(&ava->value); 199 if (!email) { 200 goto loser; 201 } 202 len += email->len; 203 // email will have BREAK after it 204 len += BREAKLEN; 205 break; 206 default: 207 break; 208 } 209 } 210 } 211 212 // there may be a final BREAK 213 len += BREAKLEN; 214 215 /* allocate buffer */ 216 buf = (char *)PORT_Alloc(len); 217 if (!buf) { 218 goto loser; 219 } 220 221 tmpbuf = buf; 222 223 if (cn) { 224 PORT_Memcpy(tmpbuf, cn->data, cn->len); 225 tmpbuf += cn->len; 226 PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); 227 tmpbuf += BREAKLEN; 228 } 229 if (email) { 230 PORT_Memcpy(tmpbuf, email->data, email->len); 231 tmpbuf += (email->len); 232 PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); 233 tmpbuf += BREAKLEN; 234 } 235 for (i = ou_count - 1; i >= 0; i--) { 236 PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len); 237 tmpbuf += (orgunit[i]->len); 238 PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); 239 tmpbuf += BREAKLEN; 240 } 241 if (dq) { 242 PORT_Memcpy(tmpbuf, dq->data, dq->len); 243 tmpbuf += (dq->len); 244 PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); 245 tmpbuf += BREAKLEN; 246 } 247 if (org) { 248 PORT_Memcpy(tmpbuf, org->data, org->len); 249 tmpbuf += (org->len); 250 PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); 251 tmpbuf += BREAKLEN; 252 } 253 for (i = dc_count - 1; i >= 0; i--) { 254 PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len); 255 tmpbuf += (dc[i]->len); 256 PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); 257 tmpbuf += BREAKLEN; 258 } 259 first = PR_TRUE; 260 if (loc) { 261 PORT_Memcpy(tmpbuf, loc->data, loc->len); 262 tmpbuf += (loc->len); 263 first = PR_FALSE; 264 } 265 if (state) { 266 if (!first) { 267 PORT_Memcpy(tmpbuf, COMMA, COMMALEN); 268 tmpbuf += COMMALEN; 269 } 270 PORT_Memcpy(tmpbuf, state->data, state->len); 271 tmpbuf += (state->len); 272 first = PR_FALSE; 273 } 274 if (country) { 275 if (!first) { 276 PORT_Memcpy(tmpbuf, COMMA, COMMALEN); 277 tmpbuf += COMMALEN; 278 } 279 PORT_Memcpy(tmpbuf, country->data, country->len); 280 tmpbuf += (country->len); 281 first = PR_FALSE; 282 } 283 if (!first) { 284 PORT_Memcpy(tmpbuf, BREAK, BREAKLEN); 285 tmpbuf += BREAKLEN; 286 } 287 288 *tmpbuf = 0; 289 290 /* fall through and clean */ 291 loser: 292 if (cn) { 293 SECITEM_FreeItem(cn, PR_TRUE); 294 } 295 if (email) { 296 SECITEM_FreeItem(email, PR_TRUE); 297 } 298 for (i = ou_count - 1; i >= 0; i--) { 299 SECITEM_FreeItem(orgunit[i], PR_TRUE); 300 } 301 if (dq) { 302 SECITEM_FreeItem(dq, PR_TRUE); 303 } 304 if (org) { 305 SECITEM_FreeItem(org, PR_TRUE); 306 } 307 for (i = dc_count - 1; i >= 0; i--) { 308 SECITEM_FreeItem(dc[i], PR_TRUE); 309 } 310 if (loc) { 311 SECITEM_FreeItem(loc, PR_TRUE); 312 } 313 if (state) { 314 SECITEM_FreeItem(state, PR_TRUE); 315 } 316 if (country) { 317 SECITEM_FreeItem(country, PR_TRUE); 318 } 319 320 return (buf); 321 }