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
)
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; i
< strings
->num_strings
; i
++) {
148 ret
= krb5_parse_name(contextp
, strings
->strings
[i
], &p
);
149 ret
= copy_Principal(p
, &ext
.data
.u
.aliases
.aliases
.val
[i
]);
150 krb5_free_principal(contextp
, p
);
154 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
156 free_HDB_extension(&ext
);
159 if (buf
.length
!= size
)
162 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
166 add_pkinit_acl(krb5_context contextp
, kadm5_principal_ent_rec
*princ
,
167 struct getarg_strings
*strings
)
175 memset(&ext
, 0, sizeof(ext
));
176 ext
.mandatory
= FALSE
;
177 ext
.data
.element
= choice_HDB_extension_data_pkinit_acl
;
178 ext
.data
.u
.aliases
.case_insensitive
= 0;
180 if (strings
->num_strings
== 1 && strings
->strings
[0][0] == '\0') {
181 ext
.data
.u
.pkinit_acl
.val
= NULL
;
182 ext
.data
.u
.pkinit_acl
.len
= 0;
184 ext
.data
.u
.pkinit_acl
.val
=
185 calloc(strings
->num_strings
,
186 sizeof(ext
.data
.u
.pkinit_acl
.val
[0]));
187 ext
.data
.u
.pkinit_acl
.len
= strings
->num_strings
;
189 for (i
= 0; i
< strings
->num_strings
; i
++) {
190 ext
.data
.u
.pkinit_acl
.val
[i
].subject
= estrdup(strings
->strings
[i
]);
194 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
196 free_HDB_extension(&ext
);
199 if (buf
.length
!= size
)
202 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
205 static krb5_error_code
206 add_etypes(krb5_context contextp
,
207 kadm5_principal_ent_rec
*princ
,
208 struct getarg_strings
*strings
)
210 krb5_error_code ret
= 0;
211 HDB_EncTypeList etypes
;
215 etypes
.len
= strings
->num_strings
;
216 if ((etypes
.val
= calloc(strings
->num_strings
,
217 sizeof(etypes
.val
[0]))) == NULL
)
218 krb5_err(contextp
, 1, ret
, "Out of memory");
220 for (i
= 0; i
< strings
->num_strings
; i
++) {
223 ret
= krb5_string_to_enctype(contextp
, strings
->strings
[i
], &etype
);
225 krb5_warn(contextp
, ret
, "Could not parse enctype %s",
226 strings
->strings
[i
]);
229 etypes
.val
[i
] = etype
;
233 ASN1_MALLOC_ENCODE(HDB_EncTypeList
, buf
.data
, buf
.length
,
234 &etypes
, &size
, ret
);
236 if (ret
|| buf
.length
!= size
)
238 add_tl(princ
, KRB5_TL_ETYPES
, &buf
);
243 add_kvno_diff(krb5_context contextp
, kadm5_principal_ent_rec
*princ
,
244 int is_svc_diff
, krb5_kvno kvno_diff
)
253 if (kvno_diff
> 2048)
257 ext
.data
.element
= choice_HDB_extension_data_hist_kvno_diff_svc
;
258 ext
.data
.u
.hist_kvno_diff_svc
= (unsigned int)kvno_diff
;
260 ext
.data
.element
= choice_HDB_extension_data_hist_kvno_diff_clnt
;
261 ext
.data
.u
.hist_kvno_diff_clnt
= (unsigned int)kvno_diff
;
263 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
267 if (buf
.length
!= size
)
270 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
274 add_krb5_config(kadm5_principal_ent_rec
*princ
, const char *fname
)
281 memset(&ext
, 0, sizeof(ext
));
282 ext
.mandatory
= FALSE
;
283 ext
.data
.element
= choice_HDB_extension_data_krb5_config
;
285 if ((ret
= rk_undumpdata(fname
,
286 &ext
.data
.u
.krb5_config
.data
,
287 &ext
.data
.u
.krb5_config
.length
))) {
288 krb5_warn(context
, ret
, "Could not read %s", fname
);
292 ASN1_MALLOC_ENCODE(HDB_extension
, buf
.data
, buf
.length
,
294 free_HDB_extension(&ext
);
297 if (buf
.length
!= size
)
299 add_tl(princ
, KRB5_TL_EXTENSION
, &buf
);
303 do_mod_entry(krb5_principal principal
, void *data
)
306 kadm5_principal_ent_rec princ
;
308 struct modify_options
*e
= data
;
310 memset (&princ
, 0, sizeof(princ
));
311 ret
= kadm5_get_principal(kadm_handle
, principal
, &princ
,
312 KADM5_PRINCIPAL
| KADM5_ATTRIBUTES
|
313 KADM5_MAX_LIFE
| KADM5_MAX_RLIFE
|
314 KADM5_PRINC_EXPIRE_TIME
|
315 KADM5_PW_EXPIRATION
);
319 if(e
->max_ticket_life_string
||
320 e
->max_renewable_life_string
||
321 e
->expiration_time_string
||
322 e
->pw_expiration_time_string
||
323 e
->attributes_string
||
325 e
->kvno_integer
!= -1 ||
326 e
->service_enctypes_strings
.num_strings
||
327 e
->constrained_delegation_strings
.num_strings
||
328 e
->alias_strings
.num_strings
||
329 e
->pkinit_acl_strings
.num_strings
||
330 e
->krb5_config_file_string
||
331 e
->hist_kvno_diff_clnt_integer
!= -1 ||
332 e
->hist_kvno_diff_svc_integer
!= -1) {
333 ret
= set_entry(context
, &princ
, &mask
,
334 e
->max_ticket_life_string
,
335 e
->max_renewable_life_string
,
336 e
->expiration_time_string
,
337 e
->pw_expiration_time_string
,
338 e
->attributes_string
,
340 if(e
->kvno_integer
!= -1) {
341 princ
.kvno
= e
->kvno_integer
;
344 if (e
->constrained_delegation_strings
.num_strings
) {
345 add_constrained_delegation(context
, &princ
,
346 &e
->constrained_delegation_strings
);
347 mask
|= KADM5_TL_DATA
;
349 if (e
->alias_strings
.num_strings
) {
350 add_aliases(context
, &princ
, &e
->alias_strings
);
351 mask
|= KADM5_TL_DATA
;
353 if (e
->pkinit_acl_strings
.num_strings
) {
354 add_pkinit_acl(context
, &princ
, &e
->pkinit_acl_strings
);
355 mask
|= KADM5_TL_DATA
;
357 if (e
->service_enctypes_strings
.num_strings
) {
358 ret
= add_etypes(context
, &princ
, &e
->service_enctypes_strings
);
359 mask
|= KADM5_TL_DATA
;
361 if (e
->hist_kvno_diff_clnt_integer
!= -1) {
362 add_kvno_diff(context
, &princ
, 0, e
->hist_kvno_diff_clnt_integer
);
363 mask
|= KADM5_TL_DATA
;
365 if (e
->hist_kvno_diff_svc_integer
!= -1) {
366 add_kvno_diff(context
, &princ
, 1, e
->hist_kvno_diff_svc_integer
);
367 mask
|= KADM5_TL_DATA
;
369 if (e
->krb5_config_file_string
) {
370 add_krb5_config(&princ
, e
->krb5_config_file_string
);
371 mask
|= KADM5_TL_DATA
;
374 ret
= edit_entry(&princ
, &mask
, NULL
, 0);
376 ret
= kadm5_modify_principal(kadm_handle
, &princ
, mask
);
378 krb5_warn(context
, ret
, "kadm5_modify_principal");
381 kadm5_free_principal_ent(kadm_handle
, &princ
);
386 mod_entry(struct modify_options
*opt
, int argc
, char **argv
)
388 krb5_error_code ret
= 0;
391 for(i
= 0; i
< argc
; i
++) {
392 ret
= foreach_principal(argv
[i
], do_mod_entry
, "mod", opt
);
400 do_mod_ns_entry(krb5_principal principal
, void *data
)
403 kadm5_principal_ent_rec princ
;
405 struct modify_namespace_options
*e
= data
;
407 memset (&princ
, 0, sizeof(princ
));
408 ret
= kadm5_get_principal(kadm_handle
, principal
, &princ
,
409 KADM5_PRINCIPAL
| KADM5_ATTRIBUTES
|
410 KADM5_MAX_LIFE
| KADM5_MAX_RLIFE
|
411 KADM5_PRINC_EXPIRE_TIME
|
412 KADM5_PW_EXPIRATION
);
416 if(e
->max_ticket_life_string
||
417 e
->max_renewable_life_string
||
418 e
->attributes_string
||
419 e
->enctypes_strings
.num_strings
||
420 e
->krb5_config_file_string
) {
421 ret
= set_entry(context
, &princ
, &mask
, e
->max_ticket_life_string
,
422 e
->max_renewable_life_string
, NULL
, NULL
,
423 e
->attributes_string
, NULL
);
424 if (e
->enctypes_strings
.num_strings
) {
425 ret
= add_etypes(context
, &princ
, &e
->enctypes_strings
);
426 mask
|= KADM5_TL_DATA
;
428 if (e
->krb5_config_file_string
) {
429 add_krb5_config(&princ
, e
->krb5_config_file_string
);
430 mask
|= KADM5_TL_DATA
;
433 ret
= edit_entry(&princ
, &mask
, NULL
, 0);
435 ret
= kadm5_modify_principal(kadm_handle
, &princ
, mask
);
437 krb5_warn(context
, ret
, "kadm5_modify_principal");
440 kadm5_free_principal_ent(kadm_handle
, &princ
);
445 modify_namespace(struct modify_namespace_options
*opt
, int argc
, char **argv
)
447 krb5_error_code ret
= 0;
450 for(i
= 0; i
< argc
; i
++) {
451 ret
= foreach_principal(argv
[i
], do_mod_ns_entry
, "mod_ns", opt
);
459 struct modify_namespace_key_rotation_options
{
461 int keep_base_key_flag
;
462 char* revoke_old_string
;
463 char* new_key_rotation_epoch_string
;
464 char* new_key_rotation_period_string
;
469 princ2kstuple(kadm5_principal_ent_rec
*princ
,
471 krb5_key_salt_tuple
**kstuple
,
474 krb5_error_code ret
= 0;
475 HDB_EncTypeList etypes
;
483 for (tl
= princ
->tl_data
; tl
; tl
= tl
->tl_data_next
) {
484 if (tl
->tl_data_type
!= KRB5_TL_ETYPES
|| tl
->tl_data_length
< 0)
486 ret
= decode_HDB_EncTypeList(tl
->tl_data_contents
, tl
->tl_data_length
,
490 *nkstuple
= etypes
.len
;
491 *kstuple
= ecalloc(etypes
.len
, sizeof(kstuple
[0][0]));
492 for (i
= 0; i
< etypes
.len
; i
++) {
493 (*kstuple
)[i
].ks_enctype
= etypes
.val
[i
];
494 (*kstuple
)[i
].ks_salttype
= 0;
498 if (princ
->n_key_data
> 0) {
499 *kstuple
= ecalloc(1, sizeof(kstuple
[0][0]));
501 for (i
= 0; i
< princ
->n_key_data
; i
++) {
502 if (princ
->key_data
->key_data_kvno
== kvno
) {
503 (*kstuple
)[0].ks_enctype
= princ
->key_data
->key_data_type
[0];
504 (*kstuple
)[0].ks_salttype
= princ
->key_data
->key_data_type
[1];
509 krb5_warnx(context
, "Could not determine what enctypes to generate "
510 "keys for; recreate namespace?");
515 randkey_kr(kadm5_principal_ent_rec
*princ
,
516 unsigned int old_kvno
,
519 krb5_key_salt_tuple
*kstuple
= 0;
520 krb5_error_code ret
= 0;
524 * We might be using kadm5clnt, so we'll use kadm5_randkey_principal_3(),
525 * which will generate new keys on the server side. This allows a race,
526 * but it will be detected by the key rotation update checks in lib/kadm5
529 ret
= princ2kstuple(princ
, old_kvno
, &kstuple
, &nkstuple
);
531 ret
= kadm5_randkey_principal_3(kadm_handle
, princ
->principal
, 1,
532 nkstuple
, kstuple
, NULL
, NULL
);
538 do_mod_ns_kr(krb5_principal principal
, void *data
)
541 kadm5_principal_ent_rec princ
;
542 struct modify_namespace_key_rotation_options
*e
= data
;
543 HDB_Ext_KeyRotation existing
;
544 HDB_Ext_KeyRotation new_kr
;
546 KeyRotation new_krs
[3];
549 time_t now
= time(NULL
);
556 new_kr
.val
= new_krs
;
558 ext
.data
.element
= choice_HDB_extension_data_key_rotation
;
559 ext
.data
.u
.key_rotation
.len
= 0;
560 ext
.data
.u
.key_rotation
.val
= 0;
563 memset(&new_krs
, 0, sizeof(new_krs
));
564 memset(&princ
, 0, sizeof(princ
));
566 if (e
->force_flag
|| e
->revoke_old_string
) {
567 krb5_warnx(context
, "--force and --revoke-old not implemented yet");
571 ret
= kadm5_get_principal(kadm_handle
, principal
, &princ
,
572 KADM5_PRINCIPAL
| KADM5_KVNO
|
573 KADM5_KEY_DATA
| KADM5_TL_DATA
);
576 for (tl
= princ
.tl_data
; tl
; tl
= tl
->tl_data_next
) {
577 if (tl
->tl_data_type
!= KRB5_TL_KRB5_CONFIG
)
579 ret
= decode_HDB_Ext_KeyRotation(tl
->tl_data_contents
,
580 tl
->tl_data_length
, &existing
, NULL
);
582 krb5_warn(context
, ret
, "unable to decode existing key "
583 "rotation schedule");
584 kadm5_free_principal_ent(kadm_handle
, &princ
);
589 krb5_warnx(context
, "no key rotation schedule; "
590 "re-create namespace?");
591 kadm5_free_principal_ent(kadm_handle
, &princ
);
597 krb5_warn(context
, ret
, "No such namespace");
598 kadm5_free_principal_ent(kadm_handle
, &princ
);
602 if (existing
.len
> 1)
603 new_kr
.val
[1] = existing
.val
[0];
604 if (existing
.len
> 2)
605 new_kr
.val
[2] = existing
.val
[1];
606 new_kr
.val
[0].flags
= existing
.val
[0].flags
;
607 new_kr
.val
[0].base_kvno
= princ
.kvno
+ 2; /* XXX Compute better */
608 new_kr
.val
[0].base_key_kvno
= existing
.val
[0].base_key_kvno
+ 1;
609 if (e
->new_key_rotation_epoch_string
) {
610 if ((ret
= str2time_t(e
->new_key_rotation_epoch_string
,
611 &new_kr
.val
[0].epoch
)))
612 krb5_warn(context
, ret
, "Invalid epoch specification: %s",
613 e
->new_key_rotation_epoch_string
);
615 new_kr
.val
[0].epoch
= existing
.val
[0].epoch
+
616 existing
.val
[0].period
* (princ
.kvno
- new_kr
.val
[0].base_kvno
);
618 if (ret
== 0 && e
->new_key_rotation_period_string
) {
621 if ((ret
= str2time_t(e
->new_key_rotation_period_string
, &t
)))
622 krb5_warn(context
, ret
, "Invalid period specification: %s",
623 e
->new_key_rotation_period_string
);
625 new_kr
.val
[0].period
= t
;
627 new_kr
.val
[0].period
= existing
.val
[0].period
+
628 existing
.val
[0].period
* (princ
.kvno
- new_kr
.val
[0].base_kvno
);
630 if (new_kr
.val
[0].epoch
< now
) {
631 krb5_warnx(context
, "New epoch cannot be in the past");
634 if (new_kr
.val
[0].epoch
< 30) {
635 krb5_warnx(context
, "New period cannot be less than 30s");
639 ret
= randkey_kr(&princ
, princ
.kvno
, new_kr
.val
[0].base_key_kvno
);
640 ext
.data
.u
.key_rotation
= new_kr
;
642 ASN1_MALLOC_ENCODE(HDB_extension
, d
.data
, d
.length
,
645 add_tl(&princ
, KRB5_TL_EXTENSION
, &d
);
647 ret
= kadm5_modify_principal(kadm_handle
, &princ
,
648 KADM5_PRINCIPAL
| KADM5_TL_DATA
);
650 krb5_warn(context
, ret
, "Could not update namespace");
654 free_HDB_Ext_KeyRotation(&existing
);
656 kadm5_free_principal_ent(kadm_handle
, &princ
);
661 modify_ns_kr(struct modify_namespace_key_rotation_options
*opt
,
665 krb5_error_code ret
= 0;
668 for(i
= 0; i
< argc
; i
++) {
669 ret
= foreach_principal(argv
[i
], do_mod_ns_kr
, "mod_ns", opt
);
677 #define princ_realm(P) ((P)->realm)
678 #define princ_num_comp(P) ((P)->name.name_string.len)
679 #define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
682 princ_cmp(const void *a
, const void *b
)
684 krb5_const_principal pa
= a
;
685 krb5_const_principal pb
= b
;
689 r
= strcmp(princ_realm(pa
), princ_realm(pb
));
691 r
= princ_num_comp(pa
) - princ_num_comp(pb
);
692 for (i
= 0; r
== 0 && i
< princ_num_comp(pa
); i
++)
693 r
= strcmp(princ_ncomp(pa
, i
), princ_ncomp(pb
, i
));
697 /* Sort and remove dups */
699 uniq(HDB_Ext_Aliases
*a
)
703 qsort(a
->aliases
.val
, a
->aliases
.len
, sizeof(a
->aliases
.val
[0]),
706 /* While there are at least two principals left to look at... */
707 while (i
+ 1 < a
->aliases
.len
) {
708 if (princ_cmp(&a
->aliases
.val
[i
], &a
->aliases
.val
[i
+ 1])) {
709 /* ...if they are different, increment i and loop */
713 /* ...else drop the one on the right and loop w/o incrementing i */
714 free_Principal(&a
->aliases
.val
[i
+ 1]);
715 if (i
+ 2 < a
->aliases
.len
)
716 memmove(&a
->aliases
.val
[i
+ 1],
717 &a
->aliases
.val
[i
+ 2],
718 sizeof(a
->aliases
.val
[i
+ 1]) * (a
->aliases
.len
- (i
+ 2)));
724 add_alias(void *opt
, int argc
, char **argv
)
726 kadm5_principal_ent_rec princ
;
728 krb5_principal p
= NULL
;
731 krb5_tl_data
*tl
= NULL
;
735 memset(&princ
, 0, sizeof(princ
));
739 krb5_warnx(context
, "Principal not given");
742 ret
= krb5_parse_name(context
, argv
[0], &p
);
744 krb5_warn(context
, ret
, "Invalid principal: %s", argv
[0]);
748 ret
= kadm5_get_principal(kadm_handle
, p
, &princ
,
749 KADM5_PRINCIPAL_NORMAL_MASK
| KADM5_TL_DATA
);
751 krb5_warn(context
, ret
, "Principal not found %s", argv
[0]);
754 krb5_free_principal(context
, p
);
757 a
= &ext
.data
.u
.aliases
;
758 a
->case_insensitive
= 0;
761 if ((tl
= get_tl(&princ
, KRB5_TL_ALIASES
))) {
762 ret
= decode_HDB_Ext_Aliases(tl
->tl_data_contents
, tl
->tl_data_length
,
765 kadm5_free_principal_ent(kadm_handle
, &princ
);
766 krb5_warn(context
, ret
, "Principal has invalid aliases extension "
767 "contents: %s", argv
[0]);
775 a
->aliases
.val
= realloc(a
->aliases
.val
,
776 sizeof(a
->aliases
.val
[0]) * (a
->aliases
.len
+ argc
));
777 if (a
->aliases
.val
== NULL
)
778 krb5_err(context
, 1, errno
, "Out of memory");
779 for (i
= 0; ret
== 0 && i
< argc
; i
++) {
780 ret
= krb5_parse_name(context
, argv
[i
], &p
);
782 krb5_warn(context
, ret
, "krb5_parse_name");
785 ret
= copy_Principal(p
, &a
->aliases
.val
[a
->aliases
.len
]);
786 krb5_free_principal(context
, p
);
792 ext
.data
.element
= choice_HDB_extension_data_aliases
;
795 ASN1_MALLOC_ENCODE(HDB_extension
, d
.data
, d
.length
, &ext
, &i
, ret
);
796 free_HDB_extension(&ext
);
798 int16_t len
= d
.length
;
800 if (len
< 0 || d
.length
!= (size_t)len
) {
801 krb5_warnx(context
, "Too many aliases; does not fit in 32767 bytes");
806 add_tl(&princ
, KRB5_TL_EXTENSION
, &d
);
808 ret
= kadm5_modify_principal(kadm_handle
, &princ
,
809 KADM5_PRINCIPAL
| KADM5_TL_DATA
);
811 krb5_warn(context
, ret
, "kadm5_modify_principal");
814 kadm5_free_principal_ent(kadm_handle
, &princ
);
816 return ret
== 0 ? 0 : 1;