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