| Index: nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c
|
| ===================================================================
|
| --- nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c (revision 239365)
|
| +++ nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c (working copy)
|
| @@ -341,6 +341,8 @@
|
| * PARAMETERS
|
| * "request"
|
| * Address of the OcspRequest for which a response is desired.
|
| + * "httpMethod"
|
| + * GET or POST
|
| * "responder"
|
| * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP
|
| * query.
|
| @@ -364,6 +366,7 @@
|
| PKIX_Error *
|
| pkix_pl_OcspResponse_Create(
|
| PKIX_PL_OcspRequest *request,
|
| + const char *httpMethod,
|
| void *responder,
|
| PKIX_PL_VerifyCallback verifyFcn,
|
| void **pNBIOContext,
|
| @@ -389,6 +392,10 @@
|
| PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create");
|
| PKIX_NULLCHECK_TWO(pNBIOContext, pResponse);
|
|
|
| + if (!strcmp(httpMethod, "GET") && !strcmp(httpMethod, "POST")) {
|
| + PKIX_ERROR(PKIX_INVALIDOCSPHTTPMETHOD);
|
| + }
|
| +
|
| nbioContext = *pNBIOContext;
|
| *pNBIOContext = NULL;
|
|
|
| @@ -422,6 +429,9 @@
|
| }
|
|
|
| if (httpClient && (httpClient->version == 1)) {
|
| + char *fullGetPath = NULL;
|
| + const char *sessionPath = NULL;
|
| + PRBool usePOST = !strcmp(httpMethod, "POST");
|
|
|
| hcv1 = &(httpClient->fcnTable.ftable1);
|
|
|
| @@ -441,21 +451,68 @@
|
| PKIX_ERROR(PKIX_OCSPSERVERERROR);
|
| }
|
|
|
| - rv = (*hcv1->createFcn)(serverSession, "http", path,
|
| - "POST",
|
| + if (usePOST) {
|
| + sessionPath = path;
|
| + } else {
|
| + /* calculate, are we allowed to use GET? */
|
| + enum { max_get_request_size = 255 }; /* defined by RFC2560 */
|
| + char b64ReqBuf[max_get_request_size+1];
|
| + size_t base64size;
|
| + size_t slashLengthIfNeeded = 0;
|
| + size_t pathLength;
|
| + PRInt32 urlEncodedBufLength;
|
| + size_t getURLLength;
|
| + char *walkOutput = NULL;
|
| +
|
| + pathLength = strlen(path);
|
| + if (path[pathLength-1] != '/') {
|
| + slashLengthIfNeeded = 1;
|
| + }
|
| + base64size = (((encodedRequest->len +2)/3) * 4);
|
| + if (base64size > max_get_request_size) {
|
| + PKIX_ERROR(PKIX_OCSPGETREQUESTTOOBIG);
|
| + }
|
| + memset(b64ReqBuf, 0, sizeof(b64ReqBuf));
|
| + PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len, b64ReqBuf);
|
| + urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL);
|
| + getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded;
|
| + fullGetPath = (char*)PORT_Alloc(getURLLength);
|
| + if (!fullGetPath) {
|
| + PKIX_ERROR(PKIX_OUTOFMEMORY);
|
| + }
|
| + strcpy(fullGetPath, path);
|
| + walkOutput = fullGetPath + pathLength;
|
| + if (walkOutput > fullGetPath && slashLengthIfNeeded) {
|
| + strcpy(walkOutput, "/");
|
| + ++walkOutput;
|
| + }
|
| + ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput);
|
| + sessionPath = fullGetPath;
|
| + }
|
| +
|
| + rv = (*hcv1->createFcn)(serverSession, "http",
|
| + sessionPath, httpMethod,
|
| PR_SecondsToInterval(timeout),
|
| &sessionRequest);
|
| + sessionPath = NULL;
|
| + if (fullGetPath) {
|
| + PORT_Free(fullGetPath);
|
| + fullGetPath = NULL;
|
| + }
|
| +
|
| if (rv != SECSuccess) {
|
| PKIX_ERROR(PKIX_OCSPSERVERERROR);
|
| }
|
|
|
| - rv = (*hcv1->setPostDataFcn)(sessionRequest,
|
| - (char *)encodedRequest->data,
|
| - encodedRequest->len,
|
| - "application/ocsp-request");
|
| - if (rv != SECSuccess) {
|
| - PKIX_ERROR(PKIX_OCSPSERVERERROR);
|
| - }
|
| + if (usePOST) {
|
| + rv = (*hcv1->setPostDataFcn)(sessionRequest,
|
| + (char *)encodedRequest->data,
|
| + encodedRequest->len,
|
| + "application/ocsp-request");
|
| + if (rv != SECSuccess) {
|
| + PKIX_ERROR(PKIX_OCSPSERVERERROR);
|
| + }
|
| + }
|
|
|
| /* create a PKIX_PL_OcspResponse object */
|
| PKIX_CHECK(PKIX_PL_Object_Alloc
|
| @@ -797,10 +854,12 @@
|
| signature, issuerCert);
|
|
|
| if (response->signerCert == NULL) {
|
| - PORT_SetError(SEC_ERROR_UNKNOWN_SIGNER);
|
| + if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
|
| + /* Make the error a little more specific. */
|
| + PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
|
| + }
|
| goto cleanup;
|
| - }
|
| -
|
| + }
|
| PKIX_CHECK(
|
| PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert,
|
| &(response->pkixSignerCert),
|
| @@ -937,6 +996,7 @@
|
| pkix_pl_OcspResponse_GetStatusForCert(
|
| PKIX_PL_OcspCertID *cid,
|
| PKIX_PL_OcspResponse *response,
|
| + PKIX_Boolean allowCachingOfFailures,
|
| PKIX_PL_Date *validity,
|
| PKIX_Boolean *pPassed,
|
| SECErrorCodes *pReturnCode,
|
| @@ -944,8 +1004,7 @@
|
| {
|
| PRTime time = 0;
|
| SECStatus rv = SECFailure;
|
| - SECStatus rvCache;
|
| - PRBool certIDWasConsumed = PR_FALSE;
|
| + CERTOCSPSingleResponse *single = NULL;
|
|
|
| PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_GetStatusForCert");
|
| PKIX_NULLCHECK_THREE(response, pPassed, pReturnCode);
|
| @@ -966,17 +1025,36 @@
|
| time = PR_Now();
|
| }
|
|
|
| - rv = cert_ProcessOCSPResponse(response->handle,
|
| - response->nssOCSPResponse,
|
| - cid->certID,
|
| - response->signerCert,
|
| - time,
|
| - &certIDWasConsumed,
|
| - &rvCache);
|
| - if (certIDWasConsumed) {
|
| - cid->certID = NULL;
|
| + rv = ocsp_GetVerifiedSingleResponseForCertID(response->handle,
|
| + response->nssOCSPResponse,
|
| + cid->certID,
|
| + response->signerCert,
|
| + time, &single);
|
| + if (rv == SECSuccess) {
|
| + /*
|
| + * Check whether the status says revoked, and if so
|
| + * how that compares to the time value passed into this routine.
|
| + */
|
| + rv = ocsp_CertHasGoodStatus(single->certStatus, time);
|
| }
|
|
|
| + if (rv == SECSuccess || allowCachingOfFailures) {
|
| + /* allowed to update the cache */
|
| + PRBool certIDWasConsumed = PR_FALSE;
|
| +
|
| + if (single) {
|
| + ocsp_CacheSingleResponse(cid->certID,single,
|
| + &certIDWasConsumed);
|
| + } else {
|
| + cert_RememberOCSPProcessingFailure(cid->certID,
|
| + &certIDWasConsumed);
|
| + }
|
| +
|
| + if (certIDWasConsumed) {
|
| + cid->certID = NULL;
|
| + }
|
| + }
|
| +
|
| if (rv == SECSuccess) {
|
| *pPassed = PKIX_TRUE;
|
| *pReturnCode = 0;
|
|
|