Path: blob/main/crypto/krb5/src/lib/kadm5/t_kadm5.c
39536 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* lib/kadm5/t_kadm5.c - API tests for libkadm5 */2/*3* Copyright (C) 2021 by the Massachusetts Institute of Technology.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9*10* * Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in15* the documentation and/or other materials provided with the16* distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS19* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT20* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS21* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE22* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,23* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES24* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR25* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,27* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED29* OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132#include "k5-int.h"33#include <kadm5/admin.h>3435static uint32_t api;36static krb5_boolean rpc;3738static krb5_context context;3940/* These must match the creation commands in t_kadm5.py. */41#define ADMIN_PASSWORD "admin"42#define USER_PASSWORD "us3r"4344/* This list must match the supported_enctypes setting in t_kadm5.py. */45static krb5_enctype46default_supported_enctypes[] = {47ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,48ENCTYPE_NULL49};5051static void52check(krb5_error_code code)53{54assert(code == 0);55}5657static void58check_fail(krb5_error_code code, krb5_error_code expected)59{60assert(code == expected);61}6263/*64* Initialize a handle using the global context. The caller must destroy this65* handle before initializing another one. If the client name begins with '$',66* authenticate to kadmin/changepw; otherwise authenticate to kadmin/admin. If67* client is null, return a null handle.68*/69static void *70get_handle(char *client)71{72void *handle;73char *service, *pass;7475if (client == NULL)76return NULL;7778if (*client == '$') {79service = KADM5_CHANGEPW_SERVICE;80client++;81} else {82service = KADM5_ADMIN_SERVICE;83}84pass = (strcmp(client, "user") == 0) ? USER_PASSWORD : ADMIN_PASSWORD;8586check(kadm5_init(context, client, pass, service, NULL,87KADM5_STRUCT_VERSION, api, NULL, &handle));88return handle;89}9091static void92free_handle(void *handle)93{94if (handle != NULL)95check(kadm5_destroy(handle));96}9798static krb5_principal99parse_princ(const char *str)100{101krb5_principal princ;102103check(krb5_parse_name(context, str, &princ));104return princ;105}106107static void108create_simple_policy(char *name)109{110void *handle = get_handle("admin");111kadm5_policy_ent_rec ent;112113memset(&ent, 0, sizeof(ent));114ent.policy = name;115check(kadm5_create_policy(handle, &ent, KADM5_POLICY));116free_handle(handle);117}118119static void120delete_policy(char *name)121{122void *handle = get_handle("admin");123124check(kadm5_delete_policy(handle, name));125free_handle(handle);126}127128static void129compare_policy(kadm5_policy_ent_t x, uint32_t mask)130{131kadm5_policy_ent_rec g;132void *handle = get_handle("admin");133134check(kadm5_get_policy(handle, x->policy, &g));135136assert(strcmp(g.policy, x->policy) == 0);137if (mask & KADM5_PW_MAX_LIFE)138assert(g.pw_max_life == x->pw_max_life);139if (mask & KADM5_PW_MIN_LIFE)140assert(g.pw_min_life == x->pw_min_life);141if (mask & KADM5_PW_MIN_LENGTH)142assert(g.pw_min_length == x->pw_min_length);143if (mask & KADM5_PW_MIN_CLASSES)144assert(g.pw_min_classes == x->pw_min_classes);145if (mask & KADM5_PW_HISTORY_NUM)146assert(g.pw_history_num == x->pw_history_num);147if (mask & KADM5_PW_MAX_FAILURE)148assert(g.pw_max_fail == x->pw_max_fail);149if (mask & KADM5_PW_FAILURE_COUNT_INTERVAL)150assert(g.pw_failcnt_interval == x->pw_failcnt_interval);151if (mask & KADM5_PW_LOCKOUT_DURATION)152assert(g.pw_lockout_duration == x->pw_lockout_duration);153154check(kadm5_free_policy_ent(handle, &g));155free_handle(handle);156}157158static void159create_simple_princ(krb5_principal princ, char *policy)160{161void *handle = get_handle("admin");162kadm5_principal_ent_rec ent;163uint32_t mask = KADM5_PRINCIPAL;164165memset(&ent, 0, sizeof(ent));166ent.principal = princ;167ent.policy = policy;168if (policy != NULL)169mask |= KADM5_POLICY;170check(kadm5_create_principal(handle, &ent, mask, "pw"));171free_handle(handle);172}173174static void175delete_princ(krb5_principal princ)176{177void *handle = get_handle("admin");178179check(kadm5_delete_principal(handle, princ));180free_handle(handle);181}182183static void184compare_key_data(kadm5_principal_ent_t ent, const krb5_enctype *etypes)185{186int i;187188for (i = 0; etypes[i] != ENCTYPE_NULL; i++) {189assert(i < ent->n_key_data);190assert(ent->key_data[i].key_data_ver >= 1);191assert(ent->key_data[i].key_data_type[0] == etypes[i]);192}193}194195static void196compare_princ(kadm5_principal_ent_t x, uint32_t mask)197{198void *handle = get_handle("admin");199kadm5_principal_ent_rec g;200kadm5_policy_ent_rec pol;201202check(kadm5_get_principal(handle, x->principal, &g,203KADM5_PRINCIPAL_NORMAL_MASK));204205assert(krb5_principal_compare(context, g.principal, x->principal));206if (mask & KADM5_POLICY)207assert(strcmp(g.policy, x->policy) == 0);208if (mask & KADM5_PRINC_EXPIRE_TIME)209assert(g.princ_expire_time == x->princ_expire_time);210if (mask & KADM5_MAX_LIFE)211assert(g.max_life == x->max_life);212if (mask & KADM5_MAX_RLIFE)213assert(g.max_renewable_life == x->max_renewable_life);214if (mask & KADM5_FAIL_AUTH_COUNT)215assert(g.fail_auth_count == x->fail_auth_count);216if (mask & KADM5_ATTRIBUTES)217assert(g.attributes == x->attributes);218if (mask & KADM5_KVNO)219assert(g.kvno == x->kvno);220221if (mask & KADM5_PW_EXPIRATION) {222assert(g.pw_expiration == x->pw_expiration);223} else if ((mask & KADM5_POLICY) &&224kadm5_get_policy(handle, g.policy, &pol) == 0) {225/* Check the policy pw_max_life computation. */226if (pol.pw_max_life != 0) {227assert(ts_incr(g.last_pwd_change, pol.pw_max_life) ==228g.pw_expiration);229} else {230assert(g.pw_expiration == 0);231}232check(kadm5_free_policy_ent(handle, &pol));233}234235if (mask & KADM5_POLICY_CLR) {236assert(g.policy == NULL);237if (!(mask & KADM5_PW_EXPIRATION))238assert(g.pw_expiration == 0);239}240241check(kadm5_free_principal_ent(handle, &g));242free_handle(handle);243}244245static void246kinit(krb5_ccache cc, const char *user, const char *pass, const char *service)247{248krb5_get_init_creds_opt *opt;249krb5_principal client = parse_princ(user);250krb5_creds creds;251252check(krb5_get_init_creds_opt_alloc(context, &opt));253check(krb5_get_init_creds_opt_set_out_ccache(context, opt, cc));254check(krb5_get_init_creds_password(context, &creds, client, pass, NULL,255NULL, 0, service, opt));256krb5_get_init_creds_opt_free(context, opt);257krb5_free_cred_contents(context, &creds);258krb5_free_principal(context, client);259}260261static void262cpw_test_fail(char *user, krb5_principal princ, char *pass,263krb5_error_code code)264{265void *handle = get_handle(user);266267check_fail(kadm5_chpass_principal(handle, princ, pass), code);268free_handle(handle);269}270271static void272cpw_test_succeed(char *user, krb5_principal princ, char *pass)273{274cpw_test_fail(user, princ, pass, 0);275}276277static void278test_chpass(void)279{280krb5_principal princ = parse_princ("chpass-test");281krb5_principal hist_princ = parse_princ("kadmin/history");282kadm5_principal_ent_rec ent;283void *handle;284285/* Specify a policy so that kadmin/history is created. */286create_simple_princ(princ, "minlife-pol");287288/* Check kvno and enctypes after a password change. */289handle = get_handle("admin");290check(kadm5_chpass_principal(handle, princ, "newpassword"));291check(kadm5_get_principal(handle, princ, &ent, KADM5_KEY_DATA));292compare_key_data(&ent, default_supported_enctypes);293assert(ent.key_data[0].key_data_kvno == 2);294check(kadm5_free_principal_ent(handle, &ent));295free_handle(handle);296297/* Fails for protected principal. */298cpw_test_fail("admin", hist_princ, "pw", KADM5_PROTECT_PRINCIPAL);299300/* Fails over RPC if "change" ACL is not granted, or if we authenticated to301* kadmin/changepw and are changing another principal's password. */302if (rpc) {303cpw_test_succeed("admin/modify", princ, "pw2");304cpw_test_fail("admin/none", princ, "pw3", KADM5_AUTH_CHANGEPW);305cpw_test_fail("$admin", princ, "pw3", KADM5_AUTH_CHANGEPW);306}307308/* Fails with null handle or principal name. */309cpw_test_fail(NULL, princ, "pw", KADM5_BAD_SERVER_HANDLE);310cpw_test_fail("admin", NULL, "pw", EINVAL);311312delete_princ(princ);313krb5_free_principal(context, princ);314krb5_free_principal(context, hist_princ);315}316317static void318cpol_test_fail(char *user, kadm5_policy_ent_t ent, uint32_t mask,319krb5_error_code code)320{321void *handle = get_handle(user);322323check_fail(kadm5_create_policy(handle, ent, mask | KADM5_POLICY), code);324free_handle(handle);325}326327static void328cpol_test_compare(char *user, kadm5_policy_ent_t ent, uint32_t mask)329{330cpol_test_fail(user, ent, mask, 0);331compare_policy(ent, mask);332delete_policy(ent->policy);333}334335static void336test_create_policy(void)337{338void *handle;339kadm5_policy_ent_rec ent;340341memset(&ent, 0, sizeof(ent));342343/* Fails with undefined mask bit. */344ent.policy = "create-policy-test";345cpol_test_fail("admin", &ent, 0x10000000, KADM5_BAD_MASK);346347/* Fails without KADM5_POLICY mask bit. */348handle = get_handle("admin");349check_fail(kadm5_create_policy(handle, &ent, 0), KADM5_BAD_MASK);350free_handle(handle);351352/* pw_min_life = 0 and pw_min_life != 0 */353cpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);354ent.pw_min_life = 32;355cpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);356357/* pw_max_life = 0 and pw_max_life != 0 */358cpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);359ent.pw_max_life = 32;360cpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);361362/* pw_min_length = 0 (rejected) and pw_min_length != 0 */363cpol_test_fail("admin", &ent, KADM5_PW_MIN_LENGTH, KADM5_BAD_LENGTH);364ent.pw_min_length = 32;365cpol_test_compare("admin", &ent, KADM5_PW_MIN_LENGTH);366367/* pw_min_classes = 0 (rejected), 1, 5, 6 (rejected) */368cpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);369ent.pw_min_classes = 1;370cpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);371ent.pw_min_classes = 5;372cpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);373ent.pw_min_classes = 6;374cpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);375376/* pw_history_num = 0 (rejected), 1, 10 */377cpol_test_fail("admin", &ent, KADM5_PW_HISTORY_NUM, KADM5_BAD_HISTORY);378ent.pw_history_num = 1;379cpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);380ent.pw_history_num = 10;381cpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);382383if (api >= KADM5_API_VERSION_3) {384ent.pw_max_fail = 2;385cpol_test_compare("admin", &ent, KADM5_PW_MAX_FAILURE);386ent.pw_failcnt_interval = 90;387cpol_test_compare("admin", &ent,388KADM5_PW_FAILURE_COUNT_INTERVAL);389ent.pw_lockout_duration = 180;390cpol_test_compare("admin", &ent, KADM5_PW_LOCKOUT_DURATION);391}392393/* Fails over RPC if "add" ACL is not granted, or if we authenticated to394* kadmin/changepw. */395if (rpc) {396cpol_test_fail("$admin", &ent, 0, KADM5_AUTH_ADD);397cpol_test_fail("admin/none", &ent, 0, KADM5_AUTH_ADD);398cpol_test_fail("admin/get", &ent, 0, KADM5_AUTH_ADD);399cpol_test_fail("admin/modify", &ent, 0, KADM5_AUTH_ADD);400cpol_test_fail("admin/delete", &ent, 0, KADM5_AUTH_ADD);401cpol_test_compare("admin/add", &ent, 0);402}403404/* Fails with existing policy name. */405ent.policy = "test-pol";406cpol_test_fail("admin", &ent, 0, KADM5_DUP);407408/* Fails with null or empty policy name, or invalid character in name. */409ent.policy = NULL;410cpol_test_fail("admin", &ent, 0, EINVAL);411ent.policy = "";412cpol_test_fail("admin", &ent, 0, KADM5_BAD_POLICY);413ent.policy = "pol\7";414cpol_test_fail("admin", &ent, 0, KADM5_BAD_POLICY);415416/* Fails with null handle or policy ent. */417cpol_test_fail(NULL, &ent, 0, KADM5_BAD_SERVER_HANDLE);418cpol_test_fail("admin", NULL, 0, EINVAL);419}420421static void422cprinc_test_fail(char *user, kadm5_principal_ent_t ent, uint32_t mask,423char *pass, krb5_error_code code)424{425void *handle = get_handle(user);426427check_fail(kadm5_create_principal(handle, ent, mask | KADM5_PRINCIPAL,428pass), code);429free_handle(handle);430}431432static void433cprinc_test_compare(char *user, kadm5_principal_ent_t ent, uint32_t mask,434char *pass)435{436cprinc_test_fail(user, ent, mask, pass, 0);437compare_princ(ent, mask);438delete_princ(ent->principal);439}440441static void442test_create_principal(void)443{444void *handle;445kadm5_principal_ent_rec ent;446krb5_principal princ = parse_princ("create-principal-test");447krb5_principal user_princ = parse_princ("user");448449memset(&ent, 0, sizeof(ent));450ent.principal = princ;451452/* Fails with undefined or prohibited mask bit. */453cprinc_test_fail("admin", &ent, 0x100000, "", KADM5_BAD_MASK);454cprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, "pw",455KADM5_BAD_MASK);456cprinc_test_fail("admin", &ent, KADM5_MOD_TIME, "pw", KADM5_BAD_MASK);457cprinc_test_fail("admin", &ent, KADM5_MOD_NAME, "pw", KADM5_BAD_MASK);458cprinc_test_fail("admin", &ent, KADM5_MKVNO, "pw", KADM5_BAD_MASK);459cprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, "pw",460KADM5_BAD_MASK);461462/* Fails without KADM5_PRINCIPAL mask bit. */463handle = get_handle("admin");464check_fail(kadm5_create_principal(handle, &ent, 0, "pw"), KADM5_BAD_MASK);465free_handle(handle);466467/* Fails with empty password or password prohibited by policy. */468cprinc_test_fail("admin", &ent, 0, "", KADM5_PASS_Q_TOOSHORT);469ent.policy = "test-pol";470cprinc_test_fail("admin", &ent, KADM5_POLICY, "tP", KADM5_PASS_Q_TOOSHORT);471cprinc_test_fail("admin", &ent, KADM5_POLICY, "testpassword",472KADM5_PASS_Q_CLASS);473cprinc_test_fail("admin", &ent, KADM5_POLICY, "Abyssinia",474KADM5_PASS_Q_DICT);475476cprinc_test_compare("admin", &ent, 0, "pw");477ent.policy = "nonexistent-pol";478cprinc_test_compare("admin", &ent, KADM5_POLICY, "pw");479cprinc_test_compare("admin/rename", &ent, KADM5_POLICY, "pw");480481/* Test pw_expiration explicit specifications vs. policy pw_max_life. */482ent.policy = "test-pol";483cprinc_test_compare("admin", &ent, KADM5_POLICY, "NotinTheDictionary");484cprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME, "pw");485cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw");486cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,487"NotinTheDictionary");488ent.pw_expiration = 1234;489cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw");490cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,491"NotinTheDictionary");492ent.pw_expiration = 999999999;493cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,494"NotinTheDictionary");495ent.policy = "dict-only-pol";496cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,497"pw");498499/* Fails over RPC if "add" ACL is not granted, or if we authenticated to500* kadmin/changepw. */501if (rpc) {502cprinc_test_fail("$admin", &ent, 0, "pw", KADM5_AUTH_ADD);503cprinc_test_fail("admin/none", &ent, 0, "pw", KADM5_AUTH_ADD);504cprinc_test_fail("admin/get", &ent, 0, "pw", KADM5_AUTH_ADD);505cprinc_test_fail("admin/modify", &ent, 0, "pw", KADM5_AUTH_ADD);506cprinc_test_fail("admin/delete", &ent, 0, "pw", KADM5_AUTH_ADD);507}508509/* Fails with existing policy name. */510ent.principal = user_princ;511cprinc_test_fail("admin", &ent, 0, "pw", KADM5_DUP);512513/* Fails with null handle or principal ent. */514cprinc_test_fail(NULL, &ent, 0, "pw", KADM5_BAD_SERVER_HANDLE);515cprinc_test_fail("admin", NULL, 0, "pw", EINVAL);516517krb5_free_principal(context, princ);518krb5_free_principal(context, user_princ);519}520521static void522dpol_test_fail(char *user, char *name, krb5_error_code code)523{524void *handle = get_handle(user);525526check_fail(kadm5_delete_policy(handle, name), code);527free_handle(handle);528}529530static void531dpol_test_succeed(char *user, char *name)532{533dpol_test_fail(user, name, 0);534}535536static void537test_delete_policy(void)538{539krb5_principal princ = parse_princ("delete-policy-test-princ");540541/* Fails with unknown policy. */542dpol_test_fail("admin", "delete-policy-test", KADM5_UNK_POLICY);543544/* Fails with empty policy name. */545dpol_test_fail("admin", "", KADM5_BAD_POLICY);546547/* Succeeds with "delete" ACL (or local authentication). */548create_simple_policy("delete-policy-test");549dpol_test_succeed("admin/delete", "delete-policy-test");550551/* Succeeds even if a principal references the policy, since we now allow552* principals to reference nonexistent policies. */553create_simple_policy("delete-policy-test");554create_simple_princ(princ, "delete-policy-test");555dpol_test_succeed("admin", "delete-policy-test");556delete_princ(princ);557558/* Fails over RPC if "delete" ACL is not granted, or if we authenticated to559* kadmin/changepw. */560if (rpc) {561dpol_test_fail("$admin", "test-pol", KADM5_AUTH_DELETE);562dpol_test_fail("admin/none", "test-pol", KADM5_AUTH_DELETE);563dpol_test_fail("admin/add", "test-pol", KADM5_AUTH_DELETE);564}565566/* Fails with null handle or principal ent. */567dpol_test_fail(NULL, "test-pol", KADM5_BAD_SERVER_HANDLE);568dpol_test_fail("admin", NULL, EINVAL);569570krb5_free_principal(context, princ);571}572573static void574dprinc_test_fail(char *user, krb5_principal princ, krb5_error_code code)575{576void *handle = get_handle(user);577578check_fail(kadm5_delete_principal(handle, princ), code);579free_handle(handle);580}581582static void583dprinc_test_succeed(char *user, krb5_principal princ)584{585dprinc_test_fail(user, princ, 0);586}587588static void589test_delete_principal(void)590{591krb5_principal princ = parse_princ("delete-principal-test");592593/* Fails with unknown principal. */594dprinc_test_fail("admin", princ, KADM5_UNK_PRINC);595596/* Succeeds with "delete" ACL (or local authentication). */597create_simple_princ(princ, NULL);598dprinc_test_succeed("admin/delete", princ);599600/* Fails over RPC if "delete" ACL is not granted, or if we authenticated to601* kadmin/changepw. */602if (rpc) {603dprinc_test_fail("$admin", princ, KADM5_AUTH_DELETE);604dprinc_test_fail("admin/add", princ, KADM5_AUTH_DELETE);605dprinc_test_fail("admin/modify", princ, KADM5_AUTH_DELETE);606dprinc_test_fail("admin/get", princ, KADM5_AUTH_DELETE);607dprinc_test_fail("admin/none", princ, KADM5_AUTH_DELETE);608}609610/* Fails with null handle or principal ent. */611dprinc_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE);612dprinc_test_fail("admin", NULL, EINVAL);613614krb5_free_principal(context, princ);615}616617static void618gpol_test_succeed(char *user, char *name)619{620void *handle = get_handle(user);621kadm5_policy_ent_rec ent;622623check(kadm5_get_policy(handle, name, &ent));624assert(strcmp(ent.policy, name) == 0);625check(kadm5_free_policy_ent(handle, &ent));626free_handle(handle);627}628629static void630gpol_test_fail(char *user, char *name, krb5_error_code code)631{632void *handle = get_handle(user);633kadm5_policy_ent_rec ent;634635check_fail(kadm5_get_policy(handle, name, &ent), code);636free_handle(handle);637}638639static void640test_get_policy(void)641{642/* Fails with unknown policy. */643dpol_test_fail("admin", "unknown-policy", KADM5_UNK_POLICY);644645/* Fails with empty or null policy name or a null handle. */646gpol_test_fail("admin", "", KADM5_BAD_POLICY);647gpol_test_fail("admin", NULL, EINVAL);648gpol_test_fail(NULL, "", KADM5_BAD_SERVER_HANDLE);649650/* Fails over RPC unless "get" ACL is granted or the principal's own policy651* is retrieved. */652if (rpc) {653gpol_test_fail("admin/none", "test-pol", KADM5_AUTH_GET);654gpol_test_fail("admin/add", "test-pol", KADM5_AUTH_GET);655gpol_test_succeed("admin/get", "test-pol");656gpol_test_succeed("user", "minlife-pol");657gpol_test_succeed("$user", "minlife-pol");658}659}660661static void662gprinc_test_succeed(char *user, krb5_principal princ)663{664void *handle = get_handle(user);665kadm5_principal_ent_rec ent;666667check(kadm5_get_principal(handle, princ, &ent,668KADM5_PRINCIPAL_NORMAL_MASK));669assert(krb5_principal_compare(context, ent.principal, princ));670check(kadm5_free_principal_ent(handle, &ent));671free_handle(handle);672}673674static void675gprinc_test_fail(char *user, krb5_principal princ, krb5_error_code code)676{677void *handle = get_handle(user);678kadm5_principal_ent_rec ent;679680check_fail(kadm5_get_principal(handle, princ, &ent,681KADM5_PRINCIPAL_NORMAL_MASK), code);682free_handle(handle);683}684685static void686test_get_principal(void)687{688void *handle;689kadm5_principal_ent_rec ent;690krb5_principal princ = parse_princ("get-principal-test");691krb5_principal admin_princ = parse_princ("admin");692krb5_principal admin_none_princ = parse_princ("admin/none");693int i;694695/* Fails with unknown principal. */696gprinc_test_fail("admin", princ, KADM5_UNK_PRINC);697698create_simple_princ(princ, NULL);699700/* Succeeds with "get" ACL (or local authentication), or operating on701* self. */702gprinc_test_succeed("admin/none", admin_none_princ);703gprinc_test_succeed("$admin", admin_princ);704gprinc_test_succeed("admin/get", princ);705706/* Fails over RPC if "get" ACL is not granted, or if we authenticated to707* kadmin/changepw and getting another principal entry. */708if (rpc) {709gprinc_test_fail("$admin", princ, KADM5_AUTH_GET);710gprinc_test_fail("admin/none", princ, KADM5_AUTH_GET);711gprinc_test_fail("admin/add", princ, KADM5_AUTH_GET);712gprinc_test_fail("admin/modify", princ, KADM5_AUTH_GET);713gprinc_test_fail("admin/delete", princ, KADM5_AUTH_GET);714}715716/* Entry contains no key data or tl-data unless asked for. */717handle = get_handle("admin");718check(kadm5_get_principal(handle, princ, &ent,719KADM5_PRINCIPAL_NORMAL_MASK));720assert(ent.n_tl_data == 0);721assert(ent.n_key_data == 0);722assert(ent.tl_data == NULL);723check(kadm5_free_principal_ent(handle, &ent));724725/* Key data (without the actual keys over RPC) is provided if asked for. */726check(kadm5_get_principal(handle, princ, &ent,727KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA));728assert(ent.n_key_data == 2);729for (i = 0; i < ent.n_key_data; i++)730assert(rpc == (ent.key_data[i].key_data_length[0] == 0));731check(kadm5_free_principal_ent(handle, &ent));732free_handle(handle);733734/* Fails with null handle or principal. */735gprinc_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE);736gprinc_test_fail("admin", NULL, EINVAL);737738delete_princ(princ);739krb5_free_principal(context, princ);740krb5_free_principal(context, admin_princ);741krb5_free_principal(context, admin_none_princ);742}743744static void745test_init_destroy(void)746{747krb5_context ctx;748kadm5_ret_t ret;749kadm5_config_params params;750kadm5_principal_ent_rec ent, gent;751krb5_principal princ = parse_princ("init-test");752krb5_ccache cc;753void *handle;754char hostname[MAXHOSTNAMELEN];755int r;756757memset(¶ms, 0, sizeof(params));758memset(&ent, 0, sizeof(ent));759ent.principal = princ;760761r = gethostname(hostname, sizeof(hostname));762assert(r == 0);763764/* Destroy fails with no server handle. */765check_fail(kadm5_destroy(NULL), KADM5_BAD_SERVER_HANDLE);766767/* Fails with bad structure version mask. */768check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,7690x65432101, api, NULL, &handle),770KADM5_BAD_STRUCT_VERSION);771check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,7721, api, NULL, &handle), KADM5_BAD_STRUCT_VERSION);773774/* Fails with too-old or too-new structure version. */775check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,776KADM5_STRUCT_VERSION_MASK, api, NULL, &handle),777KADM5_OLD_STRUCT_VERSION);778check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,779KADM5_STRUCT_VERSION_MASK | 0xca, api, NULL,780&handle), KADM5_NEW_STRUCT_VERSION);781782/* Fails with bad API version mask. */783check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,784KADM5_STRUCT_VERSION, 0x65432100, NULL, &handle),785KADM5_BAD_API_VERSION);786check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,787KADM5_STRUCT_VERSION, 4, NULL, &handle),788KADM5_BAD_API_VERSION);789790/* Fails with too-old or too-new API version.*/791ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,792KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK, NULL,793&handle);794assert(ret == (rpc ? KADM5_OLD_LIB_API_VERSION :795KADM5_OLD_SERVER_API_VERSION));796ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,797KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK | 0xca, NULL,798&handle);799assert(ret == (rpc ? KADM5_NEW_LIB_API_VERSION :800KADM5_NEW_SERVER_API_VERSION));801802/* Fails with structure and API version reversed. */803check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,804api, KADM5_STRUCT_VERSION, NULL, &handle),805KADM5_BAD_STRUCT_VERSION);806807/* Hardcoded default max lifetime is used when no handle or krb5.conf808* setting is given. */809handle = get_handle("admin");810check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw"));811check(kadm5_get_principal(handle, princ, &gent,812KADM5_PRINCIPAL_NORMAL_MASK));813assert(gent.max_life == KRB5_KDB_MAX_LIFE);814check(kadm5_delete_principal(handle, princ));815check(kadm5_free_principal_ent(handle, &gent));816free_handle(handle);817818/* Fails with configured unknown realm. Do these tests in separate krb5819* contexts since the realm setting sticks to the context. */820check(kadm5_init_krb5_context(&ctx));821params.realm = "";822params.mask = KADM5_CONFIG_REALM;823ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms,824KADM5_STRUCT_VERSION, api, NULL, &handle);825assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT));826krb5_free_context(ctx);827828check(kadm5_init_krb5_context(&ctx));829params.realm = "@";830ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms,831KADM5_STRUCT_VERSION, api, NULL, &handle);832assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT));833krb5_free_context(ctx);834835check(kadm5_init_krb5_context(&ctx));836params.realm = "BAD.REALM";837ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms,838KADM5_STRUCT_VERSION, api, NULL, &handle);839assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT));840krb5_free_context(ctx);841842/* Succeeds with explicit client realm and configured realm. */843check(kadm5_init_krb5_context(&ctx));844params.realm = "KRBTEST.COM";845check(kadm5_init(ctx, "[email protected]", "admin", KADM5_ADMIN_SERVICE,846¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle));847check(kadm5_destroy(handle));848krb5_free_context(ctx);849850/* Succeeds with explicit client realm. */851check(kadm5_init(context, "[email protected]", "admin",852KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, api,853NULL, &handle));854check(kadm5_destroy(handle));855856857if (rpc) {858check(krb5_cc_default(context, &cc));859860/* Succeeds with configured host and port. */861params.admin_server = hostname;862params.kadmind_port = 61001;863params.mask = KADM5_CONFIG_ADMIN_SERVER | KADM5_CONFIG_KADMIND_PORT;864check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,865¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle));866check(kadm5_destroy(handle));867868/* Fails with wrong configured port. */869params.kadmind_port = 4;870check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,871¶ms, KADM5_STRUCT_VERSION, api, NULL,872&handle), KADM5_RPC_ERROR);873874/* Fails with non-resolving hostname. */875params.admin_server = "does.not.exist";876params.mask = KADM5_CONFIG_ADMIN_SERVER;877check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,878¶ms, KADM5_STRUCT_VERSION, api, NULL,879&handle), KADM5_CANT_RESOLVE);880881/* Fails with uninitialized cache. */882check_fail(kadm5_init_with_creds(context, "admin", cc,883KADM5_ADMIN_SERVICE, NULL,884KADM5_STRUCT_VERSION, api, NULL,885&handle), KRB5_FCC_NOFILE);886887/* Succeeds with cache containing kadmin/admin cred. */888kinit(cc, "admin", "admin", KADM5_ADMIN_SERVICE);889check(kadm5_init_with_creds(context, "admin", cc, KADM5_ADMIN_SERVICE,890NULL, KADM5_STRUCT_VERSION, api, NULL,891&handle));892check(kadm5_destroy(handle));893894/* Succeeds with cache containing kadmin/changepw cred. */895kinit(cc, "admin", "admin", KADM5_CHANGEPW_SERVICE);896check(kadm5_init_with_creds(context, "admin", cc,897KADM5_CHANGEPW_SERVICE, NULL,898KADM5_STRUCT_VERSION, api, NULL, &handle));899check(kadm5_destroy(handle));900901/* Fails with cache containing only a TGT. */902kinit(cc, "admin", "admin", NULL);903check_fail(kadm5_init_with_creds(context, "admin", cc,904KADM5_ADMIN_SERVICE, NULL,905KADM5_STRUCT_VERSION, api, NULL,906&handle), KRB5_CC_NOTFOUND);907908/* Fails authenticating to non-kadmin princ. */909check_fail(kadm5_init(context, "admin", "admin", "user", NULL,910KADM5_STRUCT_VERSION, api, NULL, &handle),911KADM5_RPC_ERROR);912913/* Fails authenticating to nonexistent princ. */914check_fail(kadm5_init(context, "admin", "admin", "noexist", NULL,915KADM5_STRUCT_VERSION, api, NULL, &handle),916KADM5_SECURE_PRINC_MISSING);917918/* Fails authenticating to client princ (which is non-kadmin). */919check_fail(kadm5_init(context, "admin", "admin", "admin", NULL,920KADM5_STRUCT_VERSION, api, NULL, &handle),921KADM5_RPC_ERROR);922923/* Fails with wrong password. */924check_fail(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE,925NULL, KADM5_STRUCT_VERSION, api, NULL, &handle),926KADM5_BAD_PASSWORD);927928/* Fails with null client name. */929check_fail(kadm5_init(context, NULL, "admin", KADM5_ADMIN_SERVICE,930NULL, KADM5_STRUCT_VERSION, api, NULL, &handle),931EINVAL);932933/* Fails with nonexistent client name. */934check_fail(kadm5_init(context, "noexist", "admin", KADM5_ADMIN_SERVICE,935NULL, KADM5_STRUCT_VERSION, api, NULL, &handle),936KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);937938/* Fails with nonexistent client name with explicit realm. */939check_fail(kadm5_init(context, "[email protected]", "admin",940KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION,941api, NULL, &handle),942KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);943944/* Fails with nonexistent client name with unknown realm. */945check_fail(kadm5_init(context, "[email protected]", "admin",946KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION,947api, NULL, &handle), KRB5_REALM_UNKNOWN);948949/* Fails with known name but unknown realm. */950check_fail(kadm5_init(context, "[email protected]", "admin",951KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION,952api, NULL, &handle), KRB5_REALM_UNKNOWN);953954check(krb5_cc_destroy(context, cc));955} else {956/* Fails with nonexistent stash file. */957params.stash_file = "does/not/exist";958params.mask = KADM5_CONFIG_STASH_FILE;959check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,960¶ms, KADM5_STRUCT_VERSION, api, NULL,961&handle), KRB5_KDB_CANTREAD_STORED);962963/* Uses configured defaults for principal creation. */964params.max_life = 10;965params.max_rlife = 20;966params.expiration = 30;967params.num_keysalts = 0;968params.mask = KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE |969KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES;970check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,971¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle));972check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw"));973check(kadm5_get_principal(handle, princ, &gent,974KADM5_PRINCIPAL_NORMAL_MASK |975KADM5_KEY_DATA));976assert(gent.max_life == 10);977assert(gent.max_renewable_life == 20);978assert(gent.princ_expire_time == 30);979assert(gent.n_key_data == 0);980check(kadm5_delete_principal(handle, princ));981check(kadm5_free_principal_ent(handle, &gent));982check(kadm5_destroy(handle));983984/* Succeeds with incorrect password using local auth. */985check(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE, NULL,986KADM5_STRUCT_VERSION, api, NULL, &handle));987check(kadm5_destroy(handle));988989/* Succeeds with null service using local auth. */990check(kadm5_init(context, "admin", "admin", NULL, NULL,991KADM5_STRUCT_VERSION, api, NULL, &handle));992check(kadm5_destroy(handle));993994/* Succeeds with nonexistent, non-kadmin service using local auth. */995check(kadm5_init(context, "admin", "admin", "foobar", NULL,996KADM5_STRUCT_VERSION, api, NULL, &handle));997check(kadm5_destroy(handle));998}9991000krb5_free_principal(context, princ);1001}10021003static void1004mpol_test_fail(char *user, kadm5_policy_ent_t ent, uint32_t mask,1005krb5_error_code code)1006{1007void *handle = get_handle(user);10081009check_fail(kadm5_modify_policy(handle, ent, mask), code);1010free_handle(handle);1011}10121013static void1014mpol_test_compare(void *handle, kadm5_policy_ent_t ent, uint32_t mask)1015{1016mpol_test_fail(handle, ent, mask, 0);1017compare_policy(ent, mask);1018}10191020static void1021test_modify_policy(void)1022{1023kadm5_policy_ent_rec ent;10241025memset(&ent, 0, sizeof(ent));1026ent.policy = "modify-policy-test";1027create_simple_policy(ent.policy);10281029/* pw_min_life = 0 and pw_min_life != 0 */1030mpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);1031ent.pw_min_life = 32;1032mpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);10331034/* pw_max_life = 0 and pw_max_life != 0 */1035mpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);1036ent.pw_max_life = 32;1037mpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);10381039/* pw_min_length = 0 (rejected) and pw_min_length != 0 */1040mpol_test_fail("admin", &ent, KADM5_PW_MIN_LENGTH, KADM5_BAD_LENGTH);1041ent.pw_min_length = 8;1042mpol_test_compare("admin", &ent, KADM5_PW_MIN_LENGTH);10431044/* pw_min_classes = 0 (rejected), 1, 5, 6 (rejected) */1045mpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);1046ent.pw_min_classes = 1;1047mpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);1048ent.pw_min_classes = 5;1049mpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);1050ent.pw_min_classes = 6;1051mpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);10521053/* pw_history_num = 0 (rejected), 1, 10 */1054mpol_test_fail("admin", &ent, KADM5_PW_HISTORY_NUM, KADM5_BAD_HISTORY);1055ent.pw_history_num = 1;1056mpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);1057ent.pw_history_num = 10;1058mpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);10591060if (api >= KADM5_API_VERSION_3) {1061ent.pw_max_fail = 2;1062mpol_test_compare("admin", &ent, KADM5_PW_MAX_FAILURE);1063ent.pw_failcnt_interval = 90;1064mpol_test_compare("admin", &ent, KADM5_PW_FAILURE_COUNT_INTERVAL);1065ent.pw_lockout_duration = 180;1066mpol_test_compare("admin", &ent, KADM5_PW_LOCKOUT_DURATION);1067}10681069/* Fails over RPC if "modify" ACL is not granted, or if we authenticated to1070* kadmin/changepw. */1071if (rpc) {1072mpol_test_fail("$admin", &ent, KADM5_PW_MAX_LIFE, KADM5_AUTH_MODIFY);1073mpol_test_fail("admin/none", &ent, KADM5_PW_MAX_LIFE,1074KADM5_AUTH_MODIFY);1075mpol_test_fail("admin/get", &ent, KADM5_PW_MAX_LIFE,1076KADM5_AUTH_MODIFY);1077mpol_test_compare("admin/modify", &ent, KADM5_PW_MAX_LIFE);1078}10791080delete_policy(ent.policy);10811082/* Fails with empty or null policy name. */1083ent.policy = NULL;1084mpol_test_fail("admin", &ent, KADM5_PW_MAX_LIFE, EINVAL);1085ent.policy = "";1086mpol_test_fail("admin", &ent, KADM5_PW_MAX_LIFE, KADM5_BAD_POLICY);10871088/* Fails with null handle or policy ent. */1089mpol_test_fail(NULL, &ent, KADM5_PW_MAX_LIFE, KADM5_BAD_SERVER_HANDLE);1090mpol_test_fail("admin", NULL, KADM5_PW_MAX_LIFE, EINVAL);1091}10921093static void1094mprinc_test_fail(char *user, kadm5_principal_ent_t ent, uint32_t mask,1095krb5_error_code code)1096{1097void *handle = get_handle(user);10981099check_fail(kadm5_modify_principal(handle, ent, mask), code);1100free_handle(handle);1101}11021103static void1104mprinc_test_compare(char *user, kadm5_principal_ent_t ent, uint32_t mask)1105{1106mprinc_test_fail(user, ent, mask, 0);1107compare_princ(ent, mask);1108}11091110static void1111test_modify_principal(void)1112{1113void *handle;1114krb5_principal princ = parse_princ("modify-principal-test");1115kadm5_principal_ent_rec ent;1116krb5_tl_data tl = { NULL, 1, 1, (uint8_t *)"x" };1117krb5_tl_data tl2 = { NULL, 999, 6, (uint8_t *)"foobar" };11181119memset(&ent, 0, sizeof(ent));1120ent.principal = princ;11211122/* Fails with unknown principal. */1123mprinc_test_fail("admin", &ent, KADM5_KVNO, KADM5_UNK_PRINC);11241125create_simple_princ(princ, NULL);11261127/* Fails with prohibited mask bit or tl-data type. */1128mprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, KADM5_BAD_MASK);1129mprinc_test_fail("admin", &ent, KADM5_KEY_DATA, KADM5_BAD_MASK);1130mprinc_test_fail("admin", &ent, KADM5_LAST_FAILED, KADM5_BAD_MASK);1131mprinc_test_fail("admin", &ent, KADM5_LAST_SUCCESS, KADM5_BAD_MASK);1132mprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, KADM5_BAD_MASK);1133mprinc_test_fail("admin", &ent, KADM5_MKVNO, KADM5_BAD_MASK);1134mprinc_test_fail("admin", &ent, KADM5_MOD_NAME, KADM5_BAD_MASK);1135mprinc_test_fail("admin", &ent, KADM5_MOD_TIME, KADM5_BAD_MASK);1136mprinc_test_fail("admin", &ent, KADM5_PRINCIPAL, KADM5_BAD_MASK);11371138/* Fails with tl-data type below 256. */1139ent.n_tl_data = 1;1140ent.tl_data = &tl;1141mprinc_test_fail("admin", &ent, KADM5_TL_DATA, KADM5_BAD_TL_TYPE);11421143/* Fails with fail_auth_count other than zero. */1144ent.fail_auth_count = 1234;1145mprinc_test_fail("admin", &ent, KADM5_FAIL_AUTH_COUNT,1146KADM5_BAD_SERVER_PARAMS);1147ent.fail_auth_count = 0;11481149/* Succeeds with zero values of various fields. */1150mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION);1151mprinc_test_compare("admin", &ent, KADM5_MAX_LIFE);1152mprinc_test_compare("admin", &ent, KADM5_MAX_RLIFE);1153mprinc_test_compare("admin", &ent, KADM5_FAIL_AUTH_COUNT);1154mprinc_test_compare("admin/modify", &ent, KADM5_PRINC_EXPIRE_TIME);1155mprinc_test_compare("admin", &ent, KADM5_POLICY_CLR);11561157/* Setting a policy causes a pw_expiration computation. Explicit1158* PW_EXPIRATION overrides the policy. */1159ent.pw_expiration = 1234;1160mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION);1161ent.policy = "dict-only-pol";1162mprinc_test_compare("admin", &ent, KADM5_POLICY);1163ent.policy = "test-pol";1164mprinc_test_compare("admin", &ent, KADM5_POLICY);1165ent.pw_expiration = 999999999;1166mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION);1167mprinc_test_compare("admin", &ent, KADM5_POLICY_CLR);11681169/* Succeeds with non-zero values of various fields. */1170ent.princ_expire_time = 1234;1171mprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME);1172ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX;1173mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES);1174ent.attributes = KRB5_KDB_REQUIRES_PWCHANGE;1175mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES);1176ent.attributes = KRB5_KDB_DISALLOW_TGT_BASED;1177mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES);1178ent.max_life = 3456;1179mprinc_test_compare("admin", &ent, KADM5_MAX_LIFE);1180ent.kvno = 7;1181mprinc_test_compare("admin", &ent, KADM5_KVNO);11821183/* Fails over RPC if "modify" ACL is not granted, or if we authenticated to1184* kadmin/changepw. */1185if (rpc) {1186mprinc_test_fail("$admin", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);1187mprinc_test_fail("admin/none", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);1188mprinc_test_fail("admin/get", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);1189mprinc_test_fail("admin/add", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);1190mprinc_test_fail("admin/delete", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);1191}11921193/* tl-data of type > 255 is accepted. */1194handle = get_handle("admin");1195ent.max_renewable_life = 88;1196ent.tl_data = &tl2;1197check(kadm5_modify_principal(handle, &ent,1198KADM5_MAX_RLIFE | KADM5_TL_DATA));1199memset(&ent, 0, sizeof(ent));1200check(kadm5_get_principal(handle, princ, &ent,1201KADM5_PRINCIPAL_NORMAL_MASK | KADM5_TL_DATA));1202assert(ent.max_renewable_life == 88);1203assert(ent.n_tl_data == 1);1204assert(ent.tl_data->tl_data_type == tl2.tl_data_type);1205assert(ent.tl_data->tl_data_length == tl2.tl_data_length);1206assert(memcmp(ent.tl_data->tl_data_contents, tl2.tl_data_contents,1207tl2.tl_data_length) == 0);1208check(kadm5_free_principal_ent(handle, &ent));1209free_handle(handle);12101211/* Fails with null handle or principal ent. */1212mprinc_test_fail(NULL, &ent, KADM5_KVNO, KADM5_BAD_SERVER_HANDLE);1213mprinc_test_fail("admin", NULL, KADM5_KVNO, EINVAL);12141215delete_princ(princ);1216krb5_free_principal(context, princ);1217}12181219static void1220rnd_test_fail(char *user, krb5_principal princ, krb5_error_code code)1221{1222void *handle = get_handle(user);12231224check_fail(kadm5_randkey_principal(handle, princ, NULL, NULL), code);1225free_handle(handle);1226}12271228static void1229rnd_test_succeed(char *user, krb5_principal princ)1230{1231rnd_test_fail(user, princ, 0);1232}12331234static void1235test_randkey(void)1236{1237void *handle;1238krb5_principal princ = parse_princ("randkey-principal-test");1239krb5_principal user_princ = parse_princ("user");1240krb5_principal admin_princ = parse_princ("admin");1241kadm5_principal_ent_rec ent;1242krb5_keyblock *keys;1243int n_keys, i;12441245create_simple_princ(princ, NULL);12461247/* Check kvno and enctypes after randkey. */1248handle = get_handle("admin");1249check(kadm5_randkey_principal(handle, princ, &keys, &n_keys));1250check(kadm5_get_principal(handle, princ, &ent, KADM5_KEY_DATA));1251compare_key_data(&ent, default_supported_enctypes);1252assert(ent.key_data[0].key_data_kvno == 2);1253assert(n_keys == ent.n_key_data);1254for (i = 0; i < n_keys; i++)1255krb5_free_keyblock_contents(context, &keys[i]);1256free(keys);1257check(kadm5_free_principal_ent(handle, &ent));1258free_handle(handle);12591260/*1261* Fails over RPC if "change" ACL is not granted, or if we authenticated to1262* kadmin/changepw and are changing another principal's password, or for1263* self-service if the policy minimum life has not elapsed since the last1264* key change.1265*/1266if (rpc) {1267rnd_test_fail("$admin", user_princ, KADM5_AUTH_CHANGEPW);1268rnd_test_fail("admin/none", user_princ, KADM5_AUTH_CHANGEPW);1269rnd_test_fail("admin/delete", user_princ, KADM5_AUTH_CHANGEPW);1270rnd_test_succeed("admin/modify", user_princ);1271cpw_test_succeed("admin", user_princ, USER_PASSWORD);1272rnd_test_fail("user", user_princ, KADM5_PASS_TOOSOON);1273rnd_test_fail("$user", user_princ, KADM5_PASS_TOOSOON);1274}12751276/* Succeeds with change privilege in spite of policy minimum life. */1277rnd_test_succeed("admin/modify", user_princ);1278cpw_test_succeed("admin", user_princ, USER_PASSWORD);12791280/* Succeeds for self-service when authenticating to kadmin/changepw. */1281handle = get_handle("$admin");1282check(kadm5_randkey_principal(handle, admin_princ, NULL, NULL));1283check(kadm5_chpass_principal(handle, admin_princ, ADMIN_PASSWORD));1284free_handle(handle);12851286/* Fails with null handle or principal name. */1287rnd_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE);1288rnd_test_fail("admin", NULL, EINVAL);12891290delete_princ(princ);1291krb5_free_principal(context, princ);1292krb5_free_principal(context, user_princ);1293krb5_free_principal(context, admin_princ);1294}12951296int1297main(int argc, char **argv)1298{1299assert(argc == 2);1300rpc = (strcmp(argv[1], "clnt") == 0);13011302check(kadm5_init_krb5_context(&context));13031304api = KADM5_API_VERSION_2;1305test_create_policy();1306test_get_policy();1307test_modify_policy();13081309api = KADM5_API_VERSION_4;1310test_chpass();1311test_create_policy();1312test_create_principal();1313test_delete_policy();1314test_delete_principal();1315test_get_policy();1316test_get_principal();1317test_init_destroy();1318test_modify_policy();1319test_modify_principal();1320test_randkey();13211322krb5_free_context(context);13231324return 0;1325}132613271328