2 * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "kadmin_locl.h"
35 #include "kadmin-commands.h"
38 add_tl(kadm5_principal_ent_rec
*princ
, int type
, krb5_data
*data
)
40 krb5_tl_data
*tl
, **ptl
;
42 tl
= ecalloc(1, sizeof(*tl
));
43 tl
->tl_data_next
= NULL
;
44 tl
->tl_data_type
= type
;
45 tl
->tl_data_length
= data
->length
;
46 tl
->tl_data_contents
= data
->data
;
48 if (tl
->tl_data_length
< 0 || data
->length
!= (size_t)tl
->tl_data_length
)
49 errx(1, "TL data overflow");
52 ptl
= &princ
->tl_data
;
54 ptl
= &(*ptl
)->tl_data_next
;
61 * Find a TL data of type KRB5_TL_EXTENSION that has an extension of type
65 get_tl(kadm5_principal_ent_rec
*princ
, int type
)
67 krb5_tl_data
*tl
= princ
->tl_data
;
69 while (tl
&& tl
->tl_data_type
!= type
)
70 tl
= tl
->tl_data_next
;
75 add_constrained_delegation(krb5_context contextp
,
76 kadm5_principal_ent_rec
*princ
,
77 struct getarg_strings
*strings
)
84 memset(&ext
, 0, sizeof(ext
));
85 ext
.mandatory
= FALSE
;
86 ext
.data
.element
= choice_HDB_extension_data_allowed_to_delegate_to
;
88 if (strings
->num_strings
== 1 && strings
->strings
[0][0] == '\0') {
89 ext
.data
.u
.allowed_to_delegate_to
.val
= NULL
;
90 ext
.data
.u
.allowed_to_delegate_to
.len
= 0;
95 ext
.data
.u
.allowed_to_delegate_to
.val
=
96 calloc(strings
->num_strings
,
97 sizeof(ext
.data
.u
.allowed_to_delegate_to
.val
[0]));
98 ext
.data
.u
.allowed_to_delegate_to
.len
= strings
->num_strings
;
100 for (i
= 0; i
< strings
->num_strings
; i
++) {
101 ret
= krb5_parse_name(contextp
, strings
->strings
[i
], &p
);
104 ret
= copy_Principal(p
, &ext
.data
.u
.allowed_to_delegate_to
.val
[i
]);
107 krb5_free_principal(contextp
, p
);
111 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
113 free_HDB_extension(&ext
);
116 if (buf
.length
!= size
)
119 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
123 add_aliases(krb5_context contextp
, kadm5_principal_ent_rec
*princ
,
124 struct getarg_strings
*strings
)
126 krb5_error_code ret
= 0;
133 memset(&ext
, 0, sizeof(ext
));
134 ext
.mandatory
= FALSE
;
135 ext
.data
.element
= choice_HDB_extension_data_aliases
;
136 ext
.data
.u
.aliases
.case_insensitive
= 0;
138 if (strings
->num_strings
== 1 && strings
->strings
[0][0] == '\0') {
139 ext
.data
.u
.aliases
.aliases
.val
= NULL
;
140 ext
.data
.u
.aliases
.aliases
.len
= 0;
142 ext
.data
.u
.aliases
.aliases
.val
=
143 calloc(strings
->num_strings
,
144 sizeof(ext
.data
.u
.aliases
.aliases
.val
[0]));
145 ext
.data
.u
.aliases
.aliases
.len
= strings
->num_strings
;
147 for (i
= 0; ret
== 0 && i
< strings
->num_strings
; i
++) {
148 ret
= krb5_parse_name(contextp
, strings
->strings
[i
], &p
);
150 krb5_err(contextp
, 1, ret
, "Could not parse alias %s",
151 strings
->strings
[i
]);
153 ret
= copy_Principal(p
, &ext
.data
.u
.aliases
.aliases
.val
[i
]);
155 krb5_err(contextp
, 1, ret
, "Could not copy parsed alias %s",
156 strings
->strings
[i
]);
157 krb5_free_principal(contextp
, p
);
161 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
163 free_HDB_extension(&ext
);
166 if (buf
.length
!= size
)
169 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
173 add_pkinit_acl(krb5_context contextp
, kadm5_principal_ent_rec
*princ
,
174 struct getarg_strings
*strings
)
182 memset(&ext
, 0, sizeof(ext
));
183 ext
.mandatory
= FALSE
;
184 ext
.data
.element
= choice_HDB_extension_data_pkinit_acl
;
185 ext
.data
.u
.aliases
.case_insensitive
= 0;
187 if (strings
->num_strings
== 1 && strings
->strings
[0][0] == '\0') {
188 ext
.data
.u
.pkinit_acl
.val
= NULL
;
189 ext
.data
.u
.pkinit_acl
.len
= 0;
191 ext
.data
.u
.pkinit_acl
.val
=
192 calloc(strings
->num_strings
,
193 sizeof(ext
.data
.u
.pkinit_acl
.val
[0]));
194 ext
.data
.u
.pkinit_acl
.len
= strings
->num_strings
;
196 for (i
= 0; i
< strings
->num_strings
; i
++) {
197 ext
.data
.u
.pkinit_acl
.val
[i
].subject
= estrdup(strings
->strings
[i
]);
201 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
203 free_HDB_extension(&ext
);
206 if (buf
.length
!= size
)
209 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
212 static krb5_error_code
213 add_etypes(krb5_context contextp
,
214 kadm5_principal_ent_rec
*princ
,
215 struct getarg_strings
*strings
)
217 krb5_error_code ret
= 0;
218 HDB_EncTypeList etypes
;
222 etypes
.len
= strings
->num_strings
;
223 if ((etypes
.val
= calloc(strings
->num_strings
,
224 sizeof(etypes
.val
[0]))) == NULL
)
225 krb5_err(contextp
, 1, ret
, "Out of memory");
227 for (i
= 0; i
< strings
->num_strings
; i
++) {
230 ret
= krb5_string_to_enctype(contextp
, strings
->strings
[i
], &etype
);
232 krb5_warn(contextp
, ret
, "Could not parse enctype %s",
233 strings
->strings
[i
]);
237 etypes
.val
[i
] = etype
;
241 ASN1_MALLOC_ENCODE(HDB_EncTypeList
, buf
.data
, buf
.length
,
242 &etypes
, &size
, ret
);
244 if (ret
|| buf
.length
!= size
)
246 add_tl(princ
, KRB5_TL_ETYPES
, &buf
);
252 add_kvno_diff(krb5_context contextp
, kadm5_principal_ent_rec
*princ
,
253 int is_svc_diff
, krb5_kvno kvno_diff
)
262 if (kvno_diff
> 2048)
266 ext
.data
.element
= choice_HDB_extension_data_hist_kvno_diff_svc
;
267 ext
.data
.u
.hist_kvno_diff_svc
= (unsigned int)kvno_diff
;
269 ext
.data
.element
= choice_HDB_extension_data_hist_kvno_diff_clnt
;
270 ext
.data
.u
.hist_kvno_diff_clnt
= (unsigned int)kvno_diff
;
272 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
276 if (buf
.length
!= size
)
279 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
283 add_krb5_config(kadm5_principal_ent_rec
*princ
, const char *fname
)
290 memset(&ext
, 0, sizeof(ext
));
291 ext
.mandatory
= FALSE
;
292 ext
.data
.element
= choice_HDB_extension_data_krb5_config
;
294 if ((ret
= rk_undumpdata(fname
,
295 &ext
.data
.u
.krb5_config
.data
,
296 &ext
.data
.u
.krb5_config
.length
))) {
297 krb5_warn(context
, ret
, "Could not read %s", fname
);
301 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
303 free_HDB_extension(&ext
);
306 if (buf
.length
!= size
)
308 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
312 do_mod_entry(krb5_principal principal
, void *data
)
315 kadm5_principal_ent_rec princ
;
317 struct modify_options
*e
= data
;
319 memset (&princ
, 0, sizeof(princ
));
320 ret
= kadm5_get_principal(kadm_handle
, principal
, &princ
,
321 KADM5_PRINCIPAL
| KADM5_ATTRIBUTES
|
322 KADM5_MAX_LIFE
| KADM5_MAX_RLIFE
|
323 KADM5_PRINC_EXPIRE_TIME
|
324 KADM5_PW_EXPIRATION
);
328 if(e
->max_ticket_life_string
||
329 e
->max_renewable_life_string
||
330 e
->expiration_time_string
||
331 e
->pw_expiration_time_string
||
332 e
->attributes_string
||
334 e
->kvno_integer
!= -1 ||
335 e
->service_enctypes_strings
.num_strings
||
336 e
->constrained_delegation_strings
.num_strings
||
337 e
->alias_strings
.num_strings
||
338 e
->pkinit_acl_strings
.num_strings
||
339 e
->krb5_config_file_string
||
340 e
->hist_kvno_diff_clnt_integer
!= -1 ||
341 e
->hist_kvno_diff_svc_integer
!= -1) {
342 ret
= set_entry(context
, &princ
, &mask
,
343 e
->max_ticket_life_string
,
344 e
->max_renewable_life_string
,
345 e
->expiration_time_string
,
346 e
->pw_expiration_time_string
,
347 e
->attributes_string
,
349 if(e
->kvno_integer
!= -1) {
350 princ
.kvno
= e
->kvno_integer
;
353 if (e
->constrained_delegation_strings
.num_strings
) {
354 add_constrained_delegation(context
, &princ
,
355 &e
->constrained_delegation_strings
);
356 mask
|= KADM5_TL_DATA
;
358 if (e
->alias_strings
.num_strings
) {
359 add_aliases(context
, &princ
, &e
->alias_strings
);
360 mask
|= KADM5_TL_DATA
;
362 if (e
->pkinit_acl_strings
.num_strings
) {
363 add_pkinit_acl(context
, &princ
, &e
->pkinit_acl_strings
);
364 mask
|= KADM5_TL_DATA
;
366 if (e
->service_enctypes_strings
.num_strings
) {
367 ret
= add_etypes(context
, &princ
, &e
->service_enctypes_strings
);
368 mask
|= KADM5_TL_DATA
;
370 if (e
->hist_kvno_diff_clnt_integer
!= -1) {
371 add_kvno_diff(context
, &princ
, 0, e
->hist_kvno_diff_clnt_integer
);
372 mask
|= KADM5_TL_DATA
;
374 if (e
->hist_kvno_diff_svc_integer
!= -1) {
375 add_kvno_diff(context
, &princ
, 1, e
->hist_kvno_diff_svc_integer
);
376 mask
|= KADM5_TL_DATA
;
378 if (e
->krb5_config_file_string
) {
379 add_krb5_config(&princ
, e
->krb5_config_file_string
);
380 mask
|= KADM5_TL_DATA
;
383 ret
= edit_entry(&princ
, &mask
, NULL
, 0);
385 ret
= kadm5_modify_principal(kadm_handle
, &princ
, mask
);
387 krb5_warn(context
, ret
, "kadm5_modify_principal");
390 kadm5_free_principal_ent(kadm_handle
, &princ
);
395 mod_entry(struct modify_options
*opt
, int argc
, char **argv
)
397 krb5_error_code ret
= 0;
400 for(i
= 0; i
< argc
; i
++) {
401 ret
= foreach_principal(argv
[i
], do_mod_entry
, "mod", opt
);
409 do_mod_ns_entry(krb5_principal principal
, void *data
)
412 kadm5_principal_ent_rec princ
;
414 struct modify_namespace_options
*e
= data
;
416 memset (&princ
, 0, sizeof(princ
));
417 ret
= kadm5_get_principal(kadm_handle
, principal
, &princ
,
418 KADM5_PRINCIPAL
| KADM5_ATTRIBUTES
|
419 KADM5_MAX_LIFE
| KADM5_MAX_RLIFE
|
420 KADM5_PRINC_EXPIRE_TIME
|
421 KADM5_PW_EXPIRATION
);
425 if(e
->max_ticket_life_string
||
426 e
->max_renewable_life_string
||
427 e
->attributes_string
||
428 e
->enctypes_strings
.num_strings
||
429 e
->krb5_config_file_string
) {
430 ret
= set_entry(context
, &princ
, &mask
, e
->max_ticket_life_string
,
431 e
->max_renewable_life_string
, NULL
, NULL
,
432 e
->attributes_string
, NULL
);
433 if (e
->enctypes_strings
.num_strings
) {
434 ret
= add_etypes(context
, &princ
, &e
->enctypes_strings
);
435 mask
|= KADM5_TL_DATA
;
437 if (e
->krb5_config_file_string
) {
438 add_krb5_config(&princ
, e
->krb5_config_file_string
);
439 mask
|= KADM5_TL_DATA
;
442 ret
= edit_entry(&princ
, &mask
, NULL
, 0);
444 ret
= kadm5_modify_principal(kadm_handle
, &princ
, mask
);
446 krb5_warn(context
, ret
, "kadm5_modify_principal");
449 kadm5_free_principal_ent(kadm_handle
, &princ
);
454 modify_namespace(struct modify_namespace_options
*opt
, int argc
, char **argv
)
456 krb5_error_code ret
= 0;
459 for(i
= 0; i
< argc
; i
++) {
460 ret
= foreach_principal(argv
[i
], do_mod_ns_entry
, "mod_ns", opt
);
468 struct modify_namespace_key_rotation_options
{
470 int keep_base_key_flag
;
471 char* revoke_old_string
;
472 char* new_key_rotation_epoch_string
;
473 char* new_key_rotation_period_string
;
478 princ2kstuple(kadm5_principal_ent_rec
*princ
,
480 krb5_key_salt_tuple
**kstuple
,
483 krb5_error_code ret
= 0;
484 HDB_EncTypeList etypes
;
492 for (tl
= princ
->tl_data
; tl
; tl
= tl
->tl_data_next
) {
493 if (tl
->tl_data_type
!= KRB5_TL_ETYPES
|| tl
->tl_data_length
< 0)
495 ret
= decode_HDB_EncTypeList(tl
->tl_data_contents
, tl
->tl_data_length
,
499 *nkstuple
= etypes
.len
;
500 *kstuple
= ecalloc(etypes
.len
, sizeof(kstuple
[0][0]));
501 for (i
= 0; i
< etypes
.len
; i
++) {
502 (*kstuple
)[i
].ks_enctype
= etypes
.val
[i
];
503 (*kstuple
)[i
].ks_salttype
= 0;
507 if (princ
->n_key_data
> 0) {
508 *kstuple
= ecalloc(1, sizeof(kstuple
[0][0]));
510 for (i
= 0; i
< princ
->n_key_data
; i
++) {
511 if (princ
->key_data
->key_data_kvno
== kvno
) {
512 (*kstuple
)[0].ks_enctype
= princ
->key_data
->key_data_type
[0];
513 (*kstuple
)[0].ks_salttype
= princ
->key_data
->key_data_type
[1];
518 krb5_warnx(context
, "Could not determine what enctypes to generate "
519 "keys for; recreate namespace?");
524 randkey_kr(kadm5_principal_ent_rec
*princ
,
525 unsigned int old_kvno
,
528 krb5_key_salt_tuple
*kstuple
= 0;
529 krb5_error_code ret
= 0;
533 * We might be using kadm5clnt, so we'll use kadm5_randkey_principal_3(),
534 * which will generate new keys on the server side. This allows a race,
535 * but it will be detected by the key rotation update checks in lib/kadm5
538 ret
= princ2kstuple(princ
, old_kvno
, &kstuple
, &nkstuple
);
540 ret
= kadm5_randkey_principal_3(kadm_handle
, princ
->principal
, 1,
541 nkstuple
, kstuple
, NULL
, NULL
);
547 do_mod_ns_kr(krb5_principal principal
, void *data
)
550 kadm5_principal_ent_rec princ
;
551 struct modify_namespace_key_rotation_options
*e
= data
;
552 HDB_Ext_KeyRotation existing
;
553 HDB_Ext_KeyRotation new_kr
;
555 KeyRotation new_krs
[3];
558 time_t now
= time(NULL
);
565 new_kr
.val
= new_krs
;
567 ext
.data
.element
= choice_HDB_extension_data_key_rotation
;
568 ext
.data
.u
.key_rotation
.len
= 0;
569 ext
.data
.u
.key_rotation
.val
= 0;
572 memset(&new_krs
, 0, sizeof(new_krs
));
573 memset(&princ
, 0, sizeof(princ
));
575 if (e
->force_flag
|| e
->revoke_old_string
) {
576 krb5_warnx(context
, "--force and --revoke-old not implemented yet");
580 ret
= kadm5_get_principal(kadm_handle
, principal
, &princ
,
581 KADM5_PRINCIPAL
| KADM5_KVNO
|
582 KADM5_KEY_DATA
| KADM5_TL_DATA
);
585 for (tl
= princ
.tl_data
; tl
; tl
= tl
->tl_data_next
) {
586 if (tl
->tl_data_type
!= KRB5_TL_KRB5_CONFIG
)
588 ret
= decode_HDB_Ext_KeyRotation(tl
->tl_data_contents
,
589 tl
->tl_data_length
, &existing
, NULL
);
591 krb5_warn(context
, ret
, "unable to decode existing key "
592 "rotation schedule");
593 kadm5_free_principal_ent(kadm_handle
, &princ
);
598 krb5_warnx(context
, "no key rotation schedule; "
599 "re-create namespace?");
600 kadm5_free_principal_ent(kadm_handle
, &princ
);
606 krb5_warn(context
, ret
, "No such namespace");
607 kadm5_free_principal_ent(kadm_handle
, &princ
);
611 if (existing
.len
> 1)
612 new_kr
.val
[1] = existing
.val
[0];
613 if (existing
.len
> 2)
614 new_kr
.val
[2] = existing
.val
[1];
615 new_kr
.val
[0].flags
= existing
.val
[0].flags
;
616 new_kr
.val
[0].base_kvno
= princ
.kvno
+ 2; /* XXX Compute better */
617 new_kr
.val
[0].base_key_kvno
= existing
.val
[0].base_key_kvno
+ 1;
618 if (e
->new_key_rotation_epoch_string
) {
619 if ((ret
= str2time_t(e
->new_key_rotation_epoch_string
,
620 &new_kr
.val
[0].epoch
)))
621 krb5_warn(context
, ret
, "Invalid epoch specification: %s",
622 e
->new_key_rotation_epoch_string
);
624 new_kr
.val
[0].epoch
= existing
.val
[0].epoch
+
625 existing
.val
[0].period
* (princ
.kvno
- new_kr
.val
[0].base_kvno
);
627 if (ret
== 0 && e
->new_key_rotation_period_string
) {
630 if ((ret
= str2time_t(e
->new_key_rotation_period_string
, &t
)))
631 krb5_warn(context
, ret
, "Invalid period specification: %s",
632 e
->new_key_rotation_period_string
);
634 new_kr
.val
[0].period
= t
;
636 new_kr
.val
[0].period
= existing
.val
[0].period
+
637 existing
.val
[0].period
* (princ
.kvno
- new_kr
.val
[0].base_kvno
);
639 if (new_kr
.val
[0].epoch
< now
) {
640 krb5_warnx(context
, "New epoch cannot be in the past");
643 if (new_kr
.val
[0].epoch
< 30) {
644 krb5_warnx(context
, "New period cannot be less than 30s");
648 ret
= randkey_kr(&princ
, princ
.kvno
, new_kr
.val
[0].base_key_kvno
);
649 ext
.data
.u
.key_rotation
= new_kr
;
651 ASN1_MALLOC_ENCODE(HDB_extension
, d
.data
, d
.length
,
654 add_tl(&princ
, KRB5_TL_EXTENSION
, &d
);
656 ret
= kadm5_modify_principal(kadm_handle
, &princ
,
657 KADM5_PRINCIPAL
| KADM5_TL_DATA
);
659 krb5_warn(context
, ret
, "Could not update namespace");
663 free_HDB_Ext_KeyRotation(&existing
);
665 kadm5_free_principal_ent(kadm_handle
, &princ
);
670 modify_ns_kr(struct modify_namespace_key_rotation_options
*opt
,
674 krb5_error_code ret
= 0;
677 for(i
= 0; i
< argc
; i
++) {
678 ret
= foreach_principal(argv
[i
], do_mod_ns_kr
, "mod_ns", opt
);
686 #define princ_realm(P) ((P)->realm)
687 #define princ_num_comp(P) ((P)->name.name_string.len)
688 #define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
691 princ_cmp(const void *a
, const void *b
)
693 krb5_const_principal pa
= a
;
694 krb5_const_principal pb
= b
;
698 r
= strcmp(princ_realm(pa
), princ_realm(pb
));
700 r
= princ_num_comp(pa
) - princ_num_comp(pb
);
701 for (i
= 0; r
== 0 && i
< princ_num_comp(pa
); i
++)
702 r
= strcmp(princ_ncomp(pa
, i
), princ_ncomp(pb
, i
));
706 /* Sort and remove dups */
708 uniq(HDB_Ext_Aliases
*a
)
712 qsort(a
->aliases
.val
, a
->aliases
.len
, sizeof(a
->aliases
.val
[0]),
715 /* While there are at least two principals left to look at... */
716 while (i
+ 1 < a
->aliases
.len
) {
717 if (princ_cmp(&a
->aliases
.val
[i
], &a
->aliases
.val
[i
+ 1])) {
718 /* ...if they are different, increment i and loop */
722 /* ...else drop the one on the right and loop w/o incrementing i */
723 free_Principal(&a
->aliases
.val
[i
+ 1]);
724 if (i
+ 2 < a
->aliases
.len
)
725 memmove(&a
->aliases
.val
[i
+ 1],
726 &a
->aliases
.val
[i
+ 2],
727 sizeof(a
->aliases
.val
[i
+ 1]) * (a
->aliases
.len
- (i
+ 2)));
733 add_alias(void *opt
, int argc
, char **argv
)
735 kadm5_principal_ent_rec princ
;
737 krb5_principal p
= NULL
;
740 krb5_tl_data
*tl
= NULL
;
744 memset(&princ
, 0, sizeof(princ
));
748 krb5_warnx(context
, "Principal not given");
751 ret
= krb5_parse_name(context
, argv
[0], &p
);
753 krb5_warn(context
, ret
, "Invalid principal: %s", argv
[0]);
757 ret
= kadm5_get_principal(kadm_handle
, p
, &princ
,
758 KADM5_PRINCIPAL_NORMAL_MASK
| KADM5_TL_DATA
);
760 krb5_warn(context
, ret
, "Principal not found %s", argv
[0]);
763 krb5_free_principal(context
, p
);
766 a
= &ext
.data
.u
.aliases
;
767 a
->case_insensitive
= 0;
770 if ((tl
= get_tl(&princ
, KRB5_TL_ALIASES
))) {
771 ret
= decode_HDB_Ext_Aliases(tl
->tl_data_contents
, tl
->tl_data_length
,
774 kadm5_free_principal_ent(kadm_handle
, &princ
);
775 krb5_warn(context
, ret
, "Principal has invalid aliases extension "
776 "contents: %s", argv
[0]);
784 a
->aliases
.val
= realloc(a
->aliases
.val
,
785 sizeof(a
->aliases
.val
[0]) * (a
->aliases
.len
+ argc
));
786 if (a
->aliases
.val
== NULL
)
787 krb5_err(context
, 1, errno
, "Out of memory");
788 for (i
= 0; ret
== 0 && i
< argc
; i
++) {
789 ret
= krb5_parse_name(context
, argv
[i
], &p
);
791 krb5_warn(context
, ret
, "krb5_parse_name");
794 ret
= copy_Principal(p
, &a
->aliases
.val
[a
->aliases
.len
]);
795 krb5_free_principal(context
, p
);
801 ext
.data
.element
= choice_HDB_extension_data_aliases
;
804 ASN1_MALLOC_ENCODE(HDB_extension
, d
.data
, d
.length
, &ext
, &i
, ret
);
805 free_HDB_extension(&ext
);
807 int16_t len
= d
.length
;
809 if (len
< 0 || d
.length
!= (size_t)len
) {
810 krb5_warnx(context
, "Too many aliases; does not fit in 32767 bytes");
815 add_tl(&princ
, KRB5_TL_EXTENSION
, &d
);
817 ret
= kadm5_modify_principal(kadm_handle
, &princ
,
818 KADM5_PRINCIPAL
| KADM5_TL_DATA
);
820 krb5_warn(context
, ret
, "kadm5_modify_principal");
823 kadm5_free_principal_ent(kadm_handle
, &princ
);
825 return ret
== 0 ? 0 : 1;