1 /*
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
8 *
9 * $Id: kadm5_create.c,v 1.6 1998/10/30 02:52:37 marc Exp $
10 * $Source: /cvs/krbdev/krb5/src/kadmin/dbutil/kadm5_create.c,v $
11 */
12
13 /*
14 * Copyright (C) 1998 by the FundsXpress, INC.
15 *
16 * All rights reserved.
17 *
18 * Export of this software from the United States of America may require
19 * a specific license from the United States Government. It is the
20 * responsibility of any person or organization contemplating export to
21 * obtain such a license before exporting.
22 *
23 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
24 * distribute this software and its documentation for any purpose and
25 * without fee is hereby granted, provided that the above copyright
26 * notice appear in all copies and that both that copyright notice and
27 * this permission notice appear in supporting documentation, and that
28 * the name of FundsXpress. not be used in advertising or publicity pertaining
29 * to distribution of the software without specific, written prior
30 * permission. FundsXpress makes no representations about the suitability of
31 * this software for any purpose. It is provided "as is" without express
32 * or implied warranty.
33 *
34 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
36 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
37 */
38
39 #include "string_table.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <k5-int.h>
45 #include <kdb.h>
46 #include <kadm5/admin.h>
47 #include <krb5/adm_proto.h>
48
49 #include <krb5.h>
50 #include <krb5/kdb.h>
51 #include "kdb5_util.h"
52 #include <libintl.h>
53
54 int
55 add_admin_old_princ(void *handle, krb5_context context,
56 char *name, char *realm, int attrs, int lifetime);
57 int
58 add_admin_sname_princ(void *handle, krb5_context context,
59 char *sname, int attrs, int lifetime);
60 static int
61 add_admin_princ(void *handle, krb5_context context,
62 krb5_principal principal, int attrs, int lifetime);
63
64 static int add_admin_princs(void *handle, krb5_context context, char *realm);
65
66 #define ERR 1
67 #define OK 0
68
69 #define ADMIN_LIFETIME 60*60*3 /* 3 hours */
70 #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
71
72 extern char *progname;
73
74 /*
75 * Function: kadm5_create
76 *
77 * Purpose: create admin principals in KDC database
78 *
79 * Arguments: params (r) configuration parameters to use
80 *
81 * Effects: Creates KADM5_ADMIN_SERVICE and KADM5_CHANGEPW_SERVICE
82 * principals in the KDC database and sets their attributes
83 * appropriately.
84 */
kadm5_create(kadm5_config_params * params)85 int kadm5_create(kadm5_config_params *params)
86 {
87 int retval;
88 krb5_context context;
89
90 kadm5_config_params lparams;
91
92 if ((retval = kadm5_init_krb5_context(&context)))
93 exit(ERR);
94
95 (void) memset(&lparams, 0, sizeof (kadm5_config_params));
96
97 /*
98 * The lock file has to exist before calling kadm5_init, but
99 * params->admin_lockfile may not be set yet...
100 */
101 if ((retval = kadm5_get_config_params(context, 1,
102 params, &lparams))) {
103 com_err(progname, retval, gettext("while looking up the Kerberos configuration"));
104 return 1;
105 }
106
107 retval = kadm5_create_magic_princs(&lparams, context);
108
109 kadm5_free_config_params(context, &lparams);
110 krb5_free_context(context);
111
112 return retval;
113 }
114
kadm5_create_magic_princs(kadm5_config_params * params,krb5_context context)115 int kadm5_create_magic_princs(kadm5_config_params *params,
116 krb5_context context)
117 {
118 int retval;
119 void *handle;
120
121 retval = krb5_klog_init(context, "admin_server", progname, 0);
122 if (retval)
123 return retval;
124 if ((retval = kadm5_init(progname, NULL, NULL, params,
125 KADM5_STRUCT_VERSION,
126 KADM5_API_VERSION_2,
127 db5util_db_args,
128 &handle))) {
129 com_err(progname, retval, gettext("while initializing the Kerberos admin interface"));
130 return retval;
131 }
132
133 retval = add_admin_princs(handle, context, params->realm);
134
135 kadm5_destroy(handle);
136
137 krb5_klog_close(context);
138
139 return retval;
140 }
141
142 /*
143 * Function: build_name_with_realm
144 *
145 * Purpose: concatenate a name and a realm to form a krb5 name
146 *
147 * Arguments:
148 *
149 * name (input) the name
150 * realm (input) the realm
151 *
152 * Returns:
153 *
154 * pointer to name@realm, in allocated memory, or NULL if it
155 * cannot be allocated
156 *
157 * Requires: both strings are null-terminated
158 */
build_name_with_realm(char * name,char * realm)159 static char *build_name_with_realm(char *name, char *realm)
160 {
161 char *n;
162
163 n = (char *) malloc(strlen(name) + strlen(realm) + 2);
164 sprintf(n, "%s@%s", name, realm);
165 return n;
166 }
167
168 /*
169 * Function: add_admin_princs
170 *
171 * Purpose: create admin principals
172 *
173 * Arguments:
174 *
175 * rseed (input) random seed
176 * realm (input) realm, or NULL for default realm
177 * <return value> (output) status, 0 for success, 1 for serious error
178 *
179 * Requires:
180 *
181 * Effects:
182 *
183 * add_admin_princs creates KADM5_ADMIN_SERVICE,
184 * KADM5_CHANGEPW_SERVICE. If any of these exist a message is
185 * printed. If any of these existing principal do not have the proper
186 * attributes, a warning message is printed.
187 */
add_admin_princs(void * handle,krb5_context context,char * realm)188 static int add_admin_princs(void *handle, krb5_context context, char *realm)
189 {
190 krb5_error_code ret = 0;
191
192 /*
193 * Solaris Kerberos:
194 * The kadmin/admin principal is unused on Solaris. This principal is used
195 * in AUTH_GSSAPI but Solaris doesn't support AUTH_GSSAPI. RPCSEC_GSS can only
196 * be used with host-based principals.
197 *
198 */
199
200 #if 0
201 if ((ret = add_admin_old_princ(handle, context,
202 KADM5_ADMIN_SERVICE, realm,
203 KRB5_KDB_DISALLOW_TGT_BASED,
204 ADMIN_LIFETIME)))
205 goto clean_and_exit;
206 #endif
207
208 if ((ret = add_admin_old_princ(handle, context,
209 KADM5_CHANGEPW_SERVICE, realm,
210 KRB5_KDB_DISALLOW_TGT_BASED |
211 KRB5_KDB_PWCHANGE_SERVICE,
212 CHANGEPW_LIFETIME)))
213 goto clean_and_exit;
214
215 if ((ret = add_admin_sname_princ(handle, context,
216 KADM5_ADMIN_HOST_SERVICE,
217 KRB5_KDB_DISALLOW_TGT_BASED,
218 ADMIN_LIFETIME)))
219 goto clean_and_exit;
220
221 if ((ret = add_admin_sname_princ(handle, context,
222 KADM5_CHANGEPW_HOST_SERVICE,
223 KRB5_KDB_DISALLOW_TGT_BASED |
224 KRB5_KDB_PWCHANGE_SERVICE,
225 ADMIN_LIFETIME)))
226 goto clean_and_exit;
227
228 if ((ret = add_admin_sname_princ(handle, context,
229 KADM5_KIPROP_HOST_SERVICE,
230 KRB5_KDB_DISALLOW_TGT_BASED,
231 ADMIN_LIFETIME)))
232 goto clean_and_exit;
233
234 clean_and_exit:
235
236 return ret;
237 }
238
239 /*
240 * Function: add_admin_princ
241 *
242 * Arguments:
243 *
244 * creator (r) principal to use as "mod_by"
245 * rseed (r) seed for random key generator
246 * principal (r) kerberos principal to add
247 * attrs (r) principal's attributes
248 * lifetime (r) principal's max life, or 0
249 * not_unique (r) error message for multiple entries, never used
250 * exists (r) warning message for principal exists
251 * wrong_attrs (r) warning message for wrong attributes
252 *
253 * Returns:
254 *
255 * OK on success
256 * ERR on serious errors
257 *
258 * Effects:
259 *
260 * If the principal is not unique, not_unique is printed (but this
261 * never happens). If the principal exists, then exists is printed
262 * and if the principals attributes != attrs, wrong_attrs is printed.
263 * Otherwise, the principal is created with mod_by creator and
264 * attributes attrs and max life of lifetime (if not zero).
265 */
266
add_admin_princ(void * handle,krb5_context context,krb5_principal principal,int attrs,int lifetime)267 static int add_admin_princ(void *handle, krb5_context context,
268 krb5_principal principal, int attrs, int lifetime)
269 {
270 char *fullname;
271 krb5_error_code ret;
272 kadm5_principal_ent_rec ent;
273
274 memset(&ent, 0, sizeof(ent));
275
276 if (krb5_unparse_name(context, principal, &fullname))
277 return ERR;
278
279 ent.principal = principal;
280 ent.max_life = lifetime;
281 ent.attributes = attrs | KRB5_KDB_DISALLOW_ALL_TIX;
282
283 ret = kadm5_create_principal(handle, &ent,
284 (KADM5_PRINCIPAL | KADM5_MAX_LIFE |
285 KADM5_ATTRIBUTES),
286 "to-be-random");
287 if (ret) {
288 if (ret != KADM5_DUP) {
289 com_err(progname, ret,
290 gettext(str_PUT_PRINC), fullname);
291 krb5_free_principal(context, ent.principal);
292 free(fullname);
293 return ERR;
294 }
295 } else {
296 /* only randomize key if we created the principal */
297
298 /*
299 * Solaris Kerberos:
300 * Create kadmind principals with keys for all supported encryption types.
301 * Follows a similar pattern to add_principal() in keytab.c.
302 */
303 krb5_enctype *tmpenc, *enctype = NULL;
304 krb5_key_salt_tuple *keysalt;
305 int num_ks, i;
306 krb5_int32 normalsalttype;
307
308 ret = krb5_get_permitted_enctypes(context, &enctype);
309 if (ret || *enctype == NULL) {
310 com_err(progname, ret,
311 gettext("while getting list of permitted encryption types"));
312 krb5_free_principal(context, ent.principal);
313 free(fullname);
314 return ERR;
315 }
316
317 /* Count the number of enc types */
318 for (tmpenc = enctype, num_ks = 0; *tmpenc; tmpenc++)
319 num_ks++;
320
321 keysalt = malloc (sizeof (krb5_key_salt_tuple) * num_ks);
322 if (keysalt == NULL) {
323 com_err(progname, ENOMEM,
324 gettext("while generating list of key salt tuples"));
325 krb5_free_ktypes(context, enctype);
326 krb5_free_principal(context, ent.principal);
327 free(fullname);
328 return ERR;
329 }
330
331 ret = krb5_string_to_salttype("normal", &normalsalttype);
332 if (ret) {
333 com_err(progname, ret,
334 gettext("while converting \"normal\" to a salttype"));
335 free(keysalt);
336 krb5_free_ktypes(context, enctype);
337 krb5_free_principal(context, ent.principal);
338 free(fullname);
339 return ERR;
340 }
341
342 /* Only create keys with "normal" salttype */
343 for (i = 0; i < num_ks; i++) {
344 keysalt[i].ks_enctype = enctype[i];
345 keysalt[i].ks_salttype = normalsalttype;
346 }
347
348 ret = kadm5_randkey_principal_3(handle, ent.principal, FALSE, num_ks,
349 keysalt, NULL, NULL);
350 free(keysalt);
351 krb5_free_ktypes (context, enctype);
352
353
354 if (ret) {
355 com_err(progname, ret,
356 gettext(str_RANDOM_KEY), fullname);
357 krb5_free_principal(context, ent.principal);
358 free(fullname);
359 return ERR;
360 }
361
362 ent.attributes = attrs;
363 ret = kadm5_modify_principal(handle, &ent, KADM5_ATTRIBUTES);
364 if (ret) {
365 com_err(progname, ret,
366 gettext(str_PUT_PRINC), fullname);
367 krb5_free_principal(context, ent.principal);
368 free(fullname);
369 return ERR;
370 }
371 }
372
373 krb5_free_principal(context, ent.principal);
374 free(fullname);
375
376 return OK;
377 }
378
379 int
add_admin_old_princ(void * handle,krb5_context context,char * name,char * realm,int attrs,int lifetime)380 add_admin_old_princ(void *handle, krb5_context context,
381 char *name, char *realm, int attrs, int lifetime)
382 {
383 char *fullname;
384 krb5_error_code ret;
385 krb5_principal principal;
386
387 fullname = build_name_with_realm(name, realm);
388 if (ret = krb5_parse_name(context, fullname, &principal)) {
389 com_err(progname, ret, gettext(str_PARSE_NAME));
390 return (ERR);
391 }
392
393 return (add_admin_princ(handle, context, principal, attrs, lifetime));
394 }
395
396 int
add_admin_sname_princ(void * handle,krb5_context context,char * sname,int attrs,int lifetime)397 add_admin_sname_princ(void *handle, krb5_context context,
398 char *sname, int attrs, int lifetime)
399 {
400 krb5_error_code ret;
401 krb5_principal principal;
402
403 if (ret = krb5_sname_to_principal(context, NULL, sname,
404 KRB5_NT_SRV_HST, &principal)) {
405 com_err(progname, ret,
406 gettext("Could not get host based "
407 "service name for %s principal\n"), sname);
408 return (ERR);
409 }
410 return (add_admin_princ(handle, context, principal, attrs, lifetime));
411 }
412
413
414
415