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

📄 pkinit.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2003 - 2006 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.  */#include "kdc_locl.h"RCSID("$Id: pkinit.c 22243 2007-12-08 23:39:30Z lha $");#ifdef PKINIT#include <heim_asn1.h>#include <rfc2459_asn1.h>#include <cms_asn1.h>#include <pkinit_asn1.h>#include <hx509.h>#include "crypto-headers.h"/* XXX copied from lib/krb5/pkinit.c */struct krb5_pk_identity {    hx509_context hx509ctx;    hx509_verify_ctx verify_ctx;    hx509_certs certs;    hx509_certs anchors;    hx509_certs certpool;    hx509_revoke_ctx revoke;};enum pkinit_type {    PKINIT_COMPAT_WIN2K = 1,    PKINIT_COMPAT_27 = 3};struct pk_client_params {    enum pkinit_type type;    BIGNUM *dh_public_key;    hx509_cert cert;    unsigned nonce;    DH *dh;    EncryptionKey reply_key;    char *dh_group_name;    hx509_peer_info peer;    hx509_certs client_anchors;};struct pk_principal_mapping {    unsigned int len;    struct pk_allowed_princ {	krb5_principal principal;	char *subject;    } *val;};static struct krb5_pk_identity *kdc_identity;static struct pk_principal_mapping principal_mappings;static struct krb5_dh_moduli **moduli;static struct {    krb5_data data;    time_t expire;    time_t next_update;} ocsp;/* * */static krb5_error_codepk_check_pkauthenticator_win2k(krb5_context context,			       PKAuthenticator_Win2k *a,			       const KDC_REQ *req){    krb5_timestamp now;    krb5_timeofday (context, &now);    /* XXX cusec */    if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {	krb5_clear_error_string(context);	return KRB5KRB_AP_ERR_SKEW;    }    return 0;}static krb5_error_codepk_check_pkauthenticator(krb5_context context,			 PKAuthenticator *a,			 const KDC_REQ *req){    u_char *buf = NULL;    size_t buf_size;    krb5_error_code ret;    size_t len;    krb5_timestamp now;    Checksum checksum;    krb5_timeofday (context, &now);    /* XXX cusec */    if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {	krb5_clear_error_string(context);	return KRB5KRB_AP_ERR_SKEW;    }    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret);    if (ret) {	krb5_clear_error_string(context);	return ret;    }    if (buf_size != len)	krb5_abortx(context, "Internal error in ASN.1 encoder");    ret = krb5_create_checksum(context,			       NULL,			       0,			       CKSUMTYPE_SHA1,			       buf,			       len,			       &checksum);    free(buf);    if (ret) {	krb5_clear_error_string(context);	return ret;    }	    if (a->paChecksum == NULL) {	krb5_clear_error_string(context);	ret = KRB5_KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;	goto out;    }    if (der_heim_octet_string_cmp(a->paChecksum, &checksum.checksum) != 0) {	krb5_clear_error_string(context);	ret = KRB5KRB_ERR_GENERIC;    }out:    free_Checksum(&checksum);    return ret;}void_kdc_pk_free_client_param(krb5_context context, 			  pk_client_params *client_params){    if (client_params->cert)	hx509_cert_free(client_params->cert);    if (client_params->dh)	DH_free(client_params->dh);    if (client_params->dh_public_key)	BN_free(client_params->dh_public_key);    krb5_free_keyblock_contents(context, &client_params->reply_key);    if (client_params->dh_group_name)	free(client_params->dh_group_name);    if (client_params->peer)	hx509_peer_info_free(client_params->peer);    if (client_params->client_anchors)	hx509_certs_free(&client_params->client_anchors);    memset(client_params, 0, sizeof(*client_params));    free(client_params);}static krb5_error_codegenerate_dh_keyblock(krb5_context context, pk_client_params *client_params,                     krb5_enctype enctype, krb5_keyblock *reply_key){    unsigned char *dh_gen_key = NULL;    krb5_keyblock key;    krb5_error_code ret;    size_t dh_gen_keylen, size;    memset(&key, 0, sizeof(key));    if (!DH_generate_key(client_params->dh)) {	krb5_set_error_string(context, "Can't generate Diffie-Hellman keys");	ret = KRB5KRB_ERR_GENERIC;	goto out;    }    if (client_params->dh_public_key == NULL) {	krb5_set_error_string(context, "dh_public_key");	ret = KRB5KRB_ERR_GENERIC;	goto out;    }    dh_gen_keylen = DH_size(client_params->dh);    size = BN_num_bytes(client_params->dh->p);    if (size < dh_gen_keylen)	size = dh_gen_keylen;    dh_gen_key = malloc(size);    if (dh_gen_key == NULL) {	krb5_set_error_string(context, "malloc: out of memory");	ret = ENOMEM;	goto out;    }    memset(dh_gen_key, 0, size - dh_gen_keylen);    dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),				   client_params->dh_public_key,				   client_params->dh);    if (dh_gen_keylen == -1) {	krb5_set_error_string(context, "Can't compute Diffie-Hellman key");	ret = KRB5KRB_ERR_GENERIC;	goto out;    }    ret = _krb5_pk_octetstring2key(context,				   enctype,				   dh_gen_key, dh_gen_keylen,				   NULL, NULL,				   reply_key); out:    if (dh_gen_key)	free(dh_gen_key);    if (key.keyvalue.data)	krb5_free_keyblock_contents(context, &key);    return ret;}static BIGNUM *integer_to_BN(krb5_context context, const char *field, heim_integer *f){    BIGNUM *bn;    bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL);    if (bn == NULL) {	krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field);	return NULL;    }    BN_set_negative(bn, f->negative);    return bn;}static krb5_error_codeget_dh_param(krb5_context context,	     krb5_kdc_configuration *config,	     SubjectPublicKeyInfo *dh_key_info,	     pk_client_params *client_params){    DomainParameters dhparam;    DH *dh = NULL;    krb5_error_code ret;    memset(&dhparam, 0, sizeof(dhparam));    if (der_heim_oid_cmp(&dh_key_info->algorithm.algorithm, oid_id_dhpublicnumber())) {	krb5_set_error_string(context,			      "PKINIT invalid oid in clientPublicValue");	return KRB5_BADMSGTYPE;    }    if (dh_key_info->algorithm.parameters == NULL) {	krb5_set_error_string(context, "PKINIT missing algorithm parameter "			      "in clientPublicValue");	return KRB5_BADMSGTYPE;    }    ret = decode_DomainParameters(dh_key_info->algorithm.parameters->data,				  dh_key_info->algorithm.parameters->length,				  &dhparam,				  NULL);    if (ret) {	krb5_set_error_string(context, "Can't decode algorithm "			      "parameters in clientPublicValue");	goto out;    }    if ((dh_key_info->subjectPublicKey.length % 8) != 0) {	ret = KRB5_BADMSGTYPE;	krb5_set_error_string(context, "PKINIT: subjectPublicKey not aligned "			      "to 8 bit boundary");	goto out;    }    ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits, 			    &dhparam.p, &dhparam.g, &dhparam.q, moduli,			    &client_params->dh_group_name);    if (ret) {	/* XXX send back proposal of better group */	goto out;    }    dh = DH_new();    if (dh == NULL) {	krb5_set_error_string(context, "Cannot create DH structure");	ret = ENOMEM;	goto out;    }    ret = KRB5_BADMSGTYPE;    dh->p = integer_to_BN(context, "DH prime", &dhparam.p);    if (dh->p == NULL)	goto out;    dh->g = integer_to_BN(context, "DH base", &dhparam.g);    if (dh->g == NULL)	goto out;    dh->q = integer_to_BN(context, "DH p-1 factor", &dhparam.q);    if (dh->g == NULL)	goto out;    {	heim_integer glue;	size_t size;	ret = decode_DHPublicKey(dh_key_info->subjectPublicKey.data,				 dh_key_info->subjectPublicKey.length / 8,				 &glue,				 &size);	if (ret) {	    krb5_clear_error_string(context);	    return ret;	}	client_params->dh_public_key = integer_to_BN(context,						     "subjectPublicKey",						     &glue);	der_free_heim_integer(&glue);	if (client_params->dh_public_key == NULL)	    goto out;    }    client_params->dh = dh;    dh = NULL;    ret = 0;     out:    if (dh)	DH_free(dh);    free_DomainParameters(&dhparam);    return ret;}krb5_error_code_kdc_pk_rd_padata(krb5_context context,		  krb5_kdc_configuration *config,		  const KDC_REQ *req,		  const PA_DATA *pa,		  pk_client_params **ret_params){    pk_client_params *client_params;    krb5_error_code ret;    heim_oid eContentType = { 0, NULL }, contentInfoOid = { 0, NULL };    krb5_data eContent = { 0, NULL };    krb5_data signed_content = { 0, NULL };    const char *type = "unknown type";    int have_data = 0;    *ret_params = NULL;        if (!config->enable_pkinit) {	kdc_log(context, config, 0, "PK-INIT request but PK-INIT not enabled");	krb5_clear_error_string(context);	return 0;    }    hx509_verify_set_time(kdc_identity->verify_ctx, _kdc_now.tv_sec);    client_params = calloc(1, sizeof(*client_params));    if (client_params == NULL) {	krb5_clear_error_string(context);	ret = ENOMEM;	goto out;    }    if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {	PA_PK_AS_REQ_Win2k r;	type = "PK-INIT-Win2k";	ret = decode_PA_PK_AS_REQ_Win2k(pa->padata_value.data,					pa->padata_value.length,					&r,					NULL);	if (ret) {	    krb5_set_error_string(context, "Can't decode "				  "PK-AS-REQ-Win2k: %d", ret);	    goto out;	}		ret = hx509_cms_unwrap_ContentInfo(&r.signed_auth_pack,					   &contentInfoOid,					   &signed_content,					   &have_data);	free_PA_PK_AS_REQ_Win2k(&r);	if (ret) {	    krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret);	    goto out;	}    } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) {	PA_PK_AS_REQ r;	type = "PK-INIT-IETF";	ret = decode_PA_PK_AS_REQ(pa->padata_value.data,				  pa->padata_value.length,				  &r,				  NULL);	if (ret) {	    krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret);	    goto out;	}		/* XXX look at r.kdcPkId */	if (r.trustedCertifiers) {	    ExternalPrincipalIdentifiers *edi = r.trustedCertifiers;	    unsigned int i;	    ret = hx509_certs_init(kdc_identity->hx509ctx,				   "MEMORY:client-anchors",				   0, NULL,				   &client_params->client_anchors);	    if (ret) {		krb5_set_error_string(context, "Can't allocate client anchors: %d", ret);		goto out;	    }	    for (i = 0; i < edi->len; i++) {		IssuerAndSerialNumber iasn;		hx509_query *q;		hx509_cert cert;		size_t size;		if (edi->val[i].issuerAndSerialNumber == NULL)		    continue;		ret = hx509_query_alloc(kdc_identity->hx509ctx, &q);		if (ret) {		    krb5_set_error_string(context, 					  "Failed to allocate hx509_query");		    goto out;		}				ret = decode_IssuerAndSerialNumber(edi->val[i].issuerAndSerialNumber->data,						   edi->val[i].issuerAndSerialNumber->length,						   &iasn,						   &size);		if (ret) {		    hx509_query_free(kdc_identity->hx509ctx, q);		    continue;		}		ret = hx509_query_match_issuer_serial(q, &iasn.issuer, &iasn.serialNumber);		free_IssuerAndSerialNumber(&iasn);		if (ret)		    continue;		ret = hx509_certs_find(kdc_identity->hx509ctx,				       kdc_identity->certs,				       q,				       &cert);		hx509_query_free(kdc_identity->hx509ctx, q);		if (ret)		    continue;		hx509_certs_add(kdc_identity->hx509ctx, 				client_params->client_anchors, cert);		hx509_cert_free(cert);	    }	}	ret = hx509_cms_unwrap_ContentInfo(&r.signedAuthPack,					   &contentInfoOid,					   &signed_content,					   &have_data);	free_PA_PK_AS_REQ(&r);	if (ret) {	    krb5_set_error_string(context, "Can't unwrap ContentInfo: %d", ret);	    goto out;	}    } else { 	krb5_clear_error_string(context);	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;	goto out;    }    ret = der_heim_oid_cmp(&contentInfoOid, oid_id_pkcs7_signedData());    if (ret != 0) {	krb5_set_error_string(context, "PK-AS-REQ-Win2k invalid content "			      "type oid");	ret = KRB5KRB_ERR_GENERIC;	goto out;    }	    if (!have_data) {	krb5_set_error_string(context,			      "PK-AS-REQ-Win2k no signed auth pack");	ret = KRB5KRB_ERR_GENERIC;	goto out;    }    {	hx509_certs signer_certs;	ret = hx509_cms_verify_signed(kdc_identity->hx509ctx,				      kdc_identity->verify_ctx,				      signed_content.data,				      signed_content.length,				      NULL,				      kdc_identity->certpool,				      &eContentType,				      &eContent,				      &signer_certs);	if (ret) {	    char *s = hx509_get_error_string(kdc_identity->hx509ctx, ret);	    krb5_warnx(context, "PKINIT: failed to verify signature: %s: %d",		       s, ret);	    free(s);	    goto out;	}	ret = hx509_get_one_cert(kdc_identity->hx509ctx, signer_certs,				 &client_params->cert);	hx509_certs_free(&signer_certs);	if (ret)	    goto out;    }    /* Signature is correct, now verify the signed message */    if (der_heim_oid_cmp(&eContentType, oid_id_pkcs7_data()) != 0 &&	der_heim_oid_cmp(&eContentType, oid_id_pkauthdata()) != 0)    {	krb5_set_error_string(context, "got wrong oid for pkauthdata");	ret = KRB5_BADMSGTYPE;	goto out;    }

⌨️ 快捷键说明

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