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 + -
显示快捷键?