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 /*
23 * Function check_handle
24 *
25 * Purpose: Check a server handle and return a com_err code if it is
26 * invalid or 0 if it is valid.
27 *
28 * Arguments:
29 *
30 * handle The server handle.
31 */
32
check_handle(void * handle)33 static int check_handle(void *handle)
34 {
35 CHECK_HANDLE(handle);
36 return 0;
37 }
38
dup_db_args(kadm5_server_handle_t handle,char ** db_args)39 static int dup_db_args(kadm5_server_handle_t handle, char **db_args)
40 {
41 int count = 0;
42 int ret = 0;
43
44 for (count=0; db_args && db_args[count]; count++);
45 if (count == 0) {
46 handle->db_args = NULL;
47 goto clean_n_exit;
48 }
49
50 handle->db_args = calloc(sizeof(char*), count+1);
51 if (handle->db_args == NULL) {
52 ret=ENOMEM;
53 goto clean_n_exit;
54 }
55
56 for (count=0; db_args[count]; count++) {
57 handle->db_args[count] = strdup(db_args[count]);
58 if (handle->db_args[count] == NULL) {
59 ret = ENOMEM;
60 goto clean_n_exit;
61 }
62 }
63
64 clean_n_exit:
65 if (ret && handle->db_args) {
66 for (count=0; handle->db_args[count]; count++)
67 free(handle->db_args[count]);
68
69 free(handle->db_args), handle->db_args = NULL;
70 }
71
72 return ret;
73 }
74
free_db_args(kadm5_server_handle_t handle)75 static void free_db_args(kadm5_server_handle_t handle)
76 {
77 int count;
78
79 if (handle->db_args) {
80 for (count=0; handle->db_args[count]; count++)
81 free(handle->db_args[count]);
82
83 free(handle->db_args), handle->db_args = NULL;
84 }
85 }
86
kadm5_init_with_password(krb5_context context,char * client_name,char * pass,char * service_name,kadm5_config_params * params,krb5_ui_4 struct_version,krb5_ui_4 api_version,char ** db_args,void ** server_handle)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
kadm5_init_anonymous(krb5_context context,char * client_name,char * service_name,kadm5_config_params * params,krb5_ui_4 struct_version,krb5_ui_4 api_version,char ** db_args,void ** server_handle)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
kadm5_init_with_creds(krb5_context context,char * client_name,krb5_ccache ccache,char * service_name,kadm5_config_params * params,krb5_ui_4 struct_version,krb5_ui_4 api_version,char ** db_args,void ** server_handle)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
kadm5_init_with_skey(krb5_context context,char * client_name,char * keytab,char * service_name,kadm5_config_params * params,krb5_ui_4 struct_version,krb5_ui_4 api_version,char ** db_args,void ** server_handle)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
kadm5_init(krb5_context context,char * client_name,char * pass,char * service_name,kadm5_config_params * params_in,krb5_ui_4 struct_version,krb5_ui_4 api_version,char ** db_args,void ** server_handle)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 int ret;
167 kadm5_server_handle_t handle;
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 if (! (handle = (kadm5_server_handle_t) malloc(sizeof *handle)))
177 return ENOMEM;
178 memset(handle, 0, sizeof(*handle));
179
180 ret = dup_db_args(handle, db_args);
181 if (ret) {
182 free(handle);
183 return ret;
184 }
185
186 handle->context = context;
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 * Verify the version numbers before proceeding; we can't use
197 * CHECK_HANDLE because not all fields are set yet.
198 */
199 GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION,
200 KADM5_NEW_SERVER_API_VERSION);
201
202 /*
203 * Acquire relevant profile entries. Merge values
204 * in params_in with values from profile, based on
205 * params_in->mask.
206 */
207 memset(¶ms_local, 0, sizeof(params_local));
208
209 ret = kadm5_get_config_params(handle->context, 1, params_in,
210 &handle->params);
211 if (ret) {
212 free_db_args(handle);
213 free(handle);
214 return(ret);
215 }
216
217 #define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \
218 KADM5_CONFIG_ENCTYPE | \
219 KADM5_CONFIG_FLAGS | \
220 KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \
221 KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES)
222
223 #define IPROP_REQUIRED_PARAMS \
224 (KADM5_CONFIG_IPROP_ENABLED | \
225 KADM5_CONFIG_IPROP_LOGFILE | \
226 KADM5_CONFIG_IPROP_PORT)
227
228 if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
229 kadm5_free_config_params(handle->context, &handle->params);
230 free_db_args(handle);
231 free(handle);
232 return KADM5_MISSING_CONF_PARAMS;
233 }
234 if ((handle->params.mask & KADM5_CONFIG_IPROP_ENABLED) == KADM5_CONFIG_IPROP_ENABLED
235 && handle->params.iprop_enabled) {
236 if ((handle->params.mask & IPROP_REQUIRED_PARAMS) != IPROP_REQUIRED_PARAMS) {
237 kadm5_free_config_params(handle->context, &handle->params);
238 free_db_args(handle);
239 free(handle);
240 return KADM5_MISSING_CONF_PARAMS;
241 }
242 }
243
244 ret = krb5_set_default_realm(handle->context, handle->params.realm);
245 if (ret) {
246 kadm5_free_config_params(handle->context, &handle->params);
247 free_db_args(handle);
248 free(handle);
249 return ret;
250 }
251
252 ret = krb5_db_open(handle->context, db_args,
253 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
254 if (ret) {
255 kadm5_free_config_params(handle->context, &handle->params);
256 free_db_args(handle);
257 free(handle);
258 return(ret);
259 }
260
261 if ((ret = krb5_parse_name(handle->context, client_name,
262 &handle->current_caller))) {
263 kadm5_free_config_params(handle->context, &handle->params);
264 krb5_db_fini(handle->context);
265 free_db_args(handle);
266 free(handle);
267 return ret;
268 }
269
270 if (! (handle->lhandle = malloc(sizeof(*handle)))) {
271 kadm5_free_config_params(handle->context, &handle->params);
272 krb5_db_fini(handle->context);
273 free_db_args(handle);
274 free(handle);
275 return ENOMEM;
276 }
277 *handle->lhandle = *handle;
278 handle->lhandle->api_version = KADM5_API_VERSION_4;
279 handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
280 handle->lhandle->lhandle = handle->lhandle;
281
282 /* can't check the handle until current_caller is set */
283 ret = check_handle((void *) handle);
284 if (ret) {
285 kadm5_free_config_params(handle->context, &handle->params);
286 free_db_args(handle);
287 free(handle);
288 return ret;
289 }
290
291 ret = kdb_init_master(handle, handle->params.realm,
292 (handle->params.mask & KADM5_CONFIG_MKEY_FROM_KBD)
293 && handle->params.mkey_from_kbd);
294 if (ret) {
295 kadm5_free_config_params(handle->context, &handle->params);
296 krb5_db_fini(handle->context);
297 free_db_args(handle);
298 free(handle);
299 return ret;
300 }
301
302 ret = kdb_init_hist(handle, handle->params.realm);
303 if (ret) {
304 kadm5_free_config_params(handle->context, &handle->params);
305 krb5_db_fini(handle->context);
306 free_db_args(handle);
307 free(handle);
308 return ret;
309 }
310
311 ret = k5_kadm5_hook_load(context,&handle->hook_handles);
312 if (ret) {
313 kadm5_free_config_params(handle->context, &handle->params);
314 krb5_db_fini(handle->context);
315 krb5_free_principal(handle->context, handle->current_caller);
316 free_db_args(handle);
317 free(handle);
318 return ret;
319 }
320
321 ret = init_pwqual(handle);
322 if (ret) {
323 kadm5_free_config_params(handle->context, &handle->params);
324 k5_kadm5_hook_free_handles(context, handle->hook_handles);
325 krb5_db_fini(handle->context);
326 krb5_free_principal(handle->context, handle->current_caller);
327 free_db_args(handle);
328 free(handle);
329 return ret;
330 }
331
332 *server_handle = (void *) handle;
333
334 return KADM5_OK;
335 }
336
kadm5_destroy(void * server_handle)337 kadm5_ret_t kadm5_destroy(void *server_handle)
338 {
339 kadm5_server_handle_t handle = server_handle;
340
341 CHECK_HANDLE(server_handle);
342
343 destroy_pwqual(handle);
344
345 k5_kadm5_hook_free_handles(handle->context, handle->hook_handles);
346 ulog_fini(handle->context);
347 krb5_db_fini(handle->context);
348 krb5_free_principal(handle->context, handle->current_caller);
349 kadm5_free_config_params(handle->context, &handle->params);
350 handle->magic_number = 0;
351 free(handle->lhandle);
352 free_db_args(handle);
353 free(handle);
354
355 return KADM5_OK;
356 }
357
kadm5_lock(void * server_handle)358 kadm5_ret_t kadm5_lock(void *server_handle)
359 {
360 kadm5_server_handle_t handle = server_handle;
361 kadm5_ret_t ret;
362
363 CHECK_HANDLE(server_handle);
364 ret = krb5_db_lock(handle->context, KRB5_DB_LOCKMODE_EXCLUSIVE);
365 if (ret)
366 return ret;
367
368 return KADM5_OK;
369 }
370
kadm5_unlock(void * server_handle)371 kadm5_ret_t kadm5_unlock(void *server_handle)
372 {
373 kadm5_server_handle_t handle = server_handle;
374 kadm5_ret_t ret;
375
376 CHECK_HANDLE(server_handle);
377 ret = krb5_db_unlock(handle->context);
378 if (ret)
379 return ret;
380
381 return KADM5_OK;
382 }
383
kadm5_flush(void * server_handle)384 kadm5_ret_t kadm5_flush(void *server_handle)
385 {
386 kadm5_server_handle_t handle = server_handle;
387 kadm5_ret_t ret;
388
389 CHECK_HANDLE(server_handle);
390
391 if ((ret = krb5_db_fini(handle->context)) ||
392 (ret = krb5_db_open(handle->context, handle->db_args,
393 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) {
394 (void) kadm5_destroy(server_handle);
395 return ret;
396 }
397 return KADM5_OK;
398 }
399
_kadm5_check_handle(void * handle)400 int _kadm5_check_handle(void *handle)
401 {
402 CHECK_HANDLE(handle);
403 return 0;
404 }
405
406 #include "gssapiP_krb5.h"
kadm5_init_krb5_context(krb5_context * ctx)407 krb5_error_code kadm5_init_krb5_context (krb5_context *ctx)
408 {
409 static int first_time = 1;
410 if (first_time) {
411 krb5_error_code err;
412 err = krb5_gss_use_kdc_context();
413 if (err)
414 return err;
415 first_time = 0;
416 }
417 return krb5int_init_context_kdc(ctx);
418 }
419
420 krb5_error_code
kadm5_init_iprop(void * handle,char ** db_args)421 kadm5_init_iprop(void *handle, char **db_args)
422 {
423 kadm5_server_handle_t iprop_h;
424 krb5_error_code retval;
425
426 iprop_h = handle;
427 if (iprop_h->params.iprop_enabled) {
428 ulog_set_role(iprop_h->context, IPROP_PRIMARY);
429 retval = ulog_map(iprop_h->context, iprop_h->params.iprop_logfile,
430 iprop_h->params.iprop_ulogsize);
431 if (retval)
432 return (retval);
433 }
434 return (0);
435 }
436