2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A#include "k5-int.h"
2N/A#include "int-proto.h"
2N/A#include "auth_con.h"
2N/A
2N/Astatic krb5_boolean chk_heimdal_seqnum(krb5_ui_4, krb5_ui_4);
2N/A
2N/Astatic krb5_error_code
2N/Aactx_copy_addr(krb5_context context, const krb5_address *inad, krb5_address **outad)
2N/A{
2N/A krb5_address *tmpad;
2N/A
2N/A if (!(tmpad = (krb5_address *)malloc(sizeof(*tmpad))))
2N/A return ENOMEM;
2N/A *tmpad = *inad;
2N/A if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
2N/A free(tmpad);
2N/A return ENOMEM;
2N/A }
2N/A memcpy(tmpad->contents, inad->contents, inad->length);
2N/A *outad = tmpad;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context)
2N/A{
2N/A *auth_context =
2N/A (krb5_auth_context)calloc(1, sizeof(struct _krb5_auth_context));
2N/A if (!*auth_context)
2N/A return ENOMEM;
2N/A
2N/A /* Default flags, do time not seq */
2N/A (*auth_context)->auth_context_flags =
2N/A KRB5_AUTH_CONTEXT_DO_TIME | KRB5_AUTH_CONN_INITIALIZED;
2N/A
2N/A (*auth_context)->req_cksumtype = context->default_ap_req_sumtype;
2N/A (*auth_context)->safe_cksumtype = context->default_safe_sumtype;
2N/A (*auth_context)->checksum_func = NULL;
2N/A (*auth_context)->checksum_func_data = NULL;
2N/A (*auth_context)->negotiated_etype = ENCTYPE_NULL;
2N/A (*auth_context)->magic = KV5M_AUTH_CONTEXT;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_free(krb5_context context, krb5_auth_context auth_context)
2N/A{
2N/A if (auth_context == NULL)
2N/A return 0;
2N/A if (auth_context->local_addr)
2N/A krb5_free_address(context, auth_context->local_addr);
2N/A if (auth_context->remote_addr)
2N/A krb5_free_address(context, auth_context->remote_addr);
2N/A if (auth_context->local_port)
2N/A krb5_free_address(context, auth_context->local_port);
2N/A if (auth_context->remote_port)
2N/A krb5_free_address(context, auth_context->remote_port);
2N/A if (auth_context->authentp)
2N/A krb5_free_authenticator(context, auth_context->authentp);
2N/A if (auth_context->key)
2N/A krb5_k_free_key(context, auth_context->key);
2N/A if (auth_context->send_subkey)
2N/A krb5_k_free_key(context, auth_context->send_subkey);
2N/A if (auth_context->recv_subkey)
2N/A krb5_k_free_key(context, auth_context->recv_subkey);
2N/A if (auth_context->rcache)
2N/A krb5_rc_close(context, auth_context->rcache);
2N/A if (auth_context->permitted_etypes)
2N/A free(auth_context->permitted_etypes);
2N/A if (auth_context->ad_context)
2N/A krb5_authdata_context_free(context, auth_context->ad_context);
2N/A free(auth_context);
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr)
2N/A{
2N/A krb5_error_code retval;
2N/A
2N/A /* Free old addresses */
2N/A if (auth_context->local_addr)
2N/A (void) krb5_free_address(context, auth_context->local_addr);
2N/A if (auth_context->remote_addr)
2N/A (void) krb5_free_address(context, auth_context->remote_addr);
2N/A
2N/A retval = 0;
2N/A if (local_addr)
2N/A retval = actx_copy_addr(context,
2N/A local_addr,
2N/A &auth_context->local_addr);
2N/A else
2N/A auth_context->local_addr = NULL;
2N/A
2N/A if (!retval && remote_addr)
2N/A retval = actx_copy_addr(context,
2N/A remote_addr,
2N/A &auth_context->remote_addr);
2N/A else
2N/A auth_context->remote_addr = NULL;
2N/A
2N/A return retval;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr)
2N/A{
2N/A krb5_error_code retval;
2N/A
2N/A retval = 0;
2N/A if (local_addr && auth_context->local_addr) {
2N/A retval = actx_copy_addr(context,
2N/A auth_context->local_addr,
2N/A local_addr);
2N/A }
2N/A if (!retval && (remote_addr) && auth_context->remote_addr) {
2N/A retval = actx_copy_addr(context,
2N/A auth_context->remote_addr,
2N/A remote_addr);
2N/A }
2N/A return retval;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port)
2N/A{
2N/A krb5_error_code retval;
2N/A
2N/A /* Free old addresses */
2N/A if (auth_context->local_port)
2N/A (void) krb5_free_address(context, auth_context->local_port);
2N/A if (auth_context->remote_port)
2N/A (void) krb5_free_address(context, auth_context->remote_port);
2N/A
2N/A retval = 0;
2N/A if (local_port)
2N/A retval = actx_copy_addr(context,
2N/A local_port,
2N/A &auth_context->local_port);
2N/A else
2N/A auth_context->local_port = NULL;
2N/A
2N/A if (!retval && remote_port)
2N/A retval = actx_copy_addr(context,
2N/A remote_port,
2N/A &auth_context->remote_port);
2N/A else
2N/A auth_context->remote_port = NULL;
2N/A
2N/A return retval;
2N/A}
2N/A
2N/A
2N/A/*
2N/A * This function overloads the keyblock field. It is only useful prior to
2N/A * a krb5_rd_req_decode() call for user to user authentication where the
2N/A * server has the key and needs to use it to decrypt the incoming request.
2N/A * Once decrypted this key is no longer necessary and is then overwritten
2N/A * with the session key sent by the client.
2N/A */
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock)
2N/A{
2N/A if (auth_context->key)
2N/A krb5_k_free_key(context, auth_context->key);
2N/A return(krb5_k_create_key(context, keyblock, &(auth_context->key)));
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
2N/A{
2N/A if (auth_context->key)
2N/A return krb5_k_key_keyblock(context, auth_context->key, keyblock);
2N/A *keyblock = NULL;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getkey_k(krb5_context context, krb5_auth_context auth_context,
2N/A krb5_key *key)
2N/A{
2N/A krb5_k_reference_key(context, auth_context->key);
2N/A *key = auth_context->key;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
2N/A{
2N/A return krb5_auth_con_getsendsubkey(context, auth_context, keyblock);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
2N/A{
2N/A return krb5_auth_con_getrecvsubkey(context, auth_context, keyblock);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
2N/A{
2N/A if (ac->send_subkey != NULL)
2N/A krb5_k_free_key(ctx, ac->send_subkey);
2N/A ac->send_subkey = NULL;
2N/A if (keyblock !=NULL)
2N/A return krb5_k_create_key(ctx, keyblock, &ac->send_subkey);
2N/A else
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
2N/A{
2N/A if (ac->recv_subkey != NULL)
2N/A krb5_k_free_key(ctx, ac->recv_subkey);
2N/A ac->recv_subkey = NULL;
2N/A if (keyblock != NULL)
2N/A return krb5_k_create_key(ctx, keyblock, &ac->recv_subkey);
2N/A else
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
2N/A{
2N/A if (ac->send_subkey != NULL)
2N/A return krb5_k_key_keyblock(ctx, ac->send_subkey, keyblock);
2N/A *keyblock = NULL;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getsendsubkey_k(krb5_context ctx, krb5_auth_context ac,
2N/A krb5_key *key)
2N/A{
2N/A krb5_k_reference_key(ctx, ac->send_subkey);
2N/A *key = ac->send_subkey;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
2N/A{
2N/A if (ac->recv_subkey != NULL)
2N/A return krb5_k_key_keyblock(ctx, ac->recv_subkey, keyblock);
2N/A *keyblock = NULL;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getrecvsubkey_k(krb5_context ctx, krb5_auth_context ac,
2N/A krb5_key *key)
2N/A{
2N/A krb5_k_reference_key(ctx, ac->recv_subkey);
2N/A *key = ac->recv_subkey;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
2N/A{
2N/A auth_context->req_cksumtype = cksumtype;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_set_safe_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
2N/A{
2N/A auth_context->safe_cksumtype = cksumtype;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
2N/A{
2N/A *seqnumber = auth_context->local_seq_number;
2N/A return 0;
2N/A}
2N/A#ifndef LEAN_CLIENT
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, krb5_authenticator **authenticator)
2N/A{
2N/A return (krb5_copy_authenticator(context, auth_context->authentp,
2N/A authenticator));
2N/A}
2N/A#endif
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
2N/A{
2N/A *seqnumber = auth_context->remote_seq_number;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context)
2N/A{
2N/A krb5_error_code ret;
2N/A krb5_enctype enctype;
2N/A
2N/A if (auth_context->key) {
2N/A size_t blocksize;
2N/A
2N/A enctype = krb5_k_key_enctype(context, auth_context->key);
2N/A if ((ret = krb5_c_block_size(context, enctype, &blocksize)))
2N/A return(ret);
2N/A if ((auth_context->i_vector = (krb5_pointer)calloc(1,blocksize))) {
2N/A return 0;
2N/A }
2N/A return ENOMEM;
2N/A }
2N/A return EINVAL; /* XXX need an error for no keyblock */
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_setivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer ivector)
2N/A{
2N/A auth_context->i_vector = ivector;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_getivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer *ivector)
2N/A{
2N/A *ivector = auth_context->i_vector;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags)
2N/A{
2N/A auth_context->auth_context_flags = flags;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 *flags)
2N/A{
2N/A *flags = auth_context->auth_context_flags;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache)
2N/A{
2N/A auth_context->rcache = rcache;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache *rcache)
2N/A{
2N/A *rcache = auth_context->rcache;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_setpermetypes(krb5_context context,
2N/A krb5_auth_context auth_context,
2N/A const krb5_enctype *permetypes)
2N/A{
2N/A krb5_enctype *newpe;
2N/A krb5_error_code ret;
2N/A
2N/A ret = krb5int_copy_etypes(permetypes, &newpe);
2N/A if (ret != 0)
2N/A return ret;
2N/A
2N/A free(auth_context->permitted_etypes);
2N/A auth_context->permitted_etypes = newpe;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_getpermetypes(krb5_context context,
2N/A krb5_auth_context auth_context,
2N/A krb5_enctype **permetypes)
2N/A{
2N/A *permetypes = NULL;
2N/A if (auth_context->permitted_etypes == NULL)
2N/A return 0;
2N/A return krb5int_copy_etypes(auth_context->permitted_etypes, permetypes);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_set_checksum_func( krb5_context context,
2N/A krb5_auth_context auth_context,
2N/A krb5_mk_req_checksum_func func,
2N/A void *data)
2N/A{
2N/A auth_context->checksum_func = func;
2N/A auth_context->checksum_func_data = data;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_get_checksum_func( krb5_context context,
2N/A krb5_auth_context auth_context,
2N/A krb5_mk_req_checksum_func *func,
2N/A void **data)
2N/A{
2N/A *func = auth_context->checksum_func;
2N/A *data = auth_context->checksum_func_data;
2N/A return 0;
2N/A}
2N/A
2N/A/*
2N/A * krb5int_auth_con_chkseqnum
2N/A *
2N/A * We use a somewhat complex heuristic for validating received
2N/A * sequence numbers. We must accommodate both our older
2N/A * implementation, which sends negative sequence numbers, and the
2N/A * broken Heimdal implementation (at least as of 0.5.2), which
2N/A * violates X.690 BER for integer encodings. The requirement of
2N/A * handling negative sequence numbers removes one of easier means of
2N/A * detecting a Heimdal implementation, so we resort to this mess
2N/A * here.
2N/A *
2N/A * X.690 BER (and consequently DER, which are the required encoding
2N/A * rules in RFC1510) encode all integer types as signed integers.
2N/A * This means that the MSB being set on the first octet of the
2N/A * contents of the encoding indicates a negative value. Heimdal does
2N/A * not prepend the required zero octet to unsigned integer encodings
2N/A * which would otherwise have the MSB of the first octet of their
2N/A * encodings set.
2N/A *
2N/A * Our ASN.1 library implements a special decoder for sequence
2N/A * numbers, accepting both negative and positive 32-bit numbers but
2N/A * mapping them both into the space of positive unsigned 32-bit
2N/A * numbers in the obvious bit-pattern-preserving way. This maintains
2N/A * compatibility with our older implementations. This also means that
2N/A * encodings emitted by Heimdal are ambiguous.
2N/A *
2N/A * Heimdal counter value received uint32 value
2N/A *
2N/A * 0x00000080 0xFFFFFF80
2N/A * 0x000000FF 0xFFFFFFFF
2N/A * 0x00008000 0xFFFF8000
2N/A * 0x0000FFFF 0xFFFFFFFF
2N/A * 0x00800000 0xFF800000
2N/A * 0x00FFFFFF 0xFFFFFFFF
2N/A * 0xFF800000 0xFF800000
2N/A * 0xFFFFFFFF 0xFFFFFFFF
2N/A *
2N/A * We use two auth_context flags, SANE_SEQ and HEIMDAL_SEQ, which are
2N/A * only set after we can unambiguously determine the sanity of the
2N/A * sending implementation. Once one of these flags is set, we accept
2N/A * only the sequence numbers appropriate to the remote implementation
2N/A * type. We can make the determination in two different ways. The
2N/A * first is to note the receipt of a "negative" sequence number when a
2N/A * "positive" one was expected. The second is to note the receipt of
2N/A * a sequence number that wraps through "zero" in a weird way. The
2N/A * latter corresponds to the receipt of an initial sequence number in
2N/A * the ambiguous range.
2N/A *
2N/A * There are 2^7 + 2^15 + 2^23 + 2^23 = 16810112 total ambiguous
2N/A * initial Heimdal counter values, but we receive them as one of 2^23
2N/A * possible values. There is a ~1/256 chance of a Heimdal
2N/A * implementation sending an intial sequence number in the ambiguous
2N/A * range.
2N/A *
2N/A * We have to do special treatment when receiving sequence numbers
2N/A * between 0xFF800000..0xFFFFFFFF, or when wrapping through zero
2N/A * weirdly (due to ambiguous initial sequence number). If we are
2N/A * expecting a value corresponding to an ambiguous Heimdal counter
2N/A * value, and we receive an exact match, we can mark the remote end as
2N/A * sane.
2N/A */
2N/Akrb5_boolean
2N/Akrb5int_auth_con_chkseqnum(
2N/A krb5_context ctx,
2N/A krb5_auth_context ac,
2N/A krb5_ui_4 in_seq)
2N/A{
2N/A krb5_ui_4 exp_seq;
2N/A
2N/A exp_seq = ac->remote_seq_number;
2N/A
2N/A /*
2N/A * If sender is known to be sane, accept _only_ exact matches.
2N/A */
2N/A if (ac->auth_context_flags & KRB5_AUTH_CONN_SANE_SEQ)
2N/A return in_seq == exp_seq;
2N/A
2N/A /*
2N/A * If sender is not known to be sane, first check the ambiguous
2N/A * range of received values, 0xFF800000..0xFFFFFFFF.
2N/A */
2N/A if ((in_seq & 0xFF800000) == 0xFF800000) {
2N/A /*
2N/A * If expected sequence number is in the range
2N/A * 0xFF800000..0xFFFFFFFF, then we can't make any
2N/A * determinations about the sanity of the sending
2N/A * implementation.
2N/A */
2N/A if ((exp_seq & 0xFF800000) == 0xFF800000 && in_seq == exp_seq)
2N/A return 1;
2N/A /*
2N/A * If sender is not known for certain to be a broken Heimdal
2N/A * implementation, check for exact match.
2N/A */
2N/A if (!(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)
2N/A && in_seq == exp_seq)
2N/A return 1;
2N/A /*
2N/A * Now apply hairy algorithm for matching sequence numbers
2N/A * sent by broken Heimdal implementations. If it matches, we
2N/A * know for certain it's a broken Heimdal sender.
2N/A */
2N/A if (chk_heimdal_seqnum(exp_seq, in_seq)) {
2N/A ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
2N/A return 1;
2N/A }
2N/A return 0;
2N/A }
2N/A
2N/A /*
2N/A * Received value not in the ambiguous range? If the _expected_
2N/A * value is in the range of ambiguous Hemidal counter values, and
2N/A * it matches the received value, sender is known to be sane.
2N/A */
2N/A if (in_seq == exp_seq) {
2N/A if (( exp_seq & 0xFFFFFF80) == 0x00000080
2N/A || (exp_seq & 0xFFFF8000) == 0x00008000
2N/A || (exp_seq & 0xFF800000) == 0x00800000)
2N/A ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ;
2N/A return 1;
2N/A }
2N/A
2N/A /*
2N/A * Magic wraparound for the case where the intial sequence number
2N/A * is in the ambiguous range. This means that the sender's
2N/A * counter is at a different count than ours, so we correct ours,
2N/A * and mark the sender as being a broken Heimdal implementation.
2N/A */
2N/A if (exp_seq == 0
2N/A && !(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)) {
2N/A switch (in_seq) {
2N/A case 0x100:
2N/A case 0x10000:
2N/A case 0x1000000:
2N/A ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
2N/A exp_seq = in_seq;
2N/A return 1;
2N/A default:
2N/A return 0;
2N/A }
2N/A }
2N/A return 0;
2N/A}
2N/A
2N/Astatic krb5_boolean
2N/Achk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq)
2N/A{
2N/A if (( exp_seq & 0xFF800000) == 0x00800000
2N/A && (in_seq & 0xFF800000) == 0xFF800000
2N/A && (in_seq & 0x00FFFFFF) == exp_seq)
2N/A return 1;
2N/A else if (( exp_seq & 0xFFFF8000) == 0x00008000
2N/A && (in_seq & 0xFFFF8000) == 0xFFFF8000
2N/A && (in_seq & 0x0000FFFF) == exp_seq)
2N/A return 1;
2N/A else if (( exp_seq & 0xFFFFFF80) == 0x00000080
2N/A && (in_seq & 0xFFFFFF80) == 0xFFFFFF80
2N/A && (in_seq & 0x000000FF) == exp_seq)
2N/A return 1;
2N/A else
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_auth_con_get_subkey_enctype(krb5_context context,
2N/A krb5_auth_context auth_context,
2N/A krb5_enctype *etype)
2N/A{
2N/A *etype = auth_context->negotiated_etype;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_get_authdata_context(krb5_context context,
2N/A krb5_auth_context auth_context,
2N/A krb5_authdata_context *ad_context)
2N/A{
2N/A *ad_context = auth_context->ad_context;
2N/A return 0;
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_auth_con_set_authdata_context(krb5_context context,
2N/A krb5_auth_context auth_context,
2N/A krb5_authdata_context ad_context)
2N/A{
2N/A auth_context->ad_context = ad_context;
2N/A return 0;
2N/A}