diff options
Diffstat (limited to 'security/nss/cmd/crmf-cgi/crmfcgi.c')
-rw-r--r-- | security/nss/cmd/crmf-cgi/crmfcgi.c | 1090 |
1 files changed, 0 insertions, 1090 deletions
diff --git a/security/nss/cmd/crmf-cgi/crmfcgi.c b/security/nss/cmd/crmf-cgi/crmfcgi.c deleted file mode 100644 index 955f5201c..000000000 --- a/security/nss/cmd/crmf-cgi/crmfcgi.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "seccomon.h" -#include "nss.h" -#include "key.h" -#include "cert.h" -#include "pk11func.h" -#include "secmod.h" -#include "cmmf.h" -#include "crmf.h" -#include "base64.h" -#include "secasn1.h" -#include "cryptohi.h" -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#define DEFAULT_ALLOC_SIZE 200 -#define DEFAULT_CGI_VARS 20 - -typedef struct CGIVariableStr { - char *name; - char *value; -} CGIVariable; - -typedef struct CGIVarTableStr { - CGIVariable **variables; - int numVars; - int numAlloc; -} CGIVarTable; - -typedef struct CertResponseInfoStr { - CERTCertificate *cert; - long certReqID; -} CertResponseInfo; - -typedef struct ChallengeCreationInfoStr { - long random; - SECKEYPublicKey *pubKey; -} ChallengeCreationInfo; - -char *missingVar = NULL; - -/* - * Error values. - */ -typedef enum { - NO_ERROR = 0, - NSS_INIT_FAILED, - AUTH_FAILED, - REQ_CGI_VAR_NOT_PRESENT, - CRMF_REQ_NOT_PRESENT, - BAD_ASCII_FOR_REQ, - CGI_VAR_MISSING, - COULD_NOT_FIND_CA, - COULD_NOT_DECODE_REQS, - OUT_OF_MEMORY, - ERROR_RETRIEVING_REQUEST_MSG, - ERROR_RETRIEVING_CERT_REQUEST, - ERROR_RETRIEVING_SUBJECT_FROM_REQ, - ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ, - ERROR_CREATING_NEW_CERTIFICATE, - COULD_NOT_START_EXTENSIONS, - ERROR_RETRIEVING_EXT_FROM_REQ, - ERROR_ADDING_EXT_TO_CERT, - ERROR_ENDING_EXTENSIONS, - COULD_NOT_FIND_ISSUER_PRIVATE_KEY, - UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER, - ERROR_SETTING_SIGN_ALG, - ERROR_ENCODING_NEW_CERT, - ERROR_SIGNING_NEW_CERT, - ERROR_CREATING_CERT_REP_CONTENT, - ERROR_CREATING_SINGLE_CERT_RESPONSE, - ERROR_SETTING_CERT_RESPONSES, - ERROR_CREATING_CA_LIST, - ERROR_ADDING_ISSUER_TO_CA_LIST, - ERROR_ENCODING_CERT_REP_CONTENT, - NO_POP_FOR_REQUEST, - UNSUPPORTED_POP, - ERROR_RETRIEVING_POP_SIGN_KEY, - ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY, - ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY, - DO_CHALLENGE_RESPONSE, - ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT, - ERROR_ENCODING_CERT_REQ_FOR_POP, - ERROR_VERIFYING_SIGNATURE_POP, - ERROR_RETRIEVING_PUB_KEY_FOR_CHALL, - ERROR_CREATING_EMPTY_CHAL_CONTENT, - ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER, - ERROR_SETTING_CHALLENGE, - ERROR_ENCODING_CHALL, - ERROR_CONVERTING_CHALL_TO_BASE64, - ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN, - ERROR_CREATING_KEY_RESP_FROM_DER, - ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE, - ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED, - ERROR_GETTING_KEY_ENCIPHERMENT, - ERROR_NO_POP_FOR_PRIVKEY, - ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE -} ErrorCode; - -const char * -CGITableFindValue(CGIVarTable *varTable, const char *key); - -void -spitOutHeaders(void) -{ - printf("Content-type: text/html\n\n"); -} - -void -dumpRequest(CGIVarTable *varTable) -{ - int i; - CGIVariable *var; - - printf ("<table border=1 cellpadding=1 cellspacing=1 width=\"100%%\">\n"); - printf ("<tr><td><b><center>Variable Name<center></b></td>" - "<td><b><center>Value</center></b></td></tr>\n"); - for (i=0; i<varTable->numVars; i++) { - var = varTable->variables[i]; - printf ("<tr><td><pre>%s</pre></td><td><pre>%s</pre></td></tr>\n", - var->name, var->value); - } - printf("</table>\n"); -} - -void -echo_request(CGIVarTable *varTable) -{ - spitOutHeaders(); - printf("<html><head><title>CGI Echo Page</title></head>\n" - "<body><h1>Got the following request</h1>\n"); - dumpRequest(varTable); - printf("</body></html>"); -} - -void -processVariable(CGIVariable *var) -{ - char *plusSign, *percentSign; - - /*First look for all of the '+' and convert them to spaces */ - plusSign = var->value; - while ((plusSign=strchr(plusSign, '+')) != NULL) { - *plusSign = ' '; - } - percentSign = var->value; - while ((percentSign=strchr(percentSign, '%')) != NULL) { - char string[3]; - int value; - - string[0] = percentSign[1]; - string[1] = percentSign[2]; - string[2] = '\0'; - - sscanf(string,"%x", &value); - *percentSign = (char)value; - memmove(&percentSign[1], &percentSign[3], 1+strlen(&percentSign[3])); - } -} - -char * -parseNextVariable(CGIVarTable *varTable, char *form_output) -{ - char *ampersand, *equal; - CGIVariable *var; - - if (varTable->numVars == varTable->numAlloc) { - CGIVariable **newArr = realloc(varTable->variables, - (varTable->numAlloc + DEFAULT_CGI_VARS)*sizeof(CGIVariable*)); - if (newArr == NULL) { - return NULL; - } - varTable->variables = newArr; - varTable->numAlloc += DEFAULT_CGI_VARS; - } - equal = strchr(form_output, '='); - if (equal == NULL) { - return NULL; - } - ampersand = strchr(equal, '&'); - if (ampersand == NULL) { - return NULL; - } - equal[0] = '\0'; - if (ampersand != NULL) { - ampersand[0] = '\0'; - } - var = malloc(sizeof(CGIVariable)); - var->name = form_output; - var->value = &equal[1]; - varTable->variables[varTable->numVars] = var; - varTable->numVars++; - processVariable(var); - return (ampersand != NULL) ? &ersand[1] : NULL; -} - -void -ParseInputVariables(CGIVarTable *varTable, char *form_output) -{ - varTable->variables = malloc(sizeof(CGIVariable*)*DEFAULT_CGI_VARS); - varTable->numVars = 0; - varTable->numAlloc = DEFAULT_CGI_VARS; - while (form_output && form_output[0] != '\0') { - form_output = parseNextVariable(varTable, form_output); - } -} - -const char * -CGITableFindValue(CGIVarTable *varTable, const char *key) -{ - const char *retVal = NULL; - int i; - - for (i=0; i<varTable->numVars; i++) { - if (strcmp(varTable->variables[i]->name, key) == 0) { - retVal = varTable->variables[i]->value; - break; - } - } - return retVal; -} - -char* -passwordCallback(PK11SlotInfo *slot, PRBool retry, void *arg) -{ - const char *passwd; - if (retry) { - return NULL; - } - passwd = CGITableFindValue((CGIVarTable*)arg, "dbPassword"); - if (passwd == NULL) { - return NULL; - } - return PORT_Strdup(passwd); -} - -ErrorCode -initNSS(CGIVarTable *varTable) -{ - const char *nssDir; - PK11SlotInfo *keySlot; - SECStatus rv; - - nssDir = CGITableFindValue(varTable,"NSSDirectory"); - if (nssDir == NULL) { - missingVar = "NSSDirectory"; - return REQ_CGI_VAR_NOT_PRESENT; - } - rv = NSS_Init(nssDir); - if (rv != SECSuccess) { - return NSS_INIT_FAILED; - } - PK11_SetPasswordFunc(passwordCallback); - keySlot = PK11_GetInternalKeySlot(); - rv = PK11_Authenticate(keySlot, PR_FALSE, varTable); - PK11_FreeSlot(keySlot); - if (rv != SECSuccess) { - return AUTH_FAILED; - } - return NO_ERROR; -} - -void -dumpErrorMessage(ErrorCode errNum) -{ - spitOutHeaders(); - printf("<html><head><title>Error</title></head><body><h1>Error processing " - "data</h1> Received the error %d<p>", errNum); - if (errNum == REQ_CGI_VAR_NOT_PRESENT) { - printf ("The missing variable is %s.", missingVar); - } - printf ("<i>More useful information here in the future.</i></body></html>"); -} - -ErrorCode -initOldCertReq(CERTCertificateRequest *oldCertReq, - CERTName *subject, CERTSubjectPublicKeyInfo *spki) -{ - PRArenaPool *poolp; - - poolp = oldCertReq->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - SEC_ASN1EncodeInteger(poolp, &oldCertReq->version, - SEC_CERTIFICATE_VERSION_3); - CERT_CopyName(poolp, &oldCertReq->subject, subject); - SECKEY_CopySubjectPublicKeyInfo(poolp, &oldCertReq->subjectPublicKeyInfo, - spki); - oldCertReq->attributes = NULL; - return NO_ERROR; -} - -ErrorCode -addExtensions(CERTCertificate *newCert, CRMFCertRequest *certReq) -{ - int numExtensions, i; - void *extHandle; - ErrorCode rv = NO_ERROR; - CRMFCertExtension *ext; - SECStatus srv; - - numExtensions = CRMF_CertRequestGetNumberOfExtensions(certReq); - if (numExtensions == 0) { - /* No extensions to add */ - return NO_ERROR; - } - extHandle = CERT_StartCertExtensions(newCert); - if (extHandle == NULL) { - rv = COULD_NOT_START_EXTENSIONS; - goto loser; - } - for (i=0; i<numExtensions; i++) { - ext = CRMF_CertRequestGetExtensionAtIndex(certReq, i); - if (ext == NULL) { - rv = ERROR_RETRIEVING_EXT_FROM_REQ; - } - srv = CERT_AddExtension(extHandle, CRMF_CertExtensionGetOidTag(ext), - CRMF_CertExtensionGetValue(ext), - CRMF_CertExtensionGetIsCritical(ext), PR_FALSE); - if (srv != SECSuccess) { - rv = ERROR_ADDING_EXT_TO_CERT; - } - } - srv = CERT_FinishExtensions(extHandle); - if (srv != SECSuccess) { - rv = ERROR_ENDING_EXTENSIONS; - goto loser; - } - return NO_ERROR; - loser: - return rv; -} - -void -writeOutItem(const char *filePath, SECItem *der) -{ - PRFileDesc *outfile; - - outfile = PR_Open (filePath, - PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, - 0666); - PR_Write(outfile, der->data, der->len); - PR_Close(outfile); - -} - -ErrorCode -createNewCert(CERTCertificate**issuedCert,CERTCertificateRequest *oldCertReq, - CRMFCertReqMsg *currReq, CRMFCertRequest *certReq, - CERTCertificate *issuerCert, CGIVarTable *varTable) -{ - CERTCertificate *newCert = NULL; - CERTValidity *validity; - PRExplodedTime printableTime; - PRTime now, after; - ErrorCode rv=NO_ERROR; - SECKEYPrivateKey *issuerPrivKey; - SECItem derCert = { 0 }; - SECOidTag signTag; - SECStatus srv; - long version; - - now = PR_Now(); - PR_ExplodeTime(now, PR_GMTParameters, &printableTime); - printableTime.tm_month += 9; - after = PR_ImplodeTime(&printableTime); - validity = CERT_CreateValidity(now, after); - newCert = *issuedCert = - CERT_CreateCertificate(rand(), &(issuerCert->subject), validity, - oldCertReq); - if (newCert == NULL) { - rv = ERROR_CREATING_NEW_CERTIFICATE; - goto loser; - } - rv = addExtensions(newCert, certReq); - if (rv != NO_ERROR) { - goto loser; - } - issuerPrivKey = PK11_FindKeyByAnyCert(issuerCert, varTable); - if (issuerPrivKey == NULL) { - rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY; - } - signTag = SEC_GetSignatureAlgorithmOidTag(issuerPrivatekey->keytype, - SEC_OID_UNKNOWN); - if (signTag == SEC_OID_UNKNOWN) { - rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER; - goto loser; - } - srv = SECOID_SetAlgorithmID(newCert->arena, &newCert->signature, - signTag, 0); - if (srv != SECSuccess) { - rv = ERROR_SETTING_SIGN_ALG; - goto loser; - } - srv = CRMF_CertRequestGetCertTemplateVersion(certReq, &version); - if (srv != SECSuccess) { - /* No version included in the request */ - *(newCert->version.data) = SEC_CERTIFICATE_VERSION_3; - } else { - SECITEM_FreeItem(&newCert->version, PR_FALSE); - SEC_ASN1EncodeInteger(newCert->arena, &newCert->version, version); - } - SEC_ASN1EncodeItem(newCert->arena, &derCert, newCert, - CERT_CertificateTemplate); - if (derCert.data == NULL) { - rv = ERROR_ENCODING_NEW_CERT; - goto loser; - } - srv = SEC_DerSignData(newCert->arena, &(newCert->derCert), derCert.data, - derCert.len, issuerPrivKey, signTag); - if (srv != SECSuccess) { - rv = ERROR_SIGNING_NEW_CERT; - goto loser; - } -#ifdef WRITE_OUT_RESPONSE - writeOutItem("newcert.der", &newCert->derCert); -#endif - return NO_ERROR; - loser: - *issuedCert = NULL; - if (newCert) { - CERT_DestroyCertificate(newCert); - } - return rv; - -} - -void -formatCMMFResponse(char *nickname, char *base64Response) -{ - char *currLine, *nextLine; - - printf("var retVal = crypto.importUserCertificates(\"%s\",\n", nickname); - currLine = base64Response; - while (1) { - nextLine = strchr(currLine, '\n'); - if (nextLine == NULL) { - /* print out the last line here. */ - printf ("\"%s\",\n", currLine); - break; - } - nextLine[0] = '\0'; - printf("\"%s\\n\"+\n", currLine); - currLine = nextLine+1; - } - printf("true);\n" - "if(retVal == '') {\n" - "\tdocument.write(\"<h1>New Certificate Successfully Imported.</h1>\");\n" - "} else {\n" - "\tdocument.write(\"<h2>Unable to import New Certificate</h2>\");\n" - "\tdocument.write(\"crypto.importUserCertificates returned <b>\");\n" - "\tdocument.write(retVal);\n" - "\tdocument.write(\"</b>\");\n" - "}\n"); -} - -void -spitOutCMMFResponse(char *nickname, char *base64Response) -{ - spitOutHeaders(); - printf("<html>\n<head>\n<title>CMMF Resonse Page</title>\n</head>\n\n" - "<body><h1>CMMF Response Page</h1>\n" - "<script language=\"JavaScript\">\n" - "<!--\n"); - formatCMMFResponse(nickname, base64Response); - printf("// -->\n" - "</script>\n</body>\n</html>"); -} - -char* -getNickname(CERTCertificate *cert) -{ - char *nickname; - - if (cert->nickname != NULL) { - return cert->nickname; - } - nickname = CERT_GetCommonName(&cert->subject); - if (nickname != NULL) { - return nickname; - } - return CERT_NameToAscii(&cert->subject); -} - -ErrorCode -createCMMFResponse(CertResponseInfo *issuedCerts, int numCerts, - CERTCertificate *issuerCert, char **base64der) -{ - CMMFCertRepContent *certRepContent=NULL; - ErrorCode rv = NO_ERROR; - CMMFCertResponse **responses, *currResponse; - CERTCertList *caList; - int i; - SECStatus srv; - PRArenaPool *poolp; - SECItem *der; - - certRepContent = CMMF_CreateCertRepContent(); - if (certRepContent == NULL) { - rv = ERROR_CREATING_CERT_REP_CONTENT; - goto loser; - } - responses = PORT_NewArray(CMMFCertResponse*, numCerts); - if (responses == NULL) { - rv = OUT_OF_MEMORY; - goto loser; - } - for (i=0; i<numCerts;i++) { - responses[i] = currResponse = - CMMF_CreateCertResponse(issuedCerts[i].certReqID); - if (currResponse == NULL) { - rv = ERROR_CREATING_SINGLE_CERT_RESPONSE; - goto loser; - } - CMMF_CertResponseSetPKIStatusInfoStatus(currResponse, cmmfGranted); - CMMF_CertResponseSetCertificate(currResponse, issuedCerts[i].cert); - } - srv = CMMF_CertRepContentSetCertResponses(certRepContent, responses, - numCerts); - if (srv != SECSuccess) { - rv = ERROR_SETTING_CERT_RESPONSES; - goto loser; - } - caList = CERT_NewCertList(); - if (caList == NULL) { - rv = ERROR_CREATING_CA_LIST; - goto loser; - } - srv = CERT_AddCertToListTail(caList, issuerCert); - if (srv != SECSuccess) { - rv = ERROR_ADDING_ISSUER_TO_CA_LIST; - goto loser; - } - srv = CMMF_CertRepContentSetCAPubs(certRepContent, caList); - CERT_DestroyCertList(caList); - poolp = PORT_NewArena(1024); - der = SEC_ASN1EncodeItem(poolp, NULL, certRepContent, - CMMFCertRepContentTemplate); - if (der == NULL) { - rv = ERROR_ENCODING_CERT_REP_CONTENT; - goto loser; - } -#ifdef WRITE_OUT_RESPONSE - writeOutItem("CertRepContent.der", der); -#endif - *base64der = BTOA_DataToAscii(der->data, der->len); - return NO_ERROR; - loser: - return rv; -} - -ErrorCode -issueCerts(CertResponseInfo *issuedCerts, int numCerts, - CERTCertificate *issuerCert) -{ - ErrorCode rv; - char *base64Response; - - rv = createCMMFResponse(issuedCerts, numCerts, issuerCert, &base64Response); - if (rv != NO_ERROR) { - goto loser; - } - spitOutCMMFResponse(getNickname(issuedCerts[0].cert),base64Response); - return NO_ERROR; - loser: - return rv; -} - -ErrorCode -verifySignature(CGIVarTable *varTable, CRMFCertReqMsg *currReq, - CRMFCertRequest *certReq, CERTCertificate *newCert) -{ - SECStatus srv; - ErrorCode rv = NO_ERROR; - CRMFPOPOSigningKey *signKey = NULL; - SECAlgorithmID *algID = NULL; - SECItem *signature = NULL; - SECKEYPublicKey *pubKey = NULL; - SECItem *reqDER = NULL; - - srv = CRMF_CertReqMsgGetPOPOSigningKey(currReq, &signKey); - if (srv != SECSuccess || signKey == NULL) { - rv = ERROR_RETRIEVING_POP_SIGN_KEY; - goto loser; - } - algID = CRMF_POPOSigningKeyGetAlgID(signKey); - if (algID == NULL) { - rv = ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY; - goto loser; - } - signature = CRMF_POPOSigningKeyGetSignature(signKey); - if (signature == NULL) { - rv = ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY; - goto loser; - } - /* Make the length the number of bytes instead of bits */ - signature->len = (signature->len+7)/8; - pubKey = CERT_ExtractPublicKey(newCert); - if (pubKey == NULL) { - rv = ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT; - goto loser; - } - reqDER = SEC_ASN1EncodeItem(NULL, NULL, certReq, CRMFCertRequestTemplate); - if (reqDER == NULL) { - rv = ERROR_ENCODING_CERT_REQ_FOR_POP; - goto loser; - } - srv = VFY_VerifyDataWithAlgorithmID(reqDER->data, reqDER->len, pubKey, - signature, &algID->algorithm, NULL, varTable); - if (srv != SECSuccess) { - rv = ERROR_VERIFYING_SIGNATURE_POP; - goto loser; - } - /* Fall thru in successfull case. */ - loser: - if (pubKey != NULL) { - SECKEY_DestroyPublicKey(pubKey); - } - if (reqDER != NULL) { - SECITEM_FreeItem(reqDER, PR_TRUE); - } - if (signature != NULL) { - SECITEM_FreeItem(signature, PR_TRUE); - } - if (algID != NULL) { - SECOID_DestroyAlgorithmID(algID, PR_TRUE); - } - if (signKey != NULL) { - CRMF_DestroyPOPOSigningKey(signKey); - } - return rv; -} - -ErrorCode -doChallengeResponse(CGIVarTable *varTable, CRMFCertReqMsg *currReq, - CRMFCertRequest *certReq, CERTCertificate *newCert, - ChallengeCreationInfo *challs, int *numChall) -{ - CRMFPOPOPrivKey *privKey = NULL; - CRMFPOPOPrivKeyChoice privKeyChoice; - SECStatus srv; - ErrorCode rv = NO_ERROR; - - srv = CRMF_CertReqMsgGetPOPKeyEncipherment(currReq, &privKey); - if (srv != SECSuccess || privKey == NULL) { - rv = ERROR_GETTING_KEY_ENCIPHERMENT; - goto loser; - } - privKeyChoice = CRMF_POPOPrivKeyGetChoice(privKey); - CRMF_DestroyPOPOPrivKey(privKey); - switch (privKeyChoice) { - case crmfSubsequentMessage: - challs = &challs[*numChall]; - challs->random = rand(); - challs->pubKey = CERT_ExtractPublicKey(newCert); - if (challs->pubKey == NULL) { - rv = ERROR_RETRIEVING_PUB_KEY_FOR_CHALL; - goto loser; - } - (*numChall)++; - rv = DO_CHALLENGE_RESPONSE; - break; - case crmfThisMessage: - /* There'd better be a PKIArchiveControl in this message */ - if (!CRMF_CertRequestIsControlPresent(certReq, - crmfPKIArchiveOptionsControl)) { - rv = ERROR_NO_POP_FOR_PRIVKEY; - goto loser; - } - break; - default: - rv = ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE; - goto loser; - } -loser: - return rv; -} - -ErrorCode -doProofOfPossession(CGIVarTable *varTable, CRMFCertReqMsg *currReq, - CRMFCertRequest *certReq, CERTCertificate *newCert, - ChallengeCreationInfo *challs, int *numChall) -{ - CRMFPOPChoice popChoice; - ErrorCode rv = NO_ERROR; - - popChoice = CRMF_CertReqMsgGetPOPType(currReq); - if (popChoice == crmfNoPOPChoice) { - rv = NO_POP_FOR_REQUEST; - goto loser; - } - switch (popChoice) { - case crmfSignature: - rv = verifySignature(varTable, currReq, certReq, newCert); - break; - case crmfKeyEncipherment: - rv = doChallengeResponse(varTable, currReq, certReq, newCert, - challs, numChall); - break; - case crmfRAVerified: - case crmfKeyAgreement: - default: - rv = UNSUPPORTED_POP; - goto loser; - } - loser: - return rv; -} - -void -convertB64ToJS(char *base64) -{ - int i; - - for (i=0; base64[i] != '\0'; i++) { - if (base64[i] == '\n') { - printf ("\\n"); - }else { - printf ("%c", base64[i]); - } - } -} - -void -formatChallenge(char *chall64, char *certRepContentDER, - ChallengeCreationInfo *challInfo, int numChalls) -{ - printf ("function respondToChallenge() {\n" - " var chalForm = document.chalForm;\n\n" - " chalForm.CertRepContent.value = '"); - convertB64ToJS(certRepContentDER); - printf ("';\n" - " chalForm.ChallResponse.value = crypto.popChallengeResponse('"); - convertB64ToJS(chall64); - printf("');\n" - " chalForm.submit();\n" - "}\n"); - -} - -void -spitOutChallenge(char *chall64, char *certRepContentDER, - ChallengeCreationInfo *challInfo, int numChalls, - char *nickname) -{ - int i; - - spitOutHeaders(); - printf("<html>\n" - "<head>\n" - "<title>Challenge Page</title>\n" - "<script language=\"JavaScript\">\n" - "<!--\n"); - /* The JavaScript function actually gets defined within - * this function call - */ - formatChallenge(chall64, certRepContentDER, challInfo, numChalls); - printf("// -->\n" - "</script>\n" - "</head>\n" - "<body onLoad='respondToChallenge()'>\n" - "<h1>Cartman is now responding to the Challenge " - "presented by the CGI</h1>\n" - "<form action='crmfcgi' method='post' name='chalForm'>\n" - "<input type='hidden' name=CertRepContent value=''>\n" - "<input type='hidden' name=ChallResponse value=''>\n"); - for (i=0;i<numChalls; i++) { - printf("<input type='hidden' name='chal%d' value='%d'>\n", - i+1, challInfo[i].random); - } - printf("<input type='hidden' name='nickname' value='%s'>\n", nickname); - printf("</form>\n</body>\n</html>"); -} - -ErrorCode -issueChallenge(CertResponseInfo *issuedCerts, int numCerts, - ChallengeCreationInfo *challInfo, int numChalls, - CERTCertificate *issuer, CGIVarTable *varTable) -{ - ErrorCode rv = NO_ERROR; - CMMFPOPODecKeyChallContent *chalContent = NULL; - int i; - SECStatus srv; - PRArenaPool *poolp; - CERTGeneralName *genName; - SECItem *challDER = NULL; - char *chall64, *certRepContentDER; - - rv = createCMMFResponse(issuedCerts, numCerts, issuer, - &certRepContentDER); - if (rv != NO_ERROR) { - goto loser; - } - chalContent = CMMF_CreatePOPODecKeyChallContent(); - if (chalContent == NULL) { - rv = ERROR_CREATING_EMPTY_CHAL_CONTENT; - goto loser; - } - poolp = PORT_NewArena(1024); - if (poolp == NULL) { - rv = OUT_OF_MEMORY; - goto loser; - } - genName = CERT_GetCertificateNames(issuer, poolp); - if (genName == NULL) { - rv = ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER; - goto loser; - } - for (i=0;i<numChalls;i++) { - srv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent, - challInfo[i].random, - genName, - challInfo[i].pubKey, - varTable); - SECKEY_DestroyPublicKey(challInfo[i].pubKey); - if (srv != SECSuccess) { - rv = ERROR_SETTING_CHALLENGE; - goto loser; - } - } - challDER = SEC_ASN1EncodeItem(NULL, NULL, chalContent, - CMMFPOPODecKeyChallContentTemplate); - if (challDER == NULL) { - rv = ERROR_ENCODING_CHALL; - goto loser; - } - chall64 = BTOA_DataToAscii(challDER->data, challDER->len); - SECITEM_FreeItem(challDER, PR_TRUE); - if (chall64 == NULL) { - rv = ERROR_CONVERTING_CHALL_TO_BASE64; - goto loser; - } - spitOutChallenge(chall64, certRepContentDER, challInfo, numChalls, - getNickname(issuedCerts[0].cert)); - loser: - return rv; -} - - -ErrorCode -processRequest(CGIVarTable *varTable) -{ - CERTCertDBHandle *certdb; - SECKEYKeyDBHandle *keydb; - CRMFCertReqMessages *certReqs = NULL; - const char *crmfReq; - const char *caNickname; - CERTCertificate *caCert = NULL; - CertResponseInfo *issuedCerts = NULL; - CERTSubjectPublicKeyInfo spki = { 0 }; - ErrorCode rv=NO_ERROR; - PRBool doChallengeResponse = PR_FALSE; - SECItem der = { 0 }; - SECStatus srv; - CERTCertificateRequest oldCertReq = { 0 }; - CRMFCertReqMsg **reqMsgs = NULL,*currReq = NULL; - CRMFCertRequest **reqs = NULL, *certReq = NULL; - CERTName subject = { 0 }; - int numReqs,i; - ChallengeCreationInfo *challInfo=NULL; - int numChalls = 0; - - certdb = CERT_GetDefaultCertDB(); - keydb = SECKEY_GetDefaultKeyDB(); - crmfReq = CGITableFindValue(varTable, "CRMFRequest"); - if (crmfReq == NULL) { - rv = CGI_VAR_MISSING; - missingVar = "CRMFRequest"; - goto loser; - } - caNickname = CGITableFindValue(varTable, "CANickname"); - if (caNickname == NULL) { - rv = CGI_VAR_MISSING; - missingVar = "CANickname"; - goto loser; - } - caCert = CERT_FindCertByNickname(certdb, caNickname); - if (caCert == NULL) { - rv = COULD_NOT_FIND_CA; - goto loser; - } - srv = ATOB_ConvertAsciiToItem(&der, crmfReq); - if (srv != SECSuccess) { - rv = BAD_ASCII_FOR_REQ; - goto loser; - } - certReqs = CRMF_CreateCertReqMessagesFromDER(der.data, der.len); - SECITEM_FreeItem(&der, PR_FALSE); - if (certReqs == NULL) { - rv = COULD_NOT_DECODE_REQS; - goto loser; - } - numReqs = CRMF_CertReqMessagesGetNumMessages(certReqs); - issuedCerts = PORT_ZNewArray(CertResponseInfo, numReqs); - challInfo = PORT_ZNewArray(ChallengeCreationInfo, numReqs); - if (issuedCerts == NULL || challInfo == NULL) { - rv = OUT_OF_MEMORY; - goto loser; - } - reqMsgs = PORT_ZNewArray(CRMFCertReqMsg*, numReqs); - reqs = PORT_ZNewArray(CRMFCertRequest*, numReqs); - if (reqMsgs == NULL || reqs == NULL) { - rv = OUT_OF_MEMORY; - goto loser; - } - for (i=0; i<numReqs; i++) { - currReq = reqMsgs[i] = - CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqs, i); - if (currReq == NULL) { - rv = ERROR_RETRIEVING_REQUEST_MSG; - goto loser; - } - certReq = reqs[i] = CRMF_CertReqMsgGetCertRequest(currReq); - if (certReq == NULL) { - rv = ERROR_RETRIEVING_CERT_REQUEST; - goto loser; - } - srv = CRMF_CertRequestGetCertTemplateSubject(certReq, &subject); - if (srv != SECSuccess) { - rv = ERROR_RETRIEVING_SUBJECT_FROM_REQ; - goto loser; - } - srv = CRMF_CertRequestGetCertTemplatePublicKey(certReq, &spki); - if (srv != SECSuccess) { - rv = ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ; - goto loser; - } - rv = initOldCertReq(&oldCertReq, &subject, &spki); - if (rv != NO_ERROR) { - goto loser; - } - rv = createNewCert(&issuedCerts[i].cert, &oldCertReq, currReq, certReq, - caCert, varTable); - if (rv != NO_ERROR) { - goto loser; - } - rv = doProofOfPossession(varTable, currReq, certReq, issuedCerts[i].cert, - challInfo, &numChalls); - if (rv != NO_ERROR) { - if (rv == DO_CHALLENGE_RESPONSE) { - doChallengeResponse = PR_TRUE; - } else { - goto loser; - } - } - CRMF_CertReqMsgGetID(currReq, &issuedCerts[i].certReqID); - CRMF_DestroyCertReqMsg(currReq); - CRMF_DestroyCertRequest(certReq); - } - if (doChallengeResponse) { - rv = issueChallenge(issuedCerts, numReqs, challInfo, numChalls, caCert, - varTable); - } else { - rv = issueCerts(issuedCerts, numReqs, caCert); - } - loser: - if (certReqs != NULL) { - CRMF_DestroyCertReqMessages(certReqs); - } - return rv; -} - -ErrorCode -processChallengeResponse(CGIVarTable *varTable, const char *certRepContent) -{ - SECItem binDER = { 0 }; - SECStatus srv; - ErrorCode rv = NO_ERROR; - const char *clientResponse; - const char *formChalValue; - const char *nickname; - CMMFPOPODecKeyRespContent *respContent = NULL; - int numResponses,i; - long curResponse, expectedResponse; - char cgiChalVar[10]; -#ifdef WRITE_OUT_RESPONSE - SECItem certRepBinDER = { 0 }; - - ATOB_ConvertAsciiToItem(&certRepBinDER, certRepContent); - writeOutItem("challCertRepContent.der", &certRepBinDER); - PORT_Free(certRepBinDER.data); -#endif - clientResponse = CGITableFindValue(varTable, "ChallResponse"); - if (clientResponse == NULL) { - rv = REQ_CGI_VAR_NOT_PRESENT; - missingVar = "ChallResponse"; - goto loser; - } - srv = ATOB_ConvertAsciiToItem(&binDER, clientResponse); - if (srv != SECSuccess) { - rv = ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN; - goto loser; - } - respContent = CMMF_CreatePOPODecKeyRespContentFromDER(binDER.data, - binDER.len); - SECITEM_FreeItem(&binDER, PR_FALSE); - binDER.data = NULL; - if (respContent == NULL) { - rv = ERROR_CREATING_KEY_RESP_FROM_DER; - goto loser; - } - numResponses = CMMF_POPODecKeyRespContentGetNumResponses(respContent); - for (i=0;i<numResponses;i++){ - srv = CMMF_POPODecKeyRespContentGetResponse(respContent,i,&curResponse); - if (srv != SECSuccess) { - rv = ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE; - goto loser; - } - sprintf(cgiChalVar, "chal%d", i+1); - formChalValue = CGITableFindValue(varTable, cgiChalVar); - if (formChalValue == NULL) { - rv = REQ_CGI_VAR_NOT_PRESENT; - missingVar = strdup(cgiChalVar); - goto loser; - } - sscanf(formChalValue, "%ld", &expectedResponse); - if (expectedResponse != curResponse) { - rv = ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED; - goto loser; - } - } - nickname = CGITableFindValue(varTable, "nickname"); - if (nickname == NULL) { - rv = REQ_CGI_VAR_NOT_PRESENT; - missingVar = "nickname"; - goto loser; - } - spitOutCMMFResponse(nickname, certRepContent); - loser: - if (respContent != NULL) { - CMMF_DestroyPOPODecKeyRespContent(respContent); - } - return rv; -} - -int -main() -{ - char *form_output = NULL; - int form_output_len, form_output_used; - CGIVarTable varTable = { 0 }; - ErrorCode errNum = 0; - char *certRepContent; - -#ifdef ATTACH_CGI - /* Put an ifinite loop in here so I can attach to - * the process after the process is spun off - */ - { int stupid = 1; - while (stupid); - } -#endif - - form_output_used = 0; - srand(time(NULL)); - while (feof(stdin) == 0) { - if (form_output == NULL) { - form_output = PORT_NewArray(char, DEFAULT_ALLOC_SIZE+1); - form_output_len = DEFAULT_ALLOC_SIZE; - } else if ((form_output_used + DEFAULT_ALLOC_SIZE) >= form_output_len) { - form_output_len += DEFAULT_ALLOC_SIZE; - form_output = PORT_Realloc(form_output, form_output_len+1); - } - form_output_used += fread(&form_output[form_output_used], sizeof(char), - DEFAULT_ALLOC_SIZE, stdin); - } - ParseInputVariables(&varTable, form_output); - certRepContent = CGITableFindValue(&varTable, "CertRepContent"); - if (certRepContent == NULL) { - errNum = initNSS(&varTable); - if (errNum != 0) { - goto loser; - } - errNum = processRequest(&varTable); - } else { - errNum = processChallengeResponse(&varTable, certRepContent); - } - if (errNum != NO_ERROR) { - goto loser; - } - goto done; -loser: - dumpErrorMessage(errNum); -done: - free (form_output); - return 0; -} - |