security/nss/cmd/crmf-cgi/crmfcgi.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/crmf-cgi/crmfcgi.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1090 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "seccomon.h"
     1.9 +#include "nss.h"
    1.10 +#include "key.h"
    1.11 +#include "cert.h"
    1.12 +#include "pk11func.h"
    1.13 +#include "secmod.h"
    1.14 +#include "cmmf.h"
    1.15 +#include "crmf.h"
    1.16 +#include "base64.h"
    1.17 +#include "secasn1.h"
    1.18 +#include "cryptohi.h"
    1.19 +#include <string.h>
    1.20 +#include <stdlib.h>
    1.21 +#include <stdio.h>
    1.22 +
    1.23 +#define DEFAULT_ALLOC_SIZE 200
    1.24 +#define DEFAULT_CGI_VARS   20
    1.25 +
    1.26 +typedef struct CGIVariableStr {
    1.27 +  char *name;
    1.28 +  char *value;
    1.29 +} CGIVariable;
    1.30 +
    1.31 +typedef struct CGIVarTableStr {
    1.32 +  CGIVariable **variables;
    1.33 +  int           numVars;
    1.34 +  int           numAlloc; 
    1.35 +} CGIVarTable;
    1.36 +
    1.37 +typedef struct CertResponseInfoStr {
    1.38 +  CERTCertificate *cert;
    1.39 +  long             certReqID;
    1.40 +} CertResponseInfo;
    1.41 +
    1.42 +typedef struct ChallengeCreationInfoStr {
    1.43 +  long             random;
    1.44 +  SECKEYPublicKey *pubKey;
    1.45 +} ChallengeCreationInfo;
    1.46 +
    1.47 +char *missingVar = NULL;
    1.48 +
    1.49 +/*
    1.50 + * Error values.
    1.51 + */
    1.52 +typedef enum {
    1.53 +  NO_ERROR = 0,
    1.54 +  NSS_INIT_FAILED,
    1.55 +  AUTH_FAILED,
    1.56 +  REQ_CGI_VAR_NOT_PRESENT,
    1.57 +  CRMF_REQ_NOT_PRESENT,
    1.58 +  BAD_ASCII_FOR_REQ,
    1.59 +  CGI_VAR_MISSING,
    1.60 +  COULD_NOT_FIND_CA,
    1.61 +  COULD_NOT_DECODE_REQS,
    1.62 +  OUT_OF_MEMORY,
    1.63 +  ERROR_RETRIEVING_REQUEST_MSG,
    1.64 +  ERROR_RETRIEVING_CERT_REQUEST,
    1.65 +  ERROR_RETRIEVING_SUBJECT_FROM_REQ,
    1.66 +  ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ,
    1.67 +  ERROR_CREATING_NEW_CERTIFICATE,
    1.68 +  COULD_NOT_START_EXTENSIONS,
    1.69 +  ERROR_RETRIEVING_EXT_FROM_REQ,
    1.70 +  ERROR_ADDING_EXT_TO_CERT,
    1.71 +  ERROR_ENDING_EXTENSIONS,
    1.72 +  COULD_NOT_FIND_ISSUER_PRIVATE_KEY,
    1.73 +  UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER,
    1.74 +  ERROR_SETTING_SIGN_ALG,
    1.75 +  ERROR_ENCODING_NEW_CERT,
    1.76 +  ERROR_SIGNING_NEW_CERT,
    1.77 +  ERROR_CREATING_CERT_REP_CONTENT,
    1.78 +  ERROR_CREATING_SINGLE_CERT_RESPONSE,
    1.79 +  ERROR_SETTING_CERT_RESPONSES,
    1.80 +  ERROR_CREATING_CA_LIST,
    1.81 +  ERROR_ADDING_ISSUER_TO_CA_LIST,
    1.82 +  ERROR_ENCODING_CERT_REP_CONTENT,
    1.83 +  NO_POP_FOR_REQUEST,
    1.84 +  UNSUPPORTED_POP,
    1.85 +  ERROR_RETRIEVING_POP_SIGN_KEY,
    1.86 +  ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY,
    1.87 +  ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY,
    1.88 +  DO_CHALLENGE_RESPONSE,
    1.89 +  ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT,
    1.90 +  ERROR_ENCODING_CERT_REQ_FOR_POP,
    1.91 +  ERROR_VERIFYING_SIGNATURE_POP,
    1.92 +  ERROR_RETRIEVING_PUB_KEY_FOR_CHALL,
    1.93 +  ERROR_CREATING_EMPTY_CHAL_CONTENT,
    1.94 +  ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER,
    1.95 +  ERROR_SETTING_CHALLENGE,
    1.96 +  ERROR_ENCODING_CHALL,
    1.97 +  ERROR_CONVERTING_CHALL_TO_BASE64,
    1.98 +  ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN,
    1.99 +  ERROR_CREATING_KEY_RESP_FROM_DER,
   1.100 +  ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE,
   1.101 +  ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED,
   1.102 +  ERROR_GETTING_KEY_ENCIPHERMENT,
   1.103 +  ERROR_NO_POP_FOR_PRIVKEY,
   1.104 +  ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE
   1.105 +} ErrorCode;
   1.106 +
   1.107 +const char *
   1.108 +CGITableFindValue(CGIVarTable *varTable, const char *key);
   1.109 +
   1.110 +void
   1.111 +spitOutHeaders(void)
   1.112 +{
   1.113 +  printf("Content-type: text/html\n\n");
   1.114 +}
   1.115 +
   1.116 +void
   1.117 +dumpRequest(CGIVarTable *varTable)
   1.118 +{
   1.119 +  int i;
   1.120 +  CGIVariable *var;
   1.121 +
   1.122 +  printf ("<table border=1 cellpadding=1 cellspacing=1 width=\"100%%\">\n");
   1.123 +  printf ("<tr><td><b><center>Variable Name<center></b></td>"
   1.124 +          "<td><b><center>Value</center></b></td></tr>\n");
   1.125 +  for (i=0; i<varTable->numVars; i++) {
   1.126 +    var = varTable->variables[i];
   1.127 +    printf ("<tr><td><pre>%s</pre></td><td><pre>%s</pre></td></tr>\n", 
   1.128 +             var->name, var->value);
   1.129 +  }
   1.130 +  printf("</table>\n");
   1.131 +}
   1.132 +
   1.133 +void
   1.134 +echo_request(CGIVarTable *varTable)
   1.135 +{
   1.136 +  spitOutHeaders();
   1.137 +  printf("<html><head><title>CGI Echo Page</title></head>\n"
   1.138 +	 "<body><h1>Got the following request</h1>\n");
   1.139 +  dumpRequest(varTable);
   1.140 +  printf("</body></html>");
   1.141 +}
   1.142 +
   1.143 +void
   1.144 +processVariable(CGIVariable *var)
   1.145 +{
   1.146 +  char *plusSign, *percentSign;
   1.147 +
   1.148 +  /*First look for all of the '+' and convert them to spaces */
   1.149 +  plusSign = var->value;
   1.150 +  while ((plusSign=strchr(plusSign, '+')) != NULL) {
   1.151 +    *plusSign = ' ';
   1.152 +  }
   1.153 +  percentSign = var->value;
   1.154 +  while ((percentSign=strchr(percentSign, '%')) != NULL) {
   1.155 +    char string[3];
   1.156 +    int  value;
   1.157 +
   1.158 +    string[0] = percentSign[1];
   1.159 +    string[1] = percentSign[2];
   1.160 +    string[2] = '\0';
   1.161 +
   1.162 +    sscanf(string,"%x", &value);
   1.163 +    *percentSign = (char)value;
   1.164 +    memmove(&percentSign[1], &percentSign[3], 1+strlen(&percentSign[3]));
   1.165 +  }
   1.166 +}
   1.167 +
   1.168 +char *
   1.169 +parseNextVariable(CGIVarTable *varTable, char *form_output)
   1.170 +{
   1.171 +  char *ampersand, *equal;
   1.172 +  CGIVariable *var;
   1.173 +
   1.174 +  if (varTable->numVars == varTable->numAlloc) {
   1.175 +    CGIVariable **newArr = realloc(varTable->variables, 
   1.176 +                                   (varTable->numAlloc + DEFAULT_CGI_VARS)*sizeof(CGIVariable*));
   1.177 +    if (newArr == NULL) {
   1.178 +      return NULL;
   1.179 +    }
   1.180 +    varTable->variables = newArr;
   1.181 +    varTable->numAlloc += DEFAULT_CGI_VARS;
   1.182 +  }
   1.183 +  equal     = strchr(form_output, '=');
   1.184 +  if (equal == NULL) {
   1.185 +    return NULL;
   1.186 +  }
   1.187 +  ampersand = strchr(equal, '&');
   1.188 +  if (ampersand == NULL) {
   1.189 +    return NULL;
   1.190 +  }
   1.191 +  equal[0] = '\0';
   1.192 +  if (ampersand != NULL) {
   1.193 +    ampersand[0] = '\0';
   1.194 +  }
   1.195 +  var = malloc(sizeof(CGIVariable));
   1.196 +  var->name = form_output; 
   1.197 +  var->value = &equal[1];
   1.198 +  varTable->variables[varTable->numVars] = var;
   1.199 +  varTable->numVars++;
   1.200 +  processVariable(var);
   1.201 +  return (ampersand != NULL) ? &ampersand[1] : NULL;
   1.202 +}
   1.203 +
   1.204 +void
   1.205 +ParseInputVariables(CGIVarTable *varTable, char *form_output)
   1.206 +{
   1.207 +  varTable->variables = malloc(sizeof(CGIVariable*)*DEFAULT_CGI_VARS);
   1.208 +  varTable->numVars = 0;
   1.209 +  varTable->numAlloc = DEFAULT_CGI_VARS;
   1.210 +  while (form_output && form_output[0] != '\0') {
   1.211 +    form_output = parseNextVariable(varTable, form_output);
   1.212 +  }
   1.213 +}
   1.214 +
   1.215 +const char *
   1.216 +CGITableFindValue(CGIVarTable *varTable, const char *key)
   1.217 +{
   1.218 +  const char *retVal = NULL;
   1.219 +  int i;
   1.220 +
   1.221 +  for (i=0; i<varTable->numVars; i++) {
   1.222 +    if (strcmp(varTable->variables[i]->name, key) == 0) {
   1.223 +      retVal = varTable->variables[i]->value;
   1.224 +      break;
   1.225 +    } 
   1.226 +  }
   1.227 +  return retVal;
   1.228 +}
   1.229 +
   1.230 +char*
   1.231 +passwordCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
   1.232 +{
   1.233 +  const char *passwd;
   1.234 +  if (retry) {
   1.235 +    return NULL;
   1.236 +  }
   1.237 +  passwd = CGITableFindValue((CGIVarTable*)arg, "dbPassword");
   1.238 +  if (passwd == NULL) {
   1.239 +    return NULL;
   1.240 +  }
   1.241 +  return PORT_Strdup(passwd);
   1.242 +}
   1.243 +
   1.244 +ErrorCode
   1.245 +initNSS(CGIVarTable *varTable)
   1.246 +{
   1.247 +  const char *nssDir;
   1.248 +  PK11SlotInfo *keySlot;
   1.249 +  SECStatus rv;
   1.250 +
   1.251 +  nssDir = CGITableFindValue(varTable,"NSSDirectory");
   1.252 +  if (nssDir == NULL) {
   1.253 +    missingVar = "NSSDirectory";
   1.254 +    return REQ_CGI_VAR_NOT_PRESENT;
   1.255 +  }
   1.256 +  rv = NSS_Init(nssDir);
   1.257 +  if (rv != SECSuccess) {
   1.258 +    return NSS_INIT_FAILED;
   1.259 +  }
   1.260 +  PK11_SetPasswordFunc(passwordCallback);
   1.261 +  keySlot = PK11_GetInternalKeySlot();
   1.262 +  rv = PK11_Authenticate(keySlot, PR_FALSE, varTable);
   1.263 +  PK11_FreeSlot(keySlot);
   1.264 +  if (rv != SECSuccess) {
   1.265 +    return AUTH_FAILED;
   1.266 +  }
   1.267 +  return NO_ERROR;
   1.268 +}
   1.269 +
   1.270 +void
   1.271 +dumpErrorMessage(ErrorCode errNum)
   1.272 +{
   1.273 +  spitOutHeaders();
   1.274 +  printf("<html><head><title>Error</title></head><body><h1>Error processing "
   1.275 +	 "data</h1> Received the error %d<p>", errNum);
   1.276 +  if (errNum  ==   REQ_CGI_VAR_NOT_PRESENT) {
   1.277 +    printf ("The missing variable is %s.", missingVar);
   1.278 +  }
   1.279 +  printf ("<i>More useful information here in the future.</i></body></html>");
   1.280 +}
   1.281 +
   1.282 +ErrorCode
   1.283 +initOldCertReq(CERTCertificateRequest *oldCertReq,
   1.284 +	       CERTName *subject, CERTSubjectPublicKeyInfo *spki)
   1.285 +{
   1.286 +  PLArenaPool *poolp;
   1.287 +
   1.288 +  poolp = oldCertReq->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.289 +  SEC_ASN1EncodeInteger(poolp, &oldCertReq->version, 
   1.290 +			SEC_CERTIFICATE_VERSION_3);
   1.291 +  CERT_CopyName(poolp, &oldCertReq->subject, subject);
   1.292 +  SECKEY_CopySubjectPublicKeyInfo(poolp, &oldCertReq->subjectPublicKeyInfo,
   1.293 +				  spki);
   1.294 +  oldCertReq->attributes = NULL;
   1.295 +  return NO_ERROR;
   1.296 +}
   1.297 +
   1.298 +ErrorCode
   1.299 +addExtensions(CERTCertificate *newCert, CRMFCertRequest *certReq)
   1.300 +{
   1.301 +  int numExtensions, i;
   1.302 +  void *extHandle;
   1.303 +  ErrorCode rv = NO_ERROR;
   1.304 +  CRMFCertExtension *ext;
   1.305 +  SECStatus srv;
   1.306 +
   1.307 +  numExtensions = CRMF_CertRequestGetNumberOfExtensions(certReq);
   1.308 +  if (numExtensions == 0) {
   1.309 +    /* No extensions to add */
   1.310 +    return NO_ERROR;
   1.311 +  }
   1.312 +  extHandle = CERT_StartCertExtensions(newCert);
   1.313 +  if (extHandle == NULL) {
   1.314 +    rv = COULD_NOT_START_EXTENSIONS;
   1.315 +    goto loser;
   1.316 +  }
   1.317 +  for (i=0; i<numExtensions; i++) {
   1.318 +    ext = CRMF_CertRequestGetExtensionAtIndex(certReq, i);
   1.319 +    if (ext == NULL) {
   1.320 +      rv = ERROR_RETRIEVING_EXT_FROM_REQ;
   1.321 +    }
   1.322 +    srv = CERT_AddExtension(extHandle, CRMF_CertExtensionGetOidTag(ext),
   1.323 +			    CRMF_CertExtensionGetValue(ext),
   1.324 +			    CRMF_CertExtensionGetIsCritical(ext), PR_FALSE);
   1.325 +    if (srv != SECSuccess) {
   1.326 +      rv = ERROR_ADDING_EXT_TO_CERT;
   1.327 +    }
   1.328 +  }
   1.329 +  srv = CERT_FinishExtensions(extHandle);
   1.330 +  if (srv != SECSuccess) {
   1.331 +    rv = ERROR_ENDING_EXTENSIONS;
   1.332 +    goto loser;
   1.333 +  }
   1.334 +  return NO_ERROR;
   1.335 + loser:
   1.336 +  return rv;
   1.337 +}
   1.338 +
   1.339 +void
   1.340 +writeOutItem(const char *filePath, SECItem *der)
   1.341 +{
   1.342 +  PRFileDesc *outfile;
   1.343 +
   1.344 +  outfile = PR_Open (filePath,
   1.345 +		     PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
   1.346 +		     0666);
   1.347 +  PR_Write(outfile, der->data, der->len);
   1.348 +  PR_Close(outfile);
   1.349 +
   1.350 +}
   1.351 +
   1.352 +ErrorCode
   1.353 +createNewCert(CERTCertificate**issuedCert,CERTCertificateRequest *oldCertReq,
   1.354 +	      CRMFCertReqMsg *currReq, CRMFCertRequest *certReq, 
   1.355 +	      CERTCertificate *issuerCert, CGIVarTable *varTable)
   1.356 +{
   1.357 +  CERTCertificate *newCert = NULL;
   1.358 +  CERTValidity *validity;
   1.359 +  PRExplodedTime printableTime;
   1.360 +  PRTime now, after;
   1.361 +  ErrorCode rv=NO_ERROR;
   1.362 +  SECKEYPrivateKey *issuerPrivKey;
   1.363 +  SECItem derCert = { 0 };
   1.364 +  SECOidTag signTag;
   1.365 +  SECStatus srv;
   1.366 +  long version;
   1.367 +
   1.368 +  now = PR_Now();
   1.369 +  PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
   1.370 +  printableTime.tm_month += 9;
   1.371 +  after = PR_ImplodeTime(&printableTime);
   1.372 +  validity = CERT_CreateValidity(now, after);
   1.373 +  newCert = *issuedCert = 
   1.374 +    CERT_CreateCertificate(rand(), &(issuerCert->subject), validity, 
   1.375 +			   oldCertReq);
   1.376 +  if (newCert == NULL) {
   1.377 +    rv = ERROR_CREATING_NEW_CERTIFICATE;
   1.378 +    goto loser;
   1.379 +  }
   1.380 +  rv = addExtensions(newCert, certReq);
   1.381 +  if (rv != NO_ERROR) {
   1.382 +    goto loser;
   1.383 +  }
   1.384 +  issuerPrivKey = PK11_FindKeyByAnyCert(issuerCert, varTable);
   1.385 +  if (issuerPrivKey == NULL) {
   1.386 +    rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY;
   1.387 +  }
   1.388 +  signTag = SEC_GetSignatureAlgorithmOidTag(issuerPrivatekey->keytype, 
   1.389 +					    SEC_OID_UNKNOWN);
   1.390 +  if (signTag == SEC_OID_UNKNOWN) {
   1.391 +    rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER;
   1.392 +    goto loser;
   1.393 +  }
   1.394 +  srv = SECOID_SetAlgorithmID(newCert->arena, &newCert->signature, 
   1.395 +			      signTag, 0);
   1.396 +  if (srv != SECSuccess) {
   1.397 +    rv = ERROR_SETTING_SIGN_ALG;
   1.398 +    goto loser;
   1.399 +  }
   1.400 +  srv = CRMF_CertRequestGetCertTemplateVersion(certReq, &version);
   1.401 +  if (srv != SECSuccess) {
   1.402 +    /* No version included in the request */
   1.403 +    *(newCert->version.data) = SEC_CERTIFICATE_VERSION_3;
   1.404 +  } else {
   1.405 +    SECITEM_FreeItem(&newCert->version, PR_FALSE);
   1.406 +    SEC_ASN1EncodeInteger(newCert->arena, &newCert->version, version);
   1.407 +  }
   1.408 +  SEC_ASN1EncodeItem(newCert->arena, &derCert, newCert, 
   1.409 +		     CERT_CertificateTemplate);
   1.410 +  if (derCert.data == NULL) {
   1.411 +    rv = ERROR_ENCODING_NEW_CERT;
   1.412 +    goto loser;
   1.413 +  }
   1.414 +  srv = SEC_DerSignData(newCert->arena, &(newCert->derCert), derCert.data,
   1.415 +			derCert.len, issuerPrivKey, signTag);
   1.416 +  if (srv != SECSuccess) {
   1.417 +    rv = ERROR_SIGNING_NEW_CERT;
   1.418 +    goto loser;
   1.419 +  }
   1.420 +#ifdef WRITE_OUT_RESPONSE
   1.421 +  writeOutItem("newcert.der", &newCert->derCert);
   1.422 +#endif
   1.423 +  return NO_ERROR;
   1.424 + loser:
   1.425 +  *issuedCert = NULL;
   1.426 +  if (newCert) {
   1.427 +    CERT_DestroyCertificate(newCert);
   1.428 +  }
   1.429 +  return rv;
   1.430 +		     
   1.431 +}
   1.432 +
   1.433 +void
   1.434 +formatCMMFResponse(char *nickname, char *base64Response)
   1.435 +{
   1.436 +  char *currLine, *nextLine;
   1.437 +
   1.438 +  printf("var retVal = crypto.importUserCertificates(\"%s\",\n", nickname);
   1.439 +  currLine = base64Response;
   1.440 +  while (1) {
   1.441 +    nextLine = strchr(currLine, '\n');
   1.442 +    if (nextLine == NULL) {
   1.443 +      /* print out the last line here. */
   1.444 +      printf ("\"%s\",\n", currLine);
   1.445 +      break;
   1.446 +    }
   1.447 +    nextLine[0] = '\0';
   1.448 +    printf("\"%s\\n\"+\n", currLine);
   1.449 +    currLine = nextLine+1;
   1.450 +  }
   1.451 +  printf("true);\n"
   1.452 +	 "if(retVal == '') {\n"
   1.453 +	 "\tdocument.write(\"<h1>New Certificate Successfully Imported.</h1>\");\n"
   1.454 +	 "} else {\n"
   1.455 +	 "\tdocument.write(\"<h2>Unable to import New Certificate</h2>\");\n"
   1.456 +	 "\tdocument.write(\"crypto.importUserCertificates returned <b>\");\n"
   1.457 +	 "\tdocument.write(retVal);\n"
   1.458 +	 "\tdocument.write(\"</b>\");\n"
   1.459 +	 "}\n");
   1.460 +}
   1.461 +
   1.462 +void
   1.463 +spitOutCMMFResponse(char *nickname, char *base64Response)
   1.464 +{
   1.465 +  spitOutHeaders();
   1.466 +  printf("<html>\n<head>\n<title>CMMF Resonse Page</title>\n</head>\n\n"
   1.467 +	 "<body><h1>CMMF Response Page</h1>\n"
   1.468 +	 "<script language=\"JavaScript\">\n"
   1.469 +	 "<!--\n");
   1.470 +  formatCMMFResponse(nickname, base64Response);
   1.471 +  printf("// -->\n"
   1.472 +	 "</script>\n</body>\n</html>");
   1.473 +}
   1.474 +
   1.475 +char*
   1.476 +getNickname(CERTCertificate *cert)
   1.477 +{
   1.478 +  char *nickname;
   1.479 +
   1.480 +  if (cert->nickname != NULL) {
   1.481 +    return cert->nickname;
   1.482 +  }
   1.483 +  nickname = CERT_GetCommonName(&cert->subject);
   1.484 +  if (nickname != NULL) {
   1.485 +    return nickname;
   1.486 +  }
   1.487 +  return CERT_NameToAscii(&cert->subject);
   1.488 +}
   1.489 +
   1.490 +ErrorCode
   1.491 +createCMMFResponse(CertResponseInfo *issuedCerts, int numCerts, 
   1.492 +		   CERTCertificate *issuerCert, char **base64der)
   1.493 +{
   1.494 + CMMFCertRepContent *certRepContent=NULL;
   1.495 +  ErrorCode rv = NO_ERROR;
   1.496 +  CMMFCertResponse **responses, *currResponse;
   1.497 +  CERTCertList *caList;
   1.498 +  int i;
   1.499 +  SECStatus srv;
   1.500 +  PLArenaPool *poolp;
   1.501 +  SECItem *der;
   1.502 +
   1.503 +  certRepContent = CMMF_CreateCertRepContent();
   1.504 +  if (certRepContent == NULL) {
   1.505 +    rv = ERROR_CREATING_CERT_REP_CONTENT;
   1.506 +    goto loser;
   1.507 +  }
   1.508 +  responses = PORT_NewArray(CMMFCertResponse*, numCerts);
   1.509 +  if (responses == NULL) {
   1.510 +    rv = OUT_OF_MEMORY;
   1.511 +    goto loser;
   1.512 +  }
   1.513 +  for (i=0; i<numCerts;i++) {
   1.514 +    responses[i] = currResponse = 
   1.515 +      CMMF_CreateCertResponse(issuedCerts[i].certReqID);
   1.516 +    if (currResponse == NULL) {
   1.517 +      rv = ERROR_CREATING_SINGLE_CERT_RESPONSE;
   1.518 +      goto loser;
   1.519 +    }
   1.520 +    CMMF_CertResponseSetPKIStatusInfoStatus(currResponse, cmmfGranted);
   1.521 +    CMMF_CertResponseSetCertificate(currResponse, issuedCerts[i].cert);
   1.522 +  }
   1.523 +  srv = CMMF_CertRepContentSetCertResponses(certRepContent, responses,
   1.524 +					    numCerts);
   1.525 +  if (srv != SECSuccess) {
   1.526 +    rv = ERROR_SETTING_CERT_RESPONSES;
   1.527 +    goto loser;
   1.528 +  }
   1.529 +  caList = CERT_NewCertList();
   1.530 +  if (caList == NULL) {
   1.531 +    rv = ERROR_CREATING_CA_LIST;
   1.532 +    goto loser;
   1.533 +  }
   1.534 +  srv = CERT_AddCertToListTail(caList, issuerCert);
   1.535 +  if (srv != SECSuccess) {
   1.536 +    rv = ERROR_ADDING_ISSUER_TO_CA_LIST;
   1.537 +    goto loser;
   1.538 +  }
   1.539 +  srv = CMMF_CertRepContentSetCAPubs(certRepContent, caList);
   1.540 +  CERT_DestroyCertList(caList);
   1.541 +  poolp = PORT_NewArena(1024);
   1.542 +  der = SEC_ASN1EncodeItem(poolp, NULL, certRepContent, 
   1.543 +			   CMMFCertRepContentTemplate);
   1.544 +  if (der == NULL) {
   1.545 +    rv = ERROR_ENCODING_CERT_REP_CONTENT;
   1.546 +    goto loser;
   1.547 +  }
   1.548 +#ifdef WRITE_OUT_RESPONSE
   1.549 +  writeOutItem("CertRepContent.der", der);
   1.550 +#endif
   1.551 +  *base64der = BTOA_DataToAscii(der->data, der->len);
   1.552 +  return NO_ERROR;
   1.553 + loser:
   1.554 +  return rv;
   1.555 +}
   1.556 +
   1.557 +ErrorCode
   1.558 +issueCerts(CertResponseInfo *issuedCerts, int numCerts, 
   1.559 +	   CERTCertificate *issuerCert)
   1.560 +{
   1.561 +  ErrorCode rv;
   1.562 +  char *base64Response;
   1.563 +
   1.564 +  rv = createCMMFResponse(issuedCerts, numCerts, issuerCert, &base64Response);
   1.565 +  if (rv != NO_ERROR) {
   1.566 +    goto loser;
   1.567 +  }
   1.568 +  spitOutCMMFResponse(getNickname(issuedCerts[0].cert),base64Response);
   1.569 +  return NO_ERROR;
   1.570 + loser:
   1.571 +  return rv;
   1.572 +}
   1.573 +
   1.574 +ErrorCode
   1.575 +verifySignature(CGIVarTable *varTable, CRMFCertReqMsg *currReq, 
   1.576 +		CRMFCertRequest *certReq, CERTCertificate *newCert)
   1.577 +{
   1.578 +  SECStatus srv;
   1.579 +  ErrorCode rv = NO_ERROR;
   1.580 +  CRMFPOPOSigningKey *signKey   = NULL;
   1.581 +  SECAlgorithmID     *algID     = NULL;
   1.582 +  SECItem            *signature = NULL;
   1.583 +  SECKEYPublicKey    *pubKey    = NULL;
   1.584 +  SECItem            *reqDER    = NULL;
   1.585 +
   1.586 +  srv = CRMF_CertReqMsgGetPOPOSigningKey(currReq, &signKey);
   1.587 +  if (srv != SECSuccess || signKey == NULL) {
   1.588 +    rv = ERROR_RETRIEVING_POP_SIGN_KEY;
   1.589 +    goto loser;
   1.590 +  }
   1.591 +  algID = CRMF_POPOSigningKeyGetAlgID(signKey);
   1.592 +  if (algID == NULL) {
   1.593 +    rv = ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY;
   1.594 +    goto loser;
   1.595 +  }
   1.596 +  signature = CRMF_POPOSigningKeyGetSignature(signKey);
   1.597 +  if (signature == NULL) {
   1.598 +    rv = ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY;
   1.599 +    goto loser;
   1.600 +  }
   1.601 +  /* Make the length the number of bytes instead of bits */
   1.602 +  signature->len = (signature->len+7)/8;
   1.603 +  pubKey = CERT_ExtractPublicKey(newCert);
   1.604 +  if (pubKey == NULL) {
   1.605 +    rv = ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT;
   1.606 +    goto loser;
   1.607 +  }
   1.608 +  reqDER = SEC_ASN1EncodeItem(NULL, NULL, certReq, CRMFCertRequestTemplate);
   1.609 +  if (reqDER == NULL) {
   1.610 +    rv = ERROR_ENCODING_CERT_REQ_FOR_POP;
   1.611 +    goto loser;
   1.612 +  }
   1.613 +  srv = VFY_VerifyDataWithAlgorithmID(reqDER->data, reqDER->len, pubKey, 
   1.614 +			signature, &algID->algorithm, NULL, varTable);
   1.615 +  if (srv != SECSuccess) {
   1.616 +    rv = ERROR_VERIFYING_SIGNATURE_POP;
   1.617 +    goto loser;
   1.618 +  }
   1.619 +  /* Fall thru in successfull case. */
   1.620 + loser:
   1.621 +  if (pubKey != NULL) {
   1.622 +    SECKEY_DestroyPublicKey(pubKey);
   1.623 +  }
   1.624 +  if (reqDER != NULL) {
   1.625 +    SECITEM_FreeItem(reqDER, PR_TRUE);
   1.626 +  }
   1.627 +  if (signature != NULL) {
   1.628 +    SECITEM_FreeItem(signature, PR_TRUE);
   1.629 +  }
   1.630 +  if (algID != NULL) {
   1.631 +    SECOID_DestroyAlgorithmID(algID, PR_TRUE);
   1.632 +  }
   1.633 +  if (signKey != NULL) {
   1.634 +    CRMF_DestroyPOPOSigningKey(signKey);
   1.635 +  }  
   1.636 +  return rv;
   1.637 +}
   1.638 +
   1.639 +ErrorCode
   1.640 +doChallengeResponse(CGIVarTable *varTable, CRMFCertReqMsg *currReq, 
   1.641 +		    CRMFCertRequest *certReq, CERTCertificate *newCert,
   1.642 +		    ChallengeCreationInfo *challs, int *numChall)
   1.643 +{
   1.644 +  CRMFPOPOPrivKey *privKey = NULL;
   1.645 +  CRMFPOPOPrivKeyChoice privKeyChoice;
   1.646 +  SECStatus srv;
   1.647 +  ErrorCode rv = NO_ERROR;
   1.648 + 
   1.649 +  srv = CRMF_CertReqMsgGetPOPKeyEncipherment(currReq, &privKey);
   1.650 +  if (srv != SECSuccess || privKey == NULL) {
   1.651 +    rv = ERROR_GETTING_KEY_ENCIPHERMENT;
   1.652 +    goto loser;
   1.653 +  } 
   1.654 +  privKeyChoice = CRMF_POPOPrivKeyGetChoice(privKey);
   1.655 +  CRMF_DestroyPOPOPrivKey(privKey);
   1.656 +  switch (privKeyChoice) {
   1.657 +  case crmfSubsequentMessage:
   1.658 +    challs = &challs[*numChall];
   1.659 +    challs->random = rand();
   1.660 +    challs->pubKey = CERT_ExtractPublicKey(newCert);
   1.661 +    if (challs->pubKey == NULL) {
   1.662 +      rv = ERROR_RETRIEVING_PUB_KEY_FOR_CHALL;
   1.663 +      goto loser;
   1.664 +    }
   1.665 +    (*numChall)++;
   1.666 +    rv = DO_CHALLENGE_RESPONSE;
   1.667 +    break;
   1.668 +  case crmfThisMessage:
   1.669 +    /* There'd better be a PKIArchiveControl in this message */
   1.670 +    if (!CRMF_CertRequestIsControlPresent(certReq, 
   1.671 +					  crmfPKIArchiveOptionsControl)) {
   1.672 +      rv = ERROR_NO_POP_FOR_PRIVKEY;
   1.673 +      goto loser;
   1.674 +    }
   1.675 +    break;
   1.676 +  default:
   1.677 +    rv = ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE;
   1.678 +    goto loser;
   1.679 +  }
   1.680 +loser:
   1.681 +  return rv;
   1.682 +}
   1.683 +
   1.684 +ErrorCode
   1.685 +doProofOfPossession(CGIVarTable *varTable, CRMFCertReqMsg *currReq, 
   1.686 +		    CRMFCertRequest *certReq, CERTCertificate *newCert,
   1.687 +		    ChallengeCreationInfo *challs, int *numChall)
   1.688 +{
   1.689 +  CRMFPOPChoice popChoice;
   1.690 +  ErrorCode rv = NO_ERROR;
   1.691 +
   1.692 +  popChoice = CRMF_CertReqMsgGetPOPType(currReq);
   1.693 +  if (popChoice == crmfNoPOPChoice) {
   1.694 +    rv = NO_POP_FOR_REQUEST;
   1.695 +    goto loser;
   1.696 +  }
   1.697 +  switch (popChoice) {
   1.698 +  case crmfSignature:
   1.699 +    rv = verifySignature(varTable, currReq, certReq, newCert);
   1.700 +    break;
   1.701 +  case crmfKeyEncipherment:
   1.702 +    rv = doChallengeResponse(varTable, currReq, certReq, newCert,
   1.703 +			     challs, numChall);
   1.704 +    break;
   1.705 +  case crmfRAVerified:
   1.706 +  case crmfKeyAgreement:
   1.707 +  default:
   1.708 +    rv = UNSUPPORTED_POP;
   1.709 +    goto loser;
   1.710 +  }
   1.711 + loser:
   1.712 +  return rv;
   1.713 +}
   1.714 +
   1.715 +void
   1.716 +convertB64ToJS(char *base64)
   1.717 +{
   1.718 +  int i;
   1.719 +
   1.720 +  for (i=0; base64[i] != '\0'; i++) {
   1.721 +    if (base64[i] == '\n') {
   1.722 +      printf ("\\n");
   1.723 +    }else {
   1.724 +      printf ("%c", base64[i]);
   1.725 +    }
   1.726 +  }
   1.727 +}
   1.728 +
   1.729 +void
   1.730 +formatChallenge(char *chall64, char *certRepContentDER,
   1.731 +		 ChallengeCreationInfo *challInfo, int numChalls)
   1.732 +{
   1.733 +  printf ("function respondToChallenge() {\n"
   1.734 +	  "  var chalForm = document.chalForm;\n\n"
   1.735 +	  "  chalForm.CertRepContent.value = '");
   1.736 +  convertB64ToJS(certRepContentDER);
   1.737 +  printf ("';\n"
   1.738 +	  "  chalForm.ChallResponse.value = crypto.popChallengeResponse('");
   1.739 +  convertB64ToJS(chall64);
   1.740 +  printf("');\n"
   1.741 +	 "  chalForm.submit();\n"
   1.742 +	 "}\n");
   1.743 +
   1.744 +}
   1.745 +
   1.746 +void
   1.747 +spitOutChallenge(char *chall64, char *certRepContentDER,
   1.748 +		 ChallengeCreationInfo *challInfo, int numChalls,
   1.749 +		 char *nickname)
   1.750 +{
   1.751 +  int i;
   1.752 +
   1.753 +  spitOutHeaders();
   1.754 +  printf("<html>\n"
   1.755 +	 "<head>\n"
   1.756 +	 "<title>Challenge Page</title>\n"
   1.757 +	 "<script language=\"JavaScript\">\n"
   1.758 +	 "<!--\n");
   1.759 +  /* The JavaScript function actually gets defined within
   1.760 +   * this function call
   1.761 +   */
   1.762 +  formatChallenge(chall64, certRepContentDER, challInfo, numChalls);
   1.763 +  printf("// -->\n"
   1.764 +	 "</script>\n"
   1.765 +	 "</head>\n"
   1.766 +	 "<body onLoad='respondToChallenge()'>\n"
   1.767 +	 "<h1>Cartman is now responding to the Challenge "
   1.768 +	 "presented by the CGI</h1>\n"
   1.769 +	 "<form action='crmfcgi' method='post' name='chalForm'>\n"
   1.770 +	 "<input type='hidden' name=CertRepContent value=''>\n"
   1.771 +	 "<input type='hidden' name=ChallResponse value=''>\n");
   1.772 +  for (i=0;i<numChalls; i++) {
   1.773 +    printf("<input type='hidden' name='chal%d' value='%d'>\n",
   1.774 +	   i+1, challInfo[i].random);
   1.775 +  }
   1.776 +  printf("<input type='hidden' name='nickname' value='%s'>\n", nickname);
   1.777 +  printf("</form>\n</body>\n</html>");
   1.778 +}
   1.779 +
   1.780 +ErrorCode
   1.781 +issueChallenge(CertResponseInfo *issuedCerts, int numCerts, 
   1.782 +	       ChallengeCreationInfo *challInfo, int numChalls,
   1.783 +	       CERTCertificate *issuer, CGIVarTable *varTable)
   1.784 +{
   1.785 +  ErrorCode rv = NO_ERROR;
   1.786 +  CMMFPOPODecKeyChallContent *chalContent = NULL;
   1.787 +  int i;
   1.788 +  SECStatus srv;
   1.789 +  PLArenaPool *poolp;
   1.790 +  CERTGeneralName *genName;
   1.791 +  SECItem *challDER = NULL;
   1.792 +  char *chall64, *certRepContentDER;
   1.793 +
   1.794 +  rv = createCMMFResponse(issuedCerts, numCerts, issuer, 
   1.795 +			  &certRepContentDER);
   1.796 +  if (rv != NO_ERROR) {
   1.797 +    goto loser;
   1.798 +  }
   1.799 +  chalContent = CMMF_CreatePOPODecKeyChallContent();
   1.800 +  if (chalContent == NULL) {
   1.801 +    rv = ERROR_CREATING_EMPTY_CHAL_CONTENT;
   1.802 +    goto loser;
   1.803 +  }
   1.804 +  poolp = PORT_NewArena(1024);
   1.805 +  if (poolp == NULL) {
   1.806 +    rv = OUT_OF_MEMORY;
   1.807 +    goto loser;
   1.808 +  }
   1.809 +  genName = CERT_GetCertificateNames(issuer, poolp);
   1.810 +  if (genName == NULL) {
   1.811 +    rv = ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER;
   1.812 +    goto loser;
   1.813 +  }
   1.814 +  for (i=0;i<numChalls;i++) {
   1.815 +    srv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent,
   1.816 +						      challInfo[i].random,
   1.817 +						      genName,
   1.818 +						      challInfo[i].pubKey,
   1.819 +						      varTable);
   1.820 +    SECKEY_DestroyPublicKey(challInfo[i].pubKey);
   1.821 +    if (srv != SECSuccess) {
   1.822 +      rv = ERROR_SETTING_CHALLENGE;
   1.823 +      goto loser;
   1.824 +    }
   1.825 +  }
   1.826 +  challDER = SEC_ASN1EncodeItem(NULL, NULL, chalContent, 
   1.827 +				CMMFPOPODecKeyChallContentTemplate);
   1.828 +  if (challDER == NULL) {
   1.829 +    rv = ERROR_ENCODING_CHALL;
   1.830 +    goto loser;
   1.831 +  }
   1.832 +  chall64 = BTOA_DataToAscii(challDER->data, challDER->len);
   1.833 +  SECITEM_FreeItem(challDER, PR_TRUE);
   1.834 +  if (chall64 == NULL) {
   1.835 +    rv = ERROR_CONVERTING_CHALL_TO_BASE64;
   1.836 +    goto loser;
   1.837 +  }
   1.838 +  spitOutChallenge(chall64, certRepContentDER, challInfo, numChalls,
   1.839 +		   getNickname(issuedCerts[0].cert));
   1.840 + loser:
   1.841 +  return rv;
   1.842 +}
   1.843 +
   1.844 +
   1.845 +ErrorCode
   1.846 +processRequest(CGIVarTable *varTable)
   1.847 +{
   1.848 +  CERTCertDBHandle *certdb;
   1.849 +  SECKEYKeyDBHandle *keydb;
   1.850 +  CRMFCertReqMessages *certReqs = NULL;
   1.851 +  const char *crmfReq;
   1.852 +  const char *caNickname;
   1.853 +  CERTCertificate *caCert = NULL;
   1.854 +  CertResponseInfo *issuedCerts = NULL;
   1.855 +  CERTSubjectPublicKeyInfo spki = { 0 };
   1.856 +  ErrorCode rv=NO_ERROR;
   1.857 +  PRBool doChallengeResponse = PR_FALSE;
   1.858 +  SECItem der = { 0 };
   1.859 +  SECStatus srv;
   1.860 +  CERTCertificateRequest oldCertReq = { 0 };
   1.861 +  CRMFCertReqMsg **reqMsgs = NULL,*currReq = NULL;
   1.862 +  CRMFCertRequest **reqs = NULL, *certReq = NULL;
   1.863 +  CERTName         subject = { 0 };
   1.864 +  int numReqs,i;
   1.865 +  ChallengeCreationInfo *challInfo=NULL;
   1.866 +  int numChalls = 0;
   1.867 +
   1.868 +  certdb = CERT_GetDefaultCertDB();
   1.869 +  keydb = SECKEY_GetDefaultKeyDB();
   1.870 +  crmfReq = CGITableFindValue(varTable, "CRMFRequest");
   1.871 +  if (crmfReq == NULL) {
   1.872 +    rv = CGI_VAR_MISSING;
   1.873 +    missingVar = "CRMFRequest";
   1.874 +    goto loser;
   1.875 +  }
   1.876 +  caNickname = CGITableFindValue(varTable, "CANickname");
   1.877 +  if (caNickname == NULL) {
   1.878 +    rv = CGI_VAR_MISSING;
   1.879 +    missingVar = "CANickname";
   1.880 +    goto loser;
   1.881 +  }
   1.882 +  caCert = CERT_FindCertByNickname(certdb, caNickname);
   1.883 +  if (caCert == NULL) {
   1.884 +    rv = COULD_NOT_FIND_CA;
   1.885 +    goto loser;
   1.886 +  }
   1.887 +  srv = ATOB_ConvertAsciiToItem(&der, crmfReq);
   1.888 +  if (srv != SECSuccess) {
   1.889 +    rv = BAD_ASCII_FOR_REQ;
   1.890 +    goto loser;
   1.891 +  }
   1.892 +  certReqs = CRMF_CreateCertReqMessagesFromDER(der.data, der.len);
   1.893 +  SECITEM_FreeItem(&der, PR_FALSE);
   1.894 +  if (certReqs == NULL) {
   1.895 +    rv = COULD_NOT_DECODE_REQS;
   1.896 +    goto loser;
   1.897 +  }
   1.898 +  numReqs = CRMF_CertReqMessagesGetNumMessages(certReqs);
   1.899 +  issuedCerts = PORT_ZNewArray(CertResponseInfo, numReqs);
   1.900 +  challInfo   = PORT_ZNewArray(ChallengeCreationInfo, numReqs);
   1.901 +  if (issuedCerts == NULL || challInfo == NULL) {
   1.902 +    rv = OUT_OF_MEMORY;
   1.903 +    goto loser;
   1.904 +  }
   1.905 +  reqMsgs = PORT_ZNewArray(CRMFCertReqMsg*,   numReqs);
   1.906 +  reqs    = PORT_ZNewArray(CRMFCertRequest*, numReqs);
   1.907 +  if (reqMsgs == NULL || reqs == NULL) {
   1.908 +    rv =   OUT_OF_MEMORY;
   1.909 +    goto loser;
   1.910 +  }
   1.911 +  for (i=0; i<numReqs; i++) {
   1.912 +    currReq = reqMsgs[i] = 
   1.913 +      CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqs, i);
   1.914 +    if (currReq == NULL) {
   1.915 +      rv = ERROR_RETRIEVING_REQUEST_MSG;
   1.916 +      goto loser;
   1.917 +    }
   1.918 +    certReq = reqs[i] = CRMF_CertReqMsgGetCertRequest(currReq);
   1.919 +    if (certReq == NULL) {
   1.920 +      rv = ERROR_RETRIEVING_CERT_REQUEST;
   1.921 +      goto loser;
   1.922 +    }
   1.923 +    srv = CRMF_CertRequestGetCertTemplateSubject(certReq, &subject);
   1.924 +    if (srv != SECSuccess) {
   1.925 +      rv = ERROR_RETRIEVING_SUBJECT_FROM_REQ;
   1.926 +      goto loser;
   1.927 +    }
   1.928 +    srv = CRMF_CertRequestGetCertTemplatePublicKey(certReq, &spki);
   1.929 +    if (srv != SECSuccess) {
   1.930 +      rv = ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ;
   1.931 +      goto loser;
   1.932 +    }
   1.933 +    rv = initOldCertReq(&oldCertReq, &subject, &spki);
   1.934 +    if (rv != NO_ERROR) {
   1.935 +      goto loser;
   1.936 +    }
   1.937 +    rv = createNewCert(&issuedCerts[i].cert, &oldCertReq, currReq, certReq, 
   1.938 +		       caCert, varTable);
   1.939 +    if (rv != NO_ERROR) {
   1.940 +      goto loser;
   1.941 +    }
   1.942 +    rv = doProofOfPossession(varTable, currReq, certReq, issuedCerts[i].cert,
   1.943 +			     challInfo, &numChalls);
   1.944 +    if (rv != NO_ERROR) {
   1.945 +      if (rv == DO_CHALLENGE_RESPONSE) {
   1.946 +	doChallengeResponse = PR_TRUE;
   1.947 +      } else {
   1.948 +	goto loser;
   1.949 +      }
   1.950 +    }
   1.951 +    CRMF_CertReqMsgGetID(currReq, &issuedCerts[i].certReqID);
   1.952 +    CRMF_DestroyCertReqMsg(currReq);
   1.953 +    CRMF_DestroyCertRequest(certReq);
   1.954 +  }
   1.955 +  if (doChallengeResponse) {
   1.956 +    rv = issueChallenge(issuedCerts, numReqs, challInfo, numChalls, caCert,
   1.957 +			varTable);
   1.958 +  } else {
   1.959 +    rv = issueCerts(issuedCerts, numReqs, caCert);
   1.960 +  }
   1.961 + loser:
   1.962 +  if (certReqs != NULL) {
   1.963 +    CRMF_DestroyCertReqMessages(certReqs);
   1.964 +  }
   1.965 +  return rv;
   1.966 +}
   1.967 +
   1.968 +ErrorCode
   1.969 +processChallengeResponse(CGIVarTable *varTable, const char *certRepContent)
   1.970 +{
   1.971 +  SECItem binDER = { 0 };
   1.972 +  SECStatus srv;
   1.973 +  ErrorCode rv = NO_ERROR;
   1.974 +  const char *clientResponse;
   1.975 +  const char *formChalValue;
   1.976 +  const char *nickname;
   1.977 +  CMMFPOPODecKeyRespContent *respContent = NULL;
   1.978 +  int numResponses,i;
   1.979 +  long curResponse, expectedResponse;
   1.980 +  char cgiChalVar[10];
   1.981 +#ifdef WRITE_OUT_RESPONSE
   1.982 +  SECItem certRepBinDER = { 0 };
   1.983 +
   1.984 +  ATOB_ConvertAsciiToItem(&certRepBinDER, certRepContent);
   1.985 +  writeOutItem("challCertRepContent.der", &certRepBinDER);
   1.986 +  PORT_Free(certRepBinDER.data);
   1.987 +#endif  
   1.988 +  clientResponse = CGITableFindValue(varTable, "ChallResponse");
   1.989 +  if (clientResponse == NULL) {
   1.990 +    rv =   REQ_CGI_VAR_NOT_PRESENT;
   1.991 +    missingVar = "ChallResponse";
   1.992 +    goto loser;
   1.993 +  }
   1.994 +  srv = ATOB_ConvertAsciiToItem(&binDER, clientResponse);
   1.995 +  if (srv != SECSuccess) {
   1.996 +    rv = ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN;
   1.997 +    goto loser;
   1.998 +  }
   1.999 +  respContent = CMMF_CreatePOPODecKeyRespContentFromDER(binDER.data,
  1.1000 +							binDER.len);
  1.1001 +  SECITEM_FreeItem(&binDER, PR_FALSE);
  1.1002 +  binDER.data = NULL;
  1.1003 +  if (respContent == NULL) {
  1.1004 +    rv = ERROR_CREATING_KEY_RESP_FROM_DER;
  1.1005 +    goto loser;
  1.1006 +  }
  1.1007 +  numResponses = CMMF_POPODecKeyRespContentGetNumResponses(respContent);
  1.1008 +  for (i=0;i<numResponses;i++){
  1.1009 +    srv = CMMF_POPODecKeyRespContentGetResponse(respContent,i,&curResponse);
  1.1010 +    if (srv != SECSuccess) {
  1.1011 +      rv = ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE;
  1.1012 +      goto loser;
  1.1013 +    }
  1.1014 +    sprintf(cgiChalVar, "chal%d", i+1);
  1.1015 +    formChalValue = CGITableFindValue(varTable, cgiChalVar);
  1.1016 +    if (formChalValue == NULL) {
  1.1017 +      rv = REQ_CGI_VAR_NOT_PRESENT;
  1.1018 +      missingVar = strdup(cgiChalVar);
  1.1019 +      goto loser;
  1.1020 +    }
  1.1021 +    sscanf(formChalValue, "%ld", &expectedResponse);
  1.1022 +    if (expectedResponse != curResponse) {
  1.1023 +      rv = ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED;
  1.1024 +      goto loser;
  1.1025 +    }
  1.1026 +  }
  1.1027 +  nickname = CGITableFindValue(varTable, "nickname");
  1.1028 +  if (nickname == NULL) {
  1.1029 +    rv = REQ_CGI_VAR_NOT_PRESENT;
  1.1030 +    missingVar = "nickname";
  1.1031 +    goto loser;
  1.1032 +  }
  1.1033 +  spitOutCMMFResponse(nickname, certRepContent);
  1.1034 + loser:
  1.1035 +  if (respContent != NULL) {
  1.1036 +    CMMF_DestroyPOPODecKeyRespContent(respContent);
  1.1037 +  }
  1.1038 +  return rv;
  1.1039 +}
  1.1040 +
  1.1041 +int
  1.1042 +main()
  1.1043 +{
  1.1044 +  char *form_output = NULL;
  1.1045 +  int   form_output_len, form_output_used;
  1.1046 +  CGIVarTable varTable = { 0 };
  1.1047 +  ErrorCode errNum = 0;
  1.1048 +  char *certRepContent;
  1.1049 +
  1.1050 +#ifdef ATTACH_CGI
  1.1051 +  /* Put an ifinite loop in here so I can attach to 
  1.1052 +   * the process after the process is spun off
  1.1053 +   */
  1.1054 +  { int stupid = 1;
  1.1055 +    while (stupid);
  1.1056 +  }
  1.1057 +#endif
  1.1058 +
  1.1059 +  form_output_used = 0;
  1.1060 +  srand(time(NULL));
  1.1061 +  while (feof(stdin) == 0) {
  1.1062 +    if (form_output == NULL) {
  1.1063 +      form_output = PORT_NewArray(char, DEFAULT_ALLOC_SIZE+1);
  1.1064 +      form_output_len  = DEFAULT_ALLOC_SIZE;
  1.1065 +    } else if ((form_output_used + DEFAULT_ALLOC_SIZE) >= form_output_len) {
  1.1066 +      form_output_len += DEFAULT_ALLOC_SIZE;
  1.1067 +      form_output = PORT_Realloc(form_output, form_output_len+1);
  1.1068 +    }
  1.1069 +    form_output_used += fread(&form_output[form_output_used], sizeof(char), 
  1.1070 +			      DEFAULT_ALLOC_SIZE, stdin);
  1.1071 +  }
  1.1072 +  ParseInputVariables(&varTable, form_output);
  1.1073 +  certRepContent = CGITableFindValue(&varTable, "CertRepContent");
  1.1074 +  if (certRepContent == NULL) {
  1.1075 +    errNum = initNSS(&varTable);
  1.1076 +    if (errNum != 0) {
  1.1077 +      goto loser;
  1.1078 +    }
  1.1079 +    errNum = processRequest(&varTable);
  1.1080 +  } else {
  1.1081 +    errNum = processChallengeResponse(&varTable, certRepContent);
  1.1082 +  }
  1.1083 +  if (errNum != NO_ERROR) {
  1.1084 +    goto loser;
  1.1085 +  }
  1.1086 +  goto done;
  1.1087 +loser:
  1.1088 +  dumpErrorMessage(errNum);
  1.1089 +done:
  1.1090 +  free (form_output);
  1.1091 +  return 0;
  1.1092 +}
  1.1093 +

mercurial