diff options
author | neil.williams%sun.com <devnull@localhost> | 2007-09-07 18:45:53 +0000 |
---|---|---|
committer | neil.williams%sun.com <devnull@localhost> | 2007-09-07 18:45:53 +0000 |
commit | ac86c940d22f611c8d711ac0d5c58a88f1053127 (patch) | |
tree | dd25d8b42af4d6b46afff1916fbb3516576e3251 /security/nss/cmd/certutil | |
parent | dc25d0e0163b0e6064c2c743069698ff4a3b1fa7 (diff) | |
download | nss-hg-ac86c940d22f611c8d711ac0d5c58a88f1053127.tar.gz |
Bug 324744, add gen of policy extns to certutil, second of 3 patches
r=julien
Diffstat (limited to 'security/nss/cmd/certutil')
-rw-r--r-- | security/nss/cmd/certutil/certext.c | 929 | ||||
-rw-r--r-- | security/nss/cmd/certutil/certutil.c | 81 |
2 files changed, 837 insertions, 173 deletions
diff --git a/security/nss/cmd/certutil/certext.c b/security/nss/cmd/certutil/certext.c index 49a3ce18e..fae378aba 100644 --- a/security/nss/cmd/certutil/certext.c +++ b/security/nss/cmd/certutil/certext.c @@ -57,11 +57,11 @@ #endif #include "cert.h" +#include "prprf.h" +#include "certutil.h" #define GEN_BREAK(e) rv=e; break; -extern char *progName; - static char * Gets_s(char *buff, size_t size) { char *str; @@ -95,6 +95,20 @@ Gets_s(char *buff, size_t size) { return str; } + +static SECStatus +PrintChoicesAndGetAnswer(char* str, char* rBuff, int rSize) +{ + fprintf(stdout, str); + fprintf(stdout, " > "); + fflush (stdout); + if (Gets_s(rBuff, rSize) == NULL) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + return SECSuccess; +} + static CERTGeneralName * GetGeneralName (PRArenaPool *arena) { @@ -109,15 +123,13 @@ GetGeneralName (PRArenaPool *arena) PORT_Assert (arena); mark = PORT_ArenaMark (arena); do { - puts ("\nSelect one of the following general name type: \n"); - puts ("\t1 - instance of other name\n\t2 - rfc822Name\n\t3 - " - "dnsName\n"); - puts ("\t4 - x400Address\n\t5 - directoryName\n\t6 - ediPartyName\n"); - puts ("\t7 - uniformResourceidentifier\n\t8 - ipAddress\n\t9 - " - "registerID\n"); - puts ("\tAny other number to finish\n\t\tChoice:"); - if (Gets_s (buffer, sizeof(buffer)) == NULL) { - PORT_SetError(SEC_ERROR_INPUT_LEN); + if (PrintChoicesAndGetAnswer( + "\nSelect one of the following general name type: \n" + "\t1 - instance of other name\n\t2 - rfc822Name\n\t3 - dnsName\n" + "\t4 - x400Address\n\t5 - directoryName\n\t6 - ediPartyName\n" + "\t7 - uniformResourceidentifier\n\t8 - ipAddress\n\t9 - registerID\n" + "\tAny other number to finish\n\t\tChoice:", + buffer, sizeof(buffer)) == SECFailure) { GEN_BREAK (SECFailure); } intValue = PORT_Atoi (buffer); @@ -260,31 +272,30 @@ AddKeyUsage (void *extHandle) PRBool yesNoAns; while (1) { - fprintf(stdout, "%-25s 0 - Digital Signature\n", ""); - fprintf(stdout, "%-25s 1 - Non-repudiation\n", ""); - fprintf(stdout, "%-25s 2 - Key encipherment\n", ""); - fprintf(stdout, "%-25s 3 - Data encipherment\n", ""); - fprintf(stdout, "%-25s 4 - Key agreement\n", ""); - fprintf(stdout, "%-25s 5 - Cert signing key\n", ""); - fprintf(stdout, "%-25s 6 - CRL signing key\n", ""); - fprintf(stdout, "%-25s Other to finish\n", ""); - if (Gets_s (buffer, sizeof(buffer))) { - value = PORT_Atoi (buffer); - if (value < 0 || value > 6) - break; - if (value == 0) { - /* Checking that zero value of variable 'value' - * corresponds to '0' input made by user */ - char *chPtr = strchr(buffer, '0'); - if (chPtr == NULL) { - continue; - } - } - keyUsage |= (0x80 >> value); + if (PrintChoicesAndGetAnswer( + "\t\t0 - Dcigital Signature\n" + "\t\t1 - Non-repudiation\n" + "\t\t2 - Key encipherment\n" + "\t\t3 - Data encipherment\n" + "\t\t4 - Key agreement\n" + "\t\t5 - Cert signing key\n" + "\t\t6 - CRL signing key\n" + "\t\tOther to finish\n", + buffer, sizeof(buffer)) == SECFailure) { + return SECFailure; } - else {/* gets() returns NULL on EOF or error */ + value = PORT_Atoi (buffer); + if (value < 0 || value > 6) break; + if (value == 0) { + /* Checking that zero value of variable 'value' + * corresponds to '0' input made by user */ + char *chPtr = strchr(buffer, '0'); + if (chPtr == NULL) { + continue; + } } + keyUsage |= (0x80 >> value); } bitStringValue.data = &keyUsage; @@ -309,12 +320,12 @@ CreateOidSequence(void) goto loser; } - rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence)); + rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence); if( (CERTOidSequence *)NULL == rv ) { goto loser; } - rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *)); + rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *); if( (SECItem **)NULL == rv->oids ) { goto loser; } @@ -359,8 +370,7 @@ AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag) { PRUint32 i; - oids = (SECItem **)PORT_ArenaZAlloc(os->arena, - sizeof(SECItem *) * (count+2)); + oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2); if( (SECItem **)NULL == oids ) { return SECFailure; } @@ -392,7 +402,7 @@ EncodeOidSequence(CERTOidSequence *os) { SECItem *rv; - rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem)); + rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem); if( (SECItem *)NULL == rv ) { goto loser; } @@ -423,19 +433,17 @@ AddExtKeyUsage (void *extHandle) } while (1) { - fprintf(stdout, "%-25s 0 - Server Auth\n", ""); - fprintf(stdout, "%-25s 1 - Client Auth\n", ""); - fprintf(stdout, "%-25s 2 - Code Signing\n", ""); - fprintf(stdout, "%-25s 3 - Email Protection\n", ""); - fprintf(stdout, "%-25s 4 - Timestamp\n", ""); - fprintf(stdout, "%-25s 5 - OCSP Responder\n", ""); - fprintf(stdout, "%-25s 6 - Step-up\n", ""); - fprintf(stdout, "%-25s Other to finish\n", ""); - - if (Gets_s(buffer, sizeof(buffer)) == NULL) { - PORT_SetError(SEC_ERROR_INPUT_LEN); - rv = SECFailure; - goto loser; + if (PrintChoicesAndGetAnswer( + "\t\t0 - Server Auth\n" + "\t\t1 - Client Auth\n" + "\t\t2 - Code Signing\n" + "\t\t3 - Email Protection\n" + "\t\t4 - Timestamp\n" + "\t\t5 - OCSP Responder\n" + "\t\t6 - Step-up\n" + "\t\tOther to finish\n", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK(SECFailure); } value = PORT_Atoi(buffer); @@ -500,17 +508,17 @@ AddNscpCertType (void *extHandle) PRBool yesNoAns; while (1) { - fprintf(stdout, "%-25s 0 - SSL Client\n", ""); - fprintf(stdout, "%-25s 1 - SSL Server\n", ""); - fprintf(stdout, "%-25s 2 - S/MIME\n", ""); - fprintf(stdout, "%-25s 3 - Object Signing\n", ""); - fprintf(stdout, "%-25s 4 - Reserved for future use\n", ""); - fprintf(stdout, "%-25s 5 - SSL CA\n", ""); - fprintf(stdout, "%-25s 6 - S/MIME CA\n", ""); - fprintf(stdout, "%-25s 7 - Object Signing CA\n", ""); - fprintf(stdout, "%-25s Other to finish\n", ""); - if (Gets_s (buffer, sizeof(buffer)) == NULL) { - PORT_SetError(SEC_ERROR_INPUT_LEN); + if (PrintChoicesAndGetAnswer( + "\t\t0 - SSL Client\n" + "\t\t1 - SSL Server\n" + "\t\t2 - S/MIME\n" + "\t\t3 - Object Signing\n" + "\t\t4 - Reserved for future use\n" + "\t\t5 - SSL CA\n" + "\t\t6 - S/MIME CA\n" + "\t\t7 - Object Signing CA\n" + "\t\tOther to finish\n", + buffer, sizeof(buffer)) == SECFailure) { return SECFailure; } value = PORT_Atoi (buffer); @@ -627,35 +635,32 @@ static SECStatus AddBasicConstraint(void *extHandle) { CERTBasicConstraints basicConstraint; - SECItem encodedValue; SECStatus rv; char buffer[10]; PRBool yesNoAns; - encodedValue.data = NULL; - encodedValue.len = 0; do { basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT; basicConstraint.isCA = GetYesNo ("Is this a CA certificate [y/N]?"); buffer[0] = '\0'; - puts ("Enter the path length constraint, enter to skip " - "[<0 for unlimited path]:"); - Gets_s (buffer, sizeof(buffer)); + if (PrintChoicesAndGetAnswer("Enter the path length constraint, " + "enter to skip [<0 for unlimited path]:", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK(SECFailure); + } if (PORT_Strlen (buffer) > 0) basicConstraint.pathLenConstraint = PORT_Atoi (buffer); - rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint, - &encodedValue); - if (rv) - return (rv); - yesNoAns = GetYesNo ("Is this a critical extension [y/N]?"); - rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS, - &encodedValue, yesNoAns, PR_TRUE); + rv = SECU_EncodeAndAddExtensionValue(NULL, extHandle, + &basicConstraint, yesNoAns, + SEC_OID_X509_BASIC_CONSTRAINTS, + (EXTEN_EXT_VALUE_ENCODER) + CERT_EncodeBasicConstraintValue); } while (0); - PORT_Free (encodedValue.data); + return (rv); } @@ -677,7 +682,7 @@ AddAuthKeyID (void *extHandle) if (GetYesNo ("Enter value for the authKeyID extension [y/N]?") == 0) break; - authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID)); + authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID); if (authKeyID == NULL) { GEN_BREAK (SECFailure); } @@ -728,19 +733,19 @@ AddCrlDistPoint(void *extHandle) do { current = NULL; - current = PORT_ArenaZAlloc (arena, sizeof (*current)); + current = PORT_ArenaZNew(arena, CRLDistributionPoint); if (current == NULL) { GEN_BREAK (SECFailure); } /* Get the distributionPointName fields - this field is optional */ - puts ("Enter the type of the distribution point name:\n"); - puts ("\t1 - Full Name\n\t2 - Relative Name\n\tAny other " - "number to finish\n\t\tChoice: "); - if (Gets_s (buffer, sizeof(buffer)) == NULL) { - PORT_SetError(SEC_ERROR_INPUT_LEN); - GEN_BREAK (SECFailure); - } + if (PrintChoicesAndGetAnswer( + "Enter the type of the distribution point name:\n" + "\t1 - Full Name\n\t2 - Relative Name\n\tAny other " + "number to finish\n\t\tChoice: ", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK (SECFailure); + } intValue = PORT_Atoi (buffer); switch (intValue) { case generalName: @@ -774,16 +779,15 @@ AddCrlDistPoint(void *extHandle) break; /* Get the reason flags */ - puts ("\nSelect one of the following for the reason flags\n"); - puts ("\t0 - unused\n\t1 - keyCompromise\n\t2 - caCompromise\n" - "\t3 - affiliationChanged\n"); - puts ("\t4 - superseded\n\t5 - cessationOfOperation\n" - "\t6 - certificateHold\n"); - puts ("\tAny other number to finish\t\tChoice: "); - - if (Gets_s (buffer, sizeof(buffer)) == NULL) { - PORT_SetError(SEC_ERROR_INPUT_LEN); - GEN_BREAK (SECFailure); + if (PrintChoicesAndGetAnswer( + "\nSelect one of the following for the reason flags\n" + "\t0 - unused\n\t1 - keyCompromise\n" + "\t2 - caCompromise\n\t3 - affiliationChanged\n" + "\t4 - superseded\n\t5 - cessationOfOperation\n" + "\t6 - certificateHold\n" + "\tAny other number to finish\t\tChoice: ", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK(SECFailure); } intValue = PORT_Atoi (buffer); if (intValue == 0) { @@ -808,12 +812,12 @@ AddCrlDistPoint(void *extHandle) break; if (crlDistPoints == NULL) { - crlDistPoints = PORT_ArenaZAlloc (arena, sizeof (*crlDistPoints)); + crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints); if (crlDistPoints == NULL) { GEN_BREAK (SECFailure); } } - + crlDistPoints->distPoints = PORT_ArenaGrow (arena, crlDistPoints->distPoints, sizeof (*crlDistPoints->distPoints) * count, @@ -826,7 +830,7 @@ AddCrlDistPoint(void *extHandle) ++count; if (GetYesNo ("Enter more value for the CRL distribution " "point extension [y/N]") == 0) { - /* Add null to the end of the crlDistPoints to mark end of data */ + /* Add null to the end to mark end of data */ crlDistPoints->distPoints = PORT_ArenaGrow(arena, crlDistPoints->distPoints, sizeof (*crlDistPoints->distPoints) * count, @@ -852,54 +856,723 @@ AddCrlDistPoint(void *extHandle) return (rv); } + + +static SECStatus +AddPolicyConstraints(void *extHandle) +{ + CERTCertificatePolicyConstraints *policyConstr; + PRArenaPool *arena = NULL; + SECStatus rv = SECSuccess; + SECItem *item, *dummy; + char buffer[512]; + int value; + PRBool yesNoAns; + PRBool skipExt = PR_TRUE; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( !arena ) { + SECU_PrintError(progName, "out of memory"); + return SECFailure; + } + + policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints); + if (policyConstr == NULL) { + SECU_PrintError(progName, "out of memory"); + goto loser; + } + + if (PrintChoicesAndGetAnswer("Enter explicit policy value or " + "Enter to omit", + buffer, sizeof(buffer)) == SECFailure) { + goto loser; + } + + if (PORT_Strlen(buffer)) { + item = &policyConstr->explicitPolicySkipCerts; + value = PORT_Atoi(buffer); + dummy = SEC_ASN1EncodeInteger(arena, item, value); + if (!dummy) { + goto loser; + } + skipExt = PR_FALSE; + } + + if (PrintChoicesAndGetAnswer("Enter inhibit mapping value or " + "Enter to omit", + buffer, sizeof(buffer)) == SECFailure) { + goto loser; + } + + if (PORT_Strlen(buffer)) { + item = &policyConstr->inhibitMappingSkipCerts; + value = PORT_Atoi(buffer); + dummy = SEC_ASN1EncodeInteger(arena, item, value); + if (!dummy) { + goto loser; + } + skipExt = PR_FALSE; + } + + + if (!skipExt) { + + yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); + + rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr, + yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS, + (EXTEN_EXT_VALUE_ENCODER) + CERT_EncodePolicyConstraintsExtension); + } + +loser: + if (arena) { + PORT_FreeArena (arena, PR_FALSE); + } + return (rv); +} + + +static SECStatus +AddInhibitAnyPolicy(void *extHandle) +{ + CERTCertificateInhibitAny certInhibitAny; + PRArenaPool *arena = NULL; + SECStatus rv = SECSuccess; + SECItem *item, *dummy; + char buffer[10]; + int value; + PRBool yesNoAns; + + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( !arena ) { + SECU_PrintError(progName, "out of memory"); + return SECFailure; + } + + if (PrintChoicesAndGetAnswer("Enter the number of certs in the path " + "permited to use anyPolicy.\n" + "Enter for 0", + buffer, sizeof(buffer)) == SECFailure) { + goto loser; + } + + item = &certInhibitAny.inhibitAnySkipCerts; + value = PORT_Atoi(buffer); + dummy = SEC_ASN1EncodeInteger(arena, item, value); + if (!dummy) { + goto loser; + } + + yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); + + rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny, + yesNoAns, + SEC_OID_X509_INHIBIT_ANY_POLICY, + (EXTEN_EXT_VALUE_ENCODER) + CERT_EncodeInhibitAnyExtension); +loser: + if (arena) { + PORT_FreeArena (arena, PR_FALSE); + } + return (rv); +} + + +static SECStatus +AddPolicyMappings(void *extHandle) +{ + CERTPolicyMap **policyMapArr = NULL; + CERTPolicyMap *current; + PRArenaPool *arena = NULL; + SECStatus rv = SECSuccess; + int count = 0; + char buffer[512]; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( !arena ) { + SECU_PrintError(progName, "out of memory"); + return SECFailure; + } + + do { + if (PrintChoicesAndGetAnswer("Enter an Object Identifier for Issuer " + "Domain Policy", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK (SECFailure); + } + + current = PORT_ArenaZNew(arena, CERTPolicyMap); + if (current == NULL) { + GEN_BREAK(SECFailure); + } + + rv = SEC_StringToOID(arena, ¤t->issuerDomainPolicy, buffer, 0); + if (rv == SECFailure) { + GEN_BREAK(SECFailure); + } + + if (PrintChoicesAndGetAnswer("Enter an Object Identifier for " + "Subject Domain Policy", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK (SECFailure); + } + + rv = SEC_StringToOID(arena, ¤t->subjectDomainPolicy, buffer, 0); + if (rv == SECFailure) { + GEN_BREAK(SECFailure); + } + + if (policyMapArr == NULL) { + policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *); + if (policyMapArr == NULL) { + GEN_BREAK (SECFailure); + } + } + + policyMapArr = PORT_ArenaGrow(arena, policyMapArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + if (policyMapArr == NULL) { + GEN_BREAK (SECFailure); + } + + policyMapArr[count] = current; + ++count; + + if (!GetYesNo("Enter more set to Policy Mappings extension [y/N]")) { + /* Add null to the end to mark end of data */ + policyMapArr = PORT_ArenaGrow (arena, policyMapArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + if (policyMapArr == NULL) { + GEN_BREAK (SECFailure); + } + policyMapArr[count] = NULL; + break; + } + + } while (1); + + if (rv == SECSuccess) { + CERTCertificatePolicyMappings mappings; + PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); + + mappings.arena = arena; + mappings.policyMaps = policyMapArr; + rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings, + yesNoAns, SEC_OID_X509_POLICY_MAPPINGS, + (EXTEN_EXT_VALUE_ENCODER) + CERT_EncodePolicyMappingExtension); + } + if (arena) + PORT_FreeArena (arena, PR_FALSE); + return (rv); +} + +enum PoliciQualifierEnum { + cpsPointer = 1, + userNotice = 2, +}; + + +static CERTPolicyQualifier ** +RequestPolicyQualifiers(PRArenaPool *arena, SECItem *policyID) +{ + CERTPolicyQualifier **policyQualifArr = NULL; + CERTPolicyQualifier *current; + SECStatus rv = SECSuccess; + int count = 0; + char buffer[512]; + void *mark; + SECOidData *oid = NULL; + int intValue = 0; + int inCount = 0; + + PORT_Assert(arena); + mark = PORT_ArenaMark(arena); + do { + current = PORT_ArenaZNew(arena, CERTPolicyQualifier); + if (current == NULL) { + GEN_BREAK(SECFailure); + } + + /* Get the accessMethod fields */ + SECU_PrintObjectID(stdout, policyID, + "Choose the type of qualifier for policy" , 0); + + if (PrintChoicesAndGetAnswer( + "\t1 - CPS Pointer qualifier\n" + "\t2 - User notice qualifier\n" + "\tAny other number to finish\n" + "\t\tChoice: ", buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK (SECFailure); + } + intValue = PORT_Atoi(buffer); + switch (intValue) { + case cpsPointer: { + SECItem input; + oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CPS_POINTER_QUALIFIER); + if (PrintChoicesAndGetAnswer("Enter CPS Pointer uri: ", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK (SECFailure); + } + input.len = PORT_Strlen(buffer); + input.data = (void*)PORT_ArenaStrdup(arena, buffer); + if (input.data == NULL || + SEC_ASN1EncodeItem(arena, ¤t->qualifierValue, &input, + SEC_IA5StringTemplate) == NULL) { + GEN_BREAK (SECFailure); + } + break; + } + case userNotice: { + SECItem input; + SECItem **noticeNumArr; + CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice); + if (!notice) { + GEN_BREAK(SECFailure); + } + + oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER); + + if (GetYesNo("\t Enter user notice reference? [y/N]")) { + + if (PrintChoicesAndGetAnswer("Enter user organization: ", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK (SECFailure); + } + + notice->noticeReference.organization.type = siAsciiString; + notice->noticeReference.organization.len = + PORT_Strlen(buffer); + notice->noticeReference.organization.data = + (void*)PORT_ArenaStrdup(arena, buffer); + + + noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2); + if (!noticeNumArr) { + GEN_BREAK (SECFailure); + } + + do { + SECItem *noticeNum; + + noticeNum = PORT_ArenaZNew(arena, SECItem); + + if (noticeNum == NULL || + PrintChoicesAndGetAnswer("Enter notice number of any key" + " to continue:", buffer, sizeof(buffer)) + == SECFailure) { + GEN_BREAK (SECFailure); + } + + intValue = PORT_Atoi(buffer); + if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) { + GEN_BREAK (SECFailure); + } + noticeNumArr[inCount++] = noticeNum; + noticeNumArr[inCount] = NULL; + + if (GetYesNo("Enter one more user notice number[y/N]")) { + noticeNumArr = PORT_ArenaGrow(arena, noticeNumArr, + sizeof (current) * inCount, + sizeof (current) *(inCount + 1)); + if (noticeNumArr == NULL) { + GEN_BREAK (SECFailure); + } + } else { + break; + } + } while (1); + if (rv == SECFailure) { + GEN_BREAK(SECFailure); + } + notice->noticeReference.noticeNumbers = noticeNumArr; + rv = CERT_EncodeNoticeReference(arena, ¬ice->noticeReference, + ¬ice->derNoticeReference); + if (rv == SECFailure) { + GEN_BREAK(SECFailure); + } + } + if (GetYesNo("\t Enter user notice text? [y/N]")) { + /* Getting only 200 bytes - RFC limitation */ + if (PrintChoicesAndGetAnswer( + "\t", buffer, 200) == SECFailure) { + GEN_BREAK (SECFailure); + } + notice->displayText.type = siAsciiString; + notice->displayText.len = PORT_Strlen(buffer); + notice->displayText.data = (void*)PORT_ArenaStrdup(arena, buffer); + if (notice->displayText.data == NULL) { + GEN_BREAK(SECFailure); + } + } + + rv = CERT_EncodeUserNotice(arena, notice, ¤t->qualifierValue); + if (rv == SECFailure) { + GEN_BREAK(SECFailure); + } + + break; + } + } + if (rv == SECFailure || oid == NULL || + SECITEM_CopyItem(arena, ¤t->qualifierID, &oid->oid) == SECFailure) { + GEN_BREAK (SECFailure); + } + + if (!policyQualifArr) { + policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *); + } else { + policyQualifArr = PORT_ArenaGrow (arena, policyQualifArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + } + if (policyQualifArr == NULL) { + GEN_BREAK (SECFailure); + } + + policyQualifArr[count] = current; + ++count; + + if (!GetYesNo ("Enter more policy qualifiers for the policy [y/N]")) { + /* Add null to the end to mark end of data */ + policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + if (policyQualifArr == NULL) { + GEN_BREAK (SECFailure); + } + policyQualifArr[count] = NULL; + break; + } + + } while (1); + + if (rv != SECSuccess) { + PORT_ArenaRelease (arena, mark); + policyQualifArr = NULL; + } + return (policyQualifArr); +} + +static SECStatus +AddCertPolices(void *extHandle) +{ + CERTPolicyInfo **certPoliciesArr = NULL; + CERTPolicyInfo *current; + PRArenaPool *arena = NULL; + SECStatus rv = SECSuccess; + int count = 0; + char buffer[512]; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( !arena ) { + SECU_PrintError(progName, "out of memory"); + return SECFailure; + } + + do { + current = PORT_ArenaZNew(arena, CERTPolicyInfo); + if (current == NULL) { + GEN_BREAK(SECFailure); + } + + if (PrintChoicesAndGetAnswer("Enter policy ID object identifier" + " or any for AnyPolicy:", + buffer, sizeof(buffer)) == SECFailure) { + GEN_BREAK (SECFailure); + } + rv = SEC_StringToOID(arena, ¤t->policyID, buffer, 0); + if (rv == SECFailure) { + GEN_BREAK(SECFailure); + } + + current->policyQualifiers = + RequestPolicyQualifiers(arena, ¤t->policyID); + + if (!certPoliciesArr) { + certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *); + } else { + certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + } + if (certPoliciesArr == NULL) { + GEN_BREAK (SECFailure); + } + + certPoliciesArr[count] = current; + ++count; + + if (!GetYesNo ("Enter more policy information to the" + " Cert Policy extension [y/N]")) { + /* Add null to the end to mark end of data */ + certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + if (certPoliciesArr == NULL) { + GEN_BREAK (SECFailure); + } + certPoliciesArr[count] = NULL; + break; + } + + } while (1); + + if (rv == SECSuccess) { + CERTCertificatePolicies policies; + PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); + + policies.arena = arena; + policies.policyInfos = certPoliciesArr; + + rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies, + yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES, + (EXTEN_EXT_VALUE_ENCODER) + CERT_EncodeCertPoliciesExtension); + } + if (arena) + PORT_FreeArena(arena, PR_FALSE); + return (rv); +} + +enum AuthInfoAccessTypesEnum { + caIssuers = 1, + ocsp = 2 +}; + +enum SubjInfoAccessTypesEnum { + caRepository = 1, + timeStamping = 2 +}; + +/* Encode and add an AIA or SIA extension */ +static SECStatus +AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert) +{ + CERTAuthInfoAccess **infoAccArr = NULL; + CERTAuthInfoAccess *current; + PRArenaPool *arena = NULL; + SECStatus rv = SECSuccess; + int count = 0; + char buffer[512]; + SECOidData *oid = NULL; + int intValue = 0; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( !arena ) { + SECU_PrintError(progName, "out of memory"); + return SECFailure; + } + + do { + current = NULL; + current = PORT_ArenaZNew(arena, CERTAuthInfoAccess); + if (current == NULL) { + GEN_BREAK(SECFailure); + } + + /* Get the accessMethod fields */ + if (addSIAExt) { + if (isCACert) { + puts("Adding \"CA Repository\" access method type for " + "Subject Information Access extension:\n"); + intValue = caRepository; + } else { + puts("Adding \"Time Stamping Services\" access method type for " + "Subject Information Access extension:\n"); + intValue = timeStamping; + } + } else { + PrintChoicesAndGetAnswer("Enter access method type " + "for Authority Information Access extension:\n" + "\t1 - CA Issuers\n\t2 - OCSP\n\tAny" + "other number to finish\n\tChoice", + buffer, sizeof(buffer)); + intValue = PORT_Atoi(buffer); + } + if (addSIAExt) { + switch (intValue) { + case caRepository: + oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY); + break; + + case timeStamping: + oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING); + break; + } + } else { + switch (intValue) { + case caIssuers: + oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS); + break; + + case ocsp: + oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP); + break; + } + } + if (oid == NULL || + SECITEM_CopyItem(arena, ¤t->method, &oid->oid) == SECFailure) { + GEN_BREAK (SECFailure); + } + + current->location = GetGeneralName(arena); + if (!current->location) { + GEN_BREAK(SECFailure); + } + + if (infoAccArr == NULL) { + infoAccArr = PORT_ArenaZNew(arena, CERTAuthInfoAccess *); + } else { + infoAccArr = PORT_ArenaGrow(arena, infoAccArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + } + if (infoAccArr == NULL) { + GEN_BREAK (SECFailure); + } + + infoAccArr[count] = current; + ++count; + + PR_snprintf(buffer, sizeof(buffer), "Enter more location to the %s" + " Information Access extension [y/N]", + (addSIAExt) ? "Subject" : "Authority"); + + if (GetYesNo (buffer) == 0) { + /* Add null to the end to mark end of data */ + infoAccArr = PORT_ArenaGrow(arena, infoAccArr, + sizeof (current) * count, + sizeof (current) *(count + 1)); + if (infoAccArr == NULL) { + GEN_BREAK (SECFailure); + } + infoAccArr[count] = NULL; + break; + } + + } while (1); + + if (rv == SECSuccess) { + int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS; + + PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); + + if (addSIAExt) { + oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS; + } + rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr, + yesNoAns, oidIdent, + (EXTEN_EXT_VALUE_ENCODER) + CERT_EncodeInfoAccessExtension); + } + if (arena) + PORT_FreeArena(arena, PR_FALSE); + return (rv); +} + SECStatus AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames, - PRBool keyUsage, - PRBool extKeyUsage, - PRBool basicConstraint, - PRBool authKeyID, - PRBool crlDistPoints, - PRBool nscpCertType) + certutilExtnList extList) { SECStatus rv = SECSuccess; + char *errstring = NULL; + do { /* Add key usage extension */ - if (keyUsage) { + if (extList[ext_keyUsage]) { rv = AddKeyUsage(extHandle); - if (rv) + if (rv) { + errstring = "KeyUsage"; break; + } } /* Add extended key usage extension */ - if (extKeyUsage) { + if (extList[ext_extKeyUsage]) { rv = AddExtKeyUsage(extHandle); - if (rv) + if (rv) { + errstring = "ExtendedKeyUsage"; break; + } } /* Add basic constraint extension */ - if (basicConstraint) { + if (extList[ext_basicConstraint]) { rv = AddBasicConstraint(extHandle); - if (rv) + if (rv) { + errstring = "BasicConstraint"; break; + } } - if (authKeyID) { - rv = AddAuthKeyID (extHandle); - if (rv) + if (extList[ext_authorityKeyID]) { + rv = AddAuthKeyID(extHandle); + if (rv) { + errstring = "AuthorityKeyID"; break; + } } - if (crlDistPoints) { - rv = AddCrlDistPoint (extHandle); - if (rv) + if (extList[ext_CRLDistPts]) { + rv = AddCrlDistPoint(extHandle); + if (rv) { + errstring = "CRLDistPoints"; break; + } } - if (nscpCertType) { + if (extList[ext_NSCertType]) { rv = AddNscpCertType(extHandle); - if (rv) + if (rv) { + errstring = "NSCertType"; + break; + } + } + + if (extList[ext_authInfoAcc] || extList[ext_subjInfoAcc]) { + rv = AddInfoAccess(extHandle, extList[ext_authInfoAcc], + extList[ext_basicConstraint]); + if (rv) { + errstring = "InformationAccess"; break; + } + } + + if (extList[ext_certPolicies]) { + rv = AddCertPolices(extHandle); + if (rv) { + errstring = "Policies"; + break; + } + } + + if (extList[ext_policyMappings]) { + rv = AddPolicyMappings(extHandle); + if (rv) { + errstring = "PolicyMappings"; + break; + } + } + + if (extList[ext_policyConstr]) { + rv = AddPolicyConstraints(extHandle); + if (rv) { + errstring = "PolicyConstraints"; + break; + } + } + + if (extList[ext_inhibitAnyPolicy]) { + rv = AddInhibitAnyPolicy(extHandle); + if (rv) { + errstring = "InhibitAnyPolicy"; + break; + } } if (emailAddrs || dnsNames) { @@ -918,15 +1591,23 @@ AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames, rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames); if (rv == SECSuccess) { - rv = CERT_EncodeAltNameExtension(arena, namelist, &item); - if (rv == SECSuccess) { + rv = CERT_EncodeAltNameExtension(arena, namelist, &item); + if (rv == SECSuccess) { rv = CERT_AddExtension(extHandle, - SEC_OID_X509_SUBJECT_ALT_NAME, - &item, PR_FALSE, PR_TRUE); - } + SEC_OID_X509_SUBJECT_ALT_NAME, + &item, PR_FALSE, PR_TRUE); + } } - PORT_FreeArena(arena, PR_FALSE); + PORT_FreeArena(arena, PR_FALSE); + if (rv) { + errstring = "SubjectAltName"; + break; + } } } while (0); + + if (rv != SECSuccess) { + SECU_PrintError(progName, "Problem creating %s extension", errstring); + } return rv; } diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index 81ac00f48..614c07fc5 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -68,6 +68,7 @@ #include "secoid.h" #include "certdb.h" #include "nss.h" +#include "certutil.h" #define MIN_KEY_BITS 512 /* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */ @@ -76,22 +77,8 @@ #define GEN_BREAK(e) rv=e; break; - -extern SECKEYPrivateKey *CERTUTIL_GeneratePrivateKey(KeyType keytype, - PK11SlotInfo *slot, - int rsasize, - int publicExponent, - char *noise, - SECKEYPublicKey **pubkeyp, - char *pqgFile, - secuPWData *pwdata); - char *progName; -extern SECStatus -AddExtensions(void *, const char *, const char *, PRBool, PRBool, - PRBool, PRBool, PRBool, PRBool); - static CERTCertificateRequest * GetCertRequest(PRFileDesc *inFile, PRBool ascii) { @@ -239,12 +226,7 @@ static SECStatus CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii, const char *emailAddrs, const char *dnsNames, - PRBool keyUsage, - PRBool extKeyUsage, - PRBool basicConstraint, - PRBool authKeyID, - PRBool crlDistPoints, - PRBool nscpCertType, + certutilExtnList extnList, PRFileDesc *outFile) { CERTSubjectPublicKeyInfo *spki; @@ -282,8 +264,7 @@ CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, PORT_FreeArena (arena, PR_FALSE); return SECFailure; } - if (AddExtensions(extHandle, emailAddrs, dnsNames, keyUsage, extKeyUsage, - basicConstraint, authKeyID, crlDistPoints, nscpCertType) + if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList) != SECSuccess) { PORT_FreeArena (arena, PR_FALSE); return SECFailure; @@ -293,7 +274,7 @@ CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, /* Der encode the request */ encoding = SEC_ASN1EncodeItem(arena, NULL, cr, - SEC_ASN1_GET(CERT_CertificateRequestTemplate)); + SEC_ASN1_GET(CERT_CertificateRequestTemplate)); if (encoding == NULL) { SECU_PrintError(progName, "der encoding of request failed"); return SECFailure; @@ -1406,12 +1387,7 @@ CreateCert( const char *dnsNames, PRBool ascii, PRBool selfsign, - PRBool keyUsage, - PRBool extKeyUsage, - PRBool basicConstraint, - PRBool authKeyID, - PRBool crlDistPoints, - PRBool nscpCertType) + certutilExtnList extnList) { void * extHandle; SECItem * certDER; @@ -1447,8 +1423,7 @@ CreateCert( GEN_BREAK (SECFailure) } - rv = AddExtensions(extHandle, emailAddrs, dnsNames, keyUsage, extKeyUsage, - basicConstraint, authKeyID, crlDistPoints, nscpCertType); + rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList); if (rv != SECSuccess) { GEN_BREAK (SECFailure) } @@ -1642,6 +1617,8 @@ static const secuCommand certutil = { certutil_options }; +static certutilExtnList certutil_extns; + static int certutil_main(int argc, char **argv, PRBool initialize) { @@ -2196,6 +2173,26 @@ certutil_main(int argc, char **argv, PRBool initialize) } } + /* If we need a list of extensions convert the flags into list format */ + if (certutil.commands[cmd_CertReq].activated || + certutil.commands[cmd_CreateAndAddCert].activated || + certutil.commands[cmd_CreateNewCert].activated) { + certutil_extns[ext_keyUsage] = + certutil.options[opt_AddKeyUsageExt].activated; + certutil_extns[ext_basicConstraint] = + certutil.options[opt_AddBasicConstraintExt].activated; + certutil_extns[ext_authorityKeyID] = + certutil.options[opt_AddAuthorityKeyIDExt].activated; + certutil_extns[ext_CRLDistPts] = + certutil.options[opt_AddCRLDistPtsExt].activated; + certutil_extns[ext_NSCertType] = + certutil.options[opt_AddNSCertTypeExt].activated; + certutil_extns[ext_extKeyUsage] = + certutil.options[opt_AddExtKeyUsageExt].activated; + /* We can't generate the rest of the extensions yet. When long form + * options are available this code block will be extended + */ + } /* * Certificate request */ @@ -2207,12 +2204,7 @@ certutil_main(int argc, char **argv, PRBool initialize) certutil.options[opt_ASCIIForIO].activated, certutil.options[opt_ExtendedEmailAddrs].arg, certutil.options[opt_ExtendedDNSNames].arg, - certutil.options[opt_AddKeyUsageExt].activated, - certutil.options[opt_AddExtKeyUsageExt].activated, - certutil.options[opt_AddBasicConstraintExt].activated, - certutil.options[opt_AddAuthorityKeyIDExt].activated, - certutil.options[opt_AddCRLDistPtsExt].activated, - certutil.options[opt_AddNSCertTypeExt].activated, + certutil_extns, outFile ? outFile : PR_STDOUT); if (rv) goto shutdown; @@ -2228,17 +2220,13 @@ certutil_main(int argc, char **argv, PRBool initialize) * and output the cert to another file. */ if (certutil.commands[cmd_CreateAndAddCert].activated) { + static certutilExtnList nullextnlist = {PR_FALSE}; rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject, certutil.options[opt_PhoneNumber].arg, certutil.options[opt_ASCIIForIO].activated, NULL, NULL, - PR_FALSE, - PR_FALSE, - PR_FALSE, - PR_FALSE, - PR_FALSE, - PR_FALSE, + nullextnlist, outFile ? outFile : PR_STDOUT); if (rv) goto shutdown; @@ -2271,12 +2259,7 @@ certutil_main(int argc, char **argv, PRBool initialize) certutil.options[opt_ExtendedDNSNames].arg, certutil.options[opt_ASCIIForIO].activated, certutil.options[opt_SelfSign].activated, - certutil.options[opt_AddKeyUsageExt].activated, - certutil.options[opt_AddExtKeyUsageExt].activated, - certutil.options[opt_AddBasicConstraintExt].activated, - certutil.options[opt_AddAuthorityKeyIDExt].activated, - certutil.options[opt_AddCRLDistPtsExt].activated, - certutil.options[opt_AddNSCertTypeExt].activated); + certutil_extns); if (rv) goto shutdown; } |