2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
10 * Openvision retains the copyright to derivative works of
11 * this source code. Do *NOT* create a derivative of this
12 * source code before consulting with your legal department.
13 * Do *NOT* integrate *ANY* of this source code into another
14 * product before consulting with your legal department.
16 * For further information, read the top-level Openvision
17 * copyright which is contained in the top-level MIT Kerberos
20 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
26 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
28 * $Id: server_init.c 18584 2006-09-13 20:30:23Z raeburn $
32 static char *rcsid
= "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_init.c,v 1.8 2002/10/15 15:40:49 epeisach Exp $";
38 #include "k5-int.h" /* needed for gssapiP_krb5.h */
39 #include <kadm5/admin.h>
41 #include "server_internal.h"
42 #include <kdb/kdb_log.h>
45 * Function check_handle
47 * Purpose: Check a server handle and return a com_err code if it is
48 * invalid or 0 if it is valid.
52 * handle The server handle.
55 static int check_handle(void *handle
)
61 static int dup_db_args(kadm5_server_handle_t handle
, char **db_args
)
66 for (count
=0; db_args
&& db_args
[count
]; count
++);
68 handle
->db_args
= NULL
;
72 handle
->db_args
= calloc(sizeof(char*), count
+1);
73 if (handle
->db_args
== NULL
) {
78 for (count
=0; db_args
[count
]; count
++) {
79 handle
->db_args
[count
] = strdup(db_args
[count
]);
80 if (handle
->db_args
[count
] == NULL
) {
87 if (ret
&& handle
->db_args
) {
88 for (count
=0; handle
->db_args
[count
]; count
++)
89 free(handle
->db_args
[count
]);
91 free(handle
->db_args
), handle
->db_args
= NULL
;
97 static void free_db_args(kadm5_server_handle_t handle
)
101 if (handle
->db_args
) {
102 for (count
=0; handle
->db_args
[count
]; count
++)
103 free(handle
->db_args
[count
]);
105 free(handle
->db_args
), handle
->db_args
= NULL
;
109 kadm5_ret_t
kadm5_init_with_password(char *client_name
, char *pass
,
111 kadm5_config_params
*params
,
112 krb5_ui_4 struct_version
,
113 krb5_ui_4 api_version
,
115 void **server_handle
)
117 return kadm5_init(client_name
, pass
, service_name
, params
,
118 struct_version
, api_version
, db_args
,
122 kadm5_ret_t
kadm5_init_with_creds(char *client_name
,
125 kadm5_config_params
*params
,
126 krb5_ui_4 struct_version
,
127 krb5_ui_4 api_version
,
129 void **server_handle
)
132 * A program calling init_with_creds *never* expects to prompt the
133 * user. Therefore, always pass a dummy password in case this is
134 * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and
135 * MKEY_FROM_KBD is non-zero, return an error.
137 if (api_version
== KADM5_API_VERSION_2
&& params
&&
138 (params
->mask
& KADM5_CONFIG_MKEY_FROM_KBD
) &&
139 params
->mkey_from_kbd
)
140 return KADM5_BAD_SERVER_PARAMS
;
141 return kadm5_init(client_name
, NULL
, service_name
, params
,
142 struct_version
, api_version
, db_args
,
147 kadm5_ret_t
kadm5_init_with_skey(char *client_name
, char *keytab
,
149 kadm5_config_params
*params
,
150 krb5_ui_4 struct_version
,
151 krb5_ui_4 api_version
,
153 void **server_handle
)
156 * A program calling init_with_skey *never* expects to prompt the
157 * user. Therefore, always pass a dummy password in case this is
158 * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and
159 * MKEY_FROM_KBD is non-zero, return an error.
161 if (api_version
== KADM5_API_VERSION_2
&& params
&&
162 (params
->mask
& KADM5_CONFIG_MKEY_FROM_KBD
) &&
163 params
->mkey_from_kbd
)
164 return KADM5_BAD_SERVER_PARAMS
;
165 return kadm5_init(client_name
, NULL
, service_name
, params
,
166 struct_version
, api_version
, db_args
,
172 * A private extended version of kadm5_init which potentially
173 * returns more information in case of an error.
175 kadm5_ret_t
kadm5_init2(char *client_name
, char *pass
,
177 kadm5_config_params
*params_in
,
178 krb5_ui_4 struct_version
,
179 krb5_ui_4 api_version
,
181 void **server_handle
,
185 kadm5_server_handle_t handle
;
186 kadm5_config_params params_local
; /* for v1 compat */
197 if (! (handle
= (kadm5_server_handle_t
) malloc(sizeof *handle
)))
199 memset(handle
, 0, sizeof(*handle
));
201 ret
= dup_db_args(handle
, db_args
);
207 ret
= (int) krb5int_init_context_kdc(&(handle
->context
));
209 free_db_args(handle
);
214 handle
->magic_number
= KADM5_SERVER_HANDLE_MAGIC
;
215 handle
->struct_version
= struct_version
;
216 handle
->api_version
= api_version
;
219 * Verify the version numbers before proceeding; we can't use
220 * CHECK_HANDLE because not all fields are set yet.
222 GENERIC_CHECK_HANDLE(handle
, KADM5_OLD_SERVER_API_VERSION
,
223 KADM5_NEW_SERVER_API_VERSION
);
226 * Acquire relevant profile entries. In version 2, merge values
227 * in params_in with values from profile, based on
230 * In version 1, we've given a realm (which may be NULL) instead
231 * of params_in. So use that realm, make params_in contain an
232 * empty mask, and behave like version 2.
234 memset((char *) ¶ms_local
, 0, sizeof(params_local
));
235 if (api_version
== KADM5_API_VERSION_1
) {
236 params_local
.realm
= (char *) params_in
;
238 params_local
.mask
= KADM5_CONFIG_REALM
;
239 params_in
= ¶ms_local
;
242 #if 0 /* Now that we look at krb5.conf as well as kdc.conf, we can
243 expect to see admin_server being set sometimes. */
244 #define ILLEGAL_PARAMS (KADM5_CONFIG_ADMIN_SERVER)
245 if (params_in
&& (params_in
->mask
& ILLEGAL_PARAMS
)) {
246 krb5_free_context(handle
->context
);
247 free_db_args(handle
);
249 return KADM5_BAD_SERVER_PARAMS
;
253 ret
= kadm5_get_config_params(handle
->context
, 1, params_in
,
256 krb5_free_context(handle
->context
);
257 free_db_args(handle
);
262 #define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \
263 KADM5_CONFIG_ADBNAME | \
264 KADM5_CONFIG_ADB_LOCKFILE | \
265 KADM5_CONFIG_ENCTYPE | \
266 KADM5_CONFIG_FLAGS | \
267 KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \
268 KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES)
270 if ((handle
->params
.mask
& REQUIRED_PARAMS
) != REQUIRED_PARAMS
) {
271 kadm5_free_config_params(handle
->context
, &handle
->params
);
272 krb5_free_context(handle
->context
);
273 free_db_args(handle
);
275 return KADM5_MISSING_CONF_PARAMS
;
278 ret
= krb5_set_default_realm(handle
->context
, handle
->params
.realm
);
280 kadm5_free_config_params(handle
->context
, &handle
->params
);
281 krb5_free_context(handle
->context
);
282 free_db_args(handle
);
287 ret
= krb5_db_open(handle
->context
, db_args
,
288 KRB5_KDB_OPEN_RW
| KRB5_KDB_SRV_TYPE_ADMIN
);
291 const char *m
= krb5_get_error_message(handle
->context
, ret
);
293 krb5_free_error_message(handle
->context
, m
);
295 kadm5_free_config_params(handle
->context
, &handle
->params
);
296 krb5_free_context(handle
->context
);
297 free_db_args(handle
);
302 if ((ret
= krb5_parse_name(handle
->context
, client_name
,
303 &handle
->current_caller
))) {
304 krb5_db_fini(handle
->context
);
305 kadm5_free_config_params(handle
->context
, &handle
->params
);
306 krb5_free_context(handle
->context
);
307 free_db_args(handle
);
312 if (! (handle
->lhandle
= malloc(sizeof(*handle
)))) {
313 krb5_db_fini(handle
->context
);
314 kadm5_free_config_params(handle
->context
, &handle
->params
);
315 krb5_free_context(handle
->context
);
316 free_db_args(handle
);
320 *handle
->lhandle
= *handle
;
321 handle
->lhandle
->api_version
= KADM5_API_VERSION_2
;
322 handle
->lhandle
->struct_version
= KADM5_STRUCT_VERSION
;
323 handle
->lhandle
->lhandle
= handle
->lhandle
;
325 /* can't check the handle until current_caller is set */
326 ret
= check_handle((void *) handle
);
328 krb5_db_fini(handle
->context
);
329 kadm5_free_config_params(handle
->context
, &handle
->params
);
330 krb5_free_context(handle
->context
);
331 free_db_args(handle
);
337 * The KADM5_API_VERSION_1 spec said "If pass (or keytab) is NULL
338 * or an empty string, reads the master password from [the stash
339 * file]. Otherwise, the non-NULL password is ignored and the
340 * user is prompted for it via the tty." However, the code was
341 * implemented the other way: when a non-NULL password was
342 * provided, the stash file was used. This is somewhat more
343 * sensible, as then a local or remote client that provides a
344 * password does not prompt the user. This code maintains the
345 * previous actual behavior, and not the old spec behavior,
346 * because that is how the unit tests are written.
348 * In KADM5_API_VERSION_2, this decision is controlled by
351 * kdb_init_master's third argument is "from_keyboard".
354 * Solaris Kerberos: Setting to an unknown enc type will make the function
355 * read the encryption type in the stash file instead of assumming that it
356 * is the default type.
358 if (handle
->params
.enctype
== DEFAULT_KDC_ENCTYPE
)
359 handle
->params
.enctype
= ENCTYPE_UNKNOWN
;
360 ret
= kdb_init_master(handle
, handle
->params
.realm
,
361 (handle
->api_version
== KADM5_API_VERSION_1
?
362 ((pass
== NULL
) || !(strlen(pass
))) :
363 ((handle
->params
.mask
& KADM5_CONFIG_MKEY_FROM_KBD
)
364 && handle
->params
.mkey_from_kbd
)
367 krb5_db_fini(handle
->context
);
368 kadm5_free_config_params(handle
->context
, &handle
->params
);
369 krb5_free_context(handle
->context
);
370 free_db_args(handle
);
375 * Solaris Kerberos: We used the enc type that was discovered in the stash
376 * file to associate with the other magic principals in the database.
378 handle
->params
.enctype
= handle
->master_keyblock
.enctype
;
380 ret
= kdb_init_hist(handle
, handle
->params
.realm
);
382 krb5_db_fini(handle
->context
);
383 kadm5_free_config_params(handle
->context
, &handle
->params
);
384 krb5_free_context(handle
->context
);
385 free_db_args(handle
);
390 ret
= init_dict(&handle
->params
);
392 krb5_db_fini(handle
->context
);
393 krb5_free_principal(handle
->context
, handle
->current_caller
);
394 kadm5_free_config_params(handle
->context
, &handle
->params
);
395 krb5_free_context(handle
->context
);
396 free_db_args(handle
);
401 *server_handle
= (void *) handle
;
406 kadm5_ret_t
kadm5_init(char *client_name
, char *pass
,
408 kadm5_config_params
*params_in
,
409 krb5_ui_4 struct_version
,
410 krb5_ui_4 api_version
,
412 void **server_handle
) {
413 return (kadm5_init2(client_name
, pass
, service_name
, params_in
,
414 struct_version
, api_version
, db_args
, server_handle
, NULL
));
418 kadm5_ret_t
kadm5_destroy(void *server_handle
)
420 kadm5_server_handle_t handle
= server_handle
;
422 CHECK_HANDLE(server_handle
);
426 adb_policy_close(handle
);
427 krb5_db_fini(handle
->context
);
428 krb5_free_principal(handle
->context
, handle
->current_caller
);
429 kadm5_free_config_params(handle
->context
, &handle
->params
);
430 krb5_free_context(handle
->context
);
431 handle
->magic_number
= 0;
432 free(handle
->lhandle
);
433 free_db_args(handle
);
439 kadm5_ret_t
kadm5_lock(void *server_handle
)
441 kadm5_server_handle_t handle
= server_handle
;
444 CHECK_HANDLE(server_handle
);
445 ret
= krb5_db_lock(handle
->context
, KRB5_DB_LOCKMODE_EXCLUSIVE
);
452 kadm5_ret_t
kadm5_unlock(void *server_handle
)
454 kadm5_server_handle_t handle
= server_handle
;
457 CHECK_HANDLE(server_handle
);
458 ret
= krb5_db_unlock(handle
->context
);
465 kadm5_ret_t
kadm5_flush(void *server_handle
)
467 kadm5_server_handle_t handle
= server_handle
;
470 CHECK_HANDLE(server_handle
);
472 if ((ret
= krb5_db_fini(handle
->context
)) ||
473 (ret
= krb5_db_open(handle
->context
, handle
->db_args
,
474 KRB5_KDB_OPEN_RW
| KRB5_KDB_SRV_TYPE_ADMIN
)) ||
475 (ret
= adb_policy_close(handle
)) ||
476 (ret
= adb_policy_init(handle
))) {
477 (void) kadm5_destroy(server_handle
);
483 int _kadm5_check_handle(void *handle
)
485 CHECK_HANDLE(handle
);
489 #include "gssapiP_krb5.h"
490 krb5_error_code
kadm5_init_krb5_context (krb5_context
*ctx
)
492 /* Solaris Kerberos: not needed */
493 #if 0 /************** Begin IFDEF'ed OUT *******************************/
494 static int first_time
= 1;
497 err
= krb5_gss_use_kdc_context();
502 #endif /**************** END IFDEF'ed OUT *******************************/
503 return krb5int_init_context_kdc(ctx
);
507 kadm5_init_iprop(void *handle
)
509 kadm5_server_handle_t iprop_h
;
510 krb5_error_code retval
;
513 if (iprop_h
->params
.iprop_enabled
) {
514 ulog_set_role(iprop_h
->context
, IPROP_MASTER
);
515 if ((retval
= ulog_map(iprop_h
->context
, &iprop_h
->params
,