⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 revoke.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2006 - 2007 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden).  * All rights reserved.  * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * * 3. Neither the name of the Institute nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  * SUCH DAMAGE.  *//** * @page page_revoke Revocation methods * * There are two revocation method for PKIX/X.509: CRL and OCSP. * Revocation is needed if the private key is lost and * stolen. Depending on how picky you are, you might want to make * revocation for destroyed private keys too (smartcard broken), but * that should not be a problem. * * CRL is a list of certifiates that have expired. * * OCSP is an online checking method where the requestor sends a list * of certificates to the OCSP server to return a signed reply if they * are valid or not. Some services sends a OCSP reply as part of the * hand-shake to make the revoktion decision simpler/faster for the * client. */#include "hx_locl.h"RCSID("$Id: revoke.c 22583 2008-02-11 20:46:21Z lha $");struct revoke_crl {    char *path;    time_t last_modfied;    CRLCertificateList crl;    int verified;    int failed_verify;};struct revoke_ocsp {    char *path;    time_t last_modfied;    OCSPBasicOCSPResponse ocsp;    hx509_certs certs;    hx509_cert signer;};struct hx509_revoke_ctx_data {    unsigned ref;    struct {	struct revoke_crl *val;	size_t len;    } crls;    struct {	struct revoke_ocsp *val;	size_t len;    } ocsps;};/** * Allocate a revokation context. Free with hx509_revoke_free(). * * @param context A hx509 context. * @param ctx returns a newly allocated revokation context. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_revoke */inthx509_revoke_init(hx509_context context, hx509_revoke_ctx *ctx){    *ctx = calloc(1, sizeof(**ctx));    if (*ctx == NULL)	return ENOMEM;    (*ctx)->ref = 1;    (*ctx)->crls.len = 0;    (*ctx)->crls.val = NULL;    (*ctx)->ocsps.len = 0;    (*ctx)->ocsps.val = NULL;    return 0;}hx509_revoke_ctx_hx509_revoke_ref(hx509_revoke_ctx ctx){    if (ctx == NULL)	return NULL;    if (ctx->ref <= 0)	_hx509_abort("revoke ctx refcount <= 0");    ctx->ref++;    if (ctx->ref == 0)	_hx509_abort("revoke ctx refcount == 0");    return ctx;}static voidfree_ocsp(struct revoke_ocsp *ocsp){    free(ocsp->path);    free_OCSPBasicOCSPResponse(&ocsp->ocsp);    hx509_certs_free(&ocsp->certs);    hx509_cert_free(ocsp->signer);}/** * Free a hx509 revokation context. * * @param ctx context to be freed * * @ingroup hx509_revoke */voidhx509_revoke_free(hx509_revoke_ctx *ctx){    size_t i ;    if (ctx == NULL || *ctx == NULL)	return;    if ((*ctx)->ref <= 0)	_hx509_abort("revoke ctx refcount <= 0 on free");    if (--(*ctx)->ref > 0)	return;    for (i = 0; i < (*ctx)->crls.len; i++) {	free((*ctx)->crls.val[i].path);	free_CRLCertificateList(&(*ctx)->crls.val[i].crl);    }    for (i = 0; i < (*ctx)->ocsps.len; i++)	free_ocsp(&(*ctx)->ocsps.val[i]);    free((*ctx)->ocsps.val);    free((*ctx)->crls.val);    memset(*ctx, 0, sizeof(**ctx));    free(*ctx);    *ctx = NULL;}static intverify_ocsp(hx509_context context,	    struct revoke_ocsp *ocsp,	    time_t time_now,	    hx509_certs certs,	    hx509_cert parent){    hx509_cert signer = NULL;    hx509_query q;    int ret;	    _hx509_query_clear(&q);	    /*     * Need to match on issuer too in case there are two CA that have     * issued the same name to a certificate. One example of this is     * the www.openvalidation.org test's ocsp validator.     */    q.match = HX509_QUERY_MATCH_ISSUER_NAME;    q.issuer_name = &_hx509_get_cert(parent)->tbsCertificate.issuer;    switch(ocsp->ocsp.tbsResponseData.responderID.element) {    case choice_OCSPResponderID_byName:	q.match |= HX509_QUERY_MATCH_SUBJECT_NAME;	q.subject_name = &ocsp->ocsp.tbsResponseData.responderID.u.byName;	break;    case choice_OCSPResponderID_byKey:	q.match |= HX509_QUERY_MATCH_KEY_HASH_SHA1;	q.keyhash_sha1 = &ocsp->ocsp.tbsResponseData.responderID.u.byKey;	break;    }	    ret = hx509_certs_find(context, certs, &q, &signer);    if (ret && ocsp->certs)	ret = hx509_certs_find(context, ocsp->certs, &q, &signer);    if (ret)	goto out;    /*     * If signer certificate isn't the CA certificate, lets check the     * it is the CA that signed the signer certificate and the OCSP EKU     * is set.     */    if (hx509_cert_cmp(signer, parent) != 0) {	Certificate *p = _hx509_get_cert(parent);	Certificate *s = _hx509_get_cert(signer);	ret = _hx509_cert_is_parent_cmp(s, p, 0);	if (ret != 0) {	    ret = HX509_PARENT_NOT_CA;	    hx509_set_error_string(context, 0, ret, "Revoke OSCP signer is "				   "doesn't have CA as signer certificate");	    goto out;	}	ret = _hx509_verify_signature_bitstring(context,						p,						&s->signatureAlgorithm,						&s->tbsCertificate._save,						&s->signatureValue);	if (ret) {	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,				   "OSCP signer signature invalid");	    goto out;	}	ret = hx509_cert_check_eku(context, signer, 				   oid_id_pkix_kp_OCSPSigning(), 0);	if (ret)	    goto out;    }    ret = _hx509_verify_signature_bitstring(context,					    _hx509_get_cert(signer), 					    &ocsp->ocsp.signatureAlgorithm,					    &ocsp->ocsp.tbsResponseData._save,					    &ocsp->ocsp.signature);    if (ret) {	hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 			       "OSCP signature invalid");	goto out;    }    ocsp->signer = signer;    signer = NULL;out:    if (signer)	hx509_cert_free(signer);    return ret;}/* * */static intparse_ocsp_basic(const void *data, size_t length, OCSPBasicOCSPResponse *basic){    OCSPResponse resp;    size_t size;    int ret;    memset(basic, 0, sizeof(*basic));    ret = decode_OCSPResponse(data, length, &resp, &size);    if (ret)	return ret;    if (length != size) {	free_OCSPResponse(&resp);	return ASN1_EXTRA_DATA;    }    switch (resp.responseStatus) {    case successful:	break;    default:	free_OCSPResponse(&resp);	return HX509_REVOKE_WRONG_DATA;    }    if (resp.responseBytes == NULL) {	free_OCSPResponse(&resp);	return EINVAL;    }    ret = der_heim_oid_cmp(&resp.responseBytes->responseType, 			   oid_id_pkix_ocsp_basic());    if (ret != 0) {	free_OCSPResponse(&resp);	return HX509_REVOKE_WRONG_DATA;    }    ret = decode_OCSPBasicOCSPResponse(resp.responseBytes->response.data,				       resp.responseBytes->response.length,				       basic,				       &size);    if (ret) {	free_OCSPResponse(&resp);	return ret;    }    if (size != resp.responseBytes->response.length) {	free_OCSPResponse(&resp);	free_OCSPBasicOCSPResponse(basic);	return ASN1_EXTRA_DATA;    }    free_OCSPResponse(&resp);    return 0;}/* * */static intload_ocsp(hx509_context context, struct revoke_ocsp *ocsp){    OCSPBasicOCSPResponse basic;    hx509_certs certs = NULL;    size_t length;    struct stat sb;    void *data;    int ret;    ret = _hx509_map_file(ocsp->path, &data, &length, &sb);    if (ret)	return ret;    ret = parse_ocsp_basic(data, length, &basic);    _hx509_unmap_file(data, length);    if (ret) {	hx509_set_error_string(context, 0, ret,			       "Failed to parse OCSP response");	return ret;    }    if (basic.certs) {	int i;	ret = hx509_certs_init(context, "MEMORY:ocsp-certs", 0, 			       NULL, &certs);	if (ret) {	    free_OCSPBasicOCSPResponse(&basic);	    return ret;	}	for (i = 0; i < basic.certs->len; i++) {	    hx509_cert c;	    	    ret = hx509_cert_init(context, &basic.certs->val[i], &c);	    if (ret)		continue;	    	    ret = hx509_certs_add(context, certs, c);	    hx509_cert_free(c);	    if (ret)		continue;	}    }    ocsp->last_modfied = sb.st_mtime;    free_OCSPBasicOCSPResponse(&ocsp->ocsp);    hx509_certs_free(&ocsp->certs);    hx509_cert_free(ocsp->signer);    ocsp->ocsp = basic;    ocsp->certs = certs;    ocsp->signer = NULL;    return 0;}/** * Add a OCSP file to the revokation context. * * @param context hx509 context * @param ctx hx509 revokation context * @param path path to file that is going to be added to the context. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_revoke */inthx509_revoke_add_ocsp(hx509_context context,		      hx509_revoke_ctx ctx,		      const char *path){    void *data;    int ret;    size_t i;    if (strncmp(path, "FILE:", 5) != 0) {	hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,			       "unsupport type in %s", path);	return HX509_UNSUPPORTED_OPERATION;    }    path += 5;    for (i = 0; i < ctx->ocsps.len; i++) {	if (strcmp(ctx->ocsps.val[0].path, path) == 0)	    return 0;    }    data = realloc(ctx->ocsps.val, 		   (ctx->ocsps.len + 1) * sizeof(ctx->ocsps.val[0]));    if (data == NULL) {	hx509_clear_error_string(context);	return ENOMEM;    }    ctx->ocsps.val = data;    memset(&ctx->ocsps.val[ctx->ocsps.len], 0, 	   sizeof(ctx->ocsps.val[0]));    ctx->ocsps.val[ctx->ocsps.len].path = strdup(path);    if (ctx->ocsps.val[ctx->ocsps.len].path == NULL) {	hx509_clear_error_string(context);	return ENOMEM;    }    ret = load_ocsp(context, &ctx->ocsps.val[ctx->ocsps.len]);    if (ret) {	free(ctx->ocsps.val[ctx->ocsps.len].path);	return ret;    }    ctx->ocsps.len++;    return ret;}/* * */static intverify_crl(hx509_context context,	   hx509_revoke_ctx ctx,	   CRLCertificateList *crl,	   time_t time_now,	   hx509_certs certs,	   hx509_cert parent){    hx509_cert signer;    hx509_query q;    time_t t;    int ret;	    t = _hx509_Time2time_t(&crl->tbsCertList.thisUpdate);    if (t > time_now) {	hx509_set_error_string(context, 0, HX509_CRL_USED_BEFORE_TIME,			       "CRL used before time");	return HX509_CRL_USED_BEFORE_TIME;    }    if (crl->tbsCertList.nextUpdate == NULL) {	hx509_set_error_string(context, 0, HX509_CRL_INVALID_FORMAT,			       "CRL missing nextUpdate");	return HX509_CRL_INVALID_FORMAT;    }    t = _hx509_Time2time_t(crl->tbsCertList.nextUpdate);    if (t < time_now) {	hx509_set_error_string(context, 0, HX509_CRL_USED_AFTER_TIME,			       "CRL used after time");	return HX509_CRL_USED_AFTER_TIME;    }    _hx509_query_clear(&q);	    /*     * If it's the signer have CRLSIGN bit set, use that as the signer     * cert for the certificate, otherwise, search for a certificate.     */    if (_hx509_check_key_usage(context, parent, 1 << 6, FALSE) == 0) {	signer = hx509_cert_ref(parent);    } else {	q.match = HX509_QUERY_MATCH_SUBJECT_NAME;	q.match |= HX509_QUERY_KU_CRLSIGN;	q.subject_name = &crl->tbsCertList.issuer;		ret = hx509_certs_find(context, certs, &q, &signer);	if (ret) {	    hx509_set_error_string(context, HX509_ERROR_APPEND, ret,				   "Failed to find certificate for CRL");	    return ret;	}    }    ret = _hx509_verify_signature_bitstring(context,					    _hx509_get_cert(signer), 					    &crl->signatureAlgorithm,					    &crl->tbsCertList._save,					    &crl->signatureValue);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -