void k5_free_cammac(krb5_context context, krb5_cammac *val);
void k5_free_secure_cookie(krb5_context context, krb5_secure_cookie *val);
+krb5_error_code
+k5_unwrap_cammac_svc(krb5_context context, const krb5_authdata *ad,
+ const krb5_keyblock *key, krb5_authdata ***adata_out);
+krb5_error_code
+k5_authind_decode(const krb5_authdata *ad, krb5_data ***indicators);
+
/* #include "krb5/wordsize.h" -- comes in through base-defs.h. */
#include "com_err.h"
#include "k5-plugin.h"
krb5_free_data(context, der_enctkt);
return valid;
}
-
-/* Return true if cammac's service verifier is valid for server_key. */
-krb5_boolean
-cammac_check_svcver(krb5_context context, krb5_cammac *cammac,
- krb5_keyblock *server_key)
-{
- krb5_error_code ret;
- krb5_verifier_mac *ver = cammac->svc_verifier;
- krb5_boolean valid = FALSE;
- krb5_data *der_authdata = NULL;
-
- if (ver == NULL)
- return FALSE;
- ret = encode_krb5_authdata(cammac->elements, &der_authdata);
- if (ret)
- return FALSE;
- ret = krb5_c_verify_checksum(context, server_key, KRB5_KEYUSAGE_CAMMAC,
- der_authdata, &ver->checksum, &valid);
- krb5_free_data(context, der_authdata);
- return valid;
-}
cammac_check_kdcver(krb5_context context, krb5_cammac *cammac,
krb5_enc_tkt_part *enc_tkt, krb5_db_entry *krbtgt);
-krb5_boolean
-cammac_check_svcver(krb5_context context, krb5_cammac *cammac,
- krb5_keyblock *server_key);
-
/* do_as_req.c */
void
process_as_req (krb5_kdc_req *, krb5_data *,
allow_weak.o \
appdefault.o \
auth_con.o \
+ cammac_util.o \
authdata.o \
authdata_exp.o \
authdata_enc.o \
$(OUTPRE)allow_weak.$(OBJEXT) \
$(OUTPRE)appdefault.$(OBJEXT) \
$(OUTPRE)auth_con.$(OBJEXT) \
+ $(OUTPRE)cammac_util.$(OBJEXT) \
$(OUTPRE)authdata.$(OBJEXT) \
$(OUTPRE)authdata_exp.$(OBJEXT) \
$(OUTPRE)authdata_enc.$(OBJEXT) \
$(srcdir)/addr_srch.c \
$(srcdir)/appdefault.c \
$(srcdir)/auth_con.c \
+ $(srcdir)/cammac_util.c \
$(srcdir)/authdata.c \
$(srcdir)/authdata_exp.c \
$(srcdir)/authdata_enc.c \
return 0;
}
+
+/*
+ * Decode authentication indicator strings from authdata and return as an
+ * allocated array of krb5_data pointers. The caller must initialize
+ * *indicators to NULL for the first call, and successive calls will reallocate
+ * and append to the indicators array.
+ */
+krb5_error_code
+k5_authind_decode(const krb5_authdata *ad, krb5_data ***indicators)
+{
+ krb5_error_code ret = 0;
+ krb5_data der_ad, **strdata = NULL, **ai_list = *indicators;
+ size_t count, scount;
+
+ if (ad == NULL || ad->ad_type != KRB5_AUTHDATA_AUTH_INDICATOR)
+ goto cleanup;
+
+ /* Count existing auth indicators. */
+ for (count = 0; ai_list != NULL && ai_list[count] != NULL; count++);
+
+ der_ad = make_data(ad->contents, ad->length);
+ ret = decode_utf8_strings(&der_ad, &strdata);
+ if (ret)
+ return ret;
+
+ /* Count new auth indicators. */
+ for (scount = 0; strdata[scount] != NULL; scount++);
+
+ ai_list = realloc(ai_list, (count + scount + 1) * sizeof(*ai_list));
+ if (ai_list == NULL) {
+ ret = ENOMEM;
+ goto cleanup;
+ }
+ *indicators = ai_list;
+
+ /* Steal decoder-allocated pointers and free the container array. */
+ memcpy(ai_list + count, strdata, scount * sizeof(*strdata));
+ ai_list[count + scount] = NULL;
+ free(strdata);
+ strdata = NULL;
+
+cleanup:
+ k5_free_data_ptr_list(strdata);
+ return ret;
+}
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* cammac_util.c - CAMMAC related functions */
+/*
+ * 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"
+
+/* Return 0 if cammac's service verifier is valid for server_key. */
+static krb5_error_code
+check_svcver(krb5_context context, const krb5_cammac *cammac,
+ const krb5_keyblock *server_key)
+{
+ krb5_error_code ret;
+ krb5_boolean valid = FALSE;
+ krb5_verifier_mac *ver = cammac->svc_verifier;
+ krb5_data *der_authdata = NULL;
+
+ if (ver == NULL)
+ return EINVAL;
+
+ ret = encode_krb5_authdata(cammac->elements, &der_authdata);
+ if (ret)
+ return ret;
+
+ ret = krb5_c_verify_checksum(context, server_key, KRB5_KEYUSAGE_CAMMAC,
+ der_authdata, &ver->checksum, &valid);
+ if (!ret && !valid)
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+
+ krb5_free_data(context, der_authdata);
+ return ret;
+}
+
+/* Decode and verify CAMMAC authdata using the svc verifier,
+ * and return the contents as an allocated array of authdata pointers. */
+krb5_error_code
+k5_unwrap_cammac_svc(krb5_context context, const krb5_authdata *ad,
+ const krb5_keyblock *key, krb5_authdata ***adata_out)
+{
+ krb5_data ad_data;
+ krb5_error_code ret;
+ krb5_cammac *cammac = NULL;
+
+ *adata_out = NULL;
+
+ ad_data = make_data(ad->contents, ad->length);
+ ret = decode_krb5_cammac(&ad_data, &cammac);
+ if (ret)
+ return ret;
+
+ ret = check_svcver(context, cammac, key);
+ if (!ret) {
+ *adata_out = cammac->elements;
+ cammac->elements = NULL;
+ }
+
+ k5_free_cammac(context, cammac);
+ return ret;
+}
initialize_k5e1_error_table
initialize_kv5m_error_table
initialize_prof_error_table
+k5_authind_decode
k5_build_conf_principals
k5_ccselect_free_context
k5_change_error_message_code
k5_plugin_register_dyn
k5_unmarshal_cred
k5_unmarshal_princ
+k5_unwrap_cammac_svc
k5_zapfree_pa_data
krb524_convert_creds_kdc
krb524_init_ets
return ad;
}
-/* Verify a CAMMAC's svc_verifier and return its contents. */
-static krb5_authdata **
-unwrap_cammac(krb5_authdata *ad, krb5_keyblock *tktkey)
-{
- krb5_data *der_elements, ad_data = make_data(ad->contents, ad->length);
- krb5_authdata **elements;
- krb5_cammac *cammac;
- krb5_boolean valid;
-
- check(decode_krb5_cammac(&ad_data, &cammac));
- check(encode_krb5_authdata(cammac->elements, &der_elements));
- assert(cammac->svc_verifier != NULL);
- krb5_c_verify_checksum(ctx, tktkey, KRB5_KEYUSAGE_CAMMAC, der_elements,
- &cammac->svc_verifier->checksum, &valid);
- assert(valid);
- elements = cammac->elements;
- cammac->elements = NULL;
- krb5_free_data(ctx, der_elements);
- k5_free_cammac(ctx, cammac);
- return elements;
-}
-
static krb5_authdata **
get_container_contents(krb5_authdata *ad, krb5_keyblock *skey,
krb5_keyblock *tktkey)
if (ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED)
check(krb5_verify_authdata_kdc_issued(ctx, skey, ad, NULL, &inner_ad));
else if (ad->ad_type == KRB5_AUTHDATA_CAMMAC)
- inner_ad = unwrap_cammac(ad, tktkey);
+ check(k5_unwrap_cammac_svc(ctx, ad, tktkey, &inner_ad));
else
check(krb5_decode_authdata_container(ctx, ad->ad_type, ad, &inner_ad));
return inner_ad;
static void
display_auth_indicator(krb5_authdata *ad)
{
- krb5_data **strs, **p, d = make_data(ad->contents, ad->length);
+ krb5_data **strs = NULL, **p;
+
+ check(k5_authind_decode(ad, &strs));
+ assert(strs != NULL);
- check(decode_utf8_strings(&d, &strs));
printf("[");
for (p = strs; *p != NULL; p++) {
printf("%.*s", (int)(*p)->length, (*p)->data);
if '+97: [indcl]' not in out:
fail('auth-indicator not seen for AS req to cross-realm TGT')
+# Multiple indicators
+realm.kinit(realm.user_princ, password('user'),
+ ['-X', 'indicators=indcl indcl2 indcl3'])
+out = realm.run(['./adata', realm.krbtgt_princ])
+if '+97: [indcl, indcl2, indcl3]' not in out:
+ fail('multiple auth-indicators not seen for normal AS req')
+
# AS request to local TGT (resulting creds are used for TGS tests)
realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl'])
out = realm.run(['./adata', realm.krbtgt_princ])