summaryrefslogtreecommitdiff
path: root/third_party/heimdal/lib/krb5/auth_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib/krb5/auth_context.c')
-rw-r--r--third_party/heimdal/lib/krb5/auth_context.c622
1 files changed, 622 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 00000000000..43c762b7699
--- /dev/null
+++ b/third_party/heimdal/lib/krb5/auth_context.c
@@ -0,0 +1,622 @@
+/*
+ * 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);
+
+ copy_Authenticator(auth_context->authenticator,
+ *authenticator);
+ return 0;
+}
+
+
+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 */