📄 ocsp.c
字号:
#endif switch (status) { case CERT_GOOD: DBG(DBG_CONTROL, DBG_log("certificate is good") ) /* with strict crl policy the public key must have the * same lifetime as the validity of the ocsp status */ if (strict && nextUpdate < *until) *until = nextUpdate; break; case CERT_REVOKED: plog("certificate is revoked"); remove_x509_public_key(cert); return FALSE; case CERT_UNKNOWN: plog("certificate status unkown"); if (strict) { remove_x509_public_key(cert); return FALSE; } break; } return TRUE;}/* * check if an ocsp status is about to expire */voidcheck_ocsp(void){ ocsp_location_t *location; lock_ocsp_cache("check_ocsp"); location = ocsp_cache; while (location != NULL) { char buf[BUF_LEN]; bool first = TRUE; ocsp_certinfo_t *certinfo = location->certinfo; while (certinfo != NULL) { if (!certinfo->once) { time_t time_left = certinfo->nextUpdate - time(NULL); DBG(DBG_CONTROL, if (first) { dntoa(buf, BUF_LEN, location->issuer); DBG_log("issuer: '%s'", buf); if (location->authKeyID.ptr != NULL) { datatot(location->authKeyID.ptr, location->authKeyID.len , ':', buf, BUF_LEN); DBG_log("authkey: %s", buf); } first = FALSE; } datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len , ':', buf, BUF_LEN); DBG_log("serial: %s, %ld seconds left", buf, time_left) )#ifdef HAVE_THREADS if (time_left < 2*crl_check_interval) add_ocsp_fetch_request(location, certinfo->serialNumber);#endif } certinfo = certinfo->next; } location = location->next; } unlock_ocsp_cache("check_ocsp");}/* * sets the default uri */voidocsp_set_default_uri(char *uri){ ocsp_default_uri = empty_chunk; if (uri == NULL) return; if (strncasecmp(uri, "http", 4) != 0) { plog("warning: ignoring default ocsp uri with unkown protocol"); return; } clonetochunk(ocsp_default_uri, uri, strlen(uri), "ocsp default uri");}/* * frees the allocated memory of a certinfo struct */static voidfree_certinfo(ocsp_certinfo_t *certinfo){ freeanychunk(certinfo->serialNumber); pfree(certinfo);}/* * frees all certinfos in a chained list */static voidfree_certinfos(ocsp_certinfo_t *chain){ ocsp_certinfo_t *certinfo; while (chain != NULL) { certinfo = chain; chain = chain->next; free_certinfo(certinfo); }}/* * frees the memory allocated to an ocsp location including all certinfos */static voidfree_ocsp_location(ocsp_location_t* location){ freeanychunk(location->issuer); freeanychunk(location->authNameID); freeanychunk(location->authKeyID); freeanychunk(location->authKeySerialNumber); freeanychunk(location->uri); free_certinfos(location->certinfo); pfree(location);}/* * free a chained list of ocsp locations */voidfree_ocsp_locations(ocsp_location_t **chain){ while (*chain != NULL) { ocsp_location_t *location = *chain; *chain = location->next; free_ocsp_location(location); }}/* * free the ocsp cache */voidfree_ocsp_cache(void){ lock_ocsp_cache("free_ocsp_cache"); free_ocsp_locations(&ocsp_cache); unlock_ocsp_cache("free_ocsp_cache");}/* * frees the ocsp cache and global variables */voidfree_ocsp(void){ pfreeany(ocsp_default_uri.ptr); free_ocsp_cache();}/* * list a chained list of ocsp_locations */voidlist_ocsp_locations(ocsp_location_t *location, bool requests, bool utc, bool strict){ bool first = TRUE; while (location != NULL) { ocsp_certinfo_t *certinfo = location->certinfo; if (certinfo != NULL) { u_char buf[BUF_LEN]; if (first) { whack_log(RC_COMMENT, " "); whack_log(RC_COMMENT, "List of OCSP %s:", requests? "fetch requests":"responses"); first = FALSE; } whack_log(RC_COMMENT, " "); if (location->issuer.ptr != NULL) { dntoa(buf, BUF_LEN, location->issuer); whack_log(RC_COMMENT, " issuer: '%s'", buf); } whack_log(RC_COMMENT, " uri: '%.*s", (int)location->uri.len , location->uri.ptr); if (location->authNameID.ptr != NULL) { datatot(location->authNameID.ptr, location->authNameID.len, ':' , buf, BUF_LEN); whack_log(RC_COMMENT, " authname: %s", buf); } if (location->authKeyID.ptr != NULL) { datatot(location->authKeyID.ptr, location->authKeyID.len, ':' , buf, BUF_LEN); whack_log(RC_COMMENT, " authkey: %s", buf); } if (location->authKeySerialNumber.ptr != NULL) { datatot(location->authKeySerialNumber.ptr , location->authKeySerialNumber.len, ':', buf, BUF_LEN); whack_log(RC_COMMENT, " aserial: %s", buf); } while (certinfo != NULL) { char thisUpdate[TIMETOA_BUF]; timetoa(&certinfo->thisUpdate, utc, thisUpdate, sizeof(thisUpdate)); if (requests) { whack_log(RC_COMMENT, "%s, trials: %d", thisUpdate , certinfo->trials); } else if (certinfo->once) { whack_log(RC_COMMENT, "%s, onetime use%s", thisUpdate , (certinfo->nextUpdate < time(NULL))? " (expired)": ""); } else { char tbuf2[TIMETOA_BUF]; whack_log(RC_COMMENT, "%s, until %s %s", thisUpdate , timetoa(&certinfo->nextUpdate, utc, tbuf2, sizeof(tbuf2)) , check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict)); } datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len, ':' , buf, BUF_LEN); whack_log(RC_COMMENT, " serial: %s, %s", buf , cert_status_names[certinfo->status]); certinfo = certinfo->next; } } location = location->next; }}/* * list the ocsp cache */voidlist_ocsp_cache(bool utc, bool strict){ lock_ocsp_cache("list_ocsp_cache"); list_ocsp_locations(ocsp_cache, FALSE, utc, strict); unlock_ocsp_cache("list_ocsp_cache");}/* moves a chunk to a memory position, chunk is freed afterwards * position pointer is advanced after the insertion point */static voidmv_chunk(u_char **pos, chunk_t content){ if (content.len > 0) { chunkcpy(*pos, content); freeanychunk(content); }}static boolget_ocsp_requestor_cert(ocsp_location_t *location){ x509cert_t *cert = NULL; /* initialize temporary static storage */ ocsp_requestor_cert = NULL; ocsp_requestor_sc = NULL; ocsp_requestor_pri = NULL; for (;;) { char buf[BUF_LEN]; /* looking for a certificate from the same issuer */ cert = get_x509cert(location->issuer, location->authKeySerialNumber ,location->authKeyID, cert); if (cert == NULL) break; DBG(DBG_CONTROL, dntoa(buf, BUF_LEN, cert->subject); DBG_log("candidate: '%s'", buf); ) if (cert->smartcard) {#ifdef SMARTCARD /* look for a matching private key on a smartcard */ smartcard_t *sc = scx_get(cert); if (sc != NULL) { DBG(DBG_CONTROL, DBG_log("matching smartcard found") ) if (sc->valid) { ocsp_requestor_cert = cert; ocsp_requestor_sc = sc; return TRUE; } plog("unable to sign ocsp request without PIN"); }#endif } else { /* look for a matching private key in the chained list */ const struct RSA_private_key *pri = get_x509_private_key(cert); if (pri != NULL) { DBG(DBG_CONTROL, DBG_log("matching private key found") ) ocsp_requestor_cert = cert; ocsp_requestor_pri = pri; return TRUE; } } } return FALSE;}static chunk_tgenerate_signature(chunk_t digest, smartcard_t *sc , const struct RSA_private_key *pri){ chunk_t sigdata; u_char *pos; size_t siglen = 0; if (sc != NULL) { /* RSA signature is done on smartcard */#ifdef SMARTCARD if (!scx_establish_context(sc->reader)) { scx_release_context(); return empty_chunk; } siglen = scx_get_keylength(sc) / BITS_PER_BYTE; if (siglen == 0) { plog("failed to get keylength from smartcard"); scx_release_context(); return empty_chunk; } DBG(DBG_CONTROL | DBG_CRYPT, DBG_log("signing hash with RSA key from smartcard (reader: %d, id: %s)" , sc->reader, sc->id) ) pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); *pos++ = 0x00; scx_sign_hash(sc, digest.ptr, digest.len, pos, siglen); scx_release_context();#endif } else { /* RSA signature is done in software */ siglen = pri->pub.k; pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); *pos++ = 0x00; sign_hash(pri, digest.ptr, digest.len, pos, siglen); } return sigdata;}/* * build signature into ocsp request * gets built only if a request cert with * a corresponding private key is found */static chunk_tbuild_signature(chunk_t tbsRequest){ chunk_t signature, sigdata, certs; chunk_t digest, digest_info; u_char *pos; u_char digest_buf[MAX_DIGEST_LEN]; chunk_t digest_raw = { digest_buf, MAX_DIGEST_LEN }; if (!compute_digest(tbsRequest, OID_SHA1_WITH_RSA, &digest_raw)) return empty_chunk; /* according to PKCS#1 v2.1 digest must be packaged into * an ASN.1 structure for encryption */ pos = build_asn1_object(&digest, ASN1_OCTET_STRING , digest_raw.len); chunkcpy(pos, digest_raw); pos = build_asn1_object(&digest_info, ASN1_SEQUENCE , sizeof(ASN1_sha1_id) + digest.len); constcpy( pos, ASN1_sha1_id); mv_chunk(&pos, digest); /* generate the RSA signature */ sigdata = generate_signature(digest_info , ocsp_requestor_sc , ocsp_requestor_pri); freeanychunk(digest_info); /* has the RSA signature generation been successful? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -