]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add API to retrieve etype-info from KDC
authorMubashir Kazia <mkazia@gmail.com>
Sat, 24 Jun 2017 19:47:53 +0000 (19:47 +0000)
committerGreg Hudson <ghudson@mit.edu>
Thu, 4 Oct 2018 16:54:18 +0000 (12:54 -0400)
Add the krb5_get_etype_info() API, which sends an initial ticket
request to the KDC and extracts an enctype, salt, and s2kparams value
from the first KDC reply.  This function will help ktutil use the
correct salt and s2kparams when creating keytabs.

[ghudson@mit.edu: renamed API to krb5_get_etype_info() and adjusted
behavior]

ticket: 8587

.gitignore
doc/appdev/refs/api/index.rst
src/include/krb5/krb5.hin
src/lib/krb5/krb/Makefile.in
src/lib/krb5/krb/get_etype_info.c [new file with mode: 0644]
src/lib/krb5/krb/int-proto.h
src/lib/krb5/krb/preauth2.c
src/lib/krb5/krb/t_get_etype_info.c [new file with mode: 0644]
src/lib/krb5/krb/t_get_etype_info.py [new file with mode: 0644]
src/lib/krb5/libkrb5.exports
src/lib/krb5_32.def

index 713d4a6262a7cc26aa87e624ba9c11480a5e6f50..9e0546d34ff4d119b9ab39d32a19c7d5cf762f1d 100644 (file)
@@ -371,6 +371,7 @@ local.properties
 /src/lib/krb5/krb/t_etypes
 /src/lib/krb5/krb/t_expand
 /src/lib/krb5/krb/t_expire_warn
+/src/lib/krb5/krb/t_get_etype_info
 /src/lib/krb5/krb/t_in_ccache
 /src/lib/krb5/krb/t_kerb
 /src/lib/krb5/krb/t_pac
index f2f27fe72ea21474eb678b64a02957c9a4e4b2fd..66aff5951eac7ac7487e371b27ae4ba37a8a0726 100644 (file)
@@ -212,6 +212,7 @@ Rarely used public interfaces
    krb5_free_string.rst
    krb5_free_ticket.rst
    krb5_free_unparsed_name.rst
+   krb5_get_etype_info.rst
    krb5_get_permitted_enctypes.rst
    krb5_get_server_rcache.rst
    krb5_get_time_offsets.rst
index 384bb838fb69681aab0d1916172c018e4474d010..21fabb48c0b88409e13867ffd3ffa08d290019b1 100644 (file)
@@ -7317,6 +7317,42 @@ krb5_get_init_creds_password(krb5_context context, krb5_creds *creds,
                              const char *in_tkt_service,
                              krb5_get_init_creds_opt *k5_gic_options);
 
+/**
+ * Retrieve enctype, salt and s2kparams from KDC
+ *
+ * @param [in]  context         Library context
+ * @param [in]  principal       Principal whose information is requested
+ * @param [in]  opt             Initial credential options
+ * @param [out] enctype_out     The enctype chosen by KDC
+ * @param [out] salt_out        Salt returned from KDC
+ * @param [out] s2kparams_out   String-to-key parameters returned from KDC
+ *
+ * Send an initial ticket request for @a principal and extract the encryption
+ * type, salt type, and string-to-key parameters from the KDC response.  If the
+ * KDC provides no etype-info, set @a enctype_out to @c ENCTYPE_NULL and set @a
+ * salt_out and @a s2kparams_out to empty.  If the KDC etype-info provides no
+ * salt, compute the default salt and place it in @a salt_out.  If the KDC
+ * etype-info provides no string-to-key parameters, set @a s2kparams_out to
+ * empty.
+ *
+ * @a opt may be used to specify options which affect the initial request, such
+ * as request encryption types or a FAST armor cache (see
+ * krb5_get_init_creds_opt_set_etype_list() and
+ * krb5_get_init_creds_opt_set_fast_ccache_name()).
+ *
+ * Use krb5_free_data_contents() to free @a salt_out and @a s2kparams_out when
+ * they are no longer needed.
+ *
+ * @version New in 1.17
+ *
+ * @retval 0 Success
+ * @return A Kerberos error code
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_etype_info(krb5_context context, krb5_principal principal,
+                    krb5_get_init_creds_opt *opt, krb5_enctype *enctype_out,
+                    krb5_data *salt_out, krb5_data *s2kparams_out);
+
 struct _krb5_init_creds_context;
 typedef struct _krb5_init_creds_context *krb5_init_creds_context;
 
@@ -8486,7 +8522,6 @@ void KRB5_CALLCONV
 krb5_set_kdc_recv_hook(krb5_context context, krb5_post_recv_fn recv_hook,
                        void *data);
 
-
 #if defined(TARGET_OS_MAC) && TARGET_OS_MAC
 #    pragma pack(pop)
 #endif
index e4015b64d61f9b9a2a318ac6048e296cc7eb494e..69b9101a848fc2033638b4f5ec6d30cba02f4745 100644 (file)
@@ -55,6 +55,7 @@ STLIBOBJS= \
        gen_subkey.o    \
        gen_save_subkey.o       \
        get_creds.o     \
+       get_etype_info.o \
        get_in_tkt.o    \
        gic_keytab.o    \
        gic_opt.o       \
@@ -167,6 +168,7 @@ OBJS=       $(OUTPRE)addr_comp.$(OBJEXT)    \
        $(OUTPRE)gen_subkey.$(OBJEXT)   \
        $(OUTPRE)gen_save_subkey.$(OBJEXT)      \
        $(OUTPRE)get_creds.$(OBJEXT)    \
+       $(OUTPRE)get_etype_info.$(OBJEXT) \
        $(OUTPRE)get_in_tkt.$(OBJEXT)   \
        $(OUTPRE)gic_keytab.$(OBJEXT)   \
        $(OUTPRE)gic_opt.$(OBJEXT)      \
@@ -279,6 +281,7 @@ SRCS=       $(srcdir)/addr_comp.c   \
        $(srcdir)/gen_subkey.c  \
        $(srcdir)/gen_save_subkey.c     \
        $(srcdir)/get_creds.c   \
+       $(srcdir)/get_etype_info.c \
        $(srcdir)/get_in_tkt.c  \
        $(srcdir)/gic_keytab.c  \
        $(srcdir)/gic_opt.c     \
@@ -353,6 +356,7 @@ SRCS=       $(srcdir)/addr_comp.c   \
        $(srcdir)/t_ser.c       \
        $(srcdir)/t_deltat.c    \
        $(srcdir)/t_expand.c    \
+       $(srcdir)/t_get_etype_info.c \
        $(srcdir)/t_pac.c       \
        $(srcdir)/t_parse_host_string.c \
        $(srcdir)/t_princ.c     \
@@ -461,9 +465,12 @@ t_sname_match: t_sname_match.o sname_match.o $(KRB5_BASE_DEPLIBS)
 t_valid_times: t_valid_times.o valid_times.o $(KRB5_BASE_DEPLIBS)
        $(CC_LINK) -o $@ t_valid_times.o valid_times.o $(KRB5_BASE_LIBS)
 
+t_get_etype_info: t_get_etype_info.o $(KRB5_BASE_DEPLIBS)
+       $(CC_LINK) -o $@ t_get_etype_info.o $(KRB5_BASE_LIBS)
+
 TEST_PROGS= t_walk_rtree t_kerb t_ser t_deltat t_expand t_authdata t_pac \
        t_in_ccache t_cc_config t_copy_context t_princ t_etypes t_vfy_increds \
-       t_response_items t_sname_match t_valid_times
+       t_response_items t_sname_match t_valid_times t_get_etype_info
 
 check-unix: $(TEST_PROGS)
        $(RUN_TEST_LOCAL_CONF) ./t_kerb \
@@ -502,10 +509,11 @@ check-unix: $(TEST_PROGS)
        $(RUN_TEST) ./t_sname_match
        $(RUN_TEST) ./t_valid_times
 
-check-pytests: t_expire_warn t_vfy_increds
+check-pytests: t_expire_warn t_get_etype_info t_vfy_increds
        $(RUNPYTEST) $(srcdir)/t_expire_warn.py $(PYTESTFLAGS)
        $(RUNPYTEST) $(srcdir)/t_vfy_increds.py $(PYTESTFLAGS)
        $(RUNPYTEST) $(srcdir)/t_in_ccache_patypes.py $(PYTESTFLAGS)
+       $(RUNPYTEST) $(srcdir)/t_get_etype_info.py $(PYTESTFLAGS)
 
 check-cmocka: t_parse_host_string
        $(RUN_TEST) ./t_parse_host_string > /dev/null
@@ -530,6 +538,8 @@ clean:
        $(OUTPRE)t_response_items.$(OBJEXT) \
        $(OUTPRE)t_sname_match$(EXEEXT) $(OUTPRE)t_sname_match.$(OBJEXT) \
        $(OUTPRE)t_valid_times$(EXEEXT) $(OUTPRE)t_valid_times.$(OBJEXT) \
+       $(OUTPRE)t_get_etype_info$(EXEEXT) \
+       $(OUTPRE)t_get_etype_info.$(OBJEXT) \
        $(OUTPRE)t_parse_host_string$(EXEEXT) \
        $(OUTPRE)t_parse_host_string.$(OBJEXT)
 
diff --git a/src/lib/krb5/krb/get_etype_info.c b/src/lib/krb5/krb/get_etype_info.c
new file mode 100644 (file)
index 0000000..3a9589d
--- /dev/null
@@ -0,0 +1,180 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/get_etype_salt_s2kp.c - Retrieve enctype, salt and s2kparams */
+/*
+ * Copyright (C) 2017 by Cloudera, 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 "fast.h"
+#include "init_creds_ctx.h"
+
+/* Extract etype info from the error message pkt into icc, if it is a
+ * PREAUTH_REQUIRED error.  Otherwise return the protocol error code. */
+static krb5_error_code
+get_from_error(krb5_context context, krb5_data *pkt,
+               krb5_init_creds_context icc)
+{
+    krb5_error *error = NULL;
+    krb5_pa_data **padata = NULL;
+    krb5_error_code ret;
+
+    ret = decode_krb5_error(pkt, &error);
+    if (ret)
+        return ret;
+    ret = krb5int_fast_process_error(context, icc->fast_state, &error, &padata,
+                                     NULL);
+    if (ret)
+        goto cleanup;
+    if (error->error != KDC_ERR_PREAUTH_REQUIRED) {
+        ret = ERROR_TABLE_BASE_krb5 + error->error;
+        goto cleanup;
+    }
+    ret = k5_get_etype_info(context, icc, padata);
+
+cleanup:
+    krb5_free_pa_data(context, padata);
+    krb5_free_error(context, error);
+    return ret;
+}
+
+/* Extract etype info from the AS reply pkt into icc. */
+static krb5_error_code
+get_from_reply(krb5_context context, krb5_data *pkt,
+               krb5_init_creds_context icc)
+{
+    krb5_kdc_rep *asrep = NULL;
+    krb5_error_code ret;
+    krb5_keyblock *strengthen_key = NULL;
+
+    ret = decode_krb5_as_rep(pkt, &asrep);
+    if (ret)
+        return ret;
+    ret = krb5int_fast_process_response(context, icc->fast_state, asrep,
+                                        &strengthen_key);
+    if (ret)
+        goto cleanup;
+    ret = k5_get_etype_info(context, icc, asrep->padata);
+
+cleanup:
+    krb5_free_kdc_rep(context, asrep);
+    krb5_free_keyblock(context, strengthen_key);
+    return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_etype_info(krb5_context context, krb5_principal principal,
+                    krb5_get_init_creds_opt *opt, krb5_enctype *enctype_out,
+                    krb5_data *salt_out, krb5_data *s2kparams_out)
+{
+    krb5_init_creds_context icc = NULL;
+    krb5_data reply = empty_data(), req = empty_data(), realm = empty_data();
+    krb5_data salt = empty_data(), s2kparams = empty_data();
+    unsigned int flags;
+    int master, tcp_only;
+    krb5_error_code ret;
+
+    *enctype_out = ENCTYPE_NULL;
+    *salt_out = empty_data();
+    *s2kparams_out = empty_data();
+
+    /* Create an initial creds context and get the initial request packet. */
+    ret = krb5_init_creds_init(context, principal, NULL, NULL, 0, opt, &icc);
+    if (ret)
+        goto cleanup;
+    ret = krb5_init_creds_step(context, icc, &reply, &req, &realm, &flags);
+    if (ret)
+        goto cleanup;
+    if (flags != KRB5_INIT_CREDS_STEP_FLAG_CONTINUE) {
+        ret = KRB5KRB_AP_ERR_MSG_TYPE;
+        goto cleanup;
+    }
+
+    /* Send the packet (possibly once with UDP and again with TCP). */
+    tcp_only = 0;
+    for (;;) {
+        master = 0;
+        ret = krb5_sendto_kdc(context, &req, &realm, &reply, &master,
+                              tcp_only);
+        if (ret)
+            goto cleanup;
+
+        icc->etype = ENCTYPE_NULL;
+        if (krb5_is_krb_error(&reply)) {
+            ret = get_from_error(context, &reply, icc);
+            if (ret) {
+                if (!tcp_only && ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
+                    tcp_only = 1;
+                    krb5_free_data_contents(context, &reply);
+                    continue;
+                }
+                goto cleanup;
+            }
+        } else if (krb5_is_as_rep(&reply)) {
+            ret = get_from_reply(context, &reply, icc);
+            if (ret)
+                goto cleanup;
+        } else {
+            ret = KRB5KRB_AP_ERR_MSG_TYPE;
+            goto cleanup;
+        }
+        break;
+    }
+
+    /* If we found no etype-info, return successfully with all null values. */
+    if (icc->etype == ENCTYPE_NULL)
+        goto cleanup;
+
+    if (icc->default_salt)
+        ret = krb5_principal2salt(context, principal, &salt);
+    else if (icc->salt.length > 0)
+        ret = krb5int_copy_data_contents(context, &icc->salt, &salt);
+    if (ret)
+        goto cleanup;
+
+    if (icc->s2kparams.length > 0) {
+        ret = krb5int_copy_data_contents(context, &icc->s2kparams, &s2kparams);
+        if (ret)
+            goto cleanup;
+    }
+
+    *salt_out = salt;
+    *s2kparams_out = s2kparams;
+    *enctype_out = icc->etype;
+    salt = empty_data();
+    s2kparams = empty_data();
+
+cleanup:
+    krb5_free_data_contents(context, &req);
+    krb5_free_data_contents(context, &reply);
+    krb5_free_data_contents(context, &realm);
+    krb5_free_data_contents(context, &salt);
+    krb5_free_data_contents(context, &s2kparams);
+    krb5_init_creds_free(context, icc);
+    return ret;
+}
index d20133885f2d1a48911977b90905d903352592b0..978354848ef2e0af04a33f159c6f4458a22bcc16 100644 (file)
@@ -334,4 +334,8 @@ k5_gic_opt_shallow_copy(krb5_get_init_creds_opt *opt);
 int
 k5_gic_opt_pac_request(krb5_get_init_creds_opt *opt);
 
+krb5_error_code
+k5_get_etype_info(krb5_context context, krb5_init_creds_context ctx,
+                  krb5_pa_data **padata);
+
 #endif /* KRB5_INT_FUNC_PROTO__ */
index c5785489bd5a02b1a6eb584f73c22f2e7fe5f89a..a73568cba5972982b111a2b1209a550f84188333 100644 (file)
@@ -782,9 +782,9 @@ get_salt(krb5_context context, krb5_init_creds_context ctx,
 }
 
 /* Set etype info parameters in rock based on padata. */
-static krb5_error_code
-get_etype_info(krb5_context context, krb5_init_creds_context ctx,
-               krb5_pa_data **padata)
+krb5_error_code
+k5_get_etype_info(krb5_context context, krb5_init_creds_context ctx,
+                  krb5_pa_data **padata)
 {
     krb5_error_code ret = 0;
     krb5_pa_data *pa;
@@ -1023,7 +1023,7 @@ k5_preauth(krb5_context context, krb5_init_creds_context ctx,
     TRACE_PREAUTH_INPUT(context, in_padata);
 
     /* Scan the padata list and process etype-info or salt elements. */
-    ret = get_etype_info(context, ctx, in_padata);
+    ret = k5_get_etype_info(context, ctx, in_padata);
     if (ret)
         return ret;
 
diff --git a/src/lib/krb5/krb/t_get_etype_info.c b/src/lib/krb5/krb/t_get_etype_info.c
new file mode 100644 (file)
index 0000000..041c349
--- /dev/null
@@ -0,0 +1,110 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/t_get_etype_info.c - test harness for krb5_get_etype_info() */
+/*
+ * Copyright (C) 2018 by the Massachusetts Institute of Technology.
+ * 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-platform.h"
+#include "k5-hex.h"
+#include <krb5.h>
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_principal princ;
+    krb5_get_init_creds_opt *opt = NULL;
+    krb5_enctype *etypes = NULL, *newptr, etype;
+    krb5_data salt, s2kparams;
+    const char *armor_ccache = NULL, *msg;
+    char buf[128], *hex;
+    int c, netypes = 0;
+
+    while ((c = getopt(argc, argv, "e:T:")) != -1) {
+        switch (c) {
+        case 'e':
+            newptr = realloc(etypes, (netypes + 1) * sizeof(*etypes));
+            assert(newptr != NULL);
+            etypes = newptr;
+            ret = krb5_string_to_enctype(optarg, &etypes[netypes]);
+            assert(!ret);
+            netypes++;
+            break;
+        case 'T':
+            armor_ccache = optarg;
+            break;
+        }
+    }
+    assert(argc == optind + 1);
+
+    ret = krb5_init_context(&context);
+    assert(!ret);
+    ret = krb5_parse_name(context, argv[optind], &princ);
+    assert(!ret);
+    if (netypes > 0 || armor_ccache != NULL) {
+        ret = krb5_get_init_creds_opt_alloc(context, &opt);
+        assert(!ret);
+        if (netypes > 0)
+            krb5_get_init_creds_opt_set_etype_list(opt, etypes, netypes);
+        if (armor_ccache != NULL) {
+            ret = krb5_get_init_creds_opt_set_fast_ccache_name(context, opt,
+                                                               armor_ccache);
+            assert(!ret);
+        }
+    }
+    ret = krb5_get_etype_info(context, princ, opt, &etype, &salt, &s2kparams);
+    if (ret) {
+        msg = krb5_get_error_message(context, ret);
+        fprintf(stderr, "%s\n", msg);
+        krb5_free_error_message(context, msg);
+        exit(1);
+    } else if (etype == ENCTYPE_NULL) {
+        printf("no etype-info\n");
+    } else {
+        ret = krb5_enctype_to_name(etype, TRUE, buf, sizeof(buf));
+        assert(!ret);
+        printf("etype: %s\n", buf);
+        printf("salt: %.*s\n", (int)salt.length, salt.data);
+        if (s2kparams.length > 0) {
+            ret = k5_hex_encode(s2kparams.data, s2kparams.length, TRUE, &hex);
+            assert(!ret);
+            printf("s2kparams: %s\n", hex);
+            free(hex);
+        }
+    }
+
+    krb5_free_data_contents(context, &salt);
+    krb5_free_data_contents(context, &s2kparams);
+    krb5_free_principal(context, princ);
+    krb5_get_init_creds_opt_free(context, opt);
+    krb5_free_context(context);
+    free(etypes);
+    return 0;
+}
diff --git a/src/lib/krb5/krb/t_get_etype_info.py b/src/lib/krb5/krb/t_get_etype_info.py
new file mode 100644 (file)
index 0000000..7c400be
--- /dev/null
@@ -0,0 +1,63 @@
+from k5test import *
+
+conf = {'libdefaults': {'allow_weak_crypto': 'true'}}
+realm = K5Realm(create_host=False, krb5_conf=conf)
+
+realm.run([kadminl, 'ank', '-pw', 'pw', '+preauth', 'puser'])
+realm.run([kadminl, 'ank', '-nokey', 'nokey'])
+realm.run([kadminl, 'ank', '-nokey', '+preauth', 'pnokey'])
+realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', 'exp'])
+realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', '+preauth',
+           'pexp'])
+realm.run([kadminl, 'ank', '-e', 'des-cbc-crc:afs3', '-pw', 'pw', 'afs'])
+realm.run([kadminl, 'ank', '-e', 'des-cbc-crc:afs3', '-pw', 'pw', '+preauth',
+           'pafs'])
+
+# Extract the explicit salt values from the database.
+out = realm.run([kdb5_util, 'tabdump', 'keyinfo'])
+salt_dict = {f[0]: f[5] for f in [l.split('\t') for l in out.splitlines()]}
+exp_salt = bytes.fromhex(salt_dict['exp@KRBTEST.COM']).decode('ascii')
+pexp_salt = bytes.fromhex(salt_dict['pexp@KRBTEST.COM']).decode('ascii')
+
+# Test an error reply (other than PREAUTH_REQUIRED).
+out = realm.run(['./t_get_etype_info', 'notfound'], expected_code=1,
+                expected_msg='Client not found in Kerberos database')
+
+# Test with default salt and no specific options, with and without
+# preauth.  (Our KDC always sends an explicit salt, so unfortunately
+# we aren't really testing client handling of the default salt.)
+realm.run(['./t_get_etype_info', 'user'],
+          expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMuser\n')
+realm.run(['./t_get_etype_info', 'puser'],
+          expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMpuser\n')
+
+# Test with a specified request enctype.
+msg = 'etype: aes128-cts\nsalt: KRBTEST.COMuser\n'
+realm.run(['./t_get_etype_info', '-e', 'aes128-cts', 'user'],
+          expected_msg='etype: aes128-cts\nsalt: KRBTEST.COMuser\n')
+realm.run(['./t_get_etype_info', '-e', 'aes128-cts', 'puser'],
+          expected_msg='etype: aes128-cts\nsalt: KRBTEST.COMpuser\n')
+
+# Test with FAST.
+msg = 'etype: aes256-cts\nsalt: KRBTEST.COMuser\n'
+realm.run(['./t_get_etype_info', '-T', realm.ccache, 'user'],
+          expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMuser\n')
+realm.run(['./t_get_etype_info', '-T', realm.ccache, 'puser'],
+          expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMpuser\n')
+
+# Test with no available etype-info.
+realm.run(['./t_get_etype_info', 'nokey'], expected_code=1,
+          expected_msg='KDC has no support for encryption type')
+realm.run(['./t_get_etype_info', 'pnokey'], expected_msg='no etype-info')
+
+# Test with explicit salt.
+realm.run(['./t_get_etype_info', 'exp'],
+          expected_msg='etype: aes256-cts\nsalt: ' + exp_salt + '\n')
+realm.run(['./t_get_etype_info', 'pexp'],
+          expected_msg='etype: aes256-cts\nsalt: ' + pexp_salt + '\n')
+
+msg = 'etype: des-cbc-crc\nsalt: KRBTEST.COM\ns2kparams: 01\n'
+realm.run(['./t_get_etype_info', 'afs'], expected_msg=msg)
+realm.run(['./t_get_etype_info', 'pafs'], expected_msg=msg)
+
+success('krb5_get_etype_info() tests')
index 622bc3673c5fa1ee387a92433a6891fe58964219..542209d9d174ca309959b7bb32de3ed03f80490d 100644 (file)
@@ -374,6 +374,7 @@ krb5_get_default_config_files
 krb5_get_default_in_tkt_ktypes
 krb5_get_default_realm
 krb5_get_error_message
+krb5_get_etype_info
 krb5_get_fallback_host_realm
 krb5_get_host_realm
 krb5_get_in_tkt_with_keytab
index 7dee65da6c6c56046414ba7413b0deb237f4b199..3bb2a80f8d3c465fd6414ef981524b55a50da7f7 100644 (file)
@@ -475,6 +475,7 @@ EXPORTS
        k5_enctype_to_ssf                               @438 ; PRIVATE GSSAPI
 
 ; new in 1.17
+       krb5_get_etype_info                             @447
 ; private symbols used by SPAKE client module
        profile_get_string                              @439 ; PRIVATE
        profile_release_string                          @440 ; PRIVATE