xref: /freebsd/crypto/krb5/src/lib/kadm5/srv/server_init.c (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
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(&params_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