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) ? &ampersand[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 + -
显示快捷键?