1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 10 * 11 * Openvision retains the copyright to derivative works of 12 * this source code. Do *NOT* create a derivative of this 13 * source code before consulting with your legal department. 14 * Do *NOT* integrate *ANY* of this source code into another 15 * product before consulting with your legal department. 16 * 17 * For further information, read the top-level Openvision 18 * copyright which is contained in the top-level MIT Kerberos 19 * copyright. 20 * 21 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 22 * 23 */ 24 25 26 /* 27 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. 28 * 29 * $Id: server_init.c,v 1.5 1997/10/13 15:03:13 epeisach Exp $ 30 * $Source: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_init.c,v $ 31 */ 32 33 #if !defined(lint) && !defined(__CODECENTER__) 34 static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_init.c,v 1.5 1997/10/13 15:03:13 epeisach Exp $"; 35 #endif 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <com_err.h> 40 #include <kadm5/admin.h> 41 #include <krb5.h> 42 #include "server_internal.h" 43 #include <kdb/kdb_log.h> 44 45 /* 46 * Function check_handle 47 * 48 * Purpose: Check a server handle and return a com_err code if it is 49 * invalid or 0 if it is valid. 50 * 51 * Arguments: 52 * 53 * handle The server handle. 54 */ 55 56 static int check_handle(void *handle) 57 { 58 CHECK_HANDLE(handle); 59 return 0; 60 } 61 62 kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass, 63 char *service_name, 64 kadm5_config_params *params, 65 krb5_ui_4 struct_version, 66 krb5_ui_4 api_version, 67 void **server_handle) 68 { 69 return kadm5_init(client_name, pass, service_name, params, 70 struct_version, api_version, 71 server_handle); 72 } 73 74 kadm5_ret_t kadm5_init_with_creds(char *client_name, 75 krb5_ccache ccache, 76 char *service_name, 77 kadm5_config_params *params, 78 krb5_ui_4 struct_version, 79 krb5_ui_4 api_version, 80 void **server_handle) 81 { 82 /* 83 * A program calling init_with_creds *never* expects to prompt the 84 * user. Therefore, always pass a dummy password in case this is 85 * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and 86 * MKEY_FROM_KBD is non-zero, return an error. 87 */ 88 if (api_version == KADM5_API_VERSION_2 && params && 89 (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && 90 params->mkey_from_kbd) 91 return KADM5_BAD_SERVER_PARAMS; 92 return kadm5_init(client_name, NULL, service_name, params, 93 struct_version, api_version, 94 server_handle); 95 } 96 97 98 kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab, 99 char *service_name, 100 kadm5_config_params *params, 101 krb5_ui_4 struct_version, 102 krb5_ui_4 api_version, 103 void **server_handle) 104 { 105 /* 106 * A program calling init_with_skey *never* expects to prompt the 107 * user. Therefore, always pass a dummy password in case this is 108 * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and 109 * MKEY_FROM_KBD is non-zero, return an error. 110 */ 111 if (api_version == KADM5_API_VERSION_2 && params && 112 (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && 113 params->mkey_from_kbd) 114 return KADM5_BAD_SERVER_PARAMS; 115 return kadm5_init(client_name, NULL, service_name, params, 116 struct_version, api_version, 117 server_handle); 118 } 119 120 kadm5_ret_t kadm5_init(char *client_name, char *pass, 121 char *service_name, 122 kadm5_config_params *params_in, 123 krb5_ui_4 struct_version, 124 krb5_ui_4 api_version, 125 void **server_handle) 126 { 127 int ret; 128 kadm5_server_handle_t handle; 129 kadm5_config_params params_local; /* for v1 compat */ 130 131 if (! server_handle) 132 return EINVAL; 133 134 if (! client_name) 135 return EINVAL; 136 137 if (! (handle = (kadm5_server_handle_t) malloc(sizeof *handle))) 138 return ENOMEM; 139 memset(handle, 0, sizeof(*handle)); 140 141 if (ret = (int) krb5_init_context(&(handle->context))) { 142 free(handle); 143 return(ret); 144 } 145 146 handle->magic_number = KADM5_SERVER_HANDLE_MAGIC; 147 handle->struct_version = struct_version; 148 handle->api_version = api_version; 149 150 /* 151 * Verify the version numbers before proceeding; we can't use 152 * CHECK_HANDLE because not all fields are set yet. 153 */ 154 GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION, 155 KADM5_NEW_SERVER_API_VERSION); 156 157 /* 158 * Acquire relevant profile entries. In version 2, merge values 159 * in params_in with values from profile, based on 160 * params_in->mask. 161 * 162 * In version 1, we've given a realm (which may be NULL) instead 163 * of params_in. So use that realm, make params_in contain an 164 * empty mask, and behave like version 2. 165 */ 166 memset((char *) ¶ms_local, 0, sizeof(params_local)); 167 if (api_version == KADM5_API_VERSION_1) { 168 params_local.realm = (char *) params_in; 169 if (params_in) 170 params_local.mask = KADM5_CONFIG_REALM; 171 params_in = ¶ms_local; 172 } 173 174 #define ILLEGAL_PARAMS (KADM5_CONFIG_ADMIN_SERVER) 175 if (params_in && (params_in->mask & ILLEGAL_PARAMS)) { 176 krb5_free_context(handle->context); 177 free(handle); 178 return KADM5_BAD_SERVER_PARAMS; 179 } 180 181 if (ret = kadm5_get_config_params(handle->context, 182 (char *) NULL, 183 (char *) NULL, 184 params_in, 185 &handle->params)) { 186 krb5_free_context(handle->context); 187 free(handle); 188 return(ret); 189 } 190 191 #define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \ 192 KADM5_CONFIG_ADBNAME | \ 193 KADM5_CONFIG_ADB_LOCKFILE | \ 194 KADM5_CONFIG_ENCTYPE | \ 195 KADM5_CONFIG_FLAGS | \ 196 KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \ 197 KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES) 198 if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { 199 krb5_free_context(handle->context); 200 free(handle); 201 return KADM5_MISSING_CONF_PARAMS; 202 } 203 204 /* 205 * Set the db_name based on configuration before calling 206 * krb5_db_init, so it will get used. 207 */ 208 if (ret = krb5_db_set_name(handle->context, 209 handle->params.dbname)) { 210 free(handle); 211 return(ret); 212 } 213 214 if (ret = krb5_db_init(handle->context)) { 215 krb5_free_context(handle->context); 216 free(handle); 217 return(ret); 218 } 219 220 if ((ret = krb5_parse_name(handle->context, client_name, 221 &handle->current_caller))) { 222 krb5_db_fini(handle->context); 223 krb5_free_context(handle->context); 224 free(handle); 225 return ret; 226 } 227 228 if (! (handle->lhandle = malloc(sizeof(*handle)))) { 229 krb5_db_fini(handle->context); 230 krb5_free_context(handle->context); 231 free(handle); 232 return ENOMEM; 233 } 234 *handle->lhandle = *handle; 235 handle->lhandle->api_version = KADM5_API_VERSION_2; 236 handle->lhandle->struct_version = KADM5_STRUCT_VERSION; 237 handle->lhandle->lhandle = handle->lhandle; 238 239 /* can't check the handle until current_caller is set */ 240 if (ret = check_handle((void *) handle)) { 241 free(handle); 242 return ret; 243 } 244 245 /* 246 * The KADM5_API_VERSION_1 spec said "If pass (or keytab) is NULL 247 * or an empty string, reads the master password from [the stash 248 * file]. Otherwise, the non-NULL password is ignored and the 249 * user is prompted for it via the tty." However, the code was 250 * implemented the other way: when a non-NULL password was 251 * provided, the stash file was used. This is somewhat more 252 * sensible, as then a local or remote client that provides a 253 * password does not prompt the user. This code maintains the 254 * previous actual behavior, and not the old spec behavior, 255 * because that is how the unit tests are written. 256 * 257 * In KADM5_API_VERSION_2, this decision is controlled by 258 * params. 259 * 260 * kdb_init_master's third argument is "from_keyboard". 261 */ 262 if (ret = kdb_init_master(handle, handle->params.realm, 263 (handle->api_version == KADM5_API_VERSION_1 ? 264 ((pass == NULL) || !(strlen(pass))) : 265 ((handle->params.mask & 266 KADM5_CONFIG_MKEY_FROM_KBD) && 267 handle->params.mkey_from_kbd)) 268 )) { 269 krb5_db_fini(handle->context); 270 krb5_free_context(handle->context); 271 free(handle); 272 return ret; 273 } 274 275 if ((ret = kdb_init_hist(handle, handle->params.realm))) { 276 krb5_db_fini(handle->context); 277 krb5_free_context(handle->context); 278 free(handle); 279 return ret; 280 } 281 282 if (ret = init_dict(&handle->params)) { 283 krb5_db_fini(handle->context); 284 krb5_free_principal(handle->context, handle->current_caller); 285 krb5_free_context(handle->context); 286 free(handle); 287 return ret; 288 } 289 290 if (ret = adb_policy_init(handle)) { 291 krb5_db_fini(handle->context); 292 krb5_free_principal(handle->context, handle->current_caller); 293 krb5_free_context(handle->context); 294 free(handle); 295 return ret; 296 } 297 handle->lhandle->policy_db = handle->policy_db; 298 299 *server_handle = (void *) handle; 300 301 return KADM5_OK; 302 } 303 304 kadm5_ret_t kadm5_destroy(void *server_handle) 305 { 306 kadm5_server_handle_t handle = server_handle; 307 308 CHECK_HANDLE(server_handle); 309 310 destroy_dict(); 311 312 adb_policy_close(handle); 313 krb5_db_fini(handle->context); 314 krb5_free_principal(handle->context, handle->current_caller); 315 kadm5_free_config_params(handle->context, &handle->params); 316 krb5_free_context(handle->context); 317 handle->magic_number = 0; 318 free(handle->lhandle); 319 free(handle); 320 321 return KADM5_OK; 322 } 323 324 kadm5_ret_t kadm5_flush(void *server_handle) 325 { 326 kadm5_server_handle_t handle = server_handle; 327 kadm5_ret_t ret; 328 329 CHECK_HANDLE(server_handle); 330 331 if ((ret = krb5_db_fini(handle->context)) || 332 /* 333 * Set the db_name based on configuration before calling 334 * krb5_db_init, so it will get used. 335 */ 336 (ret = krb5_db_set_name(handle->context, 337 handle->params.dbname)) || 338 (ret = krb5_db_init(handle->context)) || 339 (ret = adb_policy_close(handle)) || 340 (ret = adb_policy_init(handle))) { 341 (void) kadm5_destroy(server_handle); 342 return ret; 343 } 344 return KADM5_OK; 345 } 346 347 int _kadm5_check_handle(void *handle) 348 { 349 CHECK_HANDLE(handle); 350 return 0; 351 } 352 353 krb5_error_code 354 kadm5_init_iprop(void *handle) 355 { 356 kadm5_server_handle_t iprop_h; 357 krb5_error_code retval; 358 359 iprop_h = handle; 360 if (iprop_h->params.iprop_enabled) { 361 ulog_set_role(iprop_h->context, IPROP_MASTER); 362 if ((retval = ulog_map(iprop_h->context, &iprop_h->params, 363 FKCOMMAND)) != 0) 364 return (retval); 365 } 366 return (0); 367 } 368