From 17d34e956ec454c36573e0cb07a7dc3f3328c99c Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 2 Jul 2017 01:32:13 -0400 Subject: Add tests for kadm5_auth interface Add a test plugin module to exercise features of the kadm5_auth interface, and a Python test script using the module. Also test the initial ticket requirement for self-service key changes in t_kadmin_acl.py. ticket: 8595 --- src/Makefile.in | 1 + src/configure.in | 1 + src/plugins/kadm5_auth/test/Makefile.in | 20 ++ src/plugins/kadm5_auth/test/deps | 22 ++ .../kadm5_auth/test/kadm5_auth_test.exports | 2 + src/plugins/kadm5_auth/test/main.c | 305 +++++++++++++++++++++ src/tests/Makefile.in | 1 + src/tests/t_kadm5_auth.py | 81 ++++++ src/tests/t_kadmin_acl.py | 15 + 9 files changed, 448 insertions(+) create mode 100644 src/plugins/kadm5_auth/test/Makefile.in create mode 100644 src/plugins/kadm5_auth/test/deps create mode 100644 src/plugins/kadm5_auth/test/kadm5_auth_test.exports create mode 100644 src/plugins/kadm5_auth/test/main.c create mode 100644 src/tests/t_kadm5_auth.py diff --git a/src/Makefile.in b/src/Makefile.in index c7297b0..7bb6b8a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -12,6 +12,7 @@ SUBDIRS=util include lib \ plugins/audit/test \ @audit_plugin@ \ plugins/kadm5_hook/test \ + plugins/kadm5_auth/test \ plugins/hostrealm/test \ plugins/localauth/test \ plugins/pwqual/test \ diff --git a/src/configure.in b/src/configure.in index ce354fc..fd64604 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1421,6 +1421,7 @@ dnl ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test plugins/hostrealm/test plugins/localauth/test plugins/kadm5_hook/test + plugins/kadm5_auth/test plugins/pwqual/test plugins/audit plugins/audit/test diff --git a/src/plugins/kadm5_auth/test/Makefile.in b/src/plugins/kadm5_auth/test/Makefile.in new file mode 100644 index 0000000..825c4ae --- /dev/null +++ b/src/plugins/kadm5_auth/test/Makefile.in @@ -0,0 +1,20 @@ +mydir=plugins$(S)kadm5_auth$(S)test +BUILDTOP=$(REL)..$(S)..$(S).. + +LIBBASE=kadm5_auth_test +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/kadm5_auth/test +SHLIB_EXPDEPS=$(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS=$(KDB5_LIBS) $(KRB5_BASE_LIBS) $(LIBS) + +STLIBOBJS=main.o + +SRCS=$(srcdir)/main.c + +all-unix: all-libs +install-unix: +clean-unix:: clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/src/plugins/kadm5_auth/test/deps b/src/plugins/kadm5_auth/test/deps new file mode 100644 index 0000000..a2b74c2 --- /dev/null +++ b/src/plugins/kadm5_auth/test/deps @@ -0,0 +1,22 @@ +# +# Generated makefile dependencies follow. +# +main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(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/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kadm5_auth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h main.c diff --git a/src/plugins/kadm5_auth/test/kadm5_auth_test.exports b/src/plugins/kadm5_auth/test/kadm5_auth_test.exports new file mode 100644 index 0000000..31319af --- /dev/null +++ b/src/plugins/kadm5_auth/test/kadm5_auth_test.exports @@ -0,0 +1,2 @@ +kadm5_auth_welcomer_initvt +kadm5_auth_bouncer_initvt diff --git a/src/plugins/kadm5_auth/test/main.c b/src/plugins/kadm5_auth/test/main.c new file mode 100644 index 0000000..6899f22 --- /dev/null +++ b/src/plugins/kadm5_auth/test/main.c @@ -0,0 +1,305 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kadm5_auth/test/main.c - test modules for kadm5_auth interface */ +/* + * 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 file implements two testing kadm5_auth modules, the welcomer and the + * bouncer. The welcomer implements permissive behavior, while the bouncer + * implements restrictive behavior. + * + * Module data objects and restrictions are adequately tested by the acl + * module, so we do not test them here. Focus instead on the ability to + * examine principal and policy objects and to perform DB operations. + */ + +#include "k5-int.h" +#include +#include + +krb5_error_code +kadm5_auth_welcomer_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); +krb5_error_code +kadm5_auth_bouncer_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +/* The welcomer authorizes all getprinc operations, since kadmin uses them as a + * precursor to modprinc. */ +static krb5_error_code +welcomer_getprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return 0; +} + +/* The welcomer authorizes addprinc operations which set a policy "VIP". */ +static krb5_error_code +welcomer_addprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + if ((mask & KADM5_POLICY) && strcmp(ent->policy, "VIP") == 0) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies addprinc operations which include a maximum lifetime. */ +static krb5_error_code +bouncer_addprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + return (mask & KADM5_MAX_LIFE) ? EPERM : KRB5_PLUGIN_NO_HANDLE; +} + +/* The welcomer authorizes modprinc operations which only set maxrenewlife. */ +static krb5_error_code +welcomer_modprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + return (mask == KADM5_MAX_RLIFE) ? 0 : KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies modprinc operations if the target principal has an even + * number of components. */ +static krb5_error_code +bouncer_modprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + return (target->length % 2 == 0) ? EPERM : KRB5_PLUGIN_NO_HANDLE; +} + +/* The welcomer authorizes setstr operations for the attribute "note". */ +static krb5_error_code +welcomer_setstr(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const char *key, const char *value) +{ + return (strcmp(key, "note") == 0) ? 0 : KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies setstr operations if the value is more than 10 bytes. */ +static krb5_error_code +bouncer_setstr(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const char *key, const char *value) +{ + return (strlen(value) > 10) ? EPERM : KRB5_PLUGIN_NO_HANDLE; +} + +/* The welcomer authorizes delprinc operations if the target principal starts + * with "d". */ +static krb5_error_code +welcomer_delprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + if (target->length > 0 && target->data[0].length > 0 && + *target->data[0].data == 'd') + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies delprinc operations if the target principal has the + * "nodelete" string attribute. */ +static krb5_error_code +bouncer_delprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + krb5_error_code ret; + krb5_db_entry *ent; + char *val = NULL; + + if (krb5_db_get_principal(context, target, 0, &ent) != 0) + return EPERM; + ret = krb5_dbe_get_string(context, ent, "nodelete", &val); + krb5_db_free_principal(context, ent); + ret = (ret != 0 || val != NULL) ? EPERM : KRB5_PLUGIN_NO_HANDLE; + krb5_dbe_free_string(context, val); + return ret; +} + +/* The welcomer authorizes rename operations if the first components of the + * principals have the same length. */ +static krb5_error_code +welcomer_renprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal src, + krb5_const_principal dest) +{ + if (src->length > 0 && dest->length > 0 && + src->data[0].length == dest->data[0].length) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies rename operations if the source principal starts with + * "a". */ +static krb5_error_code +bouncer_renprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal src, + krb5_const_principal dest) +{ + if (src->length > 0 && src->data[0].length > 0 && + *src->data[0].data == 'a') + return EPERM; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* The welcomer authorizes addpol operations which set a minlength of 3. */ +static krb5_error_code +welcomer_addpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + if ((mask & KADM5_PW_MIN_LENGTH) && ent->pw_min_length == 3) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies addpol operations if the name is 3 bytes or less. */ +static krb5_error_code +bouncer_addpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + return (strlen(policy) <= 3) ? EPERM : KRB5_PLUGIN_NO_HANDLE; +} + +/* The welcomer authorizes modpol operations which only change min_life. */ +static krb5_error_code +welcomer_modpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + return (mask == KADM5_PW_MIN_LIFE) ? 0 : KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies modpol operations which set pw_min_life above 10. */ +static krb5_error_code +bouncer_modpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + if ((mask & KADM5_PW_MIN_LIFE) && ent->pw_min_life > 10) + return EPERM; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* The welcomer authorizes getpol operations if the policy and client principal + * policy have the same length. */ +static krb5_error_code +welcomer_getpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy) +{ + if (client_policy != NULL && strlen(policy) == strlen(client_policy)) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* The bouncer denies getpol operations if the policy name begins with 'x'. */ +static krb5_error_code +bouncer_getpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy) +{ + return (*policy == 'x') ? EPERM : KRB5_PLUGIN_NO_HANDLE; +} + +/* The welcomer counts end calls by incrementing the "ends" string attribute on + * the "opcount" principal, if it exists. */ +static void +welcomer_end(krb5_context context, kadm5_auth_moddata data) +{ + krb5_principal princ = NULL; + krb5_db_entry *ent = NULL; + char *val = NULL, buf[10]; + + if (krb5_parse_name(context, "opcount", &princ) != 0) + goto cleanup; + if (krb5_db_get_principal(context, princ, 0, &ent) != 0) + goto cleanup; + if (krb5_dbe_get_string(context, ent, "ends", &val) != 0 || val == NULL) + goto cleanup; + snprintf(buf, sizeof(buf), "%d", atoi(val) + 1); + if (krb5_dbe_set_string(context, ent, "ends", buf) != 0) + goto cleanup; + ent->mask = KADM5_TL_DATA; + krb5_db_put_principal(context, ent); + +cleanup: + krb5_dbe_free_string(context, val); + krb5_db_free_principal(context, ent); + krb5_free_principal(context, princ); +} + +krb5_error_code +kadm5_auth_welcomer_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + kadm5_auth_vtable vt = (kadm5_auth_vtable)vtable; + + vt->name = "welcomer"; + vt->addprinc = welcomer_addprinc; + vt->modprinc = welcomer_modprinc; + vt->setstr = welcomer_setstr; + vt->delprinc = welcomer_delprinc; + vt->renprinc = welcomer_renprinc; + vt->getprinc = welcomer_getprinc; + vt->addpol = welcomer_addpol; + vt->modpol = welcomer_modpol; + vt->getpol = welcomer_getpol; + vt->end = welcomer_end; + return 0; +} + +krb5_error_code +kadm5_auth_bouncer_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + kadm5_auth_vtable vt = (kadm5_auth_vtable)vtable; + + vt->name = "bouncer"; + vt->addprinc = bouncer_addprinc; + vt->modprinc = bouncer_modprinc; + vt->setstr = bouncer_setstr; + vt->delprinc = bouncer_delprinc; + vt->renprinc = bouncer_renprinc; + vt->addpol = bouncer_addpol; + vt->modpol = bouncer_modpol; + vt->getpol = bouncer_getpol; + return 0; +} diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index b44c7bc..0013442 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -132,6 +132,7 @@ check-pytests: unlockiter $(RUNPYTEST) $(srcdir)/t_otp.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_localauth.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_kadm5_hook.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadm5_auth.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_pwqual.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_hostrealm.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_kdb_locking.py $(PYTESTFLAGS) diff --git a/src/tests/t_kadm5_auth.py b/src/tests/t_kadm5_auth.py new file mode 100644 index 0000000..ba4ab8e --- /dev/null +++ b/src/tests/t_kadm5_auth.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +from k5test import * + +# Create a realm with the welcomer and bouncer kadm5_auth test modules +# in place of the builtin modules. +modpath = os.path.join(buildtop, 'plugins', 'kadm5_auth', 'test', + 'kadm5_auth_test.so') +conf = {'plugins': {'kadm5_auth': {'module': ['welcomer:' + modpath, + 'bouncer:' + modpath], + 'enable_only': ['welcomer', 'bouncer']}}} +realm = K5Realm(krb5_conf=conf, create_host=False) +realm.start_kadmind() +realm.prep_kadmin() + +# addprinc: welcomer accepts with policy VIP, bouncer denies maxlife. +realm.run_kadmin(['addprinc', '-randkey', 'princ'], expected_code=1) +realm.run_kadmin(['addprinc', '-randkey', '-policy', 'VIP', 'princ']) +realm.run_kadmin(['addprinc', '-randkey', '-policy', 'VIP', '-maxlife', '3', + 'princ'], expected_code=1) + +# modprinc: welcomer accepts with only maxrenewlife, bouncer denies +# with even-component target principal. +realm.run_kadmin(['modprinc', '-maxlife', '3', 'princ'], expected_code=1) +realm.run_kadmin(['modprinc', '-maxrenewlife', '3', 'princ']) +realm.run_kadmin(['modprinc', '-maxrenewlife', '3', 'user/admin'], + expected_code=1) + +# setstr: welcomer accepts with key 'note', bouncer denies with value +# length > 10. +realm.run_kadmin(['setstr', 'princ', 'somekey', 'someval'], expected_code=1) +realm.run_kadmin(['setstr', 'princ', 'note', 'abc']) +realm.run_kadmin(['setstr', 'princ', 'note', 'abcdefghijkl'], expected_code=1) + +# delprinc: welcomer accepts with target principal beginning with 'd', +# bouncer denies with "nodelete" string attribute. +realm.run_kadmin(['delprinc', 'user'], expected_code=1) +realm.run([kadminl, 'addprinc', '-randkey', 'deltest']) +realm.run_kadmin(['delprinc', 'deltest']) +realm.run([kadminl, 'addprinc', '-randkey', 'deltest']) +realm.run([kadminl, 'setstr', 'deltest', 'nodelete', 'yes']) +realm.run_kadmin(['delprinc', 'deltest'], expected_code=1) + +# renprinc: welcomer accepts with same-length first components, bouncer +# refuses with source principal beginning with 'a'. +realm.run_kadmin(['renprinc', 'princ', 'xyz'], expected_code=1) +realm.run_kadmin(['renprinc', 'princ', 'abcde']) +realm.run_kadmin(['renprinc', 'abcde', 'fghij'], expected_code=1) + +# addpol: welcomer accepts with minlength 3, bouncer denies with name +# length <= 3. +realm.run_kadmin(['addpol', 'testpol'], expected_code=1) +realm.run_kadmin(['addpol', '-minlength', '3', 'testpol']) +realm.run_kadmin(['addpol', '-minlength', '3', 'abc'], expected_code=1) + +# modpol: welcomer accepts changes to minlife, bouncer denies with +# minlife > 10. +realm.run_kadmin(['modpol', '-minlength', '4', 'testpol'], expected_code=1) +realm.run_kadmin(['modpol', '-minlife', '8', 'testpol']) +realm.run_kadmin(['modpol', '-minlife', '11', 'testpol'], expected_code=1) + +# getpol: welcomer accepts if policy and client policy have same length, +# bouncer denies if policy name begins with 'x'. +realm.run([kadminl, 'addpol', 'aaaa']) +realm.run([kadminl, 'addpol', 'bbbb']) +realm.run([kadminl, 'addpol', 'xxxx']) +realm.run([kadminl, 'modprinc', '-policy', 'aaaa', 'user/admin']) +realm.run_kadmin(['getpol', 'testpol'], expected_code=1) +realm.run_kadmin(['getpol', 'bbbb']) +realm.run_kadmin(['getpol', 'xxxx'], expected_code=1) + +# end: welcomer counts operations using "ends" string attribute on +# "opcount" principal. kadmind is dumb and invokes the end method for +# every RPC operation including init, so we expect four calls to the +# end operation. +realm.run([kadminl, 'addprinc', '-nokey', 'opcount']) +realm.run([kadminl, 'setstr', 'opcount', 'ends', '0']) +realm.run_kadmin(['getprinc', 'user']) +realm.run_kadmin(['getpol', 'bbbb']) +realm.run([kadminl, 'getstrs', 'opcount'], expected_msg='ends: 4') + +success('kadm5_auth pluggable interface tests') diff --git a/src/tests/t_kadmin_acl.py b/src/tests/t_kadmin_acl.py index f7c04cf..42bdf42 100755 --- a/src/tests/t_kadmin_acl.py +++ b/src/tests/t_kadmin_acl.py @@ -296,4 +296,19 @@ kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys']) realm.kinit('extractkeys', flags=['-k']) os.remove(realm.keytab) +# Verify that self-service key changes require an initial ticket. +realm.run([kadminl, 'cpw', '-pw', password('none'), 'none']) +realm.run([kadminl, 'modprinc', '+allow_tgs_req', 'kadmin/admin']) +realm.kinit('none', password('none')) +realm.run([kvno, 'kadmin/admin']) +msg = 'Operation requires initial ticket' +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', 'newpw', 'none'], + expected_code=1, expected_msg=msg) +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', 'newpw', + '-e', 'aes256-cts', 'none'], expected_code=1, expected_msg=msg) +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-randkey', 'none'], + expected_code=1, expected_msg=msg) +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-randkey', '-e', 'aes256-cts', + 'none'], expected_code=1, expected_msg=msg) + success('kadmin ACL enforcement') -- cgit v1.1