From: Matt Rogers Date: Fri, 13 May 2016 00:06:42 +0000 (-0400) Subject: Add auth indicator authdata module X-Git-Tag: krb5-1.15-beta1~171 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=365ac06e3d70f48e6dbfff4dfe259e2725a9f6c1;p=thirdparty%2Fkrb5.git Add auth indicator authdata module This authdata module makes the 'auth-indicator' attribute available to the GSSAPI name extension functions. The auth indicator values are UTF8 strings imported during AP_REQ processing. ticket: 8425 --- diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 2c6ea5cd09..ad5ef9357f 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -17,6 +17,7 @@ STLIBOBJS= \ addr_srch.o \ allow_weak.o \ appdefault.o \ + ai_authdata.o \ auth_con.o \ cammac_util.o \ authdata.o \ @@ -128,6 +129,7 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ $(OUTPRE)addr_srch.$(OBJEXT) \ $(OUTPRE)allow_weak.$(OBJEXT) \ $(OUTPRE)appdefault.$(OBJEXT) \ + $(OUTPRE)ai_authdata.$(OBJEXT) \ $(OUTPRE)auth_con.$(OBJEXT) \ $(OUTPRE)cammac_util.$(OBJEXT) \ $(OUTPRE)authdata.$(OBJEXT) \ @@ -240,6 +242,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/appdefault.c \ $(srcdir)/auth_con.c \ $(srcdir)/cammac_util.c \ + $(srcdir)/ai_authdata.c \ $(srcdir)/authdata.c \ $(srcdir)/authdata_exp.c \ $(srcdir)/authdata_enc.c \ @@ -385,7 +388,7 @@ T_KERB_OBJS= t_kerb.o conv_princ.o unparse.o set_realm.o str_conv.o T_SER_OBJS= t_ser.o ser_actx.o ser_adata.o ser_addr.o ser_auth.o ser_cksum.o \ ser_ctx.o ser_key.o ser_princ.o serialize.o authdata.o pac.o \ - pac_sign.o authdata_exp.o s4u_authdata.o copy_data.o etype_list.o + pac_sign.o ai_authdata.o authdata_exp.o s4u_authdata.o copy_data.o etype_list.o T_DELTAT_OBJS= t_deltat.o deltat.o diff --git a/src/lib/krb5/krb/ai_authdata.c b/src/lib/krb5/krb/ai_authdata.c new file mode 100644 index 0000000000..45a3ac6cb0 --- /dev/null +++ b/src/lib/krb5/krb/ai_authdata.c @@ -0,0 +1,340 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* src/lib/krb5/krb/ai_authdata.c - auth-indicator authdata module */ +/* + * Copyright (C) 2016 by Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 "k5-int.h" +#include "authdata.h" +#include "auth_con.h" +#include "int-proto.h" + +struct authind_context { + krb5_data **indicators; + int count; +}; + +static krb5_error_code +authind_init(krb5_context kcontext, void **plugin_context) +{ + *plugin_context = NULL; + return 0; +} + +static void +authind_flags(krb5_context kcontext, void *plugin_context, + krb5_authdatatype ad_type, krb5_flags *flags) +{ + *flags = AD_CAMMAC_PROTECTED; +} + +static krb5_error_code +authind_request_init(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void **request_context) +{ + krb5_error_code ret = 0; + struct authind_context *aictx; + + *request_context = NULL; + + aictx = k5alloc(sizeof(*aictx), &ret); + if (aictx == NULL) + return ret; + aictx->indicators = NULL; + aictx->count = 0; + *request_context = aictx; + return ret; +} + +static krb5_error_code +authind_import_authdata(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + krb5_authdata **authdata, krb5_boolean kdc_issued, + krb5_const_principal kdc_issuer) +{ + struct authind_context *aictx = request_context; + krb5_error_code ret = 0; + krb5_data **indps = NULL; + int count, i; + + for (i = 0; authdata != NULL && authdata[i] != NULL; i++) { + ret = k5_authind_decode(authdata[i], &indps); + if (ret) + goto cleanup; + } + + for (count = 0; indps != NULL && indps[count] != NULL; count++); + if (count != 0) { + aictx->indicators = indps; + aictx->count = count; + indps = NULL; + } + +cleanup: + k5_free_data_ptr_list(indps); + return ret; +} + +static void +authind_request_fini(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context) +{ + struct authind_context *aictx = request_context; + + if (aictx != NULL) { + k5_free_data_ptr_list(aictx->indicators); + free(aictx); + } +} + +/* This is a non-URI "local attribute" that is implementation defined. */ +static krb5_data authind_attr = { + KV5M_DATA, + sizeof("auth-indicators") - 1, + "auth-indicators" +}; + +static krb5_error_code +authind_get_attribute_types(krb5_context kcontext, + krb5_authdata_context context, + void *plugin_context, void *request_context, + krb5_data **out_attrs) +{ + struct authind_context *aictx = (struct authind_context *)request_context; + krb5_error_code ret; + krb5_data *attrs; + + *out_attrs = NULL; + + if (aictx->count == 0) + return ENOENT; + + attrs = k5calloc(2, sizeof(*attrs), &ret); + if (attrs == NULL) + return ENOMEM; + + ret = krb5int_copy_data_contents(kcontext, &authind_attr, &attrs[0]); + if (ret) + goto cleanup; + + attrs[1].data = NULL; + attrs[1].length = 0; + + *out_attrs = attrs; + attrs = NULL; + +cleanup: + krb5int_free_data_list(kcontext, attrs); + return ret; +} + +static krb5_error_code +authind_get_attribute(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + const krb5_data *attribute, krb5_boolean *authenticated, + krb5_boolean *complete, krb5_data *value, + krb5_data *display_value, int *more) +{ + struct authind_context *aictx = (struct authind_context *)request_context; + krb5_error_code ret; + krb5_data *value_out; + int left; + + if (!data_eq(*attribute, authind_attr)) + return ENOENT; + + /* The caller should set more to -1 before the first call. Successive + * calls return the number of indicators left, ending at 0. */ + left = (*more < 0) ? aictx->count : *more; + if (left <= 0) + return ENOENT; + else if (left > aictx->count) + return EINVAL; + + ret = krb5_copy_data(kcontext, aictx->indicators[aictx->count - left], + &value_out); + if (ret) + return ret; + + *more = left - 1; + *value = *value_out; + /* Indicators are delivered in a CAMMAC verified outside of this module, + * so these are authenticated values. */ + *authenticated = TRUE; + *complete = TRUE; + + free(value_out); + return ret; +} + +static krb5_error_code +authind_set_attribute(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + krb5_boolean complete, const krb5_data *attribute, + const krb5_data *value) +{ + /* Indicators are imported from ticket authdata, not set by this module. */ + if (!data_eq(*attribute, authind_attr)) + return ENOENT; + + return EPERM; +} + +static krb5_error_code +authind_size(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, size_t *sizep) +{ + struct authind_context *aictx = (struct authind_context *)request_context; + int i; + + /* Add the indicator count. */ + *sizep += sizeof(int32_t); + + /* Add each indicator's length and value. */ + for (i = 0; i < aictx->count; i++) + *sizep += sizeof(int32_t) + aictx->indicators[i]->length; + + return 0; +} + +static krb5_error_code +authind_externalize(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + uint8_t **buffer, size_t *lenremain) +{ + struct authind_context *aictx = (struct authind_context *)request_context; + krb5_error_code ret = 0; + uint8_t *bp = *buffer; + size_t remain = *lenremain; + int i; + + /* Serialize the indicator count. */ + krb5_ser_pack_int32(aictx->count, &bp, &remain); + + for (i = 0; i < aictx->count; i++) { + /* Serialize the length and indicator value. */ + krb5_ser_pack_int32(aictx->indicators[i]->length, &bp, &remain); + ret = krb5_ser_pack_bytes((uint8_t *)aictx->indicators[i]->data, + aictx->indicators[i]->length, &bp, &remain); + if (ret) + return ret; + } + + *buffer = bp; + *lenremain = remain; + return ret; +} + + +static krb5_error_code +authind_internalize(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + uint8_t **buffer, size_t *lenremain) +{ + struct authind_context *aictx = (struct authind_context *)request_context; + krb5_error_code ret; + int32_t count, len, i; + uint8_t *bp = *buffer; + size_t remain = *lenremain; + krb5_data **inds = NULL; + + /* Get the count. */ + ret = krb5_ser_unpack_int32(&count, &bp, &remain); + if (ret) + return ret; + + if ((size_t)count > remain) + return ERANGE; + + inds = k5calloc(count, sizeof(*inds), &ret); + if (inds == NULL) + return errno; + + for (i = 0; i < count; i++) { + /* Get the length. */ + ret = krb5_ser_unpack_int32(&len, &bp, &remain); + if (ret) + goto cleanup; + if ((size_t)len > remain) { + ret = ERANGE; + goto cleanup; + } + + /* Get the indicator. */ + inds[i] = k5alloc(sizeof(*inds[i]), &ret); + if (inds[i] == NULL) + goto cleanup; + ret = alloc_data(inds[i], len); + if (ret) + goto cleanup; + ret = krb5_ser_unpack_bytes((uint8_t *)inds[i]->data, len, &bp, + &remain); + if (ret) + goto cleanup; + } + + k5_free_data_ptr_list(aictx->indicators); + aictx->count = count; + aictx->indicators = inds; + inds = NULL; + + *buffer = bp; + *lenremain = remain; + +cleanup: + k5_free_data_ptr_list(inds); + return ret; +} + +static krb5_authdatatype authind_ad_types[] = { + KRB5_AUTHDATA_AUTH_INDICATOR, 0 +}; + +krb5plugin_authdata_client_ftable_v0 k5_authind_ad_client_ftable = { + "authentication-indicators", + authind_ad_types, + authind_init, + NULL, /* fini */ + authind_flags, + authind_request_init, + authind_request_fini, + authind_get_attribute_types, + authind_get_attribute, + authind_set_attribute, + NULL, /* delete_attribute_proc */ + NULL, /* export_authdata */ + authind_import_authdata, + NULL, /* export_internal */ + NULL, /* free_internal */ + NULL, /* verify */ + authind_size, + authind_externalize, + authind_internalize, + NULL /* authind_copy */ +}; diff --git a/src/lib/krb5/krb/authdata.c b/src/lib/krb5/krb/authdata.c index f2c66bdf66..047128a00d 100644 --- a/src/lib/krb5/krb/authdata.c +++ b/src/lib/krb5/krb/authdata.c @@ -45,6 +45,7 @@ static const char *objdirs[] = { static krb5plugin_authdata_client_ftable_v0 *authdata_systems[] = { &krb5int_mspac_authdata_client_ftable, &krb5int_s4u2proxy_authdata_client_ftable, + &k5_authind_ad_client_ftable, NULL }; diff --git a/src/lib/krb5/krb/authdata.h b/src/lib/krb5/krb/authdata.h index 46b699ca9f..b193f6a493 100644 --- a/src/lib/krb5/krb/authdata.h +++ b/src/lib/krb5/krb/authdata.h @@ -78,6 +78,7 @@ struct krb5_pac_data { extern krb5plugin_authdata_client_ftable_v0 krb5int_mspac_authdata_client_ftable; extern krb5plugin_authdata_client_ftable_v0 krb5int_s4u2proxy_authdata_client_ftable; +extern krb5plugin_authdata_client_ftable_v0 k5_authind_ad_client_ftable; krb5_error_code k5_pac_locate_buffer(krb5_context context, diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps index d08d533713..09e7771b7f 100644 --- a/src/lib/krb5/krb/deps +++ b/src/lib/krb5/krb/deps @@ -45,6 +45,18 @@ appdefault.so appdefault.po $(OUTPRE)appdefault.$(OBJEXT): \ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ appdefault.c +ai_authdata.so ai_authdata.po $(OUTPRE)ai_authdata.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h authdata.h \ + int-proto.h ai_authdata.c auth_con.so auth_con.po $(OUTPRE)auth_con.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \