krb5 commit: Add libkrb5 CAMMAC and auth-indicator functions

Greg Hudson ghudson at mit.edu
Mon Jun 20 11:54:11 EDT 2016


https://github.com/krb5/krb5/commit/3563485fdb54024bd79a4491000c84943cc20ab9
commit 3563485fdb54024bd79a4491000c84943cc20ab9
Author: Matt Rogers <mrogers at redhat.com>
Date:   Thu May 12 19:43:55 2016 -0400

    Add libkrb5 CAMMAC and auth-indicator functions
    
    Add k5_unwrap_cammac_svc() and k5_authind_decode() internal functions
    to libkrb5, for use by test programs and the forthcoming
    auth-indicator authdata module.  Remove the unused
    cammac_check_svcver() from the KDC code.  Modify tests/adata.c to use
    the new functions, and add a test case to t_authdata.py for multiple
    indicator values.
    
    [ghudson at mit.edu: squash three commits; make k5_cammac_check_svcver()
    a static helper]
    
    ticket: 8425

 src/include/k5-int.h            |    6 +++
 src/kdc/cammac.c                |   21 ---------
 src/kdc/kdc_util.h              |    4 --
 src/lib/krb5/krb/Makefile.in    |    3 +
 src/lib/krb5/krb/authdata_dec.c |   45 ++++++++++++++++++++
 src/lib/krb5/krb/cammac_util.c  |   86 +++++++++++++++++++++++++++++++++++++++
 src/lib/krb5/libkrb5.exports    |    2 +
 src/tests/adata.c               |   30 ++-----------
 src/tests/t_authdata.py         |    7 +++
 9 files changed, 154 insertions(+), 50 deletions(-)

diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 1d3667d..1cda50d 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -956,6 +956,12 @@ void k5_free_kkdcp_message(krb5_context context, krb5_kkdcp_message *val);
 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"
diff --git a/src/kdc/cammac.c b/src/kdc/cammac.c
index 37926e5..8d18b16 100644
--- a/src/kdc/cammac.c
+++ b/src/kdc/cammac.c
@@ -171,24 +171,3 @@ cleanup:
     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;
-}
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 137952d..bcf05fc 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -137,10 +137,6 @@ krb5_boolean
 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 *,
diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
index 81eebb4..2c6ea5c 100644
--- a/src/lib/krb5/krb/Makefile.in
+++ b/src/lib/krb5/krb/Makefile.in
@@ -18,6 +18,7 @@ STLIBOBJS= \
 	allow_weak.o	\
 	appdefault.o	\
 	auth_con.o	\
+	cammac_util.o	\
 	authdata.o	\
 	authdata_exp.o	\
 	authdata_enc.o	\
@@ -128,6 +129,7 @@ OBJS=	$(OUTPRE)addr_comp.$(OBJEXT)	\
 	$(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)	\
@@ -237,6 +239,7 @@ SRCS=	$(srcdir)/addr_comp.c	\
 	$(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	\
diff --git a/src/lib/krb5/krb/authdata_dec.c b/src/lib/krb5/krb/authdata_dec.c
index 80f5385..0d1c1c4 100644
--- a/src/lib/krb5/krb/authdata_dec.c
+++ b/src/lib/krb5/krb/authdata_dec.c
@@ -249,3 +249,48 @@ krb5_verify_authdata_kdc_issued(krb5_context context,
 
     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;
+}
diff --git a/src/lib/krb5/krb/cammac_util.c b/src/lib/krb5/krb/cammac_util.c
new file mode 100644
index 0000000..ab9da05
--- /dev/null
+++ b/src/lib/krb5/krb/cammac_util.c
@@ -0,0 +1,86 @@
+/* -*- 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;
+}
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 2c5f181..e350c89 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -113,6 +113,7 @@ initialize_krb5_error_table
 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
@@ -145,6 +146,7 @@ k5_plugin_register
 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
diff --git a/src/tests/adata.c b/src/tests/adata.c
index 77f1708..08bc16a 100644
--- a/src/tests/adata.c
+++ b/src/tests/adata.c
@@ -146,28 +146,6 @@ make_authdata(const char *typestr, const char *contents)
     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)
@@ -177,7 +155,7 @@ get_container_contents(krb5_authdata *ad, krb5_keyblock *skey,
     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;
@@ -187,9 +165,11 @@ get_container_contents(krb5_authdata *ad, krb5_keyblock *skey,
 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);
diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py
index 20c8bc6..5ce66d9 100644
--- a/src/tests/t_authdata.py
+++ b/src/tests/t_authdata.py
@@ -115,6 +115,13 @@ out = realm.run(['./adata', 'krbtgt/FOREIGN'])
 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])


More information about the cvs-krb5 mailing list