10Sstevel@tonic-gate /* 2*2881Smp153739 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate 80Sstevel@tonic-gate /* 90Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 100Sstevel@tonic-gate * 110Sstevel@tonic-gate * Openvision retains the copyright to derivative works of 120Sstevel@tonic-gate * this source code. Do *NOT* create a derivative of this 130Sstevel@tonic-gate * source code before consulting with your legal department. 140Sstevel@tonic-gate * Do *NOT* integrate *ANY* of this source code into another 150Sstevel@tonic-gate * product before consulting with your legal department. 160Sstevel@tonic-gate * 170Sstevel@tonic-gate * For further information, read the top-level Openvision 180Sstevel@tonic-gate * copyright which is contained in the top-level MIT Kerberos 190Sstevel@tonic-gate * copyright. 200Sstevel@tonic-gate * 210Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 220Sstevel@tonic-gate * 230Sstevel@tonic-gate */ 240Sstevel@tonic-gate 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. 280Sstevel@tonic-gate * 29*2881Smp153739 * $Id: server_init.c,v 1.8 2002/10/15 15:40:49 epeisach Exp $ 300Sstevel@tonic-gate * $Source: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_init.c,v $ 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #if !defined(lint) && !defined(__CODECENTER__) 34*2881Smp153739 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 $"; 350Sstevel@tonic-gate #endif 360Sstevel@tonic-gate 370Sstevel@tonic-gate #include <stdio.h> 380Sstevel@tonic-gate #include <stdlib.h> 390Sstevel@tonic-gate #include <com_err.h> 400Sstevel@tonic-gate #include <kadm5/admin.h> 410Sstevel@tonic-gate #include <krb5.h> 420Sstevel@tonic-gate #include "server_internal.h" 430Sstevel@tonic-gate #include <kdb/kdb_log.h> 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* 460Sstevel@tonic-gate * Function check_handle 470Sstevel@tonic-gate * 480Sstevel@tonic-gate * Purpose: Check a server handle and return a com_err code if it is 490Sstevel@tonic-gate * invalid or 0 if it is valid. 500Sstevel@tonic-gate * 510Sstevel@tonic-gate * Arguments: 520Sstevel@tonic-gate * 530Sstevel@tonic-gate * handle The server handle. 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate 560Sstevel@tonic-gate static int check_handle(void *handle) 570Sstevel@tonic-gate { 580Sstevel@tonic-gate CHECK_HANDLE(handle); 590Sstevel@tonic-gate return 0; 600Sstevel@tonic-gate } 610Sstevel@tonic-gate 620Sstevel@tonic-gate kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass, 630Sstevel@tonic-gate char *service_name, 640Sstevel@tonic-gate kadm5_config_params *params, 650Sstevel@tonic-gate krb5_ui_4 struct_version, 660Sstevel@tonic-gate krb5_ui_4 api_version, 670Sstevel@tonic-gate void **server_handle) 680Sstevel@tonic-gate { 690Sstevel@tonic-gate return kadm5_init(client_name, pass, service_name, params, 700Sstevel@tonic-gate struct_version, api_version, 710Sstevel@tonic-gate server_handle); 720Sstevel@tonic-gate } 730Sstevel@tonic-gate 740Sstevel@tonic-gate kadm5_ret_t kadm5_init_with_creds(char *client_name, 750Sstevel@tonic-gate krb5_ccache ccache, 760Sstevel@tonic-gate char *service_name, 770Sstevel@tonic-gate kadm5_config_params *params, 780Sstevel@tonic-gate krb5_ui_4 struct_version, 790Sstevel@tonic-gate krb5_ui_4 api_version, 800Sstevel@tonic-gate void **server_handle) 810Sstevel@tonic-gate { 820Sstevel@tonic-gate /* 830Sstevel@tonic-gate * A program calling init_with_creds *never* expects to prompt the 840Sstevel@tonic-gate * user. Therefore, always pass a dummy password in case this is 850Sstevel@tonic-gate * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and 860Sstevel@tonic-gate * MKEY_FROM_KBD is non-zero, return an error. 870Sstevel@tonic-gate */ 880Sstevel@tonic-gate if (api_version == KADM5_API_VERSION_2 && params && 890Sstevel@tonic-gate (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && 900Sstevel@tonic-gate params->mkey_from_kbd) 910Sstevel@tonic-gate return KADM5_BAD_SERVER_PARAMS; 920Sstevel@tonic-gate return kadm5_init(client_name, NULL, service_name, params, 930Sstevel@tonic-gate struct_version, api_version, 940Sstevel@tonic-gate server_handle); 950Sstevel@tonic-gate } 960Sstevel@tonic-gate 970Sstevel@tonic-gate 980Sstevel@tonic-gate kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab, 990Sstevel@tonic-gate char *service_name, 1000Sstevel@tonic-gate kadm5_config_params *params, 1010Sstevel@tonic-gate krb5_ui_4 struct_version, 1020Sstevel@tonic-gate krb5_ui_4 api_version, 1030Sstevel@tonic-gate void **server_handle) 1040Sstevel@tonic-gate { 1050Sstevel@tonic-gate /* 1060Sstevel@tonic-gate * A program calling init_with_skey *never* expects to prompt the 1070Sstevel@tonic-gate * user. Therefore, always pass a dummy password in case this is 1080Sstevel@tonic-gate * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and 1090Sstevel@tonic-gate * MKEY_FROM_KBD is non-zero, return an error. 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate if (api_version == KADM5_API_VERSION_2 && params && 1120Sstevel@tonic-gate (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && 1130Sstevel@tonic-gate params->mkey_from_kbd) 1140Sstevel@tonic-gate return KADM5_BAD_SERVER_PARAMS; 1150Sstevel@tonic-gate return kadm5_init(client_name, NULL, service_name, params, 1160Sstevel@tonic-gate struct_version, api_version, 1170Sstevel@tonic-gate server_handle); 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate kadm5_ret_t kadm5_init(char *client_name, char *pass, 1210Sstevel@tonic-gate char *service_name, 1220Sstevel@tonic-gate kadm5_config_params *params_in, 1230Sstevel@tonic-gate krb5_ui_4 struct_version, 1240Sstevel@tonic-gate krb5_ui_4 api_version, 1250Sstevel@tonic-gate void **server_handle) 1260Sstevel@tonic-gate { 1270Sstevel@tonic-gate int ret; 1280Sstevel@tonic-gate kadm5_server_handle_t handle; 1290Sstevel@tonic-gate kadm5_config_params params_local; /* for v1 compat */ 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate if (! server_handle) 1320Sstevel@tonic-gate return EINVAL; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate if (! client_name) 1350Sstevel@tonic-gate return EINVAL; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate if (! (handle = (kadm5_server_handle_t) malloc(sizeof *handle))) 1380Sstevel@tonic-gate return ENOMEM; 1390Sstevel@tonic-gate memset(handle, 0, sizeof(*handle)); 1400Sstevel@tonic-gate 141*2881Smp153739 ret = (int) krb5_init_context(&(handle->context)); 142*2881Smp153739 if (ret) { 1430Sstevel@tonic-gate free(handle); 1440Sstevel@tonic-gate return(ret); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate handle->magic_number = KADM5_SERVER_HANDLE_MAGIC; 1480Sstevel@tonic-gate handle->struct_version = struct_version; 1490Sstevel@tonic-gate handle->api_version = api_version; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate /* 1520Sstevel@tonic-gate * Verify the version numbers before proceeding; we can't use 1530Sstevel@tonic-gate * CHECK_HANDLE because not all fields are set yet. 1540Sstevel@tonic-gate */ 1550Sstevel@tonic-gate GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION, 1560Sstevel@tonic-gate KADM5_NEW_SERVER_API_VERSION); 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * Acquire relevant profile entries. In version 2, merge values 1600Sstevel@tonic-gate * in params_in with values from profile, based on 1610Sstevel@tonic-gate * params_in->mask. 1620Sstevel@tonic-gate * 1630Sstevel@tonic-gate * In version 1, we've given a realm (which may be NULL) instead 1640Sstevel@tonic-gate * of params_in. So use that realm, make params_in contain an 1650Sstevel@tonic-gate * empty mask, and behave like version 2. 1660Sstevel@tonic-gate */ 1670Sstevel@tonic-gate memset((char *) ¶ms_local, 0, sizeof(params_local)); 1680Sstevel@tonic-gate if (api_version == KADM5_API_VERSION_1) { 1690Sstevel@tonic-gate params_local.realm = (char *) params_in; 1700Sstevel@tonic-gate if (params_in) 1710Sstevel@tonic-gate params_local.mask = KADM5_CONFIG_REALM; 1720Sstevel@tonic-gate params_in = ¶ms_local; 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate #define ILLEGAL_PARAMS (KADM5_CONFIG_ADMIN_SERVER) 1760Sstevel@tonic-gate if (params_in && (params_in->mask & ILLEGAL_PARAMS)) { 1770Sstevel@tonic-gate krb5_free_context(handle->context); 1780Sstevel@tonic-gate free(handle); 1790Sstevel@tonic-gate return KADM5_BAD_SERVER_PARAMS; 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 182*2881Smp153739 ret = kadm5_get_config_params(handle->context, (char *) NULL, 183*2881Smp153739 (char *) NULL, params_in, 184*2881Smp153739 &handle->params); 185*2881Smp153739 if (ret) { 1860Sstevel@tonic-gate krb5_free_context(handle->context); 1870Sstevel@tonic-gate free(handle); 1880Sstevel@tonic-gate return(ret); 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate #define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \ 1920Sstevel@tonic-gate KADM5_CONFIG_ADBNAME | \ 1930Sstevel@tonic-gate KADM5_CONFIG_ADB_LOCKFILE | \ 1940Sstevel@tonic-gate KADM5_CONFIG_ENCTYPE | \ 1950Sstevel@tonic-gate KADM5_CONFIG_FLAGS | \ 1960Sstevel@tonic-gate KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \ 1970Sstevel@tonic-gate KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES) 198*2881Smp153739 1990Sstevel@tonic-gate if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { 2000Sstevel@tonic-gate krb5_free_context(handle->context); 2010Sstevel@tonic-gate free(handle); 2020Sstevel@tonic-gate return KADM5_MISSING_CONF_PARAMS; 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate 205*2881Smp153739 /* 206*2881Smp153739 * Set the db_name based on configuration before calling 207*2881Smp153739 * krb5_db_init, so it will get used. 208*2881Smp153739 */ 209*2881Smp153739 210*2881Smp153739 ret = krb5_db_set_name(handle->context, handle->params.dbname); 211*2881Smp153739 if (ret) { 2120Sstevel@tonic-gate free(handle); 2130Sstevel@tonic-gate return(ret); 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 216*2881Smp153739 ret = krb5_db_init(handle->context); 217*2881Smp153739 if (ret) { 2180Sstevel@tonic-gate krb5_free_context(handle->context); 2190Sstevel@tonic-gate free(handle); 2200Sstevel@tonic-gate return(ret); 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate if ((ret = krb5_parse_name(handle->context, client_name, 2240Sstevel@tonic-gate &handle->current_caller))) { 2250Sstevel@tonic-gate krb5_db_fini(handle->context); 2260Sstevel@tonic-gate krb5_free_context(handle->context); 2270Sstevel@tonic-gate free(handle); 2280Sstevel@tonic-gate return ret; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 231*2881Smp153739 if (! (handle->lhandle = malloc(sizeof(*handle)))) { 232*2881Smp153739 krb5_db_fini(handle->context); 233*2881Smp153739 krb5_free_context(handle->context); 2340Sstevel@tonic-gate free(handle); 235*2881Smp153739 return ENOMEM; 2360Sstevel@tonic-gate } 237*2881Smp153739 *handle->lhandle = *handle; 238*2881Smp153739 handle->lhandle->api_version = KADM5_API_VERSION_2; 239*2881Smp153739 handle->lhandle->struct_version = KADM5_STRUCT_VERSION; 240*2881Smp153739 handle->lhandle->lhandle = handle->lhandle; 2410Sstevel@tonic-gate 242*2881Smp153739 /* can't check the handle until current_caller is set */ 243*2881Smp153739 ret = check_handle((void *) handle); 244*2881Smp153739 if (ret) { 245*2881Smp153739 free(handle); 246*2881Smp153739 return ret; 247*2881Smp153739 } 248*2881Smp153739 249*2881Smp153739 /* 250*2881Smp153739 * The KADM5_API_VERSION_1 spec said "If pass (or keytab) is NULL 251*2881Smp153739 * or an empty string, reads the master password from [the stash 252*2881Smp153739 * file]. Otherwise, the non-NULL password is ignored and the 253*2881Smp153739 * user is prompted for it via the tty." However, the code was 254*2881Smp153739 * implemented the other way: when a non-NULL password was 255*2881Smp153739 * provided, the stash file was used. This is somewhat more 256*2881Smp153739 * sensible, as then a local or remote client that provides a 257*2881Smp153739 * password does not prompt the user. This code maintains the 258*2881Smp153739 * previous actual behavior, and not the old spec behavior, 259*2881Smp153739 * because that is how the unit tests are written. 260*2881Smp153739 * 261*2881Smp153739 * In KADM5_API_VERSION_2, this decision is controlled by 262*2881Smp153739 * params. 263*2881Smp153739 * 264*2881Smp153739 * kdb_init_master's third argument is "from_keyboard". 265*2881Smp153739 */ 266*2881Smp153739 ret = kdb_init_master(handle, handle->params.realm, 267*2881Smp153739 (handle->api_version == KADM5_API_VERSION_1 ? 268*2881Smp153739 ((pass == NULL) || !(strlen(pass))) : 269*2881Smp153739 ((handle->params.mask & KADM5_CONFIG_MKEY_FROM_KBD) 270*2881Smp153739 && handle->params.mkey_from_kbd) 271*2881Smp153739 )); 272*2881Smp153739 if (ret) { 273*2881Smp153739 krb5_db_fini(handle->context); 274*2881Smp153739 krb5_free_context(handle->context); 275*2881Smp153739 free(handle); 276*2881Smp153739 return ret; 277*2881Smp153739 } 278*2881Smp153739 279*2881Smp153739 ret = kdb_init_hist(handle, handle->params.realm); 280*2881Smp153739 if (ret) { 2810Sstevel@tonic-gate krb5_db_fini(handle->context); 2820Sstevel@tonic-gate krb5_free_context(handle->context); 2830Sstevel@tonic-gate free(handle); 2840Sstevel@tonic-gate return ret; 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate 287*2881Smp153739 ret = init_dict(&handle->params); 288*2881Smp153739 if (ret) { 289*2881Smp153739 krb5_db_fini(handle->context); 2900Sstevel@tonic-gate krb5_free_principal(handle->context, handle->current_caller); 2910Sstevel@tonic-gate krb5_free_context(handle->context); 2920Sstevel@tonic-gate free(handle); 2930Sstevel@tonic-gate return ret; 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 296*2881Smp153739 ret = adb_policy_init(handle); 297*2881Smp153739 if (ret) { 2980Sstevel@tonic-gate krb5_db_fini(handle->context); 2990Sstevel@tonic-gate krb5_free_principal(handle->context, handle->current_caller); 3000Sstevel@tonic-gate krb5_free_context(handle->context); 3010Sstevel@tonic-gate free(handle); 3020Sstevel@tonic-gate return ret; 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate handle->lhandle->policy_db = handle->policy_db; 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate *server_handle = (void *) handle; 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate return KADM5_OK; 3090Sstevel@tonic-gate } 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate kadm5_ret_t kadm5_destroy(void *server_handle) 3120Sstevel@tonic-gate { 3130Sstevel@tonic-gate kadm5_server_handle_t handle = server_handle; 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate CHECK_HANDLE(server_handle); 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate destroy_dict(); 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate adb_policy_close(handle); 3200Sstevel@tonic-gate krb5_db_fini(handle->context); 3210Sstevel@tonic-gate krb5_free_principal(handle->context, handle->current_caller); 3220Sstevel@tonic-gate kadm5_free_config_params(handle->context, &handle->params); 3230Sstevel@tonic-gate krb5_free_context(handle->context); 3240Sstevel@tonic-gate handle->magic_number = 0; 3250Sstevel@tonic-gate free(handle->lhandle); 3260Sstevel@tonic-gate free(handle); 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate return KADM5_OK; 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate 331*2881Smp153739 kadm5_ret_t kadm5_lock(void *server_handle) 332*2881Smp153739 { 333*2881Smp153739 kadm5_server_handle_t handle = server_handle; 334*2881Smp153739 kadm5_ret_t ret; 335*2881Smp153739 336*2881Smp153739 CHECK_HANDLE(server_handle); 337*2881Smp153739 ret = osa_adb_open_and_lock(handle->policy_db, OSA_ADB_EXCLUSIVE); 338*2881Smp153739 if (ret) 339*2881Smp153739 return ret; 340*2881Smp153739 ret = krb5_db_lock(handle->context, KRB5_LOCKMODE_EXCLUSIVE); 341*2881Smp153739 if (ret) 342*2881Smp153739 return ret; 343*2881Smp153739 344*2881Smp153739 return KADM5_OK; 345*2881Smp153739 } 346*2881Smp153739 347*2881Smp153739 kadm5_ret_t kadm5_unlock(void *server_handle) 348*2881Smp153739 { 349*2881Smp153739 kadm5_server_handle_t handle = server_handle; 350*2881Smp153739 kadm5_ret_t ret; 351*2881Smp153739 352*2881Smp153739 CHECK_HANDLE(server_handle); 353*2881Smp153739 ret = osa_adb_close_and_unlock(handle->policy_db); 354*2881Smp153739 if (ret) 355*2881Smp153739 return ret; 356*2881Smp153739 ret = krb5_db_unlock(handle->context); 357*2881Smp153739 if (ret) 358*2881Smp153739 return ret; 359*2881Smp153739 360*2881Smp153739 return KADM5_OK; 361*2881Smp153739 } 362*2881Smp153739 3630Sstevel@tonic-gate kadm5_ret_t kadm5_flush(void *server_handle) 3640Sstevel@tonic-gate { 3650Sstevel@tonic-gate kadm5_server_handle_t handle = server_handle; 3660Sstevel@tonic-gate kadm5_ret_t ret; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate CHECK_HANDLE(server_handle); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate if ((ret = krb5_db_fini(handle->context)) || 3710Sstevel@tonic-gate /* 3720Sstevel@tonic-gate * Set the db_name based on configuration before calling 3730Sstevel@tonic-gate * krb5_db_init, so it will get used. 3740Sstevel@tonic-gate */ 3750Sstevel@tonic-gate (ret = krb5_db_set_name(handle->context, 3760Sstevel@tonic-gate handle->params.dbname)) || 3770Sstevel@tonic-gate (ret = krb5_db_init(handle->context)) || 3780Sstevel@tonic-gate (ret = adb_policy_close(handle)) || 3790Sstevel@tonic-gate (ret = adb_policy_init(handle))) { 3800Sstevel@tonic-gate (void) kadm5_destroy(server_handle); 3810Sstevel@tonic-gate return ret; 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate return KADM5_OK; 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate int _kadm5_check_handle(void *handle) 3870Sstevel@tonic-gate { 3880Sstevel@tonic-gate CHECK_HANDLE(handle); 3890Sstevel@tonic-gate return 0; 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate krb5_error_code 3930Sstevel@tonic-gate kadm5_init_iprop(void *handle) 3940Sstevel@tonic-gate { 3950Sstevel@tonic-gate kadm5_server_handle_t iprop_h; 3960Sstevel@tonic-gate krb5_error_code retval; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate iprop_h = handle; 3990Sstevel@tonic-gate if (iprop_h->params.iprop_enabled) { 4000Sstevel@tonic-gate ulog_set_role(iprop_h->context, IPROP_MASTER); 4010Sstevel@tonic-gate if ((retval = ulog_map(iprop_h->context, &iprop_h->params, 4020Sstevel@tonic-gate FKCOMMAND)) != 0) 4030Sstevel@tonic-gate return (retval); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate return (0); 4060Sstevel@tonic-gate } 407