PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/security/nss/cmd/certutil/certext.c

http://github.com/zpao/v8monkey
C | 1817 lines | 1471 code | 238 blank | 108 comment | 385 complexity | 80abf726914889ad06d1182531db211d 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
  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. * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. ** certext.c
  39. **
  40. ** part of certutil for managing certificates extensions
  41. **
  42. */
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <stdlib.h>
  46. #if defined(WIN32)
  47. #include "fcntl.h"
  48. #include "io.h"
  49. #endif
  50. #include "secutil.h"
  51. #if defined(XP_UNIX)
  52. #include <unistd.h>
  53. #endif
  54. #include "cert.h"
  55. #include "xconst.h"
  56. #include "prprf.h"
  57. #include "certutil.h"
  58. #define GEN_BREAK(e) rv=e; break;
  59. static char *
  60. Gets_s(char *buff, size_t size) {
  61. char *str;
  62. if (buff == NULL || size < 1) {
  63. PORT_Assert(0);
  64. return NULL;
  65. }
  66. if ((str = fgets(buff, size, stdin)) != NULL) {
  67. int len = PORT_Strlen(str);
  68. /*
  69. * fgets() automatically converts native text file
  70. * line endings to '\n'. As defensive programming
  71. * (just in case fgets has a bug or we put stdin in
  72. * binary mode by mistake), we handle three native
  73. * text file line endings here:
  74. * '\n' Unix (including Linux and Mac OS X)
  75. * '\r''\n' DOS/Windows & OS/2
  76. * '\r' Mac OS Classic
  77. * len can not be less then 1, since in case with
  78. * empty string it has at least '\n' in the buffer
  79. */
  80. if (buff[len - 1] == '\n' || buff[len - 1] == '\r') {
  81. buff[len - 1] = '\0';
  82. if (len > 1 && buff[len - 2] == '\r')
  83. buff[len - 2] = '\0';
  84. }
  85. } else {
  86. buff[0] = '\0';
  87. }
  88. return str;
  89. }
  90. static SECStatus
  91. PrintChoicesAndGetAnswer(char* str, char* rBuff, int rSize)
  92. {
  93. fputs(str, stdout);
  94. fputs(" > ", stdout);
  95. fflush (stdout);
  96. if (Gets_s(rBuff, rSize) == NULL) {
  97. PORT_SetError(SEC_ERROR_INPUT_LEN);
  98. return SECFailure;
  99. }
  100. return SECSuccess;
  101. }
  102. static CERTGeneralName *
  103. GetGeneralName (PRArenaPool *arena)
  104. {
  105. CERTGeneralName *namesList = NULL;
  106. CERTGeneralName *current;
  107. CERTGeneralName *tail = NULL;
  108. SECStatus rv = SECSuccess;
  109. int intValue;
  110. char buffer[512];
  111. void *mark;
  112. PORT_Assert (arena);
  113. mark = PORT_ArenaMark (arena);
  114. do {
  115. if (PrintChoicesAndGetAnswer(
  116. "\nSelect one of the following general name type: \n"
  117. "\t2 - rfc822Name\n"
  118. "\t3 - dnsName\n"
  119. "\t5 - directoryName\n"
  120. "\t7 - uniformResourceidentifier\n"
  121. "\t8 - ipAddress\n"
  122. "\t9 - registerID\n"
  123. "\tAny other number to finish\n"
  124. "\t\tChoice:", buffer, sizeof(buffer)) == SECFailure) {
  125. GEN_BREAK (SECFailure);
  126. }
  127. intValue = PORT_Atoi (buffer);
  128. /*
  129. * Should use ZAlloc instead of Alloc to avoid problem with garbage
  130. * initialized pointers in CERT_CopyName
  131. */
  132. switch (intValue) {
  133. case certRFC822Name:
  134. case certDNSName:
  135. case certDirectoryName:
  136. case certURI:
  137. case certIPAddress:
  138. case certRegisterID:
  139. break;
  140. default:
  141. intValue = 0; /* force a break for anything else */
  142. }
  143. if (intValue == 0)
  144. break;
  145. if (namesList == NULL) {
  146. namesList = current = tail =
  147. PORT_ArenaZNew(arena, CERTGeneralName);
  148. } else {
  149. current = PORT_ArenaZNew(arena, CERTGeneralName);
  150. }
  151. if (current == NULL) {
  152. GEN_BREAK (SECFailure);
  153. }
  154. current->type = intValue;
  155. puts ("\nEnter data:");
  156. fflush (stdout);
  157. if (Gets_s (buffer, sizeof(buffer)) == NULL) {
  158. PORT_SetError(SEC_ERROR_INPUT_LEN);
  159. GEN_BREAK (SECFailure);
  160. }
  161. switch (current->type) {
  162. case certURI:
  163. case certDNSName:
  164. case certRFC822Name:
  165. current->name.other.data =
  166. PORT_ArenaAlloc (arena, strlen (buffer));
  167. if (current->name.other.data == NULL) {
  168. GEN_BREAK (SECFailure);
  169. }
  170. PORT_Memcpy(current->name.other.data, buffer,
  171. current->name.other.len = strlen(buffer));
  172. break;
  173. case certEDIPartyName:
  174. case certIPAddress:
  175. case certOtherName:
  176. case certRegisterID:
  177. case certX400Address: {
  178. current->name.other.data =
  179. PORT_ArenaAlloc (arena, strlen (buffer) + 2);
  180. if (current->name.other.data == NULL) {
  181. GEN_BREAK (SECFailure);
  182. }
  183. PORT_Memcpy (current->name.other.data + 2, buffer,
  184. strlen (buffer));
  185. /* This may not be accurate for all cases. For now,
  186. * use this tag type */
  187. current->name.other.data[0] =
  188. (char)(((current->type - 1) & 0x1f)| 0x80);
  189. current->name.other.data[1] = (char)strlen (buffer);
  190. current->name.other.len = strlen (buffer) + 2;
  191. break;
  192. }
  193. case certDirectoryName: {
  194. CERTName *directoryName = NULL;
  195. directoryName = CERT_AsciiToName (buffer);
  196. if (!directoryName) {
  197. fprintf(stderr, "certutil: improperly formatted name: "
  198. "\"%s\"\n", buffer);
  199. break;
  200. }
  201. rv = CERT_CopyName (arena, &current->name.directoryName,
  202. directoryName);
  203. CERT_DestroyName (directoryName);
  204. break;
  205. }
  206. }
  207. if (rv != SECSuccess)
  208. break;
  209. current->l.next = &(namesList->l);
  210. current->l.prev = &(tail->l);
  211. tail->l.next = &(current->l);
  212. tail = current;
  213. }while (1);
  214. if (rv != SECSuccess) {
  215. PORT_ArenaRelease (arena, mark);
  216. namesList = NULL;
  217. }
  218. return (namesList);
  219. }
  220. static SECStatus
  221. GetString(PRArenaPool *arena, char *prompt, SECItem *value)
  222. {
  223. char buffer[251];
  224. char *buffPrt;
  225. buffer[0] = '\0';
  226. value->data = NULL;
  227. value->len = 0;
  228. puts (prompt);
  229. buffPrt = Gets_s (buffer, sizeof(buffer));
  230. /* returned NULL here treated the same way as empty string */
  231. if (buffPrt && strlen (buffer) > 0) {
  232. value->data = PORT_ArenaAlloc (arena, strlen (buffer));
  233. if (value->data == NULL) {
  234. PORT_SetError (SEC_ERROR_NO_MEMORY);
  235. return (SECFailure);
  236. }
  237. PORT_Memcpy (value->data, buffer, value->len = strlen(buffer));
  238. }
  239. return (SECSuccess);
  240. }
  241. static PRBool
  242. GetYesNo(char *prompt)
  243. {
  244. char buf[3];
  245. char *buffPrt;
  246. buf[0] = 'n';
  247. puts(prompt);
  248. buffPrt = Gets_s(buf, sizeof(buf));
  249. return (buffPrt && (buf[0] == 'y' || buf[0] == 'Y')) ? PR_TRUE : PR_FALSE;
  250. }
  251. /* Parses comma separated values out of the string pointed by nextPos.
  252. * Parsed value is compared to an array of possible values(valueArray).
  253. * If match is found, a value index is returned, otherwise returns SECFailue.
  254. * nextPos is set to the token after found comma separator or to NULL.
  255. * NULL in nextPos should be used as indication of the last parsed token.
  256. * A special value "critical" can be parsed out from the supplied sting.*/
  257. static SECStatus
  258. parseNextCmdInput(const char * const *valueArray, int *value, char **nextPos,
  259. PRBool *critical)
  260. {
  261. char *thisPos = *nextPos;
  262. int keyLen = 0;
  263. int arrIndex = 0;
  264. if (!valueArray || !value || !nextPos || !critical) {
  265. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  266. return SECFailure;
  267. }
  268. while (1) {
  269. if ((*nextPos = strchr(thisPos, ',')) == NULL) {
  270. keyLen = strlen(thisPos);
  271. } else {
  272. keyLen = *nextPos - thisPos;
  273. *nextPos += 1;
  274. }
  275. /* if critical keyword is found, go for another loop,
  276. * but check, if it is the last keyword of
  277. * the string.*/
  278. if (!strncmp("critical", thisPos, keyLen)) {
  279. *critical = PR_TRUE;
  280. if (*nextPos == NULL) {
  281. return SECSuccess;
  282. }
  283. thisPos = *nextPos;
  284. continue;
  285. }
  286. break;
  287. }
  288. for (arrIndex = 0; valueArray[arrIndex]; arrIndex++) {
  289. if (!strncmp(valueArray[arrIndex], thisPos, keyLen)) {
  290. *value = arrIndex;
  291. return SECSuccess;
  292. }
  293. }
  294. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  295. return SECFailure;
  296. }
  297. static const char * const
  298. keyUsageKeyWordArray[] = { "digitalSignature",
  299. "nonRepudiation",
  300. "keyEncipherment",
  301. "dataEncipherment",
  302. "keyAgreement",
  303. "certSigning",
  304. "crlSigning",
  305. NULL};
  306. static SECStatus
  307. AddKeyUsage (void *extHandle, const char *userSuppliedValue)
  308. {
  309. SECItem bitStringValue;
  310. unsigned char keyUsage = 0x0;
  311. char buffer[5];
  312. int value;
  313. char *nextPos = (char*)userSuppliedValue;
  314. PRBool isCriticalExt = PR_FALSE;
  315. if (!userSuppliedValue) {
  316. while (1) {
  317. if (PrintChoicesAndGetAnswer(
  318. "\t\t0 - Digital Signature\n"
  319. "\t\t1 - Non-repudiation\n"
  320. "\t\t2 - Key encipherment\n"
  321. "\t\t3 - Data encipherment\n"
  322. "\t\t4 - Key agreement\n"
  323. "\t\t5 - Cert signing key\n"
  324. "\t\t6 - CRL signing key\n"
  325. "\t\tOther to finish\n",
  326. buffer, sizeof(buffer)) == SECFailure) {
  327. return SECFailure;
  328. }
  329. value = PORT_Atoi (buffer);
  330. if (value < 0 || value > 6)
  331. break;
  332. if (value == 0) {
  333. /* Checking that zero value of variable 'value'
  334. * corresponds to '0' input made by user */
  335. char *chPtr = strchr(buffer, '0');
  336. if (chPtr == NULL) {
  337. continue;
  338. }
  339. }
  340. keyUsage |= (0x80 >> value);
  341. }
  342. isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
  343. } else {
  344. while (1) {
  345. if (parseNextCmdInput(keyUsageKeyWordArray, &value, &nextPos,
  346. &isCriticalExt) == SECFailure) {
  347. return SECFailure;
  348. }
  349. keyUsage |= (0x80 >> value);
  350. if (!nextPos)
  351. break;
  352. }
  353. }
  354. bitStringValue.data = &keyUsage;
  355. bitStringValue.len = 1;
  356. return (CERT_EncodeAndAddBitStrExtension
  357. (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
  358. isCriticalExt));
  359. }
  360. static CERTOidSequence *
  361. CreateOidSequence(void)
  362. {
  363. CERTOidSequence *rv = (CERTOidSequence *)NULL;
  364. PRArenaPool *arena = (PRArenaPool *)NULL;
  365. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  366. if( (PRArenaPool *)NULL == arena ) {
  367. goto loser;
  368. }
  369. rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence);
  370. if( (CERTOidSequence *)NULL == rv ) {
  371. goto loser;
  372. }
  373. rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *);
  374. if( (SECItem **)NULL == rv->oids ) {
  375. goto loser;
  376. }
  377. rv->arena = arena;
  378. return rv;
  379. loser:
  380. if( (PRArenaPool *)NULL != arena ) {
  381. PORT_FreeArena(arena, PR_FALSE);
  382. }
  383. return (CERTOidSequence *)NULL;
  384. }
  385. static void
  386. DestroyOidSequence(CERTOidSequence *os)
  387. {
  388. if (os->arena) {
  389. PORT_FreeArena(os->arena, PR_FALSE);
  390. }
  391. }
  392. static SECStatus
  393. AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
  394. {
  395. SECItem **oids;
  396. PRUint32 count = 0;
  397. SECOidData *od;
  398. od = SECOID_FindOIDByTag(oidTag);
  399. if( (SECOidData *)NULL == od ) {
  400. return SECFailure;
  401. }
  402. for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
  403. if (*oids == &od->oid) {
  404. /* We already have this oid */
  405. return SECSuccess;
  406. }
  407. count++;
  408. }
  409. /* ArenaZRealloc */
  410. {
  411. PRUint32 i;
  412. oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2);
  413. if( (SECItem **)NULL == oids ) {
  414. return SECFailure;
  415. }
  416. for( i = 0; i < count; i++ ) {
  417. oids[i] = os->oids[i];
  418. }
  419. /* ArenaZFree(os->oids); */
  420. }
  421. os->oids = oids;
  422. os->oids[count] = &od->oid;
  423. return SECSuccess;
  424. }
  425. SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
  426. const SEC_ASN1Template CERT_OidSeqTemplate[] = {
  427. { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
  428. SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
  429. };
  430. static SECItem *
  431. EncodeOidSequence(CERTOidSequence *os)
  432. {
  433. SECItem *rv;
  434. rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem);
  435. if( (SECItem *)NULL == rv ) {
  436. goto loser;
  437. }
  438. if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
  439. goto loser;
  440. }
  441. return rv;
  442. loser:
  443. return (SECItem *)NULL;
  444. }
  445. static const char * const
  446. extKeyUsageKeyWordArray[] = { "serverAuth",
  447. "clientAuth",
  448. "codeSigning",
  449. "emailProtection",
  450. "timeStamp",
  451. "ocspResponder",
  452. "stepUp",
  453. NULL};
  454. static SECStatus
  455. AddExtKeyUsage (void *extHandle, const char *userSuppliedValue)
  456. {
  457. char buffer[5];
  458. int value;
  459. CERTOidSequence *os;
  460. SECStatus rv;
  461. SECItem *item;
  462. PRBool isCriticalExt = PR_FALSE;
  463. char *nextPos = (char*)userSuppliedValue;
  464. os = CreateOidSequence();
  465. if( (CERTOidSequence *)NULL == os ) {
  466. return SECFailure;
  467. }
  468. while (1) {
  469. if (!userSuppliedValue) {
  470. if (PrintChoicesAndGetAnswer(
  471. "\t\t0 - Server Auth\n"
  472. "\t\t1 - Client Auth\n"
  473. "\t\t2 - Code Signing\n"
  474. "\t\t3 - Email Protection\n"
  475. "\t\t4 - Timestamp\n"
  476. "\t\t5 - OCSP Responder\n"
  477. "\t\t6 - Step-up\n"
  478. "\t\tOther to finish\n",
  479. buffer, sizeof(buffer)) == SECFailure) {
  480. GEN_BREAK(SECFailure);
  481. }
  482. value = PORT_Atoi(buffer);
  483. if (value == 0) {
  484. /* Checking that zero value of variable 'value'
  485. * corresponds to '0' input made by user */
  486. char *chPtr = strchr(buffer, '0');
  487. if (chPtr == NULL) {
  488. continue;
  489. }
  490. }
  491. } else {
  492. if (parseNextCmdInput(extKeyUsageKeyWordArray, &value, &nextPos,
  493. &isCriticalExt) == SECFailure) {
  494. return SECFailure;
  495. }
  496. }
  497. switch( value ) {
  498. case 0:
  499. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
  500. break;
  501. case 1:
  502. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
  503. break;
  504. case 2:
  505. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
  506. break;
  507. case 3:
  508. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
  509. break;
  510. case 4:
  511. rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
  512. break;
  513. case 5:
  514. rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
  515. break;
  516. case 6:
  517. rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
  518. break;
  519. default:
  520. goto endloop;
  521. }
  522. if (userSuppliedValue && !nextPos)
  523. break;
  524. if( SECSuccess != rv )
  525. goto loser;
  526. }
  527. endloop:
  528. item = EncodeOidSequence(os);
  529. if (!userSuppliedValue) {
  530. isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
  531. }
  532. rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
  533. isCriticalExt, PR_TRUE);
  534. /*FALLTHROUGH*/
  535. loser:
  536. DestroyOidSequence(os);
  537. return rv;
  538. }
  539. static const char * const
  540. nsCertTypeKeyWordArray[] = { "sslClient",
  541. "sslServer",
  542. "smime",
  543. "objectSigning",
  544. "Not!Used",
  545. "sslCA",
  546. "smimeCA",
  547. "objectSigningCA",
  548. NULL };
  549. static SECStatus
  550. AddNscpCertType (void *extHandle, const char *userSuppliedValue)
  551. {
  552. SECItem bitStringValue;
  553. unsigned char keyUsage = 0x0;
  554. char buffer[5];
  555. int value;
  556. char *nextPos = (char*)userSuppliedValue;
  557. PRBool isCriticalExt = PR_FALSE;
  558. if (!userSuppliedValue) {
  559. while (1) {
  560. if (PrintChoicesAndGetAnswer(
  561. "\t\t0 - SSL Client\n"
  562. "\t\t1 - SSL Server\n"
  563. "\t\t2 - S/MIME\n"
  564. "\t\t3 - Object Signing\n"
  565. "\t\t4 - Reserved for future use\n"
  566. "\t\t5 - SSL CA\n"
  567. "\t\t6 - S/MIME CA\n"
  568. "\t\t7 - Object Signing CA\n"
  569. "\t\tOther to finish\n",
  570. buffer, sizeof(buffer)) == SECFailure) {
  571. return SECFailure;
  572. }
  573. value = PORT_Atoi (buffer);
  574. if (value < 0 || value > 7)
  575. break;
  576. if (value == 0) {
  577. /* Checking that zero value of variable 'value'
  578. * corresponds to '0' input made by user */
  579. char *chPtr = strchr(buffer, '0');
  580. if (chPtr == NULL) {
  581. continue;
  582. }
  583. }
  584. keyUsage |= (0x80 >> value);
  585. }
  586. isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
  587. } else {
  588. while (1) {
  589. if (parseNextCmdInput(nsCertTypeKeyWordArray, &value, &nextPos,
  590. &isCriticalExt) == SECFailure) {
  591. return SECFailure;
  592. }
  593. keyUsage |= (0x80 >> value);
  594. if (!nextPos)
  595. break;
  596. }
  597. }
  598. bitStringValue.data = &keyUsage;
  599. bitStringValue.len = 1;
  600. return (CERT_EncodeAndAddBitStrExtension
  601. (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
  602. isCriticalExt));
  603. }
  604. static SECStatus
  605. AddSubjectAltNames(PRArenaPool *arena, CERTGeneralName **existingListp,
  606. const char *names, CERTGeneralNameType type)
  607. {
  608. CERTGeneralName *nameList = NULL;
  609. CERTGeneralName *current = NULL;
  610. PRCList *prev = NULL;
  611. const char *cp;
  612. char *tbuf;
  613. SECStatus rv = SECSuccess;
  614. /*
  615. * walk down the comma separated list of names. NOTE: there is
  616. * no sanity checks to see if the email address look like
  617. * email addresses.
  618. */
  619. for (cp=names; cp; cp = PORT_Strchr(cp,',')) {
  620. int len;
  621. char *end;
  622. if (*cp == ',') {
  623. cp++;
  624. }
  625. end = PORT_Strchr(cp,',');
  626. len = end ? end-cp : PORT_Strlen(cp);
  627. if (len <= 0) {
  628. continue;
  629. }
  630. tbuf = PORT_ArenaAlloc(arena,len+1);
  631. PORT_Memcpy(tbuf,cp,len);
  632. tbuf[len] = 0;
  633. current = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
  634. if (!current) {
  635. rv = SECFailure;
  636. break;
  637. }
  638. if (prev) {
  639. current->l.prev = prev;
  640. prev->next = &(current->l);
  641. } else {
  642. nameList = current;
  643. }
  644. current->type = type;
  645. current->name.other.data = (unsigned char *)tbuf;
  646. current->name.other.len = PORT_Strlen(tbuf);
  647. prev = &(current->l);
  648. }
  649. /* at this point nameList points to the head of a doubly linked,
  650. * but not yet circular, list and current points to its tail. */
  651. if (rv == SECSuccess && nameList) {
  652. if (*existingListp != NULL) {
  653. PRCList *existingprev;
  654. /* add nameList to the end of the existing list */
  655. existingprev = (*existingListp)->l.prev;
  656. (*existingListp)->l.prev = &(current->l);
  657. nameList->l.prev = existingprev;
  658. existingprev->next = &(nameList->l);
  659. current->l.next = &((*existingListp)->l);
  660. }
  661. else {
  662. /* make nameList circular and set it as the new existingList */
  663. nameList->l.prev = prev;
  664. current->l.next = &(nameList->l);
  665. *existingListp = nameList;
  666. }
  667. }
  668. return rv;
  669. }
  670. static SECStatus
  671. AddEmailSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
  672. const char *emailAddrs)
  673. {
  674. return AddSubjectAltNames(arena, existingListp, emailAddrs,
  675. certRFC822Name);
  676. }
  677. static SECStatus
  678. AddDNSSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
  679. const char *dnsNames)
  680. {
  681. return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
  682. }
  683. static SECStatus
  684. AddBasicConstraint(void *extHandle)
  685. {
  686. CERTBasicConstraints basicConstraint;
  687. SECStatus rv;
  688. char buffer[10];
  689. PRBool yesNoAns;
  690. do {
  691. basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
  692. basicConstraint.isCA = GetYesNo ("Is this a CA certificate [y/N]?");
  693. buffer[0] = '\0';
  694. if (PrintChoicesAndGetAnswer("Enter the path length constraint, "
  695. "enter to skip [<0 for unlimited path]:",
  696. buffer, sizeof(buffer)) == SECFailure) {
  697. GEN_BREAK(SECFailure);
  698. }
  699. if (PORT_Strlen (buffer) > 0)
  700. basicConstraint.pathLenConstraint = PORT_Atoi (buffer);
  701. yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
  702. rv = SECU_EncodeAndAddExtensionValue(NULL, extHandle,
  703. &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS,
  704. (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeBasicConstraintValue);
  705. } while (0);
  706. return (rv);
  707. }
  708. static SECStatus
  709. AddAuthKeyID (void *extHandle)
  710. {
  711. CERTAuthKeyID *authKeyID = NULL;
  712. PRArenaPool *arena = NULL;
  713. SECStatus rv = SECSuccess;
  714. PRBool yesNoAns;
  715. do {
  716. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  717. if ( !arena ) {
  718. SECU_PrintError(progName, "out of memory");
  719. GEN_BREAK (SECFailure);
  720. }
  721. if (GetYesNo ("Enter value for the authKeyID extension [y/N]?") == 0)
  722. break;
  723. authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
  724. if (authKeyID == NULL) {
  725. GEN_BREAK (SECFailure);
  726. }
  727. rv = GetString (arena, "Enter value for the key identifier fields,"
  728. "enter to omit:", &authKeyID->keyID);
  729. if (rv != SECSuccess)
  730. break;
  731. SECU_SECItemHexStringToBinary(&authKeyID->keyID);
  732. authKeyID->authCertIssuer = GetGeneralName (arena);
  733. if (authKeyID->authCertIssuer == NULL &&
  734. SECFailure == PORT_GetError ())
  735. break;
  736. rv = GetString (arena, "Enter value for the authCertSerial field, "
  737. "enter to omit:", &authKeyID->authCertSerialNumber);
  738. yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
  739. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
  740. authKeyID, yesNoAns, SEC_OID_X509_AUTH_KEY_ID,
  741. (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeAuthKeyID);
  742. if (rv)
  743. break;
  744. } while (0);
  745. if (arena)
  746. PORT_FreeArena (arena, PR_FALSE);
  747. return (rv);
  748. }
  749. static SECStatus
  750. AddSubjKeyID (void *extHandle)
  751. {
  752. SECItem keyID;
  753. PRArenaPool *arena = NULL;
  754. SECStatus rv = SECSuccess;
  755. PRBool yesNoAns;
  756. do {
  757. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  758. if ( !arena ) {
  759. SECU_PrintError(progName, "out of memory");
  760. GEN_BREAK (SECFailure);
  761. }
  762. printf("Adding Subject Key ID extension.\n");
  763. rv = GetString (arena, "Enter value for the key identifier fields,"
  764. "enter to omit:", &keyID);
  765. if (rv != SECSuccess)
  766. break;
  767. SECU_SECItemHexStringToBinary(&keyID);
  768. yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
  769. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
  770. &keyID, yesNoAns, SEC_OID_X509_SUBJECT_KEY_ID,
  771. (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeSubjectKeyID);
  772. if (rv)
  773. break;
  774. } while (0);
  775. if (arena)
  776. PORT_FreeArena (arena, PR_FALSE);
  777. return (rv);
  778. }
  779. static SECStatus
  780. AddCrlDistPoint(void *extHandle)
  781. {
  782. PRArenaPool *arena = NULL;
  783. CERTCrlDistributionPoints *crlDistPoints = NULL;
  784. CRLDistributionPoint *current;
  785. SECStatus rv = SECSuccess;
  786. int count = 0, intValue;
  787. char buffer[512];
  788. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  789. if ( !arena )
  790. return (SECFailure);
  791. do {
  792. current = NULL;
  793. current = PORT_ArenaZNew(arena, CRLDistributionPoint);
  794. if (current == NULL) {
  795. GEN_BREAK (SECFailure);
  796. }
  797. /* Get the distributionPointName fields - this field is optional */
  798. if (PrintChoicesAndGetAnswer(
  799. "Enter the type of the distribution point name:\n"
  800. "\t1 - Full Name\n\t2 - Relative Name\n\tAny other "
  801. "number to finish\n\t\tChoice: ",
  802. buffer, sizeof(buffer)) == SECFailure) {
  803. GEN_BREAK (SECFailure);
  804. }
  805. intValue = PORT_Atoi (buffer);
  806. switch (intValue) {
  807. case generalName:
  808. current->distPointType = intValue;
  809. current->distPoint.fullName = GetGeneralName (arena);
  810. rv = PORT_GetError();
  811. break;
  812. case relativeDistinguishedName: {
  813. CERTName *name;
  814. current->distPointType = intValue;
  815. puts ("Enter the relative name: ");
  816. fflush (stdout);
  817. if (Gets_s (buffer, sizeof(buffer)) == NULL) {
  818. GEN_BREAK (SECFailure);
  819. }
  820. /* For simplicity, use CERT_AsciiToName to converse from a string
  821. to NAME, but we only interest in the first RDN */
  822. name = CERT_AsciiToName (buffer);
  823. if (!name) {
  824. GEN_BREAK (SECFailure);
  825. }
  826. rv = CERT_CopyRDN (arena, &current->distPoint.relativeName,
  827. name->rdns[0]);
  828. CERT_DestroyName (name);
  829. break;
  830. }
  831. }
  832. if (rv != SECSuccess)
  833. break;
  834. /* Get the reason flags */
  835. if (PrintChoicesAndGetAnswer(
  836. "\nSelect one of the following for the reason flags\n"
  837. "\t0 - unused\n\t1 - keyCompromise\n"
  838. "\t2 - caCompromise\n\t3 - affiliationChanged\n"
  839. "\t4 - superseded\n\t5 - cessationOfOperation\n"
  840. "\t6 - certificateHold\n"
  841. "\tAny other number to finish\t\tChoice: ",
  842. buffer, sizeof(buffer)) == SECFailure) {
  843. GEN_BREAK(SECFailure);
  844. }
  845. intValue = PORT_Atoi (buffer);
  846. if (intValue == 0) {
  847. /* Checking that zero value of variable 'value'
  848. * corresponds to '0' input made by user */
  849. char *chPtr = strchr(buffer, '0');
  850. if (chPtr == NULL) {
  851. intValue = -1;
  852. }
  853. }
  854. if (intValue >= 0 && intValue <8) {
  855. current->reasons.data = PORT_ArenaAlloc (arena, sizeof(char));
  856. if (current->reasons.data == NULL) {
  857. GEN_BREAK (SECFailure);
  858. }
  859. *current->reasons.data = (char)(0x80 >> intValue);
  860. current->reasons.len = 1;
  861. }
  862. puts ("Enter value for the CRL Issuer name:\n");
  863. current->crlIssuer = GetGeneralName (arena);
  864. if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure)
  865. break;
  866. if (crlDistPoints == NULL) {
  867. crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
  868. if (crlDistPoints == NULL) {
  869. GEN_BREAK (SECFailure);
  870. }
  871. }
  872. crlDistPoints->distPoints =
  873. PORT_ArenaGrow (arena, crlDistPoints->distPoints,
  874. sizeof (*crlDistPoints->distPoints) * count,
  875. sizeof (*crlDistPoints->distPoints) *(count + 1));
  876. if (crlDistPoints->distPoints == NULL) {
  877. GEN_BREAK (SECFailure);
  878. }
  879. crlDistPoints->distPoints[count] = current;
  880. ++count;
  881. if (GetYesNo("Enter another value for the CRLDistributionPoint "
  882. "extension [y/N]?") == 0) {
  883. /* Add null to the end to mark end of data */
  884. crlDistPoints->distPoints =
  885. PORT_ArenaGrow(arena, crlDistPoints->distPoints,
  886. sizeof (*crlDistPoints->distPoints) * count,
  887. sizeof (*crlDistPoints->distPoints) *(count + 1));
  888. crlDistPoints->distPoints[count] = NULL;
  889. break;
  890. }
  891. } while (1);
  892. if (rv == SECSuccess) {
  893. PRBool yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
  894. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
  895. crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS,
  896. (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCRLDistributionPoints);
  897. }
  898. if (arena)
  899. PORT_FreeArena (arena, PR_FALSE);
  900. return (rv);
  901. }
  902. static SECStatus
  903. AddPolicyConstraints(void *extHandle)
  904. {
  905. CERTCertificatePolicyConstraints *policyConstr;
  906. PRArenaPool *arena = NULL;
  907. SECStatus rv = SECSuccess;
  908. SECItem *item, *dummy;
  909. char buffer[512];
  910. int value;
  911. PRBool yesNoAns;
  912. PRBool skipExt = PR_TRUE;
  913. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  914. if ( !arena ) {
  915. SECU_PrintError(progName, "out of memory");
  916. return SECFailure;
  917. }
  918. policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints);
  919. if (policyConstr == NULL) {
  920. SECU_PrintError(progName, "out of memory");
  921. goto loser;
  922. }
  923. if (PrintChoicesAndGetAnswer("for requireExplicitPolicy enter the number "
  924. "of certs in path\nbefore explicit policy is required\n"
  925. "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
  926. goto loser;
  927. }
  928. if (PORT_Strlen(buffer)) {
  929. value = PORT_Atoi(buffer);
  930. if (value < 0) {
  931. goto loser;
  932. }
  933. item = &policyConstr->explicitPolicySkipCerts;
  934. dummy = SEC_ASN1EncodeInteger(arena, item, value);
  935. if (!dummy) {
  936. goto loser;
  937. }
  938. skipExt = PR_FALSE;
  939. }
  940. if (PrintChoicesAndGetAnswer("for inihibitPolicyMapping enter "
  941. "the number of certs in path\n"
  942. "after which policy mapping is not allowed\n"
  943. "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
  944. goto loser;
  945. }
  946. if (PORT_Strlen(buffer)) {
  947. value = PORT_Atoi(buffer);
  948. if (value < 0) {
  949. goto loser;
  950. }
  951. item = &policyConstr->inhibitMappingSkipCerts;
  952. dummy = SEC_ASN1EncodeInteger(arena, item, value);
  953. if (!dummy) {
  954. goto loser;
  955. }
  956. skipExt = PR_FALSE;
  957. }
  958. if (!skipExt) {
  959. yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  960. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr,
  961. yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS,
  962. (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyConstraintsExtension);
  963. } else {
  964. fprintf(stdout, "Policy Constraint extensions must contain "
  965. "at least one policy field\n");
  966. rv = SECFailure;
  967. }
  968. loser:
  969. if (arena) {
  970. PORT_FreeArena (arena, PR_FALSE);
  971. }
  972. return (rv);
  973. }
  974. static SECStatus
  975. AddInhibitAnyPolicy(void *extHandle)
  976. {
  977. CERTCertificateInhibitAny certInhibitAny;
  978. PRArenaPool *arena = NULL;
  979. SECStatus rv = SECSuccess;
  980. SECItem *item, *dummy;
  981. char buffer[10];
  982. int value;
  983. PRBool yesNoAns;
  984. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  985. if ( !arena ) {
  986. SECU_PrintError(progName, "out of memory");
  987. return SECFailure;
  988. }
  989. if (PrintChoicesAndGetAnswer("Enter the number of certs in the path "
  990. "permitted to use anyPolicy.\n"
  991. "(press Enter for 0)",
  992. buffer, sizeof(buffer)) == SECFailure) {
  993. goto loser;
  994. }
  995. item = &certInhibitAny.inhibitAnySkipCerts;
  996. value = PORT_Atoi(buffer);
  997. if (value < 0) {
  998. goto loser;
  999. }
  1000. dummy = SEC_ASN1EncodeInteger(arena, item, value);
  1001. if (!dummy) {
  1002. goto loser;
  1003. }
  1004. yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1005. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny,
  1006. yesNoAns, SEC_OID_X509_INHIBIT_ANY_POLICY,
  1007. (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInhibitAnyExtension);
  1008. loser:
  1009. if (arena) {
  1010. PORT_FreeArena (arena, PR_FALSE);
  1011. }
  1012. return (rv);
  1013. }
  1014. static SECStatus
  1015. AddPolicyMappings(void *extHandle)
  1016. {
  1017. CERTPolicyMap **policyMapArr = NULL;
  1018. CERTPolicyMap *current;
  1019. PRArenaPool *arena = NULL;
  1020. SECStatus rv = SECSuccess;
  1021. int count = 0;
  1022. char buffer[512];
  1023. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1024. if ( !arena ) {
  1025. SECU_PrintError(progName, "out of memory");
  1026. return SECFailure;
  1027. }
  1028. do {
  1029. if (PrintChoicesAndGetAnswer("Enter an Object Identifier (dotted "
  1030. "decimal format) for Issuer Domain Policy",
  1031. buffer, sizeof(buffer)) == SECFailure) {
  1032. GEN_BREAK (SECFailure);
  1033. }
  1034. current = PORT_ArenaZNew(arena, CERTPolicyMap);
  1035. if (current == NULL) {
  1036. GEN_BREAK(SECFailure);
  1037. }
  1038. rv = SEC_StringToOID(arena, &current->issuerDomainPolicy, buffer, 0);
  1039. if (rv == SECFailure) {
  1040. GEN_BREAK(SECFailure);
  1041. }
  1042. if (PrintChoicesAndGetAnswer("Enter an Object Identifier for "
  1043. "Subject Domain Policy",
  1044. buffer, sizeof(buffer)) == SECFailure) {
  1045. GEN_BREAK (SECFailure);
  1046. }
  1047. rv = SEC_StringToOID(arena, &current->subjectDomainPolicy, buffer, 0);
  1048. if (rv == SECFailure) {
  1049. GEN_BREAK(SECFailure);
  1050. }
  1051. if (policyMapArr == NULL) {
  1052. policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *);
  1053. if (policyMapArr == NULL) {
  1054. GEN_BREAK (SECFailure);
  1055. }
  1056. }
  1057. policyMapArr = PORT_ArenaGrow(arena, policyMapArr,
  1058. sizeof (current) * count,
  1059. sizeof (current) *(count + 1));
  1060. if (policyMapArr == NULL) {
  1061. GEN_BREAK (SECFailure);
  1062. }
  1063. policyMapArr[count] = current;
  1064. ++count;
  1065. if (!GetYesNo("Enter another Policy Mapping [y/N]")) {
  1066. /* Add null to the end to mark end of data */
  1067. policyMapArr = PORT_ArenaGrow (arena, policyMapArr,
  1068. sizeof (current) * count,
  1069. sizeof (current) *(count + 1));
  1070. if (policyMapArr == NULL) {
  1071. GEN_BREAK (SECFailure);
  1072. }
  1073. policyMapArr[count] = NULL;
  1074. break;
  1075. }
  1076. } while (1);
  1077. if (rv == SECSuccess) {
  1078. CERTCertificatePolicyMappings mappings;
  1079. PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1080. mappings.arena = arena;
  1081. mappings.policyMaps = policyMapArr;
  1082. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings,
  1083. yesNoAns, SEC_OID_X509_POLICY_MAPPINGS,
  1084. (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyMappingExtension);
  1085. }
  1086. if (arena)
  1087. PORT_FreeArena (arena, PR_FALSE);
  1088. return (rv);
  1089. }
  1090. enum PoliciQualifierEnum {
  1091. cpsPointer = 1,
  1092. userNotice = 2
  1093. };
  1094. static CERTPolicyQualifier **
  1095. RequestPolicyQualifiers(PRArenaPool *arena, SECItem *policyID)
  1096. {
  1097. CERTPolicyQualifier **policyQualifArr = NULL;
  1098. CERTPolicyQualifier *current;
  1099. SECStatus rv = SECSuccess;
  1100. int count = 0;
  1101. char buffer[512];
  1102. void *mark;
  1103. SECOidData *oid = NULL;
  1104. int intValue = 0;
  1105. int inCount = 0;
  1106. PORT_Assert(arena);
  1107. mark = PORT_ArenaMark(arena);
  1108. do {
  1109. current = PORT_ArenaZNew(arena, CERTPolicyQualifier);
  1110. if (current == NULL) {
  1111. GEN_BREAK(SECFailure);
  1112. }
  1113. /* Get the accessMethod fields */
  1114. SECU_PrintObjectID(stdout, policyID,
  1115. "Choose the type of qualifier for policy" , 0);
  1116. if (PrintChoicesAndGetAnswer(
  1117. "\t1 - CPS Pointer qualifier\n"
  1118. "\t2 - User notice qualifier\n"
  1119. "\tAny other number to finish\n"
  1120. "\t\tChoice: ", buffer, sizeof(buffer)) == SECFailure) {
  1121. GEN_BREAK (SECFailure);
  1122. }
  1123. intValue = PORT_Atoi(buffer);
  1124. switch (intValue) {
  1125. case cpsPointer: {
  1126. SECItem input;
  1127. oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CPS_POINTER_QUALIFIER);
  1128. if (PrintChoicesAndGetAnswer("Enter CPS pointer URI: ",
  1129. buffer, sizeof(buffer)) == SECFailure) {
  1130. GEN_BREAK (SECFailure);
  1131. }
  1132. input.len = PORT_Strlen(buffer);
  1133. input.data = (void*)PORT_ArenaStrdup(arena, buffer);
  1134. if (input.data == NULL ||
  1135. SEC_ASN1EncodeItem(arena, &current->qualifierValue, &input,
  1136. SEC_ASN1_GET(SEC_IA5StringTemplate)) == NULL) {
  1137. GEN_BREAK (SECFailure);
  1138. }
  1139. break;
  1140. }
  1141. case userNotice: {
  1142. SECItem **noticeNumArr;
  1143. CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice);
  1144. if (!notice) {
  1145. GEN_BREAK(SECFailure);
  1146. }
  1147. oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
  1148. if (GetYesNo("\t add a User Notice reference? [y/N]")) {
  1149. if (PrintChoicesAndGetAnswer("Enter user organization string: ",
  1150. buffer, sizeof(buffer)) == SECFailure) {
  1151. GEN_BREAK (SECFailure);
  1152. }
  1153. notice->noticeReference.organization.type = siAsciiString;
  1154. notice->noticeReference.organization.len =
  1155. PORT_Strlen(buffer);
  1156. notice->noticeReference.organization.data =
  1157. (void*)PORT_ArenaStrdup(arena, buffer);
  1158. noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2);
  1159. if (!noticeNumArr) {
  1160. GEN_BREAK (SECFailure);
  1161. }
  1162. do {
  1163. SECItem *noticeNum;
  1164. noticeNum = PORT_ArenaZNew(arena, SECItem);
  1165. if (PrintChoicesAndGetAnswer(
  1166. "Enter User Notice reference number "
  1167. "(or -1 to quit): ",
  1168. buffer, sizeof(buffer)) == SECFailure) {
  1169. GEN_BREAK (SECFailure);
  1170. }
  1171. intValue = PORT_Atoi(buffer);
  1172. if (noticeNum == NULL) {
  1173. if (intValue < 0) {
  1174. fprintf(stdout, "a noticeReference must have at "
  1175. "least one reference number\n");
  1176. GEN_BREAK (SECFailure);
  1177. }
  1178. } else {
  1179. if (intValue >= 0) {
  1180. noticeNumArr = PORT_ArenaGrow(arena, noticeNumArr,
  1181. sizeof (current) * inCount,
  1182. sizeof (current) *(inCount + 1));
  1183. if (noticeNumArr == NULL) {
  1184. GEN_BREAK (SECFailure);
  1185. }
  1186. } else {
  1187. break;
  1188. }
  1189. }
  1190. if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) {
  1191. GEN_BREAK (SECFailure);
  1192. }
  1193. noticeNumArr[inCount++] = noticeNum;
  1194. noticeNumArr[inCount] = NULL;
  1195. } while (1);
  1196. if (rv == SECFailure) {
  1197. GEN_BREAK(SECFailure);
  1198. }
  1199. notice->noticeReference.noticeNumbers = noticeNumArr;
  1200. rv = CERT_EncodeNoticeReference(arena, &notice->noticeReference,
  1201. &notice->derNoticeReference);
  1202. if (rv == SECFailure) {
  1203. GEN_BREAK(SECFailure);
  1204. }
  1205. }
  1206. if (GetYesNo("\t EnterUser Notice explicit text? [y/N]")) {
  1207. /* Getting only 200 bytes - RFC limitation */
  1208. if (PrintChoicesAndGetAnswer(
  1209. "\t", buffer, 200) == SECFailure) {
  1210. GEN_BREAK (SECFailure);
  1211. }
  1212. notice->displayText.type = siAsciiString;
  1213. notice->displayText.len = PORT_Strlen(buffer);
  1214. notice->displayText.data =
  1215. (void*)PORT_ArenaStrdup(arena, buffer);
  1216. if (notice->displayText.data == NULL) {
  1217. GEN_BREAK(SECFailure);
  1218. }
  1219. }
  1220. rv = CERT_EncodeUserNotice(arena, notice, &current->qualifierValue);
  1221. if (rv == SECFailure) {
  1222. GEN_BREAK(SECFailure);
  1223. }
  1224. break;
  1225. }
  1226. }
  1227. if (rv == SECFailure || oid == NULL ||
  1228. SECITEM_CopyItem(arena, &current->qualifierID, &oid->oid)
  1229. == SECFailure) {
  1230. GEN_BREAK (SECFailure);
  1231. }
  1232. if (!policyQualifArr) {
  1233. policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *);
  1234. } else {
  1235. policyQualifArr = PORT_ArenaGrow (arena, policyQualifArr,
  1236. sizeof (current) * count,
  1237. sizeof (current) *(count + 1));
  1238. }
  1239. if (policyQualifArr == NULL) {
  1240. GEN_BREAK (SECFailure);
  1241. }
  1242. policyQualifArr[count] = current;
  1243. ++count;
  1244. if (!GetYesNo ("Enter another policy qualifier [y/N]")) {
  1245. /* Add null to the end to mark end of data */
  1246. policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr,
  1247. sizeof (current) * count,
  1248. sizeof (current) *(count + 1));
  1249. if (policyQualifArr == NULL) {
  1250. GEN_BREAK (SECFailure);
  1251. }
  1252. policyQualifArr[count] = NULL;
  1253. break;
  1254. }
  1255. } while (1);
  1256. if (rv != SECSuccess) {
  1257. PORT_ArenaRelease (arena, mark);
  1258. policyQualifArr = NULL;
  1259. }
  1260. return (policyQualifArr);
  1261. }
  1262. static SECStatus
  1263. AddCertPolicies(void *extHandle)
  1264. {
  1265. CERTPolicyInfo **certPoliciesArr = NULL;
  1266. CERTPolicyInfo *current;
  1267. PRArenaPool *arena = NULL;
  1268. SECStatus rv = SECSuccess;
  1269. int count = 0;
  1270. char buffer[512];
  1271. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1272. if ( !arena ) {
  1273. SECU_PrintError(progName, "out of memory");
  1274. return SECFailure;
  1275. }
  1276. do {
  1277. current = PORT_ArenaZNew(arena, CERTPolicyInfo);
  1278. if (current == NULL) {
  1279. GEN_BREAK(SECFailure);
  1280. }
  1281. if (PrintChoicesAndGetAnswer("Enter a CertPolicy Object Identifier "
  1282. "(dotted decimal format)\n"
  1283. "or \"any\" for AnyPolicy:",
  1284. buffer, sizeof(buffer)) == SECFailure) {
  1285. GEN_BREAK (SECFailure);
  1286. }
  1287. if (strncmp(buffer, "any", 3) == 0) {
  1288. /* use string version of X509_CERTIFICATE_POLICIES.anyPolicy */
  1289. strcpy(buffer, "OID.2.5.29.32.0");
  1290. }
  1291. rv = SEC_StringToOID(arena, &current->policyID, buffer, 0);
  1292. if (rv == SECFailure) {
  1293. GEN_BREAK(SECFailure);
  1294. }
  1295. current->policyQualifiers =
  1296. RequestPolicyQualifiers(arena, &current->policyID);
  1297. if (!certPoliciesArr) {
  1298. certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *);
  1299. } else {
  1300. certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
  1301. sizeof (current) * count,
  1302. sizeof (current) *(count + 1));
  1303. }
  1304. if (certPoliciesArr == NULL) {
  1305. GEN_BREAK (SECFailure);
  1306. }
  1307. certPoliciesArr[count] = current;
  1308. ++count;
  1309. if (!GetYesNo ("Enter another PolicyInformation field [y/N]?")) {
  1310. /* Add null to the end to mark end of data */
  1311. certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
  1312. sizeof (current) * count,
  1313. sizeof (current) *(count + 1));
  1314. if (certPoliciesArr == NULL) {
  1315. GEN_BREAK (SECFailure);
  1316. }
  1317. certPoliciesArr[count] = NULL;
  1318. break;
  1319. }
  1320. } while (1);
  1321. if (rv == SECSuccess) {
  1322. CERTCertificatePolicies policies;
  1323. PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1324. policies.arena = arena;
  1325. policies.policyInfos = certPoliciesArr;
  1326. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies,
  1327. yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES,
  1328. (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCertPoliciesExtension);
  1329. }
  1330. if (arena)
  1331. PORT_FreeArena(arena, PR_FALSE);
  1332. return (rv);
  1333. }
  1334. enum AuthInfoAccessTypesEnum {
  1335. caIssuers = 1,
  1336. ocsp = 2
  1337. };
  1338. enum SubjInfoAccessTypesEnum {
  1339. caRepository = 1,
  1340. timeStamping = 2
  1341. };
  1342. /* Encode and add an AIA or SIA extension */
  1343. static SECStatus
  1344. AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
  1345. {
  1346. CERTAuthInfoAccess **infoAccArr = NULL;
  1347. CERTAuthInfoAccess *current;
  1348. PRArenaPool *arena = NULL;
  1349. SECStatus rv = SECSuccess;
  1350. int count = 0;
  1351. char buffer[512];
  1352. SECOidData *oid = NULL;
  1353. int intValue = 0;
  1354. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1355. if ( !arena ) {
  1356. SECU_PrintError(progName, "out of memory");
  1357. return SECFailure;
  1358. }
  1359. do {
  1360. current = NULL;
  1361. current = PORT_ArenaZNew(arena, CERTAuthInfoAccess);
  1362. if (current == NULL) {
  1363. GEN_BREAK(SECFailure);
  1364. }
  1365. /* Get the accessMethod fields */
  1366. if (addSIAExt) {
  1367. if (isCACert) {
  1368. puts("Adding \"CA Repository\" access method type for "
  1369. "Subject Information Access extension:\n");
  1370. intValue = caRepository;
  1371. } else {
  1372. puts("Adding \"Time Stamping Services\" access method type for "
  1373. "Subject Information Access extension:\n");
  1374. intValue = timeStamping;
  1375. }
  1376. } else {
  1377. PrintChoicesAndGetAnswer("Enter access method type "
  1378. "for Authority Information Access extension:\n"
  1379. "\t1 - CA Issuers\n\t2 - OCSP\n\tAny"
  1380. "other number to finish\n\tChoice",
  1381. buffer, sizeof(buffer));
  1382. intValue = PORT_Atoi(buffer);
  1383. }
  1384. if (addSIAExt) {
  1385. switch (intValue) {
  1386. case caRepository:
  1387. oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY);
  1388. break;
  1389. case timeStamping:
  1390. oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING);
  1391. break;
  1392. }
  1393. } else {
  1394. switch (intValue) {
  1395. case caIssuers:
  1396. oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS);
  1397. break;
  1398. case ocsp:
  1399. oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP);
  1400. break;
  1401. }
  1402. }
  1403. if (oid == NULL ||
  1404. SECITEM_CopyItem(arena, &current->method, &oid->oid)
  1405. == SECFailure) {
  1406. GEN_BREAK (SECFailure);
  1407. }
  1408. current->location = GetGeneralName(arena);
  1409. if (!current->location) {
  1410. GEN_BREAK(SECFailure);
  1411. }
  1412. if (infoAccArr == NULL) {
  1413. infoAccArr = PORT_ArenaZNew(arena, CERTAuthInfoAccess *);
  1414. } else {
  1415. infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
  1416. sizeof (current) * count,
  1417. sizeof (current) *(count + 1));
  1418. }
  1419. if (infoAccArr == NULL) {
  1420. GEN_BREAK (SECFailure);
  1421. }
  1422. infoAccArr[count] = current;
  1423. ++count;
  1424. PR_snprintf(buffer, sizeof(buffer), "Add another location to the %s"
  1425. " Information Access extension [y/N]",
  1426. (addSIAExt) ? "Subject" : "Authority");
  1427. if (GetYesNo (buffer) == 0) {
  1428. /* Add null to the end to mark end of data */
  1429. infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
  1430. sizeof (current) * count,
  1431. sizeof (current) *(count + 1));
  1432. if (infoAccArr == NULL) {
  1433. GEN_BREAK (SECFailure);
  1434. }
  1435. infoAccArr[count] = NULL;
  1436. break;
  1437. }
  1438. } while (1);
  1439. if (rv == SECSuccess) {
  1440. int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS;
  1441. PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
  1442. if (addSIAExt) {
  1443. oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS;
  1444. }
  1445. rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr,
  1446. yesNoAns, oidIdent,
  1447. (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInfoAccessExtension);
  1448. }
  1449. if (arena)
  1450. PORT_FreeArena(arena, PR_FALSE);
  1451. return (rv);
  1452. }
  1453. SECStatus
  1454. AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
  1455. certutilExtnList extList)
  1456. {
  1457. SECStatus rv = SECSuccess;
  1458. char *errstring = NULL;
  1459. do {
  1460. /* Add key usage extension */
  1461. if (extList[ext_keyUsage].activated) {
  1462. rv = AddKeyUsage(extHandle, extList[ext_keyUsage].arg);
  1463. if (rv) {
  1464. errstring = "KeyUsage";
  1465. break;
  1466. }
  1467. }
  1468. /* Add extended key usage extension */
  1469. if (extList[ext_extKeyUsage].activated) {
  1470. rv = AddExtKeyUsage(extHandle, extList[ext_extKeyUsage].arg);
  1471. if (rv) {
  1472. errstring = "ExtendedKeyUsage";
  1473. break;
  1474. }
  1475. }
  1476. /* Add basic constraint extension */
  1477. if (extList[ext_basicConstraint].activated) {
  1478. rv = AddBasicConstraint(extHandle);
  1479. if (rv) {
  1480. errstring = "BasicConstraint";
  1481. break;
  1482. }
  1483. }
  1484. if (extList[ext_authorityKeyID].activated) {
  1485. rv = AddAuthKeyID(extHandle);
  1486. if (rv) {
  1487. errstring = "AuthorityKeyID";
  1488. break;
  1489. }
  1490. }
  1491. if (extList[ext_subjectKeyID].activated) {
  1492. rv = AddSubjKeyID(extHandle);
  1493. if (rv) {
  1494. errstring = "SubjectKeyID";
  1495. break;
  1496. }
  1497. }
  1498. if (extList[ext_CRLDistPts].activated) {
  1499. rv = AddCrlDistPoint(extHandle);
  1500. if (rv) {
  1501. errstring = "CRLDistPoints";
  1502. break;
  1503. }
  1504. }
  1505. if (extList[ext_NSCertType].activated) {
  1506. rv = AddNscpCertType(extHandle, extList[ext_NSCertType].arg);
  1507. if (rv) {
  1508. errstring = "NSCertType";
  1509. break;
  1510. }
  1511. }
  1512. if (extList[ext_authInfoAcc].activated ||
  1513. extList[ext_subjInfoAcc].activated) {
  1514. rv = AddInfoAccess(extHandle, extList[ext_subjInfoAcc].activated,
  1515. extList[ext_basicConstraint].activated);
  1516. if (rv) {
  1517. errstring = "InformationAccess";
  1518. break;
  1519. }
  1520. }
  1521. if (extList[ext_certPolicies].activated) {
  1522. rv = AddCertPolicies(extHandle);
  1523. if (rv) {
  1524. errstring = "Policies";
  1525. break;
  1526. }
  1527. }
  1528. if (extList[ext_policyMappings].activated) {
  1529. rv = AddPolicyMappings(extHandle);
  1530. if (rv) {
  1531. errstring = "PolicyMappings";
  1532. break;
  1533. }
  1534. }
  1535. if (extList[ext_policyConstr].activated) {
  1536. rv = AddPolicyConstraints(extHandle);
  1537. if (rv) {
  1538. errstring = "PolicyConstraints";
  1539. break;
  1540. }
  1541. }
  1542. if (extList[ext_inhibitAnyPolicy].activated) {
  1543. rv = AddInhibitAnyPolicy(extHandle);
  1544. if (rv) {
  1545. errstring = "InhibitAnyPolicy";
  1546. break;
  1547. }
  1548. }
  1549. if (emailAddrs || dnsNames) {
  1550. PRArenaPool *arena;
  1551. CERTGeneralName *namelist = NULL;
  1552. SECItem item = { 0, NULL, 0 };
  1553. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1554. if (arena == NULL) {
  1555. rv = SECFailure;
  1556. break;
  1557. }
  1558. rv = AddEmailSubjectAlt(arena, &namelist, emailAddrs);
  1559. rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
  1560. if (rv == SECSuccess) {
  1561. rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
  1562. if (rv == SECSuccess) {
  1563. rv = CERT_AddExtension(extHandle,
  1564. SEC_OID_X509_SUBJECT_ALT_NAME,
  1565. &item, PR_FALSE, PR_TRUE);
  1566. }
  1567. }
  1568. PORT_FreeArena(arena, PR_FALSE);
  1569. if (rv) {
  1570. errstring = "SubjectAltName";
  1571. break;
  1572. }
  1573. }
  1574. } while (0);
  1575. if (rv != SECSuccess) {
  1576. SECU_PrintError(progName, "Problem creating %s extension", errstring);
  1577. }
  1578. return rv;
  1579. }