revoke.c
来自「samba最新软件」· C语言 代码 · 共 1,527 行 · 第 1/3 页
C
1,527 行
ret = RAND_bytes(es->val[0].extnValue.data, es->val[0].extnValue.length); if (ret != 1) { ret = HX509_CRYPTO_INTERNAL_ERROR; goto out; } ret = der_copy_octet_string(nonce, &es->val[0].extnValue); if (ret) { ret = ENOMEM; goto out; } } ASN1_MALLOC_ENCODE(OCSPRequest, request->data, request->length, &req, &size, ret); free_OCSPRequest(&req); if (ret) goto out; if (size != request->length) _hx509_abort("internal ASN.1 encoder error"); return 0;out: free_OCSPRequest(&req); return ret;}static char *printable_time(time_t t){ static char s[128]; strlcpy(s, ctime(&t)+ 4, sizeof(s)); s[20] = 0; return s;}/** * Print the OCSP reply stored in a file. * * @param context a hx509 context * @param path path to a file with a OCSP reply * @param out the out FILE descriptor to print the reply on * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_revoke */inthx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out){ struct revoke_ocsp ocsp; int ret, i; if (out == NULL) out = stdout; memset(&ocsp, 0, sizeof(ocsp)); ocsp.path = strdup(path); if (ocsp.path == NULL) return ENOMEM; ret = load_ocsp(context, &ocsp); if (ret) { free_ocsp(&ocsp); return ret; } fprintf(out, "signer: "); switch(ocsp.ocsp.tbsResponseData.responderID.element) { case choice_OCSPResponderID_byName: { hx509_name n; char *s; _hx509_name_from_Name(&ocsp.ocsp.tbsResponseData.responderID.u.byName, &n); hx509_name_to_string(n, &s); hx509_name_free(&n); fprintf(out, " byName: %s\n", s); free(s); break; } case choice_OCSPResponderID_byKey: { char *s; hex_encode(ocsp.ocsp.tbsResponseData.responderID.u.byKey.data, ocsp.ocsp.tbsResponseData.responderID.u.byKey.length, &s); fprintf(out, " byKey: %s\n", s); free(s); break; } default: _hx509_abort("choice_OCSPResponderID unknown"); break; } fprintf(out, "producedAt: %s\n", printable_time(ocsp.ocsp.tbsResponseData.producedAt)); fprintf(out, "replies: %d\n", ocsp.ocsp.tbsResponseData.responses.len); for (i = 0; i < ocsp.ocsp.tbsResponseData.responses.len; i++) { const char *status; switch (ocsp.ocsp.tbsResponseData.responses.val[i].certStatus.element) { case choice_OCSPCertStatus_good: status = "good"; break; case choice_OCSPCertStatus_revoked: status = "revoked"; break; case choice_OCSPCertStatus_unknown: status = "unknown"; break; default: status = "element unknown"; } fprintf(out, "\t%d. status: %s\n", i, status); fprintf(out, "\tthisUpdate: %s\n", printable_time(ocsp.ocsp.tbsResponseData.responses.val[i].thisUpdate)); if (ocsp.ocsp.tbsResponseData.responses.val[i].nextUpdate) fprintf(out, "\tproducedAt: %s\n", printable_time(ocsp.ocsp.tbsResponseData.responses.val[i].thisUpdate)); } fprintf(out, "appended certs:\n"); if (ocsp.certs) ret = hx509_certs_iter(context, ocsp.certs, hx509_ci_print_names, out); free_ocsp(&ocsp); return ret;}/** * Verify that the certificate is part of the OCSP reply and it's not * expired. Doesn't verify signature the OCSP reply or it's done by a * authorized sender, that is assumed to be already done. * * @param context a hx509 context * @param now the time right now, if 0, use the current time. * @param cert the certificate to verify * @param flags flags control the behavior * @param data pointer to the encode ocsp reply * @param length the length of the encode ocsp reply * @param expiration return the time the OCSP will expire and need to * be rechecked. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_verify */inthx509_ocsp_verify(hx509_context context, time_t now, hx509_cert cert, int flags, const void *data, size_t length, time_t *expiration){ const Certificate *c = _hx509_get_cert(cert); OCSPBasicOCSPResponse basic; int ret, i; if (now == 0) now = time(NULL); *expiration = 0; ret = parse_ocsp_basic(data, length, &basic); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to parse OCSP response"); return ret; } for (i = 0; i < basic.tbsResponseData.responses.len; i++) { ret = der_heim_integer_cmp(&basic.tbsResponseData.responses.val[i].certID.serialNumber, &c->tbsCertificate.serialNumber); if (ret != 0) continue; /* verify issuer hashes hash */ ret = _hx509_verify_signature(context, NULL, &basic.tbsResponseData.responses.val[i].certID.hashAlgorithm, &c->tbsCertificate.issuer._save, &basic.tbsResponseData.responses.val[i].certID.issuerNameHash); if (ret != 0) continue; switch (basic.tbsResponseData.responses.val[i].certStatus.element) { case choice_OCSPCertStatus_good: break; case choice_OCSPCertStatus_revoked: case choice_OCSPCertStatus_unknown: continue; } /* don't allow the update to be in the future */ if (basic.tbsResponseData.responses.val[i].thisUpdate > now + context->ocsp_time_diff) continue; /* don't allow the next update to be in the past */ if (basic.tbsResponseData.responses.val[i].nextUpdate) { if (*basic.tbsResponseData.responses.val[i].nextUpdate < now) continue; *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate; } else *expiration = now; free_OCSPBasicOCSPResponse(&basic); return 0; } free_OCSPBasicOCSPResponse(&basic); { hx509_name name; char *subject; ret = hx509_cert_get_subject(cert, &name); if (ret) { hx509_clear_error_string(context); goto out; } ret = hx509_name_to_string(name, &subject); hx509_name_free(&name); if (ret) { hx509_clear_error_string(context); goto out; } hx509_set_error_string(context, 0, HX509_CERT_NOT_IN_OCSP, "Certificate %s not in OCSP response " "or not good", subject); free(subject); }out: return HX509_CERT_NOT_IN_OCSP;}struct hx509_crl { hx509_certs revoked; time_t expire;};/** * Create a CRL context. Use hx509_crl_free() to free the CRL context. * * @param context a hx509 context. * @param crl return pointer to a newly allocated CRL context. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_verify */inthx509_crl_alloc(hx509_context context, hx509_crl *crl){ int ret; *crl = calloc(1, sizeof(**crl)); if (*crl == NULL) { hx509_set_error_string(context, 0, ENOMEM, "out of memory"); return ENOMEM; } ret = hx509_certs_init(context, "MEMORY:crl", 0, NULL, &(*crl)->revoked); if (ret) { free(*crl); *crl = NULL; return ret; } (*crl)->expire = 0; return ret;}/** * Add revoked certificate to an CRL context. * * @param context a hx509 context. * @param crl the CRL to add the revoked certificate to. * @param certs keyset of certificate to revoke. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_verify */inthx509_crl_add_revoked_certs(hx509_context context, hx509_crl crl, hx509_certs certs){ return hx509_certs_merge(context, crl->revoked, certs);}/** * Set the lifetime of a CRL context. * * @param context a hx509 context. * @param crl a CRL context * @param delta delta time the certificate is valid, library adds the * current time to this. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_verify */inthx509_crl_lifetime(hx509_context context, hx509_crl crl, int delta){ crl->expire = time(NULL) + delta; return 0;}/** * Free a CRL context. * * @param context a hx509 context. * @param crl a CRL context to free. * * @ingroup hx509_verify */voidhx509_crl_free(hx509_context context, hx509_crl *crl){ if (*crl == NULL) return; hx509_certs_free(&(*crl)->revoked); memset(*crl, 0, sizeof(**crl)); free(*crl); *crl = NULL;}static intadd_revoked(hx509_context context, void *ctx, hx509_cert cert){ TBSCRLCertList *c = ctx; unsigned int num; void *ptr; int ret; num = c->revokedCertificates->len; ptr = realloc(c->revokedCertificates->val, (num + 1) * sizeof(c->revokedCertificates->val[0])); if (ptr == NULL) { hx509_clear_error_string(context); return ENOMEM; } c->revokedCertificates->val = ptr; ret = hx509_cert_get_serialnumber(cert, &c->revokedCertificates->val[num].userCertificate); if (ret) { hx509_clear_error_string(context); return ret; } c->revokedCertificates->val[num].revocationDate.element = choice_Time_generalTime; c->revokedCertificates->val[num].revocationDate.u.generalTime = time(NULL) - 3600 * 24; c->revokedCertificates->val[num].crlEntryExtensions = NULL; c->revokedCertificates->len++; return 0;} /** * Sign a CRL and return an encode certificate. * * @param context a hx509 context. * @param signer certificate to sign the CRL with * @param crl the CRL to sign * @param os return the signed and encoded CRL, free with * free_heim_octet_string() * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_verify */inthx509_crl_sign(hx509_context context, hx509_cert signer, hx509_crl crl, heim_octet_string *os){ const AlgorithmIdentifier *sigalg = _hx509_crypto_default_sig_alg; CRLCertificateList c; size_t size; int ret; hx509_private_key signerkey; memset(&c, 0, sizeof(c)); signerkey = _hx509_cert_private_key(signer); if (signerkey == NULL) { ret = HX509_PRIVATE_KEY_MISSING; hx509_set_error_string(context, 0, ret, "Private key missing for CRL signing"); return ret; } c.tbsCertList.version = malloc(sizeof(*c.tbsCertList.version)); if (c.tbsCertList.version == NULL) { hx509_set_error_string(context, 0, ENOMEM, "out of memory"); return ENOMEM; } *c.tbsCertList.version = 1; ret = copy_AlgorithmIdentifier(sigalg, &c.tbsCertList.signature); if (ret) { hx509_clear_error_string(context); goto out; } ret = copy_Name(&_hx509_get_cert(signer)->tbsCertificate.issuer, &c.tbsCertList.issuer); if (ret) { hx509_clear_error_string(context); goto out; } c.tbsCertList.thisUpdate.element = choice_Time_generalTime; c.tbsCertList.thisUpdate.u.generalTime = time(NULL) - 24 * 3600; c.tbsCertList.nextUpdate = malloc(sizeof(*c.tbsCertList.nextUpdate)); if (c.tbsCertList.nextUpdate == NULL) { hx509_set_error_string(context, 0, ENOMEM, "out of memory"); ret = ENOMEM; goto out; } { time_t next = crl->expire; if (next == 0) next = time(NULL) + 24 * 3600 * 365; c.tbsCertList.nextUpdate->element = choice_Time_generalTime; c.tbsCertList.nextUpdate->u.generalTime = next; } c.tbsCertList.revokedCertificates = calloc(1, sizeof(*c.tbsCertList.revokedCertificates)); if (c.tbsCertList.revokedCertificates == NULL) { hx509_set_error_string(context, 0, ENOMEM, "out of memory"); ret = ENOMEM; goto out; } c.tbsCertList.crlExtensions = NULL; ret = hx509_certs_iter(context, crl->revoked, add_revoked, &c.tbsCertList); if (ret) goto out; /* if not revoked certs, remove OPTIONAL entry */ if (c.tbsCertList.revokedCertificates->len == 0) { free(c.tbsCertList.revokedCertificates); c.tbsCertList.revokedCertificates = NULL; } ASN1_MALLOC_ENCODE(TBSCRLCertList, os->data, os->length, &c.tbsCertList, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "failed to encode tbsCRL"); goto out; } if (size != os->length) _hx509_abort("internal ASN.1 encoder error"); ret = _hx509_create_signature_bitstring(context, signerkey, sigalg, os, &c.signatureAlgorithm, &c.signatureValue); free(os->data); ASN1_MALLOC_ENCODE(CRLCertificateList, os->data, os->length, &c, &size, ret); free_CRLCertificateList(&c); if (ret) { hx509_set_error_string(context, 0, ret, "failed to encode CRL"); goto out; } if (size != os->length) _hx509_abort("internal ASN.1 encoder error"); return 0;out: free_CRLCertificateList(&c); return ret;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?