crmfcgi.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,124 行 · 第 1/2 页
C
1,124 行
} 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;}ErrorCodeissueCerts(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;}ErrorCodeverifySignature(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_VerifyData(reqDER->data, reqDER->len, pubKey, signature, SECOID_FindOIDTag(&algID->algorithm), 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;}ErrorCodedoChallengeResponse(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;}ErrorCodedoProofOfPossession(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;}voidconvertB64ToJS(char *base64){ int i; for (i=0; base64[i] != '\0'; i++) { if (base64[i] == '\n') { printf ("\\n"); }else { printf ("%c", base64[i]); } }}voidformatChallenge(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");}voidspitOutChallenge(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>");}ErrorCodeissueChallenge(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;}ErrorCodeprocessRequest(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;}ErrorCodeprocessChallengeResponse(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;}intmain(){ 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;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?