crmfcgi.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,124 行 · 第 1/2 页
C
1,124 行
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#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 "crypto.h"#include <string.h>#include <stdlib.h>#include <stdio.h>#define DEFAULT_ALLOC_SIZE 200#define DEFAULT_CGI_VARS 20typedef 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);voidspitOutHeaders(void){ printf("Content-type: text/html\n\n");}voiddumpRequest(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");}voidecho_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>");}voidprocessVariable(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;}voidParseInputVariables(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);}ErrorCodeinitNSS(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); if (rv != SECSuccess) { return AUTH_FAILED; } return NO_ERROR;}voiddumpErrorMessage(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>");}ErrorCodeinitOldCertReq(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;}ErrorCodeaddExtensions(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;}voidwriteOutItem(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);}ErrorCodecreateNewCert(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; } switch(issuerPrivKey->keyType) { case rsaKey: signTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; break; case dsaKey: signTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break; default: 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; }voidformatCMMFResponse(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 Succesfully 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");}voidspitOutCMMFResponse(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);}ErrorCodecreateCMMFResponse(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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?