1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. 4 * 5 * $Id$ 6 * $Source$ 7 */ 8 /* 9 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 10 * Use is subject to license terms. 11 */ 12 13 #include "k5-int.h" 14 #include <com_err.h> 15 #include <kadm5/admin.h> 16 #include <krb5.h> 17 #include <kdb_log.h> 18 #include "server_internal.h" 19 #include "osconf.h" 20 #include "iprop_hdr.h" 21 22 static int dup_db_args(kadm5_server_handle_t handle, char **db_args) 23 { 24 int count = 0; 25 int ret = 0; 26 27 for (count=0; db_args && db_args[count]; count++); 28 if (count == 0) { 29 handle->db_args = NULL; 30 goto clean_n_exit; 31 } 32 33 handle->db_args = calloc(sizeof(char*), count+1); 34 if (handle->db_args == NULL) { 35 ret=ENOMEM; 36 goto clean_n_exit; 37 } 38 39 for (count=0; db_args[count]; count++) { 40 handle->db_args[count] = strdup(db_args[count]); 41 if (handle->db_args[count] == NULL) { 42 ret = ENOMEM; 43 goto clean_n_exit; 44 } 45 } 46 47 clean_n_exit: 48 if (ret && handle->db_args) { 49 for (count=0; handle->db_args[count]; count++) 50 free(handle->db_args[count]); 51 52 free(handle->db_args), handle->db_args = NULL; 53 } 54 55 return ret; 56 } 57 58 static void free_db_args(kadm5_server_handle_t handle) 59 { 60 int count; 61 62 if (handle->db_args) { 63 for (count=0; handle->db_args[count]; count++) 64 free(handle->db_args[count]); 65 66 free(handle->db_args), handle->db_args = NULL; 67 } 68 } 69 70 static void 71 free_handle(kadm5_server_handle_t handle) 72 { 73 if (handle == NULL) 74 return; 75 76 destroy_pwqual(handle); 77 k5_kadm5_hook_free_handles(handle->context, handle->hook_handles); 78 ulog_fini(handle->context); 79 krb5_db_fini(handle->context); 80 krb5_free_principal(handle->context, handle->current_caller); 81 kadm5_free_config_params(handle->context, &handle->params); 82 free(handle->lhandle); 83 free_db_args(handle); 84 free(handle); 85 } 86 87 kadm5_ret_t kadm5_init_with_password(krb5_context context, char *client_name, 88 char *pass, char *service_name, 89 kadm5_config_params *params, 90 krb5_ui_4 struct_version, 91 krb5_ui_4 api_version, 92 char **db_args, 93 void **server_handle) 94 { 95 return kadm5_init(context, client_name, pass, service_name, params, 96 struct_version, api_version, db_args, 97 server_handle); 98 } 99 100 kadm5_ret_t kadm5_init_anonymous(krb5_context context, char *client_name, 101 char *service_name, 102 kadm5_config_params *params, 103 krb5_ui_4 struct_version, 104 krb5_ui_4 api_version, 105 char **db_args, 106 void **server_handle) 107 { 108 return kadm5_init(context, client_name, NULL, service_name, params, 109 struct_version, api_version, db_args, 110 server_handle); 111 } 112 113 kadm5_ret_t kadm5_init_with_creds(krb5_context context, 114 char *client_name, 115 krb5_ccache ccache, 116 char *service_name, 117 kadm5_config_params *params, 118 krb5_ui_4 struct_version, 119 krb5_ui_4 api_version, 120 char **db_args, 121 void **server_handle) 122 { 123 /* 124 * A program calling init_with_creds *never* expects to prompt 125 * the user. If this is KADM5_API_VERSION_2 and MKEY_FROM_KBD is 126 * non-zero, return an error. 127 */ 128 if (params && (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && 129 params->mkey_from_kbd) 130 return KADM5_BAD_SERVER_PARAMS; 131 return kadm5_init(context, client_name, NULL, service_name, params, 132 struct_version, api_version, db_args, 133 server_handle); 134 } 135 136 137 kadm5_ret_t kadm5_init_with_skey(krb5_context context, char *client_name, 138 char *keytab, char *service_name, 139 kadm5_config_params *params, 140 krb5_ui_4 struct_version, 141 krb5_ui_4 api_version, 142 char **db_args, 143 void **server_handle) 144 { 145 /* 146 * A program calling init_with_skey *never* expects to prompt the 147 * user. If this is KADM5_API_VERSION_2 and MKEY_FROM_KBD is 148 * non-zero, return an error. 149 */ 150 if (params && (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && 151 params->mkey_from_kbd) 152 return KADM5_BAD_SERVER_PARAMS; 153 return kadm5_init(context, client_name, NULL, service_name, params, 154 struct_version, api_version, db_args, 155 server_handle); 156 } 157 158 kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass, 159 char *service_name, 160 kadm5_config_params *params_in, 161 krb5_ui_4 struct_version, 162 krb5_ui_4 api_version, 163 char **db_args, 164 void **server_handle) 165 { 166 krb5_error_code ret; 167 kadm5_server_handle_t handle = NULL; 168 kadm5_config_params params_local; /* for v1 compat */ 169 170 if (! server_handle) 171 return EINVAL; 172 173 if (! client_name) 174 return EINVAL; 175 176 CHECK_VERSIONS(struct_version, api_version, KADM5_OLD_SERVER_API_VERSION, 177 KADM5_NEW_SERVER_API_VERSION); 178 179 handle = k5alloc(sizeof(*handle), &ret); 180 if (handle == NULL) 181 goto cleanup; 182 handle->context = context; 183 184 ret = dup_db_args(handle, db_args); 185 if (ret) 186 goto cleanup; 187 188 initialize_ovk_error_table(); 189 initialize_ovku_error_table(); 190 191 handle->magic_number = KADM5_SERVER_HANDLE_MAGIC; 192 handle->struct_version = struct_version; 193 handle->api_version = api_version; 194 195 /* 196 * Acquire relevant profile entries. Merge values 197 * in params_in with values from profile, based on 198 * params_in->mask. 199 */ 200 memset(¶ms_local, 0, sizeof(params_local)); 201 202 ret = kadm5_get_config_params(handle->context, 1, params_in, 203 &handle->params); 204 if (ret) 205 goto cleanup; 206 207 #define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \ 208 KADM5_CONFIG_ENCTYPE | \ 209 KADM5_CONFIG_FLAGS | \ 210 KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \ 211 KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES) 212 213 #define IPROP_REQUIRED_PARAMS \ 214 (KADM5_CONFIG_IPROP_ENABLED | \ 215 KADM5_CONFIG_IPROP_LOGFILE | \ 216 KADM5_CONFIG_IPROP_PORT) 217 218 if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { 219 ret = KADM5_MISSING_CONF_PARAMS; 220 goto cleanup; 221 } 222 if ((handle->params.mask & KADM5_CONFIG_IPROP_ENABLED) == KADM5_CONFIG_IPROP_ENABLED 223 && handle->params.iprop_enabled) { 224 if ((handle->params.mask & IPROP_REQUIRED_PARAMS) != IPROP_REQUIRED_PARAMS) { 225 ret = KADM5_MISSING_CONF_PARAMS; 226 goto cleanup; 227 } 228 } 229 230 ret = krb5_set_default_realm(handle->context, handle->params.realm); 231 if (ret) 232 goto cleanup; 233 234 ret = krb5_db_open(handle->context, db_args, 235 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN); 236 if (ret) 237 goto cleanup; 238 239 ret = krb5_parse_name(handle->context, client_name, 240 &handle->current_caller); 241 if (ret) 242 goto cleanup; 243 244 handle->lhandle = k5alloc(sizeof(*handle), &ret); 245 if (handle->lhandle == NULL) 246 goto cleanup; 247 *handle->lhandle = *handle; 248 handle->lhandle->api_version = KADM5_API_VERSION_4; 249 handle->lhandle->struct_version = KADM5_STRUCT_VERSION; 250 handle->lhandle->lhandle = handle->lhandle; 251 252 ret = kdb_init_master(handle, handle->params.realm, 253 (handle->params.mask & KADM5_CONFIG_MKEY_FROM_KBD) 254 && handle->params.mkey_from_kbd); 255 if (ret) 256 goto cleanup; 257 258 ret = kdb_init_hist(handle, handle->params.realm); 259 if (ret) 260 goto cleanup; 261 262 ret = k5_kadm5_hook_load(context,&handle->hook_handles); 263 if (ret) 264 goto cleanup; 265 266 ret = init_pwqual(handle); 267 if (ret) 268 goto cleanup; 269 270 *server_handle = handle; 271 handle = NULL; 272 273 cleanup: 274 free_handle(handle); 275 return ret; 276 } 277 278 kadm5_ret_t kadm5_destroy(void *server_handle) 279 { 280 CHECK_HANDLE(server_handle); 281 free_handle(server_handle); 282 return KADM5_OK; 283 } 284 285 kadm5_ret_t kadm5_lock(void *server_handle) 286 { 287 kadm5_server_handle_t handle = server_handle; 288 kadm5_ret_t ret; 289 290 CHECK_HANDLE(server_handle); 291 ret = krb5_db_lock(handle->context, KRB5_DB_LOCKMODE_EXCLUSIVE); 292 if (ret) 293 return ret; 294 295 return KADM5_OK; 296 } 297 298 kadm5_ret_t kadm5_unlock(void *server_handle) 299 { 300 kadm5_server_handle_t handle = server_handle; 301 kadm5_ret_t ret; 302 303 CHECK_HANDLE(server_handle); 304 ret = krb5_db_unlock(handle->context); 305 if (ret) 306 return ret; 307 308 return KADM5_OK; 309 } 310 311 kadm5_ret_t kadm5_flush(void *server_handle) 312 { 313 kadm5_server_handle_t handle = server_handle; 314 kadm5_ret_t ret; 315 316 CHECK_HANDLE(server_handle); 317 318 if ((ret = krb5_db_fini(handle->context)) || 319 (ret = krb5_db_open(handle->context, handle->db_args, 320 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) { 321 (void) kadm5_destroy(server_handle); 322 return ret; 323 } 324 return KADM5_OK; 325 } 326 327 int _kadm5_check_handle(void *handle) 328 { 329 CHECK_HANDLE(handle); 330 return 0; 331 } 332 333 #include "gssapiP_krb5.h" 334 krb5_error_code kadm5_init_krb5_context (krb5_context *ctx) 335 { 336 static int first_time = 1; 337 if (first_time) { 338 krb5_error_code err; 339 err = krb5_gss_use_kdc_context(); 340 if (err) 341 return err; 342 first_time = 0; 343 } 344 return krb5int_init_context_kdc(ctx); 345 } 346 347 krb5_error_code 348 kadm5_init_iprop(void *handle, char **db_args) 349 { 350 kadm5_server_handle_t iprop_h; 351 krb5_error_code retval; 352 353 iprop_h = handle; 354 if (iprop_h->params.iprop_enabled) { 355 ulog_set_role(iprop_h->context, IPROP_PRIMARY); 356 retval = ulog_map(iprop_h->context, iprop_h->params.iprop_logfile, 357 iprop_h->params.iprop_ulogsize); 358 if (retval) 359 return (retval); 360 } 361 return (0); 362 } 363