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 * fetch the default principal corresponding to `princ'
41 static krb5_error_code
42 get_default (kadm5_server_context
*contextp
,
44 kadm5_principal_ent_t default_ent
)
47 krb5_principal def_principal
;
48 krb5_const_realm realm
= krb5_principal_get_realm(contextp
->context
, princ
);
50 ret
= krb5_make_principal (contextp
->context
, &def_principal
,
51 realm
, "default", NULL
);
54 ret
= kadm5_get_principal (contextp
, def_principal
, default_ent
,
55 KADM5_PRINCIPAL_NORMAL_MASK
);
56 krb5_free_principal (contextp
->context
, def_principal
);
61 * Add the principal `name' to the database.
62 * Prompt for all data not given by the input parameters.
65 static krb5_error_code
66 add_one_principal(const char *name
,
73 krb5_key_salt_tuple
*kstuple
,
74 krb5_key_data
*key_data
,
75 const char *max_ticket_life
,
76 const char *max_renewable_life
,
77 const char *attributes
,
78 const char *expiration
,
79 const char *pw_expiration
)
82 kadm5_principal_ent_rec princ
, defrec
;
83 kadm5_principal_ent_rec
*default_ent
= NULL
;
84 krb5_principal princ_ent
= NULL
;
85 krb5_timestamp pw_expire
;
90 memset(&princ
, 0, sizeof(princ
));
91 ret
= krb5_parse_name(context
, name
, &princ_ent
);
93 krb5_warn(context
, ret
, "krb5_parse_name");
96 princ
.principal
= princ_ent
;
97 mask
|= KADM5_PRINCIPAL
;
99 ret
= set_entry(context
, &princ
, &mask
,
100 max_ticket_life
, max_renewable_life
,
101 expiration
, pw_expiration
, attributes
, policy
);
105 default_ent
= &defrec
;
106 ret
= get_default (kadm_handle
, princ_ent
, default_ent
);
111 default_mask
= KADM5_ATTRIBUTES
| KADM5_MAX_LIFE
| KADM5_MAX_RLIFE
|
112 KADM5_PRINC_EXPIRE_TIME
| KADM5_PW_EXPIRATION
;
116 set_defaults(&princ
, &mask
, default_ent
, default_mask
);
118 if(edit_entry(&princ
, &mask
, default_ent
, default_mask
))
120 if(rand_key
|| key_data
) {
121 princ
.attributes
|= KRB5_KDB_DISALLOW_ALL_TIX
;
122 mask
|= KADM5_ATTRIBUTES
;
123 random_password (pwbuf
, sizeof(pwbuf
));
125 } else if (rand_password
) {
126 random_password (pwbuf
, sizeof(pwbuf
));
128 } else if(password
== NULL
) {
133 ret
= krb5_unparse_name(context
, princ_ent
, &princ_name
);
136 aret
= asprintf (&prompt
, "%s's Password: ", princ_name
);
140 krb5_set_error_message(context
, ret
, "out of memory");
143 ret
= UI_UTIL_read_pw_string (pwbuf
, sizeof(pwbuf
), prompt
,
144 UI_UTIL_FLAG_VERIFY
|
145 UI_UTIL_FLAG_VERIFY_SILENT
);
148 ret
= KRB5_LIBOS_BADPWDMATCH
;
149 krb5_set_error_message(context
, ret
, "failed to verify password");
155 ret
= kadm5_create_principal(kadm_handle
, &princ
, mask
, password
);
157 krb5_warn(context
, ret
, "kadm5_create_principal");
160 /* Save requested password expiry before it's clobbered */
161 pw_expire
= princ
.pw_expiration
;
163 krb5_keyblock
*new_keys
;
165 ret
= kadm5_randkey_principal_3(kadm_handle
, princ_ent
, 0,
166 nkstuple
, kstuple
, &new_keys
, &n_keys
);
168 krb5_warn(context
, ret
, "kadm5_randkey_principal");
171 for(i
= 0; i
< n_keys
; i
++)
172 krb5_free_keyblock_contents(context
, &new_keys
[i
]);
175 kadm5_get_principal(kadm_handle
, princ_ent
, &princ
,
176 KADM5_PRINCIPAL
| KADM5_KVNO
| KADM5_ATTRIBUTES
);
177 krb5_free_principal(context
, princ_ent
);
178 princ_ent
= princ
.principal
;
179 princ
.attributes
&= (~KRB5_KDB_DISALLOW_ALL_TIX
);
180 princ
.pw_expiration
= pw_expire
;
182 * Updating kvno w/o key data and vice-versa gives _kadm5_setup_entry()
183 * and _kadm5_set_keys2() headaches. But we used to, so we handle
184 * this in in those two functions. Might as well leave this code as
188 kadm5_modify_principal(kadm_handle
, &princ
,
189 KADM5_PW_EXPIRATION
| KADM5_ATTRIBUTES
| KADM5_KVNO
);
190 } else if (key_data
) {
191 ret
= kadm5_chpass_principal_with_key (kadm_handle
, princ_ent
,
194 krb5_warn(context
, ret
, "kadm5_chpass_principal_with_key");
196 kadm5_get_principal(kadm_handle
, princ_ent
, &princ
,
197 KADM5_PRINCIPAL
| KADM5_ATTRIBUTES
);
198 krb5_free_principal(context
, princ_ent
);
199 princ_ent
= princ
.principal
;
200 princ
.attributes
&= (~KRB5_KDB_DISALLOW_ALL_TIX
);
201 princ
.pw_expiration
= pw_expire
;
202 kadm5_modify_principal(kadm_handle
, &princ
,
203 KADM5_PW_EXPIRATION
| KADM5_ATTRIBUTES
);
204 } else if (rand_password
) {
207 krb5_unparse_name(context
, princ_ent
, &princ_name
);
208 printf ("added %s with password \"%s\"\n", princ_name
, password
);
212 kadm5_free_principal_ent(kadm_handle
, &princ
); /* frees princ_ent */
214 kadm5_free_principal_ent (kadm_handle
, default_ent
);
215 if (password
!= NULL
)
216 memset (password
, 0, strlen(password
));
221 * parse the string `key_string' into `key', returning 0 iff succesful.
229 * Parse arguments and add all the principals.
233 add_new_key(struct add_options
*opt
, int argc
, char **argv
)
235 krb5_error_code ret
= 0;
236 krb5_key_salt_tuple
*kstuple
= NULL
;
237 krb5_key_data key_data
[3];
238 krb5_key_data
*kdp
= NULL
;
239 const char *enctypes
;
244 if (opt
->random_key_flag
)
246 if (opt
->random_password_flag
)
248 if (opt
->password_string
)
254 fprintf (stderr
, "give only one of "
255 "--random-key, --random-password, --password, --key\n");
259 enctypes
= opt
->enctypes_string
;
260 if (enctypes
== NULL
|| enctypes
[0] == '\0')
261 enctypes
= krb5_config_get_string(context
, NULL
, "libdefaults",
262 "supported_enctypes", NULL
);
263 if (enctypes
== NULL
|| enctypes
[0] == '\0')
264 enctypes
= "aes128-cts-hmac-sha1-96";
265 ret
= krb5_string_to_keysalts2(context
, enctypes
, &nkstuple
, &kstuple
);
267 fprintf(stderr
, "enctype(s) unknown\n");
272 if (opt
->key_string
) {
275 if (parse_des_key (opt
->key_string
, key_data
, &error
)) {
276 fprintf(stderr
, "failed parsing key \"%s\": %s\n",
277 opt
->key_string
, error
);
284 for(i
= 0; i
< argc
; i
++) {
285 ret
= add_one_principal(argv
[i
],
286 opt
->random_key_flag
,
287 opt
->random_password_flag
,
288 opt
->use_defaults_flag
,
289 opt
->password_string
,
294 opt
->max_ticket_life_string
,
295 opt
->max_renewable_life_string
,
296 opt
->attributes_string
,
297 opt
->expiration_time_string
,
298 opt
->pw_expiration_time_string
);
300 krb5_warn (context
, ret
, "adding %s", argv
[i
]);
306 kadm5_free_key_data (kadm_handle
, &dummy
, key_data
);