1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is the Netscape security libraries.
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.
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.
35 * ***** END LICENSE BLOCK ***** */
37 /* Cert-O-Matic CGI */
59 /* #define FILEOUT 1 */
60 /* #define OFFLINE 1 */
61 #define START_FIELDS 100
63 #define SERIAL_FILE "../serial"
64 #define DB_DIRECTORY ".."
66 static char *progName
;
68 typedef struct PairStr Pair
;
76 char prefix
[PREFIX_LEN
];
79 const SEC_ASN1Template CERTIA5TypeTemplate
[] = {
80 { SEC_ASN1_IA5_STRING
}
85 SECKEYPrivateKey
*privkeys
[9] = {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
90 const SEC_ASN1Template CERT_GeneralNameTemplate
[] = {
91 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_AnyTemplate
}
97 error_out(char *error_string
)
99 printf("Content-type: text/plain\n\n");
100 printf(error_string
);
109 error_out("ERROR: Unable to allocate memory");
114 make_copy_string(char *read_pos
,
117 /* copys string from to a new string it creates and
118 returns a pointer to the new string */
120 int remaining
= length
;
124 new = write_pos
= (char *) PORT_Alloc (length
);
128 while (*read_pos
!= sentinal_value
) {
129 if (remaining
== 1) {
132 new = PORT_Realloc(new,length
);
136 write_pos
= new + length
- remaining
;
138 *write_pos
= *read_pos
;
141 remaining
= remaining
- 1;
149 clean_input(Pair
*data
)
150 /* converts the non-alphanumeric characters in a form post
151 from hex codes back to characters */
160 PRBool name
= PR_TRUE
;
162 begin_pos
= data
->name
;
163 while (begin_pos
!= NULL
) {
164 length
= strlen(begin_pos
);
165 read_pos
= write_pos
= begin_pos
;
166 while ((read_pos
- begin_pos
) < length
) {
167 if (*read_pos
== '+') {
170 if (*read_pos
== '%') {
171 hi_digit
= *(read_pos
+ 1);
172 low_digit
= *(read_pos
+2);
174 if (isdigit(hi_digit
)){
175 hi_digit
= hi_digit
- '0';
177 hi_digit
= toupper(hi_digit
);
178 if (isxdigit(hi_digit
)) {
179 hi_digit
= (hi_digit
- 'A') + 10;
181 error_out("ERROR: Form data incorrectly formated");
184 if (isdigit(low_digit
)){
185 low_digit
= low_digit
- '0';
187 low_digit
= toupper(low_digit
);
188 if ((low_digit
>='A') && (low_digit
<= 'F')) {
189 low_digit
= (low_digit
- 'A') + 10;
191 error_out("ERROR: Form data incorrectly formated");
194 character
= (hi_digit
<< 4) | low_digit
;
195 if (character
!= 10) {
196 *write_pos
= character
;
200 *write_pos
= *read_pos
;
206 if (name
== PR_TRUE
) {
207 begin_pos
= data
->data
;
211 begin_pos
= data
->name
;
219 make_name(char *new_data
)
220 /* gets the next field name in the input string and returns
221 a pointer to a string containing a copy of it */
226 name
= make_copy_string(new_data
, length
, '=');
231 make_data(char *new_data
)
232 /* gets the data for the next field in the input string
233 and returns a pointer to a string containing it */
240 while (*(read_pos
- 1) != '=') {
243 data
= make_copy_string(read_pos
, length
, '&');
249 make_pair(char *new_data
)
250 /* makes a pair name/data pair from the input string */
254 temp
.name
= make_name(new_data
);
255 temp
.data
= make_data(new_data
);
262 make_datastruct(char *data
, int len
)
263 /* parses the input from the form post into a data
264 structure of field name/data pairs */
269 int fields
= START_FIELDS
;
270 int remaining
= START_FIELDS
;
273 datastruct
= current
= (Pair
*) PORT_Alloc(fields
* sizeof(Pair
));
274 if (datastruct
== NULL
) {
277 while (curr_pos
- data
< len
) {
278 if (remaining
== 1) {
281 datastruct
= (Pair
*) PORT_Realloc
282 (datastruct
, fields
* sizeof(Pair
));
283 if (datastruct
== NULL
) {
286 current
= datastruct
+ (fields
- remaining
);
288 *current
= make_pair(curr_pos
);
289 while (*curr_pos
!= '&') {
294 remaining
= remaining
- 1;
296 current
->name
= NULL
;
301 return_name(Pair
*data_struct
,
303 /* returns a pointer to the name of the nth
304 (starting from 0) item in the data structure */
308 if ((data_struct
+ n
)->name
!= NULL
) {
309 name
= (data_struct
+ n
)->name
;
317 return_data(Pair
*data_struct
,int n
)
318 /* returns a pointer to the data of the nth (starting from 0)
319 itme in the data structure */
323 data
= (data_struct
+ n
)->data
;
329 add_prefix(char *field_name
)
331 extern char prefix
[PREFIX_LEN
];
336 rv
= write
= PORT_Alloc(PORT_Strlen(prefix
) + PORT_Strlen(field_name
) + 1);
337 for(i
= 0; i
< PORT_Strlen(prefix
); i
++) {
342 rv
= PORT_Strcat(rv
,field_name
);
348 find_field(Pair
*data
,
351 /* returns a pointer to the data of the first pair
352 thats name matches the string it is passed */
359 field_name
= add_prefix(field_name
);
361 while(return_name(data
, i
) != NULL
) {
362 if (PORT_Strcmp(return_name(data
, i
), field_name
) == 0) {
363 retrieved
= return_data(data
, i
);
376 find_field_bool(Pair
*data
,
382 rv
= find_field(data
, fieldname
, add_pre
);
384 if ((rv
!= NULL
) && (PORT_Strcmp(rv
, "true")) == 0) {
392 update_data_by_name(Pair
*data
,
395 /* replaces the data in the data structure associated with
396 a name with new data, returns null if not found */
403 while (return_name(data
, i
) != NULL
) {
404 if (PORT_Strcmp(return_name(data
, i
), field_name
) == 0) {
405 new = make_copy_string( new_data
, length
, '\0');
406 PORT_Free(return_data(data
, i
));
408 (*(data
+ i
)).data
= new;
420 update_data_by_index(Pair
*data
,
423 /* replaces the data of a particular index in the data structure */
428 new = make_copy_string(new_data
, length
, '\0');
429 PORT_Free(return_data(data
, n
));
430 (*(data
+ n
)).data
= new;
436 add_field(Pair
*data
,
439 /* adds a new name/data pair to the data structure */
443 int name_length
= 100;
444 int data_length
= 100;
446 while(return_name(data
, i
) != NULL
) {
450 while ( j
< (i
+ 1) ) {
454 data
= (Pair
*) PORT_Realloc(data
, (j
* 2) * sizeof(Pair
));
459 (*(data
+ i
)).name
= make_copy_string(field_name
, name_length
, '\0');
460 (*(data
+ i
)).data
= make_copy_string(field_data
, data_length
, '\0');
461 (data
+ i
+ 1)->name
= NULL
;
466 static CERTCertificateRequest
*
467 makeCertReq(Pair
*form_data
,
469 /* makes and encodes a certrequest */
473 CERTCertificateRequest
*certReq
= NULL
;
474 CERTSubjectPublicKeyInfo
*spki
;
475 SECKEYPrivateKey
*privkey
= NULL
;
476 SECKEYPublicKey
*pubkey
= NULL
;
479 extern SECKEYPrivateKey
*privkeys
[9];
481 char *challenge
= "foo";
482 SECStatus rv
= SECSuccess
;
483 PQGParams
*pqgParams
= NULL
;
484 PQGVerify
*pqgVfy
= NULL
;
486 name
= CERT_AsciiToName(find_field(form_data
, "subject", PR_TRUE
));
488 error_out("ERROR: Unable to create Subject Name");
490 key
= find_field(form_data
, "key", PR_TRUE
);
492 switch (*find_field(form_data
, "keysize", PR_TRUE
)) {
494 keySizeInBits
= 2048;
497 keySizeInBits
= 1024;
503 error_out("ERROR: Unsupported Key length selected");
505 if (find_field_bool(form_data
, "keyType-dsa", PR_TRUE
)) {
506 rv
= PK11_PQG_ParamGen(keySizeInBits
, &pqgParams
, &pqgVfy
);
507 if (rv
!= SECSuccess
) {
508 error_out("ERROR: Unable to generate PQG parameters");
510 slot
= PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN
, NULL
);
511 privkey
= PK11_GenerateKeyPair(slot
, CKM_DSA_KEY_PAIR_GEN
,
512 pqgParams
,&pubkey
, PR_FALSE
,
515 privkey
= SECKEY_CreateRSAPrivateKey(keySizeInBits
, &pubkey
, NULL
);
517 privkeys
[which_priv_key
] = privkey
;
518 spki
= SECKEY_CreateSubjectPublicKeyInfo(pubkey
);
520 spki
= SECKEY_ConvertAndDecodePublicKeyAndChallenge(key
, challenge
,
523 error_out("ERROR: Unable to decode Public Key and Challenge String");
526 certReq
= CERT_CreateCertificateRequest(name
, spki
, NULL
);
527 if (certReq
== NULL
) {
528 error_out("ERROR: Unable to create Certificate Request");
530 if (pubkey
!= NULL
) {
531 SECKEY_DestroyPublicKey(pubkey
);
534 SECKEY_DestroySubjectPublicKeyInfo(spki
);
536 if (pqgParams
!= NULL
) {
537 PK11_PQG_DestroyParams(pqgParams
);
539 if (pqgVfy
!= NULL
) {
540 PK11_PQG_DestroyVerify(pqgVfy
);
547 static CERTCertificate
*
548 MakeV1Cert(CERTCertDBHandle
*handle
,
549 CERTCertificateRequest
*req
,
556 CERTCertificate
*issuerCert
= NULL
;
557 CERTValidity
*validity
;
558 CERTCertificate
*cert
= NULL
;
559 PRExplodedTime printableTime
;
567 issuerCert
= CERT_FindCertByNameString(handle
, issuerNameStr
);
569 error_out("ERROR: Could not find issuer's certificate");
573 if (find_field_bool(data
, "manValidity", PR_TRUE
)) {
574 rv
= DER_AsciiToTime(&now
, find_field(data
, "notBefore", PR_TRUE
));
578 PR_ExplodeTime (now
, PR_GMTParameters
, &printableTime
);
580 printableTime
.tm_month
+= warpmonths
;
581 now
= PR_ImplodeTime (&printableTime
);
582 PR_ExplodeTime (now
, PR_GMTParameters
, &printableTime
);
584 if (find_field_bool(data
, "manValidity", PR_TRUE
)) {
585 rv
= DER_AsciiToTime(&after
, find_field(data
, "notAfter", PR_TRUE
));
586 PR_ExplodeTime (after
, PR_GMTParameters
, &printableTime
);
588 printableTime
.tm_month
+= 3;
589 after
= PR_ImplodeTime (&printableTime
);
591 /* note that the time is now in micro-second unit */
592 validity
= CERT_CreateValidity (now
, after
);
595 cert
= CERT_CreateCertificate
596 (serialNumber
,&(req
->subject
), validity
, req
);
598 cert
= CERT_CreateCertificate
599 (serialNumber
,&(issuerCert
->subject
), validity
, req
);
602 CERT_DestroyValidity(validity
);
604 CERT_DestroyCertificate (issuerCert
);
610 get_serial_number(Pair
*data
)
614 char *filename
= SERIAL_FILE
;
619 if (find_field_bool(data
, "serial-auto", PR_TRUE
)) {
620 serialFile
= fopen(filename
, "r");
621 if (serialFile
!= NULL
) {
622 fread(&serial
, sizeof(int), 1, serialFile
);
623 if (ferror(serialFile
) != 0) {
624 error_out("Error: Unable to read serial number file");
626 if (serial
== 4294967295) {
631 serialFile
= fopen(filename
,"w");
632 if (serialFile
== NULL
) {
633 error_out("ERROR: Unable to open serial number file for writing");
635 fwrite(&serial
, sizeof(int), 1, serialFile
);
636 if (ferror(serialFile
) != 0) {
637 error_out("Error: Unable to write to serial number file");
641 serialFile
= fopen(filename
,"w");
642 if (serialFile
== NULL
) {
643 error_out("ERROR: Unable to open serial number file");
646 fwrite(&serial
, sizeof(int), 1, serialFile
);
647 if (ferror(serialFile
) != 0) {
648 error_out("Error: Unable to write to serial number file");
650 error
= ferror(serialFile
);
652 error_out("ERROR: Unable to write to serial file");
657 SN
= find_field(data
, "serial_value", PR_TRUE
);
658 while (*SN
!= '\0') {
659 serial
= serial
* 16;
660 if ((*SN
>= 'A') && (*SN
<='F')) {
661 serial
+= *SN
- 'A' + 10;
663 if ((*SN
>= 'a') && (*SN
<='f')) {
664 serial
+= *SN
- 'a' + 10;
677 typedef SECStatus (* EXTEN_VALUE_ENCODER
)
678 (PRArenaPool
*extHandle
, void *value
, SECItem
*encodedValue
);
681 EncodeAndAddExtensionValue(
687 EXTEN_VALUE_ENCODER EncodeValueFn
)
689 SECItem encodedValue
;
693 encodedValue
.data
= NULL
;
694 encodedValue
.len
= 0;
695 rv
= (*EncodeValueFn
)(arena
, value
, &encodedValue
);
696 if (rv
!= SECSuccess
) {
697 error_out("ERROR: Unable to encode extension value");
699 rv
= CERT_AddExtension
700 (extHandle
, extenType
, &encodedValue
, criticality
, PR_TRUE
);
707 AddKeyUsage (void *extHandle
,
710 SECItem bitStringValue
;
711 unsigned char keyUsage
= 0x0;
713 if (find_field_bool(data
,"keyUsage-digitalSignature", PR_TRUE
)){
714 keyUsage
|= (0x80 >> 0);
716 if (find_field_bool(data
,"keyUsage-nonRepudiation", PR_TRUE
)){
717 keyUsage
|= (0x80 >> 1);
719 if (find_field_bool(data
,"keyUsage-keyEncipherment", PR_TRUE
)){
720 keyUsage
|= (0x80 >> 2);
722 if (find_field_bool(data
,"keyUsage-dataEncipherment", PR_TRUE
)){
723 keyUsage
|= (0x80 >> 3);
725 if (find_field_bool(data
,"keyUsage-keyAgreement", PR_TRUE
)){
726 keyUsage
|= (0x80 >> 4);
728 if (find_field_bool(data
,"keyUsage-keyCertSign", PR_TRUE
)) {
729 keyUsage
|= (0x80 >> 5);
731 if (find_field_bool(data
,"keyUsage-cRLSign", PR_TRUE
)) {
732 keyUsage
|= (0x80 >> 6);
735 bitStringValue
.data
= &keyUsage
;
736 bitStringValue
.len
= 1;
738 return (CERT_EncodeAndAddBitStrExtension
739 (extHandle
, SEC_OID_X509_KEY_USAGE
, &bitStringValue
,
740 (find_field_bool(data
, "keyUsage-crit", PR_TRUE
))));
744 static CERTOidSequence
*
745 CreateOidSequence(void)
747 CERTOidSequence
*rv
= (CERTOidSequence
*)NULL
;
748 PRArenaPool
*arena
= (PRArenaPool
*)NULL
;
750 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
751 if( (PRArenaPool
*)NULL
== arena
) {
755 rv
= (CERTOidSequence
*)PORT_ArenaZAlloc(arena
, sizeof(CERTOidSequence
));
756 if( (CERTOidSequence
*)NULL
== rv
) {
760 rv
->oids
= (SECItem
**)PORT_ArenaZAlloc(arena
, sizeof(SECItem
*));
761 if( (SECItem
**)NULL
== rv
->oids
) {
769 if( (PRArenaPool
*)NULL
!= arena
) {
770 PORT_FreeArena(arena
, PR_FALSE
);
773 return (CERTOidSequence
*)NULL
;
777 AddOidToSequence(CERTOidSequence
*os
, SECOidTag oidTag
)
783 od
= SECOID_FindOIDByTag(oidTag
);
784 if( (SECOidData
*)NULL
== od
) {
788 for( oids
= os
->oids
; (SECItem
*)NULL
!= *oids
; oids
++ ) {
797 oids
= (SECItem
**)PORT_ArenaZAlloc(os
->arena
, sizeof(SECItem
*) * (count
+2));
798 if( (SECItem
**)NULL
== oids
) {
802 for( i
= 0; i
< count
; i
++ ) {
803 oids
[i
] = os
->oids
[i
];
806 /* ArenaZFree(os->oids); */
810 os
->oids
[count
] = &od
->oid
;
816 EncodeOidSequence(CERTOidSequence
*os
)
819 extern const SEC_ASN1Template CERT_OidSeqTemplate
[];
821 rv
= (SECItem
*)PORT_ArenaZAlloc(os
->arena
, sizeof(SECItem
));
822 if( (SECItem
*)NULL
== rv
) {
826 if( !SEC_ASN1EncodeItem(os
->arena
, rv
, os
, CERT_OidSeqTemplate
) ) {
833 return (SECItem
*)NULL
;
837 AddExtKeyUsage(void *extHandle
, Pair
*data
)
844 os
= CreateOidSequence();
845 if( (CERTOidSequence
*)NULL
== os
) {
849 if( find_field_bool(data
, "extKeyUsage-serverAuth", PR_TRUE
) ) {
850 rv
= AddOidToSequence(os
, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH
);
851 if( SECSuccess
!= rv
) goto loser
;
854 if( find_field_bool(data
, "extKeyUsage-clientAuth", PR_TRUE
) ) {
855 rv
= AddOidToSequence(os
, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH
);
856 if( SECSuccess
!= rv
) goto loser
;
859 if( find_field_bool(data
, "extKeyUsage-codeSign", PR_TRUE
) ) {
860 rv
= AddOidToSequence(os
, SEC_OID_EXT_KEY_USAGE_CODE_SIGN
);
861 if( SECSuccess
!= rv
) goto loser
;
864 if( find_field_bool(data
, "extKeyUsage-emailProtect", PR_TRUE
) ) {
865 rv
= AddOidToSequence(os
, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT
);
866 if( SECSuccess
!= rv
) goto loser
;
869 if( find_field_bool(data
, "extKeyUsage-timeStamp", PR_TRUE
) ) {
870 rv
= AddOidToSequence(os
, SEC_OID_EXT_KEY_USAGE_TIME_STAMP
);
871 if( SECSuccess
!= rv
) goto loser
;
874 if( find_field_bool(data
, "extKeyUsage-ocspResponder", PR_TRUE
) ) {
875 rv
= AddOidToSequence(os
, SEC_OID_OCSP_RESPONDER
);
876 if( SECSuccess
!= rv
) goto loser
;
879 if( find_field_bool(data
, "extKeyUsage-NS-govtApproved", PR_TRUE
) ) {
880 rv
= AddOidToSequence(os
, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED
);
881 if( SECSuccess
!= rv
) goto loser
;
884 value
= EncodeOidSequence(os
);
886 crit
= find_field_bool(data
, "extKeyUsage-crit", PR_TRUE
);
888 rv
= CERT_AddExtension(extHandle
, SEC_OID_X509_EXT_KEY_USAGE
, value
,
892 CERT_DestroyOidSequence(os
);
897 AddSubKeyID(void *extHandle
,
899 CERTCertificate
*subjectCert
)
901 SECItem encodedValue
;
910 PRBool odd
= PR_FALSE
;
913 encodedValue
.data
= NULL
;
914 encodedValue
.len
= 0;
915 first
= read
= write
= find_field(data
,"subjectKeyIdentifier-text",
917 len
= PORT_Strlen(first
);
918 odd
= ((len
% 2) != 0 ) ? PR_TRUE
: PR_FALSE
;
919 if (find_field_bool(data
, "subjectKeyIdentifier-radio-hex", PR_TRUE
)) {
921 error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string");
923 while (*read
!= '\0') {
924 if (!isxdigit(*read
)) {
925 error_out("ERROR: Improperly formated subject key identifier");
927 *read
= toupper(*read
);
928 if ((*read
>= 'A') && (*read
<= 'F')) {
929 high_digit
= *read
- 'A' + 10;
931 high_digit
= *read
- '0';
934 if (!isxdigit(*read
)) {
935 error_out("ERROR: Improperly formated subject key identifier");
937 *read
= toupper(*read
);
938 if ((*read
>= 'A') && (*read
<= 'F')) {
939 low_digit
= *(read
) - 'A' + 10;
941 low_digit
= *(read
) - '0';
943 character
= (high_digit
<< 4) | low_digit
;
951 subjectCert
->subjectKeyID
.data
= (unsigned char *) find_field
952 (data
,"subjectKeyIdentifier-text", PR_TRUE
);
953 subjectCert
->subjectKeyID
.len
= len
;
954 rv
= CERT_EncodeSubjectKeyID
955 (NULL
, &subjectCert
->subjectKeyID
, &encodedValue
);
959 return (CERT_AddExtension(extHandle
, SEC_OID_X509_SUBJECT_KEY_ID
,
960 &encodedValue
, PR_FALSE
, PR_TRUE
));
965 AddAuthKeyID (void *extHandle
,
968 CERTCertDBHandle
*handle
)
970 CERTAuthKeyID
*authKeyID
= NULL
;
971 PRArenaPool
*arena
= NULL
;
972 SECStatus rv
= SECSuccess
;
973 CERTCertificate
*issuerCert
= NULL
;
974 CERTGeneralName
*genNames
;
975 CERTName
*directoryName
= NULL
;
978 issuerCert
= CERT_FindCertByNameString(handle
, issuerNameStr
);
979 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
984 authKeyID
= PORT_ArenaZAlloc (arena
, sizeof (CERTAuthKeyID
));
985 if (authKeyID
== NULL
) {
988 if (find_field_bool(data
, "authorityKeyIdentifier-radio-keyIdentifier",
990 authKeyID
->keyID
.data
= PORT_ArenaAlloc (arena
, PORT_Strlen
991 ((char *)issuerCert
->subjectKeyID
.data
));
992 if (authKeyID
->keyID
.data
== NULL
) {
995 PORT_Memcpy (authKeyID
->keyID
.data
, issuerCert
->subjectKeyID
.data
,
996 authKeyID
->keyID
.len
=
997 PORT_Strlen((char *)issuerCert
->subjectKeyID
.data
));
1000 PORT_Assert (arena
);
1001 genNames
= (CERTGeneralName
*) PORT_ArenaZAlloc (arena
, (sizeof(CERTGeneralName
)));
1002 if (genNames
== NULL
){
1005 genNames
->l
.next
= genNames
->l
.prev
= &(genNames
->l
);
1006 genNames
->type
= certDirectoryName
;
1008 directoryName
= CERT_AsciiToName(issuerCert
->subjectName
);
1009 if (!directoryName
) {
1010 error_out("ERROR: Unable to create Directory Name");
1012 rv
= CERT_CopyName (arena
, &genNames
->name
.directoryName
,
1014 CERT_DestroyName (directoryName
);
1015 if (rv
!= SECSuccess
) {
1016 error_out("ERROR: Unable to copy Directory Name");
1018 authKeyID
->authCertIssuer
= genNames
;
1019 if (authKeyID
->authCertIssuer
== NULL
&& SECFailure
==
1021 error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension");
1023 authKeyID
->authCertSerialNumber
= issuerCert
->serialNumber
;
1025 rv
= EncodeAndAddExtensionValue(arena
, extHandle
, authKeyID
, PR_FALSE
,
1026 SEC_OID_X509_AUTH_KEY_ID
,
1027 (EXTEN_VALUE_ENCODER
)
1028 CERT_EncodeAuthKeyID
);
1030 PORT_FreeArena (arena
, PR_FALSE
);
1037 AddPrivKeyUsagePeriod(void *extHandle
,
1039 CERTCertificate
*cert
)
1043 PRArenaPool
*arena
= NULL
;
1044 SECStatus rv
= SECSuccess
;
1045 CERTPrivKeyUsagePeriod
*pkup
;
1048 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1052 pkup
= PORT_ArenaZNew (arena
, CERTPrivKeyUsagePeriod
);
1056 notBeforeStr
= (char *) PORT_Alloc(16 );
1057 notAfterStr
= (char *) PORT_Alloc(16 );
1058 *notBeforeStr
= '\0';
1059 *notAfterStr
= '\0';
1060 pkup
->arena
= arena
;
1061 pkup
->notBefore
.len
= 0;
1062 pkup
->notBefore
.data
= NULL
;
1063 pkup
->notAfter
.len
= 0;
1064 pkup
->notAfter
.data
= NULL
;
1065 if (find_field_bool(data
, "privKeyUsagePeriod-radio-notBefore", PR_TRUE
) ||
1066 find_field_bool(data
, "privKeyUsagePeriod-radio-both", PR_TRUE
)) {
1067 pkup
->notBefore
.len
= 15;
1068 pkup
->notBefore
.data
= (unsigned char *)notBeforeStr
;
1069 if (find_field_bool(data
, "privKeyUsagePeriod-notBefore-radio-manual",
1071 PORT_Strcat(notBeforeStr
,find_field(data
,
1072 "privKeyUsagePeriod-notBefore-year",
1074 PORT_Strcat(notBeforeStr
,find_field(data
,
1075 "privKeyUsagePeriod-notBefore-month",
1077 PORT_Strcat(notBeforeStr
,find_field(data
,
1078 "privKeyUsagePeriod-notBefore-day",
1080 PORT_Strcat(notBeforeStr
,find_field(data
,
1081 "privKeyUsagePeriod-notBefore-hour",
1083 PORT_Strcat(notBeforeStr
,find_field(data
,
1084 "privKeyUsagePeriod-notBefore-minute",
1086 PORT_Strcat(notBeforeStr
,find_field(data
,
1087 "privKeyUsagePeriod-notBefore-second",
1089 if ((*(notBeforeStr
+ 14) != '\0') ||
1090 (!isdigit(*(notBeforeStr
+ 13))) ||
1091 (*(notBeforeStr
+ 12) >= '5' && *(notBeforeStr
+ 12) <= '0') ||
1092 (!isdigit(*(notBeforeStr
+ 11))) ||
1093 (*(notBeforeStr
+ 10) >= '5' && *(notBeforeStr
+ 10) <= '0') ||
1094 (!isdigit(*(notBeforeStr
+ 9))) ||
1095 (*(notBeforeStr
+ 8) >= '2' && *(notBeforeStr
+ 8) <= '0') ||
1096 (!isdigit(*(notBeforeStr
+ 7))) ||
1097 (*(notBeforeStr
+ 6) >= '3' && *(notBeforeStr
+ 6) <= '0') ||
1098 (!isdigit(*(notBeforeStr
+ 5))) ||
1099 (*(notBeforeStr
+ 4) >= '1' && *(notBeforeStr
+ 4) <= '0') ||
1100 (!isdigit(*(notBeforeStr
+ 3))) ||
1101 (!isdigit(*(notBeforeStr
+ 2))) ||
1102 (!isdigit(*(notBeforeStr
+ 1))) ||
1103 (!isdigit(*(notBeforeStr
+ 0))) ||
1104 (*(notBeforeStr
+ 8) == '2' && *(notBeforeStr
+ 9) >= '4') ||
1105 (*(notBeforeStr
+ 6) == '3' && *(notBeforeStr
+ 7) >= '1') ||
1106 (*(notBeforeStr
+ 4) == '1' && *(notBeforeStr
+ 5) >= '2')) {
1107 error_out("ERROR: Improperly formated private key usage period");
1109 *(notBeforeStr
+ 14) = 'Z';
1110 *(notBeforeStr
+ 15) = '\0';
1112 if ((*(cert
->validity
.notBefore
.data
) > '5') ||
1113 ((*(cert
->validity
.notBefore
.data
) == '5') &&
1114 (*(cert
->validity
.notBefore
.data
+ 1) != '0'))) {
1115 PORT_Strcat(notBeforeStr
, "19");
1117 PORT_Strcat(notBeforeStr
, "20");
1119 PORT_Strcat(notBeforeStr
, (char *)cert
->validity
.notBefore
.data
);
1122 if (find_field_bool(data
, "privKeyUsagePeriod-radio-notAfter", PR_TRUE
) ||
1123 find_field_bool(data
, "privKeyUsagePeriod-radio-both", PR_TRUE
)) {
1124 pkup
->notAfter
.len
= 15;
1125 pkup
->notAfter
.data
= (unsigned char *)notAfterStr
;
1126 PORT_Strcat(notAfterStr
,find_field(data
,"privKeyUsagePeriod-notAfter-year",
1128 PORT_Strcat(notAfterStr
,find_field(data
,"privKeyUsagePeriod-notAfter-month",
1130 PORT_Strcat(notAfterStr
,find_field(data
,"privKeyUsagePeriod-notAfter-day",
1132 PORT_Strcat(notAfterStr
,find_field(data
,"privKeyUsagePeriod-notAfter-hour",
1134 PORT_Strcat(notAfterStr
,find_field(data
,"privKeyUsagePeriod-notAfter-minute",
1136 PORT_Strcat(notAfterStr
,find_field(data
,"privKeyUsagePeriod-notAfter-second",
1138 if ((*(notAfterStr
+ 14) != '\0') ||
1139 (!isdigit(*(notAfterStr
+ 13))) ||
1140 (*(notAfterStr
+ 12) >= '5' && *(notAfterStr
+ 12) <= '0') ||
1141 (!isdigit(*(notAfterStr
+ 11))) ||
1142 (*(notAfterStr
+ 10) >= '5' && *(notAfterStr
+ 10) <= '0') ||
1143 (!isdigit(*(notAfterStr
+ 9))) ||
1144 (*(notAfterStr
+ 8) >= '2' && *(notAfterStr
+ 8) <= '0') ||
1145 (!isdigit(*(notAfterStr
+ 7))) ||
1146 (*(notAfterStr
+ 6) >= '3' && *(notAfterStr
+ 6) <= '0') ||
1147 (!isdigit(*(notAfterStr
+ 5))) ||
1148 (*(notAfterStr
+ 4) >= '1' && *(notAfterStr
+ 4) <= '0') ||
1149 (!isdigit(*(notAfterStr
+ 3))) ||
1150 (!isdigit(*(notAfterStr
+ 2))) ||
1151 (!isdigit(*(notAfterStr
+ 1))) ||
1152 (!isdigit(*(notAfterStr
+ 0))) ||
1153 (*(notAfterStr
+ 8) == '2' && *(notAfterStr
+ 9) >= '4') ||
1154 (*(notAfterStr
+ 6) == '3' && *(notAfterStr
+ 7) >= '1') ||
1155 (*(notAfterStr
+ 4) == '1' && *(notAfterStr
+ 5) >= '2')) {
1156 error_out("ERROR: Improperly formated private key usage period");
1158 *(notAfterStr
+ 14) = 'Z';
1159 *(notAfterStr
+ 15) = '\0';
1162 PORT_Assert (arena
);
1164 rv
= EncodeAndAddExtensionValue(arena
, extHandle
, pkup
,
1165 find_field_bool(data
,
1166 "privKeyUsagePeriod-crit",
1168 SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD
,
1169 (EXTEN_VALUE_ENCODER
)
1170 CERT_EncodePrivateKeyUsagePeriod
);
1172 PORT_FreeArena (arena
, PR_FALSE
);
1174 if (notBeforeStr
!= NULL
) {
1175 PORT_Free(notBeforeStr
);
1177 if (notAfterStr
!= NULL
) {
1178 PORT_Free(notAfterStr
);
1184 AddBasicConstraint(void *extHandle
,
1187 CERTBasicConstraints basicConstraint
;
1188 SECItem encodedValue
;
1191 encodedValue
.data
= NULL
;
1192 encodedValue
.len
= 0;
1193 basicConstraint
.pathLenConstraint
= CERT_UNLIMITED_PATH_CONSTRAINT
;
1194 basicConstraint
.isCA
= (find_field_bool(data
,"basicConstraints-cA-radio-CA",
1196 if (find_field_bool(data
,"basicConstraints-pathLengthConstraint", PR_TRUE
)){
1197 basicConstraint
.pathLenConstraint
= atoi
1198 (find_field(data
,"basicConstraints-pathLengthConstraint-text",
1202 rv
= CERT_EncodeBasicConstraintValue (NULL
, &basicConstraint
,
1206 rv
= CERT_AddExtension(extHandle
, SEC_OID_X509_BASIC_CONSTRAINTS
,
1208 (find_field_bool(data
,"basicConstraints-crit",
1209 PR_TRUE
)), PR_TRUE
);
1211 PORT_Free (encodedValue
.data
);
1218 AddNscpCertType (void *extHandle
,
1221 SECItem bitStringValue
;
1222 unsigned char CertType
= 0x0;
1224 if (find_field_bool(data
,"netscape-cert-type-ssl-client", PR_TRUE
)){
1225 CertType
|= (0x80 >> 0);
1227 if (find_field_bool(data
,"netscape-cert-type-ssl-server", PR_TRUE
)){
1228 CertType
|= (0x80 >> 1);
1230 if (find_field_bool(data
,"netscape-cert-type-smime", PR_TRUE
)){
1231 CertType
|= (0x80 >> 2);
1233 if (find_field_bool(data
,"netscape-cert-type-object-signing", PR_TRUE
)){
1234 CertType
|= (0x80 >> 3);
1236 if (find_field_bool(data
,"netscape-cert-type-reserved", PR_TRUE
)){
1237 CertType
|= (0x80 >> 4);
1239 if (find_field_bool(data
,"netscape-cert-type-ssl-ca", PR_TRUE
)) {
1240 CertType
|= (0x80 >> 5);
1242 if (find_field_bool(data
,"netscape-cert-type-smime-ca", PR_TRUE
)) {
1243 CertType
|= (0x80 >> 6);
1245 if (find_field_bool(data
,"netscape-cert-type-object-signing-ca", PR_TRUE
)) {
1246 CertType
|= (0x80 >> 7);
1249 bitStringValue
.data
= &CertType
;
1250 bitStringValue
.len
= 1;
1252 return (CERT_EncodeAndAddBitStrExtension
1253 (extHandle
, SEC_OID_NS_CERT_EXT_CERT_TYPE
, &bitStringValue
,
1254 (find_field_bool(data
, "netscape-cert-type-crit", PR_TRUE
))));
1259 add_IA5StringExtension(void *extHandle
,
1264 SECItem encodedValue
;
1267 encodedValue
.data
= NULL
;
1268 encodedValue
.len
= 0;
1270 rv
= CERT_EncodeIA5TypeExtension(NULL
, string
, &encodedValue
);
1274 return (CERT_AddExtension(extHandle
, idtag
, &encodedValue
, crit
, PR_TRUE
));
1278 string_to_oid(char *string
)
1287 unsigned char *oidString
;
1288 unsigned char *write
;
1289 unsigned char *read
;
1290 unsigned char *temp
;
1296 while (*string
== ' ') {
1299 while (isdigit(*(string
+ i
))) {
1302 if (*(string
+ i
) == '.') {
1303 *(string
+ i
) = '\0';
1305 error_out("ERROR: Improperly formated OID");
1307 first_value
= atoi(string
);
1308 if (first_value
< 0 || first_value
> 2) {
1309 error_out("ERROR: Improperly formated OID");
1313 while (isdigit(*(string
+ i
))) {
1316 if (*(string
+ i
) == '.') {
1317 *(string
+ i
) = '\0';
1319 error_out("ERROR: Improperly formated OID");
1321 second_value
= atoi(string
);
1322 if (second_value
< 0 || second_value
> 39) {
1323 error_out("ERROR: Improperly formated OID");
1325 oidString
= PORT_ZAlloc(2);
1326 *oidString
= (first_value
* 40) + second_value
;
1327 *(oidString
+ 1) = '\0';
1331 temp
= write
= PORT_ZAlloc(length
);
1332 while (*string
!= '\0') {
1334 while(isdigit(*(string
+ i
))) {
1337 if (*(string
+ i
) == '\0') {
1338 value
= atoi(string
);
1341 if (*(string
+ i
) == '.') {
1342 *(string
+ i
) = '\0';
1343 value
= atoi(string
);
1346 *(string
+ i
) = '\0';
1348 value
= atoi(string
);
1349 while (*(string
+ i
) == ' ')
1351 if (*(string
+ i
) != '\0') {
1352 error_out("ERROR: Improperly formated OID");
1357 while (value
!= 0) {
1358 if (remaining
< 1) {
1359 remaining
+= length
;
1360 length
= length
* 2;
1361 temp
= PORT_Realloc(temp
, length
);
1362 write
= temp
+ length
- remaining
;
1364 *write
= (value
& 0x7f) | (0x80);
1369 *temp
= *temp
& (0x7f);
1370 oidLength
+= write
- temp
;
1371 oidString
= PORT_Realloc(oidString
, (oidLength
+ 1));
1373 write
= oidLength
+ oidString
- 1;
1374 for (i
= 0; i
< (length
- remaining
); i
++) {
1382 *(oidString
+ oidLength
) = '\0';
1383 oid
= (SECItem
*) PORT_ZAlloc(sizeof(SECItem
));
1384 oid
->data
= oidString
;
1385 oid
->len
= oidLength
;
1391 string_to_ipaddress(char *string
)
1399 while (*string
== ' ') {
1402 ipaddress
= (SECItem
*) PORT_ZAlloc(sizeof(SECItem
));
1403 ipaddress
->data
= PORT_ZAlloc(9);
1404 while (*string
!= '\0' && j
< 8) {
1405 while (isdigit(*(string
+ i
))) {
1408 if (*(string
+ i
) == '.') {
1409 *(string
+ i
) = '\0';
1410 value
= atoi(string
);
1411 string
= string
+ i
+ 1;
1414 if (*(string
+ i
) == '\0') {
1415 value
= atoi(string
);
1416 string
= string
+ i
;
1419 *(string
+ i
) = '\0';
1420 while (*(string
+ i
) == ' ') {
1423 if (*(string
+ i
) == '\0') {
1424 value
= atoi(string
);
1425 string
= string
+ i
;
1428 error_out("ERROR: Improperly formated IP Address");
1432 if (value
>= 0 || value
< 256) {
1433 *(ipaddress
->data
+ j
) = value
;
1435 error_out("ERROR: Improperly formated IP Address");
1439 *(ipaddress
->data
+ j
) = '\0';
1440 if (j
!= 4 && j
!= 8) {
1441 error_out("ERROR: Improperly formated IP Address");
1448 string_to_binary(char *string
)
1454 rv
= (SECItem
*) PORT_ZAlloc(sizeof(SECItem
));
1458 rv
->data
= (unsigned char *) PORT_ZAlloc((PORT_Strlen(string
))/3 + 2);
1459 while (!isxdigit(*string
)) {
1463 while (*string
!= '\0') {
1464 if (isxdigit(*string
)) {
1465 if (*string
>= '0' && *string
<= '9') {
1466 high_digit
= *string
- '0';
1468 *string
= toupper(*string
);
1469 high_digit
= *string
- 'A';
1472 if (*string
>= '0' && *string
<= '9') {
1473 low_digit
= *string
- '0';
1475 *string
= toupper(*string
);
1476 low_digit
= *string
= 'A';
1480 if (*string
== ':') {
1483 if (*string
== ' ') {
1484 while (*string
== ' ') {
1488 if (*string
!= '\0') {
1489 error_out("ERROR: Improperly formated binary encoding");
1499 MakeGeneralName(char *name
,
1500 CERTGeneralName
*genName
,
1504 SECOidData
*oidData
;
1506 SECItem
*temp
= NULL
;
1509 PRBool binary
= PR_FALSE
;
1510 SECStatus rv
= SECSuccess
;
1511 PRBool nickname
= PR_FALSE
;
1513 PORT_Assert(genName
);
1515 nameType
= *(name
+ PORT_Strlen(name
) - 1) - '0';
1516 if (nameType
== 0 && *(name
+PORT_Strlen(name
) - 2) == '1') {
1518 nameType
= certOtherName
;
1520 if (nameType
< 1 || nameType
> 9) {
1521 error_out("ERROR: Unknown General Name Type");
1523 *(name
+ PORT_Strlen(name
) - 4) = '\0';
1524 genName
->type
= nameType
;
1526 switch (genName
->type
) {
1528 case certRFC822Name
:
1530 genName
->name
.other
.data
= (unsigned char *)name
;
1531 genName
->name
.other
.len
= PORT_Strlen(name
);
1535 case certIPAddress
: {
1536 ipaddress
= string_to_ipaddress(name
);
1537 genName
->name
.other
.data
= ipaddress
->data
;
1538 genName
->name
.other
.len
= ipaddress
->len
;
1542 case certRegisterID
: {
1543 oid
= string_to_oid(name
);
1544 genName
->name
.other
.data
= oid
->data
;
1545 genName
->name
.other
.len
= oid
->len
;
1549 case certEDIPartyName
:
1550 case certX400Address
: {
1552 genName
->name
.other
.data
= PORT_ArenaAlloc (arena
,
1553 PORT_Strlen (name
) + 2);
1554 if (genName
->name
.other
.data
== NULL
) {
1558 PORT_Memcpy (genName
->name
.other
.data
+ 2, name
, PORT_Strlen (name
));
1559 /* This may not be accurate for all cases.
1560 For now, use this tag type */
1561 genName
->name
.other
.data
[0] = (char)(((genName
->type
- 1) &
1563 genName
->name
.other
.data
[1] = (char)PORT_Strlen (name
);
1564 genName
->name
.other
.len
= PORT_Strlen (name
) + 2;
1568 case certOtherName
: {
1571 while (!isdigit(*(name
+ PORT_Strlen(name
) - i
))) {
1574 if (*(name
+ PORT_Strlen(name
) - i
) == '1') {
1579 while (*(name
+ PORT_Strlen(name
) - i
) != '-') {
1582 *(name
+ PORT_Strlen(name
) - i
- 1) = '\0';
1584 while (*(name
+ i
) != '-') {
1587 *(name
+ i
- 1) = '\0';
1588 oid
= string_to_oid(name
+ i
+ 2);
1590 oidData
= SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME
);
1591 oid
= &oidData
->oid
;
1592 while (*(name
+ PORT_Strlen(name
) - i
) != '-') {
1595 *(name
+ PORT_Strlen(name
) - i
) = '\0';
1597 genName
->name
.OthName
.oid
.data
= oid
->data
;
1598 genName
->name
.OthName
.oid
.len
= oid
->len
;
1600 temp
= string_to_binary(name
);
1601 genName
->name
.OthName
.name
.data
= temp
->data
;
1602 genName
->name
.OthName
.name
.len
= temp
->len
;
1604 temp
= (SECItem
*) PORT_ZAlloc(sizeof(SECItem
));
1608 temp
->data
= (unsigned char *)name
;
1609 temp
->len
= PORT_Strlen(name
);
1610 SEC_ASN1EncodeItem (arena
, &(genName
->name
.OthName
.name
), temp
,
1611 CERTIA5TypeTemplate
);
1617 case certDirectoryName
: {
1618 CERTName
*directoryName
= NULL
;
1620 directoryName
= CERT_AsciiToName (name
);
1621 if (!directoryName
) {
1622 error_out("ERROR: Improperly formated alternative name");
1625 rv
= CERT_CopyName (arena
, &genName
->name
.directoryName
,
1627 CERT_DestroyName (directoryName
);
1632 genName
->l
.next
= &(genName
->l
);
1633 genName
->l
.prev
= &(genName
->l
);
1638 static CERTGeneralName
*
1639 MakeAltName(Pair
*data
,
1643 CERTGeneralName
*SubAltName
;
1644 CERTGeneralName
*current
;
1645 CERTGeneralName
*newname
;
1647 SECStatus rv
= SECSuccess
;
1651 len
= PORT_Strlen(which
);
1652 name
= find_field(data
, which
, PR_TRUE
);
1653 SubAltName
= current
= (CERTGeneralName
*) PORT_ZAlloc
1654 (sizeof(CERTGeneralName
));
1655 if (current
== NULL
) {
1658 while (name
!= NULL
) {
1660 rv
= MakeGeneralName(name
, current
, arena
);
1662 if (rv
!= SECSuccess
) {
1665 if (*(which
+ len
-1) < '9') {
1666 *(which
+ len
- 1) = *(which
+ len
- 1) + 1;
1668 if (isdigit(*(which
+ len
- 2) )) {
1669 *(which
+ len
- 2) = *(which
+ len
- 2) + 1;
1670 *(which
+ len
- 1) = '0';
1672 *(which
+ len
- 1) = '1';
1673 *(which
+ len
) = '0';
1674 *(which
+ len
+ 1) = '\0';
1678 len
= PORT_Strlen(which
);
1679 name
= find_field(data
, which
, PR_TRUE
);
1681 newname
= (CERTGeneralName
*) PORT_ZAlloc(sizeof(CERTGeneralName
));
1682 if (newname
== NULL
) {
1685 current
->l
.next
= &(newname
->l
);
1686 newname
->l
.prev
= &(current
->l
);
1690 current
->l
.next
= &(SubAltName
->l
);
1691 SubAltName
->l
.prev
= &(current
->l
);
1694 if (rv
== SECFailure
) {
1700 static CERTNameConstraints
*
1701 MakeNameConstraints(Pair
*data
,
1704 CERTNameConstraints
*NameConstraints
;
1705 CERTNameConstraint
*current
= NULL
;
1706 CERTNameConstraint
*last_permited
= NULL
;
1707 CERTNameConstraint
*last_excluded
= NULL
;
1708 char *constraint
= NULL
;
1710 SECStatus rv
= SECSuccess
;
1718 NameConstraints
= (CERTNameConstraints
*) PORT_ZAlloc
1719 (sizeof(CERTNameConstraints
));
1720 which
= make_copy_string("NameConstraintSelect0", 25,'\0');
1721 len
= PORT_Strlen(which
);
1722 constraint
= find_field(data
, which
, PR_TRUE
);
1723 NameConstraints
->permited
= NameConstraints
->excluded
= NULL
;
1724 while (constraint
!= NULL
) {
1725 current
= (CERTNameConstraint
*) PORT_ZAlloc
1726 (sizeof(CERTNameConstraint
));
1727 if (current
== NULL
) {
1731 while (*(constraint
+ PORT_Strlen(constraint
) - i
) != '-') {
1734 *(constraint
+ PORT_Strlen(constraint
) - i
- 1) = '\0';
1735 max
= (long) atoi(constraint
+ PORT_Strlen(constraint
) + 3);
1737 (void) SEC_ASN1EncodeInteger(arena
, ¤t
->max
, max
);
1740 while (*(constraint
+ PORT_Strlen(constraint
) - i
) != '-') {
1743 *(constraint
+ PORT_Strlen(constraint
) - i
- 1) = '\0';
1744 min
= (long) atoi(constraint
+ PORT_Strlen(constraint
) + 3);
1745 (void) SEC_ASN1EncodeInteger(arena
, ¤t
->min
, min
);
1746 while (*(constraint
+ PORT_Strlen(constraint
) - i
) != '-') {
1749 *(constraint
+ PORT_Strlen(constraint
) - i
- 1) = '\0';
1750 if (*(constraint
+ PORT_Strlen(constraint
) + 3) == 'p') {
1753 permited
= PR_FALSE
;
1755 rv
= MakeGeneralName(constraint
, &(current
->name
), arena
);
1757 if (rv
!= SECSuccess
) {
1760 if (*(which
+ len
- 1) < '9') {
1761 *(which
+ len
- 1) = *(which
+ len
- 1) + 1;
1763 if (isdigit(*(which
+ len
- 2) )) {
1764 *(which
+ len
- 2) = *(which
+ len
- 2) + 1;
1765 *(which
+ len
- 1) = '0';
1767 *(which
+ len
- 1) = '1';
1768 *(which
+ len
) = '0';
1769 *(which
+ len
+ 1) = '\0';
1773 len
= PORT_Strlen(which
);
1775 if (NameConstraints
->permited
== NULL
) {
1776 NameConstraints
->permited
= last_permited
= current
;
1778 last_permited
->l
.next
= &(current
->l
);
1779 current
->l
.prev
= &(last_permited
->l
);
1780 last_permited
= current
;
1782 if (NameConstraints
->excluded
== NULL
) {
1783 NameConstraints
->excluded
= last_excluded
= current
;
1785 last_excluded
->l
.next
= &(current
->l
);
1786 current
->l
.prev
= &(last_excluded
->l
);
1787 last_excluded
= current
;
1789 constraint
= find_field(data
, which
, PR_TRUE
);
1790 if (constraint
!= NULL
) {
1791 current
= (CERTNameConstraint
*) PORT_ZAlloc(sizeof(CERTNameConstraint
));
1792 if (current
== NULL
) {
1797 if (NameConstraints
->permited
!= NULL
) {
1798 last_permited
->l
.next
= &(NameConstraints
->permited
->l
);
1799 NameConstraints
->permited
->l
.prev
= &(last_permited
->l
);
1801 if (NameConstraints
->excluded
!= NULL
) {
1802 last_excluded
->l
.next
= &(NameConstraints
->excluded
->l
);
1803 NameConstraints
->excluded
->l
.prev
= &(last_excluded
->l
);
1805 if (which
!= NULL
) {
1808 if (rv
== SECFailure
) {
1811 return NameConstraints
;
1817 AddAltName(void *extHandle
,
1819 char *issuerNameStr
,
1820 CERTCertDBHandle
*handle
,
1823 PRBool autoIssuer
= PR_FALSE
;
1824 PRArenaPool
*arena
= NULL
;
1825 CERTGeneralName
*genName
= NULL
;
1828 SECStatus rv
= SECSuccess
;
1829 SECItem
*issuersAltName
= NULL
;
1830 CERTCertificate
*issuerCert
= NULL
;
1832 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1833 if (arena
== NULL
) {
1837 which
= make_copy_string("SubAltNameSelect0", 20,'\0');
1838 genName
= MakeAltName(data
, which
, arena
);
1841 autoIssuer
= find_field_bool(data
,"IssuerAltNameSourceRadio-auto",
1843 issuerCert
= CERT_FindCertByNameString(handle
, issuerNameStr
);
1844 rv
= cert_FindExtension((*issuerCert
).extensions
,
1845 SEC_OID_X509_SUBJECT_ALT_NAME
,
1847 if (issuersAltName
== NULL
) {
1848 name
= PORT_Alloc(PORT_Strlen((*issuerCert
).subjectName
) + 4);
1849 PORT_Strcpy(name
, (*issuerCert
).subjectName
);
1850 PORT_Strcat(name
, " - 5");
1853 which
= make_copy_string("IssuerAltNameSelect0", 20,'\0');
1854 genName
= MakeAltName(data
, which
, arena
);
1858 EncodeAndAddExtensionValue(arena
, extHandle
, genName
,
1859 find_field_bool(data
, "SubAltName-crit",
1861 SEC_OID_X509_SUBJECT_ALT_NAME
,
1862 (EXTEN_VALUE_ENCODER
)
1863 CERT_EncodeAltNameExtension
);
1866 if (autoIssuer
&& (name
== NULL
)) {
1867 rv
= CERT_AddExtension
1868 (extHandle
, SEC_OID_X509_ISSUER_ALT_NAME
, issuersAltName
,
1869 find_field_bool(data
, "IssuerAltName-crit", PR_TRUE
), PR_TRUE
);
1871 EncodeAndAddExtensionValue(arena
, extHandle
, genName
,
1872 find_field_bool(data
,
1873 "IssuerAltName-crit",
1875 SEC_OID_X509_ISSUER_ALT_NAME
,
1876 (EXTEN_VALUE_ENCODER
)
1877 CERT_EncodeAltNameExtension
);
1880 if (which
!= NULL
) {
1883 if (issuerCert
!= NULL
) {
1884 CERT_DestroyCertificate(issuerCert
);
1891 AddNameConstraints(void *extHandle
,
1894 PRArenaPool
*arena
= NULL
;
1895 CERTNameConstraints
*constraints
= NULL
;
1896 SECStatus rv
= SECSuccess
;
1899 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1900 if (arena
== NULL
) {
1903 constraints
= MakeNameConstraints(data
, arena
);
1904 if (constraints
!= NULL
) {
1905 EncodeAndAddExtensionValue(arena
, extHandle
, constraints
, PR_TRUE
,
1906 SEC_OID_X509_NAME_CONSTRAINTS
,
1907 (EXTEN_VALUE_ENCODER
)
1908 CERT_EncodeNameConstraintsExtension
);
1910 if (arena
!= NULL
) {
1911 PORT_ArenaRelease (arena
, NULL
);
1918 add_extensions(CERTCertificate
*subjectCert
,
1920 char *issuerNameStr
,
1921 CERTCertDBHandle
*handle
)
1924 SECStatus rv
= SECSuccess
;
1927 extHandle
= CERT_StartCertExtensions (subjectCert
);
1928 if (extHandle
== NULL
) {
1929 error_out("ERROR: Unable to get certificates extension handle");
1931 if (find_field_bool(data
, "keyUsage", PR_TRUE
)) {
1932 rv
= AddKeyUsage(extHandle
, data
);
1933 if (rv
!= SECSuccess
) {
1934 error_out("ERROR: Unable to add Key Usage extension");
1938 if( find_field_bool(data
, "extKeyUsage", PR_TRUE
) ) {
1939 rv
= AddExtKeyUsage(extHandle
, data
);
1940 if( SECSuccess
!= rv
) {
1941 error_out("ERROR: Unable to add Extended Key Usage extension");
1945 if (find_field_bool(data
, "basicConstraints", PR_TRUE
)) {
1946 rv
= AddBasicConstraint(extHandle
, data
);
1947 if (rv
!= SECSuccess
) {
1948 error_out("ERROR: Unable to add Basic Constraint extension");
1951 if (find_field_bool(data
, "subjectKeyIdentifier", PR_TRUE
)) {
1952 rv
= AddSubKeyID(extHandle
, data
, subjectCert
);
1953 if (rv
!= SECSuccess
) {
1954 error_out("ERROR: Unable to add Subject Key Identifier Extension");
1957 if (find_field_bool(data
, "authorityKeyIdentifier", PR_TRUE
)) {
1958 rv
= AddAuthKeyID (extHandle
, data
, issuerNameStr
, handle
);
1959 if (rv
!= SECSuccess
) {
1960 error_out("ERROR: Unable to add Authority Key Identifier extension");
1963 if (find_field_bool(data
, "privKeyUsagePeriod", PR_TRUE
)) {
1964 rv
= AddPrivKeyUsagePeriod (extHandle
, data
, subjectCert
);
1965 if (rv
!= SECSuccess
) {
1966 error_out("ERROR: Unable to add Private Key Usage Period extension");
1969 if (find_field_bool(data
, "SubAltName", PR_TRUE
)) {
1970 rv
= AddAltName (extHandle
, data
, NULL
, NULL
, 0);
1971 if (rv
!= SECSuccess
) {
1972 error_out("ERROR: Unable to add Subject Alternative Name extension");
1975 if (find_field_bool(data
, "IssuerAltName", PR_TRUE
)) {
1976 rv
= AddAltName (extHandle
, data
, issuerNameStr
, handle
, 1);
1977 if (rv
!= SECSuccess
) {
1978 error_out("ERROR: Unable to add Issuer Alternative Name Extension");
1981 if (find_field_bool(data
, "NameConstraints", PR_TRUE
)) {
1982 rv
= AddNameConstraints(extHandle
, data
);
1983 if (rv
!= SECSuccess
) {
1984 error_out("ERROR: Unable to add Name Constraints Extension");
1987 if (find_field_bool(data
, "netscape-cert-type", PR_TRUE
)) {
1988 rv
= AddNscpCertType(extHandle
, data
);
1989 if (rv
!= SECSuccess
) {
1990 error_out("ERROR: Unable to add Netscape Certificate Type Extension");
1993 if (find_field_bool(data
, "netscape-base-url", PR_TRUE
)) {
1994 rv
= add_IA5StringExtension(extHandle
,
1995 find_field(data
, "netscape-base-url-text",
1997 find_field_bool(data
,
1998 "netscape-base-url-crit",
2000 SEC_OID_NS_CERT_EXT_BASE_URL
);
2001 if (rv
!= SECSuccess
) {
2002 error_out("ERROR: Unable to add Netscape Base URL Extension");
2005 if (find_field_bool(data
, "netscape-revocation-url", PR_TRUE
)) {
2006 rv
= add_IA5StringExtension(extHandle
,
2008 "netscape-revocation-url-text",
2011 (data
, "netscape-revocation-url-crit",
2013 SEC_OID_NS_CERT_EXT_REVOCATION_URL
);
2014 if (rv
!= SECSuccess
) {
2015 error_out("ERROR: Unable to add Netscape Revocation URL Extension");
2018 if (find_field_bool(data
, "netscape-ca-revocation-url", PR_TRUE
)) {
2019 rv
= add_IA5StringExtension(extHandle
,
2021 "netscape-ca-revocation-url-text",
2024 (data
, "netscape-ca-revocation-url-crit"
2026 SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL
);
2027 if (rv
!= SECSuccess
) {
2028 error_out("ERROR: Unable to add Netscape CA Revocation URL Extension");
2031 if (find_field_bool(data
, "netscape-cert-renewal-url", PR_TRUE
)) {
2032 rv
= add_IA5StringExtension(extHandle
,
2034 "netscape-cert-renewal-url-text",
2037 (data
, "netscape-cert-renewal-url-crit",
2039 SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL
);
2040 if (rv
!= SECSuccess
) {
2041 error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension");
2044 if (find_field_bool(data
, "netscape-ca-policy-url", PR_TRUE
)) {
2045 rv
= add_IA5StringExtension(extHandle
,
2047 "netscape-ca-policy-url-text",
2050 (data
, "netscape-ca-policy-url-crit",
2052 SEC_OID_NS_CERT_EXT_CA_POLICY_URL
);
2053 if (rv
!= SECSuccess
) {
2054 error_out("ERROR: Unable to add Netscape CA Policy URL Extension");
2057 if (find_field_bool(data
, "netscape-ssl-server-name", PR_TRUE
)) {
2058 rv
= add_IA5StringExtension(extHandle
,
2060 "netscape-ssl-server-name-text",
2063 (data
, "netscape-ssl-server-name-crit",
2065 SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME
);
2066 if (rv
!= SECSuccess
) {
2067 error_out("ERROR: Unable to add Netscape SSL Server Name Extension");
2070 if (find_field_bool(data
, "netscape-comment", PR_TRUE
)) {
2071 rv
= add_IA5StringExtension(extHandle
,
2072 find_field(data
, "netscape-comment-text",
2074 find_field_bool(data
,
2075 "netscape-comment-crit",
2077 SEC_OID_NS_CERT_EXT_COMMENT
);
2078 if (rv
!= SECSuccess
) {
2079 error_out("ERROR: Unable to add Netscape Comment Extension");
2082 CERT_FinishExtensions(extHandle
);
2089 return_dbpasswd(PK11SlotInfo
*slot
, PRBool retry
, void *data
)
2093 /* don't clobber our poor smart card */
2094 if (retry
== PR_TRUE
) {
2098 PORT_Strcpy(rv
, "foo");
2104 FindPrivateKeyFromNameStr(char *name
,
2105 CERTCertDBHandle
*certHandle
)
2107 SECKEYPrivateKey
*key
;
2108 CERTCertificate
*cert
;
2109 CERTCertificate
*p11Cert
;
2112 /* We don't presently have a PK11 function to find a cert by
2114 ** We do have a function to find a cert in the internal slot's
2115 ** cert db by subject name, but it doesn't setup the slot info.
2116 ** So, this HACK works, but should be replaced as soon as we
2117 ** have a function to search for certs accross slots by subject name.
2119 cert
= CERT_FindCertByNameString(certHandle
, name
);
2120 if (cert
== NULL
|| cert
->nickname
== NULL
) {
2121 error_out("ERROR: Unable to retrieve issuers certificate");
2123 p11Cert
= PK11_FindCertFromNickname(cert
->nickname
, NULL
);
2124 if (p11Cert
== NULL
) {
2125 error_out("ERROR: Unable to retrieve issuers certificate");
2127 key
= PK11_FindKeyByAnyCert(p11Cert
, NULL
);
2132 SignCert(CERTCertificate
*cert
,
2133 char *issuerNameStr
,
2135 CERTCertDBHandle
*handle
,
2139 SECKEYPrivateKey
*caPrivateKey
= NULL
;
2144 if (which_key
== 0) {
2145 caPrivateKey
= FindPrivateKeyFromNameStr(issuerNameStr
, handle
);
2147 caPrivateKey
= privkeys
[which_key
- 1];
2149 if (caPrivateKey
== NULL
) {
2150 error_out("ERROR: unable to retrieve issuers key");
2153 arena
= cert
->arena
;
2155 algID
= SEC_GetSignatureAlgorithmOidTag(caPrivateKey
->keyType
,
2157 if (algID
== SEC_OID_UNKNOWN
) {
2158 error_out("ERROR: Unknown key type for issuer.");
2162 rv
= SECOID_SetAlgorithmID(arena
, &cert
->signature
, algID
, 0);
2163 if (rv
!= SECSuccess
) {
2164 error_out("ERROR: Could not set signature algorithm id.");
2167 if (find_field_bool(data
,"ver-1", PR_TRUE
)) {
2168 *(cert
->version
.data
) = 0;
2169 cert
->version
.len
= 1;
2171 *(cert
->version
.data
) = 2;
2172 cert
->version
.len
= 1;
2176 (void) SEC_ASN1EncodeItem (arena
, &der
, cert
, CERT_CertificateTemplate
);
2177 if (der
.data
== NULL
) {
2178 error_out("ERROR: Could not encode certificate.\n");
2180 rv
= SEC_DerSignData (arena
, &(cert
->derCert
), der
.data
, der
.len
, caPrivateKey
,
2182 if (rv
!= SECSuccess
) {
2183 error_out("ERROR: Could not sign encoded certificate data.\n");
2186 SECKEY_DestroyPrivateKey(caPrivateKey
);
2187 return &(cert
->derCert
);
2192 main(int argc
, char **argv
)
2195 int remaining
= 500;
2203 char *form_output
= "key=MIIBPTCBpzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7SLqjWBL9Wl11Vlg%0AaMqZCvcQOL%2FnvSqYPPRP0XZy9SoAeyWzQnBOiCm2t8H5mK7r2jnKdAQOmfhjaJil%0A3hNVu3SekHOXF6Ze7bkWa6%2FSGVcY%2FojkydxFSgY43nd1iydzPQDp8WWLL%2BpVpt%2B%2B%0ATRhFtVXbF0fQI03j9h3BoTgP2lkCAwEAARYDZm9vMA0GCSqGSIb3DQEBBAUAA4GB%0AAJ8UfRKJ0GtG%2B%2BufCC6tAfTzKrq3CTBHnom55EyXcsAsv6WbDqI%2F0rLAPkn2Xo1r%0AnNhtMxIuj441blMt%2Fa3AGLOy5zmC7Qawt8IytvQikQ1XTpTBCXevytrmLjCmlURr%0ANJryTM48WaMQHiMiJpbXCqVJC1d%2FpEWBtqvALzZaOOIy&subject=CN%3D%22test%22%26serial-auto%3Dtrue%26serial_value%3D%26ver-1%3Dtrue%26ver-3%3Dfalse%26caChoiceradio-SignWithDefaultkey%3Dtrue%26caChoiceradio-SignWithRandomChain%3Dfalse%26autoCAs%3D%26caChoiceradio-SignWithSpecifiedChain%3Dfalse%26manCAs%3D%26%24";
2207 char *issuerNameStr
;
2209 char *DBdir
= DB_DIRECTORY
;
2210 char *prefixs
[10] = {"CA#1-", "CA#2-", "CA#3-",
2211 "CA#4-", "CA#5-", "CA#6-",
2212 "CA#7-", "CA#8-", "CA#9-", ""};
2214 CERTCertificate
*cert
;
2215 CERTCertDBHandle
*handle
;
2216 CERTCertificateRequest
*certReq
= NULL
;
2222 SECStatus status
= SECSuccess
;
2223 extern char prefix
[PREFIX_LEN
];
2224 SEC_PKCS7ContentInfo
*certChain
;
2225 SECItem
*encodedCertChain
;
2226 PRBool UChain
= PR_FALSE
;
2229 progName
= strrchr(argv
[0], '/');
2230 progName
= progName
? progName
+1 : argv
[0];
2236 SECU_ConfigDirectory(DBdir
);
2238 PK11_SetPasswordFunc(return_dbpasswd
);
2239 status
= NSS_InitReadWrite(DBdir
);
2240 if (status
!= SECSuccess
) {
2241 SECU_PrintPRandOSError(progName
);
2244 handle
= CERT_GetDefaultCertDB();
2247 #if !defined(OFFLINE)
2248 form_output
= (char*) PORT_Alloc(length
);
2249 if (form_output
== NULL
) {
2253 while (feof(stdin
) == 0 ) {
2254 if (remaining
<= 1) {
2255 remaining
+= length
;
2256 length
= length
* 2;
2257 form_output
= PORT_Realloc(form_output
, (length
));
2258 if (form_output
== NULL
) {
2261 pos
= form_output
+ length
- remaining
;
2263 n
= fread(pos
, 1, (size_t) (remaining
- 1), stdin
);
2269 length
= pos
- form_output
;
2271 length
= PORT_Strlen(form_output
);
2274 printf("Content-type: text/plain\n\n");
2275 fwrite(form_output
, 1, (size_t)length
, stdout
);
2279 fwrite(form_output
, 1, (size_t)length
, stdout
);
2283 form_data
= make_datastruct(form_output
, length
);
2284 status
= clean_input(form_data
);
2285 #if !defined(OFFLINE)
2286 PORT_Free(form_output
);
2290 while(return_name(form_data
, i
) != NULL
) {
2291 printf("%s",return_name(form_data
,i
));
2293 printf("%s",return_data(form_data
,i
));
2297 printf("I got that done, woo hoo\n");
2300 issuerNameStr
= PORT_Alloc(200);
2301 if (find_field_bool(form_data
, "caChoiceradio-SignWithSpecifiedChain",
2304 chainLen
= atoi(find_field(form_data
, "manCAs", PR_FALSE
));
2305 PORT_Strcpy(prefix
, prefixs
[0]);
2306 issuerNameStr
= PORT_Strcpy(issuerNameStr
,
2307 "CN=Cert-O-Matic II, O=Cert-O-Matic II");
2308 if (chainLen
== 0) {
2312 if (find_field_bool(form_data
, "caChoiceradio-SignWithRandomChain",
2314 PORT_Strcpy(prefix
,prefixs
[9]);
2315 chainLen
= atoi(find_field(form_data
, "autoCAs", PR_FALSE
));
2316 if (chainLen
< 1 || chainLen
> 18) {
2317 issuerNameStr
= PORT_Strcpy(issuerNameStr
,
2318 "CN=CA18, O=Cert-O-Matic II");
2320 issuerNameStr
= PORT_Strcpy(issuerNameStr
, "CN=CA");
2321 issuerNameStr
= PORT_Strcat(issuerNameStr
,
2322 find_field(form_data
,"autoCAs", PR_FALSE
));
2323 issuerNameStr
= PORT_Strcat(issuerNameStr
,", O=Cert-O-Matic II");
2325 issuerNameStr
= PORT_Strcpy(issuerNameStr
,
2326 "CN=Cert-O-Matic II, O=Cert-O-Matic II");
2334 extern SECStatus
cert_GetKeyID(CERTCertificate
*cert
);
2336 if (i
!= 0 && UChain
) {
2337 PORT_Strcpy(prefix
, prefixs
[i
]);
2339 /* find_field(form_data,"subject", PR_TRUE); */
2340 certReq
= makeCertReq(form_data
, which_key
);
2344 serial
= get_serial_number(form_data
);
2346 cert
= MakeV1Cert(handle
, certReq
, issuerNameStr
, PR_FALSE
,
2347 serial
, warpmonths
, form_data
);
2348 if (certReq
!= NULL
) {
2349 CERT_DestroyCertificateRequest(certReq
);
2351 if (find_field_bool(form_data
,"ver-3", PR_TRUE
)) {
2352 status
= add_extensions(cert
, form_data
, issuerNameStr
, handle
);
2353 if (status
!= SECSuccess
) {
2354 error_out("ERROR: Unable to add extensions");
2357 status
= cert_GetKeyID(cert
);
2358 if (status
== SECFailure
) {
2359 error_out("ERROR: Unable to get Key ID.");
2361 certDER
= SignCert(cert
, issuerNameStr
, form_data
, handle
, which_key
);
2362 CERT_NewTempCertificate(handle
, certDER
, NULL
, PR_FALSE
, PR_TRUE
);
2363 issuerNameStr
= find_field(form_data
, "subject", PR_TRUE
);
2364 /* SECITEM_FreeItem(certDER, PR_TRUE); */
2365 CERT_DestroyCertificate(cert
);
2366 if (i
== (chainLen
- 1)) {
2370 } while (i
< 9 && UChain
);
2375 outfile
= fopen("../certout", "wb");
2377 certName
= find_field(form_data
, "subject", PR_FALSE
);
2378 cert
= CERT_FindCertByNameString(handle
, certName
);
2379 certChain
= SEC_PKCS7CreateCertsOnly (cert
, PR_TRUE
, handle
);
2380 if (certChain
== NULL
) {
2381 error_out("ERROR: No certificates in cert chain");
2383 encodedCertChain
= SEC_PKCS7EncodeItem (NULL
, NULL
, certChain
, NULL
, NULL
,
2385 if (encodedCertChain
) {
2386 #if !defined(FILEOUT)
2387 printf("Content-type: application/x-x509-user-cert\r\n");
2388 printf("Content-length: %d\r\n\r\n", encodedCertChain
->len
);
2389 fwrite (encodedCertChain
->data
, 1, encodedCertChain
->len
, stdout
);
2391 fwrite (encodedCertChain
->data
, 1, encodedCertChain
->len
, outfile
);
2395 error_out("Error: Unable to DER encode certificate");
2398 printf("\nI got here!\n");
2403 if (NSS_Shutdown() != SECSuccess
) {