dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / krb5 / kadm5 / srv / server_init.c
blob59014a82460f90bfa72b804f8815d61d0dd8f0e2
1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
7 /*
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
18 * copyright.
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 $
29 * $Source$
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 $";
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <com_err.h>
38 #include "k5-int.h" /* needed for gssapiP_krb5.h */
39 #include <kadm5/admin.h>
40 #include <krb5.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.
50 * Arguments:
52 * handle The server handle.
55 static int check_handle(void *handle)
57 CHECK_HANDLE(handle);
58 return 0;
61 static int dup_db_args(kadm5_server_handle_t handle, char **db_args)
63 int count = 0;
64 int ret = 0;
66 for (count=0; db_args && db_args[count]; count++);
67 if (count == 0) {
68 handle->db_args = NULL;
69 goto clean_n_exit;
72 handle->db_args = calloc(sizeof(char*), count+1);
73 if (handle->db_args == NULL) {
74 ret=ENOMEM;
75 goto clean_n_exit;
78 for (count=0; db_args[count]; count++) {
79 handle->db_args[count] = strdup(db_args[count]);
80 if (handle->db_args[count] == NULL) {
81 ret = ENOMEM;
82 goto clean_n_exit;
86 clean_n_exit:
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;
94 return ret;
97 static void free_db_args(kadm5_server_handle_t handle)
99 int count;
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,
110 char *service_name,
111 kadm5_config_params *params,
112 krb5_ui_4 struct_version,
113 krb5_ui_4 api_version,
114 char **db_args,
115 void **server_handle)
117 return kadm5_init(client_name, pass, service_name, params,
118 struct_version, api_version, db_args,
119 server_handle);
122 kadm5_ret_t kadm5_init_with_creds(char *client_name,
123 krb5_ccache ccache,
124 char *service_name,
125 kadm5_config_params *params,
126 krb5_ui_4 struct_version,
127 krb5_ui_4 api_version,
128 char **db_args,
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,
143 server_handle);
147 kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab,
148 char *service_name,
149 kadm5_config_params *params,
150 krb5_ui_4 struct_version,
151 krb5_ui_4 api_version,
152 char **db_args,
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,
167 server_handle);
171 * Solaris Kerberos:
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,
176 char *service_name,
177 kadm5_config_params *params_in,
178 krb5_ui_4 struct_version,
179 krb5_ui_4 api_version,
180 char **db_args,
181 void **server_handle,
182 char **emsg)
184 int ret;
185 kadm5_server_handle_t handle;
186 kadm5_config_params params_local; /* for v1 compat */
188 if (emsg)
189 *emsg = NULL;
191 if (! server_handle)
192 return EINVAL;
194 if (! client_name)
195 return EINVAL;
197 if (! (handle = (kadm5_server_handle_t) malloc(sizeof *handle)))
198 return ENOMEM;
199 memset(handle, 0, sizeof(*handle));
201 ret = dup_db_args(handle, db_args);
202 if (ret) {
203 free(handle);
204 return ret;
207 ret = (int) krb5int_init_context_kdc(&(handle->context));
208 if (ret) {
209 free_db_args(handle);
210 free(handle);
211 return(ret);
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
228 * params_in->mask.
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 *) &params_local, 0, sizeof(params_local));
235 if (api_version == KADM5_API_VERSION_1) {
236 params_local.realm = (char *) params_in;
237 if (params_in)
238 params_local.mask = KADM5_CONFIG_REALM;
239 params_in = &params_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);
248 free(handle);
249 return KADM5_BAD_SERVER_PARAMS;
251 #endif
253 ret = kadm5_get_config_params(handle->context, 1, params_in,
254 &handle->params);
255 if (ret) {
256 krb5_free_context(handle->context);
257 free_db_args(handle);
258 free(handle);
259 return(ret);
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);
274 free(handle);
275 return KADM5_MISSING_CONF_PARAMS;
278 ret = krb5_set_default_realm(handle->context, handle->params.realm);
279 if (ret) {
280 kadm5_free_config_params(handle->context, &handle->params);
281 krb5_free_context(handle->context);
282 free_db_args(handle);
283 free(handle);
284 return ret;
287 ret = krb5_db_open(handle->context, db_args,
288 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
289 if (ret) {
290 if (emsg) {
291 const char *m = krb5_get_error_message(handle->context, ret);
292 *emsg = strdup(m);
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);
298 free(handle);
299 return(ret);
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);
308 free(handle);
309 return ret;
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);
317 free(handle);
318 return ENOMEM;
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);
327 if (ret) {
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);
332 free(handle);
333 return ret;
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
349 * params.
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)
366 if (ret) {
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);
371 free(handle);
372 return ret;
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);
381 if (ret) {
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);
386 free(handle);
387 return ret;
390 ret = init_dict(&handle->params);
391 if (ret) {
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);
397 free(handle);
398 return ret;
401 *server_handle = (void *) handle;
403 return KADM5_OK;
406 kadm5_ret_t kadm5_init(char *client_name, char *pass,
407 char *service_name,
408 kadm5_config_params *params_in,
409 krb5_ui_4 struct_version,
410 krb5_ui_4 api_version,
411 char **db_args,
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);
424 destroy_dict();
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);
434 free(handle);
436 return KADM5_OK;
439 kadm5_ret_t kadm5_lock(void *server_handle)
441 kadm5_server_handle_t handle = server_handle;
442 kadm5_ret_t ret;
444 CHECK_HANDLE(server_handle);
445 ret = krb5_db_lock(handle->context, KRB5_DB_LOCKMODE_EXCLUSIVE);
446 if (ret)
447 return ret;
449 return KADM5_OK;
452 kadm5_ret_t kadm5_unlock(void *server_handle)
454 kadm5_server_handle_t handle = server_handle;
455 kadm5_ret_t ret;
457 CHECK_HANDLE(server_handle);
458 ret = krb5_db_unlock(handle->context);
459 if (ret)
460 return ret;
462 return KADM5_OK;
465 kadm5_ret_t kadm5_flush(void *server_handle)
467 kadm5_server_handle_t handle = server_handle;
468 kadm5_ret_t ret;
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);
478 return ret;
480 return KADM5_OK;
483 int _kadm5_check_handle(void *handle)
485 CHECK_HANDLE(handle);
486 return 0;
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;
495 if (first_time) {
496 krb5_error_code err;
497 err = krb5_gss_use_kdc_context();
498 if (err)
499 return err;
500 first_time = 0;
502 #endif /**************** END IFDEF'ed OUT *******************************/
503 return krb5int_init_context_kdc(ctx);
506 krb5_error_code
507 kadm5_init_iprop(void *handle)
509 kadm5_server_handle_t iprop_h;
510 krb5_error_code retval;
512 iprop_h = handle;
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,
516 FKCOMMAND)) != 0)
517 return (retval);
519 return (0);