Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/kadmin/cli/kadmin.c
34907 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright 1994, 2008 by the Massachusetts Institute of Technology.
4
* All Rights Reserved.
5
*
6
* Export of this software from the United States of America may
7
* require a specific license from the United States Government.
8
* It is the responsibility of any person or organization contemplating
9
* export to obtain such a license before exporting.
10
*
11
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12
* distribute this software and its documentation for any purpose and
13
* without fee is hereby granted, provided that the above copyright
14
* notice appear in all copies and that both that copyright notice and
15
* this permission notice appear in supporting documentation, and that
16
* the name of M.I.T. not be used in advertising or publicity pertaining
17
* to distribution of the software without specific, written prior
18
* permission. Furthermore if you modify this software you must label
19
* your software as modified software and not distribute it in such a
20
* fashion that it might be confused with the original M.I.T. software.
21
* M.I.T. makes no representations about the suitability of
22
* this software for any purpose. It is provided "as is" without express
23
* or implied warranty.
24
*/
25
/*
26
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
27
* Use is subject to license terms.
28
*/
29
30
/* Base functions for a kadmin command line interface using the OVSecure
31
* library */
32
33
/* for "_" macro */
34
#include "k5-int.h"
35
#include <kadm5/admin.h>
36
#include <adm_proto.h>
37
#include <errno.h>
38
#include <stdio.h>
39
#include <string.h>
40
#include <ctype.h>
41
#include <sys/types.h>
42
#include <math.h>
43
#include <unistd.h>
44
#include <pwd.h>
45
/* #include <sys/timeb.h> */
46
#include <time.h>
47
#include "kadmin.h"
48
49
static krb5_boolean script_mode = FALSE;
50
int exit_status = 0;
51
char *def_realm = NULL;
52
char *whoami = NULL;
53
54
void *handle = NULL;
55
krb5_context context;
56
char *ccache_name = NULL;
57
58
int locked = 0;
59
60
static void
61
info(const char *fmt, ...)
62
#if !defined(__cplusplus) && (__GNUC__ > 2)
63
__attribute__((__format__(__printf__, 1, 2)))
64
#endif
65
;
66
67
static void
68
error(const char *fmt, ...)
69
#if !defined(__cplusplus) && (__GNUC__ > 2)
70
__attribute__((__format__(__printf__, 1, 2)))
71
#endif
72
;
73
74
/* Like printf, but suppressed if script_mode is set. */
75
static void
76
info(const char *fmt, ...)
77
{
78
va_list ap;
79
80
if (script_mode)
81
return;
82
va_start(ap, fmt);
83
vprintf(fmt, ap);
84
va_end(ap);
85
}
86
87
/* Like fprintf to stderr; also set exit_status if script_mode is set. */
88
static void
89
error(const char *fmt, ...)
90
{
91
va_list ap;
92
93
if (script_mode)
94
exit_status = 1;
95
va_start(ap, fmt);
96
vfprintf(stderr, fmt, ap);
97
va_end(ap);
98
}
99
100
static void
101
usage(void)
102
{
103
error(_("Usage: %s [-r realm] [-p principal] [-q query] "
104
"[clnt|local args]\n"
105
" [command args...]\n"
106
"\tclnt args: [-s admin_server[:port]] "
107
"[[-c ccache]|[-k [-t keytab]]]|[-n] [-O | -N]\n"
108
"\tlocal args: [-x db_args]* [-d dbname] "
109
"[-e \"enc:salt ...\"] [-m] [-w password] "
110
"where,\n\t[-x db_args]* - any number of database specific "
111
"arguments.\n"
112
"\t\t\tLook at each database documentation for supported "
113
"arguments\n"), whoami);
114
exit(1);
115
}
116
117
static char *
118
strdur(time_t duration)
119
{
120
static char out[50];
121
int neg, days, hours, minutes, seconds;
122
123
if (duration < 0) {
124
duration *= -1;
125
neg = 1;
126
} else
127
neg = 0;
128
days = duration / (24 * 3600);
129
duration %= 24 * 3600;
130
hours = duration / 3600;
131
duration %= 3600;
132
minutes = duration / 60;
133
duration %= 60;
134
seconds = duration;
135
snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
136
days, days == 1 ? "day" : "days",
137
hours, minutes, seconds);
138
return out;
139
}
140
141
static const char *
142
strdate(krb5_timestamp when)
143
{
144
struct tm *tm;
145
static char out[40];
146
time_t lcltim = ts2tt(when);
147
148
tm = localtime(&lcltim);
149
if (tm == NULL ||
150
strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm) == 0)
151
strlcpy(out, "(error)", sizeof(out));
152
return out;
153
}
154
155
/* Parse a date string using getdate.y. On failure, output an error message
156
* and return (time_t)-1. */
157
static time_t
158
parse_date(char *str, time_t now)
159
{
160
time_t date;
161
162
date = get_date_rel(str, now);
163
if (date == (time_t)-1)
164
error(_("Invalid date specification \"%s\".\n"), str);
165
return date;
166
}
167
168
/*
169
* Parse a time interval. Use krb5_string_to_deltat() if it works; otherwise
170
* use getdate.y and subtract now, with sanity checks. On failure, output an
171
* error message and return (time_t)-1.
172
*/
173
static time_t
174
parse_interval(char *str, time_t now)
175
{
176
time_t date;
177
krb5_deltat delta;
178
179
if (krb5_string_to_deltat(str, &delta) == 0)
180
return delta;
181
182
date = parse_date(str, now);
183
if (date == (time_t)-1)
184
return date;
185
186
/* Interpret an absolute time of 0 (e.g. "never") as an interval of 0. */
187
if (date == 0)
188
return 0;
189
190
/* Don't return a negative interval if the date is in the past. */
191
if (date < now) {
192
error(_("Interval specification \"%s\" is in the past.\n"), str);
193
return (time_t)-1;
194
}
195
196
return date - now;
197
}
198
199
/* this is a wrapper to go around krb5_parse_principal so we can set
200
the default realm up properly */
201
static krb5_error_code
202
kadmin_parse_name(char *name, krb5_principal *principal)
203
{
204
char *cp, *fullname;
205
krb5_error_code retval;
206
int result;
207
208
/* assumes def_realm is initialized! */
209
cp = strchr(name, '@');
210
while (cp) {
211
if (cp - name && *(cp - 1) != '\\')
212
break;
213
else
214
cp = strchr(cp + 1, '@');
215
}
216
if (cp == NULL)
217
result = asprintf(&fullname, "%s@%s", name, def_realm);
218
else
219
result = asprintf(&fullname, "%s", name);
220
if (result < 0)
221
return ENOMEM;
222
retval = krb5_parse_name(context, fullname, principal);
223
free(fullname);
224
return retval;
225
}
226
227
static void
228
extended_com_err_fn(const char *myprog, errcode_t code,
229
const char *fmt, va_list args)
230
{
231
const char *emsg;
232
233
if (code) {
234
emsg = krb5_get_error_message(context, code);
235
error("%s: %s ", myprog, emsg);
236
krb5_free_error_message(context, emsg);
237
} else {
238
error("%s: ", myprog);
239
}
240
vfprintf(stderr, fmt, args);
241
error("\n");
242
}
243
244
/* Create a principal using the oldest appropriate kadm5 API. */
245
static krb5_error_code
246
create_princ(kadm5_principal_ent_rec *princ, long mask, int n_ks,
247
krb5_key_salt_tuple *ks, char *pass)
248
{
249
if (ks)
250
return kadm5_create_principal_3(handle, princ, mask, n_ks, ks, pass);
251
else
252
return kadm5_create_principal(handle, princ, mask, pass);
253
}
254
255
/* Randomize a principal's password using the appropriate kadm5 API. */
256
krb5_error_code
257
randkey_princ(void *lhandle, krb5_principal princ, krb5_boolean keepold,
258
int n_ks, krb5_key_salt_tuple *ks, krb5_keyblock **key,
259
int *n_keys)
260
{
261
krb5_error_code ret;
262
263
/* Try the newer API first, because the Solaris kadmind only creates DES
264
* keys when the old API is used. */
265
ret = kadm5_randkey_principal_3(lhandle, princ, keepold, n_ks, ks, key,
266
n_keys);
267
268
/* Fall back to the old version if we get an error and aren't using any new
269
* parameters. */
270
if (ret == KADM5_RPC_ERROR && !keepold && ks == NULL)
271
ret = kadm5_randkey_principal(lhandle, princ, key, n_keys);
272
273
return ret;
274
}
275
276
static krb5_boolean
277
policy_exists(const char *name)
278
{
279
kadm5_policy_ent_rec pol;
280
281
if (kadm5_get_policy(handle, (char *)name, &pol) != 0)
282
return FALSE;
283
kadm5_free_policy_ent(handle, &pol);
284
return TRUE;
285
}
286
287
void
288
kadmin_startup(int argc, char *argv[], char **request_out, char ***args_out)
289
{
290
extern char *optarg;
291
char *princstr = NULL, *keytab_name = NULL, *query = NULL;
292
char *password = NULL;
293
char *luser, *canon, *cp;
294
int optchar, freeprinc = 0, use_keytab = 0, use_anonymous = 0;
295
struct passwd *pw;
296
kadm5_ret_t retval;
297
krb5_ccache cc;
298
krb5_principal princ;
299
kadm5_config_params params;
300
char **db_args = NULL;
301
size_t db_args_size = 0;
302
char *db_name = NULL;
303
char *svcname, *realm;
304
305
memset(&params, 0, sizeof(params));
306
307
set_com_err_hook(extended_com_err_fn);
308
309
retval = kadm5_init_krb5_context(&context);
310
if (retval) {
311
com_err(whoami, retval, _("while initializing krb5 library"));
312
exit(1);
313
}
314
315
while ((optchar = getopt(argc, argv,
316
"+x:r:p:knq:w:d:s:mc:t:e:ON")) != EOF) {
317
switch (optchar) {
318
case 'x':
319
db_args_size++;
320
db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
321
if (db_args == NULL) {
322
error(_("%s: Cannot initialize. Not enough memory\n"), whoami);
323
exit(1);
324
}
325
db_args[db_args_size - 1] = optarg;
326
db_args[db_args_size] = NULL;
327
break;
328
329
case 'r':
330
def_realm = optarg;
331
break;
332
case 'p':
333
princstr = optarg;
334
break;
335
case 'c':
336
ccache_name = optarg;
337
break;
338
case 'k':
339
use_keytab++;
340
break;
341
case 'n':
342
use_anonymous++;
343
break;
344
case 't':
345
keytab_name = optarg;
346
break;
347
case 'w':
348
password = optarg;
349
break;
350
case 'q':
351
query = optarg;
352
break;
353
case 'd':
354
/* db_name has to be passed as part of the db_args. */
355
free(db_name);
356
asprintf(&db_name, "dbname=%s", optarg);
357
358
db_args_size++;
359
db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
360
if (db_args == NULL) {
361
error(_("%s: Cannot initialize. Not enough memory\n"), whoami);
362
exit(1);
363
}
364
db_args[db_args_size - 1] = db_name;
365
db_args[db_args_size] = NULL;
366
break;
367
case 's':
368
params.admin_server = optarg;
369
params.mask |= KADM5_CONFIG_ADMIN_SERVER;
370
break;
371
case 'm':
372
params.mkey_from_kbd = 1;
373
params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
374
break;
375
case 'e':
376
retval = krb5_string_to_keysalts(optarg, NULL, NULL, 0,
377
&params.keysalts,
378
&params.num_keysalts);
379
if (retval) {
380
com_err(whoami, retval, _("while parsing keysalts %s"),
381
optarg);
382
exit(1);
383
}
384
params.mask |= KADM5_CONFIG_ENCTYPES;
385
break;
386
case 'O':
387
params.mask |= KADM5_CONFIG_OLD_AUTH_GSSAPI;
388
break;
389
case 'N':
390
params.mask |= KADM5_CONFIG_AUTH_NOFALLBACK;
391
break;
392
default:
393
usage();
394
}
395
}
396
if ((ccache_name && use_keytab) ||
397
(keytab_name && !use_keytab) ||
398
(ccache_name && use_anonymous) ||
399
(use_anonymous && use_keytab))
400
usage();
401
402
if (query != NULL && argv[optind] != NULL) {
403
error(_("%s: -q is exclusive with command-line query"), whoami);
404
usage();
405
}
406
407
if (argv[optind] != NULL)
408
script_mode = TRUE;
409
410
if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) {
411
error(_("%s: unable to get default realm\n"), whoami);
412
exit(1);
413
}
414
415
params.mask |= KADM5_CONFIG_REALM;
416
params.realm = def_realm;
417
418
if (params.mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)
419
svcname = KADM5_ADMIN_SERVICE;
420
else
421
svcname = NULL;
422
423
/*
424
* Set cc to an open credentials cache, either specified by the -c
425
* argument or the default.
426
*/
427
if (ccache_name == NULL) {
428
retval = krb5_cc_default(context, &cc);
429
if (retval) {
430
com_err(whoami, retval,
431
_("while opening default credentials cache"));
432
exit(1);
433
}
434
} else {
435
retval = krb5_cc_resolve(context, ccache_name, &cc);
436
if (retval) {
437
com_err(whoami, retval, _("while opening credentials cache %s"),
438
ccache_name);
439
exit(1);
440
}
441
}
442
443
/*
444
* If no principal name is specified: If authenticating anonymously, use
445
* the anonymous principal for the local realm, else if a ccache was
446
* specified and its primary principal name can be read, it is used, else
447
* if a keytab was specified, the principal name is host/hostname,
448
* otherwise append "/admin" to the primary name of the default ccache,
449
* $USER, or pw_name.
450
*
451
* Gee, 100+ lines to figure out the client principal name. This
452
* should be compressed...
453
*/
454
455
if (princstr == NULL) {
456
if (use_anonymous) {
457
if (asprintf(&princstr, "%s/%s@%s", KRB5_WELLKNOWN_NAMESTR,
458
KRB5_ANONYMOUS_PRINCSTR, def_realm) < 0) {
459
error(_("%s: out of memory\n"), whoami);
460
exit(1);
461
}
462
freeprinc++;
463
} else if (ccache_name != NULL &&
464
!krb5_cc_get_principal(context, cc, &princ)) {
465
retval = krb5_unparse_name(context, princ, &princstr);
466
if (retval) {
467
com_err(whoami, retval,
468
_("while canonicalizing principal name"));
469
exit(1);
470
}
471
krb5_free_principal(context, princ);
472
freeprinc++;
473
} else if (use_keytab != 0) {
474
retval = krb5_sname_to_principal(context, NULL, "host",
475
KRB5_NT_SRV_HST, &princ);
476
if (retval) {
477
com_err(whoami, retval, _("creating host service principal"));
478
exit(1);
479
}
480
retval = krb5_unparse_name(context, princ, &princstr);
481
if (retval) {
482
com_err(whoami, retval,
483
_("while canonicalizing principal name"));
484
exit(1);
485
}
486
krb5_free_principal(context, princ);
487
freeprinc++;
488
} else if (!krb5_cc_get_principal(context, cc, &princ)) {
489
if (krb5_unparse_name(context, princ, &canon)) {
490
error(_("%s: unable to canonicalize principal\n"), whoami);
491
exit(1);
492
}
493
/* Strip out realm of principal if it's there. */
494
realm = strchr(canon, '@');
495
while (realm) {
496
if (realm > canon && *(realm - 1) != '\\')
497
break;
498
realm = strchr(realm + 1, '@');
499
}
500
if (realm)
501
*realm++ = '\0';
502
cp = strchr(canon, '/');
503
while (cp) {
504
if (cp > canon && *(cp - 1) != '\\')
505
break;
506
cp = strchr(cp + 1, '/');
507
}
508
if (cp != NULL)
509
*cp = '\0';
510
if (asprintf(&princstr, "%s/admin%s%s", canon,
511
(realm) ? "@" : "",
512
(realm) ? realm : "") < 0) {
513
error(_("%s: out of memory\n"), whoami);
514
exit(1);
515
}
516
free(canon);
517
krb5_free_principal(context, princ);
518
freeprinc++;
519
} else if ((luser = getenv("USER"))) {
520
if (asprintf(&princstr, "%s/admin@%s", luser, def_realm) < 0) {
521
error(_("%s: out of memory\n"), whoami);
522
exit(1);
523
}
524
freeprinc++;
525
} else if ((pw = getpwuid(getuid()))) {
526
if (asprintf(&princstr, "%s/admin@%s", pw->pw_name,
527
def_realm) < 0) {
528
error(_("%s: out of memory\n"), whoami);
529
exit(1);
530
}
531
freeprinc++;
532
} else {
533
error(_("%s: unable to figure out a principal name\n"), whoami);
534
exit(1);
535
}
536
}
537
538
retval = krb5_klog_init(context, "admin_server", whoami, 0);
539
if (retval) {
540
com_err(whoami, retval, _("while setting up logging"));
541
exit(1);
542
}
543
544
/*
545
* Initialize the kadm5 connection. If we were given a ccache,
546
* use it. Otherwise, use/prompt for the password.
547
*/
548
if (ccache_name) {
549
info(_("Authenticating as principal %s with existing "
550
"credentials.\n"), princstr);
551
retval = kadm5_init_with_creds(context, princstr, cc, svcname, &params,
552
KADM5_STRUCT_VERSION,
553
KADM5_API_VERSION_4, db_args, &handle);
554
} else if (use_anonymous) {
555
info(_("Authenticating as principal %s with password; "
556
"anonymous requested.\n"), princstr);
557
retval = kadm5_init_anonymous(context, princstr, svcname, &params,
558
KADM5_STRUCT_VERSION,
559
KADM5_API_VERSION_4, db_args, &handle);
560
} else if (use_keytab) {
561
if (keytab_name != NULL) {
562
info(_("Authenticating as principal %s with keytab %s.\n"),
563
princstr, keytab_name);
564
} else {
565
info(_("Authenticating as principal %s with default keytab.\n"),
566
princstr);
567
}
568
retval = kadm5_init_with_skey(context, princstr, keytab_name, svcname,
569
&params, KADM5_STRUCT_VERSION,
570
KADM5_API_VERSION_4, db_args, &handle);
571
} else {
572
info(_("Authenticating as principal %s with password.\n"),
573
princstr);
574
retval = kadm5_init_with_password(context, princstr, password, svcname,
575
&params, KADM5_STRUCT_VERSION,
576
KADM5_API_VERSION_4, db_args,
577
&handle);
578
}
579
if (retval) {
580
com_err(whoami, retval, _("while initializing %s interface"), whoami);
581
if (retval == KADM5_BAD_CLIENT_PARAMS ||
582
retval == KADM5_BAD_SERVER_PARAMS)
583
usage();
584
exit(1);
585
}
586
if (freeprinc)
587
free(princstr);
588
589
free(params.keysalts);
590
free(db_name);
591
free(db_args);
592
593
retval = krb5_cc_close(context, cc);
594
if (retval) {
595
com_err(whoami, retval, _("while closing ccache %s"), ccache_name);
596
exit(1);
597
}
598
599
retval = kadm5_init_iprop(handle, 0);
600
if (retval) {
601
com_err(whoami, retval, _("while mapping update log"));
602
exit(1);
603
}
604
605
*request_out = query;
606
*args_out = argv + optind;
607
}
608
609
int
610
quit(void)
611
{
612
kadm5_ret_t retval;
613
614
if (locked) {
615
retval = kadm5_unlock(handle);
616
if (retval) {
617
com_err("quit", retval, _("while unlocking locked database"));
618
return 1;
619
}
620
locked = 0;
621
}
622
623
kadm5_destroy(handle);
624
if (ccache_name != NULL && !script_mode) {
625
fprintf(stderr, "\n\a\a\a%s",
626
_("Administration credentials NOT DESTROYED.\n"));
627
}
628
629
/* insert more random cleanup here */
630
krb5_klog_close(context);
631
krb5_free_context(context);
632
return 0;
633
}
634
635
void
636
kadmin_lock(int argc, char *argv[], int sci_idx, void *info_ptr)
637
{
638
kadm5_ret_t retval;
639
640
if (locked)
641
return;
642
retval = kadm5_lock(handle);
643
if (retval) {
644
com_err("lock", retval, "");
645
return;
646
}
647
locked = 1;
648
}
649
650
void
651
kadmin_unlock(int argc, char *argv[], int sci_idx, void *info_ptr)
652
{
653
kadm5_ret_t retval;
654
655
if (!locked)
656
return;
657
retval = kadm5_unlock(handle);
658
if (retval) {
659
com_err("unlock", retval, "");
660
return;
661
}
662
locked = 0;
663
}
664
665
void
666
kadmin_delprinc(int argc, char *argv[], int sci_idx, void *info_ptr)
667
{
668
kadm5_ret_t retval;
669
krb5_principal princ = NULL;
670
char *canon = NULL;
671
char reply[5];
672
673
if (! (argc == 2 ||
674
(argc == 3 && !strcmp("-force", argv[1])))) {
675
error(_("usage: delete_principal [-force] principal\n"));
676
return;
677
}
678
retval = kadmin_parse_name(argv[argc - 1], &princ);
679
if (retval) {
680
com_err("delete_principal", retval, _("while parsing principal name"));
681
return;
682
}
683
retval = krb5_unparse_name(context, princ, &canon);
684
if (retval) {
685
com_err("delete_principal", retval,
686
_("while canonicalizing principal"));
687
goto cleanup;
688
}
689
if (argc == 2 && !script_mode) {
690
printf(_("Are you sure you want to delete the principal \"%s\"? "
691
"(yes/no): "), canon);
692
fgets(reply, sizeof (reply), stdin);
693
if (strcmp("yes\n", reply)) {
694
fprintf(stderr, _("Principal \"%s\" not deleted\n"), canon);
695
goto cleanup;
696
}
697
}
698
retval = kadm5_delete_principal(handle, princ);
699
if (retval) {
700
com_err("delete_principal", retval,
701
_("while deleting principal \"%s\""), canon);
702
goto cleanup;
703
}
704
info(_("Principal \"%s\" deleted.\n"), canon);
705
info(_("Make sure that you have removed this principal from all ACLs "
706
"before reusing.\n"));
707
708
cleanup:
709
krb5_free_principal(context, princ);
710
free(canon);
711
}
712
713
void
714
kadmin_renameprinc(int argc, char *argv[], int sci_idx, void *info_ptr)
715
{
716
kadm5_ret_t retval;
717
krb5_principal oprinc = NULL, nprinc = NULL;
718
char *ocanon = NULL, *ncanon = NULL;
719
char reply[5];
720
721
if (!(argc == 3 || (argc == 4 && !strcmp("-force", argv[1])))) {
722
error(_("usage: rename_principal [-force] old_principal "
723
"new_principal\n"));
724
return;
725
}
726
retval = kadmin_parse_name(argv[argc - 2], &oprinc);
727
if (retval) {
728
com_err("rename_principal", retval,
729
_("while parsing old principal name"));
730
goto cleanup;
731
}
732
retval = kadmin_parse_name(argv[argc - 1], &nprinc);
733
if (retval) {
734
com_err("rename_principal", retval,
735
_("while parsing new principal name"));
736
goto cleanup;
737
}
738
retval = krb5_unparse_name(context, oprinc, &ocanon);
739
if (retval) {
740
com_err("rename_principal", retval,
741
_("while canonicalizing old principal"));
742
goto cleanup;
743
}
744
retval = krb5_unparse_name(context, nprinc, &ncanon);
745
if (retval) {
746
com_err("rename_principal", retval,
747
_("while canonicalizing new principal"));
748
goto cleanup;
749
}
750
if (argc == 3 && !script_mode) {
751
printf(_("Are you sure you want to rename the principal \"%s\" "
752
"to \"%s\"? (yes/no): "), ocanon, ncanon);
753
fgets(reply, sizeof(reply), stdin);
754
if (strcmp("yes\n", reply)) {
755
fprintf(stderr, _("Principal \"%s\" not renamed\n"), ocanon);
756
goto cleanup;
757
}
758
}
759
retval = kadm5_rename_principal(handle, oprinc, nprinc);
760
if (retval) {
761
com_err("rename_principal", retval,
762
_("while renaming principal \"%s\" to \"%s\""),
763
ocanon, ncanon);
764
goto cleanup;
765
}
766
info(_("Principal \"%s\" renamed to \"%s\".\n"), ocanon, ncanon);
767
info(_("Make sure that you have removed the old principal from all ACLs "
768
"before reusing.\n"));
769
770
cleanup:
771
krb5_free_principal(context, nprinc);
772
krb5_free_principal(context, oprinc);
773
free(ncanon);
774
free(ocanon);
775
}
776
777
void
778
kadmin_addalias(int argc, char *argv[], int sci_idx, void *info_ptr)
779
{
780
kadm5_ret_t retval;
781
krb5_principal alias = NULL, target = NULL;
782
char *acanon = NULL, *tcanon = NULL;
783
784
if (argc != 3) {
785
error(_("usage: add_alias alias_principal target_principal\n"));
786
return;
787
}
788
retval = kadmin_parse_name(argv[1], &alias);
789
if (retval) {
790
com_err("add_alias", retval, _("while parsing alias principal name"));
791
goto cleanup;
792
}
793
retval = kadmin_parse_name(argv[2], &target);
794
if (retval) {
795
com_err("add_alias", retval, _("while parsing target principal name"));
796
goto cleanup;
797
}
798
retval = krb5_unparse_name(context, alias, &acanon);
799
if (retval) {
800
com_err("add_alias", retval,
801
_("while canonicalizing alias principal"));
802
goto cleanup;
803
}
804
retval = krb5_unparse_name(context, target, &tcanon);
805
if (retval) {
806
com_err("add_alias", retval,
807
_("while canonicalizing target principal"));
808
goto cleanup;
809
}
810
retval = kadm5_create_alias(handle, alias, target);
811
if (retval) {
812
com_err("add_alias", retval,
813
_("while aliasing principal \"%s\" to \"%s\""),
814
acanon, tcanon);
815
goto cleanup;
816
}
817
info(_("Principal \"%s\" aliased to \"%s\".\n"), acanon, tcanon);
818
819
cleanup:
820
krb5_free_principal(context, alias);
821
krb5_free_principal(context, target);
822
free(acanon);
823
free(tcanon);
824
}
825
826
static void
827
cpw_usage(const char *str)
828
{
829
if (str)
830
error("%s\n", str);
831
error(_("usage: change_password [-randkey] [-keepold] "
832
"[-e keysaltlist] [-pw password] principal\n"));
833
}
834
835
void
836
kadmin_cpw(int argc, char *argv[], int sci_idx, void *info_ptr)
837
{
838
kadm5_ret_t retval;
839
static char newpw[1024];
840
static char prompt1[1024], prompt2[1024];
841
char *canon = NULL, *pwarg = NULL;
842
int n_ks_tuple = 0, randkey = 0;
843
krb5_boolean keepold = FALSE;
844
krb5_key_salt_tuple *ks_tuple = NULL;
845
krb5_principal princ = NULL;
846
char **db_args = NULL;
847
size_t db_args_size = 0;
848
849
if (argc < 1) {
850
cpw_usage(NULL);
851
return;
852
}
853
for (argv++, argc--; argc > 0 && **argv == '-'; argc--, argv++) {
854
if (!strcmp("-x", *argv)) {
855
argc--;
856
if (argc < 1) {
857
cpw_usage(_("change_password: missing db argument"));
858
goto cleanup;
859
}
860
db_args_size++;
861
db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
862
if (db_args == NULL) {
863
error(_("change_password: Not enough memory\n"));
864
exit(1);
865
}
866
db_args[db_args_size - 1] = *++argv;
867
db_args[db_args_size] = NULL;
868
} else if (!strcmp("-pw", *argv)) {
869
argc--;
870
if (argc < 1) {
871
cpw_usage(_("change_password: missing password arg"));
872
goto cleanup;
873
}
874
pwarg = *++argv;
875
} else if (!strcmp("-randkey", *argv)) {
876
randkey++;
877
} else if (!strcmp("-keepold", *argv)) {
878
keepold = TRUE;
879
} else if (!strcmp("-e", *argv)) {
880
argc--;
881
if (argc < 1) {
882
cpw_usage(_("change_password: missing keysaltlist arg"));
883
goto cleanup;
884
}
885
retval = krb5_string_to_keysalts(*++argv, NULL, NULL, 0,
886
&ks_tuple, &n_ks_tuple);
887
if (retval) {
888
com_err("change_password", retval,
889
_("while parsing keysalts %s"), *argv);
890
goto cleanup;
891
}
892
} else {
893
com_err("change_password", 0, _("unrecognized option %s"), *argv);
894
cpw_usage(NULL);
895
goto cleanup;
896
}
897
}
898
if (argc != 1) {
899
if (argc < 1)
900
com_err("change_password", 0, _("missing principal name"));
901
else
902
com_err("change_password", 0, _("too many arguments"));
903
cpw_usage(NULL);
904
goto cleanup;
905
}
906
retval = kadmin_parse_name(*argv, &princ);
907
if (retval) {
908
com_err("change_password", retval, _("while parsing principal name"));
909
goto cleanup;
910
}
911
retval = krb5_unparse_name(context, princ, &canon);
912
if (retval) {
913
com_err("change_password", retval,
914
_("while canonicalizing principal"));
915
goto cleanup;
916
}
917
if (pwarg != NULL) {
918
if (keepold || ks_tuple != NULL) {
919
retval = kadm5_chpass_principal_3(handle, princ, keepold,
920
n_ks_tuple, ks_tuple, pwarg);
921
} else {
922
retval = kadm5_chpass_principal(handle, princ, pwarg);
923
}
924
if (retval) {
925
com_err("change_password", retval,
926
_("while changing password for \"%s\"."), canon);
927
goto cleanup;
928
}
929
info(_("Password for \"%s\" changed.\n"), canon);
930
} else if (randkey) {
931
retval = randkey_princ(handle, princ, keepold, n_ks_tuple, ks_tuple,
932
NULL, NULL);
933
if (retval) {
934
com_err("change_password", retval,
935
_("while randomizing key for \"%s\"."), canon);
936
goto cleanup;
937
}
938
info(_("Key for \"%s\" randomized.\n"), canon);
939
} else {
940
unsigned int i = sizeof (newpw) - 1;
941
942
snprintf(prompt1, sizeof(prompt1),
943
_("Enter password for principal \"%s\""), canon);
944
snprintf(prompt2, sizeof(prompt2),
945
_("Re-enter password for principal \"%s\""), canon);
946
retval = krb5_read_password(context, prompt1, prompt2,
947
newpw, &i);
948
if (retval) {
949
com_err("change_password", retval,
950
_("while reading password for \"%s\"."), canon);
951
goto cleanup;
952
}
953
if (keepold || ks_tuple != NULL) {
954
retval = kadm5_chpass_principal_3(handle, princ, keepold,
955
n_ks_tuple, ks_tuple,
956
newpw);
957
} else {
958
retval = kadm5_chpass_principal(handle, princ, newpw);
959
}
960
memset(newpw, 0, sizeof (newpw));
961
if (retval) {
962
com_err("change_password", retval,
963
_("while changing password for \"%s\"."), canon);
964
goto cleanup;
965
}
966
info(_("Password for \"%s\" changed.\n"), canon);
967
}
968
cleanup:
969
free(canon);
970
free(db_args);
971
krb5_free_principal(context, princ);
972
free(ks_tuple);
973
}
974
975
static void
976
kadmin_free_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap)
977
{
978
krb5_tl_data *tl_data = *tl_datap, *next;
979
int n_tl_data = *n_tl_datap;
980
int i;
981
982
*n_tl_datap = 0;
983
*tl_datap = NULL;
984
985
for (i = 0; tl_data && (i < n_tl_data); i++) {
986
next = tl_data->tl_data_next;
987
free(tl_data->tl_data_contents);
988
free(tl_data);
989
tl_data = next;
990
}
991
}
992
993
/* Construct a tl_data element and add it to the tail of *tl_datap. */
994
static void
995
add_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap,
996
krb5_int16 tl_type, krb5_ui_2 len, krb5_octet *contents)
997
{
998
krb5_tl_data *tl_data;
999
krb5_octet *copy;
1000
1001
copy = malloc(len);
1002
tl_data = calloc(1, sizeof(*tl_data));
1003
if (copy == NULL || tl_data == NULL) {
1004
error(_("Not enough memory\n"));
1005
exit(1);
1006
}
1007
memcpy(copy, contents, len);
1008
1009
tl_data->tl_data_type = tl_type;
1010
tl_data->tl_data_length = len;
1011
tl_data->tl_data_contents = copy;
1012
tl_data->tl_data_next = NULL;
1013
1014
for (; *tl_datap != NULL; tl_datap = &(*tl_datap)->tl_data_next);
1015
*tl_datap = tl_data;
1016
(*n_tl_datap)++;
1017
}
1018
1019
static void
1020
unlock_princ(kadm5_principal_ent_t princ, long *mask, const char *caller)
1021
{
1022
krb5_error_code retval;
1023
krb5_timestamp now;
1024
krb5_octet timebuf[4];
1025
1026
/* Zero out the failed auth count. */
1027
princ->fail_auth_count = 0;
1028
*mask |= KADM5_FAIL_AUTH_COUNT;
1029
1030
/* Record the timestamp of this unlock operation so that replica KDCs will
1031
* see it, since fail_auth_count is unreplicated. */
1032
retval = krb5_timeofday(context, &now);
1033
if (retval) {
1034
com_err(caller, retval, _("while getting time"));
1035
exit(1);
1036
}
1037
store_32_le((krb5_int32)now, timebuf);
1038
add_tl_data(&princ->n_tl_data, &princ->tl_data,
1039
KRB5_TL_LAST_ADMIN_UNLOCK, 4, timebuf);
1040
*mask |= KADM5_TL_DATA;
1041
}
1042
1043
/*
1044
* Parse addprinc or modprinc arguments. Some output fields may be
1045
* filled in on error.
1046
*/
1047
static int
1048
kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc,
1049
long *mask, char **pass, krb5_boolean *randkey,
1050
krb5_boolean *nokey, krb5_key_salt_tuple **ks_tuple,
1051
int *n_ks_tuple, char *caller)
1052
{
1053
int i;
1054
time_t now, date, interval;
1055
krb5_error_code retval;
1056
1057
*mask = 0;
1058
*pass = NULL;
1059
*n_ks_tuple = 0;
1060
*ks_tuple = NULL;
1061
time(&now);
1062
*randkey = FALSE;
1063
*nokey = FALSE;
1064
for (i = 1; i < argc - 1; i++) {
1065
if (!strcmp("-x",argv[i])) {
1066
if (++i > argc - 2)
1067
return -1;
1068
1069
add_tl_data(&oprinc->n_tl_data, &oprinc->tl_data,
1070
KRB5_TL_DB_ARGS, strlen(argv[i]) + 1,
1071
(krb5_octet *)argv[i]);
1072
*mask |= KADM5_TL_DATA;
1073
continue;
1074
}
1075
if (!strcmp("-expire", argv[i])) {
1076
if (++i > argc - 2)
1077
return -1;
1078
date = parse_date(argv[i], now);
1079
if (date == (time_t)-1)
1080
return -1;
1081
oprinc->princ_expire_time = date;
1082
*mask |= KADM5_PRINC_EXPIRE_TIME;
1083
continue;
1084
}
1085
if (!strcmp("-pwexpire", argv[i])) {
1086
if (++i > argc - 2)
1087
return -1;
1088
date = parse_date(argv[i], now);
1089
if (date == (time_t)-1)
1090
return -1;
1091
oprinc->pw_expiration = date;
1092
*mask |= KADM5_PW_EXPIRATION;
1093
continue;
1094
}
1095
if (!strcmp("-maxlife", argv[i])) {
1096
if (++i > argc - 2)
1097
return -1;
1098
interval = parse_interval(argv[i], now);
1099
if (interval == (time_t)-1)
1100
return -1;
1101
oprinc->max_life = interval;
1102
*mask |= KADM5_MAX_LIFE;
1103
continue;
1104
}
1105
if (!strcmp("-maxrenewlife", argv[i])) {
1106
if (++i > argc - 2)
1107
return -1;
1108
interval = parse_interval(argv[i], now);
1109
if (interval == (time_t)-1)
1110
return -1;
1111
oprinc->max_renewable_life = interval;
1112
*mask |= KADM5_MAX_RLIFE;
1113
continue;
1114
}
1115
if (!strcmp("-kvno", argv[i])) {
1116
if (++i > argc - 2)
1117
return -1;
1118
oprinc->kvno = atoi(argv[i]);
1119
*mask |= KADM5_KVNO;
1120
continue;
1121
}
1122
if (!strcmp("-policy", argv[i])) {
1123
if (++i > argc - 2)
1124
return -1;
1125
oprinc->policy = argv[i];
1126
*mask |= KADM5_POLICY;
1127
continue;
1128
}
1129
if (!strcmp("-clearpolicy", argv[i])) {
1130
oprinc->policy = NULL;
1131
*mask |= KADM5_POLICY_CLR;
1132
continue;
1133
}
1134
if (!strcmp("-pw", argv[i])) {
1135
if (++i > argc - 2)
1136
return -1;
1137
*pass = argv[i];
1138
continue;
1139
}
1140
if (!strcmp("-randkey", argv[i])) {
1141
*randkey = TRUE;
1142
continue;
1143
}
1144
if (!strcmp("-nokey", argv[i])) {
1145
*nokey = TRUE;
1146
continue;
1147
}
1148
if (!strcmp("-unlock", argv[i])) {
1149
unlock_princ(oprinc, mask, caller);
1150
continue;
1151
}
1152
if (!strcmp("-e", argv[i])) {
1153
if (++i > argc - 2)
1154
return -1;
1155
retval = krb5_string_to_keysalts(argv[i], NULL, NULL, 0,
1156
ks_tuple, n_ks_tuple);
1157
if (retval) {
1158
com_err(caller, retval, _("while parsing keysalts %s"),
1159
argv[i]);
1160
return -1;
1161
}
1162
continue;
1163
}
1164
retval = krb5_flagspec_to_mask(argv[i], &oprinc->attributes,
1165
&oprinc->attributes);
1166
if (retval)
1167
return -1;
1168
else
1169
*mask |= KADM5_ATTRIBUTES;
1170
}
1171
if (i != argc - 1)
1172
return -1;
1173
retval = kadmin_parse_name(argv[i], &oprinc->principal);
1174
if (retval) {
1175
com_err(caller, retval, _("while parsing principal"));
1176
return -1;
1177
}
1178
return 0;
1179
}
1180
1181
static void
1182
kadmin_addprinc_usage(void)
1183
{
1184
error(_("usage: add_principal [options] principal\n"));
1185
error(_("\toptions are:\n"));
1186
error(_("\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] "
1187
"[-pwexpire pwexpdate] [-maxlife maxtixlife]\n"
1188
"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
1189
"\t\t[-pw password] [-maxrenewlife maxrenewlife]\n"
1190
"\t\t[-e keysaltlist]\n\t\t[{+|-}attribute]\n"));
1191
error(_("\tattributes are:\n"));
1192
error(_("\t\tallow_postdated allow_forwardable allow_tgs_req "
1193
"allow_renewable\n"
1194
"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
1195
"\t\trequires_hwauth needchange allow_svr "
1196
"password_changing_service\n"
1197
"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
1198
"\t\tlockdown_keys\n"
1199
"\nwhere,\n\t[-x db_princ_args]* - any number of database "
1200
"specific arguments.\n"
1201
"\t\t\tLook at each database documentation for supported "
1202
"arguments\n"));
1203
}
1204
1205
static void
1206
kadmin_modprinc_usage(void)
1207
{
1208
error(_("usage: modify_principal [options] principal\n"));
1209
error(_("\toptions are:\n"));
1210
error(_("\t\t[-x db_princ_args]* [-expire expdate] "
1211
"[-pwexpire pwexpdate] [-maxlife maxtixlife]\n"
1212
"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
1213
"\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n"));
1214
error(_("\tattributes are:\n"));
1215
error(_("\t\tallow_postdated allow_forwardable allow_tgs_req "
1216
"allow_renewable\n"
1217
"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
1218
"\t\trequires_hwauth needchange allow_svr "
1219
"password_changing_service\n"
1220
"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
1221
"\t\tlockdown_keys\n"
1222
"\nwhere,\n\t[-x db_princ_args]* - any number of database "
1223
"specific arguments.\n"
1224
"\t\t\tLook at each database documentation for supported "
1225
"arguments\n"));
1226
}
1227
1228
/* Create a dummy password for old-style (pre-1.8) randkey creation. */
1229
static void
1230
prepare_dummy_password(char *buf, size_t sz)
1231
{
1232
size_t i;
1233
1234
/* Must try to pass any password policy in place, and be valid UTF-8. */
1235
strlcpy(buf, "6F a[", sz);
1236
for (i = strlen(buf); i < sz - 1; i++)
1237
buf[i] = 'a' + (i % 26);
1238
buf[sz - 1] = '\0';
1239
}
1240
1241
void
1242
kadmin_addprinc(int argc, char *argv[], int sci_idx, void *info_ptr)
1243
{
1244
kadm5_principal_ent_rec princ;
1245
long mask;
1246
krb5_boolean randkey = FALSE, nokey = FALSE, old_style_randkey = FALSE;
1247
int n_ks_tuple;
1248
krb5_key_salt_tuple *ks_tuple = NULL;
1249
char *pass, *canon = NULL;
1250
krb5_error_code retval;
1251
char newpw[1024], dummybuf[256];
1252
static char prompt1[1024], prompt2[1024];
1253
1254
/* Zero all fields in request structure */
1255
memset(&princ, 0, sizeof(princ));
1256
1257
princ.attributes = 0;
1258
if (kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass, &randkey,
1259
&nokey, &ks_tuple, &n_ks_tuple,
1260
"add_principal")) {
1261
kadmin_addprinc_usage();
1262
goto cleanup;
1263
}
1264
1265
retval = krb5_unparse_name(context, princ.principal, &canon);
1266
if (retval) {
1267
com_err("add_principal", retval, _("while canonicalizing principal"));
1268
goto cleanup;
1269
}
1270
1271
if (mask & KADM5_POLICY) {
1272
/* Warn if the specified policy does not exist. */
1273
if (!script_mode && !policy_exists(princ.policy)) {
1274
fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"),
1275
princ.policy);
1276
}
1277
} else if (!(mask & KADM5_POLICY_CLR)) {
1278
/* If the policy "default" exists, assign it. */
1279
if (policy_exists("default")) {
1280
if (!script_mode) {
1281
fprintf(stderr, _("No policy specified for %s; "
1282
"assigning \"default\"\n"), canon);
1283
}
1284
princ.policy = "default";
1285
mask |= KADM5_POLICY;
1286
} else if (!script_mode) {
1287
fprintf(stderr, _("No policy specified for %s; "
1288
"defaulting to no policy\n"), canon);
1289
}
1290
}
1291
/* Don't send KADM5_POLICY_CLR to the server. */
1292
mask &= ~KADM5_POLICY_CLR;
1293
1294
if (nokey) {
1295
pass = NULL;
1296
mask |= KADM5_KEY_DATA;
1297
} else if (randkey) {
1298
pass = NULL;
1299
} else if (pass == NULL) {
1300
unsigned int sz = sizeof(newpw) - 1;
1301
1302
snprintf(prompt1, sizeof(prompt1),
1303
_("Enter password for principal \"%s\""), canon);
1304
snprintf(prompt2, sizeof(prompt2),
1305
_("Re-enter password for principal \"%s\""), canon);
1306
retval = krb5_read_password(context, prompt1, prompt2, newpw, &sz);
1307
if (retval) {
1308
com_err("add_principal", retval,
1309
_("while reading password for \"%s\"."), canon);
1310
goto cleanup;
1311
}
1312
pass = newpw;
1313
}
1314
mask |= KADM5_PRINCIPAL;
1315
retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
1316
if (retval == EINVAL && randkey) {
1317
/*
1318
* The server doesn't support randkey creation. Create the principal
1319
* with a dummy password and disallow tickets.
1320
*/
1321
prepare_dummy_password(dummybuf, sizeof(dummybuf));
1322
princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
1323
mask |= KADM5_ATTRIBUTES;
1324
pass = dummybuf;
1325
retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
1326
old_style_randkey = 1;
1327
}
1328
if (retval == KADM5_BAD_MASK && nokey) {
1329
error(_("Admin server does not support -nokey while creating "
1330
"\"%s\"\n"), canon);
1331
goto cleanup;
1332
}
1333
if (retval) {
1334
com_err("add_principal", retval, "while creating \"%s\".", canon);
1335
goto cleanup;
1336
}
1337
if (old_style_randkey) {
1338
/* Randomize the password and re-enable tickets. */
1339
retval = randkey_princ(handle, princ.principal, FALSE, n_ks_tuple,
1340
ks_tuple, NULL, NULL);
1341
if (retval) {
1342
com_err("add_principal", retval,
1343
_("while randomizing key for \"%s\"."), canon);
1344
goto cleanup;
1345
}
1346
princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; /* clear notix */
1347
mask = KADM5_ATTRIBUTES;
1348
retval = kadm5_modify_principal(handle, &princ, mask);
1349
if (retval) {
1350
com_err("add_principal", retval,
1351
_("while clearing DISALLOW_ALL_TIX for \"%s\"."), canon);
1352
goto cleanup;
1353
}
1354
}
1355
info("Principal \"%s\" created.\n", canon);
1356
1357
cleanup:
1358
krb5_free_principal(context, princ.principal);
1359
free(ks_tuple);
1360
free(canon);
1361
kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data);
1362
}
1363
1364
void
1365
kadmin_modprinc(int argc, char *argv[], int sci_idx, void *info_ptr)
1366
{
1367
kadm5_principal_ent_rec princ, oldprinc;
1368
krb5_principal kprinc = NULL;
1369
long mask;
1370
krb5_error_code retval;
1371
char *pass, *canon = NULL;
1372
krb5_boolean randkey = FALSE, nokey = FALSE;
1373
int n_ks_tuple = 0;
1374
krb5_key_salt_tuple *ks_tuple = NULL;
1375
1376
if (argc < 2) {
1377
kadmin_modprinc_usage();
1378
return;
1379
}
1380
1381
memset(&oldprinc, 0, sizeof(oldprinc));
1382
memset(&princ, 0, sizeof(princ));
1383
1384
retval = kadmin_parse_name(argv[argc - 1], &kprinc);
1385
if (retval) {
1386
com_err("modify_principal", retval, _("while parsing principal"));
1387
return;
1388
}
1389
retval = krb5_unparse_name(context, kprinc, &canon);
1390
if (retval) {
1391
com_err("modify_principal", retval,
1392
_("while canonicalizing principal"));
1393
goto cleanup;
1394
}
1395
retval = kadm5_get_principal(handle, kprinc, &oldprinc,
1396
KADM5_PRINCIPAL_NORMAL_MASK);
1397
if (retval) {
1398
com_err("modify_principal", retval, _("while getting \"%s\"."), canon);
1399
goto cleanup;
1400
}
1401
princ.attributes = oldprinc.attributes;
1402
kadm5_free_principal_ent(handle, &oldprinc);
1403
retval = kadmin_parse_princ_args(argc, argv,
1404
&princ, &mask,
1405
&pass, &randkey, &nokey,
1406
&ks_tuple, &n_ks_tuple,
1407
"modify_principal");
1408
if (retval || ks_tuple != NULL || randkey || nokey || pass) {
1409
kadmin_modprinc_usage();
1410
goto cleanup;
1411
}
1412
if (mask & KADM5_POLICY) {
1413
/* Warn if the specified policy does not exist. */
1414
if (!script_mode && !policy_exists(princ.policy)) {
1415
fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"),
1416
princ.policy);
1417
}
1418
}
1419
if (mask) {
1420
/* Skip this if all we're doing is setting certhash. */
1421
retval = kadm5_modify_principal(handle, &princ, mask);
1422
}
1423
if (retval) {
1424
com_err("modify_principal", retval, _("while modifying \"%s\"."),
1425
canon);
1426
goto cleanup;
1427
}
1428
info(_("Principal \"%s\" modified.\n"), canon);
1429
cleanup:
1430
krb5_free_principal(context, kprinc);
1431
krb5_free_principal(context, princ.principal);
1432
kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data);
1433
free(canon);
1434
free(ks_tuple);
1435
}
1436
1437
void
1438
kadmin_getprinc(int argc, char *argv[], int sci_idx, void *info_ptr)
1439
{
1440
kadm5_principal_ent_rec dprinc;
1441
krb5_principal princ = NULL;
1442
krb5_error_code retval;
1443
const char *polname, *noexist;
1444
char *canon = NULL, *princstr = NULL, *modprincstr = NULL;
1445
char **sp = NULL, **attrstrs = NULL;
1446
int i;
1447
1448
if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) {
1449
error(_("usage: get_principal [-terse] principal\n"));
1450
return;
1451
}
1452
1453
memset(&dprinc, 0, sizeof(dprinc));
1454
1455
retval = kadmin_parse_name(argv[argc - 1], &princ);
1456
if (retval) {
1457
com_err("get_principal", retval, _("while parsing principal"));
1458
return;
1459
}
1460
retval = krb5_unparse_name(context, princ, &canon);
1461
if (retval) {
1462
com_err("get_principal", retval, _("while canonicalizing principal"));
1463
goto cleanup;
1464
}
1465
retval = kadm5_get_principal(handle, princ, &dprinc,
1466
KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA);
1467
if (retval) {
1468
com_err("get_principal", retval, _("while retrieving \"%s\"."), canon);
1469
goto cleanup;
1470
}
1471
retval = krb5_unparse_name(context, dprinc.principal, &princstr);
1472
if (retval) {
1473
com_err("get_principal", retval, _("while unparsing principal"));
1474
goto cleanup;
1475
}
1476
retval = krb5_unparse_name(context, dprinc.mod_name, &modprincstr);
1477
if (retval) {
1478
com_err("get_principal", retval, _("while unparsing principal"));
1479
goto cleanup;
1480
}
1481
if (argc == 2) {
1482
printf(_("Principal: %s\n"), princstr);
1483
printf(_("Expiration date: %s\n"), dprinc.princ_expire_time ?
1484
strdate(dprinc.princ_expire_time) : _("[never]"));
1485
printf(_("Last password change: %s\n"), dprinc.last_pwd_change ?
1486
strdate(dprinc.last_pwd_change) : _("[never]"));
1487
printf(_("Password expiration date: %s\n"),
1488
dprinc.pw_expiration ?
1489
strdate(dprinc.pw_expiration) : _("[never]"));
1490
printf(_("Maximum ticket life: %s\n"), strdur(dprinc.max_life));
1491
printf(_("Maximum renewable life: %s\n"),
1492
strdur(dprinc.max_renewable_life));
1493
printf(_("Last modified: %s (%s)\n"), strdate(dprinc.mod_date),
1494
modprincstr);
1495
printf(_("Last successful authentication: %s\n"),
1496
dprinc.last_success ? strdate(dprinc.last_success) :
1497
_("[never]"));
1498
printf("Last failed authentication: %s\n",
1499
dprinc.last_failed ? strdate(dprinc.last_failed) :
1500
"[never]");
1501
printf(_("Failed password attempts: %d\n"),
1502
dprinc.fail_auth_count);
1503
printf(_("Number of keys: %d\n"), dprinc.n_key_data);
1504
for (i = 0; i < dprinc.n_key_data; i++) {
1505
krb5_key_data *key_data = &dprinc.key_data[i];
1506
char enctype[BUFSIZ], salttype[BUFSIZ];
1507
char *deprecated = "";
1508
1509
if (krb5_enctype_to_name(key_data->key_data_type[0], FALSE,
1510
enctype, sizeof(enctype)))
1511
snprintf(enctype, sizeof(enctype), _("<Encryption type 0x%x>"),
1512
key_data->key_data_type[0]);
1513
if (!krb5_c_valid_enctype(key_data->key_data_type[0]))
1514
deprecated = "UNSUPPORTED:";
1515
else if (krb5int_c_deprecated_enctype(key_data->key_data_type[0]))
1516
deprecated = "DEPRECATED:";
1517
printf("Key: vno %d, %s%s", key_data->key_data_kvno, deprecated,
1518
enctype);
1519
if (key_data->key_data_ver > 1 &&
1520
key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_NORMAL) {
1521
if (krb5_salttype_to_string(key_data->key_data_type[1],
1522
salttype, sizeof(salttype)))
1523
snprintf(salttype, sizeof(salttype), _("<Salt type 0x%x>"),
1524
key_data->key_data_type[1]);
1525
printf(":%s", salttype);
1526
}
1527
printf("\n");
1528
}
1529
printf(_("MKey: vno %d\n"), dprinc.mkvno);
1530
1531
printf(_("Attributes:"));
1532
retval = krb5_flags_to_strings(dprinc.attributes, &attrstrs);
1533
if (retval) {
1534
com_err("get_principal", retval, _("while printing flags"));
1535
return;
1536
}
1537
for (sp = attrstrs; sp != NULL && *sp != NULL; sp++) {
1538
printf(" %s", *sp);
1539
free(*sp);
1540
}
1541
free(attrstrs);
1542
printf("\n");
1543
polname = (dprinc.policy != NULL) ? dprinc.policy : _("[none]");
1544
noexist = (dprinc.policy != NULL && !policy_exists(dprinc.policy)) ?
1545
_(" [does not exist]") : "";
1546
printf(_("Policy: %s%s\n"), polname, noexist);
1547
} else {
1548
printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\""
1549
"\t%d\t%d\t%d\t%d\t%d",
1550
princstr, dprinc.princ_expire_time, dprinc.last_pwd_change,
1551
dprinc.pw_expiration, dprinc.max_life, modprincstr,
1552
dprinc.mod_date, dprinc.attributes, dprinc.kvno,
1553
dprinc.mkvno, dprinc.policy ? dprinc.policy : "[none]",
1554
dprinc.max_renewable_life, dprinc.last_success,
1555
dprinc.last_failed, dprinc.fail_auth_count,
1556
dprinc.n_key_data);
1557
for (i = 0; i < dprinc.n_key_data; i++)
1558
printf("\t%d\t%d\t%d\t%d",
1559
dprinc.key_data[i].key_data_ver,
1560
dprinc.key_data[i].key_data_kvno,
1561
dprinc.key_data[i].key_data_type[0],
1562
dprinc.key_data[i].key_data_type[1]);
1563
printf("\n");
1564
}
1565
cleanup:
1566
krb5_free_principal(context, princ);
1567
kadm5_free_principal_ent(handle, &dprinc);
1568
free(canon);
1569
free(princstr);
1570
free(modprincstr);
1571
}
1572
1573
void
1574
kadmin_getprincs(int argc, char *argv[], int sci_idx, void *info_ptr)
1575
{
1576
krb5_error_code retval;
1577
char *expr, **names;
1578
int i, count;
1579
1580
expr = NULL;
1581
if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) {
1582
error(_("usage: get_principals [expression]\n"));
1583
return;
1584
}
1585
retval = kadm5_get_principals(handle, expr, &names, &count);
1586
if (retval) {
1587
com_err("get_principals", retval, _("while retrieving list."));
1588
return;
1589
}
1590
for (i = 0; i < count; i++)
1591
printf("%s\n", names[i]);
1592
kadm5_free_name_list(handle, names, count);
1593
}
1594
1595
static int
1596
kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy,
1597
long *mask, char *caller)
1598
{
1599
krb5_error_code retval;
1600
int i;
1601
time_t now, interval;
1602
1603
time(&now);
1604
*mask = 0;
1605
for (i = 1; i < argc - 1; i++) {
1606
if (!strcmp(argv[i], "-maxlife")) {
1607
if (++i > argc -2)
1608
return -1;
1609
interval = parse_interval(argv[i], now);
1610
if (interval == (time_t)-1)
1611
return -1;
1612
policy->pw_max_life = interval;
1613
*mask |= KADM5_PW_MAX_LIFE;
1614
continue;
1615
} else if (!strcmp(argv[i], "-minlife")) {
1616
if (++i > argc - 2)
1617
return -1;
1618
interval = parse_interval(argv[i], now);
1619
if (interval == (time_t)-1)
1620
return -1;
1621
policy->pw_min_life = interval;
1622
*mask |= KADM5_PW_MIN_LIFE;
1623
continue;
1624
} else if (!strcmp(argv[i], "-minlength")) {
1625
if (++i > argc - 2)
1626
return -1;
1627
policy->pw_min_length = atoi(argv[i]);
1628
*mask |= KADM5_PW_MIN_LENGTH;
1629
continue;
1630
} else if (!strcmp(argv[i], "-minclasses")) {
1631
if (++i > argc - 2)
1632
return -1;
1633
policy->pw_min_classes = atoi(argv[i]);
1634
*mask |= KADM5_PW_MIN_CLASSES;
1635
continue;
1636
} else if (!strcmp(argv[i], "-history")) {
1637
if (++i > argc - 2)
1638
return -1;
1639
policy->pw_history_num = atoi(argv[i]);
1640
*mask |= KADM5_PW_HISTORY_NUM;
1641
continue;
1642
} else if (strlen(argv[i]) == 11 &&
1643
!strcmp(argv[i], "-maxfailure")) {
1644
if (++i > argc - 2)
1645
return -1;
1646
policy->pw_max_fail = atoi(argv[i]);
1647
*mask |= KADM5_PW_MAX_FAILURE;
1648
continue;
1649
} else if (strlen(argv[i]) == 21 &&
1650
!strcmp(argv[i], "-failurecountinterval")) {
1651
if (++i > argc - 2)
1652
return -1;
1653
interval = parse_interval(argv[i], now);
1654
if (interval == (time_t)-1)
1655
return -1;
1656
policy->pw_failcnt_interval = interval;
1657
*mask |= KADM5_PW_FAILURE_COUNT_INTERVAL;
1658
continue;
1659
} else if (strlen(argv[i]) == 16 &&
1660
!strcmp(argv[i], "-lockoutduration")) {
1661
if (++i > argc - 2)
1662
return -1;
1663
interval = parse_interval(argv[i], now);
1664
if (interval == (time_t)-1)
1665
return -1;
1666
policy->pw_lockout_duration = interval;
1667
*mask |= KADM5_PW_LOCKOUT_DURATION;
1668
continue;
1669
} else if (!strcmp(argv[i], "-allowedkeysalts")) {
1670
krb5_key_salt_tuple *ks_tuple = NULL;
1671
int n_ks_tuple = 0;
1672
1673
if (++i > argc - 2)
1674
return -1;
1675
if (strcmp(argv[i], "-")) {
1676
retval = krb5_string_to_keysalts(argv[i], ",", NULL, 0,
1677
&ks_tuple, &n_ks_tuple);
1678
if (retval) {
1679
com_err(caller, retval, _("while parsing keysalts %s"),
1680
argv[i]);
1681
return -1;
1682
}
1683
free(ks_tuple);
1684
policy->allowed_keysalts = argv[i];
1685
}
1686
*mask |= KADM5_POLICY_ALLOWED_KEYSALTS;
1687
continue;
1688
} else
1689
return -1;
1690
}
1691
if (i != argc -1) {
1692
error(_("%s: parser lost count!\n"), caller);
1693
return -1;
1694
} else
1695
return 0;
1696
}
1697
1698
static void
1699
kadmin_addmodpol_usage(char *func)
1700
{
1701
error(_("usage; %s [options] policy\n"), func);
1702
error(_("\toptions are:\n"));
1703
error(_("\t\t[-maxlife time] [-minlife time] [-minlength length]\n"
1704
"\t\t[-minclasses number] [-history number]\n"
1705
"\t\t[-maxfailure number] [-failurecountinterval time]\n"
1706
"\t\t[-allowedkeysalts keysalts]\n"));
1707
error(_("\t\t[-lockoutduration time]\n"));
1708
}
1709
1710
void
1711
kadmin_addpol(int argc, char *argv[], int sci_idx, void *info_ptr)
1712
{
1713
krb5_error_code retval;
1714
long mask;
1715
kadm5_policy_ent_rec policy;
1716
1717
memset(&policy, 0, sizeof(policy));
1718
if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) {
1719
kadmin_addmodpol_usage("add_policy");
1720
return;
1721
}
1722
policy.policy = argv[argc - 1];
1723
mask |= KADM5_POLICY;
1724
retval = kadm5_create_policy(handle, &policy, mask);
1725
if (retval) {
1726
com_err("add_policy", retval, _("while creating policy \"%s\"."),
1727
policy.policy);
1728
}
1729
}
1730
1731
void
1732
kadmin_modpol(int argc, char *argv[], int sci_idx, void *info_ptr)
1733
{
1734
krb5_error_code retval;
1735
long mask;
1736
kadm5_policy_ent_rec policy;
1737
1738
memset(&policy, 0, sizeof(policy));
1739
if (kadmin_parse_policy_args(argc, argv, &policy, &mask,
1740
"modify_policy")) {
1741
kadmin_addmodpol_usage("modify_policy");
1742
return;
1743
}
1744
policy.policy = argv[argc - 1];
1745
retval = kadm5_modify_policy(handle, &policy, mask);
1746
if (retval) {
1747
com_err("modify_policy", retval, _("while modifying policy \"%s\"."),
1748
policy.policy);
1749
}
1750
}
1751
1752
void
1753
kadmin_delpol(int argc, char *argv[], int sci_idx, void *info_ptr)
1754
{
1755
krb5_error_code retval;
1756
char reply[5];
1757
1758
if (!(argc == 2 || (argc == 3 && !strcmp("-force", argv[1])))) {
1759
error(_("usage: delete_policy [-force] policy\n"));
1760
return;
1761
}
1762
if (argc == 2 && !script_mode) {
1763
printf(_("Are you sure you want to delete the policy \"%s\"? "
1764
"(yes/no): "), argv[1]);
1765
fgets(reply, sizeof(reply), stdin);
1766
if (strcmp("yes\n", reply)) {
1767
fprintf(stderr, _("Policy \"%s\" not deleted.\n"), argv[1]);
1768
return;
1769
}
1770
}
1771
retval = kadm5_delete_policy(handle, argv[argc - 1]);
1772
if (retval) {
1773
com_err("delete_policy:", retval, _("while deleting policy \"%s\""),
1774
argv[argc - 1]);
1775
}
1776
}
1777
1778
void
1779
kadmin_getpol(int argc, char *argv[], int sci_idx, void *info_ptr)
1780
{
1781
krb5_error_code retval;
1782
kadm5_policy_ent_rec policy;
1783
1784
if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) {
1785
error(_("usage: get_policy [-terse] policy\n"));
1786
return;
1787
}
1788
retval = kadm5_get_policy(handle, argv[argc - 1], &policy);
1789
if (retval) {
1790
com_err("get_policy", retval, _("while retrieving policy \"%s\"."),
1791
argv[argc - 1]);
1792
return;
1793
}
1794
if (argc == 2) {
1795
printf(_("Policy: %s\n"), policy.policy);
1796
printf(_("Maximum password life: %s\n"), strdur(policy.pw_max_life));
1797
printf(_("Minimum password life: %s\n"), strdur(policy.pw_min_life));
1798
printf(_("Minimum password length: %ld\n"), policy.pw_min_length);
1799
printf(_("Minimum number of password character classes: %ld\n"),
1800
policy.pw_min_classes);
1801
printf(_("Number of old keys kept: %ld\n"), policy.pw_history_num);
1802
printf(_("Maximum password failures before lockout: %lu\n"),
1803
(unsigned long)policy.pw_max_fail);
1804
printf(_("Password failure count reset interval: %s\n"),
1805
strdur(policy.pw_failcnt_interval));
1806
printf(_("Password lockout duration: %s\n"),
1807
strdur(policy.pw_lockout_duration));
1808
if (policy.allowed_keysalts != NULL)
1809
printf(_("Allowed key/salt types: %s\n"), policy.allowed_keysalts);
1810
} else {
1811
/* Output 0 where we used to output policy_refcnt. */
1812
printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t0\t%lu\t%ld\t%ld\t%s\n",
1813
policy.policy, policy.pw_max_life, policy.pw_min_life,
1814
policy.pw_min_length, policy.pw_min_classes,
1815
policy.pw_history_num, (unsigned long)policy.pw_max_fail,
1816
(long)policy.pw_failcnt_interval,
1817
(long)policy.pw_lockout_duration,
1818
(policy.allowed_keysalts == NULL) ? "-" :
1819
policy.allowed_keysalts);
1820
}
1821
kadm5_free_policy_ent(handle, &policy);
1822
}
1823
1824
void
1825
kadmin_getpols(int argc, char *argv[], int sci_idx, void *info_ptr)
1826
{
1827
krb5_error_code retval;
1828
char *expr, **names;
1829
int i, count;
1830
1831
expr = NULL;
1832
if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) {
1833
error(_("usage: get_policies [expression]\n"));
1834
return;
1835
}
1836
retval = kadm5_get_policies(handle, expr, &names, &count);
1837
if (retval) {
1838
com_err("get_policies", retval, _("while retrieving list."));
1839
return;
1840
}
1841
for (i = 0; i < count; i++)
1842
printf("%s\n", names[i]);
1843
kadm5_free_name_list(handle, names, count);
1844
}
1845
1846
void
1847
kadmin_getprivs(int argc, char *argv[], int sci_idx, void *info_ptr)
1848
{
1849
static char *privs[] = {"INQUIRE", "ADD", "MODIFY", "DELETE"};
1850
krb5_error_code retval;
1851
size_t i;
1852
long plist;
1853
1854
if (argc != 1) {
1855
error(_("usage: get_privs\n"));
1856
return;
1857
}
1858
retval = kadm5_get_privs(handle, &plist);
1859
if (retval) {
1860
com_err("get_privs", retval, _("while retrieving privileges"));
1861
return;
1862
}
1863
printf(_("current privileges:"));
1864
for (i = 0; i < sizeof (privs) / sizeof (char *); i++) {
1865
if (plist & 1 << i)
1866
printf(" %s", privs[i]);
1867
}
1868
printf("\n");
1869
}
1870
1871
void
1872
kadmin_purgekeys(int argc, char *argv[], int sci_idx, void *info_ptr)
1873
{
1874
kadm5_ret_t retval;
1875
int keepkvno = -1;
1876
char *pname = NULL, *canon = NULL;
1877
krb5_principal princ;
1878
1879
if (argc == 4 && strcmp(argv[1], "-keepkvno") == 0) {
1880
keepkvno = atoi(argv[2]);
1881
pname = argv[3];
1882
} else if (argc == 3 && strcmp(argv[1], "-all") == 0) {
1883
keepkvno = KRB5_INT32_MAX;
1884
pname = argv[2];
1885
} else if (argc == 2) {
1886
pname = argv[1];
1887
}
1888
if (pname == NULL) {
1889
error(_("usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] "
1890
"principal\n"));
1891
return;
1892
}
1893
1894
retval = kadmin_parse_name(pname, &princ);
1895
if (retval) {
1896
com_err("purgekeys", retval, _("while parsing principal"));
1897
return;
1898
}
1899
1900
retval = krb5_unparse_name(context, princ, &canon);
1901
if (retval) {
1902
com_err("purgekeys", retval, _("while canonicalizing principal"));
1903
goto cleanup;
1904
}
1905
1906
retval = kadm5_purgekeys(handle, princ, keepkvno);
1907
if (retval) {
1908
com_err("purgekeys", retval,
1909
_("while purging keys for principal \"%s\""), canon);
1910
goto cleanup;
1911
}
1912
1913
if (keepkvno == KRB5_INT32_MAX)
1914
info(_("All keys for principal \"%s\" removed.\n"), canon);
1915
else
1916
info(_("Old keys for principal \"%s\" purged.\n"), canon);
1917
cleanup:
1918
krb5_free_principal(context, princ);
1919
free(canon);
1920
return;
1921
}
1922
1923
void
1924
kadmin_getstrings(int argc, char *argv[], int sci_idx, void *info_ptr)
1925
{
1926
kadm5_ret_t retval;
1927
char *pname, *canon = NULL;
1928
krb5_principal princ = NULL;
1929
krb5_string_attr *strings = NULL;
1930
int count, i;
1931
1932
if (argc != 2) {
1933
error(_("usage: get_strings principal\n"));
1934
return;
1935
}
1936
pname = argv[1];
1937
1938
retval = kadmin_parse_name(pname, &princ);
1939
if (retval) {
1940
com_err("get_strings", retval, _("while parsing principal"));
1941
return;
1942
}
1943
1944
retval = krb5_unparse_name(context, princ, &canon);
1945
if (retval) {
1946
com_err("get_strings", retval, _("while canonicalizing principal"));
1947
goto cleanup;
1948
}
1949
1950
retval = kadm5_get_strings(handle, princ, &strings, &count);
1951
if (retval) {
1952
com_err("get_strings", retval,
1953
_("while getting attributes for principal \"%s\""), canon);
1954
goto cleanup;
1955
}
1956
1957
if (count == 0)
1958
printf(_("(No string attributes.)\n"));
1959
for (i = 0; i < count; i++)
1960
printf("%s: %s\n", strings[i].key, strings[i].value);
1961
kadm5_free_strings(handle, strings, count);
1962
1963
cleanup:
1964
krb5_free_principal(context, princ);
1965
free(canon);
1966
return;
1967
}
1968
1969
void
1970
kadmin_setstring(int argc, char *argv[], int sci_idx, void *info_ptr)
1971
{
1972
kadm5_ret_t retval;
1973
char *pname, *canon = NULL, *key, *value;
1974
krb5_principal princ = NULL;
1975
1976
if (argc != 4) {
1977
error(_("usage: set_string principal key value\n"));
1978
return;
1979
}
1980
pname = argv[1];
1981
key = argv[2];
1982
value = argv[3];
1983
1984
retval = kadmin_parse_name(pname, &princ);
1985
if (retval) {
1986
com_err("set_string", retval, _("while parsing principal"));
1987
return;
1988
}
1989
1990
retval = krb5_unparse_name(context, princ, &canon);
1991
if (retval) {
1992
com_err("set_string", retval, _("while canonicalizing principal"));
1993
goto cleanup;
1994
}
1995
1996
retval = kadm5_set_string(handle, princ, key, value);
1997
if (retval) {
1998
com_err("set_string", retval,
1999
_("while setting attribute on principal \"%s\""), canon);
2000
goto cleanup;
2001
}
2002
2003
info(_("Attribute set for principal \"%s\".\n"), canon);
2004
cleanup:
2005
krb5_free_principal(context, princ);
2006
free(canon);
2007
return;
2008
}
2009
2010
void
2011
kadmin_delstring(int argc, char *argv[], int sci_idx, void *info_ptr)
2012
{
2013
kadm5_ret_t retval;
2014
char *pname, *canon = NULL, *key;
2015
krb5_principal princ = NULL;
2016
2017
if (argc != 3) {
2018
error(_("usage: del_string principal key\n"));
2019
return;
2020
}
2021
pname = argv[1];
2022
key = argv[2];
2023
2024
retval = kadmin_parse_name(pname, &princ);
2025
if (retval) {
2026
com_err("delstring", retval, _("while parsing principal"));
2027
return;
2028
}
2029
2030
retval = krb5_unparse_name(context, princ, &canon);
2031
if (retval) {
2032
com_err("del_string", retval, _("while canonicalizing principal"));
2033
goto cleanup;
2034
}
2035
2036
retval = kadm5_set_string(handle, princ, key, NULL);
2037
if (retval) {
2038
com_err("del_string", retval,
2039
_("while deleting attribute from principal \"%s\""), canon);
2040
goto cleanup;
2041
}
2042
2043
info(_("Attribute removed from principal \"%s\".\n"), canon);
2044
cleanup:
2045
krb5_free_principal(context, princ);
2046
free(canon);
2047
return;
2048
}
2049
2050