int SslOcspStapling::getCertId(X509 *pCert) { int i, n; X509 *pXissuer; X509_STORE *pXstore; STACK_OF(X509) *pXchain; X509_STORE_CTX *pXstore_ctx; pXchain = m_pCtx->extra_certs; n = sk_X509_num(pXchain); for (i = 0; i < n; i++) { pXissuer = sk_X509_value(pXchain, i); if (X509_check_issued(pXissuer, pCert) == X509_V_OK) { CRYPTO_add(&pXissuer->references, 1, CRYPTO_LOCK_X509); m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer); X509_free(pXissuer); return 0; } } pXstore = SSL_CTX_get_cert_store(m_pCtx); if (pXstore == NULL) { setLastErrMsg("SSL_CTX_get_cert_store failed!\n"); return LS_FAIL; } pXstore_ctx = X509_STORE_CTX_new(); if (pXstore_ctx == NULL) { setLastErrMsg("X509_STORE_CTX_new failed!\n"); return LS_FAIL; } if (X509_STORE_CTX_init(pXstore_ctx, pXstore, NULL, NULL) == 0) { setLastErrMsg("X509_STORE_CTX_init failed!\n"); return LS_FAIL; } n = X509_STORE_CTX_get1_issuer(&pXissuer, pXstore_ctx, pCert); X509_STORE_CTX_free(pXstore_ctx); if ((n == -1) || (n == 0)) { setLastErrMsg("X509_STORE_CTX_get1_issuer failed!\n"); return LS_FAIL; } m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer); X509_free(pXissuer); return 0; }
int SslOcspStapling::init(SSL_CTX *pSslCtx) { int iResult; X509 *pCert; struct stat st; m_pCtx = pSslCtx; pCert = NULL; iResult = -1; if (::stat(m_sRespfileTmp.c_str(), &st) == 0) { if ((st.st_mtime + 30) <= time(NULL)) unlink(m_sRespfileTmp.c_str()); } //SSL_CTX_set_default_verify_paths( m_pCtx ); pCert = load_cert(m_sCertfile.c_str()); if (pCert == NULL) { setLastErrMsg("Failed to load file: %s!\n", m_sCertfile.c_str()); return LS_FAIL; } if ((getCertId(pCert) == 0) && (getResponder(pCert) == 0)) { m_addrResponder.setHttpUrl(m_sOcspResponder.c_str(), m_sOcspResponder.len()); iResult = 0; //update(); } X509_free(pCert); return iResult; }
int SslOcspStapling::certVerify(OCSP_RESPONSE *pResponse, OCSP_BASICRESP *pBasicResp, X509_STORE *pXstore) { int n, iResult = -1; STACK_OF(X509) *pXchain; ASN1_GENERALIZEDTIME *pThisupdate, *pNextupdate; struct stat st; pXchain = m_pCtx->extra_certs; if (OCSP_basic_verify(pBasicResp, pXchain, pXstore, OCSP_NOVERIFY) == 1) { if ((m_pCertId != NULL) && (OCSP_resp_find_status(pBasicResp, m_pCertId, &n, NULL, NULL, &pThisupdate, &pNextupdate) == 1) && (n == V_OCSP_CERTSTATUS_GOOD) && (OCSP_check_validity(pThisupdate, pNextupdate, 300, -1) == 1)) { iResult = 0; updateRespData(pResponse); unlink(m_sRespfile.c_str()); rename(m_sRespfileTmp.c_str(), m_sRespfile.c_str()); if (::stat(m_sRespfile.c_str(), &st) == 0) m_RespTime = st.st_mtime; } } if (iResult) { setLastErrMsg("%s", SSLError().what()); ERR_clear_error(); if (m_pHttpFetch) m_pHttpFetch->writeLog(s_ErrMsg.c_str()); } return iResult; }
int SslOcspStapling::createRequest() { int len, len64, n1; unsigned char *pReqData, *pReqData64; unsigned char ReqData[4000], ReqData64[4000]; struct stat st; if (::stat(m_sRespfileTmp.c_str(), &st) == 0) return 0; pReqData = ReqData; pReqData64 = ReqData64; len = getRequestData(pReqData); if (len <= 0) return LS_FAIL; len64 = ls_base64_encode((const char *)ReqData, len, (char *)pReqData64); const char *pUrl = m_sOcspResponder.c_str(); memcpy(pReqData, pUrl, m_sOcspResponder.len()); pReqData += m_sOcspResponder.len(); if (pUrl[m_sOcspResponder.len() - 1] != '/') *pReqData++ = '/'; n1 = escapeBase64Uri(pReqData64, len64, pReqData); pReqData += n1; *pReqData = 0; len = pReqData - ReqData; if (m_pHttpFetch != NULL) delete m_pHttpFetch; m_pHttpFetch = new HttpFetch(); m_pHttpFetch->setResProcessor(OcspRespCb, this); m_pHttpFetch->setTimeout(30); //Set Req timeout as 30 seconds m_pHttpFetch->startReq((const char *)ReqData, 1, 1, NULL, 0, m_sRespfileTmp.c_str(), NULL, m_addrResponder); setLastErrMsg("%lu, len = %d\n%s \n", m_pHttpFetch, len, ReqData); //printf("%s\n", s_ErrMsg.c_str()); return 0; }
int SslOcspStapling::processResponse(HttpFetch *pHttpFetch) { struct stat st; const char *pRespContentType; //assert( pHttpFetch == m_pHttpFetch ); int istatusCode = m_pHttpFetch->getStatusCode() ; pRespContentType = m_pHttpFetch->getRespContentType(); if ((istatusCode == 200) && (strcasecmp(pRespContentType, "application/ocsp-response") == 0)) verifyRespFile(); else { setLastErrMsg("Received bad OCSP response. ReponderUrl=%s, StatusCode=%d, ContentType=%s\n", m_sOcspResponder.c_str(), istatusCode, ((pRespContentType) ? (pRespContentType) : (""))); //printf("%s\n", s_ErrMsg.c_str()); m_pHttpFetch->writeLog(s_ErrMsg.c_str()); } if (::stat(m_sRespfileTmp.c_str(), &st) == 0) unlink(m_sRespfileTmp.c_str()); return 0; }
int SslOcspStapling::getResponder(X509 *pCert) { char *pUrl; X509 *pCAt; STACK_OF(X509) *pXchain; int i; int n; #if OPENSSL_VERSION_NUMBER >= 0x10000003L STACK_OF(OPENSSL_STRING) *strResp; #else STACK *strResp; #endif if (m_sOcspResponder.c_str()) return 0; strResp = X509_get1_ocsp(pCert); if (strResp == NULL) { pXchain = m_pCtx->extra_certs; n = sk_X509_num(pXchain); for (i = 0; i < n; i++) { pCert = sk_X509_value(pXchain, i); strResp = X509_get1_ocsp(pCert); if (strResp) break; } } if (strResp == NULL) { if (m_sCAfile.c_str() == NULL) return LS_FAIL; pCAt = load_cert(m_sCAfile.c_str()); if (pCAt == NULL) { setLastErrMsg("Failed to load file: %s!\n", m_sCAfile.c_str()); return LS_FAIL; } strResp = X509_get1_ocsp(pCAt); X509_free(pCAt); if (strResp == NULL) { setLastErrMsg("Failed to get responder!\n"); return LS_FAIL; } } #if OPENSSL_VERSION_NUMBER >= 0x1000004fL pUrl = sk_OPENSSL_STRING_value(strResp, 0); #elif OPENSSL_VERSION_NUMBER >= 0x10000003L pUrl = (char *)sk_value((const _STACK *) strResp, 0); #else pUrl = (char *)sk_value((const STACK *) strResp, 0); #endif if (pUrl) { m_sOcspResponder.setStr(pUrl); return 0; } X509_email_free(strResp); setLastErrMsg("Failed to get responder Url!\n"); return LS_FAIL; }