PageRenderTime 62ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/cmd/certcgi/certcgi.c

http://github.com/zpao/v8monkey
C | 2408 lines | 2107 code | 224 blank | 77 comment | 557 complexity | c127247590ce3c50e5db505d09422edb MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD

Large files files are truncated, but you can click here to view the full file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. /* Cert-O-Matic CGI */
  37. #include "nspr.h"
  38. #include "prtypes.h"
  39. #include "prtime.h"
  40. #include "prlong.h"
  41. #include "pk11func.h"
  42. #include "cert.h"
  43. #include "cryptohi.h"
  44. #include "secoid.h"
  45. #include "secder.h"
  46. #include "genname.h"
  47. #include "xconst.h"
  48. #include "secutil.h"
  49. #include "pk11pqg.h"
  50. #include "certxutl.h"
  51. #include "nss.h"
  52. /* #define TEST 1 */
  53. /* #define FILEOUT 1 */
  54. /* #define OFFLINE 1 */
  55. #define START_FIELDS 100
  56. #define PREFIX_LEN 6
  57. #define SERIAL_FILE "../serial"
  58. #define DB_DIRECTORY ".."
  59. static char *progName;
  60. typedef struct PairStr Pair;
  61. struct PairStr {
  62. char *name;
  63. char *data;
  64. };
  65. char prefix[PREFIX_LEN];
  66. const SEC_ASN1Template CERTIA5TypeTemplate[] = {
  67. { SEC_ASN1_IA5_STRING }
  68. };
  69. SECKEYPrivateKey *privkeys[9] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  70. NULL, NULL};
  71. #ifdef notdef
  72. const SEC_ASN1Template CERT_GeneralNameTemplate[] = {
  73. { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
  74. };
  75. #endif
  76. static void
  77. error_out(char *error_string)
  78. {
  79. printf("Content-type: text/plain\n\n");
  80. printf(error_string);
  81. fflush(stderr);
  82. fflush(stdout);
  83. exit(1);
  84. }
  85. static void
  86. error_allocate(void)
  87. {
  88. error_out("ERROR: Unable to allocate memory");
  89. }
  90. static char *
  91. make_copy_string(char *read_pos,
  92. int length,
  93. char sentinal_value)
  94. /* copys string from to a new string it creates and
  95. returns a pointer to the new string */
  96. {
  97. int remaining = length;
  98. char *write_pos;
  99. char *new;
  100. new = write_pos = (char *) PORT_Alloc (length);
  101. if (new == NULL) {
  102. error_allocate();
  103. }
  104. while (*read_pos != sentinal_value) {
  105. if (remaining == 1) {
  106. remaining += length;
  107. length = length * 2;
  108. new = PORT_Realloc(new,length);
  109. if (new == NULL) {
  110. error_allocate();
  111. }
  112. write_pos = new + length - remaining;
  113. }
  114. *write_pos = *read_pos;
  115. ++write_pos;
  116. ++read_pos;
  117. remaining = remaining - 1;
  118. }
  119. *write_pos = '\0';
  120. return new;
  121. }
  122. static SECStatus
  123. clean_input(Pair *data)
  124. /* converts the non-alphanumeric characters in a form post
  125. from hex codes back to characters */
  126. {
  127. int length;
  128. int hi_digit;
  129. int low_digit;
  130. char character;
  131. char *begin_pos;
  132. char *read_pos;
  133. char *write_pos;
  134. PRBool name = PR_TRUE;
  135. begin_pos = data->name;
  136. while (begin_pos != NULL) {
  137. length = strlen(begin_pos);
  138. read_pos = write_pos = begin_pos;
  139. while ((read_pos - begin_pos) < length) {
  140. if (*read_pos == '+') {
  141. *read_pos = ' ';
  142. }
  143. if (*read_pos == '%') {
  144. hi_digit = *(read_pos + 1);
  145. low_digit = *(read_pos +2);
  146. read_pos += 3;
  147. if (isdigit(hi_digit)){
  148. hi_digit = hi_digit - '0';
  149. } else {
  150. hi_digit = toupper(hi_digit);
  151. if (isxdigit(hi_digit)) {
  152. hi_digit = (hi_digit - 'A') + 10;
  153. } else {
  154. error_out("ERROR: Form data incorrectly formated");
  155. }
  156. }
  157. if (isdigit(low_digit)){
  158. low_digit = low_digit - '0';
  159. } else {
  160. low_digit = toupper(low_digit);
  161. if ((low_digit >='A') && (low_digit <= 'F')) {
  162. low_digit = (low_digit - 'A') + 10;
  163. } else {
  164. error_out("ERROR: Form data incorrectly formated");
  165. }
  166. }
  167. character = (hi_digit << 4) | low_digit;
  168. if (character != 10) {
  169. *write_pos = character;
  170. ++write_pos;
  171. }
  172. } else {
  173. *write_pos = *read_pos;
  174. ++write_pos;
  175. ++read_pos;
  176. }
  177. }
  178. *write_pos = '\0';
  179. if (name == PR_TRUE) {
  180. begin_pos = data->data;
  181. name = PR_FALSE;
  182. } else {
  183. data++;
  184. begin_pos = data->name;
  185. name = PR_TRUE;
  186. }
  187. }
  188. return SECSuccess;
  189. }
  190. static char *
  191. make_name(char *new_data)
  192. /* gets the next field name in the input string and returns
  193. a pointer to a string containing a copy of it */
  194. {
  195. int length = 20;
  196. char *name;
  197. name = make_copy_string(new_data, length, '=');
  198. return name;
  199. }
  200. static char *
  201. make_data(char *new_data)
  202. /* gets the data for the next field in the input string
  203. and returns a pointer to a string containing it */
  204. {
  205. int length = 100;
  206. char *data;
  207. char *read_pos;
  208. read_pos = new_data;
  209. while (*(read_pos - 1) != '=') {
  210. ++read_pos;
  211. }
  212. data = make_copy_string(read_pos, length, '&');
  213. return data;
  214. }
  215. static Pair
  216. make_pair(char *new_data)
  217. /* makes a pair name/data pair from the input string */
  218. {
  219. Pair temp;
  220. temp.name = make_name(new_data);
  221. temp.data = make_data(new_data);
  222. return temp;
  223. }
  224. static Pair *
  225. make_datastruct(char *data, int len)
  226. /* parses the input from the form post into a data
  227. structure of field name/data pairs */
  228. {
  229. Pair *datastruct;
  230. Pair *current;
  231. char *curr_pos;
  232. int fields = START_FIELDS;
  233. int remaining = START_FIELDS;
  234. curr_pos = data;
  235. datastruct = current = (Pair *) PORT_Alloc(fields * sizeof(Pair));
  236. if (datastruct == NULL) {
  237. error_allocate();
  238. }
  239. while (curr_pos - data < len) {
  240. if (remaining == 1) {
  241. remaining += fields;
  242. fields = fields * 2;
  243. datastruct = (Pair *) PORT_Realloc
  244. (datastruct, fields * sizeof(Pair));
  245. if (datastruct == NULL) {
  246. error_allocate();
  247. }
  248. current = datastruct + (fields - remaining);
  249. }
  250. *current = make_pair(curr_pos);
  251. while (*curr_pos != '&') {
  252. ++curr_pos;
  253. }
  254. ++curr_pos;
  255. ++current;
  256. remaining = remaining - 1;
  257. }
  258. current->name = NULL;
  259. return datastruct;
  260. }
  261. static char *
  262. return_name(Pair *data_struct,
  263. int n)
  264. /* returns a pointer to the name of the nth
  265. (starting from 0) item in the data structure */
  266. {
  267. char *name;
  268. if ((data_struct + n)->name != NULL) {
  269. name = (data_struct + n)->name;
  270. return name;
  271. } else {
  272. return NULL;
  273. }
  274. }
  275. static char *
  276. return_data(Pair *data_struct,int n)
  277. /* returns a pointer to the data of the nth (starting from 0)
  278. itme in the data structure */
  279. {
  280. char *data;
  281. data = (data_struct + n)->data;
  282. return data;
  283. }
  284. static char *
  285. add_prefix(char *field_name)
  286. {
  287. extern char prefix[PREFIX_LEN];
  288. int i = 0;
  289. char *rv;
  290. char *write;
  291. rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1);
  292. for(i = 0; i < PORT_Strlen(prefix); i++) {
  293. *write = prefix[i];
  294. write++;
  295. }
  296. *write = '\0';
  297. rv = PORT_Strcat(rv,field_name);
  298. return rv;
  299. }
  300. static char *
  301. find_field(Pair *data,
  302. char *field_name,
  303. PRBool add_pre)
  304. /* returns a pointer to the data of the first pair
  305. thats name matches the string it is passed */
  306. {
  307. int i = 0;
  308. char *retrieved;
  309. int found = 0;
  310. if (add_pre) {
  311. field_name = add_prefix(field_name);
  312. }
  313. while(return_name(data, i) != NULL) {
  314. if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
  315. retrieved = return_data(data, i);
  316. found = 1;
  317. break;
  318. }
  319. i++;
  320. }
  321. if (!found) {
  322. retrieved = NULL;
  323. }
  324. return retrieved;
  325. }
  326. static PRBool
  327. find_field_bool(Pair *data,
  328. char *fieldname,
  329. PRBool add_pre)
  330. {
  331. char *rv;
  332. rv = find_field(data, fieldname, add_pre);
  333. if ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) {
  334. return PR_TRUE;
  335. } else {
  336. return PR_FALSE;
  337. }
  338. }
  339. static char *
  340. update_data_by_name(Pair *data,
  341. char *field_name,
  342. char *new_data)
  343. /* replaces the data in the data structure associated with
  344. a name with new data, returns null if not found */
  345. {
  346. int i = 0;
  347. int found = 0;
  348. int length = 100;
  349. char *new;
  350. while (return_name(data, i) != NULL) {
  351. if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
  352. new = make_copy_string( new_data, length, '\0');
  353. PORT_Free(return_data(data, i));
  354. found = 1;
  355. (*(data + i)).data = new;
  356. break;
  357. }
  358. i++;
  359. }
  360. if (!found) {
  361. new = NULL;
  362. }
  363. return new;
  364. }
  365. static char *
  366. update_data_by_index(Pair *data,
  367. int n,
  368. char *new_data)
  369. /* replaces the data of a particular index in the data structure */
  370. {
  371. int length = 100;
  372. char *new;
  373. new = make_copy_string(new_data, length, '\0');
  374. PORT_Free(return_data(data, n));
  375. (*(data + n)).data = new;
  376. return new;
  377. }
  378. static Pair *
  379. add_field(Pair *data,
  380. char* field_name,
  381. char* field_data)
  382. /* adds a new name/data pair to the data structure */
  383. {
  384. int i = 0;
  385. int j;
  386. int name_length = 100;
  387. int data_length = 100;
  388. while(return_name(data, i) != NULL) {
  389. i++;
  390. }
  391. j = START_FIELDS;
  392. while ( j < (i + 1) ) {
  393. j = j * 2;
  394. }
  395. if (j == (i + 1)) {
  396. data = (Pair *) PORT_Realloc(data, (j * 2) * sizeof(Pair));
  397. if (data == NULL) {
  398. error_allocate();
  399. }
  400. }
  401. (*(data + i)).name = make_copy_string(field_name, name_length, '\0');
  402. (*(data + i)).data = make_copy_string(field_data, data_length, '\0');
  403. (data + i + 1)->name = NULL;
  404. return data;
  405. }
  406. static CERTCertificateRequest *
  407. makeCertReq(Pair *form_data,
  408. int which_priv_key)
  409. /* makes and encodes a certrequest */
  410. {
  411. PK11SlotInfo *slot;
  412. CERTCertificateRequest *certReq = NULL;
  413. CERTSubjectPublicKeyInfo *spki;
  414. SECKEYPrivateKey *privkey = NULL;
  415. SECKEYPublicKey *pubkey = NULL;
  416. CERTName *name;
  417. char *key;
  418. extern SECKEYPrivateKey *privkeys[9];
  419. int keySizeInBits;
  420. char *challenge = "foo";
  421. SECStatus rv = SECSuccess;
  422. PQGParams *pqgParams = NULL;
  423. PQGVerify *pqgVfy = NULL;
  424. name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE));
  425. if (name == NULL) {
  426. error_out("ERROR: Unable to create Subject Name");
  427. }
  428. key = find_field(form_data, "key", PR_TRUE);
  429. if (key == NULL) {
  430. switch (*find_field(form_data, "keysize", PR_TRUE)) {
  431. case '0':
  432. keySizeInBits = 2048;
  433. break;
  434. case '1':
  435. keySizeInBits = 1024;
  436. break;
  437. case '2':
  438. keySizeInBits = 512;
  439. break;
  440. default:
  441. error_out("ERROR: Unsupported Key length selected");
  442. }
  443. if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) {
  444. rv = PK11_PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy);
  445. if (rv != SECSuccess) {
  446. error_out("ERROR: Unable to generate PQG parameters");
  447. }
  448. slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
  449. privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN,
  450. pqgParams,&pubkey, PR_FALSE,
  451. PR_TRUE, NULL);
  452. } else {
  453. privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL);
  454. }
  455. privkeys[which_priv_key] = privkey;
  456. spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey);
  457. } else {
  458. spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge,
  459. NULL);
  460. if (spki == NULL) {
  461. error_out("ERROR: Unable to decode Public Key and Challenge String");
  462. }
  463. }
  464. certReq = CERT_CreateCertificateRequest(name, spki, NULL);
  465. if (certReq == NULL) {
  466. error_out("ERROR: Unable to create Certificate Request");
  467. }
  468. if (pubkey != NULL) {
  469. SECKEY_DestroyPublicKey(pubkey);
  470. }
  471. if (spki != NULL) {
  472. SECKEY_DestroySubjectPublicKeyInfo(spki);
  473. }
  474. if (pqgParams != NULL) {
  475. PK11_PQG_DestroyParams(pqgParams);
  476. }
  477. if (pqgVfy != NULL) {
  478. PK11_PQG_DestroyVerify(pqgVfy);
  479. }
  480. return certReq;
  481. }
  482. static CERTCertificate *
  483. MakeV1Cert(CERTCertDBHandle *handle,
  484. CERTCertificateRequest *req,
  485. char *issuerNameStr,
  486. PRBool selfsign,
  487. int serialNumber,
  488. int warpmonths,
  489. Pair *data)
  490. {
  491. CERTCertificate *issuerCert = NULL;
  492. CERTValidity *validity;
  493. CERTCertificate *cert = NULL;
  494. PRExplodedTime printableTime;
  495. PRTime now,
  496. after;
  497. SECStatus rv;
  498. if ( !selfsign ) {
  499. issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  500. if (!issuerCert) {
  501. error_out("ERROR: Could not find issuer's certificate");
  502. return NULL;
  503. }
  504. }
  505. if (find_field_bool(data, "manValidity", PR_TRUE)) {
  506. rv = DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE));
  507. } else {
  508. now = PR_Now();
  509. }
  510. PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  511. if ( warpmonths ) {
  512. printableTime.tm_month += warpmonths;
  513. now = PR_ImplodeTime (&printableTime);
  514. PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  515. }
  516. if (find_field_bool(data, "manValidity", PR_TRUE)) {
  517. rv = DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE));
  518. PR_ExplodeTime (after, PR_GMTParameters, &printableTime);
  519. } else {
  520. printableTime.tm_month += 3;
  521. after = PR_ImplodeTime (&printableTime);
  522. }
  523. /* note that the time is now in micro-second unit */
  524. validity = CERT_CreateValidity (now, after);
  525. if ( selfsign ) {
  526. cert = CERT_CreateCertificate
  527. (serialNumber,&(req->subject), validity, req);
  528. } else {
  529. cert = CERT_CreateCertificate
  530. (serialNumber,&(issuerCert->subject), validity, req);
  531. }
  532. CERT_DestroyValidity(validity);
  533. if ( issuerCert ) {
  534. CERT_DestroyCertificate (issuerCert);
  535. }
  536. return(cert);
  537. }
  538. static int
  539. get_serial_number(Pair *data)
  540. {
  541. int serial = 0;
  542. int error;
  543. char *filename = SERIAL_FILE;
  544. char *SN;
  545. FILE *serialFile;
  546. if (find_field_bool(data, "serial-auto", PR_TRUE)) {
  547. serialFile = fopen(filename, "r");
  548. if (serialFile != NULL) {
  549. fread(&serial, sizeof(int), 1, serialFile);
  550. if (ferror(serialFile) != 0) {
  551. error_out("Error: Unable to read serial number file");
  552. }
  553. if (serial == 4294967295) {
  554. serial = 21;
  555. }
  556. fclose(serialFile);
  557. ++serial;
  558. serialFile = fopen(filename,"w");
  559. if (serialFile == NULL) {
  560. error_out("ERROR: Unable to open serial number file for writing");
  561. }
  562. fwrite(&serial, sizeof(int), 1, serialFile);
  563. if (ferror(serialFile) != 0) {
  564. error_out("Error: Unable to write to serial number file");
  565. }
  566. } else {
  567. fclose(serialFile);
  568. serialFile = fopen(filename,"w");
  569. if (serialFile == NULL) {
  570. error_out("ERROR: Unable to open serial number file");
  571. }
  572. serial = 21;
  573. fwrite(&serial, sizeof(int), 1, serialFile);
  574. if (ferror(serialFile) != 0) {
  575. error_out("Error: Unable to write to serial number file");
  576. }
  577. error = ferror(serialFile);
  578. if (error != 0) {
  579. error_out("ERROR: Unable to write to serial file");
  580. }
  581. }
  582. fclose(serialFile);
  583. } else {
  584. SN = find_field(data, "serial_value", PR_TRUE);
  585. while (*SN != '\0') {
  586. serial = serial * 16;
  587. if ((*SN >= 'A') && (*SN <='F')) {
  588. serial += *SN - 'A' + 10;
  589. } else {
  590. if ((*SN >= 'a') && (*SN <='f')) {
  591. serial += *SN - 'a' + 10;
  592. } else {
  593. serial += *SN - '0';
  594. }
  595. }
  596. ++SN;
  597. }
  598. }
  599. return serial;
  600. }
  601. typedef SECStatus (* EXTEN_VALUE_ENCODER)
  602. (PRArenaPool *extHandle, void *value, SECItem *encodedValue);
  603. static SECStatus
  604. EncodeAndAddExtensionValue(
  605. PRArenaPool *arena,
  606. void *extHandle,
  607. void *value,
  608. PRBool criticality,
  609. int extenType,
  610. EXTEN_VALUE_ENCODER EncodeValueFn)
  611. {
  612. SECItem encodedValue;
  613. SECStatus rv;
  614. encodedValue.data = NULL;
  615. encodedValue.len = 0;
  616. rv = (*EncodeValueFn)(arena, value, &encodedValue);
  617. if (rv != SECSuccess) {
  618. error_out("ERROR: Unable to encode extension value");
  619. }
  620. rv = CERT_AddExtension
  621. (extHandle, extenType, &encodedValue, criticality, PR_TRUE);
  622. return (rv);
  623. }
  624. static SECStatus
  625. AddKeyUsage (void *extHandle,
  626. Pair *data)
  627. {
  628. SECItem bitStringValue;
  629. unsigned char keyUsage = 0x0;
  630. if (find_field_bool(data,"keyUsage-digitalSignature", PR_TRUE)){
  631. keyUsage |= (0x80 >> 0);
  632. }
  633. if (find_field_bool(data,"keyUsage-nonRepudiation", PR_TRUE)){
  634. keyUsage |= (0x80 >> 1);
  635. }
  636. if (find_field_bool(data,"keyUsage-keyEncipherment", PR_TRUE)){
  637. keyUsage |= (0x80 >> 2);
  638. }
  639. if (find_field_bool(data,"keyUsage-dataEncipherment", PR_TRUE)){
  640. keyUsage |= (0x80 >> 3);
  641. }
  642. if (find_field_bool(data,"keyUsage-keyAgreement", PR_TRUE)){
  643. keyUsage |= (0x80 >> 4);
  644. }
  645. if (find_field_bool(data,"keyUsage-keyCertSign", PR_TRUE)) {
  646. keyUsage |= (0x80 >> 5);
  647. }
  648. if (find_field_bool(data,"keyUsage-cRLSign", PR_TRUE)) {
  649. keyUsage |= (0x80 >> 6);
  650. }
  651. bitStringValue.data = &keyUsage;
  652. bitStringValue.len = 1;
  653. return (CERT_EncodeAndAddBitStrExtension
  654. (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
  655. (find_field_bool(data, "keyUsage-crit", PR_TRUE))));
  656. }
  657. static CERTOidSequence *
  658. CreateOidSequence(void)
  659. {
  660. CERTOidSequence *rv = (CERTOidSequence *)NULL;
  661. PRArenaPool *arena = (PRArenaPool *)NULL;
  662. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  663. if( (PRArenaPool *)NULL == arena ) {
  664. goto loser;
  665. }
  666. rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
  667. if( (CERTOidSequence *)NULL == rv ) {
  668. goto loser;
  669. }
  670. rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
  671. if( (SECItem **)NULL == rv->oids ) {
  672. goto loser;
  673. }
  674. rv->arena = arena;
  675. return rv;
  676. loser:
  677. if( (PRArenaPool *)NULL != arena ) {
  678. PORT_FreeArena(arena, PR_FALSE);
  679. }
  680. return (CERTOidSequence *)NULL;
  681. }
  682. static SECStatus
  683. AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
  684. {
  685. SECItem **oids;
  686. PRUint32 count = 0;
  687. SECOidData *od;
  688. od = SECOID_FindOIDByTag(oidTag);
  689. if( (SECOidData *)NULL == od ) {
  690. return SECFailure;
  691. }
  692. for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
  693. count++;
  694. }
  695. /* ArenaZRealloc */
  696. {
  697. PRUint32 i;
  698. oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count+2));
  699. if( (SECItem **)NULL == oids ) {
  700. return SECFailure;
  701. }
  702. for( i = 0; i < count; i++ ) {
  703. oids[i] = os->oids[i];
  704. }
  705. /* ArenaZFree(os->oids); */
  706. }
  707. os->oids = oids;
  708. os->oids[count] = &od->oid;
  709. return SECSuccess;
  710. }
  711. static SECItem *
  712. EncodeOidSequence(CERTOidSequence *os)
  713. {
  714. SECItem *rv;
  715. extern const SEC_ASN1Template CERT_OidSeqTemplate[];
  716. rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
  717. if( (SECItem *)NULL == rv ) {
  718. goto loser;
  719. }
  720. if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
  721. goto loser;
  722. }
  723. return rv;
  724. loser:
  725. return (SECItem *)NULL;
  726. }
  727. static SECStatus
  728. AddExtKeyUsage(void *extHandle, Pair *data)
  729. {
  730. SECStatus rv;
  731. CERTOidSequence *os;
  732. SECItem *value;
  733. PRBool crit;
  734. os = CreateOidSequence();
  735. if( (CERTOidSequence *)NULL == os ) {
  736. return SECFailure;
  737. }
  738. if( find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE) ) {
  739. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
  740. if( SECSuccess != rv ) goto loser;
  741. }
  742. if( find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE) ) {
  743. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
  744. if( SECSuccess != rv ) goto loser;
  745. }
  746. if( find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE) ) {
  747. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
  748. if( SECSuccess != rv ) goto loser;
  749. }
  750. if( find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE) ) {
  751. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
  752. if( SECSuccess != rv ) goto loser;
  753. }
  754. if( find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE) ) {
  755. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
  756. if( SECSuccess != rv ) goto loser;
  757. }
  758. if( find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE) ) {
  759. rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
  760. if( SECSuccess != rv ) goto loser;
  761. }
  762. if( find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE) ) {
  763. rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
  764. if( SECSuccess != rv ) goto loser;
  765. }
  766. value = EncodeOidSequence(os);
  767. crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE);
  768. rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value,
  769. crit, PR_TRUE);
  770. /*FALLTHROUGH*/
  771. loser:
  772. CERT_DestroyOidSequence(os);
  773. return rv;
  774. }
  775. static SECStatus
  776. AddSubKeyID(void *extHandle,
  777. Pair *data,
  778. CERTCertificate *subjectCert)
  779. {
  780. SECItem encodedValue;
  781. SECStatus rv;
  782. char *read;
  783. char *write;
  784. char *first;
  785. char character;
  786. int high_digit = 0,
  787. low_digit = 0;
  788. int len;
  789. PRBool odd = PR_FALSE;
  790. encodedValue.data = NULL;
  791. encodedValue.len = 0;
  792. first = read = write = find_field(data,"subjectKeyIdentifier-text",
  793. PR_TRUE);
  794. len = PORT_Strlen(first);
  795. odd = ((len % 2) != 0 ) ? PR_TRUE : PR_FALSE;
  796. if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) {
  797. if (odd) {
  798. error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string");
  799. }
  800. while (*read != '\0') {
  801. if (!isxdigit(*read)) {
  802. error_out("ERROR: Improperly formated subject key identifier");
  803. }
  804. *read = toupper(*read);
  805. if ((*read >= 'A') && (*read <= 'F')) {
  806. high_digit = *read - 'A' + 10;
  807. } else {
  808. high_digit = *read - '0';
  809. }
  810. ++read;
  811. if (!isxdigit(*read)) {
  812. error_out("ERROR: Improperly formated subject key identifier");
  813. }
  814. *read = toupper(*read);
  815. if ((*read >= 'A') && (*read <= 'F')) {
  816. low_digit = *(read) - 'A' + 10;
  817. } else {
  818. low_digit = *(read) - '0';
  819. }
  820. character = (high_digit << 4) | low_digit;
  821. *write = character;
  822. ++write;
  823. ++read;
  824. }
  825. *write = '\0';
  826. len = write - first;
  827. }
  828. subjectCert->subjectKeyID.data = (unsigned char *) find_field
  829. (data,"subjectKeyIdentifier-text", PR_TRUE);
  830. subjectCert->subjectKeyID.len = len;
  831. rv = CERT_EncodeSubjectKeyID
  832. (NULL, &subjectCert->subjectKeyID, &encodedValue);
  833. if (rv) {
  834. return (rv);
  835. }
  836. return (CERT_AddExtension(extHandle, SEC_OID_X509_SUBJECT_KEY_ID,
  837. &encodedValue, PR_FALSE, PR_TRUE));
  838. }
  839. static SECStatus
  840. AddAuthKeyID (void *extHandle,
  841. Pair *data,
  842. char *issuerNameStr,
  843. CERTCertDBHandle *handle)
  844. {
  845. CERTAuthKeyID *authKeyID = NULL;
  846. PRArenaPool *arena = NULL;
  847. SECStatus rv = SECSuccess;
  848. CERTCertificate *issuerCert = NULL;
  849. CERTGeneralName *genNames;
  850. CERTName *directoryName = NULL;
  851. issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  852. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  853. if ( !arena ) {
  854. error_allocate();
  855. }
  856. authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID));
  857. if (authKeyID == NULL) {
  858. error_allocate();
  859. }
  860. if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier",
  861. PR_TRUE)) {
  862. authKeyID->keyID.data = PORT_ArenaAlloc (arena, PORT_Strlen
  863. ((char *)issuerCert->subjectKeyID.data));
  864. if (authKeyID->keyID.data == NULL) {
  865. error_allocate();
  866. }
  867. PORT_Memcpy (authKeyID->keyID.data, issuerCert->subjectKeyID.data,
  868. authKeyID->keyID.len =
  869. PORT_Strlen((char *)issuerCert->subjectKeyID.data));
  870. } else {
  871. PORT_Assert (arena);
  872. genNames = (CERTGeneralName *) PORT_ArenaZAlloc (arena, (sizeof(CERTGeneralName)));
  873. if (genNames == NULL){
  874. error_allocate();
  875. }
  876. genNames->l.next = genNames->l.prev = &(genNames->l);
  877. genNames->type = certDirectoryName;
  878. directoryName = CERT_AsciiToName(issuerCert->subjectName);
  879. if (!directoryName) {
  880. error_out("ERROR: Unable to create Directory Name");
  881. }
  882. rv = CERT_CopyName (arena, &genNames->name.directoryName,
  883. directoryName);
  884. CERT_DestroyName (directoryName);
  885. if (rv != SECSuccess) {
  886. error_out("ERROR: Unable to copy Directory Name");
  887. }
  888. authKeyID->authCertIssuer = genNames;
  889. if (authKeyID->authCertIssuer == NULL && SECFailure ==
  890. PORT_GetError ()) {
  891. error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension");
  892. }
  893. authKeyID->authCertSerialNumber = issuerCert->serialNumber;
  894. }
  895. rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE,
  896. SEC_OID_X509_AUTH_KEY_ID,
  897. (EXTEN_VALUE_ENCODER)
  898. CERT_EncodeAuthKeyID);
  899. if (arena) {
  900. PORT_FreeArena (arena, PR_FALSE);
  901. }
  902. return (rv);
  903. }
  904. static SECStatus
  905. AddPrivKeyUsagePeriod(void *extHandle,
  906. Pair *data,
  907. CERTCertificate *cert)
  908. {
  909. char *notBeforeStr;
  910. char *notAfterStr;
  911. PRArenaPool *arena = NULL;
  912. SECStatus rv = SECSuccess;
  913. CERTPrivKeyUsagePeriod *pkup;
  914. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  915. if ( !arena ) {
  916. error_allocate();
  917. }
  918. pkup = PORT_ArenaZNew (arena, CERTPrivKeyUsagePeriod);
  919. if (pkup == NULL) {
  920. error_allocate();
  921. }
  922. notBeforeStr = (char *) PORT_Alloc(16 );
  923. notAfterStr = (char *) PORT_Alloc(16 );
  924. *notBeforeStr = '\0';
  925. *notAfterStr = '\0';
  926. pkup->arena = arena;
  927. pkup->notBefore.len = 0;
  928. pkup->notBefore.data = NULL;
  929. pkup->notAfter.len = 0;
  930. pkup->notAfter.data = NULL;
  931. if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) ||
  932. find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  933. pkup->notBefore.len = 15;
  934. pkup->notBefore.data = (unsigned char *)notBeforeStr;
  935. if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual",
  936. PR_TRUE)) {
  937. PORT_Strcat(notBeforeStr,find_field(data,
  938. "privKeyUsagePeriod-notBefore-year",
  939. PR_TRUE));
  940. PORT_Strcat(notBeforeStr,find_field(data,
  941. "privKeyUsagePeriod-notBefore-month",
  942. PR_TRUE));
  943. PORT_Strcat(notBeforeStr,find_field(data,
  944. "privKeyUsagePeriod-notBefore-day",
  945. PR_TRUE));
  946. PORT_Strcat(notBeforeStr,find_field(data,
  947. "privKeyUsagePeriod-notBefore-hour",
  948. PR_TRUE));
  949. PORT_Strcat(notBeforeStr,find_field(data,
  950. "privKeyUsagePeriod-notBefore-minute",
  951. PR_TRUE));
  952. PORT_Strcat(notBeforeStr,find_field(data,
  953. "privKeyUsagePeriod-notBefore-second",
  954. PR_TRUE));
  955. if ((*(notBeforeStr + 14) != '\0') ||
  956. (!isdigit(*(notBeforeStr + 13))) ||
  957. (*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') ||
  958. (!isdigit(*(notBeforeStr + 11))) ||
  959. (*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') ||
  960. (!isdigit(*(notBeforeStr + 9))) ||
  961. (*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') ||
  962. (!isdigit(*(notBeforeStr + 7))) ||
  963. (*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') ||
  964. (!isdigit(*(notBeforeStr + 5))) ||
  965. (*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') ||
  966. (!isdigit(*(notBeforeStr + 3))) ||
  967. (!isdigit(*(notBeforeStr + 2))) ||
  968. (!isdigit(*(notBeforeStr + 1))) ||
  969. (!isdigit(*(notBeforeStr + 0))) ||
  970. (*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') ||
  971. (*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') ||
  972. (*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) {
  973. error_out("ERROR: Improperly formated private key usage period");
  974. }
  975. *(notBeforeStr + 14) = 'Z';
  976. *(notBeforeStr + 15) = '\0';
  977. } else {
  978. if ((*(cert->validity.notBefore.data) > '5') ||
  979. ((*(cert->validity.notBefore.data) == '5') &&
  980. (*(cert->validity.notBefore.data + 1) != '0'))) {
  981. PORT_Strcat(notBeforeStr, "19");
  982. } else {
  983. PORT_Strcat(notBeforeStr, "20");
  984. }
  985. PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data);
  986. }
  987. }
  988. if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) ||
  989. find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  990. pkup->notAfter.len = 15;
  991. pkup->notAfter.data = (unsigned char *)notAfterStr;
  992. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-year",
  993. PR_TRUE));
  994. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-month",
  995. PR_TRUE));
  996. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-day",
  997. PR_TRUE));
  998. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-hour",
  999. PR_TRUE));
  1000. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-minute",
  1001. PR_TRUE));
  1002. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-second",
  1003. PR_TRUE));
  1004. if ((*(notAfterStr + 14) != '\0') ||
  1005. (!isdigit(*(notAfterStr + 13))) ||
  1006. (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') ||
  1007. (!isdigit(*(notAfterStr + 11))) ||
  1008. (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') ||
  1009. (!isdigit(*(notAfterStr + 9))) ||
  1010. (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') ||
  1011. (!isdigit(*(notAfterStr + 7))) ||
  1012. (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') ||
  1013. (!isdigit(*(notAfterStr + 5))) ||
  1014. (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') ||
  1015. (!isdigit(*(notAfterStr + 3))) ||
  1016. (!isdigit(*(notAfterStr + 2))) ||
  1017. (!isdigit(*(notAfterStr + 1))) ||
  1018. (!isdigit(*(notAfterStr + 0))) ||
  1019. (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') ||
  1020. (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') ||
  1021. (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) {
  1022. error_out("ERROR: Improperly formated private key usage period");
  1023. }
  1024. *(notAfterStr + 14) = 'Z';
  1025. *(notAfterStr + 15) = '\0';
  1026. }
  1027. PORT_Assert (arena);
  1028. rv = EncodeAndAddExtensionValue(arena, extHandle, pkup,
  1029. find_field_bool(data,
  1030. "privKeyUsagePeriod-crit",
  1031. PR_TRUE),
  1032. SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD,
  1033. (EXTEN_VALUE_ENCODER)
  1034. CERT_EncodePrivateKeyUsagePeriod);
  1035. if (arena) {
  1036. PORT_FreeArena (arena, PR_FALSE);
  1037. }
  1038. if (notBeforeStr != NULL) {
  1039. PORT_Free(notBeforeStr);
  1040. }
  1041. if (notAfterStr != NULL) {
  1042. PORT_Free(notAfterStr);
  1043. }
  1044. return (rv);
  1045. }
  1046. static SECStatus
  1047. AddBasicConstraint(void *extHandle,
  1048. Pair *data)
  1049. {
  1050. CERTBasicConstraints basicConstraint;
  1051. SECItem encodedValue;
  1052. SECStatus rv;
  1053. encodedValue.data = NULL;
  1054. encodedValue.len = 0;
  1055. basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
  1056. basicConstraint.isCA = (find_field_bool(data,"basicConstraints-cA-radio-CA",
  1057. PR_TRUE));
  1058. if (find_field_bool(data,"basicConstraints-pathLengthConstraint", PR_TRUE)){
  1059. basicConstraint.pathLenConstraint = atoi
  1060. (find_field(data,"basicConstraints-pathLengthConstraint-text",
  1061. PR_TRUE));
  1062. }
  1063. rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint,
  1064. &encodedValue);
  1065. if (rv)
  1066. return (rv);
  1067. rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS,
  1068. &encodedValue,
  1069. (find_field_bool(data,"basicConstraints-crit",
  1070. PR_TRUE)), PR_TRUE);
  1071. PORT_Free (encodedValue.data);
  1072. return (rv);
  1073. }
  1074. static SECStatus
  1075. AddNscpCertType (void *extHandle,
  1076. Pair *data)
  1077. {
  1078. SECItem bitStringValue;
  1079. unsigned char CertType = 0x0;
  1080. if (find_field_bool(data,"netscape-cert-type-ssl-client", PR_TRUE)){
  1081. CertType |= (0x80 >> 0);
  1082. }
  1083. if (find_field_bool(data,"netscape-cert-type-ssl-server", PR_TRUE)){
  1084. CertType |= (0x80 >> 1);
  1085. }
  1086. if (find_field_bool(data,"netscape-cert-type-smime", PR_TRUE)){
  1087. CertType |= (0x80 >> 2);
  1088. }
  1089. if (find_field_bool(data,"netscape-cert-type-object-signing", PR_TRUE)){
  1090. CertType |= (0x80 >> 3);
  1091. }
  1092. if (find_field_bool(data,"netscape-cert-type-reserved", PR_TRUE)){
  1093. CertType |= (0x80 >> 4);
  1094. }
  1095. if (find_field_bool(data,"netscape-cert-type-ssl-ca", PR_TRUE)) {
  1096. CertType |= (0x80 >> 5);
  1097. }
  1098. if (find_field_bool(data,"netscape-cert-type-smime-ca", PR_TRUE)) {
  1099. CertType |= (0x80 >> 6);
  1100. }
  1101. if (find_field_bool(data,"netscape-cert-type-object-signing-ca", PR_TRUE)) {
  1102. CertType |= (0x80 >> 7);
  1103. }
  1104. bitStringValue.data = &CertType;
  1105. bitStringValue.len = 1;
  1106. return (CERT_EncodeAndAddBitStrExtension
  1107. (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
  1108. (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE))));
  1109. }
  1110. static SECStatus
  1111. add_IA5StringExtension(void *extHandle,
  1112. char *string,
  1113. PRBool crit,
  1114. int idtag)
  1115. {
  1116. SECItem encodedValue;
  1117. SECStatus rv;
  1118. encodedValue.data = NULL;
  1119. encodedValue.len = 0;
  1120. rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue);
  1121. if (rv) {
  1122. return (rv);
  1123. }
  1124. return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE));
  1125. }
  1126. static SECItem *
  1127. string_to_oid(char *string)
  1128. {
  1129. int i;
  1130. int length = 20;
  1131. int remaining;
  1132. int first_value;
  1133. int second_value;
  1134. int value;
  1135. int oidLength;
  1136. unsigned char *oidString;
  1137. unsigned char *write;
  1138. unsigned char *read;
  1139. unsigned char *temp;
  1140. SECItem *oid;
  1141. remaining = length;
  1142. i = 0;
  1143. while (*string == ' ') {
  1144. string++;
  1145. }
  1146. while (isdigit(*(string + i))) {
  1147. i++;
  1148. }
  1149. if (*(string + i) == '.') {
  1150. *(string + i) = '\0';
  1151. } else {
  1152. error_out("ERROR: Improperly formated OID");
  1153. }
  1154. first_value = atoi(string);
  1155. if (first_value < 0 || first_value > 2) {
  1156. error_out("ERROR: Improperly formated OID");
  1157. }
  1158. string += i + 1;
  1159. i = 0;
  1160. while (isdigit(*(string + i))) {
  1161. i++;
  1162. }
  1163. if (*(string + i) == '.') {
  1164. *(string + i) = '\0';
  1165. } else {
  1166. error_out("ERROR: Improperly formated OID");
  1167. }
  1168. second_value = atoi(string);
  1169. if (second_value < 0 || second_value > 39) {
  1170. error_out("ERROR: Improperly formated OID");
  1171. }
  1172. oidString = PORT_ZAlloc(2);
  1173. *oidString = (first_value * 40) + second_value;
  1174. *(oidString + 1) = '\0';
  1175. oidLength = 1;
  1176. string += i + 1;
  1177. i = 0;
  1178. temp = write = PORT_ZAlloc(length);
  1179. while (*string != '\0') {
  1180. value = 0;
  1181. while(isdigit(*(string + i))) {
  1182. i++;
  1183. }
  1184. if (*(string + i) == '\0') {
  1185. value = atoi(string);
  1186. string += i;
  1187. } else {
  1188. if (*(string + i) == '.') {
  1189. *(string + i) = '\0';
  1190. value = atoi(string);
  1191. string += i + 1;
  1192. } else {
  1193. *(string + i) = '\0';
  1194. i++;
  1195. value = atoi(string);
  1196. while (*(string + i) == ' ')
  1197. i++;
  1198. if (*(string + i) != '\0') {
  1199. error_out("ERROR: Improperly formated OID");
  1200. }
  1201. }
  1202. }
  1203. i = 0;
  1204. while (value != 0) {
  1205. if (remaining < 1) {
  1206. remaining += length;
  1207. length = length * 2;
  1208. temp = PORT_Realloc(temp, length);
  1209. write = temp + length - remaining;
  1210. }
  1211. *write = (value & 0x7f) | (0x80);
  1212. write++;
  1213. remaining--;
  1214. value = value >> 7;
  1215. }
  1216. *temp = *temp & (0x7f);
  1217. oidLength += write - temp;
  1218. oidString = PORT_Realloc(oidString, (oidLength + 1));
  1219. read = write - 1;
  1220. write = oidLength + oidString - 1;
  1221. for (i = 0; i < (length - remaining); i++) {
  1222. *write = *read;
  1223. write--;
  1224. read++;
  1225. }
  1226. write = temp;
  1227. remaining = length;
  1228. }
  1229. *(oidString + oidLength) = '\0';
  1230. oid = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1231. oid->data = oidString;
  1232. oid->len = oidLength;
  1233. PORT_Free(temp);
  1234. return oid;
  1235. }
  1236. static SECItem *
  1237. string_to_ipaddress(char *string)
  1238. {
  1239. int i = 0;
  1240. int value;
  1241. int j = 0;
  1242. SECItem *ipaddress;
  1243. while (*string == ' ') {
  1244. string++;
  1245. }
  1246. ipaddress = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1247. ipaddress->data = PORT_ZAlloc(9);
  1248. while (*string != '\0' && j < 8) {
  1249. while (isdigit(*(string + i))) {
  1250. i++;
  1251. }
  1252. if (*(string + i) == '.') {
  1253. *(string + i) = '\0';
  1254. value = atoi(string);
  1255. string = string + i + 1;
  1256. i = 0;
  1257. } else {
  1258. if (*(string + i) == '\0') {
  1259. value = atoi(string);
  1260. string = string + i;
  1261. i = 0;
  1262. } else {
  1263. *(string + i) = '\0';
  1264. while (*(string + i) == ' ') {
  1265. i++;
  1266. }
  1267. if (*(string + i) == '\0') {
  1268. value = atoi(string);
  1269. string = string + i;
  1270. i = 0;
  1271. } else {
  1272. error_out("ERROR: Improperly formated IP Address");
  1273. }
  1274. }
  1275. }
  1276. if (value >= 0 || value < 256) {
  1277. *(ipaddress->data + j) = value;
  1278. } else {
  1279. error_out("ERROR: Improperly formated IP Address");
  1280. }
  1281. j++;
  1282. }
  1283. *(ipaddress->data + j) = '\0';
  1284. if (j != 4 && j != 8) {
  1285. error_out("ERROR: Improperly formated IP Address");
  1286. }
  1287. ipaddress->len = j;
  1288. return ipaddress;
  1289. }
  1290. static SECItem *
  1291. string_to_binary(char *string)
  1292. {
  1293. SECItem *rv;
  1294. int high_digit;
  1295. int low_digit;
  1296. rv = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1297. if (rv == NULL) {
  1298. error_allocate();
  1299. }
  1300. rv->data = (unsigned char *) PORT_ZAlloc((PORT_Strlen(string))/3 + 2);
  1301. while (!isxdigit(*string)) {
  1302. string++;
  1303. }
  1304. rv->len = 0;
  1305. while (*string != '\0') {
  1306. if (isxdigit(*string)) {
  1307. if (*string >= '0' && *string <= '9') {
  1308. high_digit = *string - '0';
  1309. } else {
  1310. *string = toupper(*string);
  1311. high_digit = *string - 'A';
  1312. }
  1313. string++;
  1314. if (*string >= '0' && *string <= '9') {
  1315. low_digit = *string - '0';
  1316. } else {
  1317. *string = toupper(*string);
  1318. low_digit = *string = 'A';
  1319. }
  1320. (rv->len)++;
  1321. } else {
  1322. if (*string == ':') {
  1323. string++;
  1324. } else {
  1325. if (*string == ' ') {
  1326. while (*string == ' ') {
  1327. string++;
  1328. }
  1329. }
  1330. if (*string != '\0') {
  1331. error_out("ERROR: Improperly formated binary encoding");
  1332. }
  1333. }
  1334. }
  1335. }
  1336. return rv;
  1337. }
  1338. static SECStatus
  1339. MakeGeneralName(char *name,
  1340. CERTGeneralName *genName,
  1341. PRArenaPool *arena)
  1342. {
  1343. SECItem *oid;
  1344. SECOidData *oidData;
  1345. SECItem *ipaddress;
  1346. SECItem *temp = NULL;
  1347. int i;
  1348. int nameType;
  1349. PRBool binary = PR_FALSE;
  1350. SECStatus rv = SECSuccess;
  1351. PRBool nickname = PR_FALSE;
  1352. PORT_Assert(genName);
  1353. PORT_Assert(arena);
  1354. nameType = *(name + PORT_Strlen(name) - 1) - '0';
  1355. if (nameType == 0 && *(name +PORT_Strlen(name) - 2) == '1') {
  1356. nickname = PR_TRUE;
  1357. nameType = certOtherName;
  1358. }
  1359. if (nameType < 1 || nameType > 9) {
  1360. error_out("ERROR: Unknown General Name Type");
  1361. }
  1362. *(name + PORT_Strlen(name) - 4) = '\0';
  1363. genName->type = nameType;
  1364. switch (genName->type) {
  1365. case certURI:
  1366. case certRFC822Name:
  1367. case certDNSName: {
  1368. genName->name.other.data = (unsigned char *)name;
  1369. genName->name.other.len = PORT_Strlen(name);
  1370. break;
  1371. }
  1372. case certIPAddress: {
  1373. ipaddress = string_to_ipaddress(name);
  1374. genName->name.other.data = ipaddress->data;
  1375. genName->name.other.len = ipaddress->len;
  1376. break;
  1377. }
  1378. case certRegisterID: {
  1379. oid = string_to_oid(name);
  1380. genName->name.other.data = oid->data;
  1381. genName->name.other.len = oid->len;
  1382. break;
  1383. }
  1384. case certEDIPartyName:
  1385. case certX400Address: {
  1386. genName->name.other.data = PORT_ArenaAlloc (arena,
  1387. PORT_Strlen (name) + 2);
  1388. if (genName->name.other.data == NULL) {
  1389. error_allocate();
  1390. }
  1391. PORT_Memcpy (genName->name.other.data + 2, name, PORT_Strlen (name));
  1392. /* This may not be accurate for all cases.
  1393. For now, use this tag type */
  1394. genName->name.other.data[0] = (char)(((genName->type - 1) &
  1395. 0x1f)| 0x80);
  1396. genName->name.other.data[1] = (char)PORT_Strlen (name);
  1397. genName->name.other.len = PORT_Strlen (name) + 2;
  1398. break;
  1399. }
  1400. case certOtherName: {
  1401. i = 0;
  1402. if (!nickname) {
  1403. while (!isdigit(*(name + PORT_Strlen(name) - i))) {
  1404. i++;
  1405. }
  1406. if (*(name + PORT_Strlen(name) - i) == '1') {
  1407. binary = PR_TRUE;
  1408. } else {
  1409. binary = PR_FALSE;
  1410. }
  1411. while (*(name + PORT_Strlen(name) - i) != '-') {
  1412. i++;
  1413. }
  1414. *(name + PORT_Strlen(name) - i - 1) = '\0';
  1415. i = 0;
  1416. while (*(name + i) != '-') {
  1417. i++;
  1418. }
  1419. *(name + i - 1) = '\0';
  1420. oid = string_to_oid(name + i + 2);
  1421. } else {
  1422. oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME);
  1423. oid = &oidData->oid;
  1424. while (*(name + PORT_Strlen(name) - i) != '-') {
  1425. i++;
  1426. }
  1427. *(name + PORT_Strlen(name) - i) = '\0';
  1428. }
  1429. genName->name.OthName.oid.data = oid->data;
  1430. genName->name.OthName.oid.len = oid->len;
  1431. if (binary) {
  1432. temp = string_to_binary(name);
  1433. genName->name.OthName.name.data = temp->data;
  1434. genName->name.OthName.name.len = temp->len;
  1435. } else {
  1436. temp = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1437. if (temp == NULL) {
  1438. error_allocate();
  1439. }
  1440. temp->data = (unsigned char *)name;
  1441. temp->len = PORT_Strlen(name);
  1442. SEC_ASN1EncodeItem (arena, &(genName->name.OthName.name), temp,
  1443. CERTIA5TypeTemplate);
  1444. }
  1445. PORT_Free(temp);
  1446. break;
  1447. }
  1448. case certDirectoryName: {
  1449. CERTName *directoryName = NULL;
  1450. directoryName = CERT_AsciiToName (name);
  1451. if (!directoryName) {
  1452. error_out("ERROR: Improperly formated alternative name");
  1453. break;
  1454. }
  1455. rv = CERT_CopyName (arena, &genName->name.directoryName,
  1456. directoryName);
  1457. CERT_DestroyName (directoryName);
  1458. break;
  1459. }
  1460. }
  1461. genName->l.next = &(genName->l);
  1462. genName->l.prev = &(genName->l);
  1463. return rv;
  1464. }
  1465. static CERTGeneralName *
  1466. MakeAltName(Pair *data,
  1467. char *which,
  1468. PRArenaPool *arena)
  1469. {
  1470. CERTGeneralName *SubAltName;
  1471. CERTGeneralName *current;
  1472. CERTGeneralName *newname;
  1473. char *name = NULL;
  1474. SECStatus rv = SECSuccess;
  1475. int len;
  1476. len = PORT_Strlen(which);
  1477. name = find_field(data, which, PR_TRUE);
  1478. SubAltName = current = (CERTGeneralName *) PORT_ZAlloc
  1479. (sizeof(CERTGeneralName));
  1480. if (current == NULL) {
  1481. error_allocate();
  1482. }
  1483. while (name != NULL) {
  1484. rv = MakeGeneralName(name, current, arena);
  1485. if (rv != SECSuccess) {
  1486. break;
  1487. }
  1488. if (*(which + len -1) < '9') {
  1489. *(which + len - 1) = *(which + len - 1) + 1;
  1490. } else {
  1491. if (isdigit(*(which + len - 2) )) {
  1492. *(which + len - 2) = *(which + len - 2) + 1;
  1493. *(which + len - 1) = '0';
  1494. } else {
  1495. *(which + len - 1) = '1';
  1496. *(which + len) = '0';
  1497. *(which + len + 1) = '\0';
  1498. len++;
  1499. }
  1500. }
  1501. len = PORT_Strlen(which);
  1502. name = find_field(data, which, PR_TRUE);
  1503. if (name != NULL) {
  1504. newname = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
  1505. if (newname == NULL) {
  1506. error_allocate();
  1507. }
  1508. current->l.next = &(newname->l);
  1509. newname->l.prev = &(current->l);
  1510. current = newname;
  1511. newname = NULL;
  1512. } else {
  1513. current->l.next = &(SubAltName->l);
  1514. SubAltName->l.prev = &(current->l);
  1515. }
  1516. }
  1517. if (rv == SECFailure) {
  1518. return NULL;
  1519. }
  1520. return SubAltName;
  1521. }
  1522. static CERTNameConstraints *
  1523. MakeNameConstraints(Pair *data,
  1524. PRArenaPool *arena)
  1525. {
  1526. CERTNameConstraints *NameConstraints;
  1527. CERTNameConstraint *current = NULL;
  1528. CERTNameConstraint *last_permited = NULL;
  1529. CERTNameConstraint *last_excluded = NULL;
  1530. char *constraint = NULL;
  1531. char *which;
  1532. SECStatus rv = SECSuccess;
  1533. int len;
  1534. int i;
  1535. long max;
  1536. long min;
  1537. PRBool permited;
  1538. NameConstraints = (CERTNameConstraints *) PORT_ZAlloc
  1539. (sizeof(CERTNameConstraints));
  1540. which = make_copy_string("NameConstraintSelect0", 25,'\0');
  1541. len = PORT_Strlen(which);
  1542. constraint = find_field(data, which, PR_TRUE);
  1543. NameConstraints->permited = NameConstraints->excluded = NULL;
  1544. while (constraint != NULL) {
  1545. current = (CERTNameConstraint *) PORT_ZAlloc
  1546. (sizeof(CERTNameConstraint));
  1547. if (current == NULL) {
  1548. error_allocate();
  1549. }
  1550. i = 0;
  1551. while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1552. i++;
  1553. }
  1554. *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
  1555. max = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1556. if (max > 0) {
  1557. (void) SEC_ASN1EncodeInteger(arena, &current->max, max);
  1558. }
  1559. i = 0;
  1560. while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1561. i++;
  1562. }
  1563. *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
  1564. min = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1565. (void) SEC_ASN1EncodeInteger(arena, &current->min, min);
  1566. while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1567. i++;
  1568. }
  1569. *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
  1570. if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') {
  1571. permited = PR_TRUE;
  1572. } else {
  1573. permited = PR_FALSE;
  1574. }
  1575. rv = MakeGeneralName(constraint, &(current->name), arena);
  1576. if (rv != SECSuccess) {
  1577. break;
  1578. }
  1579. if (*(which + len - 1) < '9') {
  1580. *(which + len - 1) = *(which + len - 1) + 1;
  1581. } else {
  1582. if (isdigit(*(which + len - 2) )) {
  1583. *(which + len - 2) = *(which + len - 2) + 1;
  1584. *(which + len - 1) = '0';
  1585. } else {
  1586. *(which + len - 1) = '1';
  1587. *(which + len) = '0';
  1588. *(which + len + 1) = '\0';
  1589. len++;
  1590. }
  1591. }
  1592. len = PORT_Strlen(which);
  1593. if (permited) {
  1594. if (NameConstraints->permited == NULL) {
  1595. NameConstraints->permited = last_permited = current;
  1596. }
  1597. last_permited->l.next = &(current->l);
  1598. current->l.prev = &(last_permited->l);
  1599. last_permited = current;
  1600. } else {
  1601. if (NameConstraints->excluded == NULL) {
  1602. NameConstraints->excluded = last_excluded = current;
  1603. }
  1604. last_excluded->l.next = &(current->l);
  1605. current->l.prev = &(last_excluded->l);
  1606. last_excluded = current;
  1607. }
  1608. constraint = find_field(data, which, PR_TRUE);
  1609. if (constraint != NULL) {
  1610. current = (CERTNameConstraint *) PORT_ZAlloc(sizeof(CERTNameConstraint));
  1611. if (current == NULL) {
  1612. error_allocate();
  1613. }
  1614. }
  1615. }
  1616. if (NameConstraints->permited != NULL) {
  1617. last_permited->l.next = &(NameConstraints->permited->l);
  1618. NameConstraints->permited->l.prev = &(last_permited->l);
  1619. }
  1620. if (NameConstraints->excluded != NULL) {
  1621. last_excluded->l.next = &(NameConstraints->excluded->l);
  1622. NameConstraints->excluded->l.prev = &(last_excluded->l);
  1623. }
  1624. if (which != NULL) {
  1625. PORT_Free(which);
  1626. }
  1627. if (rv == SECFailure) {
  1628. return NULL;
  1629. }
  1630. return NameConstraints;
  1631. }
  1632. static SECStatus
  1633. AddAltName(void *extHandle,
  1634. Pair *data,
  1635. char *issuerNameStr,
  1636. CERTCertDBHandle *handle,
  1637. int type)
  1638. {
  1639. PRBool autoIssuer = PR_FALSE;
  1640. PRArenaPool *arena = NULL;
  1641. CERTGeneralName *genName = NULL;
  1642. char *which = NULL;
  1643. char *name = NULL;
  1644. SECStatus rv = SECSuccess;
  1645. SECItem *issuersAltName = NULL;
  1646. CERTCertificate *issuerCert = NULL;
  1647. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1648. if (arena == NULL) {
  1649. error_allocate();
  1650. }
  1651. if (type == 0) {
  1652. which = make_copy_string("SubAltNameSelect0", 20,'\0');
  1653. genName = MakeAltName(data, which, arena);
  1654. } else {
  1655. if (autoIssuer) {
  1656. autoIssuer = find_field_bool(data,"IssuerAltNameSourceRadio-auto",
  1657. PR_TRUE);
  1658. issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  1659. rv = cert_FindExtension((*issuerCert).extensions,
  1660. SEC_OID_X509_SUBJECT_ALT_NAME,
  1661. issuersAltName);
  1662. if (issuersA

Large files files are truncated, but you can click here to view the full file