certhtml.c 9.0 KB

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