2
* The contents of this file are subject to the Mozilla Public
3
* License Version 1.1 (the "License"); you may not use this file
4
* except in compliance with the License. You may obtain a copy of
5
* the License at http://www.mozilla.org/MPL/
7
* Software distributed under the License is distributed on an "AS
8
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9
* implied. See the License for the specific language governing
10
* rights and limitations under the License.
12
* The Original Code is the Netscape security libraries.
14
* The Initial Developer of the Original Code is Netscape
15
* Communications Corporation. Portions created by Netscape are
16
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
21
* Alternatively, the contents of this file may be used under the
22
* terms of the GNU General Public License Version 2 or later (the
23
* "GPL"), in which case the provisions of the GPL are applicable
24
* instead of those above. If you wish to allow use of your
25
* version of this file only under the terms of the GPL and not to
26
* allow others to use your version of this file under the MPL,
27
* indicate your decision by deleting the provisions above and
28
* replace them with the notice and other provisions required by
29
* the GPL. If you do not delete the provisions above, a recipient
30
* may use your version of this file under either the MPL or the
35
* certhtml.c --- convert a cert to html
37
* $Id: certhtml.c,v 1.4 2003/09/19 04:08:49 jpierre%netscape.com Exp $
51
static char *hex = "0123456789ABCDEF";
54
** Convert a der-encoded integer to a hex printable string form
56
char *CERT_Hexify (SECItem *i, int do_colon)
58
unsigned char *cp, *end;
62
return PORT_Strdup("00");
65
rv = o = (char*) PORT_Alloc(i->len * 3);
71
unsigned char ch = *cp++;
72
*o++ = hex[(ch >> 4) & 0xf];
80
*o = 0; /* Null terminate the string */
85
gatherStrings(char **strings)
92
/* find total length of all strings */
96
len += PORT_Strlen(*strs);
100
/* alloc enough memory for it */
101
ret = (char*)PORT_Alloc(len + 1);
108
/* copy the strings */
111
PORT_Strcpy(s, *strs);
112
s += PORT_Strlen(*strs);
125
#define MAX_DC MAX_OUS
128
char *CERT_FormatName (CERTName *name)
141
SECItem * country = 0;
150
SECItem * orgunit[MAX_OUS];
151
SECItem * dc[MAX_DC];
153
/* Loop over name components and gather the interesting ones */
155
while ((rdn = *rdns++) != 0) {
157
while ((ava = *avas++) != 0) {
158
tag = CERT_GetAVATag(ava);
160
case SEC_OID_AVA_COMMON_NAME:
161
cn = CERT_DecodeAVAValue(&ava->value);
164
case SEC_OID_AVA_COUNTRY_NAME:
165
country = CERT_DecodeAVAValue(&ava->value);
168
case SEC_OID_AVA_LOCALITY:
169
loc = CERT_DecodeAVAValue(&ava->value);
172
case SEC_OID_AVA_STATE_OR_PROVINCE:
173
state = CERT_DecodeAVAValue(&ava->value);
176
case SEC_OID_AVA_ORGANIZATION_NAME:
177
org = CERT_DecodeAVAValue(&ava->value);
180
case SEC_OID_AVA_DN_QUALIFIER:
181
dq = CERT_DecodeAVAValue(&ava->value);
184
case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
185
if (ou_count < MAX_OUS) {
186
orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value);
187
len += orgunit[ou_count++]->len;
191
if (dc_count < MAX_DC) {
192
dc[dc_count] = CERT_DecodeAVAValue(&ava->value);
193
len += dc[dc_count++]->len;
196
case SEC_OID_PKCS9_EMAIL_ADDRESS:
197
case SEC_OID_RFC1274_MAIL:
198
email = CERT_DecodeAVAValue(&ava->value);
207
/* XXX - add some for formatting */
210
/* allocate buffer */
211
buf = (char *)PORT_Alloc(len);
219
PORT_Memcpy(tmpbuf, cn->data, cn->len);
221
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
223
SECITEM_FreeItem(cn, PR_TRUE);
226
PORT_Memcpy(tmpbuf, email->data, email->len);
227
tmpbuf += ( email->len );
228
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
230
SECITEM_FreeItem(email, PR_TRUE);
232
for (i=ou_count-1; i >= 0; i--) {
233
PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len);
234
tmpbuf += ( orgunit[i]->len );
235
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
237
SECITEM_FreeItem(orgunit[i], PR_TRUE);
240
PORT_Memcpy(tmpbuf, dq->data, dq->len);
241
tmpbuf += ( dq->len );
242
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
244
SECITEM_FreeItem(dq, PR_TRUE);
247
PORT_Memcpy(tmpbuf, org->data, org->len);
248
tmpbuf += ( org->len );
249
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
251
SECITEM_FreeItem(org, PR_TRUE);
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);
258
SECITEM_FreeItem(dc[i], PR_TRUE);
262
PORT_Memcpy(tmpbuf, loc->data, loc->len);
263
tmpbuf += ( loc->len );
265
SECITEM_FreeItem(loc, PR_TRUE);
269
PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
272
PORT_Memcpy(tmpbuf, state->data, state->len);
273
tmpbuf += ( state->len );
275
SECITEM_FreeItem(state, PR_TRUE);
279
PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
282
PORT_Memcpy(tmpbuf, country->data, country->len);
283
tmpbuf += ( country->len );
285
SECITEM_FreeItem(country, PR_TRUE);
288
PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
297
static char *sec_FortezzaClearance(SECItem *clearance) {
298
unsigned char clr = 0;
300
if (clearance->len > 0) { clr = clearance->data[0]; }
302
if (clr & 0x4) return "Top Secret";
303
if (clr & 0x8) return "Secret";
304
if (clr & 0x10) return "Confidential";
305
if (clr & 0x20) return "Sensitive";
306
if (clr & 0x40) return "Unclassified";
310
static char *sec_FortezzaMessagePrivilege(SECItem *priv) {
311
unsigned char clr = 0;
313
if (priv->len > 0) { clr = (priv->data[0]) & 0x78; }
319
return PR_smprintf("%s%s%s%s%s%s%s",
321
clr&0x40?"Critical/Flash":"",
322
(clr&0x40) && (clr&0x38) ? ", " : "" ,
324
clr&0x20?"Immediate/Priority":"",
325
(clr&0x20) && (clr&0x18) ? ", " : "" ,
327
clr&0x10?"Routine/Deferred":"",
328
(clr&0x10) && (clr&0x08) ? ", " : "" ,
330
clr&0x08?"Rekey Agent":"");
335
static char *sec_FortezzaCertPrivilege(SECItem *priv) {
336
unsigned char clr = 0;
338
if (priv->len > 0) { clr = priv->data[0]; }
340
return PR_smprintf("%s%s%s%s%s%s%s%s%s%s%s%s",
341
clr&0x40?"Organizational Releaser":"",
342
(clr&0x40) && (clr&0x3e) ? "," : "" ,
343
clr&0x20?"Policy Creation Authority":"",
344
(clr&0x20) && (clr&0x1e) ? "," : "" ,
345
clr&0x10?"Certificate Authority":"",
346
(clr&0x10) && (clr&0x0e) ? "," : "" ,
347
clr&0x08?"Local Managment Authority":"",
348
(clr&0x08) && (clr&0x06) ? "," : "" ,
349
clr&0x04?"Configuration Vector Authority":"",
350
(clr&0x04) && (clr&0x02) ? "," : "" ,
351
clr&0x02?"No Signature Capability":"",
352
clr&0x7e?"":"Signing Only"
356
static char *htmlcertstrings[] = {
357
"<table border=0 cellspacing=0 cellpadding=0><tr><td valign=top>"
358
"<font size=2><b>This Certificate belongs to:</b><br>"
359
"<table border=0 cellspacing=0 cellpadding=0><tr><td>",
360
0, /* image goes here */
363
"</td><td width=10> </td><td><font size=2>",
364
0, /* subject name goes here */
365
"</td></tr></table></font></td><td width=20> </td><td valign=top>"
366
"<font size=2><b>This Certificate was issued by:</b><br>"
367
"<table border=0 cellspacing=0 cellpadding=0><tr><td>",
368
0, /* image goes here */
371
"</td><td width=10> </td><td><font size=2>",
372
0, /* issuer name goes here */
373
"</td></tr></table></font></td></tr></table>"
374
"<b>Serial Number:</b> ",
376
"<br><b>This Certificate is valid from ",
377
0, /* notBefore goes here */
379
0, /* notAfter does here */
380
"</b><br><b>Clearance:</b>",
382
"<br><b>DSS Privileges:</b>",
384
"<br><b>KEA Privileges:</b>",
388
"<br><b>Certificate Fingerprint:</b>"
389
"<table border=0 cellspacing=0 cellpadding=0><tr>"
390
"<td width=10> </td><td><font size=2>",
391
0, /* fingerprint goes here */
392
"</td></tr></table>",
393
0, /* comment header goes here */
394
0, /* comment goes here */
395
0, /* comment trailer goes here */
400
CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, PRBool showIssuer)
403
char *issuer, *subject, *serialNumber, *version;
404
char *notBefore, *notAfter;
408
unsigned char fingerprint[16]; /* result of MD5, always 16 bytes */
411
char *commentstring = NULL;
412
SECKEYPublicKey *pubk;
421
issuer = CERT_FormatName (&cert->issuer);
422
subject = CERT_FormatName (&cert->subject);
423
version = CERT_Hexify (&cert->version,1);
424
serialNumber = CERT_Hexify (&cert->serialNumber,1);
425
notBefore = DER_TimeChoiceDayToAscii(&cert->validity.notBefore);
426
notAfter = DER_TimeChoiceDayToAscii(&cert->validity.notAfter);
427
servername = CERT_FindNSStringExtension(cert,
428
SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
430
nickname = cert->nickname;
431
if ( nickname == NULL ) {
432
showImages = PR_FALSE;
435
dummyitem.data = NULL;
436
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_SUBJECT_LOGO,
438
if ( dummyitem.data ) {
439
PORT_Free(dummyitem.data);
442
if ( rv || !showImages ) {
443
htmlcertstrings[1] = "";
444
htmlcertstrings[2] = "";
445
htmlcertstrings[3] = "";
447
htmlcertstrings[1] = "<img src=\"about:security?subject-logo=";
448
htmlcertstrings[2] = nickname;
449
htmlcertstrings[3] = "\">";
454
tmpstr = (char *)PORT_Alloc(PORT_Strlen(subject) +
455
PORT_Strlen(servername) +
458
PORT_Strcpy(tmpstr, servername);
459
PORT_Strcat(tmpstr, "<br>");
460
PORT_Strcat(tmpstr, subject);
466
htmlcertstrings[5] = subject;
468
dummyitem.data = NULL;
470
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_ISSUER_LOGO,
472
if ( dummyitem.data ) {
473
PORT_Free(dummyitem.data);
476
if ( rv || !showImages ) {
477
htmlcertstrings[7] = "";
478
htmlcertstrings[8] = "";
479
htmlcertstrings[9] = "";
481
htmlcertstrings[7] = "<img src=\"about:security?issuer-logo=";
482
htmlcertstrings[8] = nickname;
483
htmlcertstrings[9] = "\">";
487
if (showIssuer == PR_TRUE) {
488
htmlcertstrings[11] = issuer;
490
htmlcertstrings[11] = "";
493
htmlcertstrings[13] = serialNumber;
494
htmlcertstrings[15] = notBefore;
495
htmlcertstrings[17] = notAfter;
497
pubk = CERT_ExtractPublicKey(cert);
499
if (pubk && (pubk->keyType == fortezzaKey)) {
500
htmlcertstrings[18] = "</b><br><b>Clearance:</b>";
501
htmlcertstrings[19] = sec_FortezzaClearance(
502
&pubk->u.fortezza.clearance);
503
htmlcertstrings[20] = "<br><b>DSS Privileges:</b>";
504
DSSPriv = sec_FortezzaCertPrivilege(
505
&pubk->u.fortezza.DSSpriviledge);
506
htmlcertstrings[21] = DSSPriv;
507
htmlcertstrings[22] = "<br><b>KEA Privileges:</b>";
508
htmlcertstrings[23] = sec_FortezzaMessagePrivilege(
509
&pubk->u.fortezza.KEApriviledge);
510
htmlcertstrings[24] = "<br><b>KMID:</b>";
511
dummyitem.data = &pubk->u.fortezza.KMID[0];
512
dummyitem.len = sizeof(pubk->u.fortezza.KMID);
513
KMID = CERT_Hexify (&dummyitem,0);
514
htmlcertstrings[25] = KMID;
516
/* clear out the headers in the non-fortezza cases */
517
htmlcertstrings[18] = "";
518
htmlcertstrings[19] = "";
519
htmlcertstrings[20] = "";
520
htmlcertstrings[21] = "";
521
htmlcertstrings[22] = "";
522
htmlcertstrings[23] = "";
523
htmlcertstrings[24] = "";
524
htmlcertstrings[25] = "</b>";
528
SECKEY_DestroyPublicKey(pubk);
532
rv = PK11_HashBuf(SEC_OID_MD5, fingerprint,
533
cert->derCert.data, cert->derCert.len);
535
fpitem.data = fingerprint;
536
fpitem.len = sizeof(fingerprint);
538
fpstr = CERT_Hexify (&fpitem,1);
540
htmlcertstrings[HTML_OFF] = fpstr;
542
commentstring = CERT_GetCertCommentString(cert);
544
if (commentstring == NULL) {
545
htmlcertstrings[HTML_OFF+2] = "";
546
htmlcertstrings[HTML_OFF+3] = "";
547
htmlcertstrings[HTML_OFF+4] = "";
549
htmlcertstrings[HTML_OFF+2] =
551
"<table border=0 cellspacing=0 cellpadding=0><tr>"
552
"<td width=10> </td><td><font size=3>"
553
"<textarea name=foobar rows=4 cols=55 onfocus=\"this.blur()\">";
554
htmlcertstrings[HTML_OFF+3] = commentstring;
555
htmlcertstrings[HTML_OFF+4] = "</textarea></font></td></tr></table>";
558
ret = gatherStrings(htmlcertstrings);
572
if ( serialNumber ) {
573
PORT_Free(serialNumber);
577
PORT_Free(notBefore);
595
if ( commentstring ) {
596
PORT_Free(commentstring);
600
PORT_Free(servername);