diff options
Diffstat (limited to 'third_party/heimdal/lib/krb5/auth_context.c')
-rw-r--r-- | third_party/heimdal/lib/krb5/auth_context.c | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/krb5/auth_context.c b/third_party/heimdal/lib/krb5/auth_context.c new file mode 100644 index 0000000..8b43b63 --- /dev/null +++ b/third_party/heimdal/lib/krb5/auth_context.c @@ -0,0 +1,621 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (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 "krb5_locl.h" + +/** + * Allocate and initialize an autentication context. + * + * @param context A kerberos context. + * @param auth_context The authentication context to be initialized. + * + * Use krb5_auth_con_free() to release the memory when done using the context. + * + * @return An krb5 error code, see krb5_get_error_message(). + */ +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_init(krb5_context context, + krb5_auth_context *auth_context) +{ + krb5_auth_context p; + + ALLOC(p, 1); + if (!p) + return krb5_enomem(context); + memset(p, 0, sizeof(*p)); + ALLOC(p->authenticator, 1); + if (!p->authenticator) { + free(p); + return krb5_enomem(context); + } + memset (p->authenticator, 0, sizeof(*p->authenticator)); + p->flags = KRB5_AUTH_CONTEXT_DO_TIME; + + p->local_address = NULL; + p->remote_address = NULL; + p->local_port = 0; + p->remote_port = 0; + p->keytype = KRB5_ENCTYPE_NULL; + p->cksumtype = CKSUMTYPE_NONE; + p->auth_data = NULL; + *auth_context = p; + return 0; +} + +/** + * Deallocate an authentication context previously initialized with + * krb5_auth_con_init(). + * + * @param context A kerberos context. + * @param auth_context The authentication context to be deallocated. + * + * @return An krb5 error code, see krb5_get_error_message(). + */ +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_free(krb5_context context, + krb5_auth_context auth_context) +{ + if (auth_context != NULL) { + if (auth_context->authenticator) + krb5_free_authenticator(context, &auth_context->authenticator); + if(auth_context->local_address){ + free_HostAddress(auth_context->local_address); + free(auth_context->local_address); + } + if(auth_context->remote_address){ + free_HostAddress(auth_context->remote_address); + free(auth_context->remote_address); + } + krb5_free_keyblock(context, auth_context->keyblock); + krb5_free_keyblock(context, auth_context->remote_subkey); + krb5_free_keyblock(context, auth_context->local_subkey); + if (auth_context->auth_data) { + free_AuthorizationData(auth_context->auth_data); + free(auth_context->auth_data); + } + free (auth_context); + } + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setflags(krb5_context context, + krb5_auth_context auth_context, + int32_t flags) +{ + auth_context->flags = flags; + return 0; +} + + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getflags(krb5_context context, + krb5_auth_context auth_context, + int32_t *flags) +{ + *flags = auth_context->flags; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_addflags(krb5_context context, + krb5_auth_context auth_context, + int32_t addflags, + int32_t *flags) +{ + if (flags) + *flags = auth_context->flags; + auth_context->flags |= addflags; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_removeflags(krb5_context context, + krb5_auth_context auth_context, + int32_t removeflags, + int32_t *flags) +{ + if (flags) + *flags = auth_context->flags; + auth_context->flags &= ~removeflags; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setaddrs(krb5_context context, + krb5_auth_context auth_context, + krb5_address *local_addr, + krb5_address *remote_addr) +{ + if (local_addr) { + if (auth_context->local_address) + krb5_free_address (context, auth_context->local_address); + else + if ((auth_context->local_address = malloc(sizeof(krb5_address))) == NULL) + return krb5_enomem(context); + krb5_copy_address(context, local_addr, auth_context->local_address); + } + if (remote_addr) { + if (auth_context->remote_address) + krb5_free_address (context, auth_context->remote_address); + else + if ((auth_context->remote_address = malloc(sizeof(krb5_address))) == NULL) + return krb5_enomem(context); + krb5_copy_address(context, remote_addr, auth_context->remote_address); + } + return 0; +} + +/** + * Update the authentication context \a auth_context with the local + * and remote addresses from socket \a fd, according to \a flags. + * + * @return An krb5 error code, see krb5_get_error_message(). + */ +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_genaddrs(krb5_context context, + krb5_auth_context auth_context, + krb5_socket_t fd, int flags) +{ + krb5_error_code ret; + krb5_address local_k_address, remote_k_address; + krb5_address *lptr = NULL, *rptr = NULL; + struct sockaddr_storage ss_local, ss_remote; + struct sockaddr *local = (struct sockaddr *)&ss_local; + struct sockaddr *remote = (struct sockaddr *)&ss_remote; + socklen_t len; + + if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) { + if (auth_context->local_address == NULL) { + len = sizeof(ss_local); + if(rk_IS_SOCKET_ERROR(getsockname(fd, local, &len))) { + char buf[128]; + ret = rk_SOCK_ERRNO; + rk_strerror_r(ret, buf, sizeof(buf)); + krb5_set_error_message(context, ret, "getsockname: %s", buf); + goto out; + } + ret = krb5_sockaddr2address (context, local, &local_k_address); + if(ret) goto out; + if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) { + krb5_sockaddr2port (context, local, &auth_context->local_port); + } else + auth_context->local_port = 0; + lptr = &local_k_address; + } + } + if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) { + len = sizeof(ss_remote); + if(rk_IS_SOCKET_ERROR(getpeername(fd, remote, &len))) { + char buf[128]; + ret = rk_SOCK_ERRNO; + rk_strerror_r(ret, buf, sizeof(buf)); + krb5_set_error_message(context, ret, "getpeername: %s", buf); + goto out; + } + ret = krb5_sockaddr2address (context, remote, &remote_k_address); + if(ret) goto out; + if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) { + krb5_sockaddr2port (context, remote, &auth_context->remote_port); + } else + auth_context->remote_port = 0; + rptr = &remote_k_address; + } + ret = krb5_auth_con_setaddrs (context, + auth_context, + lptr, + rptr); + out: + if (lptr) + krb5_free_address (context, lptr); + if (rptr) + krb5_free_address (context, rptr); + return ret; + +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setaddrs_from_fd (krb5_context context, + krb5_auth_context auth_context, + void *p_fd) +{ + krb5_socket_t fd = *(krb5_socket_t *)p_fd; + int flags = 0; + if(auth_context->local_address == NULL) + flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR; + if(auth_context->remote_address == NULL) + flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR; + return krb5_auth_con_genaddrs(context, auth_context, fd, flags); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getaddrs(krb5_context context, + krb5_auth_context auth_context, + krb5_address **local_addr, + krb5_address **remote_addr) +{ + if(*local_addr) + krb5_free_address (context, *local_addr); + *local_addr = malloc (sizeof(**local_addr)); + if (*local_addr == NULL) + return krb5_enomem(context); + krb5_copy_address(context, + auth_context->local_address, + *local_addr); + + if(*remote_addr) + krb5_free_address (context, *remote_addr); + *remote_addr = malloc (sizeof(**remote_addr)); + if (*remote_addr == NULL) { + krb5_free_address (context, *local_addr); + *local_addr = NULL; + return krb5_enomem(context); + } + krb5_copy_address(context, + auth_context->remote_address, + *remote_addr); + return 0; +} + +/* coverity[+alloc : arg-*2] */ +static krb5_error_code +copy_key(krb5_context context, + krb5_keyblock *in, + krb5_keyblock **out) +{ + *out = NULL; + if (in) + return krb5_copy_keyblock(context, in, out); + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->keyblock, keyblock); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getlocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->local_subkey, keyblock); +} + +/* coverity[+alloc : arg-*2] */ +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getremotesubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->remote_subkey, keyblock); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + return copy_key(context, keyblock, &auth_context->keyblock); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setlocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->local_subkey) + krb5_free_keyblock(context, auth_context->local_subkey); + return copy_key(context, keyblock, &auth_context->local_subkey); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_generatelocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_keyblock *subkey; + + ret = krb5_generate_subkey_extended (context, key, + auth_context->keytype, + &subkey); + if(ret) + return ret; + if(auth_context->local_subkey) + krb5_free_keyblock(context, auth_context->local_subkey); + auth_context->local_subkey = subkey; + return 0; +} + + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setremotesubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->remote_subkey) + krb5_free_keyblock(context, auth_context->remote_subkey); + return copy_key(context, keyblock, &auth_context->remote_subkey); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setcksumtype(krb5_context context, + krb5_auth_context auth_context, + krb5_cksumtype cksumtype) +{ + auth_context->cksumtype = cksumtype; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getcksumtype(krb5_context context, + krb5_auth_context auth_context, + krb5_cksumtype *cksumtype) +{ + *cksumtype = auth_context->cksumtype; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setkeytype (krb5_context context, + krb5_auth_context auth_context, + krb5_keytype keytype) +{ + auth_context->keytype = keytype; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getkeytype (krb5_context context, + krb5_auth_context auth_context, + krb5_keytype *keytype) +{ + *keytype = auth_context->keytype; + return 0; +} + +krb5_error_code +_krb5_add_1auth_data(krb5_context context, + krb5int32 ad_type, krb5_data *ad_data, int critical, + krb5_authdata **dst) +{ + AuthorizationDataElement e; + + e.ad_type = ad_type; + e.ad_data = *ad_data; + + if (!critical) { + AuthorizationData ad; + krb5_error_code ret; + krb5_data ir; + size_t len; + + /* Build an AD-IF-RELEVANT with the new element inside it */ + ad.len = 0; + ad.val = NULL; + ret = add_AuthorizationData(&ad, &e); + + /* Encode the AD-IF-RELEVANT */ + if (ret == 0) + ASN1_MALLOC_ENCODE(AuthorizationData, ir.data, ir.length, &ad, + &len, ret); + if (ret == 0 && ir.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + /* Re-enter to add the encoded AD-IF-RELEVANT */ + ret = _krb5_add_1auth_data(context, KRB5_AUTHDATA_IF_RELEVANT, &ir, 1, + dst); + + free_AuthorizationData(&ad); + krb5_data_free(&ir); + return ret; + } + + if (*dst == NULL) { + ALLOC(*dst, 1); + if (*dst == NULL) + return krb5_enomem(context); + } + return add_AuthorizationData(*dst, &e); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_add_AuthorizationData(krb5_context context, + krb5_auth_context auth_context, + int type, + krb5_data *data) +{ + if (auth_context->auth_data == NULL) { + auth_context->auth_data = calloc(1, sizeof(*auth_context->auth_data)); + if (auth_context->auth_data == NULL) + return krb5_enomem(context); + } + return _krb5_add_1auth_data(context, type, data, 1, + &auth_context->auth_data); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_add_AuthorizationDataIfRelevant(krb5_context context, + krb5_auth_context auth_context, + krb5int32 type, + krb5_data *data) +{ + if (auth_context->auth_data == NULL) { + auth_context->auth_data = calloc(1, sizeof(*auth_context->auth_data)); + if (auth_context->auth_data == NULL) + return krb5_enomem(context); + } + return _krb5_add_1auth_data(context, type, data, 0, + &auth_context->auth_data); +} + + + +#if 0 +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setenctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype etype) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + ALLOC(auth_context->keyblock, 1); + if(auth_context->keyblock == NULL) + return krb5_enomem(context); + auth_context->keyblock->keytype = etype; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getenctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype *etype) +{ + krb5_abortx(context, "unimplemented krb5_auth_getenctype called"); +} +#endif + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getlocalseqnumber(krb5_context context, + krb5_auth_context auth_context, + int32_t *seqnumber) +{ + *seqnumber = auth_context->local_seqnumber; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setlocalseqnumber (krb5_context context, + krb5_auth_context auth_context, + int32_t seqnumber) +{ + auth_context->local_seqnumber = seqnumber; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getremoteseqnumber(krb5_context context, + krb5_auth_context auth_context, + int32_t *seqnumber) +{ + *seqnumber = auth_context->remote_seqnumber; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setremoteseqnumber (krb5_context context, + krb5_auth_context auth_context, + int32_t seqnumber) +{ + auth_context->remote_seqnumber = seqnumber; + return 0; +} + + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getauthenticator(krb5_context context, + krb5_auth_context auth_context, + krb5_authenticator *authenticator) +{ + *authenticator = malloc(sizeof(**authenticator)); + if (*authenticator == NULL) + return krb5_enomem(context); + + return copy_Authenticator(auth_context->authenticator, + *authenticator); +} + + +KRB5_LIB_FUNCTION void KRB5_LIB_CALL +krb5_free_authenticator(krb5_context context, + krb5_authenticator *authenticator) +{ + free_Authenticator (*authenticator); + free (*authenticator); + *authenticator = NULL; +} + + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setuserkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock); +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_getrcache(krb5_context context, + krb5_auth_context auth_context, + krb5_rcache *rcache) +{ + *rcache = auth_context->rcache; + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setrcache(krb5_context context, + krb5_auth_context auth_context, + krb5_rcache rcache) +{ + auth_context->rcache = rcache; + return 0; +} + +#if 0 /* not implemented */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_initivector(krb5_context context, + krb5_auth_context auth_context) +{ + krb5_abortx(context, "unimplemented krb5_auth_con_initivector called"); +} + + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_setivector(krb5_context context, + krb5_auth_context auth_context, + krb5_pointer ivector) +{ + krb5_abortx(context, "unimplemented krb5_auth_con_setivector called"); +} + +#endif /* not implemented */ |