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
dup_db_args(kadm5_server_handle_t handle,char ** db_args)22 static int dup_db_args(kadm5_server_handle_t handle, char **db_args)
23 {
24 size_t 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
free_db_args(kadm5_server_handle_t handle)58 static void free_db_args(kadm5_server_handle_t handle)
59 {
60 size_t 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
free_handle(kadm5_server_handle_t handle)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
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 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
kadm5_destroy(void * server_handle)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
kadm5_lock(void * server_handle)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
kadm5_unlock(void * server_handle)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
kadm5_flush(void * server_handle)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
_kadm5_check_handle(void * handle)327 int _kadm5_check_handle(void *handle)
328 {
329 CHECK_HANDLE(handle);
330 return 0;
331 }
332
333 #include "gssapiP_krb5.h"
kadm5_init_krb5_context(krb5_context * ctx)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
kadm5_init_iprop(void * handle,char ** db_args)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