xref: /freebsd/crypto/krb5/src/lib/kadm5/t_kadm5.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* lib/kadm5/t_kadm5.c - API tests for libkadm5 */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright (C) 2021 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All rights reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Redistribution and use in source and binary forms, with or without
8*7f2fe78bSCy Schubert  * modification, are permitted provided that the following conditions
9*7f2fe78bSCy Schubert  * are met:
10*7f2fe78bSCy Schubert  *
11*7f2fe78bSCy Schubert  * * Redistributions of source code must retain the above copyright
12*7f2fe78bSCy Schubert  *   notice, this list of conditions and the following disclaimer.
13*7f2fe78bSCy Schubert  *
14*7f2fe78bSCy Schubert  * * Redistributions in binary form must reproduce the above copyright
15*7f2fe78bSCy Schubert  *   notice, this list of conditions and the following disclaimer in
16*7f2fe78bSCy Schubert  *   the documentation and/or other materials provided with the
17*7f2fe78bSCy Schubert  *   distribution.
18*7f2fe78bSCy Schubert  *
19*7f2fe78bSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*7f2fe78bSCy Schubert  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*7f2fe78bSCy Schubert  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22*7f2fe78bSCy Schubert  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23*7f2fe78bSCy Schubert  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24*7f2fe78bSCy Schubert  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25*7f2fe78bSCy Schubert  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26*7f2fe78bSCy Schubert  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*7f2fe78bSCy Schubert  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28*7f2fe78bSCy Schubert  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*7f2fe78bSCy Schubert  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30*7f2fe78bSCy Schubert  * OF THE POSSIBILITY OF SUCH DAMAGE.
31*7f2fe78bSCy Schubert  */
32*7f2fe78bSCy Schubert 
33*7f2fe78bSCy Schubert #include "k5-int.h"
34*7f2fe78bSCy Schubert #include <kadm5/admin.h>
35*7f2fe78bSCy Schubert 
36*7f2fe78bSCy Schubert static uint32_t api;
37*7f2fe78bSCy Schubert static krb5_boolean rpc;
38*7f2fe78bSCy Schubert 
39*7f2fe78bSCy Schubert static krb5_context context;
40*7f2fe78bSCy Schubert 
41*7f2fe78bSCy Schubert /* These must match the creation commands in t_kadm5.py. */
42*7f2fe78bSCy Schubert #define ADMIN_PASSWORD "admin"
43*7f2fe78bSCy Schubert #define USER_PASSWORD "us3r"
44*7f2fe78bSCy Schubert 
45*7f2fe78bSCy Schubert /* This list must match the supported_enctypes setting in t_kadm5.py. */
46*7f2fe78bSCy Schubert static krb5_enctype
47*7f2fe78bSCy Schubert default_supported_enctypes[] = {
48*7f2fe78bSCy Schubert     ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
49*7f2fe78bSCy Schubert     ENCTYPE_NULL
50*7f2fe78bSCy Schubert };
51*7f2fe78bSCy Schubert 
52*7f2fe78bSCy Schubert static void
check(krb5_error_code code)53*7f2fe78bSCy Schubert check(krb5_error_code code)
54*7f2fe78bSCy Schubert {
55*7f2fe78bSCy Schubert     assert(code == 0);
56*7f2fe78bSCy Schubert }
57*7f2fe78bSCy Schubert 
58*7f2fe78bSCy Schubert static void
check_fail(krb5_error_code code,krb5_error_code expected)59*7f2fe78bSCy Schubert check_fail(krb5_error_code code, krb5_error_code expected)
60*7f2fe78bSCy Schubert {
61*7f2fe78bSCy Schubert     assert(code == expected);
62*7f2fe78bSCy Schubert }
63*7f2fe78bSCy Schubert 
64*7f2fe78bSCy Schubert /*
65*7f2fe78bSCy Schubert  * Initialize a handle using the global context.  The caller must destroy this
66*7f2fe78bSCy Schubert  * handle before initializing another one.  If the client name begins with '$',
67*7f2fe78bSCy Schubert  * authenticate to kadmin/changepw; otherwise authenticate to kadmin/admin.  If
68*7f2fe78bSCy Schubert  * client is null, return a null handle.
69*7f2fe78bSCy Schubert  */
70*7f2fe78bSCy Schubert static void *
get_handle(char * client)71*7f2fe78bSCy Schubert get_handle(char *client)
72*7f2fe78bSCy Schubert {
73*7f2fe78bSCy Schubert     void *handle;
74*7f2fe78bSCy Schubert     char *service, *pass;
75*7f2fe78bSCy Schubert 
76*7f2fe78bSCy Schubert     if (client == NULL)
77*7f2fe78bSCy Schubert         return NULL;
78*7f2fe78bSCy Schubert 
79*7f2fe78bSCy Schubert     if (*client == '$') {
80*7f2fe78bSCy Schubert         service = KADM5_CHANGEPW_SERVICE;
81*7f2fe78bSCy Schubert         client++;
82*7f2fe78bSCy Schubert     } else {
83*7f2fe78bSCy Schubert         service = KADM5_ADMIN_SERVICE;
84*7f2fe78bSCy Schubert     }
85*7f2fe78bSCy Schubert     pass = (strcmp(client, "user") == 0) ? USER_PASSWORD : ADMIN_PASSWORD;
86*7f2fe78bSCy Schubert 
87*7f2fe78bSCy Schubert     check(kadm5_init(context, client, pass, service, NULL,
88*7f2fe78bSCy Schubert                      KADM5_STRUCT_VERSION, api, NULL, &handle));
89*7f2fe78bSCy Schubert     return handle;
90*7f2fe78bSCy Schubert }
91*7f2fe78bSCy Schubert 
92*7f2fe78bSCy Schubert static void
free_handle(void * handle)93*7f2fe78bSCy Schubert free_handle(void *handle)
94*7f2fe78bSCy Schubert {
95*7f2fe78bSCy Schubert     if (handle != NULL)
96*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
97*7f2fe78bSCy Schubert }
98*7f2fe78bSCy Schubert 
99*7f2fe78bSCy Schubert static krb5_principal
parse_princ(const char * str)100*7f2fe78bSCy Schubert parse_princ(const char *str)
101*7f2fe78bSCy Schubert {
102*7f2fe78bSCy Schubert     krb5_principal princ;
103*7f2fe78bSCy Schubert 
104*7f2fe78bSCy Schubert     check(krb5_parse_name(context, str, &princ));
105*7f2fe78bSCy Schubert     return princ;
106*7f2fe78bSCy Schubert }
107*7f2fe78bSCy Schubert 
108*7f2fe78bSCy Schubert static void
create_simple_policy(char * name)109*7f2fe78bSCy Schubert create_simple_policy(char *name)
110*7f2fe78bSCy Schubert {
111*7f2fe78bSCy Schubert     void *handle = get_handle("admin");
112*7f2fe78bSCy Schubert     kadm5_policy_ent_rec ent;
113*7f2fe78bSCy Schubert 
114*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
115*7f2fe78bSCy Schubert     ent.policy = name;
116*7f2fe78bSCy Schubert     check(kadm5_create_policy(handle, &ent, KADM5_POLICY));
117*7f2fe78bSCy Schubert     free_handle(handle);
118*7f2fe78bSCy Schubert }
119*7f2fe78bSCy Schubert 
120*7f2fe78bSCy Schubert static void
delete_policy(char * name)121*7f2fe78bSCy Schubert delete_policy(char *name)
122*7f2fe78bSCy Schubert {
123*7f2fe78bSCy Schubert     void *handle = get_handle("admin");
124*7f2fe78bSCy Schubert 
125*7f2fe78bSCy Schubert     check(kadm5_delete_policy(handle, name));
126*7f2fe78bSCy Schubert     free_handle(handle);
127*7f2fe78bSCy Schubert }
128*7f2fe78bSCy Schubert 
129*7f2fe78bSCy Schubert static void
compare_policy(kadm5_policy_ent_t x,uint32_t mask)130*7f2fe78bSCy Schubert compare_policy(kadm5_policy_ent_t x, uint32_t mask)
131*7f2fe78bSCy Schubert {
132*7f2fe78bSCy Schubert     kadm5_policy_ent_rec g;
133*7f2fe78bSCy Schubert     void *handle = get_handle("admin");
134*7f2fe78bSCy Schubert 
135*7f2fe78bSCy Schubert     check(kadm5_get_policy(handle, x->policy, &g));
136*7f2fe78bSCy Schubert 
137*7f2fe78bSCy Schubert     assert(strcmp(g.policy, x->policy) == 0);
138*7f2fe78bSCy Schubert     if (mask & KADM5_PW_MAX_LIFE)
139*7f2fe78bSCy Schubert         assert(g.pw_max_life == x->pw_max_life);
140*7f2fe78bSCy Schubert     if (mask & KADM5_PW_MIN_LIFE)
141*7f2fe78bSCy Schubert         assert(g.pw_min_life == x->pw_min_life);
142*7f2fe78bSCy Schubert     if (mask & KADM5_PW_MIN_LENGTH)
143*7f2fe78bSCy Schubert         assert(g.pw_min_length == x->pw_min_length);
144*7f2fe78bSCy Schubert     if (mask & KADM5_PW_MIN_CLASSES)
145*7f2fe78bSCy Schubert         assert(g.pw_min_classes == x->pw_min_classes);
146*7f2fe78bSCy Schubert     if (mask & KADM5_PW_HISTORY_NUM)
147*7f2fe78bSCy Schubert         assert(g.pw_history_num == x->pw_history_num);
148*7f2fe78bSCy Schubert     if (mask & KADM5_PW_MAX_FAILURE)
149*7f2fe78bSCy Schubert         assert(g.pw_max_fail == x->pw_max_fail);
150*7f2fe78bSCy Schubert     if (mask & KADM5_PW_FAILURE_COUNT_INTERVAL)
151*7f2fe78bSCy Schubert         assert(g.pw_failcnt_interval == x->pw_failcnt_interval);
152*7f2fe78bSCy Schubert     if (mask & KADM5_PW_LOCKOUT_DURATION)
153*7f2fe78bSCy Schubert         assert(g.pw_lockout_duration == x->pw_lockout_duration);
154*7f2fe78bSCy Schubert 
155*7f2fe78bSCy Schubert     check(kadm5_free_policy_ent(handle, &g));
156*7f2fe78bSCy Schubert     free_handle(handle);
157*7f2fe78bSCy Schubert }
158*7f2fe78bSCy Schubert 
159*7f2fe78bSCy Schubert static void
create_simple_princ(krb5_principal princ,char * policy)160*7f2fe78bSCy Schubert create_simple_princ(krb5_principal princ, char *policy)
161*7f2fe78bSCy Schubert {
162*7f2fe78bSCy Schubert     void *handle = get_handle("admin");
163*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
164*7f2fe78bSCy Schubert     uint32_t mask = KADM5_PRINCIPAL;
165*7f2fe78bSCy Schubert 
166*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
167*7f2fe78bSCy Schubert     ent.principal = princ;
168*7f2fe78bSCy Schubert     ent.policy = policy;
169*7f2fe78bSCy Schubert     if (policy != NULL)
170*7f2fe78bSCy Schubert         mask |= KADM5_POLICY;
171*7f2fe78bSCy Schubert     check(kadm5_create_principal(handle, &ent, mask, "pw"));
172*7f2fe78bSCy Schubert     free_handle(handle);
173*7f2fe78bSCy Schubert }
174*7f2fe78bSCy Schubert 
175*7f2fe78bSCy Schubert static void
delete_princ(krb5_principal princ)176*7f2fe78bSCy Schubert delete_princ(krb5_principal princ)
177*7f2fe78bSCy Schubert {
178*7f2fe78bSCy Schubert     void *handle = get_handle("admin");
179*7f2fe78bSCy Schubert 
180*7f2fe78bSCy Schubert     check(kadm5_delete_principal(handle, princ));
181*7f2fe78bSCy Schubert     free_handle(handle);
182*7f2fe78bSCy Schubert }
183*7f2fe78bSCy Schubert 
184*7f2fe78bSCy Schubert static void
compare_key_data(kadm5_principal_ent_t ent,const krb5_enctype * etypes)185*7f2fe78bSCy Schubert compare_key_data(kadm5_principal_ent_t ent, const krb5_enctype *etypes)
186*7f2fe78bSCy Schubert {
187*7f2fe78bSCy Schubert     int i;
188*7f2fe78bSCy Schubert 
189*7f2fe78bSCy Schubert     for (i = 0; etypes[i] != ENCTYPE_NULL; i++) {
190*7f2fe78bSCy Schubert         assert(i < ent->n_key_data);
191*7f2fe78bSCy Schubert         assert(ent->key_data[i].key_data_ver >= 1);
192*7f2fe78bSCy Schubert         assert(ent->key_data[i].key_data_type[0] == etypes[i]);
193*7f2fe78bSCy Schubert     }
194*7f2fe78bSCy Schubert }
195*7f2fe78bSCy Schubert 
196*7f2fe78bSCy Schubert static void
compare_princ(kadm5_principal_ent_t x,uint32_t mask)197*7f2fe78bSCy Schubert compare_princ(kadm5_principal_ent_t x, uint32_t mask)
198*7f2fe78bSCy Schubert {
199*7f2fe78bSCy Schubert     void *handle = get_handle("admin");
200*7f2fe78bSCy Schubert     kadm5_principal_ent_rec g;
201*7f2fe78bSCy Schubert     kadm5_policy_ent_rec pol;
202*7f2fe78bSCy Schubert 
203*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, x->principal, &g,
204*7f2fe78bSCy Schubert                               KADM5_PRINCIPAL_NORMAL_MASK));
205*7f2fe78bSCy Schubert 
206*7f2fe78bSCy Schubert     assert(krb5_principal_compare(context, g.principal, x->principal));
207*7f2fe78bSCy Schubert     if (mask & KADM5_POLICY)
208*7f2fe78bSCy Schubert         assert(strcmp(g.policy, x->policy) == 0);
209*7f2fe78bSCy Schubert     if (mask & KADM5_PRINC_EXPIRE_TIME)
210*7f2fe78bSCy Schubert         assert(g.princ_expire_time == x->princ_expire_time);
211*7f2fe78bSCy Schubert     if (mask & KADM5_MAX_LIFE)
212*7f2fe78bSCy Schubert         assert(g.max_life == x->max_life);
213*7f2fe78bSCy Schubert     if (mask & KADM5_MAX_RLIFE)
214*7f2fe78bSCy Schubert         assert(g.max_renewable_life == x->max_renewable_life);
215*7f2fe78bSCy Schubert     if (mask & KADM5_FAIL_AUTH_COUNT)
216*7f2fe78bSCy Schubert         assert(g.fail_auth_count == x->fail_auth_count);
217*7f2fe78bSCy Schubert     if (mask & KADM5_ATTRIBUTES)
218*7f2fe78bSCy Schubert         assert(g.attributes == x->attributes);
219*7f2fe78bSCy Schubert     if (mask & KADM5_KVNO)
220*7f2fe78bSCy Schubert         assert(g.kvno == x->kvno);
221*7f2fe78bSCy Schubert 
222*7f2fe78bSCy Schubert     if (mask & KADM5_PW_EXPIRATION) {
223*7f2fe78bSCy Schubert         assert(g.pw_expiration == x->pw_expiration);
224*7f2fe78bSCy Schubert     } else if ((mask & KADM5_POLICY) &&
225*7f2fe78bSCy Schubert                kadm5_get_policy(handle, g.policy, &pol) == 0) {
226*7f2fe78bSCy Schubert         /* Check the policy pw_max_life computation. */
227*7f2fe78bSCy Schubert         if (pol.pw_max_life != 0) {
228*7f2fe78bSCy Schubert             assert(ts_incr(g.last_pwd_change, pol.pw_max_life) ==
229*7f2fe78bSCy Schubert                    g.pw_expiration);
230*7f2fe78bSCy Schubert         } else {
231*7f2fe78bSCy Schubert             assert(g.pw_expiration == 0);
232*7f2fe78bSCy Schubert         }
233*7f2fe78bSCy Schubert         check(kadm5_free_policy_ent(handle, &pol));
234*7f2fe78bSCy Schubert     }
235*7f2fe78bSCy Schubert 
236*7f2fe78bSCy Schubert     if (mask & KADM5_POLICY_CLR) {
237*7f2fe78bSCy Schubert         assert(g.policy == NULL);
238*7f2fe78bSCy Schubert         if (!(mask & KADM5_PW_EXPIRATION))
239*7f2fe78bSCy Schubert             assert(g.pw_expiration == 0);
240*7f2fe78bSCy Schubert     }
241*7f2fe78bSCy Schubert 
242*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &g));
243*7f2fe78bSCy Schubert     free_handle(handle);
244*7f2fe78bSCy Schubert }
245*7f2fe78bSCy Schubert 
246*7f2fe78bSCy Schubert static void
kinit(krb5_ccache cc,const char * user,const char * pass,const char * service)247*7f2fe78bSCy Schubert kinit(krb5_ccache cc, const char *user, const char *pass, const char *service)
248*7f2fe78bSCy Schubert {
249*7f2fe78bSCy Schubert     krb5_get_init_creds_opt *opt;
250*7f2fe78bSCy Schubert     krb5_principal client = parse_princ(user);
251*7f2fe78bSCy Schubert     krb5_creds creds;
252*7f2fe78bSCy Schubert 
253*7f2fe78bSCy Schubert     check(krb5_get_init_creds_opt_alloc(context, &opt));
254*7f2fe78bSCy Schubert     check(krb5_get_init_creds_opt_set_out_ccache(context, opt, cc));
255*7f2fe78bSCy Schubert     check(krb5_get_init_creds_password(context, &creds, client, pass, NULL,
256*7f2fe78bSCy Schubert                                        NULL, 0, service, opt));
257*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_free(context, opt);
258*7f2fe78bSCy Schubert     krb5_free_cred_contents(context, &creds);
259*7f2fe78bSCy Schubert     krb5_free_principal(context, client);
260*7f2fe78bSCy Schubert }
261*7f2fe78bSCy Schubert 
262*7f2fe78bSCy Schubert static void
cpw_test_fail(char * user,krb5_principal princ,char * pass,krb5_error_code code)263*7f2fe78bSCy Schubert cpw_test_fail(char *user, krb5_principal princ, char *pass,
264*7f2fe78bSCy Schubert               krb5_error_code code)
265*7f2fe78bSCy Schubert {
266*7f2fe78bSCy Schubert     void *handle = get_handle(user);
267*7f2fe78bSCy Schubert 
268*7f2fe78bSCy Schubert     check_fail(kadm5_chpass_principal(handle, princ, pass), code);
269*7f2fe78bSCy Schubert     free_handle(handle);
270*7f2fe78bSCy Schubert }
271*7f2fe78bSCy Schubert 
272*7f2fe78bSCy Schubert static void
cpw_test_succeed(char * user,krb5_principal princ,char * pass)273*7f2fe78bSCy Schubert cpw_test_succeed(char *user, krb5_principal princ, char *pass)
274*7f2fe78bSCy Schubert {
275*7f2fe78bSCy Schubert     cpw_test_fail(user, princ, pass, 0);
276*7f2fe78bSCy Schubert }
277*7f2fe78bSCy Schubert 
278*7f2fe78bSCy Schubert static void
test_chpass()279*7f2fe78bSCy Schubert test_chpass()
280*7f2fe78bSCy Schubert {
281*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("chpass-test");
282*7f2fe78bSCy Schubert     krb5_principal hist_princ = parse_princ("kadmin/history");
283*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
284*7f2fe78bSCy Schubert     void *handle;
285*7f2fe78bSCy Schubert 
286*7f2fe78bSCy Schubert     /* Specify a policy so that kadmin/history is created. */
287*7f2fe78bSCy Schubert     create_simple_princ(princ, "minlife-pol");
288*7f2fe78bSCy Schubert 
289*7f2fe78bSCy Schubert     /* Check kvno and enctypes after a password change. */
290*7f2fe78bSCy Schubert     handle = get_handle("admin");
291*7f2fe78bSCy Schubert     check(kadm5_chpass_principal(handle, princ, "newpassword"));
292*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, princ, &ent, KADM5_KEY_DATA));
293*7f2fe78bSCy Schubert     compare_key_data(&ent, default_supported_enctypes);
294*7f2fe78bSCy Schubert     assert(ent.key_data[0].key_data_kvno == 2);
295*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &ent));
296*7f2fe78bSCy Schubert     free_handle(handle);
297*7f2fe78bSCy Schubert 
298*7f2fe78bSCy Schubert     /* Fails for protected principal. */
299*7f2fe78bSCy Schubert     cpw_test_fail("admin", hist_princ, "pw", KADM5_PROTECT_PRINCIPAL);
300*7f2fe78bSCy Schubert 
301*7f2fe78bSCy Schubert     /* Fails over RPC if "change" ACL is not granted, or if we authenticated to
302*7f2fe78bSCy Schubert      * kadmin/changepw and are changing another principal's password. */
303*7f2fe78bSCy Schubert     if (rpc) {
304*7f2fe78bSCy Schubert         cpw_test_succeed("admin/modify", princ, "pw2");
305*7f2fe78bSCy Schubert         cpw_test_fail("admin/none", princ, "pw3", KADM5_AUTH_CHANGEPW);
306*7f2fe78bSCy Schubert         cpw_test_fail("$admin", princ, "pw3", KADM5_AUTH_CHANGEPW);
307*7f2fe78bSCy Schubert     }
308*7f2fe78bSCy Schubert 
309*7f2fe78bSCy Schubert     /* Fails with null handle or principal name. */
310*7f2fe78bSCy Schubert     cpw_test_fail(NULL, princ, "pw", KADM5_BAD_SERVER_HANDLE);
311*7f2fe78bSCy Schubert     cpw_test_fail("admin", NULL, "pw", EINVAL);
312*7f2fe78bSCy Schubert 
313*7f2fe78bSCy Schubert     delete_princ(princ);
314*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
315*7f2fe78bSCy Schubert     krb5_free_principal(context, hist_princ);
316*7f2fe78bSCy Schubert }
317*7f2fe78bSCy Schubert 
318*7f2fe78bSCy Schubert static void
cpol_test_fail(char * user,kadm5_policy_ent_t ent,uint32_t mask,krb5_error_code code)319*7f2fe78bSCy Schubert cpol_test_fail(char *user, kadm5_policy_ent_t ent, uint32_t mask,
320*7f2fe78bSCy Schubert                krb5_error_code code)
321*7f2fe78bSCy Schubert {
322*7f2fe78bSCy Schubert     void *handle = get_handle(user);
323*7f2fe78bSCy Schubert 
324*7f2fe78bSCy Schubert     check_fail(kadm5_create_policy(handle, ent, mask | KADM5_POLICY), code);
325*7f2fe78bSCy Schubert     free_handle(handle);
326*7f2fe78bSCy Schubert }
327*7f2fe78bSCy Schubert 
328*7f2fe78bSCy Schubert static void
cpol_test_compare(char * user,kadm5_policy_ent_t ent,uint32_t mask)329*7f2fe78bSCy Schubert cpol_test_compare(char *user, kadm5_policy_ent_t ent, uint32_t mask)
330*7f2fe78bSCy Schubert {
331*7f2fe78bSCy Schubert     cpol_test_fail(user, ent, mask, 0);
332*7f2fe78bSCy Schubert     compare_policy(ent, mask);
333*7f2fe78bSCy Schubert     delete_policy(ent->policy);
334*7f2fe78bSCy Schubert }
335*7f2fe78bSCy Schubert 
336*7f2fe78bSCy Schubert static void
test_create_policy()337*7f2fe78bSCy Schubert test_create_policy()
338*7f2fe78bSCy Schubert {
339*7f2fe78bSCy Schubert     void *handle;
340*7f2fe78bSCy Schubert     kadm5_policy_ent_rec ent;
341*7f2fe78bSCy Schubert 
342*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
343*7f2fe78bSCy Schubert 
344*7f2fe78bSCy Schubert     /* Fails with undefined mask bit. */
345*7f2fe78bSCy Schubert     ent.policy = "create-policy-test";
346*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, 0x10000000, KADM5_BAD_MASK);
347*7f2fe78bSCy Schubert 
348*7f2fe78bSCy Schubert     /* Fails without KADM5_POLICY mask bit. */
349*7f2fe78bSCy Schubert     handle = get_handle("admin");
350*7f2fe78bSCy Schubert     check_fail(kadm5_create_policy(handle, &ent, 0), KADM5_BAD_MASK);
351*7f2fe78bSCy Schubert     free_handle(handle);
352*7f2fe78bSCy Schubert 
353*7f2fe78bSCy Schubert     /* pw_min_life = 0 and pw_min_life != 0 */
354*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);
355*7f2fe78bSCy Schubert     ent.pw_min_life = 32;
356*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);
357*7f2fe78bSCy Schubert 
358*7f2fe78bSCy Schubert     /* pw_max_life = 0 and pw_max_life != 0 */
359*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);
360*7f2fe78bSCy Schubert     ent.pw_max_life = 32;
361*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);
362*7f2fe78bSCy Schubert 
363*7f2fe78bSCy Schubert     /* pw_min_length = 0 (rejected) and pw_min_length != 0 */
364*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, KADM5_PW_MIN_LENGTH, KADM5_BAD_LENGTH);
365*7f2fe78bSCy Schubert     ent.pw_min_length = 32;
366*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_MIN_LENGTH);
367*7f2fe78bSCy Schubert 
368*7f2fe78bSCy Schubert     /* pw_min_classes = 0 (rejected), 1, 5, 6 (rejected) */
369*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);
370*7f2fe78bSCy Schubert     ent.pw_min_classes = 1;
371*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);
372*7f2fe78bSCy Schubert     ent.pw_min_classes = 5;
373*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);
374*7f2fe78bSCy Schubert     ent.pw_min_classes = 6;
375*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);
376*7f2fe78bSCy Schubert 
377*7f2fe78bSCy Schubert     /* pw_history_num = 0 (rejected), 1, 10 */
378*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, KADM5_PW_HISTORY_NUM, KADM5_BAD_HISTORY);
379*7f2fe78bSCy Schubert     ent.pw_history_num = 1;
380*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);
381*7f2fe78bSCy Schubert     ent.pw_history_num = 10;
382*7f2fe78bSCy Schubert     cpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);
383*7f2fe78bSCy Schubert 
384*7f2fe78bSCy Schubert     if (api >= KADM5_API_VERSION_3) {
385*7f2fe78bSCy Schubert         ent.pw_max_fail = 2;
386*7f2fe78bSCy Schubert         cpol_test_compare("admin", &ent, KADM5_PW_MAX_FAILURE);
387*7f2fe78bSCy Schubert         ent.pw_failcnt_interval = 90;
388*7f2fe78bSCy Schubert         cpol_test_compare("admin", &ent,
389*7f2fe78bSCy Schubert                           KADM5_PW_FAILURE_COUNT_INTERVAL);
390*7f2fe78bSCy Schubert         ent.pw_lockout_duration = 180;
391*7f2fe78bSCy Schubert         cpol_test_compare("admin", &ent, KADM5_PW_LOCKOUT_DURATION);
392*7f2fe78bSCy Schubert     }
393*7f2fe78bSCy Schubert 
394*7f2fe78bSCy Schubert     /* Fails over RPC if "add" ACL is not granted, or if we authenticated to
395*7f2fe78bSCy Schubert      * kadmin/changepw. */
396*7f2fe78bSCy Schubert     if (rpc) {
397*7f2fe78bSCy Schubert         cpol_test_fail("$admin", &ent, 0, KADM5_AUTH_ADD);
398*7f2fe78bSCy Schubert         cpol_test_fail("admin/none", &ent, 0, KADM5_AUTH_ADD);
399*7f2fe78bSCy Schubert         cpol_test_fail("admin/get", &ent, 0, KADM5_AUTH_ADD);
400*7f2fe78bSCy Schubert         cpol_test_fail("admin/modify", &ent, 0, KADM5_AUTH_ADD);
401*7f2fe78bSCy Schubert         cpol_test_fail("admin/delete", &ent, 0, KADM5_AUTH_ADD);
402*7f2fe78bSCy Schubert         cpol_test_compare("admin/add", &ent, 0);
403*7f2fe78bSCy Schubert     }
404*7f2fe78bSCy Schubert 
405*7f2fe78bSCy Schubert     /* Fails with existing policy name. */
406*7f2fe78bSCy Schubert     ent.policy = "test-pol";
407*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, 0, KADM5_DUP);
408*7f2fe78bSCy Schubert 
409*7f2fe78bSCy Schubert     /* Fails with null or empty policy name, or invalid character in name. */
410*7f2fe78bSCy Schubert     ent.policy = NULL;
411*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, 0, EINVAL);
412*7f2fe78bSCy Schubert     ent.policy = "";
413*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, 0, KADM5_BAD_POLICY);
414*7f2fe78bSCy Schubert     ent.policy = "pol\7";
415*7f2fe78bSCy Schubert     cpol_test_fail("admin", &ent, 0, KADM5_BAD_POLICY);
416*7f2fe78bSCy Schubert 
417*7f2fe78bSCy Schubert     /* Fails with null handle or policy ent. */
418*7f2fe78bSCy Schubert     cpol_test_fail(NULL, &ent, 0, KADM5_BAD_SERVER_HANDLE);
419*7f2fe78bSCy Schubert     cpol_test_fail("admin", NULL, 0, EINVAL);
420*7f2fe78bSCy Schubert }
421*7f2fe78bSCy Schubert 
422*7f2fe78bSCy Schubert static void
cprinc_test_fail(char * user,kadm5_principal_ent_t ent,uint32_t mask,char * pass,krb5_error_code code)423*7f2fe78bSCy Schubert cprinc_test_fail(char *user, kadm5_principal_ent_t ent, uint32_t mask,
424*7f2fe78bSCy Schubert                  char *pass, krb5_error_code code)
425*7f2fe78bSCy Schubert {
426*7f2fe78bSCy Schubert     void *handle = get_handle(user);
427*7f2fe78bSCy Schubert 
428*7f2fe78bSCy Schubert     check_fail(kadm5_create_principal(handle, ent, mask | KADM5_PRINCIPAL,
429*7f2fe78bSCy Schubert                                       pass), code);
430*7f2fe78bSCy Schubert     free_handle(handle);
431*7f2fe78bSCy Schubert }
432*7f2fe78bSCy Schubert 
433*7f2fe78bSCy Schubert static void
cprinc_test_compare(char * user,kadm5_principal_ent_t ent,uint32_t mask,char * pass)434*7f2fe78bSCy Schubert cprinc_test_compare(char *user, kadm5_principal_ent_t ent, uint32_t mask,
435*7f2fe78bSCy Schubert                     char *pass)
436*7f2fe78bSCy Schubert {
437*7f2fe78bSCy Schubert     cprinc_test_fail(user, ent, mask, pass, 0);
438*7f2fe78bSCy Schubert     compare_princ(ent, mask);
439*7f2fe78bSCy Schubert     delete_princ(ent->principal);
440*7f2fe78bSCy Schubert }
441*7f2fe78bSCy Schubert 
442*7f2fe78bSCy Schubert static void
test_create_principal()443*7f2fe78bSCy Schubert test_create_principal()
444*7f2fe78bSCy Schubert {
445*7f2fe78bSCy Schubert     void *handle;
446*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
447*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("create-principal-test");
448*7f2fe78bSCy Schubert     krb5_principal user_princ = parse_princ("user");
449*7f2fe78bSCy Schubert 
450*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
451*7f2fe78bSCy Schubert     ent.principal = princ;
452*7f2fe78bSCy Schubert 
453*7f2fe78bSCy Schubert     /* Fails with undefined or prohibited mask bit. */
454*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, 0x100000, "", KADM5_BAD_MASK);
455*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, "pw",
456*7f2fe78bSCy Schubert                      KADM5_BAD_MASK);
457*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_MOD_TIME, "pw", KADM5_BAD_MASK);
458*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_MOD_NAME, "pw", KADM5_BAD_MASK);
459*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_MKVNO, "pw", KADM5_BAD_MASK);
460*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, "pw",
461*7f2fe78bSCy Schubert                      KADM5_BAD_MASK);
462*7f2fe78bSCy Schubert 
463*7f2fe78bSCy Schubert     /* Fails without KADM5_PRINCIPAL mask bit. */
464*7f2fe78bSCy Schubert     handle = get_handle("admin");
465*7f2fe78bSCy Schubert     check_fail(kadm5_create_principal(handle, &ent, 0, "pw"), KADM5_BAD_MASK);
466*7f2fe78bSCy Schubert     free_handle(handle);
467*7f2fe78bSCy Schubert 
468*7f2fe78bSCy Schubert     /* Fails with empty password or password prohibited by policy. */
469*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, 0, "", KADM5_PASS_Q_TOOSHORT);
470*7f2fe78bSCy Schubert     ent.policy = "test-pol";
471*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_POLICY, "tP", KADM5_PASS_Q_TOOSHORT);
472*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_POLICY, "testpassword",
473*7f2fe78bSCy Schubert                      KADM5_PASS_Q_CLASS);
474*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, KADM5_POLICY, "Abyssinia",
475*7f2fe78bSCy Schubert                      KADM5_PASS_Q_DICT);
476*7f2fe78bSCy Schubert 
477*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, 0, "pw");
478*7f2fe78bSCy Schubert     ent.policy = "nonexistent-pol";
479*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_POLICY, "pw");
480*7f2fe78bSCy Schubert     cprinc_test_compare("admin/rename", &ent, KADM5_POLICY, "pw");
481*7f2fe78bSCy Schubert 
482*7f2fe78bSCy Schubert     /* Test pw_expiration explicit specifications vs. policy pw_max_life. */
483*7f2fe78bSCy Schubert     ent.policy = "test-pol";
484*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_POLICY, "NotinTheDictionary");
485*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME, "pw");
486*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw");
487*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,
488*7f2fe78bSCy Schubert                         "NotinTheDictionary");
489*7f2fe78bSCy Schubert     ent.pw_expiration = 1234;
490*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw");
491*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,
492*7f2fe78bSCy Schubert                         "NotinTheDictionary");
493*7f2fe78bSCy Schubert     ent.pw_expiration = 999999999;
494*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,
495*7f2fe78bSCy Schubert                         "NotinTheDictionary");
496*7f2fe78bSCy Schubert     ent.policy = "dict-only-pol";
497*7f2fe78bSCy Schubert     cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION,
498*7f2fe78bSCy Schubert                         "pw");
499*7f2fe78bSCy Schubert 
500*7f2fe78bSCy Schubert     /* Fails over RPC if "add" ACL is not granted, or if we authenticated to
501*7f2fe78bSCy Schubert      * kadmin/changepw. */
502*7f2fe78bSCy Schubert     if (rpc) {
503*7f2fe78bSCy Schubert         cprinc_test_fail("$admin", &ent, 0, "pw", KADM5_AUTH_ADD);
504*7f2fe78bSCy Schubert         cprinc_test_fail("admin/none", &ent, 0, "pw", KADM5_AUTH_ADD);
505*7f2fe78bSCy Schubert         cprinc_test_fail("admin/get", &ent, 0, "pw", KADM5_AUTH_ADD);
506*7f2fe78bSCy Schubert         cprinc_test_fail("admin/modify", &ent, 0, "pw", KADM5_AUTH_ADD);
507*7f2fe78bSCy Schubert         cprinc_test_fail("admin/delete", &ent, 0, "pw", KADM5_AUTH_ADD);
508*7f2fe78bSCy Schubert     }
509*7f2fe78bSCy Schubert 
510*7f2fe78bSCy Schubert     /* Fails with existing policy name. */
511*7f2fe78bSCy Schubert     ent.principal = user_princ;
512*7f2fe78bSCy Schubert     cprinc_test_fail("admin", &ent, 0, "pw", KADM5_DUP);
513*7f2fe78bSCy Schubert 
514*7f2fe78bSCy Schubert     /* Fails with null handle or principal ent. */
515*7f2fe78bSCy Schubert     cprinc_test_fail(NULL, &ent, 0, "pw", KADM5_BAD_SERVER_HANDLE);
516*7f2fe78bSCy Schubert     cprinc_test_fail("admin", NULL, 0, "pw", EINVAL);
517*7f2fe78bSCy Schubert 
518*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
519*7f2fe78bSCy Schubert     krb5_free_principal(context, user_princ);
520*7f2fe78bSCy Schubert }
521*7f2fe78bSCy Schubert 
522*7f2fe78bSCy Schubert static void
dpol_test_fail(char * user,char * name,krb5_error_code code)523*7f2fe78bSCy Schubert dpol_test_fail(char *user, char *name, krb5_error_code code)
524*7f2fe78bSCy Schubert {
525*7f2fe78bSCy Schubert     void *handle = get_handle(user);
526*7f2fe78bSCy Schubert 
527*7f2fe78bSCy Schubert     check_fail(kadm5_delete_policy(handle, name), code);
528*7f2fe78bSCy Schubert     free_handle(handle);
529*7f2fe78bSCy Schubert }
530*7f2fe78bSCy Schubert 
531*7f2fe78bSCy Schubert static void
dpol_test_succeed(char * user,char * name)532*7f2fe78bSCy Schubert dpol_test_succeed(char *user, char *name)
533*7f2fe78bSCy Schubert {
534*7f2fe78bSCy Schubert     dpol_test_fail(user, name, 0);
535*7f2fe78bSCy Schubert }
536*7f2fe78bSCy Schubert 
537*7f2fe78bSCy Schubert static void
test_delete_policy()538*7f2fe78bSCy Schubert test_delete_policy()
539*7f2fe78bSCy Schubert {
540*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("delete-policy-test-princ");
541*7f2fe78bSCy Schubert 
542*7f2fe78bSCy Schubert     /* Fails with unknown policy. */
543*7f2fe78bSCy Schubert     dpol_test_fail("admin", "delete-policy-test", KADM5_UNK_POLICY);
544*7f2fe78bSCy Schubert 
545*7f2fe78bSCy Schubert     /* Fails with empty policy name. */
546*7f2fe78bSCy Schubert     dpol_test_fail("admin", "", KADM5_BAD_POLICY);
547*7f2fe78bSCy Schubert 
548*7f2fe78bSCy Schubert     /* Succeeds with "delete" ACL (or local authentication). */
549*7f2fe78bSCy Schubert     create_simple_policy("delete-policy-test");
550*7f2fe78bSCy Schubert     dpol_test_succeed("admin/delete", "delete-policy-test");
551*7f2fe78bSCy Schubert 
552*7f2fe78bSCy Schubert     /* Succeeds even if a principal references the policy, since we now allow
553*7f2fe78bSCy Schubert      * principals to reference nonexistent policies. */
554*7f2fe78bSCy Schubert     create_simple_policy("delete-policy-test");
555*7f2fe78bSCy Schubert     create_simple_princ(princ, "delete-policy-test");
556*7f2fe78bSCy Schubert     dpol_test_succeed("admin", "delete-policy-test");
557*7f2fe78bSCy Schubert     delete_princ(princ);
558*7f2fe78bSCy Schubert 
559*7f2fe78bSCy Schubert     /* Fails over RPC if "delete" ACL is not granted, or if we authenticated to
560*7f2fe78bSCy Schubert      * kadmin/changepw. */
561*7f2fe78bSCy Schubert     if (rpc) {
562*7f2fe78bSCy Schubert         dpol_test_fail("$admin", "test-pol", KADM5_AUTH_DELETE);
563*7f2fe78bSCy Schubert         dpol_test_fail("admin/none", "test-pol", KADM5_AUTH_DELETE);
564*7f2fe78bSCy Schubert         dpol_test_fail("admin/add", "test-pol", KADM5_AUTH_DELETE);
565*7f2fe78bSCy Schubert     }
566*7f2fe78bSCy Schubert 
567*7f2fe78bSCy Schubert     /* Fails with null handle or principal ent. */
568*7f2fe78bSCy Schubert     dpol_test_fail(NULL, "test-pol", KADM5_BAD_SERVER_HANDLE);
569*7f2fe78bSCy Schubert     dpol_test_fail("admin", NULL, EINVAL);
570*7f2fe78bSCy Schubert 
571*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
572*7f2fe78bSCy Schubert }
573*7f2fe78bSCy Schubert 
574*7f2fe78bSCy Schubert static void
dprinc_test_fail(char * user,krb5_principal princ,krb5_error_code code)575*7f2fe78bSCy Schubert dprinc_test_fail(char *user, krb5_principal princ, krb5_error_code code)
576*7f2fe78bSCy Schubert {
577*7f2fe78bSCy Schubert     void *handle = get_handle(user);
578*7f2fe78bSCy Schubert 
579*7f2fe78bSCy Schubert     check_fail(kadm5_delete_principal(handle, princ), code);
580*7f2fe78bSCy Schubert     free_handle(handle);
581*7f2fe78bSCy Schubert }
582*7f2fe78bSCy Schubert 
583*7f2fe78bSCy Schubert static void
dprinc_test_succeed(char * user,krb5_principal princ)584*7f2fe78bSCy Schubert dprinc_test_succeed(char *user, krb5_principal princ)
585*7f2fe78bSCy Schubert {
586*7f2fe78bSCy Schubert     dprinc_test_fail(user, princ, 0);
587*7f2fe78bSCy Schubert }
588*7f2fe78bSCy Schubert 
589*7f2fe78bSCy Schubert static void
test_delete_principal()590*7f2fe78bSCy Schubert test_delete_principal()
591*7f2fe78bSCy Schubert {
592*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("delete-principal-test");
593*7f2fe78bSCy Schubert 
594*7f2fe78bSCy Schubert     /* Fails with unknown principal. */
595*7f2fe78bSCy Schubert     dprinc_test_fail("admin", princ, KADM5_UNK_PRINC);
596*7f2fe78bSCy Schubert 
597*7f2fe78bSCy Schubert     /* Succeeds with "delete" ACL (or local authentication). */
598*7f2fe78bSCy Schubert     create_simple_princ(princ, NULL);
599*7f2fe78bSCy Schubert     dprinc_test_succeed("admin/delete", princ);
600*7f2fe78bSCy Schubert 
601*7f2fe78bSCy Schubert     /* Fails over RPC if "delete" ACL is not granted, or if we authenticated to
602*7f2fe78bSCy Schubert      * kadmin/changepw. */
603*7f2fe78bSCy Schubert     if (rpc) {
604*7f2fe78bSCy Schubert         dprinc_test_fail("$admin", princ, KADM5_AUTH_DELETE);
605*7f2fe78bSCy Schubert         dprinc_test_fail("admin/add", princ, KADM5_AUTH_DELETE);
606*7f2fe78bSCy Schubert         dprinc_test_fail("admin/modify", princ, KADM5_AUTH_DELETE);
607*7f2fe78bSCy Schubert         dprinc_test_fail("admin/get", princ, KADM5_AUTH_DELETE);
608*7f2fe78bSCy Schubert         dprinc_test_fail("admin/none", princ, KADM5_AUTH_DELETE);
609*7f2fe78bSCy Schubert     }
610*7f2fe78bSCy Schubert 
611*7f2fe78bSCy Schubert     /* Fails with null handle or principal ent. */
612*7f2fe78bSCy Schubert     dprinc_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE);
613*7f2fe78bSCy Schubert     dprinc_test_fail("admin", NULL, EINVAL);
614*7f2fe78bSCy Schubert 
615*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
616*7f2fe78bSCy Schubert }
617*7f2fe78bSCy Schubert 
618*7f2fe78bSCy Schubert static void
gpol_test_succeed(char * user,char * name)619*7f2fe78bSCy Schubert gpol_test_succeed(char *user, char *name)
620*7f2fe78bSCy Schubert {
621*7f2fe78bSCy Schubert     void *handle = get_handle(user);
622*7f2fe78bSCy Schubert     kadm5_policy_ent_rec ent;
623*7f2fe78bSCy Schubert 
624*7f2fe78bSCy Schubert     check(kadm5_get_policy(handle, name, &ent));
625*7f2fe78bSCy Schubert     assert(strcmp(ent.policy, name) == 0);
626*7f2fe78bSCy Schubert     check(kadm5_free_policy_ent(handle, &ent));
627*7f2fe78bSCy Schubert     free_handle(handle);
628*7f2fe78bSCy Schubert }
629*7f2fe78bSCy Schubert 
630*7f2fe78bSCy Schubert static void
gpol_test_fail(char * user,char * name,krb5_error_code code)631*7f2fe78bSCy Schubert gpol_test_fail(char *user, char *name, krb5_error_code code)
632*7f2fe78bSCy Schubert {
633*7f2fe78bSCy Schubert     void *handle = get_handle(user);
634*7f2fe78bSCy Schubert     kadm5_policy_ent_rec ent;
635*7f2fe78bSCy Schubert 
636*7f2fe78bSCy Schubert     check_fail(kadm5_get_policy(handle, name, &ent), code);
637*7f2fe78bSCy Schubert     free_handle(handle);
638*7f2fe78bSCy Schubert }
639*7f2fe78bSCy Schubert 
640*7f2fe78bSCy Schubert static void
test_get_policy()641*7f2fe78bSCy Schubert test_get_policy()
642*7f2fe78bSCy Schubert {
643*7f2fe78bSCy Schubert     /* Fails with unknown policy. */
644*7f2fe78bSCy Schubert     dpol_test_fail("admin", "unknown-policy", KADM5_UNK_POLICY);
645*7f2fe78bSCy Schubert 
646*7f2fe78bSCy Schubert     /* Fails with empty or null policy name or a null handle. */
647*7f2fe78bSCy Schubert     gpol_test_fail("admin", "", KADM5_BAD_POLICY);
648*7f2fe78bSCy Schubert     gpol_test_fail("admin", NULL, EINVAL);
649*7f2fe78bSCy Schubert     gpol_test_fail(NULL, "", KADM5_BAD_SERVER_HANDLE);
650*7f2fe78bSCy Schubert 
651*7f2fe78bSCy Schubert     /* Fails over RPC unless "get" ACL is granted or the principal's own policy
652*7f2fe78bSCy Schubert      * is retrieved. */
653*7f2fe78bSCy Schubert     if (rpc) {
654*7f2fe78bSCy Schubert         gpol_test_fail("admin/none", "test-pol", KADM5_AUTH_GET);
655*7f2fe78bSCy Schubert         gpol_test_fail("admin/add", "test-pol", KADM5_AUTH_GET);
656*7f2fe78bSCy Schubert         gpol_test_succeed("admin/get", "test-pol");
657*7f2fe78bSCy Schubert         gpol_test_succeed("user", "minlife-pol");
658*7f2fe78bSCy Schubert         gpol_test_succeed("$user", "minlife-pol");
659*7f2fe78bSCy Schubert     }
660*7f2fe78bSCy Schubert }
661*7f2fe78bSCy Schubert 
662*7f2fe78bSCy Schubert static void
gprinc_test_succeed(char * user,krb5_principal princ)663*7f2fe78bSCy Schubert gprinc_test_succeed(char *user, krb5_principal princ)
664*7f2fe78bSCy Schubert {
665*7f2fe78bSCy Schubert     void *handle = get_handle(user);
666*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
667*7f2fe78bSCy Schubert 
668*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, princ, &ent,
669*7f2fe78bSCy Schubert                               KADM5_PRINCIPAL_NORMAL_MASK));
670*7f2fe78bSCy Schubert     assert(krb5_principal_compare(context, ent.principal, princ));
671*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &ent));
672*7f2fe78bSCy Schubert     free_handle(handle);
673*7f2fe78bSCy Schubert }
674*7f2fe78bSCy Schubert 
675*7f2fe78bSCy Schubert static void
gprinc_test_fail(char * user,krb5_principal princ,krb5_error_code code)676*7f2fe78bSCy Schubert gprinc_test_fail(char *user, krb5_principal princ, krb5_error_code code)
677*7f2fe78bSCy Schubert {
678*7f2fe78bSCy Schubert     void *handle = get_handle(user);
679*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
680*7f2fe78bSCy Schubert 
681*7f2fe78bSCy Schubert     check_fail(kadm5_get_principal(handle, princ, &ent,
682*7f2fe78bSCy Schubert                                    KADM5_PRINCIPAL_NORMAL_MASK), code);
683*7f2fe78bSCy Schubert     free_handle(handle);
684*7f2fe78bSCy Schubert }
685*7f2fe78bSCy Schubert 
686*7f2fe78bSCy Schubert static void
test_get_principal()687*7f2fe78bSCy Schubert test_get_principal()
688*7f2fe78bSCy Schubert {
689*7f2fe78bSCy Schubert     void *handle;
690*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
691*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("get-principal-test");
692*7f2fe78bSCy Schubert     krb5_principal admin_princ = parse_princ("admin");
693*7f2fe78bSCy Schubert     krb5_principal admin_none_princ = parse_princ("admin/none");
694*7f2fe78bSCy Schubert     int i;
695*7f2fe78bSCy Schubert 
696*7f2fe78bSCy Schubert     /* Fails with unknown principal. */
697*7f2fe78bSCy Schubert     gprinc_test_fail("admin", princ, KADM5_UNK_PRINC);
698*7f2fe78bSCy Schubert 
699*7f2fe78bSCy Schubert     create_simple_princ(princ, NULL);
700*7f2fe78bSCy Schubert 
701*7f2fe78bSCy Schubert     /* Succeeds with "get" ACL (or local authentication), or operating on
702*7f2fe78bSCy Schubert      * self. */
703*7f2fe78bSCy Schubert     gprinc_test_succeed("admin/none", admin_none_princ);
704*7f2fe78bSCy Schubert     gprinc_test_succeed("$admin", admin_princ);
705*7f2fe78bSCy Schubert     gprinc_test_succeed("admin/get", princ);
706*7f2fe78bSCy Schubert 
707*7f2fe78bSCy Schubert     /* Fails over RPC if "get" ACL is not granted, or if we authenticated to
708*7f2fe78bSCy Schubert      * kadmin/changepw and getting another principal entry. */
709*7f2fe78bSCy Schubert     if (rpc) {
710*7f2fe78bSCy Schubert         gprinc_test_fail("$admin", princ, KADM5_AUTH_GET);
711*7f2fe78bSCy Schubert         gprinc_test_fail("admin/none", princ, KADM5_AUTH_GET);
712*7f2fe78bSCy Schubert         gprinc_test_fail("admin/add", princ, KADM5_AUTH_GET);
713*7f2fe78bSCy Schubert         gprinc_test_fail("admin/modify", princ, KADM5_AUTH_GET);
714*7f2fe78bSCy Schubert         gprinc_test_fail("admin/delete", princ, KADM5_AUTH_GET);
715*7f2fe78bSCy Schubert     }
716*7f2fe78bSCy Schubert 
717*7f2fe78bSCy Schubert     /* Entry contains no key data or tl-data unless asked for. */
718*7f2fe78bSCy Schubert     handle = get_handle("admin");
719*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, princ, &ent,
720*7f2fe78bSCy Schubert                               KADM5_PRINCIPAL_NORMAL_MASK));
721*7f2fe78bSCy Schubert     assert(ent.n_tl_data == 0);
722*7f2fe78bSCy Schubert     assert(ent.n_key_data == 0);
723*7f2fe78bSCy Schubert     assert(ent.tl_data == NULL);
724*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &ent));
725*7f2fe78bSCy Schubert 
726*7f2fe78bSCy Schubert     /* Key data (without the actual keys over RPC) is provided if asked for. */
727*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, princ, &ent,
728*7f2fe78bSCy Schubert                               KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA));
729*7f2fe78bSCy Schubert     assert(ent.n_key_data == 2);
730*7f2fe78bSCy Schubert     for (i = 0; i < ent.n_key_data; i++)
731*7f2fe78bSCy Schubert         assert(rpc == (ent.key_data[i].key_data_length[0] == 0));
732*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &ent));
733*7f2fe78bSCy Schubert     free_handle(handle);
734*7f2fe78bSCy Schubert 
735*7f2fe78bSCy Schubert     /* Fails with null handle or principal. */
736*7f2fe78bSCy Schubert     gprinc_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE);
737*7f2fe78bSCy Schubert     gprinc_test_fail("admin", NULL, EINVAL);
738*7f2fe78bSCy Schubert 
739*7f2fe78bSCy Schubert     delete_princ(princ);
740*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
741*7f2fe78bSCy Schubert     krb5_free_principal(context, admin_princ);
742*7f2fe78bSCy Schubert     krb5_free_principal(context, admin_none_princ);
743*7f2fe78bSCy Schubert }
744*7f2fe78bSCy Schubert 
745*7f2fe78bSCy Schubert static void
test_init_destroy()746*7f2fe78bSCy Schubert test_init_destroy()
747*7f2fe78bSCy Schubert {
748*7f2fe78bSCy Schubert     krb5_context ctx;
749*7f2fe78bSCy Schubert     kadm5_ret_t ret;
750*7f2fe78bSCy Schubert     kadm5_config_params params;
751*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent, gent;
752*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("init-test");
753*7f2fe78bSCy Schubert     krb5_ccache cc;
754*7f2fe78bSCy Schubert     void *handle;
755*7f2fe78bSCy Schubert     char hostname[MAXHOSTNAMELEN];
756*7f2fe78bSCy Schubert     int r;
757*7f2fe78bSCy Schubert 
758*7f2fe78bSCy Schubert     memset(&params, 0, sizeof(params));
759*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
760*7f2fe78bSCy Schubert     ent.principal = princ;
761*7f2fe78bSCy Schubert 
762*7f2fe78bSCy Schubert     r = gethostname(hostname, sizeof(hostname));
763*7f2fe78bSCy Schubert     assert(r == 0);
764*7f2fe78bSCy Schubert 
765*7f2fe78bSCy Schubert     /* Destroy fails with no server handle. */
766*7f2fe78bSCy Schubert     check_fail(kadm5_destroy(NULL), KADM5_BAD_SERVER_HANDLE);
767*7f2fe78bSCy Schubert 
768*7f2fe78bSCy Schubert     /* Fails with bad structure version mask. */
769*7f2fe78bSCy Schubert     check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
770*7f2fe78bSCy Schubert                           0x65432101, api, NULL, &handle),
771*7f2fe78bSCy Schubert                KADM5_BAD_STRUCT_VERSION);
772*7f2fe78bSCy Schubert     check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
773*7f2fe78bSCy Schubert                           1, api, NULL, &handle), KADM5_BAD_STRUCT_VERSION);
774*7f2fe78bSCy Schubert 
775*7f2fe78bSCy Schubert     /* Fails with too-old or too-new structure version. */
776*7f2fe78bSCy Schubert     check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
777*7f2fe78bSCy Schubert                           KADM5_STRUCT_VERSION_MASK, api, NULL, &handle),
778*7f2fe78bSCy Schubert                KADM5_OLD_STRUCT_VERSION);
779*7f2fe78bSCy Schubert     check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
780*7f2fe78bSCy Schubert                           KADM5_STRUCT_VERSION_MASK | 0xca, api, NULL,
781*7f2fe78bSCy Schubert                           &handle), KADM5_NEW_STRUCT_VERSION);
782*7f2fe78bSCy Schubert 
783*7f2fe78bSCy Schubert     /* Fails with bad API version mask. */
784*7f2fe78bSCy Schubert     check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
785*7f2fe78bSCy Schubert                           KADM5_STRUCT_VERSION, 0x65432100, NULL, &handle),
786*7f2fe78bSCy Schubert                KADM5_BAD_API_VERSION);
787*7f2fe78bSCy Schubert     check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
788*7f2fe78bSCy Schubert                           KADM5_STRUCT_VERSION, 4, NULL, &handle),
789*7f2fe78bSCy Schubert                KADM5_BAD_API_VERSION);
790*7f2fe78bSCy Schubert 
791*7f2fe78bSCy Schubert     /* Fails with too-old or too-new API version.*/
792*7f2fe78bSCy Schubert     ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
793*7f2fe78bSCy Schubert                      KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK, NULL,
794*7f2fe78bSCy Schubert                      &handle);
795*7f2fe78bSCy Schubert     assert(ret == (rpc ? KADM5_OLD_LIB_API_VERSION :
796*7f2fe78bSCy Schubert                    KADM5_OLD_SERVER_API_VERSION));
797*7f2fe78bSCy Schubert     ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
798*7f2fe78bSCy Schubert                      KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK | 0xca, NULL,
799*7f2fe78bSCy Schubert                      &handle);
800*7f2fe78bSCy Schubert     assert(ret == (rpc ? KADM5_NEW_LIB_API_VERSION :
801*7f2fe78bSCy Schubert                    KADM5_NEW_SERVER_API_VERSION));
802*7f2fe78bSCy Schubert 
803*7f2fe78bSCy Schubert     /* Fails with structure and API version reversed. */
804*7f2fe78bSCy Schubert     check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
805*7f2fe78bSCy Schubert                           api, KADM5_STRUCT_VERSION, NULL, &handle),
806*7f2fe78bSCy Schubert                KADM5_BAD_STRUCT_VERSION);
807*7f2fe78bSCy Schubert 
808*7f2fe78bSCy Schubert     /* Hardcoded default max lifetime is used when no handle or krb5.conf
809*7f2fe78bSCy Schubert      * setting is given. */
810*7f2fe78bSCy Schubert     handle = get_handle("admin");
811*7f2fe78bSCy Schubert     check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw"));
812*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, princ, &gent,
813*7f2fe78bSCy Schubert                               KADM5_PRINCIPAL_NORMAL_MASK));
814*7f2fe78bSCy Schubert     assert(gent.max_life == KRB5_KDB_MAX_LIFE);
815*7f2fe78bSCy Schubert     check(kadm5_delete_principal(handle, princ));
816*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &gent));
817*7f2fe78bSCy Schubert     free_handle(handle);
818*7f2fe78bSCy Schubert 
819*7f2fe78bSCy Schubert     /* Fails with configured unknown realm.  Do these tests in separate krb5
820*7f2fe78bSCy Schubert      * contexts since the realm setting sticks to the context. */
821*7f2fe78bSCy Schubert     check(kadm5_init_krb5_context(&ctx));
822*7f2fe78bSCy Schubert     params.realm = "";
823*7f2fe78bSCy Schubert     params.mask = KADM5_CONFIG_REALM;
824*7f2fe78bSCy Schubert     ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, &params,
825*7f2fe78bSCy Schubert                      KADM5_STRUCT_VERSION, api, NULL, &handle);
826*7f2fe78bSCy Schubert     assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT));
827*7f2fe78bSCy Schubert     krb5_free_context(ctx);
828*7f2fe78bSCy Schubert 
829*7f2fe78bSCy Schubert     check(kadm5_init_krb5_context(&ctx));
830*7f2fe78bSCy Schubert     params.realm = "@";
831*7f2fe78bSCy Schubert     ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, &params,
832*7f2fe78bSCy Schubert                      KADM5_STRUCT_VERSION, api, NULL, &handle);
833*7f2fe78bSCy Schubert     assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT));
834*7f2fe78bSCy Schubert     krb5_free_context(ctx);
835*7f2fe78bSCy Schubert 
836*7f2fe78bSCy Schubert     check(kadm5_init_krb5_context(&ctx));
837*7f2fe78bSCy Schubert     params.realm = "BAD.REALM";
838*7f2fe78bSCy Schubert     ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, &params,
839*7f2fe78bSCy Schubert                      KADM5_STRUCT_VERSION, api, NULL, &handle);
840*7f2fe78bSCy Schubert     assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT));
841*7f2fe78bSCy Schubert     krb5_free_context(ctx);
842*7f2fe78bSCy Schubert 
843*7f2fe78bSCy Schubert     /* Succeeds with explicit client realm and configured realm. */
844*7f2fe78bSCy Schubert     check(kadm5_init_krb5_context(&ctx));
845*7f2fe78bSCy Schubert     params.realm = "KRBTEST.COM";
846*7f2fe78bSCy Schubert     check(kadm5_init(ctx, "admin@KRBTEST.COM", "admin", KADM5_ADMIN_SERVICE,
847*7f2fe78bSCy Schubert                      &params, KADM5_STRUCT_VERSION, api, NULL, &handle));
848*7f2fe78bSCy Schubert     check(kadm5_destroy(handle));
849*7f2fe78bSCy Schubert     krb5_free_context(ctx);
850*7f2fe78bSCy Schubert 
851*7f2fe78bSCy Schubert     /* Succeeds with explicit client realm. */
852*7f2fe78bSCy Schubert     check(kadm5_init(context, "admin@KRBTEST.COM", "admin",
853*7f2fe78bSCy Schubert                      KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, api,
854*7f2fe78bSCy Schubert                      NULL, &handle));
855*7f2fe78bSCy Schubert     check(kadm5_destroy(handle));
856*7f2fe78bSCy Schubert 
857*7f2fe78bSCy Schubert 
858*7f2fe78bSCy Schubert     if (rpc) {
859*7f2fe78bSCy Schubert         check(krb5_cc_default(context, &cc));
860*7f2fe78bSCy Schubert 
861*7f2fe78bSCy Schubert         /* Succeeds with configured host and port. */
862*7f2fe78bSCy Schubert         params.admin_server = hostname;
863*7f2fe78bSCy Schubert         params.kadmind_port = 61001;
864*7f2fe78bSCy Schubert         params.mask = KADM5_CONFIG_ADMIN_SERVER | KADM5_CONFIG_KADMIND_PORT;
865*7f2fe78bSCy Schubert         check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,
866*7f2fe78bSCy Schubert                          &params, KADM5_STRUCT_VERSION, api, NULL, &handle));
867*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
868*7f2fe78bSCy Schubert 
869*7f2fe78bSCy Schubert         /* Fails with wrong configured port. */
870*7f2fe78bSCy Schubert         params.kadmind_port = 4;
871*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,
872*7f2fe78bSCy Schubert                               &params, KADM5_STRUCT_VERSION, api, NULL,
873*7f2fe78bSCy Schubert                               &handle), KADM5_RPC_ERROR);
874*7f2fe78bSCy Schubert 
875*7f2fe78bSCy Schubert         /* Fails with non-resolving hostname. */
876*7f2fe78bSCy Schubert         params.admin_server = "does.not.exist";
877*7f2fe78bSCy Schubert         params.mask = KADM5_CONFIG_ADMIN_SERVER;
878*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,
879*7f2fe78bSCy Schubert                               &params, KADM5_STRUCT_VERSION, api, NULL,
880*7f2fe78bSCy Schubert                               &handle), KADM5_CANT_RESOLVE);
881*7f2fe78bSCy Schubert 
882*7f2fe78bSCy Schubert         /* Fails with uninitialized cache. */
883*7f2fe78bSCy Schubert         check_fail(kadm5_init_with_creds(context, "admin", cc,
884*7f2fe78bSCy Schubert                                          KADM5_ADMIN_SERVICE, NULL,
885*7f2fe78bSCy Schubert                                          KADM5_STRUCT_VERSION, api, NULL,
886*7f2fe78bSCy Schubert                                          &handle), KRB5_FCC_NOFILE);
887*7f2fe78bSCy Schubert 
888*7f2fe78bSCy Schubert         /* Succeeds with cache containing kadmin/admin cred. */
889*7f2fe78bSCy Schubert         kinit(cc, "admin", "admin", KADM5_ADMIN_SERVICE);
890*7f2fe78bSCy Schubert         check(kadm5_init_with_creds(context, "admin", cc, KADM5_ADMIN_SERVICE,
891*7f2fe78bSCy Schubert                                     NULL, KADM5_STRUCT_VERSION, api, NULL,
892*7f2fe78bSCy Schubert                                     &handle));
893*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
894*7f2fe78bSCy Schubert 
895*7f2fe78bSCy Schubert         /* Succeeds with cache containing kadmin/changepw cred. */
896*7f2fe78bSCy Schubert         kinit(cc, "admin", "admin", KADM5_CHANGEPW_SERVICE);
897*7f2fe78bSCy Schubert         check(kadm5_init_with_creds(context, "admin", cc,
898*7f2fe78bSCy Schubert                                     KADM5_CHANGEPW_SERVICE, NULL,
899*7f2fe78bSCy Schubert                                     KADM5_STRUCT_VERSION, api, NULL, &handle));
900*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
901*7f2fe78bSCy Schubert 
902*7f2fe78bSCy Schubert         /* Fails with cache containing only a TGT. */
903*7f2fe78bSCy Schubert         kinit(cc, "admin", "admin", NULL);
904*7f2fe78bSCy Schubert         check_fail(kadm5_init_with_creds(context, "admin", cc,
905*7f2fe78bSCy Schubert                                          KADM5_ADMIN_SERVICE, NULL,
906*7f2fe78bSCy Schubert                                          KADM5_STRUCT_VERSION, api, NULL,
907*7f2fe78bSCy Schubert                                          &handle), KRB5_CC_NOTFOUND);
908*7f2fe78bSCy Schubert 
909*7f2fe78bSCy Schubert         /* Fails authenticating to non-kadmin princ. */
910*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin", "admin", "user", NULL,
911*7f2fe78bSCy Schubert                               KADM5_STRUCT_VERSION, api, NULL, &handle),
912*7f2fe78bSCy Schubert                    KADM5_RPC_ERROR);
913*7f2fe78bSCy Schubert 
914*7f2fe78bSCy Schubert         /* Fails authenticating to nonexistent princ. */
915*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin", "admin", "noexist", NULL,
916*7f2fe78bSCy Schubert                               KADM5_STRUCT_VERSION, api, NULL, &handle),
917*7f2fe78bSCy Schubert                    KADM5_SECURE_PRINC_MISSING);
918*7f2fe78bSCy Schubert 
919*7f2fe78bSCy Schubert         /* Fails authenticating to client princ (which is non-kadmin). */
920*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin", "admin", "admin", NULL,
921*7f2fe78bSCy Schubert                               KADM5_STRUCT_VERSION, api, NULL, &handle),
922*7f2fe78bSCy Schubert                    KADM5_RPC_ERROR);
923*7f2fe78bSCy Schubert 
924*7f2fe78bSCy Schubert         /* Fails with wrong password. */
925*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE,
926*7f2fe78bSCy Schubert                               NULL, KADM5_STRUCT_VERSION, api, NULL, &handle),
927*7f2fe78bSCy Schubert                    KADM5_BAD_PASSWORD);
928*7f2fe78bSCy Schubert 
929*7f2fe78bSCy Schubert         /* Fails with null client name. */
930*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, NULL, "admin", KADM5_ADMIN_SERVICE,
931*7f2fe78bSCy Schubert                               NULL, KADM5_STRUCT_VERSION, api, NULL, &handle),
932*7f2fe78bSCy Schubert                    EINVAL);
933*7f2fe78bSCy Schubert 
934*7f2fe78bSCy Schubert         /* Fails with nonexistent client name. */
935*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "noexist", "admin", KADM5_ADMIN_SERVICE,
936*7f2fe78bSCy Schubert                               NULL, KADM5_STRUCT_VERSION, api, NULL, &handle),
937*7f2fe78bSCy Schubert                    KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);
938*7f2fe78bSCy Schubert 
939*7f2fe78bSCy Schubert         /* Fails with nonexistent client name with explicit realm. */
940*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "noexist@KRBTEST.COM", "admin",
941*7f2fe78bSCy Schubert                               KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION,
942*7f2fe78bSCy Schubert                               api, NULL, &handle),
943*7f2fe78bSCy Schubert                    KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);
944*7f2fe78bSCy Schubert 
945*7f2fe78bSCy Schubert         /* Fails with nonexistent client name with unknown realm. */
946*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "noexist@BAD.REALM", "admin",
947*7f2fe78bSCy Schubert                               KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION,
948*7f2fe78bSCy Schubert                               api, NULL, &handle), KRB5_REALM_UNKNOWN);
949*7f2fe78bSCy Schubert 
950*7f2fe78bSCy Schubert         /* Fails with known name but unknown realm. */
951*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin@BAD.REALM", "admin",
952*7f2fe78bSCy Schubert                               KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION,
953*7f2fe78bSCy Schubert                               api, NULL, &handle), KRB5_REALM_UNKNOWN);
954*7f2fe78bSCy Schubert 
955*7f2fe78bSCy Schubert         check(krb5_cc_destroy(context, cc));
956*7f2fe78bSCy Schubert     } else {
957*7f2fe78bSCy Schubert         /* Fails with nonexistent stash file. */
958*7f2fe78bSCy Schubert         params.stash_file = "does/not/exist";
959*7f2fe78bSCy Schubert         params.mask = KADM5_CONFIG_STASH_FILE;
960*7f2fe78bSCy Schubert         check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,
961*7f2fe78bSCy Schubert                               &params, KADM5_STRUCT_VERSION, api, NULL,
962*7f2fe78bSCy Schubert                               &handle), KRB5_KDB_CANTREAD_STORED);
963*7f2fe78bSCy Schubert 
964*7f2fe78bSCy Schubert         /* Uses configured defaults for principal creation. */
965*7f2fe78bSCy Schubert         params.max_life = 10;
966*7f2fe78bSCy Schubert         params.max_rlife = 20;
967*7f2fe78bSCy Schubert         params.expiration = 30;
968*7f2fe78bSCy Schubert         params.num_keysalts = 0;
969*7f2fe78bSCy Schubert         params.mask = KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE |
970*7f2fe78bSCy Schubert             KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES;
971*7f2fe78bSCy Schubert         check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE,
972*7f2fe78bSCy Schubert                          &params, KADM5_STRUCT_VERSION, api, NULL, &handle));
973*7f2fe78bSCy Schubert         check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw"));
974*7f2fe78bSCy Schubert         check(kadm5_get_principal(handle, princ, &gent,
975*7f2fe78bSCy Schubert                                   KADM5_PRINCIPAL_NORMAL_MASK |
976*7f2fe78bSCy Schubert                                   KADM5_KEY_DATA));
977*7f2fe78bSCy Schubert         assert(gent.max_life == 10);
978*7f2fe78bSCy Schubert         assert(gent.max_renewable_life == 20);
979*7f2fe78bSCy Schubert         assert(gent.princ_expire_time == 30);
980*7f2fe78bSCy Schubert         assert(gent.n_key_data == 0);
981*7f2fe78bSCy Schubert         check(kadm5_delete_principal(handle, princ));
982*7f2fe78bSCy Schubert         check(kadm5_free_principal_ent(handle, &gent));
983*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
984*7f2fe78bSCy Schubert 
985*7f2fe78bSCy Schubert         /* Succeeds with incorrect password using local auth. */
986*7f2fe78bSCy Schubert         check(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE, NULL,
987*7f2fe78bSCy Schubert                          KADM5_STRUCT_VERSION, api, NULL, &handle));
988*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
989*7f2fe78bSCy Schubert 
990*7f2fe78bSCy Schubert         /* Succeeds with null service using local auth. */
991*7f2fe78bSCy Schubert         check(kadm5_init(context, "admin", "admin", NULL, NULL,
992*7f2fe78bSCy Schubert                          KADM5_STRUCT_VERSION, api, NULL, &handle));
993*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
994*7f2fe78bSCy Schubert 
995*7f2fe78bSCy Schubert         /* Succeeds with nonexistent, non-kadmin service using local auth. */
996*7f2fe78bSCy Schubert         check(kadm5_init(context, "admin", "admin", "foobar", NULL,
997*7f2fe78bSCy Schubert                          KADM5_STRUCT_VERSION, api, NULL, &handle));
998*7f2fe78bSCy Schubert         check(kadm5_destroy(handle));
999*7f2fe78bSCy Schubert     }
1000*7f2fe78bSCy Schubert 
1001*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1002*7f2fe78bSCy Schubert }
1003*7f2fe78bSCy Schubert 
1004*7f2fe78bSCy Schubert static void
mpol_test_fail(char * user,kadm5_policy_ent_t ent,uint32_t mask,krb5_error_code code)1005*7f2fe78bSCy Schubert mpol_test_fail(char *user, kadm5_policy_ent_t ent, uint32_t mask,
1006*7f2fe78bSCy Schubert                krb5_error_code code)
1007*7f2fe78bSCy Schubert {
1008*7f2fe78bSCy Schubert     void *handle = get_handle(user);
1009*7f2fe78bSCy Schubert 
1010*7f2fe78bSCy Schubert     check_fail(kadm5_modify_policy(handle, ent, mask), code);
1011*7f2fe78bSCy Schubert     free_handle(handle);
1012*7f2fe78bSCy Schubert }
1013*7f2fe78bSCy Schubert 
1014*7f2fe78bSCy Schubert static void
mpol_test_compare(void * handle,kadm5_policy_ent_t ent,uint32_t mask)1015*7f2fe78bSCy Schubert mpol_test_compare(void *handle, kadm5_policy_ent_t ent, uint32_t mask)
1016*7f2fe78bSCy Schubert {
1017*7f2fe78bSCy Schubert     mpol_test_fail(handle, ent, mask, 0);
1018*7f2fe78bSCy Schubert     compare_policy(ent, mask);
1019*7f2fe78bSCy Schubert }
1020*7f2fe78bSCy Schubert 
1021*7f2fe78bSCy Schubert static void
test_modify_policy()1022*7f2fe78bSCy Schubert test_modify_policy()
1023*7f2fe78bSCy Schubert {
1024*7f2fe78bSCy Schubert     kadm5_policy_ent_rec ent;
1025*7f2fe78bSCy Schubert 
1026*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
1027*7f2fe78bSCy Schubert     ent.policy = "modify-policy-test";
1028*7f2fe78bSCy Schubert     create_simple_policy(ent.policy);
1029*7f2fe78bSCy Schubert 
1030*7f2fe78bSCy Schubert     /* pw_min_life = 0 and pw_min_life != 0 */
1031*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);
1032*7f2fe78bSCy Schubert     ent.pw_min_life = 32;
1033*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE);
1034*7f2fe78bSCy Schubert 
1035*7f2fe78bSCy Schubert     /* pw_max_life = 0 and pw_max_life != 0 */
1036*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);
1037*7f2fe78bSCy Schubert     ent.pw_max_life = 32;
1038*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE);
1039*7f2fe78bSCy Schubert 
1040*7f2fe78bSCy Schubert     /* pw_min_length = 0 (rejected) and pw_min_length != 0 */
1041*7f2fe78bSCy Schubert     mpol_test_fail("admin", &ent, KADM5_PW_MIN_LENGTH, KADM5_BAD_LENGTH);
1042*7f2fe78bSCy Schubert     ent.pw_min_length = 8;
1043*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_MIN_LENGTH);
1044*7f2fe78bSCy Schubert 
1045*7f2fe78bSCy Schubert     /* pw_min_classes = 0 (rejected), 1, 5, 6 (rejected) */
1046*7f2fe78bSCy Schubert     mpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);
1047*7f2fe78bSCy Schubert     ent.pw_min_classes = 1;
1048*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);
1049*7f2fe78bSCy Schubert     ent.pw_min_classes = 5;
1050*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES);
1051*7f2fe78bSCy Schubert     ent.pw_min_classes = 6;
1052*7f2fe78bSCy Schubert     mpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS);
1053*7f2fe78bSCy Schubert 
1054*7f2fe78bSCy Schubert     /* pw_history_num = 0 (rejected), 1, 10 */
1055*7f2fe78bSCy Schubert     mpol_test_fail("admin", &ent, KADM5_PW_HISTORY_NUM, KADM5_BAD_HISTORY);
1056*7f2fe78bSCy Schubert     ent.pw_history_num = 1;
1057*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);
1058*7f2fe78bSCy Schubert     ent.pw_history_num = 10;
1059*7f2fe78bSCy Schubert     mpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM);
1060*7f2fe78bSCy Schubert 
1061*7f2fe78bSCy Schubert     if (api >= KADM5_API_VERSION_3) {
1062*7f2fe78bSCy Schubert         ent.pw_max_fail = 2;
1063*7f2fe78bSCy Schubert         mpol_test_compare("admin", &ent, KADM5_PW_MAX_FAILURE);
1064*7f2fe78bSCy Schubert         ent.pw_failcnt_interval = 90;
1065*7f2fe78bSCy Schubert         mpol_test_compare("admin", &ent, KADM5_PW_FAILURE_COUNT_INTERVAL);
1066*7f2fe78bSCy Schubert         ent.pw_lockout_duration = 180;
1067*7f2fe78bSCy Schubert         mpol_test_compare("admin", &ent, KADM5_PW_LOCKOUT_DURATION);
1068*7f2fe78bSCy Schubert     }
1069*7f2fe78bSCy Schubert 
1070*7f2fe78bSCy Schubert     /* Fails over RPC if "modify" ACL is not granted, or if we authenticated to
1071*7f2fe78bSCy Schubert      * kadmin/changepw. */
1072*7f2fe78bSCy Schubert     if (rpc) {
1073*7f2fe78bSCy Schubert         mpol_test_fail("$admin", &ent, KADM5_PW_MAX_LIFE, KADM5_AUTH_MODIFY);
1074*7f2fe78bSCy Schubert         mpol_test_fail("admin/none", &ent, KADM5_PW_MAX_LIFE,
1075*7f2fe78bSCy Schubert                        KADM5_AUTH_MODIFY);
1076*7f2fe78bSCy Schubert         mpol_test_fail("admin/get", &ent, KADM5_PW_MAX_LIFE,
1077*7f2fe78bSCy Schubert                        KADM5_AUTH_MODIFY);
1078*7f2fe78bSCy Schubert         mpol_test_compare("admin/modify", &ent, KADM5_PW_MAX_LIFE);
1079*7f2fe78bSCy Schubert     }
1080*7f2fe78bSCy Schubert 
1081*7f2fe78bSCy Schubert     delete_policy(ent.policy);
1082*7f2fe78bSCy Schubert 
1083*7f2fe78bSCy Schubert     /* Fails with empty or null policy name. */
1084*7f2fe78bSCy Schubert     ent.policy = NULL;
1085*7f2fe78bSCy Schubert     mpol_test_fail("admin", &ent, KADM5_PW_MAX_LIFE, EINVAL);
1086*7f2fe78bSCy Schubert     ent.policy = "";
1087*7f2fe78bSCy Schubert     mpol_test_fail("admin", &ent, KADM5_PW_MAX_LIFE, KADM5_BAD_POLICY);
1088*7f2fe78bSCy Schubert 
1089*7f2fe78bSCy Schubert     /* Fails with null handle or policy ent. */
1090*7f2fe78bSCy Schubert     mpol_test_fail(NULL, &ent, KADM5_PW_MAX_LIFE, KADM5_BAD_SERVER_HANDLE);
1091*7f2fe78bSCy Schubert     mpol_test_fail("admin", NULL, KADM5_PW_MAX_LIFE, EINVAL);
1092*7f2fe78bSCy Schubert }
1093*7f2fe78bSCy Schubert 
1094*7f2fe78bSCy Schubert static void
mprinc_test_fail(char * user,kadm5_principal_ent_t ent,uint32_t mask,krb5_error_code code)1095*7f2fe78bSCy Schubert mprinc_test_fail(char *user, kadm5_principal_ent_t ent, uint32_t mask,
1096*7f2fe78bSCy Schubert                  krb5_error_code code)
1097*7f2fe78bSCy Schubert {
1098*7f2fe78bSCy Schubert     void *handle = get_handle(user);
1099*7f2fe78bSCy Schubert 
1100*7f2fe78bSCy Schubert     check_fail(kadm5_modify_principal(handle, ent, mask), code);
1101*7f2fe78bSCy Schubert     free_handle(handle);
1102*7f2fe78bSCy Schubert }
1103*7f2fe78bSCy Schubert 
1104*7f2fe78bSCy Schubert static void
mprinc_test_compare(char * user,kadm5_principal_ent_t ent,uint32_t mask)1105*7f2fe78bSCy Schubert mprinc_test_compare(char *user, kadm5_principal_ent_t ent, uint32_t mask)
1106*7f2fe78bSCy Schubert {
1107*7f2fe78bSCy Schubert     mprinc_test_fail(user, ent, mask, 0);
1108*7f2fe78bSCy Schubert     compare_princ(ent, mask);
1109*7f2fe78bSCy Schubert }
1110*7f2fe78bSCy Schubert 
1111*7f2fe78bSCy Schubert static void
test_modify_principal()1112*7f2fe78bSCy Schubert test_modify_principal()
1113*7f2fe78bSCy Schubert {
1114*7f2fe78bSCy Schubert     void *handle;
1115*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("modify-principal-test");
1116*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
1117*7f2fe78bSCy Schubert     krb5_tl_data tl = { NULL, 1, 1, (uint8_t *)"x" };
1118*7f2fe78bSCy Schubert     krb5_tl_data tl2 = { NULL, 999, 6, (uint8_t *)"foobar" };
1119*7f2fe78bSCy Schubert 
1120*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
1121*7f2fe78bSCy Schubert     ent.principal = princ;
1122*7f2fe78bSCy Schubert 
1123*7f2fe78bSCy Schubert     /* Fails with unknown principal. */
1124*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_KVNO, KADM5_UNK_PRINC);
1125*7f2fe78bSCy Schubert 
1126*7f2fe78bSCy Schubert     create_simple_princ(princ, NULL);
1127*7f2fe78bSCy Schubert 
1128*7f2fe78bSCy Schubert     /* Fails with prohibited mask bit or tl-data type. */
1129*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, KADM5_BAD_MASK);
1130*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_KEY_DATA, KADM5_BAD_MASK);
1131*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_LAST_FAILED, KADM5_BAD_MASK);
1132*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_LAST_SUCCESS, KADM5_BAD_MASK);
1133*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, KADM5_BAD_MASK);
1134*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_MKVNO, KADM5_BAD_MASK);
1135*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_MOD_NAME, KADM5_BAD_MASK);
1136*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_MOD_TIME, KADM5_BAD_MASK);
1137*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_PRINCIPAL, KADM5_BAD_MASK);
1138*7f2fe78bSCy Schubert 
1139*7f2fe78bSCy Schubert     /* Fails with tl-data type below 256. */
1140*7f2fe78bSCy Schubert     ent.n_tl_data = 1;
1141*7f2fe78bSCy Schubert     ent.tl_data = &tl;
1142*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_TL_DATA, KADM5_BAD_TL_TYPE);
1143*7f2fe78bSCy Schubert 
1144*7f2fe78bSCy Schubert     /* Fails with fail_auth_count other than zero. */
1145*7f2fe78bSCy Schubert     ent.fail_auth_count = 1234;
1146*7f2fe78bSCy Schubert     mprinc_test_fail("admin", &ent, KADM5_FAIL_AUTH_COUNT,
1147*7f2fe78bSCy Schubert                      KADM5_BAD_SERVER_PARAMS);
1148*7f2fe78bSCy Schubert     ent.fail_auth_count = 0;
1149*7f2fe78bSCy Schubert 
1150*7f2fe78bSCy Schubert     /* Succeeds with zero values of various fields. */
1151*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION);
1152*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_MAX_LIFE);
1153*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_MAX_RLIFE);
1154*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_FAIL_AUTH_COUNT);
1155*7f2fe78bSCy Schubert     mprinc_test_compare("admin/modify", &ent, KADM5_PRINC_EXPIRE_TIME);
1156*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_POLICY_CLR);
1157*7f2fe78bSCy Schubert 
1158*7f2fe78bSCy Schubert     /* Setting a policy causes a pw_expiration computation.  Explicit
1159*7f2fe78bSCy Schubert      * PW_EXPIRATION overrides the policy. */
1160*7f2fe78bSCy Schubert     ent.pw_expiration = 1234;
1161*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION);
1162*7f2fe78bSCy Schubert     ent.policy = "dict-only-pol";
1163*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_POLICY);
1164*7f2fe78bSCy Schubert     ent.policy = "test-pol";
1165*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_POLICY);
1166*7f2fe78bSCy Schubert     ent.pw_expiration = 999999999;
1167*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION);
1168*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_POLICY_CLR);
1169*7f2fe78bSCy Schubert 
1170*7f2fe78bSCy Schubert     /* Succeeds with non-zero values of various fields. */
1171*7f2fe78bSCy Schubert     ent.princ_expire_time = 1234;
1172*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME);
1173*7f2fe78bSCy Schubert     ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX;
1174*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES);
1175*7f2fe78bSCy Schubert     ent.attributes = KRB5_KDB_REQUIRES_PWCHANGE;
1176*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES);
1177*7f2fe78bSCy Schubert     ent.attributes = KRB5_KDB_DISALLOW_TGT_BASED;
1178*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES);
1179*7f2fe78bSCy Schubert     ent.max_life = 3456;
1180*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_MAX_LIFE);
1181*7f2fe78bSCy Schubert     ent.kvno = 7;
1182*7f2fe78bSCy Schubert     mprinc_test_compare("admin", &ent, KADM5_KVNO);
1183*7f2fe78bSCy Schubert 
1184*7f2fe78bSCy Schubert     /* Fails over RPC if "modify" ACL is not granted, or if we authenticated to
1185*7f2fe78bSCy Schubert      * kadmin/changepw. */
1186*7f2fe78bSCy Schubert     if (rpc) {
1187*7f2fe78bSCy Schubert         mprinc_test_fail("$admin", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);
1188*7f2fe78bSCy Schubert         mprinc_test_fail("admin/none", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);
1189*7f2fe78bSCy Schubert         mprinc_test_fail("admin/get", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);
1190*7f2fe78bSCy Schubert         mprinc_test_fail("admin/add", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);
1191*7f2fe78bSCy Schubert         mprinc_test_fail("admin/delete", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY);
1192*7f2fe78bSCy Schubert     }
1193*7f2fe78bSCy Schubert 
1194*7f2fe78bSCy Schubert     /* tl-data of type > 255 is accepted. */
1195*7f2fe78bSCy Schubert     handle = get_handle("admin");
1196*7f2fe78bSCy Schubert     ent.max_renewable_life = 88;
1197*7f2fe78bSCy Schubert     ent.tl_data = &tl2;
1198*7f2fe78bSCy Schubert     check(kadm5_modify_principal(handle, &ent,
1199*7f2fe78bSCy Schubert                                  KADM5_MAX_RLIFE | KADM5_TL_DATA));
1200*7f2fe78bSCy Schubert     memset(&ent, 0, sizeof(ent));
1201*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, princ, &ent,
1202*7f2fe78bSCy Schubert                               KADM5_PRINCIPAL_NORMAL_MASK | KADM5_TL_DATA));
1203*7f2fe78bSCy Schubert     assert(ent.max_renewable_life == 88);
1204*7f2fe78bSCy Schubert     assert(ent.n_tl_data == 1);
1205*7f2fe78bSCy Schubert     assert(ent.tl_data->tl_data_type == tl2.tl_data_type);
1206*7f2fe78bSCy Schubert     assert(ent.tl_data->tl_data_length == tl2.tl_data_length);
1207*7f2fe78bSCy Schubert     assert(memcmp(ent.tl_data->tl_data_contents, tl2.tl_data_contents,
1208*7f2fe78bSCy Schubert                   tl2.tl_data_length) == 0);
1209*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &ent));
1210*7f2fe78bSCy Schubert     free_handle(handle);
1211*7f2fe78bSCy Schubert 
1212*7f2fe78bSCy Schubert     /* Fails with null handle or principal ent. */
1213*7f2fe78bSCy Schubert     mprinc_test_fail(NULL, &ent, KADM5_KVNO, KADM5_BAD_SERVER_HANDLE);
1214*7f2fe78bSCy Schubert     mprinc_test_fail("admin", NULL, KADM5_KVNO, EINVAL);
1215*7f2fe78bSCy Schubert 
1216*7f2fe78bSCy Schubert     delete_princ(princ);
1217*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1218*7f2fe78bSCy Schubert }
1219*7f2fe78bSCy Schubert 
1220*7f2fe78bSCy Schubert static void
rnd_test_fail(char * user,krb5_principal princ,krb5_error_code code)1221*7f2fe78bSCy Schubert rnd_test_fail(char *user, krb5_principal princ, krb5_error_code code)
1222*7f2fe78bSCy Schubert {
1223*7f2fe78bSCy Schubert     void *handle = get_handle(user);
1224*7f2fe78bSCy Schubert 
1225*7f2fe78bSCy Schubert     check_fail(kadm5_randkey_principal(handle, princ, NULL, NULL), code);
1226*7f2fe78bSCy Schubert     free_handle(handle);
1227*7f2fe78bSCy Schubert }
1228*7f2fe78bSCy Schubert 
1229*7f2fe78bSCy Schubert static void
rnd_test_succeed(char * user,krb5_principal princ)1230*7f2fe78bSCy Schubert rnd_test_succeed(char *user, krb5_principal princ)
1231*7f2fe78bSCy Schubert {
1232*7f2fe78bSCy Schubert     rnd_test_fail(user, princ, 0);
1233*7f2fe78bSCy Schubert }
1234*7f2fe78bSCy Schubert 
1235*7f2fe78bSCy Schubert static void
test_randkey()1236*7f2fe78bSCy Schubert test_randkey()
1237*7f2fe78bSCy Schubert {
1238*7f2fe78bSCy Schubert     void *handle;
1239*7f2fe78bSCy Schubert     krb5_principal princ = parse_princ("randkey-principal-test");
1240*7f2fe78bSCy Schubert     krb5_principal user_princ = parse_princ("user");
1241*7f2fe78bSCy Schubert     krb5_principal admin_princ = parse_princ("admin");
1242*7f2fe78bSCy Schubert     kadm5_principal_ent_rec ent;
1243*7f2fe78bSCy Schubert     krb5_keyblock *keys;
1244*7f2fe78bSCy Schubert     int n_keys, i;
1245*7f2fe78bSCy Schubert 
1246*7f2fe78bSCy Schubert     create_simple_princ(princ, NULL);
1247*7f2fe78bSCy Schubert 
1248*7f2fe78bSCy Schubert     /* Check kvno and enctypes after randkey. */
1249*7f2fe78bSCy Schubert     handle = get_handle("admin");
1250*7f2fe78bSCy Schubert     check(kadm5_randkey_principal(handle, princ, &keys, &n_keys));
1251*7f2fe78bSCy Schubert     check(kadm5_get_principal(handle, princ, &ent, KADM5_KEY_DATA));
1252*7f2fe78bSCy Schubert     compare_key_data(&ent, default_supported_enctypes);
1253*7f2fe78bSCy Schubert     assert(ent.key_data[0].key_data_kvno == 2);
1254*7f2fe78bSCy Schubert     assert(n_keys == ent.n_key_data);
1255*7f2fe78bSCy Schubert     for (i = 0; i < n_keys; i++)
1256*7f2fe78bSCy Schubert         krb5_free_keyblock_contents(context, &keys[i]);
1257*7f2fe78bSCy Schubert     free(keys);
1258*7f2fe78bSCy Schubert     check(kadm5_free_principal_ent(handle, &ent));
1259*7f2fe78bSCy Schubert     free_handle(handle);
1260*7f2fe78bSCy Schubert 
1261*7f2fe78bSCy Schubert     /*
1262*7f2fe78bSCy Schubert      * Fails over RPC if "change" ACL is not granted, or if we authenticated to
1263*7f2fe78bSCy Schubert      * kadmin/changepw and are changing another principal's password, or for
1264*7f2fe78bSCy Schubert      * self-service if the policy minimum life has not elapsed since the last
1265*7f2fe78bSCy Schubert      * key change.
1266*7f2fe78bSCy Schubert      */
1267*7f2fe78bSCy Schubert     if (rpc) {
1268*7f2fe78bSCy Schubert         rnd_test_fail("$admin", user_princ, KADM5_AUTH_CHANGEPW);
1269*7f2fe78bSCy Schubert         rnd_test_fail("admin/none", user_princ, KADM5_AUTH_CHANGEPW);
1270*7f2fe78bSCy Schubert         rnd_test_fail("admin/delete", user_princ, KADM5_AUTH_CHANGEPW);
1271*7f2fe78bSCy Schubert         rnd_test_succeed("admin/modify", user_princ);
1272*7f2fe78bSCy Schubert         cpw_test_succeed("admin", user_princ, USER_PASSWORD);
1273*7f2fe78bSCy Schubert         rnd_test_fail("user", user_princ, KADM5_PASS_TOOSOON);
1274*7f2fe78bSCy Schubert         rnd_test_fail("$user", user_princ, KADM5_PASS_TOOSOON);
1275*7f2fe78bSCy Schubert     }
1276*7f2fe78bSCy Schubert 
1277*7f2fe78bSCy Schubert     /* Succeeds with change privilege in spite of policy minimum life. */
1278*7f2fe78bSCy Schubert     rnd_test_succeed("admin/modify", user_princ);
1279*7f2fe78bSCy Schubert     cpw_test_succeed("admin", user_princ, USER_PASSWORD);
1280*7f2fe78bSCy Schubert 
1281*7f2fe78bSCy Schubert     /* Succeeds for self-service when authenticating to kadmin/changepw. */
1282*7f2fe78bSCy Schubert     handle = get_handle("$admin");
1283*7f2fe78bSCy Schubert     check(kadm5_randkey_principal(handle, admin_princ, NULL, NULL));
1284*7f2fe78bSCy Schubert     check(kadm5_chpass_principal(handle, admin_princ, ADMIN_PASSWORD));
1285*7f2fe78bSCy Schubert     free_handle(handle);
1286*7f2fe78bSCy Schubert 
1287*7f2fe78bSCy Schubert     /* Fails with null handle or principal name. */
1288*7f2fe78bSCy Schubert     rnd_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE);
1289*7f2fe78bSCy Schubert     rnd_test_fail("admin", NULL, EINVAL);
1290*7f2fe78bSCy Schubert 
1291*7f2fe78bSCy Schubert     delete_princ(princ);
1292*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1293*7f2fe78bSCy Schubert     krb5_free_principal(context, user_princ);
1294*7f2fe78bSCy Schubert     krb5_free_principal(context, admin_princ);
1295*7f2fe78bSCy Schubert }
1296*7f2fe78bSCy Schubert 
1297*7f2fe78bSCy Schubert int
main(int argc,char ** argv)1298*7f2fe78bSCy Schubert main(int argc, char **argv)
1299*7f2fe78bSCy Schubert {
1300*7f2fe78bSCy Schubert     assert(argc == 2);
1301*7f2fe78bSCy Schubert     rpc = (strcmp(argv[1], "clnt") == 0);
1302*7f2fe78bSCy Schubert 
1303*7f2fe78bSCy Schubert     check(kadm5_init_krb5_context(&context));
1304*7f2fe78bSCy Schubert 
1305*7f2fe78bSCy Schubert     api = KADM5_API_VERSION_2;
1306*7f2fe78bSCy Schubert     test_create_policy();
1307*7f2fe78bSCy Schubert     test_get_policy();
1308*7f2fe78bSCy Schubert     test_modify_policy();
1309*7f2fe78bSCy Schubert 
1310*7f2fe78bSCy Schubert     api = KADM5_API_VERSION_4;
1311*7f2fe78bSCy Schubert     test_chpass();
1312*7f2fe78bSCy Schubert     test_create_policy();
1313*7f2fe78bSCy Schubert     test_create_principal();
1314*7f2fe78bSCy Schubert     test_delete_policy();
1315*7f2fe78bSCy Schubert     test_delete_principal();
1316*7f2fe78bSCy Schubert     test_get_policy();
1317*7f2fe78bSCy Schubert     test_get_principal();
1318*7f2fe78bSCy Schubert     test_init_destroy();
1319*7f2fe78bSCy Schubert     test_modify_policy();
1320*7f2fe78bSCy Schubert     test_modify_principal();
1321*7f2fe78bSCy Schubert     test_randkey();
1322*7f2fe78bSCy Schubert 
1323*7f2fe78bSCy Schubert     krb5_free_context(context);
1324*7f2fe78bSCy Schubert 
1325*7f2fe78bSCy Schubert     return 0;
1326*7f2fe78bSCy Schubert }
1327