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) ? &ersand[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 +