certhtml.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:15k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  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/
  6.  * 
  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.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  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
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  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
  31.  * GPL.
  32.  */
  33. /*
  34.  * certhtml.c --- convert a cert to html
  35.  *
  36.  * $Id: certhtml.c,v 1.1 2000/03/31 19:42:54 relyea%netscape.com Exp $
  37.  */
  38. #include "seccomon.h"
  39. #include "secitem.h"
  40. #include "sechash.h"
  41. #include "cert.h"
  42. #include "keyhi.h"
  43. #include "secder.h"
  44. #include "prprf.h"
  45. #include "secport.h"
  46. #include "secasn1.h"
  47. #include "pk11func.h"
  48. static char *hex = "0123456789ABCDEF";
  49. /*
  50. ** Convert a der-encoded integer to a hex printable string form
  51. */
  52. char *CERT_Hexify (SECItem *i, int do_colon)
  53. {
  54.     unsigned char *cp, *end;
  55.     char *rv, *o;
  56.     if (!i->len) {
  57. return PORT_Strdup("00");
  58.     }
  59.     rv = o = (char*) PORT_Alloc(i->len * 3);
  60.     if (!rv) return rv;
  61.     cp = i->data;
  62.     end = cp + i->len;
  63.     while (cp < end) {
  64. unsigned char ch = *cp++;
  65. *o++ = hex[(ch >> 4) & 0xf];
  66. *o++ = hex[ch & 0xf];
  67. if (cp != end) {
  68.     if (do_colon) {
  69. *o++ = ':';
  70.     }
  71.     }
  72.     *o = 0;           /* Null terminate the string */
  73.     return rv;
  74. }
  75. static char *
  76. gatherStrings(char **strings)
  77. {
  78.     char **strs;
  79.     int len;
  80.     char *ret;
  81.     char *s;
  82.     /* find total length of all strings */
  83.     strs = strings;
  84.     len = 0;
  85.     while ( *strs ) {
  86. len += PORT_Strlen(*strs);
  87. strs++;
  88.     }
  89.     
  90.     /* alloc enough memory for it */
  91.     ret = (char*)PORT_Alloc(len + 1);
  92.     if ( !ret ) {
  93. return(ret);
  94.     }
  95.     s = ret;
  96.     
  97.     /* copy the strings */
  98.     strs = strings;
  99.     while ( *strs ) {
  100. PORT_Strcpy(s, *strs);
  101. s += PORT_Strlen(*strs);
  102. strs++;
  103.     }
  104.     return( ret );
  105. }
  106. static PRBool
  107. CERT_IsAVAInUnicode(CERTAVA *ava, SECOidTag type)
  108. {
  109.     switch(type) {
  110. case SEC_OID_AVA_COUNTRY_NAME:
  111. case SEC_OID_PKCS9_EMAIL_ADDRESS:
  112. case SEC_OID_RFC1274_MAIL:
  113.     return PR_FALSE;
  114. default:
  115.     if(ava->value.data[0] == SEC_ASN1_UNIVERSAL_STRING) {
  116. return PR_TRUE;
  117.     }
  118.     break;
  119.     }
  120.     return PR_FALSE;
  121. }
  122. #define BREAK "<br>"
  123. #define BREAKLEN 4
  124. #define COMMA ", "
  125. #define COMMALEN 2
  126. #define MAX_OUS 20
  127. #define MAX_DC MAX_OUS
  128. char *CERT_FormatName (CERTName *name)
  129. {
  130.     CERTRDN** rdns;
  131.     CERTRDN * rdn;
  132.     CERTAVA** avas;
  133.     CERTAVA*  ava;
  134.     char *    buf = 0;
  135.     char *    tmpbuf = 0;
  136.     SECItem * cn = 0;
  137.     SECItem * email = 0;
  138.     SECItem * org = 0;
  139.     SECItem * loc = 0;
  140.     SECItem * state = 0;
  141.     SECItem * country = 0;
  142.     SECItem * dq      = 0;
  143.     unsigned  len  = 0;
  144.     int       tag;
  145.     int       i;
  146.     int       ou_count = 0;
  147.     int       dc_count = 0;
  148.     PRBool    first;
  149.     SECItem * orgunit[MAX_OUS];
  150.     SECItem * dc[MAX_DC];
  151.     /* Loop over name components and gather the interesting ones */
  152.     rdns = name->rdns;
  153.     while ((rdn = *rdns++) != 0) {
  154. avas = rdn->avas;
  155. while ((ava = *avas++) != 0) {
  156.     tag = CERT_GetAVATag(ava);
  157.     switch(tag) {
  158.       case SEC_OID_AVA_COMMON_NAME:
  159. cn = CERT_DecodeAVAValue(&ava->value);
  160. len += cn->len;
  161. break;
  162.       case SEC_OID_AVA_COUNTRY_NAME:
  163. country = CERT_DecodeAVAValue(&ava->value);
  164. len += country->len;
  165. break;
  166.       case SEC_OID_AVA_LOCALITY:
  167. loc = CERT_DecodeAVAValue(&ava->value);
  168. len += loc->len;
  169. break;
  170.       case SEC_OID_AVA_STATE_OR_PROVINCE:
  171. state = CERT_DecodeAVAValue(&ava->value);
  172. len += state->len;
  173. break;
  174.       case SEC_OID_AVA_ORGANIZATION_NAME:
  175. org = CERT_DecodeAVAValue(&ava->value);
  176. len += org->len;
  177. break;
  178.       case SEC_OID_AVA_DN_QUALIFIER:
  179. dq = CERT_DecodeAVAValue(&ava->value);
  180. len += dq->len;
  181. break;
  182.       case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
  183. if (ou_count < MAX_OUS) {
  184. orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value);
  185. len += orgunit[ou_count++]->len;
  186. }
  187. break;
  188.       case SEC_OID_AVA_DC:
  189. if (dc_count < MAX_DC) {
  190. dc[dc_count] = CERT_DecodeAVAValue(&ava->value);
  191. len += dc[dc_count++]->len;
  192. }
  193. break;
  194.       case SEC_OID_PKCS9_EMAIL_ADDRESS:
  195.       case SEC_OID_RFC1274_MAIL:
  196. email = CERT_DecodeAVAValue(&ava->value);
  197. len += email->len;
  198. break;
  199.       default:
  200. break;
  201.     }
  202. }
  203.     }
  204.     /* XXX - add some for formatting */
  205.     len += 128;
  206.     /* allocate buffer */
  207.     buf = (char *)PORT_Alloc(len);
  208.     if ( !buf ) {
  209. return(0);
  210.     }
  211.     tmpbuf = buf;
  212.     
  213.     if ( cn ) {
  214. PORT_Memcpy(tmpbuf, cn->data, cn->len);
  215. tmpbuf += cn->len;
  216. PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
  217. tmpbuf += BREAKLEN;
  218. SECITEM_FreeItem(cn, PR_TRUE);
  219.     }
  220.     if ( email ) {
  221. PORT_Memcpy(tmpbuf, email->data, email->len);
  222. tmpbuf += ( email->len );
  223. PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
  224. tmpbuf += BREAKLEN;
  225. SECITEM_FreeItem(email, PR_TRUE);
  226.     }
  227.     for (i=ou_count-1; i >= 0; i--) {
  228. PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len);
  229. tmpbuf += ( orgunit[i]->len );
  230. PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
  231. tmpbuf += BREAKLEN;
  232. SECITEM_FreeItem(orgunit[i], PR_TRUE);
  233.     }
  234.     if ( dq ) {
  235. PORT_Memcpy(tmpbuf, dq->data, dq->len);
  236. tmpbuf += ( dq->len );
  237. PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
  238. tmpbuf += BREAKLEN;
  239. SECITEM_FreeItem(dq, PR_TRUE);
  240.     }
  241.     if ( org ) {
  242. PORT_Memcpy(tmpbuf, org->data, org->len);
  243. tmpbuf += ( org->len );
  244. PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
  245. tmpbuf += BREAKLEN;
  246. SECITEM_FreeItem(org, PR_TRUE);
  247.     }
  248.     for (i=dc_count-1; i >= 0; i--) {
  249. PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len);
  250. tmpbuf += ( dc[i]->len );
  251. PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
  252. tmpbuf += BREAKLEN;
  253. SECITEM_FreeItem(dc[i], PR_TRUE);
  254.     }
  255.     first = PR_TRUE;
  256.     if ( loc ) {
  257. PORT_Memcpy(tmpbuf, loc->data,  loc->len);
  258. tmpbuf += ( loc->len );
  259. first = PR_FALSE;
  260. SECITEM_FreeItem(loc, PR_TRUE);
  261.     }
  262.     if ( state ) {
  263. if ( !first ) {
  264.     PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
  265.     tmpbuf += COMMALEN;
  266. }
  267. PORT_Memcpy(tmpbuf, state->data, state->len);
  268. tmpbuf += ( state->len );
  269. first = PR_FALSE;
  270. SECITEM_FreeItem(state, PR_TRUE);
  271.     }
  272.     if ( country ) {
  273. if ( !first ) {
  274.     PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
  275.     tmpbuf += COMMALEN;
  276. }
  277. PORT_Memcpy(tmpbuf, country->data, country->len);
  278. tmpbuf += ( country->len );
  279. first = PR_FALSE;
  280. SECITEM_FreeItem(country, PR_TRUE);
  281.     }
  282.     if ( !first ) {
  283. PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
  284. tmpbuf += BREAKLEN;
  285.     }
  286.     *tmpbuf = 0;
  287.     return(buf);
  288. }
  289. static char *sec_FortezzaClearance(SECItem *clearance) {
  290.     unsigned char clr = 0;
  291.     if (clearance->len > 0) { clr = clearance->data[0]; }
  292.     if (clr & 0x4) return "Top Secret";
  293.     if (clr & 0x8) return "Secret";
  294.     if (clr & 0x10) return "Confidential";
  295.     if (clr & 0x20) return "Sensitive";
  296.     if (clr & 0x40) return "Unclassified";
  297.     return "None";
  298. }
  299. static char *sec_FortezzaMessagePriviledge(SECItem *priv) {
  300.     unsigned char clr = 0;
  301.     if (priv->len > 0) { clr = (priv->data[0]) & 0x78; }
  302.     if (clr == 0x00) {
  303. return "None";
  304.     } else {
  305. return PR_smprintf("%s%s%s%s%s%s%s",
  306.     clr&0x40?"Critical/Flash":"",
  307.     (clr&0x40) && (clr&0x38) ? ", " : "" ,
  308.     clr&0x20?"Immediate/Priority":"",
  309.     (clr&0x20) && (clr&0x18) ? ", " : "" ,
  310.     clr&0x10?"Routine/Deferred":"",
  311.     (clr&0x10) && (clr&0x08) ? ", " : "" ,
  312.     clr&0x08?"Rekey Agent":"");
  313.     }
  314. }
  315. static char *sec_FortezzaCertPriviledge(SECItem *priv) {
  316.     unsigned char clr = 0;
  317.     if (priv->len > 0) { clr = priv->data[0]; }
  318.     return PR_smprintf("%s%s%s%s%s%s%s%s%s%s%s%s",
  319. clr&0x40?"Organizational Releaser":"",
  320. (clr&0x40) && (clr&0x3e) ? "," : "" ,
  321. clr&0x20?"Policy Creation Authority":"",
  322. (clr&0x20) && (clr&0x1e) ? "," : "" ,
  323. clr&0x10?"Certificate Authority":"",
  324. (clr&0x10) && (clr&0x0e) ? "," : "" ,
  325. clr&0x08?"Local Managment Authority":"",
  326. (clr&0x08) && (clr&0x06) ? "," : "" ,
  327. clr&0x04?"Configuration Vector Authority":"",
  328. (clr&0x04) && (clr&0x02) ? "," : "" ,
  329. clr&0x02?"No Signature Capability":"",
  330. clr&0x7e?"":"Signing Only"
  331.     );
  332. }
  333. static char *htmlcertstrings[] = {
  334.     "<table border=0 cellspacing=0 cellpadding=0><tr><td valign=top>"
  335.     "<font size=2><b>This Certificate belongs to:</b><br>"
  336.     "<table border=0 cellspacing=0 cellpadding=0><tr><td>",
  337.     0, /* image goes here */
  338.     0,
  339.     0,
  340.     "</td><td width=10> </td><td><font size=2>",
  341.     0, /* subject name goes here */
  342.     "</td></tr></table></font></td><td width=20> </td><td valign=top>"
  343.     "<font size=2><b>This Certificate was issued by:</b><br>"
  344.     "<table border=0 cellspacing=0 cellpadding=0><tr><td>",
  345.     0, /* image goes here */
  346.     0,
  347.     0,
  348.     "</td><td width=10> </td><td><font size=2>",
  349.     0, /* issuer name goes here */
  350.     "</td></tr></table></font></td></tr></table>"
  351.     "<b>Serial Number:</b> ",
  352.     0,
  353.     "<br><b>This Certificate is valid from ",
  354.     0, /* notBefore goes here */
  355.     " to ",
  356.     0, /* notAfter does here */
  357.     "</b><br><b>Clearance:</b>",
  358.     0,
  359.     "<br><b>DSS Priviledges:</b>",
  360.     0,
  361.     "<br><b>KEA Priviledges:</b>",
  362.     0,
  363.     "<br><b>KMID:</b>",
  364.     0,
  365.     "<br><b>Certificate Fingerprint:</b>"
  366.     "<table border=0 cellspacing=0 cellpadding=0><tr>"
  367.     "<td width=10> </td><td><font size=2>",
  368.     0, /* fingerprint goes here */
  369.     "</td></tr></table>",
  370.     0, /* comment header goes here */
  371.     0, /* comment goes here */
  372.     0, /* comment trailer goes here */
  373.     0
  374. };
  375. char *
  376. CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, PRBool showIssuer)
  377. {
  378.     SECStatus rv;
  379.     char *issuer, *subject, *serialNumber, *version;
  380.     char *notBefore, *notAfter;
  381.     char *ret;
  382.     char *nickname;
  383.     SECItem dummyitem;
  384.     unsigned char fingerprint[16];   /* result of MD5, always 16 bytes */
  385.     char *fpstr;
  386.     SECItem fpitem;
  387.     char *commentstring = NULL;
  388.     SECKEYPublicKey *pubk;
  389.     char *DSSPriv;
  390.     char *KMID = NULL;
  391.     char *servername;
  392.     
  393.     if (!cert) {
  394. return(0);
  395.     }
  396.     issuer = CERT_FormatName (&cert->issuer);
  397.     subject = CERT_FormatName (&cert->subject);
  398.     version = CERT_Hexify (&cert->version,1);
  399.     serialNumber = CERT_Hexify (&cert->serialNumber,1);
  400.     notBefore = DER_UTCDayToAscii(&cert->validity.notBefore);
  401.     notAfter = DER_UTCDayToAscii(&cert->validity.notAfter);
  402.     servername = CERT_FindNSStringExtension(cert,
  403.    SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
  404.     nickname = cert->nickname;
  405.     if ( nickname == NULL ) {
  406. showImages = PR_FALSE;
  407.     }
  408.     dummyitem.data = NULL;
  409.     rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_SUBJECT_LOGO,
  410.        &dummyitem);
  411.     if ( dummyitem.data ) {
  412. PORT_Free(dummyitem.data);
  413.     }
  414.     
  415.     if ( rv || !showImages ) {
  416. htmlcertstrings[1] = "";
  417. htmlcertstrings[2] = "";
  418. htmlcertstrings[3] = "";
  419.     } else {
  420. htmlcertstrings[1] = "<img src="about:security?subject-logo=";
  421. htmlcertstrings[2] = nickname;
  422. htmlcertstrings[3] = "">";
  423.     }
  424.     if ( servername ) {
  425. char *tmpstr;
  426. tmpstr = (char *)PORT_Alloc(PORT_Strlen(subject) +
  427.     PORT_Strlen(servername) +
  428.     sizeof("<br>") + 1);
  429. if ( tmpstr ) {
  430.     PORT_Strcpy(tmpstr, servername);
  431.     PORT_Strcat(tmpstr, "<br>");
  432.     PORT_Strcat(tmpstr, subject);
  433.     PORT_Free(subject);
  434.     subject = tmpstr;
  435. }
  436.     }
  437.     
  438.     htmlcertstrings[5] = subject;
  439.     dummyitem.data = NULL;
  440.     
  441.     rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_ISSUER_LOGO,
  442.        &dummyitem);
  443.     if ( dummyitem.data ) {
  444. PORT_Free(dummyitem.data);
  445.     }
  446.     
  447.     if ( rv || !showImages ) {
  448. htmlcertstrings[7] = "";
  449. htmlcertstrings[8] = "";
  450. htmlcertstrings[9] = "";
  451.     } else {
  452. htmlcertstrings[7] = "<img src="about:security?issuer-logo=";
  453. htmlcertstrings[8] = nickname;
  454. htmlcertstrings[9] = "">";
  455.     }
  456.     
  457.     if (showIssuer == PR_TRUE) {
  458.         htmlcertstrings[11] = issuer;
  459.     } else {
  460. htmlcertstrings[11] = "";
  461.     }
  462.     htmlcertstrings[13] = serialNumber;
  463.     htmlcertstrings[15] = notBefore;
  464.     htmlcertstrings[17] = notAfter;
  465.     pubk = CERT_ExtractPublicKey(cert);
  466.     DSSPriv = NULL;
  467.     if (pubk && (pubk->keyType == fortezzaKey)) {
  468. htmlcertstrings[18] = "</b><br><b>Clearance:</b>";
  469. htmlcertstrings[19] = sec_FortezzaClearance(
  470. &pubk->u.fortezza.clearance);
  471. htmlcertstrings[20] = "<br><b>DSS Priviledges:</b>";
  472. DSSPriv = sec_FortezzaCertPriviledge(
  473. &pubk->u.fortezza.DSSpriviledge);
  474. htmlcertstrings[21] = DSSPriv;
  475. htmlcertstrings[22] = "<br><b>KEA Priviledges:</b>";
  476. htmlcertstrings[23] = sec_FortezzaMessagePriviledge(
  477. &pubk->u.fortezza.KEApriviledge);
  478. htmlcertstrings[24] = "<br><b>KMID:</b>";
  479. dummyitem.data = &pubk->u.fortezza.KMID[0];
  480. dummyitem.len = sizeof(pubk->u.fortezza.KMID);
  481. KMID = CERT_Hexify (&dummyitem,0);
  482. htmlcertstrings[25] = KMID;
  483.     } else {
  484. /* clear out the headers in the non-fortezza cases */
  485. htmlcertstrings[18] = "";
  486. htmlcertstrings[19] = "";
  487. htmlcertstrings[20] = "";
  488. htmlcertstrings[21] = "";
  489. htmlcertstrings[22] = "";
  490. htmlcertstrings[23] = "";
  491. htmlcertstrings[24] = "";
  492. htmlcertstrings[25] = "</b>";
  493.     }
  494.     if (pubk) {
  495.       SECKEY_DestroyPublicKey(pubk);
  496.     }
  497. #define HTML_OFF 27
  498.     rv = PK11_HashBuf(SEC_OID_MD5, fingerprint, 
  499.                    cert->derCert.data, cert->derCert.len);
  500.     
  501.     fpitem.data = fingerprint;
  502.     fpitem.len = sizeof(fingerprint);
  503.     fpstr = CERT_Hexify (&fpitem,1);
  504.     
  505.     htmlcertstrings[HTML_OFF] = fpstr;
  506.     commentstring = CERT_GetCertCommentString(cert);
  507.     if (commentstring == NULL) {
  508. htmlcertstrings[HTML_OFF+2] = "";
  509. htmlcertstrings[HTML_OFF+3] = "";
  510. htmlcertstrings[HTML_OFF+4] = "";
  511.     } else {
  512. htmlcertstrings[HTML_OFF+2] =
  513.     "<b>Comment:</b>"
  514.     "<table border=0 cellspacing=0 cellpadding=0><tr>"
  515.     "<td width=10> </td><td><font size=3>"
  516.     "<textarea name=foobar rows=4 cols=55 onfocus="this.blur()">";
  517. htmlcertstrings[HTML_OFF+3] = commentstring;
  518. htmlcertstrings[HTML_OFF+4] = "</textarea></font></td></tr></table>";
  519.     }
  520.     
  521.     ret = gatherStrings(htmlcertstrings);
  522.     
  523.     if ( issuer ) {
  524. PORT_Free(issuer);
  525.     }
  526.     
  527.     if ( subject ) {
  528. PORT_Free(subject);
  529.     }
  530.     
  531.     if ( version ) {
  532. PORT_Free(version);
  533.     }
  534.     
  535.     if ( serialNumber ) {
  536. PORT_Free(serialNumber);
  537.     }
  538.     
  539.     if ( notBefore ) {
  540. PORT_Free(notBefore);
  541.     }
  542.     
  543.     if ( notAfter ) {
  544. PORT_Free(notAfter);
  545.     }
  546.     
  547.     if ( fpstr ) {
  548. PORT_Free(fpstr);
  549.     }
  550.     if (DSSPriv) {
  551. PORT_Free(DSSPriv);
  552.     }
  553.     if (KMID) {
  554. PORT_Free(KMID);
  555.     }
  556.     if ( commentstring ) {
  557. PORT_Free(commentstring);
  558.     }
  559.     
  560.     if ( servername ) {
  561. PORT_Free(servername);
  562.     }
  563.     
  564.     return(ret);
  565. }