/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include "k5-int.h"
#include "auth_con.h"
/*ARGSUSED*/
static krb5_error_code
{
return ENOMEM;
return ENOMEM;
}
/* Solaris Kerberos */
return 0;
}
{
*auth_context =
if (!*auth_context)
return ENOMEM;
/* Solaris Kerberos */
/* Default flags, do time not seq */
return 0;
}
{
if (auth_context->local_addr)
if (auth_context->remote_addr)
if (auth_context->local_port)
if (auth_context->remote_port)
if (auth_context->authentp)
if (auth_context->keyblock)
if (auth_context->send_subkey)
if (auth_context->recv_subkey)
/* Solaris Kerberos */
if (auth_context->rcache)
if (auth_context->permitted_etypes)
return 0;
}
krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr)
{
/* Free old addresses */
if (auth_context->local_addr)
if (auth_context->remote_addr)
retval = 0;
if (local_addr)
else
if (!retval && remote_addr)
else
return retval;
}
krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr)
{
retval = 0;
}
}
return retval;
}
krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port)
{
/* Free old addresses */
if (auth_context->local_port)
if (auth_context->remote_port)
retval = 0;
if (local_port)
else
if (!retval && remote_port)
else
return retval;
}
/*
* This function overloads the keyblock field. It is only useful prior to
* a krb5_rd_req_decode() call for user to user authentication where the
* server has the key and needs to use it to decrypt the incoming request.
* Once decrypted this key is no longer necessary and is then overwritten
* with the session key sent by the client.
*/
krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock)
{
if (auth_context->keyblock)
}
krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
{
if (auth_context->keyblock)
return 0;
}
krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
{
}
krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
{
}
{
else
return 0;
}
{
else
return 0;
}
{
return 0;
}
{
return 0;
}
/*ARGSUSED*/
krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
{
return 0;
}
/*ARGSUSED*/
krb5_auth_con_set_safe_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
{
return 0;
}
/*ARGSUSED*/
krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
{
return 0;
}
krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, krb5_authenticator **authenticator)
{
}
/*ARGSUSED*/
krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
{
return 0;
}
{
if (auth_context->keyblock) {
&blocksize)))
return(ret);
return 0;
}
return ENOMEM;
}
return EINVAL; /* XXX need an error for no keyblock */
}
/*ARGSUSED*/
krb5_auth_con_setivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer ivector)
{
return 0;
}
/*ARGSUSED*/
krb5_auth_con_getivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer *ivector)
{
return 0;
}
/*ARGSUSED*/
{
return 0;
}
/*ARGSUSED*/
{
return 0;
}
/*ARGSUSED*/
{
return 0;
}
/*ARGSUSED*/
{
return 0;
}
/*ARGSUSED*/
krb5_auth_con_setpermetypes(krb5_context context, krb5_auth_context auth_context, const krb5_enctype *permetypes)
{
int i;
for (i=0; permetypes[i]; i++)
;
i++; /* include the zero */
== NULL)
return(ENOMEM);
if (auth_context->permitted_etypes)
/* Solaris Kerberos */
return 0;
}
/*ARGSUSED*/
krb5_auth_con_getpermetypes(krb5_context context, krb5_auth_context auth_context, krb5_enctype **permetypes)
{
int i;
if (! auth_context->permitted_etypes) {
*permetypes = NULL;
return(0);
}
for (i=0; auth_context->permitted_etypes[i]; i++)
;
i++; /* include the zero */
== NULL)
return(ENOMEM);
*permetypes = newpe;
return(0);
}
void *data)
{
return 0;
}
void **data)
{
return 0;
}
/*
* krb5int_auth_con_chkseqnum
*
* We use a somewhat complex heuristic for validating received
* sequence numbers. We must accommodate both our older
* implementation, which sends negative sequence numbers, and the
* broken Heimdal implementation (at least as of 0.5.2), which
* violates X.690 BER for integer encodings. The requirement of
* handling negative sequence numbers removes one of easier means of
* detecting a Heimdal implementation, so we resort to this mess
* here.
*
* X.690 BER (and consequently DER, which are the required encoding
* rules in RFC1510) encode all integer types as signed integers.
* This means that the MSB being set on the first octet of the
* contents of the encoding indicates a negative value. Heimdal does
* not prepend the required zero octet to unsigned integer encodings
* which would otherwise have the MSB of the first octet of their
* encodings set.
*
* Our ASN.1 library implements a special decoder for sequence
* numbers, accepting both negative and positive 32-bit numbers but
* mapping them both into the space of positive unsigned 32-bit
* numbers in the obvious bit-pattern-preserving way. This maintains
* compatibility with our older implementations. This also means that
* encodings emitted by Heimdal are ambiguous.
*
* Heimdal counter value received uint32 value
*
* 0x00000080 0xFFFFFF80
* 0x000000FF 0xFFFFFFFF
* 0x00008000 0xFFFF8000
* 0x0000FFFF 0xFFFFFFFF
* 0x00800000 0xFF800000
* 0x00FFFFFF 0xFFFFFFFF
* 0xFF800000 0xFF800000
* 0xFFFFFFFF 0xFFFFFFFF
*
* We use two auth_context flags, SANE_SEQ and HEIMDAL_SEQ, which are
* only set after we can unambiguously determine the sanity of the
* sending implementation. Once one of these flags is set, we accept
* only the sequence numbers appropriate to the remote implementation
* type. We can make the determination in two different ways. The
* first is to note the receipt of a "negative" sequence number when a
* "positive" one was expected. The second is to note the receipt of
* a sequence number that wraps through "zero" in a weird way. The
* latter corresponds to the receipt of an initial sequence number in
* the ambiguous range.
*
* There are 2^7 + 2^15 + 2^23 + 2^23 = 16810112 total ambiguous
* initial Heimdal counter values, but we receive them as one of 2^23
* possible values. There is a ~1/256 chance of a Heimdal
* implementation sending an intial sequence number in the ambiguous
* range.
*
* We have to do special treatment when receiving sequence numbers
* between 0xFF800000..0xFFFFFFFF, or when wrapping through zero
* weirdly (due to ambiguous initial sequence number). If we are
* expecting a value corresponding to an ambiguous Heimdal counter
* value, and we receive an exact match, we can mark the remote end as
* sane.
*/
{
/*
* If sender is known to be sane, accept _only_ exact matches.
*/
/*
* If sender is not known to be sane, first check the ambiguous
* range of received values, 0xFF800000..0xFFFFFFFF.
*/
/*
* If expected sequence number is in the range
* 0xFF800000..0xFFFFFFFF, then we can't make any
* determinations about the sanity of the sending
* implementation.
*/
return 1;
/*
* If sender is not known for certain to be a broken Heimdal
* implementation, check for exact match.
*/
return 1;
/*
* Now apply hairy algorithm for matching sequence numbers
* sent by broken Heimdal implementations. If it matches, we
* know for certain it's a broken Heimdal sender.
*/
return 1;
}
return 0;
}
/*
* Received value not in the ambiguous range? If the _expected_
* value is in the range of ambiguous Hemidal counter values, and
* it matches the received value, sender is known to be sane.
*/
return 1;
}
/*
* Magic wraparound for the case where the intial sequence number
* is in the ambiguous range. This means that the sender's
* counter is at a different count than ours, so we correct ours,
* and mark the sender as being a broken Heimdal implementation.
*/
if (exp_seq == 0
switch (in_seq) {
case 0x100:
case 0x10000:
case 0x1000000:
return 1;
default:
return 0;
}
}
return 0;
}
static krb5_boolean
{
return 1;
return 1;
return 1;
else
return 0;
}