krb5 commit: Add tests for per-request preauth data scoping

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/c0b25fe282355d4f329418956b9c6295780af633
commit c0b25fe282355d4f329418956b9c6295780af633
Author: Greg Hudson <[email protected]>
Date:   Wed Jan 4 18:31:15 2017 -0500

    Add tests for per-request preauth data scoping
    
    Add a test harness which interleaves calls for multiple initial creds
    contexts using the same library context.  Add a test case to
    t_preauth.py using the new harness and the test preauth module to
    verify that modreq pointers are correctly tracked.
    
    ticket: 7877

 .gitignore               |    1 +
 src/tests/Makefile.in    |   23 +++++---
 src/tests/icinterleave.c |  124 ++++++++++++++++++++++++++++++++++++++++++++++
 src/tests/t_preauth.py   |   13 +++++
 4 files changed, 152 insertions(+), 9 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7fe6736..379dc77 100644
--- a/.gitignore
+++ b/.gitignore
@@ -386,6 +386,7 @@ local.properties
 /src/tests/hist
 /src/tests/hooks
 /src/tests/hrealm
+/src/tests/icinterleave
 /src/tests/icred
 /src/tests/kdbtest
 /src/tests/kdc.conf
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index b554691..219d973 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -6,12 +6,12 @@ SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \
 RUN_DB_TEST = $(RUN_SETUP) KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf \
 	LC_ALL=C $(VALGRIND)
 
-OBJS= adata.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o icred.o \
-	kdbtest.o localauth.o plugorder.o rdreq.o responder.o s2p.o \
-	s4u2proxy.o unlockiter.o
+OBJS= adata.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o \
+	icinterleave.o icred.o kdbtest.o localauth.o plugorder.o rdreq.o \
+	responder.o s2p.o s4u2proxy.o unlockiter.o
 EXTRADEPSRCS= adata.c etinfo.c forward.c gcred.c hist.c hooks.c hrealm.c \
-	icred.c kdbtest.c localauth.c plugorder.c rdreq.o responder.c s2p.c \
-	s4u2proxy.c unlockiter.c
+	icinterleave.c icred.c kdbtest.c localauth.c plugorder.c rdreq.o \
+	responder.c s2p.c s4u2proxy.c unlockiter.c
 
 TEST_DB = ./testdb
 TEST_REALM = FOO.TEST.REALM
@@ -44,6 +44,9 @@ hooks: hooks.o $(KRB5_BASE_DEPLIBS)
 hrealm: hrealm.o $(KRB5_BASE_DEPLIBS)
 	$(CC_LINK) -o $@ hrealm.o $(KRB5_BASE_LIBS)
 
+icinterleave: icinterleave.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $@ icinterleave.o $(KRB5_BASE_LIBS)
+
 icred: icred.o $(KRB5_BASE_DEPLIBS)
 	$(CC_LINK) -o $@ icred.o $(KRB5_BASE_LIBS)
 
@@ -115,8 +118,9 @@ kdb_check: kdc.conf krb5.conf
 	$(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f
 	$(RM) $(TEST_DB)* stash_file
 
-check-pytests: adata etinfo forward gcred hist hooks hrealm icred kdbtest
-check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
+check-pytests: adata etinfo forward gcred hist hooks hrealm icinterleave icred
+check-pytests: kdbtest localauth plugorder rdreq responder s2p s4u2proxy
+check-pytests: unlockiter
 	$(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS)
 	$(RUNPYTEST) $(srcdir)/t_hooks.py $(PYTESTFLAGS)
 	$(RUNPYTEST) $(srcdir)/t_dump.py $(PYTESTFLAGS)
@@ -169,8 +173,9 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
 	$(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS)
 
 clean:
-	$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
-	$(RM) localauth plugorder rdreq responder s2p s4u2proxy unlockiter
+	$(RM) adata etinfo forward gcred hist hooks hrealm icinterleave icred
+	$(RM) kdbtest localauth plugorder rdreq responder s2p s4u2proxy
+	$(RM) unlockiter
 	$(RM) krb5.conf kdc.conf
 	$(RM) -rf kdc_realm/sandbox ldap
 	$(RM) au.log
diff --git a/src/tests/icinterleave.c b/src/tests/icinterleave.c
new file mode 100644
index 0000000..d76ecf3
--- /dev/null
+++ b/src/tests/icinterleave.c
@@ -0,0 +1,124 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* tests/icinterleave.c - interleaved init_creds_step test harness */
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*
+ * This test harness performs multiple initial creds operations using
+ * krb5_init_creds_step(), interleaving the operations to test the scoping of
+ * the preauth state.  All principals must have the same password (or not
+ * require a password).
+ */
+
+#include "k5-int.h"
+
+static krb5_context ctx;
+
+static void
+check(krb5_error_code code)
+{
+    const char *errmsg;
+
+    if (code) {
+        errmsg = krb5_get_error_message(ctx, code);
+        fprintf(stderr, "%s\n", errmsg);
+        krb5_free_error_message(ctx, errmsg);
+        exit(1);
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    const char *password;
+    char **princstrs;
+    krb5_principal client;
+    krb5_init_creds_context *iccs;
+    krb5_data req, *reps, realm;
+    krb5_boolean any_left;
+    int i, nclients, master;
+    unsigned int flags;
+
+    if (argc < 3) {
+        fprintf(stderr, "Usage: icinterleave password princ1 princ2 ...\n");
+        exit(1);
+    }
+    password = argv[1];
+    princstrs = argv + 2;
+    nclients = argc - 2;
+
+    check(krb5_init_context(&ctx));
+
+    /* Create an initial creds context for each client principal. */
+    iccs = calloc(nclients, sizeof(*iccs));
+    assert(iccs != NULL);
+    for (i = 0; i < nclients; i++) {
+        check(krb5_parse_name(ctx, princstrs[i], &client));
+        check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL,
+                                   &iccs[i]));
+        check(krb5_init_creds_set_password(ctx, iccs[i], password));
+        krb5_free_principal(ctx, client);
+    }
+
+    reps = calloc(nclients, sizeof(*reps));
+    assert(reps != NULL);
+
+    any_left = TRUE;
+    while (any_left) {
+        any_left = FALSE;
+        for (i = 0; i < nclients; i++)  {
+            if (iccs[i] == NULL)
+                continue;
+            any_left = TRUE;
+
+            printf("step %d\n", i + 1);
+
+            req = empty_data();
+            realm = empty_data();
+            check(krb5_init_creds_step(ctx, iccs[i], &reps[i], &req, &realm,
+                                       &flags));
+            if (!(flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE)) {
+                printf("finish %d\n", i + 1);
+                krb5_init_creds_free(ctx, iccs[i]);
+                iccs[i] = NULL;
+                continue;
+            }
+
+            master = 0;
+            krb5_free_data_contents(ctx, &reps[i]);
+            check(krb5_sendto_kdc(ctx, &req, &realm, &reps[i], &master, 0));
+            krb5_free_data_contents(ctx, &req);
+            krb5_free_data_contents(ctx, &realm);
+        }
+    }
+
+    krb5_free_context(ctx);
+    return 0;
+}
diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py
index 1823a79..3acd409 100644
--- a/src/tests/t_preauth.py
+++ b/src/tests/t_preauth.py
@@ -18,4 +18,17 @@ realm.kinit('nokeyuser', password('user'), expected_code=1,
 realm.run([kadminl, 'setstr', realm.user_princ, '2rt', 'secondtrip'])
 realm.kinit(realm.user_princ, password('user'), expected_msg='2rt: secondtrip')
 
+# Test that multiple stepwise initial creds operations can be
+# performed with the same krb5_context, with proper tracking of
+# clpreauth module request handles.
+realm.run([kadminl, 'addprinc', '-pw', 'pw', 'u1'])
+realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u2'])
+realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u3'])
+realm.run([kadminl, 'setstr', 'u2', '2rt', 'extra'])
+out = realm.run(['./icinterleave', 'pw', 'u1', 'u2', 'u3'])
+if out != ('step 1\nstep 2\nstep 3\nstep 1\nfinish 1\nstep 2\nno attr\n'
+           'step 3\nno attr\nstep 2\n2rt: extra\nstep 3\nfinish 3\nstep 2\n'
+           'finish 2\n'):
+    fail('unexpected output from icinterleave')
+
 success('Pre-authentication framework tests')
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.