示例#1
0
文件: 524.c 项目: gojdic/samba
static krb5_error_code
encrypt_v4_ticket(krb5_context context,
		  krb5_kdc_configuration *config,
		  void *buf,
		  size_t len,
		  krb5_keyblock *skey,
		  EncryptedData *reply)
{
    krb5_crypto crypto;
    krb5_error_code ret;
    ret = krb5_crypto_init(context, skey, ETYPE_DES_PCBC_NONE, &crypto);
    if (ret) {
	free(buf);
	kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
		krb5_get_err_text(context, ret));
	return ret;
    }

    ret = krb5_encrypt_EncryptedData(context,
				     crypto,
				     KRB5_KU_TICKET,
				     buf,
				     len,
				     0,
				     reply);
    krb5_crypto_destroy(context, crypto);
    if(ret) {
	kdc_log(context, config, 0, "Failed to encrypt data: %s",
		krb5_get_err_text(context, ret));
	return ret;
    }
    return 0;
}
示例#2
0
krb5_error_code
_kdc_fast_mk_response(krb5_context context,
		      krb5_crypto armor_crypto,
		      METHOD_DATA *pa_data,
		      krb5_keyblock *strengthen_key,
		      KrbFastFinished *finished,
		      krb5uint32 nonce,
		      krb5_data *data)
{
    PA_FX_FAST_REPLY fxfastrep;
    KrbFastResponse fastrep;
    krb5_error_code ret;
    krb5_data buf;
    size_t size;

    memset(&fxfastrep, 0, sizeof(fxfastrep));
    memset(&fastrep, 0, sizeof(fastrep));
    krb5_data_zero(data);

    if (pa_data) {
	fastrep.padata.val = pa_data->val;
	fastrep.padata.len = pa_data->len;
    }
    fastrep.strengthen_key = strengthen_key;
    fastrep.finished = finished;
    fastrep.nonce = nonce;

    ASN1_MALLOC_ENCODE(KrbFastResponse, buf.data, buf.length,
		       &fastrep, &size, ret);
    if (ret)
	return ret;
    if (buf.length != size)
	krb5_abortx(context, "internal asn.1 error");
    
    fxfastrep.element = choice_PA_FX_FAST_REPLY_armored_data;

    ret = krb5_encrypt_EncryptedData(context,
				     armor_crypto,
				     KRB5_KU_FAST_REP,
				     buf.data,
				     buf.length,
				     0,
				     &fxfastrep.u.armored_data.enc_fast_rep);
    krb5_data_free(&buf);
    if (ret)
	return ret;

    ASN1_MALLOC_ENCODE(PA_FX_FAST_REPLY, data->data, data->length,
		       &fxfastrep, &size, ret);
    free_PA_FX_FAST_REPLY(&fxfastrep);
    if (ret)
	return ret;
    if (data->length != size)
	krb5_abortx(context, "internal asn.1 error");
    
    return 0;
}
示例#3
0
static krb5_error_code
make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md,
		      krb5_enctype etype, krb5_keyblock *key)
{
    PA_ENC_TS_ENC p;
    unsigned char *buf;
    size_t buf_size;
    size_t len;
    EncryptedData encdata;
    krb5_error_code ret;
    int32_t usec;
    int usec2;
    krb5_crypto crypto;

    krb5_us_timeofday (context, &p.patimestamp, &usec);
    usec2         = usec;
    p.pausec      = &usec2;

    ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
    if (ret)
	return ret;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    ret = krb5_crypto_init(context, key, 0, &crypto);
    if (ret) {
	free(buf);
	return ret;
    }
    ret = krb5_encrypt_EncryptedData(context,
				     crypto,
				     KRB5_KU_PA_ENC_TIMESTAMP,
				     buf,
				     len,
				     0,
				     &encdata);
    free(buf);
    krb5_crypto_destroy(context, crypto);
    if (ret)
	return ret;

    ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
    free_EncryptedData(&encdata);
    if (ret)
	return ret;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    ret = krb5_padata_add(context, md, KRB5_PADATA_ENC_TIMESTAMP, buf, len);
    if (ret)
	free(buf);
    return ret;
}
示例#4
0
static krb5_error_code
fast_add_cookie(kdc_request_t r, METHOD_DATA *method_data)
{
    krb5_crypto crypto = NULL;
    KDCFastCookie shell;
    krb5_error_code ret;
    krb5_data data;
    size_t size;

    memset(&shell, 0, sizeof(shell));

    r->fast.expiration = kdc_time + FAST_EXPIRATION_TIME;

    ASN1_MALLOC_ENCODE(KDCFastState, data.data, data.length, 
		       &r->fast, &size, ret);
    if (ret)
	return ret;
    heim_assert(size == data.length, "internal asn1 encoder error");

    ret = get_fastuser_crypto(r, KRB5_ENCTYPE_NULL, &crypto);
    if (ret)
	goto out;

    ret = krb5_encrypt_EncryptedData(r->context, crypto,
				     KRB5_KU_H5L_COOKIE,
				     data.data, data.length, 0,
				     &shell.cookie);
    krb5_crypto_destroy(r->context, crypto);
    if (ret)
	goto out;
    
    free(data.data);

    shell.version = "H5L1";

    ASN1_MALLOC_ENCODE(KDCFastCookie, data.data, data.length, 
		       &shell, &size, ret);
    free_EncryptedData(&shell.cookie);
    if (ret)
	goto out;
    heim_assert(size == data.length, "internal asn1 encoder error");
    
    ret = krb5_padata_add(r->context, method_data,
			  KRB5_PADATA_FX_COOKIE,
			  data.data, data.length);
 out:
    if (ret)
	free(data.data);
    return ret;
}
示例#5
0
static krb5_error_code
set_auth_data (krb5_context context,
	       KDC_REQ_BODY *req_body,
	       krb5_authdata *authdata,
	       krb5_keyblock *subkey)
{
    if(authdata->len) {
	size_t len, buf_size;
	unsigned char *buf;
	krb5_crypto crypto;
	krb5_error_code ret;

	ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, authdata,
			   &len, ret);
	if (ret)
	    return ret;
	if (buf_size != len)
	    krb5_abortx(context, "internal error in ASN.1 encoder");

	ALLOC(req_body->enc_authorization_data, 1);
	if (req_body->enc_authorization_data == NULL) {
	    free (buf);
	    krb5_set_error_message(context, ENOMEM,
				   N_("malloc: out of memory", ""));
	    return ENOMEM;
	}
	ret = krb5_crypto_init(context, subkey, 0, &crypto);
	if (ret) {
	    free (buf);
	    free (req_body->enc_authorization_data);
	    req_body->enc_authorization_data = NULL;
	    return ret;
	}
	krb5_encrypt_EncryptedData(context,
				   crypto,
				   KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
				   buf,
				   len,
				   0,
				   req_body->enc_authorization_data);
	free (buf);
	krb5_crypto_destroy(context, crypto);
    } else {
	req_body->enc_authorization_data = NULL;
    }
    return 0;
}
示例#6
0
krb5_error_code
_kdc_encode_reply(krb5_context context,
		  krb5_kdc_configuration *config,
		  KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek,
		  krb5_enctype etype,
		  int skvno, const EncryptionKey *skey,
		  int ckvno, const EncryptionKey *reply_key,
		  int rk_is_subkey,
		  const char **e_text,
		  krb5_data *reply)
{
    unsigned char *buf;
    size_t buf_size;
    size_t len = 0;
    krb5_error_code ret;
    krb5_crypto crypto;

    ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
    if(ret) {
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
	krb5_free_error_message(context, msg);
	return ret;
    }
    if(buf_size != len) {
	free(buf);
	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
	*e_text = "KDC internal error";
	return KRB5KRB_ERR_GENERIC;
    }

    ret = krb5_crypto_init(context, skey, etype, &crypto);
    if (ret) {
        const char *msg;
	free(buf);
	msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
	krb5_free_error_message(context, msg);
	return ret;
    }

    ret = krb5_encrypt_EncryptedData(context,
				     crypto,
				     KRB5_KU_TICKET,
				     buf,
				     len,
				     skvno,
				     &rep->ticket.enc_part);
    free(buf);
    krb5_crypto_destroy(context, crypto);
    if(ret) {
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
	krb5_free_error_message(context, msg);
	return ret;
    }

    if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
	ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
    else
	ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
    if(ret) {
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
	krb5_free_error_message(context, msg);
	return ret;
    }
    if(buf_size != len) {
	free(buf);
	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
	*e_text = "KDC internal error";
	return KRB5KRB_ERR_GENERIC;
    }
    ret = krb5_crypto_init(context, reply_key, 0, &crypto);
    if (ret) {
	const char *msg = krb5_get_error_message(context, ret);
	free(buf);
	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
	krb5_free_error_message(context, msg);
	return ret;
    }
    if(rep->msg_type == krb_as_rep) {
	krb5_encrypt_EncryptedData(context,
				   crypto,
				   KRB5_KU_AS_REP_ENC_PART,
				   buf,
				   len,
				   ckvno,
				   &rep->enc_part);
	free(buf);
	ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
    } else {
	krb5_encrypt_EncryptedData(context,
				   crypto,
				   rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
				   buf,
				   len,
				   ckvno,
				   &rep->enc_part);
	free(buf);
	ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
    }
    krb5_crypto_destroy(context, crypto);
    if(ret) {
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
	krb5_free_error_message(context, msg);
	return ret;
    }
    if(buf_size != len) {
	free(buf);
	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
	*e_text = "KDC internal error";
	return KRB5KRB_ERR_GENERIC;
    }
    reply->data = buf;
    reply->length = buf_size;
    return 0;
}
示例#7
0
文件: pkinit.c 项目: heimdal/heimdal
krb5_error_code
_kdc_pk_mk_pa_reply(krb5_context context,
		    krb5_kdc_configuration *config,
		    pk_client_params *cp,
		    const hdb_entry_ex *client,
		    krb5_enctype sessionetype,
		    const KDC_REQ *req,
		    const krb5_data *req_buffer,
		    krb5_keyblock *reply_key,
		    krb5_keyblock *sessionkey,
		    METHOD_DATA *md)
{
    krb5_error_code ret;
    void *buf = NULL;
    size_t len = 0, size = 0;
    krb5_enctype enctype;
    int pa_type;
    hx509_cert kdc_cert = NULL;
    size_t i;

    if (!config->enable_pkinit) {
	krb5_clear_error_message(context);
	return 0;
    }

    if (req->req_body.etype.len > 0) {
	for (i = 0; i < req->req_body.etype.len; i++)
	    if (krb5_enctype_valid(context, req->req_body.etype.val[i]) == 0)
		break;
	if (req->req_body.etype.len <= i) {
	    ret = KRB5KRB_ERR_GENERIC;
	    krb5_set_error_message(context, ret,
				   "No valid enctype available from client");
	    goto out;
	}
	enctype = req->req_body.etype.val[i];
    } else
	enctype = ETYPE_DES3_CBC_SHA1;

    if (cp->type == PKINIT_27) {
	PA_PK_AS_REP rep;
	const char *type, *other = "";

	memset(&rep, 0, sizeof(rep));

	pa_type = KRB5_PADATA_PK_AS_REP;

	if (cp->keyex == USE_RSA) {
	    ContentInfo info;

	    type = "enckey";

	    rep.element = choice_PA_PK_AS_REP_encKeyPack;

	    ret = krb5_generate_random_keyblock(context, enctype,
						&cp->reply_key);
	    if (ret) {
		free_PA_PK_AS_REP(&rep);
		goto out;
	    }
	    ret = pk_mk_pa_reply_enckey(context,
					config,
					cp,
					req,
					req_buffer,
					&cp->reply_key,
					&info,
					&kdc_cert);
	    if (ret) {
		free_PA_PK_AS_REP(&rep);
		goto out;
	    }
	    ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data,
			       rep.u.encKeyPack.length, &info, &size,
			       ret);
	    free_ContentInfo(&info);
	    if (ret) {
		krb5_set_error_message(context, ret, "encoding of Key ContentInfo "
				       "failed %d", ret);
		free_PA_PK_AS_REP(&rep);
		goto out;
	    }
	    if (rep.u.encKeyPack.length != size)
		krb5_abortx(context, "Internal ASN.1 encoder error");

	    ret = krb5_generate_random_keyblock(context, sessionetype,
						sessionkey);
	    if (ret) {
		free_PA_PK_AS_REP(&rep);
		goto out;
	    }

	} else {
	    ContentInfo info;

	    switch (cp->keyex) {
	    case USE_DH: type = "dh"; break;
	    case USE_ECDH: type = "ecdh"; break;
	    default: krb5_abortx(context, "unknown keyex"); break;
	    }

	    if (cp->dh_group_name)
		other = cp->dh_group_name;

	    rep.element = choice_PA_PK_AS_REP_dhInfo;

	    ret = generate_dh_keyblock(context, cp, enctype);
	    if (ret)
		return ret;

	    ret = pk_mk_pa_reply_dh(context, config,
				    cp,
				    &info,
				    &kdc_cert);
	    if (ret) {
		free_PA_PK_AS_REP(&rep);
		krb5_set_error_message(context, ret,
				       "create pa-reply-dh "
				       "failed %d", ret);
		goto out;
	    }

	    ASN1_MALLOC_ENCODE(ContentInfo, rep.u.dhInfo.dhSignedData.data,
			       rep.u.dhInfo.dhSignedData.length, &info, &size,
			       ret);
	    free_ContentInfo(&info);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       "encoding of Key ContentInfo "
				       "failed %d", ret);
		free_PA_PK_AS_REP(&rep);
		goto out;
	    }
	    if (rep.u.encKeyPack.length != size)
		krb5_abortx(context, "Internal ASN.1 encoder error");

	    /* generate the session key using the method from RFC6112 */
	    {
		krb5_keyblock kdc_contribution_key;
		krb5_crypto reply_crypto;
		krb5_crypto kdccont_crypto;
		krb5_data p1 = { strlen("PKINIT"), "PKINIT"};
		krb5_data p2 = { strlen("KEYEXCHANGE"), "KEYEXCHANGE"};
		void *kckdata;
		size_t kcklen;
		EncryptedData kx;
		void *kxdata;
		size_t kxlen;

		ret = krb5_generate_random_keyblock(context, sessionetype,
						&kdc_contribution_key);
		if (ret) {
		    free_PA_PK_AS_REP(&rep);
		    goto out;
		}
		ret = krb5_crypto_init(context, &cp->reply_key, enctype, &reply_crypto);
		if (ret) {
		    krb5_free_keyblock_contents(context, &kdc_contribution_key);
		    free_PA_PK_AS_REP(&rep);
		    goto out;
		}
		ret = krb5_crypto_init(context, &kdc_contribution_key, sessionetype, &kdccont_crypto);
		if (ret) {
		    krb5_crypto_destroy(context, reply_crypto);
		    krb5_free_keyblock_contents(context, &kdc_contribution_key);
		    free_PA_PK_AS_REP(&rep);
		    goto out;
		}
		/* KRB-FX-CF2 */
		ret = krb5_crypto_fx_cf2(context, kdccont_crypto, reply_crypto,
					 &p1, &p2, sessionetype, sessionkey);
		krb5_crypto_destroy(context, kdccont_crypto);
		if (ret) {
		    krb5_crypto_destroy(context, reply_crypto);
		    krb5_free_keyblock_contents(context, &kdc_contribution_key);
		    free_PA_PK_AS_REP(&rep);
		    goto out;
		}
		ASN1_MALLOC_ENCODE(EncryptionKey, kckdata, kcklen,
				   &kdc_contribution_key, &size, ret);
		krb5_free_keyblock_contents(context, &kdc_contribution_key);
		if (ret) {
		    krb5_set_error_message(context, ret, "encoding of PKINIT-KX Key failed %d", ret);
		    krb5_crypto_destroy(context, reply_crypto);
		    free_PA_PK_AS_REP(&rep);
		    goto out;
		}
		if (kcklen != size)
		    krb5_abortx(context, "Internal ASN.1 encoder error");
		ret = krb5_encrypt_EncryptedData(context, reply_crypto, KRB5_KU_PA_PKINIT_KX,
					kckdata, kcklen, 0, &kx);
		krb5_crypto_destroy(context, reply_crypto);
		free(kckdata);
		if (ret) {
		    free_PA_PK_AS_REP(&rep);
		    goto out;
		}
		ASN1_MALLOC_ENCODE(EncryptedData, kxdata, kxlen,
				   &kx, &size, ret);
		free_EncryptedData(&kx);
		if (ret) {
		    krb5_set_error_message(context, ret, "encoding of PKINIT-KX failed %d", ret);
		    free_PA_PK_AS_REP(&rep);
		    goto out;
		}
		if (kxlen != size)
		    krb5_abortx(context, "Internal ASN.1 encoder error");
		/* Add PA-PKINIT-KX */
		ret = krb5_padata_add(context, md, KRB5_PADATA_PKINIT_KX, kxdata, kxlen);
		if (ret) {
		    krb5_set_error_message(context, ret,
					   "Failed adding PKINIT-KX %d", ret);
		    free(buf);
		    goto out;
		}
	    }
	}

#define use_btmm_with_enckey 0
	if (use_btmm_with_enckey && rep.element == choice_PA_PK_AS_REP_encKeyPack) {
	    PA_PK_AS_REP_BTMM btmm;
	    heim_any any;

	    any.data = rep.u.encKeyPack.data;
	    any.length = rep.u.encKeyPack.length;

	    btmm.dhSignedData = NULL;
	    btmm.encKeyPack = &any;

	    ASN1_MALLOC_ENCODE(PA_PK_AS_REP_BTMM, buf, len, &btmm, &size, ret);
	} else {
	    ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret);
	}

	free_PA_PK_AS_REP(&rep);
	if (ret) {
	    krb5_set_error_message(context, ret,
				   "encode PA-PK-AS-REP failed %d", ret);
	    goto out;
	}
	if (len != size)
	    krb5_abortx(context, "Internal ASN.1 encoder error");

	kdc_log(context, config, 0, "PK-INIT using %s %s", type, other);

    } else if (cp->type == PKINIT_WIN2K) {
	PA_PK_AS_REP_Win2k rep;
	ContentInfo info;

	if (cp->keyex != USE_RSA) {
	    ret = KRB5KRB_ERR_GENERIC;
	    krb5_set_error_message(context, ret,
				   "Windows PK-INIT doesn't support DH");
	    goto out;
	}

	memset(&rep, 0, sizeof(rep));

	pa_type = KRB5_PADATA_PK_AS_REP_19;
	rep.element = choice_PA_PK_AS_REP_Win2k_encKeyPack;

	ret = krb5_generate_random_keyblock(context, enctype,
					    &cp->reply_key);
	if (ret) {
	    free_PA_PK_AS_REP_Win2k(&rep);
	    goto out;
	}
	ret = pk_mk_pa_reply_enckey(context,
				    config,
				    cp,
				    req,
				    req_buffer,
				    &cp->reply_key,
				    &info,
				    &kdc_cert);
	if (ret) {
	    free_PA_PK_AS_REP_Win2k(&rep);
	    goto out;
	}
	ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data,
			   rep.u.encKeyPack.length, &info, &size,
			   ret);
	free_ContentInfo(&info);
	if (ret) {
	    krb5_set_error_message(context, ret, "encoding of Key ContentInfo "
				  "failed %d", ret);
	    free_PA_PK_AS_REP_Win2k(&rep);
	    goto out;
	}
	if (rep.u.encKeyPack.length != size)
	    krb5_abortx(context, "Internal ASN.1 encoder error");

	ASN1_MALLOC_ENCODE(PA_PK_AS_REP_Win2k, buf, len, &rep, &size, ret);
	free_PA_PK_AS_REP_Win2k(&rep);
	if (ret) {
	    krb5_set_error_message(context, ret,
				  "encode PA-PK-AS-REP-Win2k failed %d", ret);
	    goto out;
	}
	if (len != size)
	    krb5_abortx(context, "Internal ASN.1 encoder error");

	ret = krb5_generate_random_keyblock(context, sessionetype,
					    sessionkey);
	if (ret) {
	    free(buf);
	    goto out;
	}

    } else
	krb5_abortx(context, "PK-INIT internal error");


    ret = krb5_padata_add(context, md, pa_type, buf, len);
    if (ret) {
	krb5_set_error_message(context, ret,
			       "Failed adding PA-PK-AS-REP %d", ret);
	free(buf);
	goto out;
    }

    if (config->pkinit_kdc_ocsp_file) {

	if (ocsp.expire == 0 && ocsp.next_update > kdc_time) {
	    struct stat sb;
	    int fd;

	    krb5_data_free(&ocsp.data);

	    ocsp.expire = 0;
	    ocsp.next_update = kdc_time + 60 * 5;

	    fd = open(config->pkinit_kdc_ocsp_file, O_RDONLY);
	    if (fd < 0) {
		kdc_log(context, config, 0,
			"PK-INIT failed to open ocsp data file %d", errno);
		goto out_ocsp;
	    }
	    ret = fstat(fd, &sb);
	    if (ret) {
		ret = errno;
		close(fd);
		kdc_log(context, config, 0,
			"PK-INIT failed to stat ocsp data %d", ret);
		goto out_ocsp;
	    }

	    ret = krb5_data_alloc(&ocsp.data, sb.st_size);
	    if (ret) {
		close(fd);
		kdc_log(context, config, 0,
			"PK-INIT failed to stat ocsp data %d", ret);
		goto out_ocsp;
	    }
	    ocsp.data.length = sb.st_size;
	    ret = read(fd, ocsp.data.data, sb.st_size);
	    close(fd);
	    if (ret != sb.st_size) {
		kdc_log(context, config, 0,
			"PK-INIT failed to read ocsp data %d", errno);
		goto out_ocsp;
	    }

	    ret = hx509_ocsp_verify(context->hx509ctx,
				    kdc_time,
				    kdc_cert,
				    0,
				    ocsp.data.data, ocsp.data.length,
				    &ocsp.expire);
	    if (ret) {
		kdc_log(context, config, 0,
			"PK-INIT failed to verify ocsp data %d", ret);
		krb5_data_free(&ocsp.data);
		ocsp.expire = 0;
	    } else if (ocsp.expire > 180) {
		ocsp.expire -= 180; /* refetch the ocsp before it expire */
		ocsp.next_update = ocsp.expire;
	    } else {
		ocsp.next_update = kdc_time;
	    }
	out_ocsp:
	    ret = 0;
	}

	if (ocsp.expire != 0 && ocsp.expire > kdc_time) {

	    ret = krb5_padata_add(context, md,
				  KRB5_PADATA_PA_PK_OCSP_RESPONSE,
				  ocsp.data.data, ocsp.data.length);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       "Failed adding OCSP response %d", ret);
		goto out;
	    }
	}
    }

out:
    if (kdc_cert)
	hx509_cert_free(kdc_cert);

    if (ret == 0)
	ret = krb5_copy_keyblock_contents(context, &cp->reply_key, reply_key);
    return ret;
}
示例#8
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_forwarded_creds (krb5_context	    context,
			  krb5_auth_context auth_context,
			  krb5_ccache       ccache,
			  krb5_flags        flags,
			  const char        *hostname,
			  krb5_creds        *in_creds,
			  krb5_data         *out_data)
{
    krb5_error_code ret;
    krb5_creds *out_creds;
    krb5_addresses addrs, *paddrs;
    KRB_CRED cred;
    KrbCredInfo *krb_cred_info;
    EncKrbCredPart enc_krb_cred_part;
    size_t len;
    unsigned char *buf;
    size_t buf_size;
    krb5_kdc_flags kdc_flags;
    krb5_crypto crypto;
    struct addrinfo *ai;
    int save_errno;
    krb5_creds *ticket;
    char *realm;

    if (in_creds->client && in_creds->client->realm)
	realm = in_creds->client->realm;
    else
	realm = in_creds->server->realm;

    addrs.len = 0;
    addrs.val = NULL;
    paddrs = &addrs;

    /*
     * If tickets are address-less, forward address-less tickets.
     */

    ret = _krb5_get_krbtgt (context,
			    ccache,
			    realm,
			    &ticket);
    if(ret == 0) {
	if (ticket->addresses.len == 0)
	    paddrs = NULL;
	krb5_free_creds (context, ticket);
    }
    
    if (paddrs != NULL) {

	ret = getaddrinfo (hostname, NULL, NULL, &ai);
	if (ret) {
	    save_errno = errno;
	    krb5_set_error_string(context, "resolving %s: %s",
				  hostname, gai_strerror(ret));
	    return krb5_eai_to_heim_errno(ret, save_errno);
	}
	
	ret = add_addrs (context, &addrs, ai);
	freeaddrinfo (ai);
	if (ret)
	    return ret;
    }
    
    kdc_flags.b = int2KDCOptions(flags);

    ret = krb5_get_kdc_cred (context,
			     ccache,
			     kdc_flags,
			     paddrs,
			     NULL,
			     in_creds,
			     &out_creds);
    krb5_free_addresses (context, &addrs);
    if (ret) {
	return ret;
    }

    memset (&cred, 0, sizeof(cred));
    cred.pvno = 5;
    cred.msg_type = krb_cred;
    ALLOC_SEQ(&cred.tickets, 1);
    if (cred.tickets.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_string(context, "malloc: out of memory");
	goto out2;
    }
    ret = decode_Ticket(out_creds->ticket.data,
			out_creds->ticket.length,
			cred.tickets.val, &len);
    if (ret)
	goto out3;

    memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
    ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1);
    if (enc_krb_cred_part.ticket_info.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_string(context, "malloc: out of memory");
	goto out4;
    }
    
    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
	krb5_timestamp sec;
	int32_t usec;
	
	krb5_us_timeofday (context, &sec, &usec);
	
	ALLOC(enc_krb_cred_part.timestamp, 1);
	if (enc_krb_cred_part.timestamp == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_string(context, "malloc: out of memory");
	    goto out4;
	}
	*enc_krb_cred_part.timestamp = sec;
	ALLOC(enc_krb_cred_part.usec, 1);
	if (enc_krb_cred_part.usec == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_string(context, "malloc: out of memory");
	    goto out4;
	}
	*enc_krb_cred_part.usec      = usec;
    } else {
	enc_krb_cred_part.timestamp = NULL;
	enc_krb_cred_part.usec = NULL;
    }

    if (auth_context->local_address && auth_context->local_port) {
	krb5_boolean noaddr;
	krb5_const_realm realm;

	realm = krb5_principal_get_realm(context, out_creds->server);
	krb5_appdefault_boolean(context, NULL, realm, "no-addresses", paddrs == NULL,
				&noaddr);
	if (!noaddr) {
	    ret = krb5_make_addrport (context,
				      &enc_krb_cred_part.s_address,
				      auth_context->local_address,
				      auth_context->local_port);
	    if (ret)
		goto out4;
	}
    }

    if (auth_context->remote_address) {
	if (auth_context->remote_port) {
	    krb5_boolean noaddr;
	    krb5_const_realm realm;

	    realm = krb5_principal_get_realm(context, out_creds->server);
	    /* Is this correct, and should we use the paddrs == NULL
               trick here as well? Having an address-less ticket may
               indicate that we don't know our own global address, but
               it does not necessary mean that we don't know the
               server's. */
	    krb5_appdefault_boolean(context, NULL, realm, "no-addresses",
				    FALSE, &noaddr);
	    if (!noaddr) {
		ret = krb5_make_addrport (context,
					  &enc_krb_cred_part.r_address,
					  auth_context->remote_address,
					  auth_context->remote_port);
		if (ret)
		    goto out4;
	    }
	} else {
	    ALLOC(enc_krb_cred_part.r_address, 1);
	    if (enc_krb_cred_part.r_address == NULL) {
		ret = ENOMEM;
		krb5_set_error_string(context, "malloc: out of memory");
		goto out4;
	    }

	    ret = krb5_copy_address (context, auth_context->remote_address,
				     enc_krb_cred_part.r_address);
	    if (ret)
		goto out4;
	}
    }

    /* fill ticket_info.val[0] */

    enc_krb_cred_part.ticket_info.len = 1;

    krb_cred_info = enc_krb_cred_part.ticket_info.val;

    copy_EncryptionKey (&out_creds->session, &krb_cred_info->key);
    ALLOC(krb_cred_info->prealm, 1);
    copy_Realm (&out_creds->client->realm, krb_cred_info->prealm);
    ALLOC(krb_cred_info->pname, 1);
    copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname);
    ALLOC(krb_cred_info->flags, 1);
    *krb_cred_info->flags          = out_creds->flags.b;
    ALLOC(krb_cred_info->authtime, 1);
    *krb_cred_info->authtime       = out_creds->times.authtime;
    ALLOC(krb_cred_info->starttime, 1);
    *krb_cred_info->starttime      = out_creds->times.starttime;
    ALLOC(krb_cred_info->endtime, 1);
    *krb_cred_info->endtime        = out_creds->times.endtime;
    ALLOC(krb_cred_info->renew_till, 1);
    *krb_cred_info->renew_till = out_creds->times.renew_till;
    ALLOC(krb_cred_info->srealm, 1);
    copy_Realm (&out_creds->server->realm, krb_cred_info->srealm);
    ALLOC(krb_cred_info->sname, 1);
    copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname);
    ALLOC(krb_cred_info->caddr, 1);
    copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr);

    krb5_free_creds (context, out_creds);

    /* encode EncKrbCredPart */

    ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size, 
		       &enc_krb_cred_part, &len, ret);
    free_EncKrbCredPart (&enc_krb_cred_part);
    if (ret) {
	free_KRB_CRED(&cred);
	return ret;
    }
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) {
	cred.enc_part.etype = ENCTYPE_NULL;
	cred.enc_part.kvno = NULL;
	cred.enc_part.cipher.data = buf;
	cred.enc_part.cipher.length = buf_size;
    } else {
	krb5_keyblock *key;

	if (auth_context->local_subkey)
	    key = auth_context->local_subkey;
	else if (auth_context->remote_subkey)
	    key = auth_context->remote_subkey;
	else
	    key = auth_context->keyblock;
	
	ret = krb5_crypto_init(context, key, 0, &crypto);
	if (ret) {
	    free(buf);
	    free_KRB_CRED(&cred);
	    return ret;
	}
	ret = krb5_encrypt_EncryptedData (context,
					  crypto,
					  KRB5_KU_KRB_CRED,
					  buf,
					  len,
					  0,
					  &cred.enc_part);
	free(buf);
	krb5_crypto_destroy(context, crypto);
	if (ret) {
	    free_KRB_CRED(&cred);
	    return ret;
	}
    }

    ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret);
    free_KRB_CRED (&cred);
    if (ret)
	return ret;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    out_data->length = len;
    out_data->data   = buf;
    return 0;
 out4:
    free_EncKrbCredPart(&enc_krb_cred_part);
 out3:
    free_KRB_CRED(&cred);
 out2:
    krb5_free_creds (context, out_creds);
    return ret;
}
示例#9
0
static krb5_error_code
digest_request(krb5_context context,
	       krb5_realm realm,
	       krb5_ccache ccache,
	       krb5_key_usage usage,
	       const DigestReqInner *ireq,
	       DigestRepInner *irep)
{
    DigestREQ req;
    DigestREP rep;
    krb5_error_code ret;
    krb5_data data, data2;
    size_t size = 0;
    krb5_crypto crypto = NULL;
    krb5_auth_context ac = NULL;
    krb5_principal principal = NULL;
    krb5_ccache id = NULL;
    krb5_realm r = NULL;

    krb5_data_zero(&data);
    krb5_data_zero(&data2);
    memset(&req, 0, sizeof(req));
    memset(&rep, 0, sizeof(rep));

    if (ccache == NULL) {
	ret = krb5_cc_default(context, &id);
	if (ret)
	    goto out;
    } else
	id = ccache;

    if (realm == NULL) {
	ret = krb5_get_default_realm(context, &r);
	if (ret)
	    goto out;
    } else
	r = realm;

    /*
     *
     */

    ret = krb5_make_principal(context, &principal,
			      r, KRB5_DIGEST_NAME, r, NULL);
    if (ret)
	goto out;

    ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length,
		       ireq, &size, ret);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to encode digest inner request", ""));
	goto out;
    }
    if (size != data.length)
	krb5_abortx(context, "ASN.1 internal encoder error");

    ret = krb5_mk_req_exact(context, &ac,
			    AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED,
			    principal, NULL, id, &req.apReq);
    if (ret)
	goto out;

    {
	krb5_keyblock *key;

	ret = krb5_auth_con_getlocalsubkey(context, ac, &key);
	if (ret)
	    goto out;
	if (key == NULL) {
	    ret = EINVAL;
	    krb5_set_error_message(context, ret,
				   N_("Digest failed to get local subkey", ""));
	    goto out;
	}

	ret = krb5_crypto_init(context, key, 0, &crypto);
	krb5_free_keyblock (context, key);
	if (ret)
	    goto out;
    }

    ret = krb5_encrypt_EncryptedData(context, crypto, usage,
				     data.data, data.length, 0,
				     &req.innerReq);
    if (ret)
	goto out;

    krb5_data_free(&data);

    ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length,
		       &req, &size, ret);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to encode DigestREQest", ""));
	goto out;
    }
    if (size != data.length)
	krb5_abortx(context, "ASN.1 internal encoder error");

    ret = krb5_sendto_kdc(context, &data, &r, &data2);
    if (ret)
	goto out;

    ret = decode_DigestREP(data2.data, data2.length, &rep, NULL);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to parse digest response", ""));
	goto out;
    }

    {
	krb5_ap_rep_enc_part *repl;

	ret = krb5_rd_rep(context, ac, &rep.apRep, &repl);
	if (ret)
	    goto out;

	krb5_free_ap_rep_enc_part(context, repl);
    }
    {
	krb5_keyblock *key;

	ret = krb5_auth_con_getremotesubkey(context, ac, &key);
	if (ret)
	    goto out;
	if (key == NULL) {
	    ret = EINVAL;
	    krb5_set_error_message(context, ret,
				   N_("Digest reply have no remote subkey", ""));
	    goto out;
	}

	krb5_crypto_destroy(context, crypto);
	ret = krb5_crypto_init(context, key, 0, &crypto);
	krb5_free_keyblock (context, key);
	if (ret)
	    goto out;
    }

    krb5_data_free(&data);
    ret = krb5_decrypt_EncryptedData(context, crypto, usage,
				     &rep.innerRep, &data);
    if (ret)
	goto out;

    ret = decode_DigestRepInner(data.data, data.length, irep, NULL);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to decode digest inner reply", ""));
	goto out;
    }

 out:
    if (ccache == NULL && id)
	krb5_cc_close(context, id);
    if (realm == NULL && r)
	free(r);
    if (crypto)
	krb5_crypto_destroy(context, crypto);
    if (ac)
	krb5_auth_con_free(context, ac);
    if (principal)
	krb5_free_principal(context, principal);

    krb5_data_free(&data);
    krb5_data_free(&data2);

    free_DigestREQ(&req);
    free_DigestREP(&rep);

    return ret;
}
示例#10
0
static void
encode_ticket (krb5_context context,
	       EncryptionKey *skey,
	       krb5_enctype etype,
	       int skvno,
	       krb5_creds *cred)
{
    size_t len, size;
    char *buf;
    krb5_error_code ret;
    krb5_crypto crypto;
    EncryptedData enc_part;
    EncTicketPart et;
    Ticket ticket;

    memset (&enc_part, 0, sizeof(enc_part));
    memset (&ticket, 0, sizeof(ticket));

    /*
     * Set up `enc_part'
     */

    et.flags = cred->flags.b;
    et.key = cred->session;
    et.crealm = cred->client->realm;
    copy_PrincipalName(&cred->client->name, &et.cname);
    {
	krb5_data empty_string;

	krb5_data_zero(&empty_string);
	et.transited.tr_type = DOMAIN_X500_COMPRESS;
	et.transited.contents = empty_string;
    }
    et.authtime = cred->times.authtime;
    et.starttime = NULL;
    et.endtime = cred->times.endtime;
    et.renew_till = NULL;
    et.caddr = &cred->addresses;
    et.authorization_data = NULL; /* XXX allow random authorization_data */

    /*
     * Encrypt `enc_part' of ticket with service key
     */

    ASN1_MALLOC_ENCODE(EncTicketPart, buf, len, &et, &size, ret);
    if (ret)
	krb5_err(context, 1, ret, "EncTicketPart");

    ret = krb5_crypto_init(context, skey, etype, &crypto);
    if (ret)
	krb5_err(context, 1, ret, "krb5_crypto_init");
    ret = krb5_encrypt_EncryptedData (context,
				      crypto,
				      KRB5_KU_TICKET,
				      buf,
				      len,
				      skvno,
				      &ticket.enc_part);
    if (ret)
	krb5_err(context, 1, ret, "krb5_encrypt_EncryptedData");

    free(buf);
    krb5_crypto_destroy(context, crypto);

    /*
     * Encode ticket
     */

    ticket.tkt_vno = 5;
    ticket.realm = cred->server->realm;
    copy_PrincipalName(&cred->server->name, &ticket.sname);

    ASN1_MALLOC_ENCODE(Ticket, buf, len, &ticket, &size, ret);
    if(ret)
	krb5_err (context, 1, ret, "encode_Ticket");

    krb5_data_copy(&cred->ticket, buf, len);
    free(buf);
}
示例#11
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_forwarded_creds (krb5_context	    context,
			  krb5_auth_context auth_context,
			  krb5_ccache       ccache,
			  krb5_flags        flags,
			  const char        *hostname,
			  krb5_creds        *in_creds,
			  krb5_data         *out_data)
{
    krb5_error_code ret;
    krb5_creds *out_creds;
    krb5_addresses addrs, *paddrs;
    KRB_CRED cred;
    KrbCredInfo *krb_cred_info;
    EncKrbCredPart enc_krb_cred_part;
    size_t len;
    unsigned char *buf;
    size_t buf_size;
    krb5_kdc_flags kdc_flags;
    krb5_crypto crypto;
    struct addrinfo *ai;
    krb5_creds *ticket;

    paddrs = NULL;
    addrs.len = 0;
    addrs.val = NULL;

    ret = krb5_get_credentials(context, 0, ccache, in_creds, &ticket);
    if(ret == 0) {
	if (ticket->addresses.len)
	    paddrs = &addrs;
	krb5_free_creds (context, ticket);
    } else {
	krb5_boolean noaddr;
	krb5_appdefault_boolean(context, NULL,
				krb5_principal_get_realm(context,
							 in_creds->client),
				"no-addresses", KRB5_ADDRESSLESS_DEFAULT,
				&noaddr);
	if (!noaddr)
	    paddrs = &addrs;
    }

    /*
     * If tickets have addresses, get the address of the remote host.
     */

    if (paddrs != NULL) {

	ret = getaddrinfo (hostname, NULL, NULL, &ai);
	if (ret) {
	    krb5_error_code ret2 = krb5_eai_to_heim_errno(ret, errno);
	    krb5_set_error_message(context, ret2,
				   N_("resolving host %s failed: %s",
				      "hostname, error"),
				  hostname, gai_strerror(ret));
	    return ret2;
	}

	ret = add_addrs (context, &addrs, ai);
	freeaddrinfo (ai);
	if (ret)
	    return ret;
    }

    kdc_flags.b = int2KDCOptions(flags);

    ret = krb5_get_kdc_cred (context,
			     ccache,
			     kdc_flags,
			     paddrs,
			     NULL,
			     in_creds,
			     &out_creds);
    krb5_free_addresses (context, &addrs);
    if (ret)
	return ret;

    memset (&cred, 0, sizeof(cred));
    cred.pvno = 5;
    cred.msg_type = krb_cred;
    ALLOC_SEQ(&cred.tickets, 1);
    if (cred.tickets.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto out2;
    }
    ret = decode_Ticket(out_creds->ticket.data,
			out_creds->ticket.length,
			cred.tickets.val, &len);
    if (ret)
	goto out3;

    memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
    ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1);
    if (enc_krb_cred_part.ticket_info.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto out4;
    }

    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
	krb5_timestamp sec;
	int32_t usec;

	krb5_us_timeofday (context, &sec, &usec);

	ALLOC(enc_krb_cred_part.timestamp, 1);
	if (enc_krb_cred_part.timestamp == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	    goto out4;
	}
	*enc_krb_cred_part.timestamp = sec;
	ALLOC(enc_krb_cred_part.usec, 1);
	if (enc_krb_cred_part.usec == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	    goto out4;
	}
	*enc_krb_cred_part.usec      = usec;
    } else {
	enc_krb_cred_part.timestamp = NULL;
	enc_krb_cred_part.usec = NULL;
    }

    if (auth_context->local_address && auth_context->local_port && paddrs) {

	ret = krb5_make_addrport (context,
				  &enc_krb_cred_part.s_address,
				  auth_context->local_address,
				  auth_context->local_port);
	if (ret)
	    goto out4;
    }

    if (auth_context->remote_address) {
	if (auth_context->remote_port) {
	    krb5_boolean noaddr;
	    krb5_const_realm srealm;

	    srealm = krb5_principal_get_realm(context, out_creds->server);
	    /* Is this correct, and should we use the paddrs == NULL
               trick here as well? Having an address-less ticket may
               indicate that we don't know our own global address, but
               it does not necessary mean that we don't know the
               server's. */
	    krb5_appdefault_boolean(context, NULL, srealm, "no-addresses",
				    FALSE, &noaddr);
	    if (!noaddr) {
		ret = krb5_make_addrport (context,
					  &enc_krb_cred_part.r_address,
					  auth_context->remote_address,
					  auth_context->remote_port);
		if (ret)
		    goto out4;
	    }
	} else {
	    ALLOC(enc_krb_cred_part.r_address, 1);
	    if (enc_krb_cred_part.r_address == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret,
				       N_("malloc: out of memory", ""));
		goto out4;
	    }

	    ret = krb5_copy_address (context, auth_context->remote_address,
				     enc_krb_cred_part.r_address);
	    if (ret)
		goto out4;
	}
    }

    /* fill ticket_info.val[0] */

    enc_krb_cred_part.ticket_info.len = 1;

    krb_cred_info = enc_krb_cred_part.ticket_info.val;

    copy_EncryptionKey (&out_creds->session, &krb_cred_info->key);
    ALLOC(krb_cred_info->prealm, 1);
    copy_Realm (&out_creds->client->realm, krb_cred_info->prealm);
    ALLOC(krb_cred_info->pname, 1);
    copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname);
    ALLOC(krb_cred_info->flags, 1);
    *krb_cred_info->flags          = out_creds->flags.b;
    ALLOC(krb_cred_info->authtime, 1);
    *krb_cred_info->authtime       = out_creds->times.authtime;
    ALLOC(krb_cred_info->starttime, 1);
    *krb_cred_info->starttime      = out_creds->times.starttime;
    ALLOC(krb_cred_info->endtime, 1);
    *krb_cred_info->endtime        = out_creds->times.endtime;
    ALLOC(krb_cred_info->renew_till, 1);
    *krb_cred_info->renew_till = out_creds->times.renew_till;
    ALLOC(krb_cred_info->srealm, 1);
    copy_Realm (&out_creds->server->realm, krb_cred_info->srealm);
    ALLOC(krb_cred_info->sname, 1);
    copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname);
    ALLOC(krb_cred_info->caddr, 1);
    copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr);

    krb5_free_creds (context, out_creds);

    /* encode EncKrbCredPart */

    ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size,
		       &enc_krb_cred_part, &len, ret);
    free_EncKrbCredPart (&enc_krb_cred_part);
    if (ret) {
	free_KRB_CRED(&cred);
	return ret;
    }
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    /**
     * Some older of the MIT gssapi library used clear-text tickets
     * (warped inside AP-REQ encryption), use the krb5_auth_context
     * flag KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED to support those
     * tickets. The session key is used otherwise to encrypt the
     * forwarded ticket.
     */

    if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) {
	cred.enc_part.etype = KRB5_ENCTYPE_NULL;
	cred.enc_part.kvno = NULL;
	cred.enc_part.cipher.data = buf;
	cred.enc_part.cipher.length = buf_size;
    } else {
	/*
	 * Here older versions then 0.7.2 of Heimdal used the local or
	 * remote subkey. That is wrong, the session key should be
	 * used. Heimdal 0.7.2 and newer have code to try both in the
	 * receiving end.
	 */

	ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
	if (ret) {
	    free(buf);
	    free_KRB_CRED(&cred);
	    return ret;
	}
	ret = krb5_encrypt_EncryptedData (context,
					  crypto,
					  KRB5_KU_KRB_CRED,
					  buf,
					  len,
					  0,
					  &cred.enc_part);
	free(buf);
	krb5_crypto_destroy(context, crypto);
	if (ret) {
	    free_KRB_CRED(&cred);
	    return ret;
	}
    }

    ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret);
    free_KRB_CRED (&cred);
    if (ret)
	return ret;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    out_data->length = len;
    out_data->data   = buf;
    return 0;
 out4:
    free_EncKrbCredPart(&enc_krb_cred_part);
 out3:
    free_KRB_CRED(&cred);
 out2:
    krb5_free_creds (context, out_creds);
    return ret;
}
示例#12
0
/*
 * Encrypt the provided enc_tkt_part structure with the key from the keytab
 * entry entry, and place the resulting blob in the ticket_reply structure.
 */
static int
encrypt_enc_tkt(krb5_context context, krb5_principal service_principal,
		krb5_keytab_entry *entry, void *tr_out, void *er_in)
{
    krb5_error_code code;
#if USING_HEIMDAL
    Ticket *ticket_reply;
    EncTicketPart *enc_tkt_reply;
    krb5_crypto crypto = 0;
    unsigned char *buf = 0;
    size_t buf_size, buf_len;
#else
    krb5_ticket *ticket_reply;
    krb5_enc_tkt_part *enc_tkt_reply;
#endif

    /* Requisite aliasing for Heimdal/MIT support. */
    ticket_reply = tr_out;
    enc_tkt_reply = er_in;

#if USING_HEIMDAL
    ticket_reply->sname = service_principal->name;
    ticket_reply->realm = service_principal->realm;

    ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, enc_tkt_reply,
		       &buf_len, code);
    if (code != 0)
	goto cleanup;

    if (buf_len != buf_size)
	goto cleanup;
    code = krb5_crypto_init(context,
			    &deref_entry_keyblock(entry),
			    deref_entry_enctype(entry),
			    &crypto);
    if (code != 0)
	goto cleanup;
    code = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TICKET, buf,
				      buf_len, entry->vno,
				      &(ticket_reply->enc_part));
    if (code != 0)
	goto cleanup;
    ticket_reply->enc_part.etype = deref_entry_enctype(entry);
    *ticket_reply->enc_part.kvno = entry->vno;
    ticket_reply->tkt_vno = 5;
#else
    ticket_reply->server = service_principal;
    ticket_reply->enc_part2 = enc_tkt_reply;
    code = krb5_encrypt_tkt_part(context, &deref_entry_keyblock(entry),
				 ticket_reply);
    if (code != 0)
        goto cleanup;
    ticket_reply->enc_part.kvno = entry->vno;
#endif

cleanup:
#if USING_HEIMDAL
    if (buf != NULL)
	free(buf);
    if (crypto != NULL)
	krb5_crypto_destroy(context, crypto);
#endif
    return code;
}