xref: /titanic_53/usr/src/lib/krb5/kdb/kdb5.c (revision 54925bf60766fbb4f1f2d7c843721406a7b7a3fb)
1*54925bf6Swillf /*
2*54925bf6Swillf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3*54925bf6Swillf  * Use is subject to license terms.
4*54925bf6Swillf  */
5*54925bf6Swillf 
6*54925bf6Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*54925bf6Swillf /*
8*54925bf6Swillf  * Copyright 2006 by the Massachusetts Institute of Technology.
9*54925bf6Swillf  * All Rights Reserved.
10*54925bf6Swillf  *
11*54925bf6Swillf  * Export of this software from the United States of America may
12*54925bf6Swillf  *   require a specific license from the United States Government.
13*54925bf6Swillf  *   It is the responsibility of any person or organization contemplating
14*54925bf6Swillf  *   export to obtain such a license before exporting.
15*54925bf6Swillf  *
16*54925bf6Swillf  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
17*54925bf6Swillf  * distribute this software and its documentation for any purpose and
18*54925bf6Swillf  * without fee is hereby granted, provided that the above copyright
19*54925bf6Swillf  * notice appear in all copies and that both that copyright notice and
20*54925bf6Swillf  * this permission notice appear in supporting documentation, and that
21*54925bf6Swillf  * the name of M.I.T. not be used in advertising or publicity pertaining
22*54925bf6Swillf  * to distribution of the software without specific, written prior
23*54925bf6Swillf  * permission.  Furthermore if you modify this software you must label
24*54925bf6Swillf  * your software as modified software and not distribute it in such a
25*54925bf6Swillf  * fashion that it might be confused with the original M.I.T. software.
26*54925bf6Swillf  * M.I.T. makes no representations about the suitability of
27*54925bf6Swillf  * this software for any purpose.  It is provided "as is" without express
28*54925bf6Swillf  * or implied warranty.
29*54925bf6Swillf  */
30*54925bf6Swillf 
31*54925bf6Swillf /*
32*54925bf6Swillf  * This code was based on code donated to MIT by Novell for
33*54925bf6Swillf  * distribution under the MIT license.
34*54925bf6Swillf  */
35*54925bf6Swillf 
36*54925bf6Swillf /*
37*54925bf6Swillf  * Include files
38*54925bf6Swillf  */
39*54925bf6Swillf 
40*54925bf6Swillf #include <stdio.h>
41*54925bf6Swillf #include <string.h>
42*54925bf6Swillf #include <k5-int.h>
43*54925bf6Swillf #include <osconf.h>
44*54925bf6Swillf #include "kdb5.h"
45*54925bf6Swillf #include <assert.h>
46*54925bf6Swillf #include "k5-platform.h"
47*54925bf6Swillf #include <libintl.h>
48*54925bf6Swillf 
49*54925bf6Swillf /* Currently DB2 policy related errors are exported from DAL.  But
50*54925bf6Swillf    other databases should set_err function to return string.  */
51*54925bf6Swillf #include "adb_err.h"
52*54925bf6Swillf 
53*54925bf6Swillf /*
54*54925bf6Swillf  * Type definitions
55*54925bf6Swillf  */
56*54925bf6Swillf #define KRB5_TL_DB_ARGS                 0x7fff
57*54925bf6Swillf 
58*54925bf6Swillf /*
59*54925bf6Swillf  * internal static variable
60*54925bf6Swillf  */
61*54925bf6Swillf 
62*54925bf6Swillf static k5_mutex_t db_lock = K5_MUTEX_PARTIAL_INITIALIZER;
63*54925bf6Swillf 
64*54925bf6Swillf #ifdef _KDB5_STATIC_LINK
65*54925bf6Swillf #undef _KDB5_DYNAMIC_LINK
66*54925bf6Swillf #else
67*54925bf6Swillf #undef _KDB5_DYNAMIC_LINK
68*54925bf6Swillf /* to avoid redefinition problem */
69*54925bf6Swillf #define _KDB5_DYNAMIC_LINK
70*54925bf6Swillf #endif
71*54925bf6Swillf 
72*54925bf6Swillf static db_library lib_list;
73*54925bf6Swillf 
74*54925bf6Swillf /*
75*54925bf6Swillf  * Helper Functions
76*54925bf6Swillf  */
77*54925bf6Swillf 
78*54925bf6Swillf MAKE_INIT_FUNCTION(kdb_init_lock_list);
79*54925bf6Swillf MAKE_FINI_FUNCTION(kdb_fini_lock_list);
80*54925bf6Swillf 
81*54925bf6Swillf int
82*54925bf6Swillf kdb_init_lock_list(void)
83*54925bf6Swillf {
84*54925bf6Swillf     return k5_mutex_finish_init(&db_lock);
85*54925bf6Swillf }
86*54925bf6Swillf 
87*54925bf6Swillf static int
88*54925bf6Swillf kdb_lock_list()
89*54925bf6Swillf {
90*54925bf6Swillf     int err;
91*54925bf6Swillf     err = CALL_INIT_FUNCTION (kdb_init_lock_list);
92*54925bf6Swillf     if (err)
93*54925bf6Swillf 	return err;
94*54925bf6Swillf     return k5_mutex_lock(&db_lock);
95*54925bf6Swillf }
96*54925bf6Swillf 
97*54925bf6Swillf void
98*54925bf6Swillf kdb_fini_lock_list(void)
99*54925bf6Swillf {
100*54925bf6Swillf     if (INITIALIZER_RAN(kdb_init_lock_list))
101*54925bf6Swillf 	k5_mutex_destroy(&db_lock);
102*54925bf6Swillf }
103*54925bf6Swillf 
104*54925bf6Swillf static int
105*54925bf6Swillf kdb_unlock_list()
106*54925bf6Swillf {
107*54925bf6Swillf     return k5_mutex_unlock(&db_lock);
108*54925bf6Swillf }
109*54925bf6Swillf 
110*54925bf6Swillf #define kdb_init_lib_lock(a) 0
111*54925bf6Swillf #define kdb_destroy_lib_lock(a) (void)0
112*54925bf6Swillf #define kdb_lock_lib_lock(a, b) 0
113*54925bf6Swillf #define kdb_unlock_lib_lock(a, b) (void)0
114*54925bf6Swillf 
115*54925bf6Swillf /* Caller must free result*/
116*54925bf6Swillf 
117*54925bf6Swillf static char *
118*54925bf6Swillf kdb_get_conf_section(krb5_context kcontext)
119*54925bf6Swillf {
120*54925bf6Swillf     krb5_error_code status = 0;
121*54925bf6Swillf     char   *result = NULL;
122*54925bf6Swillf     char   *value = NULL;
123*54925bf6Swillf 
124*54925bf6Swillf     if (kcontext->default_realm == NULL)
125*54925bf6Swillf 	return NULL;
126*54925bf6Swillf     /* The profile has to have been initialized.  If the profile was
127*54925bf6Swillf        not initialized, expect nothing less than a crash.  */
128*54925bf6Swillf     status = profile_get_string(kcontext->profile,
129*54925bf6Swillf 				/* realms */
130*54925bf6Swillf 				KDB_REALM_SECTION,
131*54925bf6Swillf 				kcontext->default_realm,
132*54925bf6Swillf 				/* under the realm name, database_module */
133*54925bf6Swillf 				KDB_MODULE_POINTER,
134*54925bf6Swillf 				/* default value is the realm name itself */
135*54925bf6Swillf 				kcontext->default_realm,
136*54925bf6Swillf 				&value);
137*54925bf6Swillf 
138*54925bf6Swillf     if (status) {
139*54925bf6Swillf 	/* some problem */
140*54925bf6Swillf 	result = strdup(kcontext->default_realm);
141*54925bf6Swillf 	/* let NULL be handled by the caller */
142*54925bf6Swillf     } else {
143*54925bf6Swillf 	result = strdup(value);
144*54925bf6Swillf 	/* free profile string */
145*54925bf6Swillf 	profile_release_string(value);
146*54925bf6Swillf     }
147*54925bf6Swillf 
148*54925bf6Swillf     return result;
149*54925bf6Swillf }
150*54925bf6Swillf 
151*54925bf6Swillf static char *
152*54925bf6Swillf kdb_get_library_name(krb5_context kcontext)
153*54925bf6Swillf {
154*54925bf6Swillf     krb5_error_code status = 0;
155*54925bf6Swillf     char   *result = NULL;
156*54925bf6Swillf     char   *value = NULL;
157*54925bf6Swillf     char   *lib = NULL;
158*54925bf6Swillf 
159*54925bf6Swillf     status = profile_get_string(kcontext->profile,
160*54925bf6Swillf 				/* realms */
161*54925bf6Swillf 				KDB_REALM_SECTION,
162*54925bf6Swillf 				kcontext->default_realm,
163*54925bf6Swillf 				/* under the realm name, database_module */
164*54925bf6Swillf 				KDB_MODULE_POINTER,
165*54925bf6Swillf 				/* default value is the realm name itself */
166*54925bf6Swillf 				kcontext->default_realm,
167*54925bf6Swillf 				&value);
168*54925bf6Swillf     if (status) {
169*54925bf6Swillf 	goto clean_n_exit;
170*54925bf6Swillf     }
171*54925bf6Swillf 
172*54925bf6Swillf #define DB2_NAME "db2"
173*54925bf6Swillf     /* we got the module section. Get the library name from the module */
174*54925bf6Swillf     status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value,
175*54925bf6Swillf 				KDB_LIB_POINTER,
176*54925bf6Swillf 				/* default to db2 */
177*54925bf6Swillf 				DB2_NAME,
178*54925bf6Swillf 				&lib);
179*54925bf6Swillf 
180*54925bf6Swillf     if (status) {
181*54925bf6Swillf 	goto clean_n_exit;
182*54925bf6Swillf     }
183*54925bf6Swillf 
184*54925bf6Swillf     result = strdup(lib);
185*54925bf6Swillf   clean_n_exit:
186*54925bf6Swillf     if (value) {
187*54925bf6Swillf 	/* free profile string */
188*54925bf6Swillf 	profile_release_string(value);
189*54925bf6Swillf     }
190*54925bf6Swillf 
191*54925bf6Swillf     if (lib) {
192*54925bf6Swillf 	/* free profile string */
193*54925bf6Swillf 	profile_release_string(lib);
194*54925bf6Swillf     }
195*54925bf6Swillf     return result;
196*54925bf6Swillf }
197*54925bf6Swillf 
198*54925bf6Swillf static void
199*54925bf6Swillf kdb_setup_opt_functions(db_library lib)
200*54925bf6Swillf {
201*54925bf6Swillf     if (lib->vftabl.set_master_key == NULL) {
202*54925bf6Swillf 	lib->vftabl.set_master_key = kdb_def_set_mkey;
203*54925bf6Swillf     }
204*54925bf6Swillf 
205*54925bf6Swillf     if (lib->vftabl.get_master_key == NULL) {
206*54925bf6Swillf 	lib->vftabl.get_master_key = kdb_def_get_mkey;
207*54925bf6Swillf     }
208*54925bf6Swillf 
209*54925bf6Swillf     if (lib->vftabl.fetch_master_key == NULL) {
210*54925bf6Swillf 	lib->vftabl.fetch_master_key = krb5_db_def_fetch_mkey;
211*54925bf6Swillf     }
212*54925bf6Swillf 
213*54925bf6Swillf     if (lib->vftabl.verify_master_key == NULL) {
214*54925bf6Swillf 	lib->vftabl.verify_master_key = krb5_def_verify_master_key;
215*54925bf6Swillf     }
216*54925bf6Swillf 
217*54925bf6Swillf     if (lib->vftabl.dbe_search_enctype == NULL) {
218*54925bf6Swillf 	lib->vftabl.dbe_search_enctype = krb5_dbe_def_search_enctype;
219*54925bf6Swillf     }
220*54925bf6Swillf 
221*54925bf6Swillf     if (lib->vftabl.db_change_pwd == NULL) {
222*54925bf6Swillf 	lib->vftabl.db_change_pwd = krb5_dbe_def_cpw;
223*54925bf6Swillf     }
224*54925bf6Swillf 
225*54925bf6Swillf     if (lib->vftabl.store_master_key == NULL) {
226*54925bf6Swillf 	lib->vftabl.store_master_key = krb5_def_store_mkey;
227*54925bf6Swillf     }
228*54925bf6Swillf 
229*54925bf6Swillf     if (lib->vftabl.promote_db == NULL) {
230*54925bf6Swillf 	lib->vftabl.promote_db = krb5_def_promote_db;
231*54925bf6Swillf     }
232*54925bf6Swillf }
233*54925bf6Swillf 
234*54925bf6Swillf static int kdb_db2_pol_err_loaded = 0;
235*54925bf6Swillf #ifdef _KDB5_STATIC_LINK
236*54925bf6Swillf #define DEF_SYMBOL(a) extern kdb_vftabl krb5_db_vftabl_ ## a
237*54925bf6Swillf #define GET_SYMBOL(a) (krb5_db_vftabl_ ## a)
238*54925bf6Swillf static krb5_error_code
239*54925bf6Swillf kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
240*54925bf6Swillf {
241*54925bf6Swillf     krb5_error_code status;
242*54925bf6Swillf     void   *vftabl_addr = NULL;
243*54925bf6Swillf     char    buf[KRB5_MAX_ERR_STR];
244*54925bf6Swillf 
245*54925bf6Swillf     if (!strcmp("kdb_db2", lib_name) && (kdb_db2_pol_err_loaded == 0)) {
246*54925bf6Swillf 	initialize_adb_error_table();
247*54925bf6Swillf 	kdb_db2_pol_err_loaded = 1;
248*54925bf6Swillf     }
249*54925bf6Swillf 
250*54925bf6Swillf     *lib = calloc((size_t) 1, sizeof(**lib));
251*54925bf6Swillf     if (*lib == NULL) {
252*54925bf6Swillf 	status = ENOMEM;
253*54925bf6Swillf 	goto clean_n_exit;
254*54925bf6Swillf     }
255*54925bf6Swillf 
256*54925bf6Swillf     status = kdb_init_lib_lock(*lib);
257*54925bf6Swillf     if (status) {
258*54925bf6Swillf 	goto clean_n_exit;
259*54925bf6Swillf     }
260*54925bf6Swillf 
261*54925bf6Swillf     strcpy((*lib)->name, lib_name);
262*54925bf6Swillf 
263*54925bf6Swillf #if !defined(KDB5_USE_LIB_KDB_DB2) && !defined(KDB5_USE_LIB_TEST)
264*54925bf6Swillf #error No database module defined
265*54925bf6Swillf #endif
266*54925bf6Swillf 
267*54925bf6Swillf #ifdef KDB5_USE_LIB_KDB_DB2
268*54925bf6Swillf     if (strcmp(lib_name, "kdb_db2") == 0) {
269*54925bf6Swillf 	DEF_SYMBOL(kdb_db2);
270*54925bf6Swillf 	vftabl_addr = (void *) &GET_SYMBOL(kdb_db2);
271*54925bf6Swillf     } else
272*54925bf6Swillf #endif
273*54925bf6Swillf #ifdef KDB5_USE_LIB_TEST
274*54925bf6Swillf     if (strcmp(lib_name, "test") == 0) {
275*54925bf6Swillf 	DEF_SYMBOL(test);
276*54925bf6Swillf 	vftabl_addr = (void *) &GET_SYMBOL(test);
277*54925bf6Swillf     } else
278*54925bf6Swillf #endif
279*54925bf6Swillf     {
280*54925bf6Swillf 	snprintf(buf, sizeof(buf), gettext("Program not built to support %s database type\n"),
281*54925bf6Swillf 		lib_name);
282*54925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOSUP;
283*54925bf6Swillf 	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
284*54925bf6Swillf 	goto clean_n_exit;
285*54925bf6Swillf     }
286*54925bf6Swillf 
287*54925bf6Swillf     memcpy(&(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
288*54925bf6Swillf 
289*54925bf6Swillf     kdb_setup_opt_functions(*lib);
290*54925bf6Swillf 
291*54925bf6Swillf     if ((status = (*lib)->vftabl.init_library())) {
292*54925bf6Swillf 	/* ERROR. library not initialized cleanly */
293*54925bf6Swillf 	snprintf(buf, sizeof(buf), gettext("%s library initialization failed, error code %ld\n"),
294*54925bf6Swillf 		lib_name, status);
295*54925bf6Swillf 	status = KRB5_KDB_DBTYPE_INIT;
296*54925bf6Swillf 	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
297*54925bf6Swillf 	goto clean_n_exit;
298*54925bf6Swillf     }
299*54925bf6Swillf 
300*54925bf6Swillf   clean_n_exit:
301*54925bf6Swillf     if (status) {
302*54925bf6Swillf 	free(*lib), *lib = NULL;
303*54925bf6Swillf     }
304*54925bf6Swillf     return status;
305*54925bf6Swillf }
306*54925bf6Swillf 
307*54925bf6Swillf #else /* KDB5_STATIC_LINK*/
308*54925bf6Swillf 
309*54925bf6Swillf static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH;
310*54925bf6Swillf #define db_dl_n_locations (sizeof(db_dl_location) / sizeof(db_dl_location[0]))
311*54925bf6Swillf 
312*54925bf6Swillf static krb5_error_code
313*54925bf6Swillf kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
314*54925bf6Swillf {
315*54925bf6Swillf     krb5_error_code status = 0;
316*54925bf6Swillf     int     ndx;
317*54925bf6Swillf     void  **vftabl_addrs = NULL;
318*54925bf6Swillf     /* N.B.: If this is "const" but not "static", the Solaris 10
319*54925bf6Swillf        native compiler has trouble building the library because of
320*54925bf6Swillf        absolute relocations needed in read-only section ".rodata".
321*54925bf6Swillf        When it's static, it goes into ".picdata", which is
322*54925bf6Swillf        read-write.  */
323*54925bf6Swillf     static const char *const dbpath_names[] = {
324*54925bf6Swillf 	KDB_MODULE_SECTION, "db_module_dir", NULL,
325*54925bf6Swillf     };
326*54925bf6Swillf     const char *filebases[2];
327*54925bf6Swillf     char **profpath = NULL;
328*54925bf6Swillf     char **path = NULL;
329*54925bf6Swillf 
330*54925bf6Swillf     filebases[0] = lib_name;
331*54925bf6Swillf     filebases[1] = NULL;
332*54925bf6Swillf 
333*54925bf6Swillf     if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
334*54925bf6Swillf 	initialize_adb_error_table();
335*54925bf6Swillf 	kdb_db2_pol_err_loaded = 1;
336*54925bf6Swillf     }
337*54925bf6Swillf 
338*54925bf6Swillf     *lib = calloc((size_t) 1, sizeof(**lib));
339*54925bf6Swillf     if (*lib == NULL) {
340*54925bf6Swillf 	status = ENOMEM;
341*54925bf6Swillf 	goto clean_n_exit;
342*54925bf6Swillf     }
343*54925bf6Swillf 
344*54925bf6Swillf     status = kdb_init_lib_lock(*lib);
345*54925bf6Swillf     if (status) {
346*54925bf6Swillf 	goto clean_n_exit;
347*54925bf6Swillf     }
348*54925bf6Swillf 
349*54925bf6Swillf     strcpy((*lib)->name, lib_name);
350*54925bf6Swillf 
351*54925bf6Swillf     /* Fetch the list of directories specified in the config
352*54925bf6Swillf        file(s) first.  */
353*54925bf6Swillf     status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
354*54925bf6Swillf     if (status != 0 && status != PROF_NO_RELATION)
355*54925bf6Swillf 	goto clean_n_exit;
356*54925bf6Swillf     ndx = 0;
357*54925bf6Swillf     if (profpath)
358*54925bf6Swillf 	while (profpath[ndx] != NULL)
359*54925bf6Swillf 	    ndx++;
360*54925bf6Swillf 
361*54925bf6Swillf     path = calloc(ndx + db_dl_n_locations, sizeof (char *));
362*54925bf6Swillf     if (path == NULL) {
363*54925bf6Swillf 	status = errno;
364*54925bf6Swillf 	goto clean_n_exit;
365*54925bf6Swillf     }
366*54925bf6Swillf     if (ndx)
367*54925bf6Swillf 	memcpy(path, profpath, ndx * sizeof(profpath[0]));
368*54925bf6Swillf     memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
369*54925bf6Swillf     status = 0;
370*54925bf6Swillf 
371*54925bf6Swillf     if ((status = krb5int_open_plugin_dirs ((const char **) path,
372*54925bf6Swillf                                             filebases,
373*54925bf6Swillf                                             &(*lib)->dl_dir_handle, &kcontext->err))) {
374*54925bf6Swillf         const char *err_str = krb5_get_error_message(kcontext, status);
375*54925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
376*54925bf6Swillf 	krb5_set_error_message (kcontext, status,
377*54925bf6Swillf 				gettext("Unable to find requested database type: %s"), err_str);
378*54925bf6Swillf 	krb5_free_error_message (kcontext, err_str);
379*54925bf6Swillf 	goto clean_n_exit;
380*54925bf6Swillf     }
381*54925bf6Swillf 
382*54925bf6Swillf     if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
383*54925bf6Swillf                                                &vftabl_addrs, &kcontext->err))) {
384*54925bf6Swillf         const char *err_str = krb5_get_error_message(kcontext, status);
385*54925bf6Swillf         status = KRB5_KDB_DBTYPE_INIT;
386*54925bf6Swillf         krb5_set_error_message (kcontext, status,
387*54925bf6Swillf                                 gettext("plugin symbol 'kdb_function_table' lookup failed: %s"), err_str);
388*54925bf6Swillf         krb5_free_error_message (kcontext, err_str);
389*54925bf6Swillf 	goto clean_n_exit;
390*54925bf6Swillf     }
391*54925bf6Swillf 
392*54925bf6Swillf     if (vftabl_addrs[0] == NULL) {
393*54925bf6Swillf 	/* No plugins! */
394*54925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
395*54925bf6Swillf 	krb5_set_error_message (kcontext, status,
396*54925bf6Swillf 				gettext("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"),
397*54925bf6Swillf 				lib_name);
398*54925bf6Swillf 	goto clean_n_exit;
399*54925bf6Swillf     }
400*54925bf6Swillf 
401*54925bf6Swillf     memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl));
402*54925bf6Swillf     kdb_setup_opt_functions(*lib);
403*54925bf6Swillf 
404*54925bf6Swillf     if ((status = (*lib)->vftabl.init_library())) {
405*54925bf6Swillf         /* ERROR. library not initialized cleanly */
406*54925bf6Swillf         goto clean_n_exit;
407*54925bf6Swillf     }
408*54925bf6Swillf 
409*54925bf6Swillf clean_n_exit:
410*54925bf6Swillf     if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); }
411*54925bf6Swillf     /* Both of these DTRT with NULL.  */
412*54925bf6Swillf     profile_free_list(profpath);
413*54925bf6Swillf     free(path);
414*54925bf6Swillf     if (status) {
415*54925bf6Swillf         if (*lib) {
416*54925bf6Swillf 	    kdb_destroy_lib_lock(*lib);
417*54925bf6Swillf             if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
418*54925bf6Swillf                 krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
419*54925bf6Swillf             }
420*54925bf6Swillf 	    free(*lib);
421*54925bf6Swillf 	    *lib = NULL;
422*54925bf6Swillf 	}
423*54925bf6Swillf     }
424*54925bf6Swillf     return status;
425*54925bf6Swillf }
426*54925bf6Swillf 
427*54925bf6Swillf #endif /* end of _KDB5_STATIC_LINK */
428*54925bf6Swillf 
429*54925bf6Swillf static krb5_error_code
430*54925bf6Swillf kdb_find_library(krb5_context kcontext, char *lib_name, db_library * lib)
431*54925bf6Swillf {
432*54925bf6Swillf     /* lock here so that no two threads try to do the same at the same time */
433*54925bf6Swillf     krb5_error_code status = 0;
434*54925bf6Swillf     int     locked = 0;
435*54925bf6Swillf     db_library curr_elt, prev_elt = NULL;
436*54925bf6Swillf 
437*54925bf6Swillf     if ((status = kdb_lock_list()) != 0) {
438*54925bf6Swillf 	goto clean_n_exit;
439*54925bf6Swillf     }
440*54925bf6Swillf     locked = 1;
441*54925bf6Swillf 
442*54925bf6Swillf     curr_elt = lib_list;
443*54925bf6Swillf     while (curr_elt != NULL) {
444*54925bf6Swillf 	if (strcmp(lib_name, curr_elt->name) == 0) {
445*54925bf6Swillf 	    *lib = curr_elt;
446*54925bf6Swillf 	    goto clean_n_exit;
447*54925bf6Swillf 	}
448*54925bf6Swillf 	prev_elt = curr_elt;
449*54925bf6Swillf 	curr_elt = curr_elt->next;
450*54925bf6Swillf     }
451*54925bf6Swillf 
452*54925bf6Swillf     /* module not found. create and add to list */
453*54925bf6Swillf     status = kdb_load_library(kcontext, lib_name, lib);
454*54925bf6Swillf     if (status) {
455*54925bf6Swillf 	goto clean_n_exit;
456*54925bf6Swillf     }
457*54925bf6Swillf 
458*54925bf6Swillf     if (prev_elt) {
459*54925bf6Swillf 	/* prev_elt points to the last element in the list */
460*54925bf6Swillf 	prev_elt->next = *lib;
461*54925bf6Swillf 	(*lib)->prev = prev_elt;
462*54925bf6Swillf     } else {
463*54925bf6Swillf 	lib_list = *lib;
464*54925bf6Swillf     }
465*54925bf6Swillf 
466*54925bf6Swillf   clean_n_exit:
467*54925bf6Swillf     if (*lib) {
468*54925bf6Swillf 	(*lib)->reference_cnt++;
469*54925bf6Swillf     }
470*54925bf6Swillf 
471*54925bf6Swillf     if (locked) {
472*54925bf6Swillf 	(void)kdb_unlock_list();
473*54925bf6Swillf     }
474*54925bf6Swillf 
475*54925bf6Swillf     return status;
476*54925bf6Swillf }
477*54925bf6Swillf 
478*54925bf6Swillf static krb5_error_code
479*54925bf6Swillf kdb_free_library(db_library lib)
480*54925bf6Swillf {
481*54925bf6Swillf     krb5_error_code status = 0;
482*54925bf6Swillf     int     locked = 0;
483*54925bf6Swillf 
484*54925bf6Swillf     if ((status = kdb_lock_list()) != 0) {
485*54925bf6Swillf 	goto clean_n_exit;
486*54925bf6Swillf     }
487*54925bf6Swillf     locked = 1;
488*54925bf6Swillf 
489*54925bf6Swillf     lib->reference_cnt--;
490*54925bf6Swillf 
491*54925bf6Swillf     if (lib->reference_cnt == 0) {
492*54925bf6Swillf 	status = lib->vftabl.fini_library();
493*54925bf6Swillf 	if (status) {
494*54925bf6Swillf 	    goto clean_n_exit;
495*54925bf6Swillf 	}
496*54925bf6Swillf 
497*54925bf6Swillf 	/* close the library */
498*54925bf6Swillf         if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle))) {
499*54925bf6Swillf             krb5int_close_plugin_dirs (&lib->dl_dir_handle);
500*54925bf6Swillf         }
501*54925bf6Swillf 
502*54925bf6Swillf 	kdb_destroy_lib_lock(lib);
503*54925bf6Swillf 
504*54925bf6Swillf 	if (lib->prev == NULL) {
505*54925bf6Swillf 	    /* first element in the list */
506*54925bf6Swillf 	    lib_list = lib->next;
507*54925bf6Swillf 	} else {
508*54925bf6Swillf 	    lib->prev->next = lib->next;
509*54925bf6Swillf 	}
510*54925bf6Swillf 
511*54925bf6Swillf 	if (lib->next) {
512*54925bf6Swillf 	    lib->next->prev = lib->prev;
513*54925bf6Swillf 	}
514*54925bf6Swillf 	free(lib);
515*54925bf6Swillf     }
516*54925bf6Swillf 
517*54925bf6Swillf   clean_n_exit:
518*54925bf6Swillf     if (locked) {
519*54925bf6Swillf 	(void)kdb_unlock_list();
520*54925bf6Swillf     }
521*54925bf6Swillf 
522*54925bf6Swillf     return status;
523*54925bf6Swillf }
524*54925bf6Swillf 
525*54925bf6Swillf static krb5_error_code
526*54925bf6Swillf kdb_setup_lib_handle(krb5_context kcontext)
527*54925bf6Swillf {
528*54925bf6Swillf     char   *library = NULL;
529*54925bf6Swillf     krb5_error_code status = 0;
530*54925bf6Swillf     db_library lib = NULL;
531*54925bf6Swillf     kdb5_dal_handle *dal_handle = NULL;
532*54925bf6Swillf 
533*54925bf6Swillf     dal_handle = calloc((size_t) 1, sizeof(kdb5_dal_handle));
534*54925bf6Swillf     if (dal_handle == NULL) {
535*54925bf6Swillf 	status = ENOMEM;
536*54925bf6Swillf 	goto clean_n_exit;
537*54925bf6Swillf     }
538*54925bf6Swillf 
539*54925bf6Swillf     library = kdb_get_library_name(kcontext);
540*54925bf6Swillf     if (library == NULL) {
541*54925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
542*54925bf6Swillf 	goto clean_n_exit;
543*54925bf6Swillf     }
544*54925bf6Swillf 
545*54925bf6Swillf     status = kdb_find_library(kcontext, library, &lib);
546*54925bf6Swillf     if (status) {
547*54925bf6Swillf 	goto clean_n_exit;
548*54925bf6Swillf     }
549*54925bf6Swillf 
550*54925bf6Swillf     dal_handle->lib_handle = lib;
551*54925bf6Swillf     kcontext->db_context = (void *) dal_handle;
552*54925bf6Swillf 
553*54925bf6Swillf   clean_n_exit:
554*54925bf6Swillf     free(library);
555*54925bf6Swillf 
556*54925bf6Swillf     if (status) {
557*54925bf6Swillf 	free(dal_handle);
558*54925bf6Swillf 	if (lib) {
559*54925bf6Swillf 	    (void)kdb_free_library(lib);
560*54925bf6Swillf 	}
561*54925bf6Swillf     }
562*54925bf6Swillf 
563*54925bf6Swillf     return status;
564*54925bf6Swillf }
565*54925bf6Swillf 
566*54925bf6Swillf static krb5_error_code
567*54925bf6Swillf kdb_free_lib_handle(krb5_context kcontext)
568*54925bf6Swillf {
569*54925bf6Swillf     krb5_error_code status = 0;
570*54925bf6Swillf 
571*54925bf6Swillf     status =
572*54925bf6Swillf 	kdb_free_library(((kdb5_dal_handle *) kcontext->db_context)->
573*54925bf6Swillf 			 lib_handle);
574*54925bf6Swillf     if (status) {
575*54925bf6Swillf 	goto clean_n_exit;
576*54925bf6Swillf     }
577*54925bf6Swillf 
578*54925bf6Swillf     free(kcontext->db_context);
579*54925bf6Swillf     kcontext->db_context = NULL;
580*54925bf6Swillf 
581*54925bf6Swillf   clean_n_exit:
582*54925bf6Swillf     return status;
583*54925bf6Swillf }
584*54925bf6Swillf 
585*54925bf6Swillf static void
586*54925bf6Swillf get_errmsg (krb5_context kcontext, krb5_error_code err_code)
587*54925bf6Swillf {
588*54925bf6Swillf     kdb5_dal_handle *dal_handle;
589*54925bf6Swillf     const char *e;
590*54925bf6Swillf     if (err_code == 0)
591*54925bf6Swillf 	return;
592*54925bf6Swillf     assert(kcontext != NULL);
593*54925bf6Swillf     /* Must be called with dal_handle->lib_handle locked!  */
594*54925bf6Swillf     assert(kcontext->db_context != NULL);
595*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
596*54925bf6Swillf     if (dal_handle->lib_handle->vftabl.errcode_2_string == NULL)
597*54925bf6Swillf 	return;
598*54925bf6Swillf     e = dal_handle->lib_handle->vftabl.errcode_2_string(kcontext, err_code);
599*54925bf6Swillf     assert (e != NULL);
600*54925bf6Swillf     krb5_set_error_message(kcontext, err_code, "%s", e);
601*54925bf6Swillf     if (dal_handle->lib_handle->vftabl.release_errcode_string)
602*54925bf6Swillf 	dal_handle->lib_handle->vftabl.release_errcode_string(kcontext, e);
603*54925bf6Swillf }
604*54925bf6Swillf 
605*54925bf6Swillf /*
606*54925bf6Swillf  *      External functions... DAL API
607*54925bf6Swillf  */
608*54925bf6Swillf krb5_error_code
609*54925bf6Swillf krb5_db_open(krb5_context kcontext, char **db_args, int mode)
610*54925bf6Swillf {
611*54925bf6Swillf     krb5_error_code status = 0;
612*54925bf6Swillf     char   *section = NULL;
613*54925bf6Swillf     kdb5_dal_handle *dal_handle;
614*54925bf6Swillf 
615*54925bf6Swillf     section = kdb_get_conf_section(kcontext);
616*54925bf6Swillf     if (section == NULL) {
617*54925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
618*54925bf6Swillf 	krb5_set_error_message (kcontext, status,
619*54925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
620*54925bf6Swillf 		kcontext->default_realm ? kcontext->default_realm : "[UNSET]");
621*54925bf6Swillf 	goto clean_n_exit;
622*54925bf6Swillf     }
623*54925bf6Swillf 
624*54925bf6Swillf     if (kcontext->db_context == NULL) {
625*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
626*54925bf6Swillf 	if (status) {
627*54925bf6Swillf 	    goto clean_n_exit;
628*54925bf6Swillf 	}
629*54925bf6Swillf     }
630*54925bf6Swillf 
631*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
632*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
633*54925bf6Swillf     if (status) {
634*54925bf6Swillf 	goto clean_n_exit;
635*54925bf6Swillf     }
636*54925bf6Swillf 
637*54925bf6Swillf     status =
638*54925bf6Swillf 	dal_handle->lib_handle->vftabl.init_module(kcontext, section, db_args,
639*54925bf6Swillf 						   mode);
640*54925bf6Swillf     get_errmsg(kcontext, status);
641*54925bf6Swillf 
642*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
643*54925bf6Swillf 
644*54925bf6Swillf   clean_n_exit:
645*54925bf6Swillf     if (section)
646*54925bf6Swillf 	free(section);
647*54925bf6Swillf     return status;
648*54925bf6Swillf }
649*54925bf6Swillf 
650*54925bf6Swillf krb5_error_code
651*54925bf6Swillf krb5_db_inited(krb5_context kcontext)
652*54925bf6Swillf {
653*54925bf6Swillf     return !(kcontext && kcontext->db_context &&
654*54925bf6Swillf 	     ((kdb5_dal_handle *) kcontext->db_context)->db_context);
655*54925bf6Swillf }
656*54925bf6Swillf 
657*54925bf6Swillf krb5_error_code
658*54925bf6Swillf krb5_db_create(krb5_context kcontext, char **db_args)
659*54925bf6Swillf {
660*54925bf6Swillf     krb5_error_code status = 0;
661*54925bf6Swillf     char   *section = NULL;
662*54925bf6Swillf     kdb5_dal_handle *dal_handle;
663*54925bf6Swillf 
664*54925bf6Swillf     section = kdb_get_conf_section(kcontext);
665*54925bf6Swillf     if (section == NULL) {
666*54925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
667*54925bf6Swillf 	krb5_set_error_message (kcontext, status,
668*54925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
669*54925bf6Swillf 		kcontext->default_realm);
670*54925bf6Swillf 	goto clean_n_exit;
671*54925bf6Swillf     }
672*54925bf6Swillf 
673*54925bf6Swillf     if (kcontext->db_context == NULL) {
674*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
675*54925bf6Swillf 	if (status) {
676*54925bf6Swillf 	    goto clean_n_exit;
677*54925bf6Swillf 	}
678*54925bf6Swillf     }
679*54925bf6Swillf 
680*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
681*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
682*54925bf6Swillf     if (status) {
683*54925bf6Swillf 	goto clean_n_exit;
684*54925bf6Swillf     }
685*54925bf6Swillf 
686*54925bf6Swillf     status =
687*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_create(kcontext, section, db_args);
688*54925bf6Swillf     get_errmsg(kcontext, status);
689*54925bf6Swillf 
690*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
691*54925bf6Swillf 
692*54925bf6Swillf   clean_n_exit:
693*54925bf6Swillf     if (section)
694*54925bf6Swillf 	free(section);
695*54925bf6Swillf     return status;
696*54925bf6Swillf }
697*54925bf6Swillf 
698*54925bf6Swillf krb5_error_code
699*54925bf6Swillf krb5_db_fini(krb5_context kcontext)
700*54925bf6Swillf {
701*54925bf6Swillf     krb5_error_code status = 0;
702*54925bf6Swillf     kdb5_dal_handle *dal_handle;
703*54925bf6Swillf 
704*54925bf6Swillf     if (kcontext->db_context == NULL) {
705*54925bf6Swillf 	/* module not loaded. So nothing to be done */
706*54925bf6Swillf 	goto clean_n_exit;
707*54925bf6Swillf     }
708*54925bf6Swillf 
709*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
710*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
711*54925bf6Swillf     if (status) {
712*54925bf6Swillf 	goto clean_n_exit;
713*54925bf6Swillf     }
714*54925bf6Swillf 
715*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.fini_module(kcontext);
716*54925bf6Swillf     get_errmsg(kcontext, status);
717*54925bf6Swillf 
718*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
719*54925bf6Swillf 
720*54925bf6Swillf     if (status) {
721*54925bf6Swillf 	goto clean_n_exit;
722*54925bf6Swillf     }
723*54925bf6Swillf 
724*54925bf6Swillf     status = kdb_free_lib_handle(kcontext);
725*54925bf6Swillf 
726*54925bf6Swillf   clean_n_exit:
727*54925bf6Swillf     return status;
728*54925bf6Swillf }
729*54925bf6Swillf 
730*54925bf6Swillf krb5_error_code
731*54925bf6Swillf krb5_db_destroy(krb5_context kcontext, char **db_args)
732*54925bf6Swillf {
733*54925bf6Swillf     krb5_error_code status = 0;
734*54925bf6Swillf     char   *section = NULL;
735*54925bf6Swillf     kdb5_dal_handle *dal_handle;
736*54925bf6Swillf 
737*54925bf6Swillf     section = kdb_get_conf_section(kcontext);
738*54925bf6Swillf     if (section == NULL) {
739*54925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
740*54925bf6Swillf 	krb5_set_error_message (kcontext, status,
741*54925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
742*54925bf6Swillf 		kcontext->default_realm);
743*54925bf6Swillf 	goto clean_n_exit;
744*54925bf6Swillf     }
745*54925bf6Swillf 
746*54925bf6Swillf     if (kcontext->db_context == NULL) {
747*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
748*54925bf6Swillf 	if (status) {
749*54925bf6Swillf 	    goto clean_n_exit;
750*54925bf6Swillf 	}
751*54925bf6Swillf     }
752*54925bf6Swillf 
753*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
754*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
755*54925bf6Swillf     if (status) {
756*54925bf6Swillf 	goto clean_n_exit;
757*54925bf6Swillf     }
758*54925bf6Swillf 
759*54925bf6Swillf     status =
760*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_destroy(kcontext, section, db_args);
761*54925bf6Swillf     get_errmsg(kcontext, status);
762*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
763*54925bf6Swillf 
764*54925bf6Swillf   clean_n_exit:
765*54925bf6Swillf     if (section)
766*54925bf6Swillf 	free(section);
767*54925bf6Swillf     return status;
768*54925bf6Swillf }
769*54925bf6Swillf 
770*54925bf6Swillf krb5_error_code
771*54925bf6Swillf krb5_db_get_age(krb5_context kcontext, char *db_name, time_t * t)
772*54925bf6Swillf {
773*54925bf6Swillf     krb5_error_code status = 0;
774*54925bf6Swillf     kdb5_dal_handle *dal_handle;
775*54925bf6Swillf 
776*54925bf6Swillf     if (kcontext->db_context == NULL) {
777*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
778*54925bf6Swillf 	if (status) {
779*54925bf6Swillf 	    goto clean_n_exit;
780*54925bf6Swillf 	}
781*54925bf6Swillf     }
782*54925bf6Swillf 
783*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
784*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
785*54925bf6Swillf     if (status) {
786*54925bf6Swillf 	goto clean_n_exit;
787*54925bf6Swillf     }
788*54925bf6Swillf 
789*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_get_age(kcontext, db_name, t);
790*54925bf6Swillf     get_errmsg(kcontext, status);
791*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
792*54925bf6Swillf 
793*54925bf6Swillf   clean_n_exit:
794*54925bf6Swillf     return status;
795*54925bf6Swillf }
796*54925bf6Swillf 
797*54925bf6Swillf krb5_error_code
798*54925bf6Swillf krb5_db_set_option(krb5_context kcontext, int option, void *value)
799*54925bf6Swillf {
800*54925bf6Swillf     krb5_error_code status = 0;
801*54925bf6Swillf     kdb5_dal_handle *dal_handle;
802*54925bf6Swillf 
803*54925bf6Swillf     if (kcontext->db_context == NULL) {
804*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
805*54925bf6Swillf 	if (status) {
806*54925bf6Swillf 	    goto clean_n_exit;
807*54925bf6Swillf 	}
808*54925bf6Swillf     }
809*54925bf6Swillf 
810*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
811*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
812*54925bf6Swillf     if (status) {
813*54925bf6Swillf 	goto clean_n_exit;
814*54925bf6Swillf     }
815*54925bf6Swillf 
816*54925bf6Swillf     status =
817*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_set_option(kcontext, option, value);
818*54925bf6Swillf     get_errmsg(kcontext, status);
819*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
820*54925bf6Swillf 
821*54925bf6Swillf   clean_n_exit:
822*54925bf6Swillf     return status;
823*54925bf6Swillf }
824*54925bf6Swillf 
825*54925bf6Swillf krb5_error_code
826*54925bf6Swillf krb5_db_lock(krb5_context kcontext, int lock_mode)
827*54925bf6Swillf {
828*54925bf6Swillf     krb5_error_code status = 0;
829*54925bf6Swillf     kdb5_dal_handle *dal_handle;
830*54925bf6Swillf 
831*54925bf6Swillf     if (kcontext->db_context == NULL) {
832*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
833*54925bf6Swillf 	if (status) {
834*54925bf6Swillf 	    goto clean_n_exit;
835*54925bf6Swillf 	}
836*54925bf6Swillf     }
837*54925bf6Swillf 
838*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
839*54925bf6Swillf     /* acquire an exclusive lock, ensures no other thread uses this context */
840*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, TRUE);
841*54925bf6Swillf     if (status) {
842*54925bf6Swillf 	goto clean_n_exit;
843*54925bf6Swillf     }
844*54925bf6Swillf 
845*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_lock(kcontext, lock_mode);
846*54925bf6Swillf     get_errmsg(kcontext, status);
847*54925bf6Swillf 
848*54925bf6Swillf     /* exclusive lock is still held, so no other thread could use this context */
849*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
850*54925bf6Swillf 
851*54925bf6Swillf   clean_n_exit:
852*54925bf6Swillf     return status;
853*54925bf6Swillf }
854*54925bf6Swillf 
855*54925bf6Swillf krb5_error_code
856*54925bf6Swillf krb5_db_unlock(krb5_context kcontext)
857*54925bf6Swillf {
858*54925bf6Swillf     krb5_error_code status = 0;
859*54925bf6Swillf     kdb5_dal_handle *dal_handle;
860*54925bf6Swillf 
861*54925bf6Swillf     if (kcontext->db_context == NULL) {
862*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
863*54925bf6Swillf 	if (status) {
864*54925bf6Swillf 	    goto clean_n_exit;
865*54925bf6Swillf 	}
866*54925bf6Swillf     }
867*54925bf6Swillf 
868*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
869*54925bf6Swillf     /* normal lock acquired and exclusive lock released */
870*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
871*54925bf6Swillf     if (status) {
872*54925bf6Swillf 	goto clean_n_exit;
873*54925bf6Swillf     }
874*54925bf6Swillf 
875*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_unlock(kcontext);
876*54925bf6Swillf     get_errmsg(kcontext, status);
877*54925bf6Swillf 
878*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, TRUE);
879*54925bf6Swillf 
880*54925bf6Swillf   clean_n_exit:
881*54925bf6Swillf     return status;
882*54925bf6Swillf }
883*54925bf6Swillf 
884*54925bf6Swillf krb5_error_code
885*54925bf6Swillf krb5_db_get_principal(krb5_context kcontext,
886*54925bf6Swillf 		      krb5_const_principal search_for,
887*54925bf6Swillf 		      krb5_db_entry * entries,
888*54925bf6Swillf 		      int *nentries, krb5_boolean * more)
889*54925bf6Swillf {
890*54925bf6Swillf     krb5_error_code status = 0;
891*54925bf6Swillf     kdb5_dal_handle *dal_handle;
892*54925bf6Swillf 
893*54925bf6Swillf     if (kcontext->db_context == NULL) {
894*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
895*54925bf6Swillf 	if (status) {
896*54925bf6Swillf 	    goto clean_n_exit;
897*54925bf6Swillf 	}
898*54925bf6Swillf     }
899*54925bf6Swillf 
900*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
901*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
902*54925bf6Swillf     if (status) {
903*54925bf6Swillf 	goto clean_n_exit;
904*54925bf6Swillf     }
905*54925bf6Swillf 
906*54925bf6Swillf     status =
907*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_get_principal(kcontext, search_for,
908*54925bf6Swillf 							entries, nentries,
909*54925bf6Swillf 							more);
910*54925bf6Swillf     get_errmsg(kcontext, status);
911*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
912*54925bf6Swillf 
913*54925bf6Swillf   clean_n_exit:
914*54925bf6Swillf     return status;
915*54925bf6Swillf }
916*54925bf6Swillf 
917*54925bf6Swillf krb5_error_code
918*54925bf6Swillf krb5_db_get_principal_nolock(krb5_context kcontext,
919*54925bf6Swillf 		      krb5_const_principal search_for,
920*54925bf6Swillf 		      krb5_db_entry * entries,
921*54925bf6Swillf 		      int *nentries, krb5_boolean * more)
922*54925bf6Swillf {
923*54925bf6Swillf     krb5_error_code status = 0;
924*54925bf6Swillf     kdb5_dal_handle *dal_handle;
925*54925bf6Swillf 
926*54925bf6Swillf     if (kcontext->db_context == NULL) {
927*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
928*54925bf6Swillf 	if (status) {
929*54925bf6Swillf 	    goto clean_n_exit;
930*54925bf6Swillf 	}
931*54925bf6Swillf     }
932*54925bf6Swillf 
933*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
934*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
935*54925bf6Swillf     if (status) {
936*54925bf6Swillf 	goto clean_n_exit;
937*54925bf6Swillf     }
938*54925bf6Swillf 
939*54925bf6Swillf     status =
940*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_get_principal_nolock(kcontext,
941*54925bf6Swillf 							search_for,
942*54925bf6Swillf 							entries, nentries,
943*54925bf6Swillf 							more);
944*54925bf6Swillf     get_errmsg(kcontext, status);
945*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
946*54925bf6Swillf 
947*54925bf6Swillf   clean_n_exit:
948*54925bf6Swillf     return status;
949*54925bf6Swillf }
950*54925bf6Swillf 
951*54925bf6Swillf krb5_error_code
952*54925bf6Swillf krb5_db_free_principal(krb5_context kcontext, krb5_db_entry * entry, int count)
953*54925bf6Swillf {
954*54925bf6Swillf     krb5_error_code status = 0;
955*54925bf6Swillf     kdb5_dal_handle *dal_handle;
956*54925bf6Swillf 
957*54925bf6Swillf     if (kcontext->db_context == NULL) {
958*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
959*54925bf6Swillf 	if (status) {
960*54925bf6Swillf 	    goto clean_n_exit;
961*54925bf6Swillf 	}
962*54925bf6Swillf     }
963*54925bf6Swillf 
964*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
965*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
966*54925bf6Swillf     if (status) {
967*54925bf6Swillf 	goto clean_n_exit;
968*54925bf6Swillf     }
969*54925bf6Swillf 
970*54925bf6Swillf     status =
971*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_free_principal(kcontext, entry,
972*54925bf6Swillf 							 count);
973*54925bf6Swillf     get_errmsg(kcontext, status);
974*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
975*54925bf6Swillf 
976*54925bf6Swillf   clean_n_exit:
977*54925bf6Swillf     return status;
978*54925bf6Swillf }
979*54925bf6Swillf 
980*54925bf6Swillf krb5_error_code
981*54925bf6Swillf krb5_db_put_principal(krb5_context kcontext,
982*54925bf6Swillf 		      krb5_db_entry * entries, int *nentries)
983*54925bf6Swillf {
984*54925bf6Swillf     krb5_error_code status = 0;
985*54925bf6Swillf     kdb5_dal_handle *dal_handle;
986*54925bf6Swillf     char  **db_args = NULL;
987*54925bf6Swillf     krb5_tl_data *prev, *curr, *next;
988*54925bf6Swillf     int     db_args_size = 0;
989*54925bf6Swillf 
990*54925bf6Swillf     if (kcontext->db_context == NULL) {
991*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
992*54925bf6Swillf 	if (status) {
993*54925bf6Swillf 	    goto clean_n_exit;
994*54925bf6Swillf 	}
995*54925bf6Swillf     }
996*54925bf6Swillf 
997*54925bf6Swillf     /* Giving db_args as part of tl data causes, db2 to store the
998*54925bf6Swillf        tl_data as such.  To prevent this, tl_data is collated and
999*54925bf6Swillf        passed as a sepearte argument. Currently supports only one
1000*54925bf6Swillf        principal.  but passing it as a seperate argument makes it
1001*54925bf6Swillf        difficult for kadmin remote to pass arguments to server.  */
1002*54925bf6Swillf     prev = NULL, curr = entries->tl_data;
1003*54925bf6Swillf     while (curr) {
1004*54925bf6Swillf 	if (curr->tl_data_type == KRB5_TL_DB_ARGS) {
1005*54925bf6Swillf 	    char  **t;
1006*54925bf6Swillf 	    /* Since this is expected to be NULL terminated string and
1007*54925bf6Swillf 	       this could come from any client, do a check before
1008*54925bf6Swillf 	       passing it to db.  */
1009*54925bf6Swillf 	    if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] !=
1010*54925bf6Swillf 		'\0') {
1011*54925bf6Swillf 		/* not null terminated. Dangerous input */
1012*54925bf6Swillf 		status = EINVAL;
1013*54925bf6Swillf 		goto clean_n_exit;
1014*54925bf6Swillf 	    }
1015*54925bf6Swillf 
1016*54925bf6Swillf 	    db_args_size++;
1017*54925bf6Swillf 	    t = realloc(db_args, sizeof(char *) * (db_args_size + 1));	/* 1 for NULL */
1018*54925bf6Swillf 	    if (t == NULL) {
1019*54925bf6Swillf 		status = ENOMEM;
1020*54925bf6Swillf 		goto clean_n_exit;
1021*54925bf6Swillf 	    }
1022*54925bf6Swillf 
1023*54925bf6Swillf 	    db_args = t;
1024*54925bf6Swillf 	    db_args[db_args_size - 1] = (char *) curr->tl_data_contents;
1025*54925bf6Swillf 	    db_args[db_args_size] = NULL;
1026*54925bf6Swillf 
1027*54925bf6Swillf 	    next = curr->tl_data_next;
1028*54925bf6Swillf 	    if (prev == NULL) {
1029*54925bf6Swillf 		/* current node is the first in the linked list. remove it */
1030*54925bf6Swillf 		entries->tl_data = curr->tl_data_next;
1031*54925bf6Swillf 	    } else {
1032*54925bf6Swillf 		prev->tl_data_next = curr->tl_data_next;
1033*54925bf6Swillf 	    }
1034*54925bf6Swillf 	    entries->n_tl_data--;
1035*54925bf6Swillf 	    krb5_db_free(kcontext, curr);
1036*54925bf6Swillf 
1037*54925bf6Swillf 	    /* previous does not change */
1038*54925bf6Swillf 	    curr = next;
1039*54925bf6Swillf 	} else {
1040*54925bf6Swillf 	    prev = curr;
1041*54925bf6Swillf 	    curr = curr->tl_data_next;
1042*54925bf6Swillf 	}
1043*54925bf6Swillf     }
1044*54925bf6Swillf 
1045*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1046*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1047*54925bf6Swillf     if (status) {
1048*54925bf6Swillf 	goto clean_n_exit;
1049*54925bf6Swillf     }
1050*54925bf6Swillf 
1051*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries,
1052*54925bf6Swillf 							     nentries,
1053*54925bf6Swillf 							     db_args);
1054*54925bf6Swillf     get_errmsg(kcontext, status);
1055*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1056*54925bf6Swillf 
1057*54925bf6Swillf   clean_n_exit:
1058*54925bf6Swillf     while (db_args_size) {
1059*54925bf6Swillf 	if (db_args[db_args_size - 1])
1060*54925bf6Swillf 	    krb5_db_free(kcontext, db_args[db_args_size - 1]);
1061*54925bf6Swillf 
1062*54925bf6Swillf 	db_args_size--;
1063*54925bf6Swillf     }
1064*54925bf6Swillf 
1065*54925bf6Swillf     if (db_args)
1066*54925bf6Swillf 	free(db_args);
1067*54925bf6Swillf 
1068*54925bf6Swillf     return status;
1069*54925bf6Swillf }
1070*54925bf6Swillf 
1071*54925bf6Swillf krb5_error_code
1072*54925bf6Swillf krb5_db_delete_principal(krb5_context kcontext,
1073*54925bf6Swillf 			 krb5_principal search_for, int *nentries)
1074*54925bf6Swillf {
1075*54925bf6Swillf     krb5_error_code status = 0;
1076*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1077*54925bf6Swillf 
1078*54925bf6Swillf     if (kcontext->db_context == NULL) {
1079*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1080*54925bf6Swillf 	if (status) {
1081*54925bf6Swillf 	    goto clean_n_exit;
1082*54925bf6Swillf 	}
1083*54925bf6Swillf     }
1084*54925bf6Swillf 
1085*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1086*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1087*54925bf6Swillf     if (status) {
1088*54925bf6Swillf 	goto clean_n_exit;
1089*54925bf6Swillf     }
1090*54925bf6Swillf 
1091*54925bf6Swillf     status =
1092*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_delete_principal(kcontext,
1093*54925bf6Swillf 							   search_for,
1094*54925bf6Swillf 							   nentries);
1095*54925bf6Swillf     get_errmsg(kcontext, status);
1096*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1097*54925bf6Swillf 
1098*54925bf6Swillf   clean_n_exit:
1099*54925bf6Swillf     return status;
1100*54925bf6Swillf }
1101*54925bf6Swillf 
1102*54925bf6Swillf krb5_error_code
1103*54925bf6Swillf krb5_db_iterate(krb5_context kcontext,
1104*54925bf6Swillf 		char *match_entry,
1105*54925bf6Swillf 		int (*func) (krb5_pointer, krb5_db_entry *),
1106*54925bf6Swillf 		krb5_pointer func_arg)
1107*54925bf6Swillf {
1108*54925bf6Swillf     krb5_error_code status = 0;
1109*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1110*54925bf6Swillf 
1111*54925bf6Swillf     if (kcontext->db_context == NULL) {
1112*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1113*54925bf6Swillf 	if (status) {
1114*54925bf6Swillf 	    goto clean_n_exit;
1115*54925bf6Swillf 	}
1116*54925bf6Swillf     }
1117*54925bf6Swillf 
1118*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1119*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1120*54925bf6Swillf     if (status) {
1121*54925bf6Swillf 	goto clean_n_exit;
1122*54925bf6Swillf     }
1123*54925bf6Swillf 
1124*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_iterate(kcontext,
1125*54925bf6Swillf 						       match_entry,
1126*54925bf6Swillf 						       func, func_arg);
1127*54925bf6Swillf     get_errmsg(kcontext, status);
1128*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1129*54925bf6Swillf 
1130*54925bf6Swillf   clean_n_exit:
1131*54925bf6Swillf     return status;
1132*54925bf6Swillf }
1133*54925bf6Swillf 
1134*54925bf6Swillf krb5_error_code
1135*54925bf6Swillf krb5_supported_realms(krb5_context kcontext, char **realms)
1136*54925bf6Swillf {
1137*54925bf6Swillf     krb5_error_code status = 0;
1138*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1139*54925bf6Swillf 
1140*54925bf6Swillf     if (kcontext->db_context == NULL) {
1141*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1142*54925bf6Swillf 	if (status) {
1143*54925bf6Swillf 	    goto clean_n_exit;
1144*54925bf6Swillf 	}
1145*54925bf6Swillf     }
1146*54925bf6Swillf 
1147*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1148*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1149*54925bf6Swillf     if (status) {
1150*54925bf6Swillf 	goto clean_n_exit;
1151*54925bf6Swillf     }
1152*54925bf6Swillf 
1153*54925bf6Swillf     status =
1154*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_supported_realms(kcontext, realms);
1155*54925bf6Swillf     get_errmsg(kcontext, status);
1156*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1157*54925bf6Swillf 
1158*54925bf6Swillf   clean_n_exit:
1159*54925bf6Swillf     return status;
1160*54925bf6Swillf }
1161*54925bf6Swillf 
1162*54925bf6Swillf krb5_error_code
1163*54925bf6Swillf krb5_free_supported_realms(krb5_context kcontext, char **realms)
1164*54925bf6Swillf {
1165*54925bf6Swillf     krb5_error_code status = 0;
1166*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1167*54925bf6Swillf 
1168*54925bf6Swillf     if (kcontext->db_context == NULL) {
1169*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1170*54925bf6Swillf 	if (status) {
1171*54925bf6Swillf 	    goto clean_n_exit;
1172*54925bf6Swillf 	}
1173*54925bf6Swillf     }
1174*54925bf6Swillf 
1175*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1176*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1177*54925bf6Swillf     if (status) {
1178*54925bf6Swillf 	goto clean_n_exit;
1179*54925bf6Swillf     }
1180*54925bf6Swillf 
1181*54925bf6Swillf     status =
1182*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_free_supported_realms(kcontext,
1183*54925bf6Swillf 								realms);
1184*54925bf6Swillf     get_errmsg(kcontext, status);
1185*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1186*54925bf6Swillf 
1187*54925bf6Swillf   clean_n_exit:
1188*54925bf6Swillf     return status;
1189*54925bf6Swillf }
1190*54925bf6Swillf 
1191*54925bf6Swillf krb5_error_code
1192*54925bf6Swillf krb5_db_set_master_key_ext(krb5_context kcontext,
1193*54925bf6Swillf 			   char *pwd, krb5_keyblock * key)
1194*54925bf6Swillf {
1195*54925bf6Swillf     krb5_error_code status = 0;
1196*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1197*54925bf6Swillf 
1198*54925bf6Swillf     if (kcontext->db_context == NULL) {
1199*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1200*54925bf6Swillf 	if (status) {
1201*54925bf6Swillf 	    goto clean_n_exit;
1202*54925bf6Swillf 	}
1203*54925bf6Swillf     }
1204*54925bf6Swillf 
1205*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1206*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1207*54925bf6Swillf     if (status) {
1208*54925bf6Swillf 	goto clean_n_exit;
1209*54925bf6Swillf     }
1210*54925bf6Swillf 
1211*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.set_master_key(kcontext, pwd, key);
1212*54925bf6Swillf     get_errmsg(kcontext, status);
1213*54925bf6Swillf 
1214*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1215*54925bf6Swillf 
1216*54925bf6Swillf   clean_n_exit:
1217*54925bf6Swillf     return status;
1218*54925bf6Swillf }
1219*54925bf6Swillf 
1220*54925bf6Swillf krb5_error_code
1221*54925bf6Swillf krb5_db_set_mkey(krb5_context context, krb5_keyblock * key)
1222*54925bf6Swillf {
1223*54925bf6Swillf     return krb5_db_set_master_key_ext(context, NULL, key);
1224*54925bf6Swillf }
1225*54925bf6Swillf 
1226*54925bf6Swillf krb5_error_code
1227*54925bf6Swillf krb5_db_get_mkey(krb5_context kcontext, krb5_keyblock ** key)
1228*54925bf6Swillf {
1229*54925bf6Swillf     krb5_error_code status = 0;
1230*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1231*54925bf6Swillf 
1232*54925bf6Swillf     if (kcontext->db_context == NULL) {
1233*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1234*54925bf6Swillf 	if (status) {
1235*54925bf6Swillf 	    goto clean_n_exit;
1236*54925bf6Swillf 	}
1237*54925bf6Swillf     }
1238*54925bf6Swillf 
1239*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1240*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1241*54925bf6Swillf     if (status) {
1242*54925bf6Swillf 	goto clean_n_exit;
1243*54925bf6Swillf     }
1244*54925bf6Swillf 
1245*54925bf6Swillf     /* Lets use temp key and copy it later to avoid memory problems
1246*54925bf6Swillf        when freed by the caller.  */
1247*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.get_master_key(kcontext, key);
1248*54925bf6Swillf     get_errmsg(kcontext, status);
1249*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1250*54925bf6Swillf 
1251*54925bf6Swillf   clean_n_exit:
1252*54925bf6Swillf     return status;
1253*54925bf6Swillf }
1254*54925bf6Swillf 
1255*54925bf6Swillf krb5_error_code
1256*54925bf6Swillf krb5_db_store_master_key(krb5_context kcontext,
1257*54925bf6Swillf 			 char *db_arg,
1258*54925bf6Swillf 			 krb5_principal mname,
1259*54925bf6Swillf 			 krb5_keyblock * key, char *master_pwd)
1260*54925bf6Swillf {
1261*54925bf6Swillf     krb5_error_code status = 0;
1262*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1263*54925bf6Swillf 
1264*54925bf6Swillf     if (kcontext->db_context == NULL) {
1265*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1266*54925bf6Swillf 	if (status) {
1267*54925bf6Swillf 	    goto clean_n_exit;
1268*54925bf6Swillf 	}
1269*54925bf6Swillf     }
1270*54925bf6Swillf 
1271*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1272*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1273*54925bf6Swillf     if (status) {
1274*54925bf6Swillf 	goto clean_n_exit;
1275*54925bf6Swillf     }
1276*54925bf6Swillf 
1277*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.store_master_key(kcontext,
1278*54925bf6Swillf 							     db_arg,
1279*54925bf6Swillf 							     mname,
1280*54925bf6Swillf 							     key, master_pwd);
1281*54925bf6Swillf     get_errmsg(kcontext, status);
1282*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1283*54925bf6Swillf 
1284*54925bf6Swillf   clean_n_exit:
1285*54925bf6Swillf     return status;
1286*54925bf6Swillf }
1287*54925bf6Swillf 
1288*54925bf6Swillf char   *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
1289*54925bf6Swillf char   *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
1290*54925bf6Swillf 
1291*54925bf6Swillf krb5_error_code
1292*54925bf6Swillf krb5_db_fetch_mkey(krb5_context context,
1293*54925bf6Swillf 		   krb5_principal mname,
1294*54925bf6Swillf 		   krb5_enctype etype,
1295*54925bf6Swillf 		   krb5_boolean fromkeyboard,
1296*54925bf6Swillf 		   krb5_boolean twice,
1297*54925bf6Swillf 		   char *db_args, krb5_data * salt, krb5_keyblock * key)
1298*54925bf6Swillf {
1299*54925bf6Swillf     krb5_error_code retval;
1300*54925bf6Swillf     char    password[BUFSIZ];
1301*54925bf6Swillf     krb5_data pwd;
1302*54925bf6Swillf     unsigned int size = sizeof(password);
1303*54925bf6Swillf     int     kvno;
1304*54925bf6Swillf     krb5_keyblock tmp_key;
1305*54925bf6Swillf 
1306*54925bf6Swillf     memset(&tmp_key, 0, sizeof(tmp_key));
1307*54925bf6Swillf 
1308*54925bf6Swillf     if (fromkeyboard) {
1309*54925bf6Swillf 	krb5_data scratch;
1310*54925bf6Swillf 
1311*54925bf6Swillf 	if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
1312*54925bf6Swillf 					 twice ? krb5_mkey_pwd_prompt2 : 0,
1313*54925bf6Swillf 					 password, &size))) {
1314*54925bf6Swillf 	    goto clean_n_exit;
1315*54925bf6Swillf 	}
1316*54925bf6Swillf 
1317*54925bf6Swillf 	pwd.data = password;
1318*54925bf6Swillf 	pwd.length = size;
1319*54925bf6Swillf 	if (!salt) {
1320*54925bf6Swillf 	    retval = krb5_principal2salt(context, mname, &scratch);
1321*54925bf6Swillf 	    if (retval)
1322*54925bf6Swillf 		goto clean_n_exit;
1323*54925bf6Swillf 	}
1324*54925bf6Swillf 	retval =
1325*54925bf6Swillf 	    krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch,
1326*54925bf6Swillf 				 key);
1327*54925bf6Swillf 
1328*54925bf6Swillf 	if (!salt)
1329*54925bf6Swillf 	    krb5_xfree(scratch.data);
1330*54925bf6Swillf 	memset(password, 0, sizeof(password));	/* erase it */
1331*54925bf6Swillf 
1332*54925bf6Swillf     } else {
1333*54925bf6Swillf 	kdb5_dal_handle *dal_handle;
1334*54925bf6Swillf 
1335*54925bf6Swillf 	if (context->db_context == NULL) {
1336*54925bf6Swillf 	    retval = kdb_setup_lib_handle(context);
1337*54925bf6Swillf 	    if (retval) {
1338*54925bf6Swillf 		goto clean_n_exit;
1339*54925bf6Swillf 	    }
1340*54925bf6Swillf 	}
1341*54925bf6Swillf 
1342*54925bf6Swillf 	dal_handle = (kdb5_dal_handle *) context->db_context;
1343*54925bf6Swillf 	retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1344*54925bf6Swillf 	if (retval) {
1345*54925bf6Swillf 	    goto clean_n_exit;
1346*54925bf6Swillf 	}
1347*54925bf6Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
1348*54925bf6Swillf 	/* Orig MIT */
1349*54925bf6Swillf 	tmp_key.enctype = key->enctype;
1350*54925bf6Swillf #else
1351*54925bf6Swillf 	/* Solaris Kerberos: need to use etype */
1352*54925bf6Swillf 	tmp_key.enctype = etype;
1353*54925bf6Swillf #endif /**************** END IFDEF'ed OUT *******************************/
1354*54925bf6Swillf 	retval = dal_handle->lib_handle->vftabl.fetch_master_key(context,
1355*54925bf6Swillf 								 mname,
1356*54925bf6Swillf 								 &tmp_key,
1357*54925bf6Swillf 								 &kvno,
1358*54925bf6Swillf 								 db_args);
1359*54925bf6Swillf 	get_errmsg(context, retval);
1360*54925bf6Swillf 	kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1361*54925bf6Swillf 
1362*54925bf6Swillf 	if (retval) {
1363*54925bf6Swillf 	    goto clean_n_exit;
1364*54925bf6Swillf 	}
1365*54925bf6Swillf 
1366*54925bf6Swillf 	key->contents = malloc(tmp_key.length);
1367*54925bf6Swillf 	if (key->contents == NULL) {
1368*54925bf6Swillf 	    retval = ENOMEM;
1369*54925bf6Swillf 	    goto clean_n_exit;
1370*54925bf6Swillf 	}
1371*54925bf6Swillf 
1372*54925bf6Swillf 	key->magic = tmp_key.magic;
1373*54925bf6Swillf 	key->enctype = tmp_key.enctype;
1374*54925bf6Swillf 	key->length = tmp_key.length;
1375*54925bf6Swillf 	memcpy(key->contents, tmp_key.contents, tmp_key.length);
1376*54925bf6Swillf     }
1377*54925bf6Swillf 
1378*54925bf6Swillf   clean_n_exit:
1379*54925bf6Swillf     if (tmp_key.contents) {
1380*54925bf6Swillf 	memset(tmp_key.contents, 0, tmp_key.length);
1381*54925bf6Swillf 	krb5_db_free(context, tmp_key.contents);
1382*54925bf6Swillf     }
1383*54925bf6Swillf     return retval;
1384*54925bf6Swillf }
1385*54925bf6Swillf 
1386*54925bf6Swillf krb5_error_code
1387*54925bf6Swillf krb5_db_verify_master_key(krb5_context kcontext,
1388*54925bf6Swillf 			  krb5_principal mprinc, krb5_keyblock * mkey)
1389*54925bf6Swillf {
1390*54925bf6Swillf     krb5_error_code status = 0;
1391*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1392*54925bf6Swillf 
1393*54925bf6Swillf     if (kcontext->db_context == NULL) {
1394*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1395*54925bf6Swillf 	if (status) {
1396*54925bf6Swillf 	    goto clean_n_exit;
1397*54925bf6Swillf 	}
1398*54925bf6Swillf     }
1399*54925bf6Swillf 
1400*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1401*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1402*54925bf6Swillf     if (status) {
1403*54925bf6Swillf 	goto clean_n_exit;
1404*54925bf6Swillf     }
1405*54925bf6Swillf 
1406*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.verify_master_key(kcontext,
1407*54925bf6Swillf 							      mprinc, mkey);
1408*54925bf6Swillf     get_errmsg(kcontext, status);
1409*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1410*54925bf6Swillf 
1411*54925bf6Swillf   clean_n_exit:
1412*54925bf6Swillf     return status;
1413*54925bf6Swillf }
1414*54925bf6Swillf 
1415*54925bf6Swillf void   *
1416*54925bf6Swillf krb5_db_alloc(krb5_context kcontext, void *ptr, size_t size)
1417*54925bf6Swillf {
1418*54925bf6Swillf     krb5_error_code status;
1419*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1420*54925bf6Swillf     void   *new_ptr = NULL;
1421*54925bf6Swillf 
1422*54925bf6Swillf     if (kcontext->db_context == NULL) {
1423*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1424*54925bf6Swillf 	if (status) {
1425*54925bf6Swillf 	    goto clean_n_exit;
1426*54925bf6Swillf 	}
1427*54925bf6Swillf     }
1428*54925bf6Swillf 
1429*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1430*54925bf6Swillf 
1431*54925bf6Swillf     new_ptr = dal_handle->lib_handle->vftabl.db_alloc(kcontext, ptr, size);
1432*54925bf6Swillf 
1433*54925bf6Swillf   clean_n_exit:
1434*54925bf6Swillf     return new_ptr;
1435*54925bf6Swillf }
1436*54925bf6Swillf 
1437*54925bf6Swillf void
1438*54925bf6Swillf krb5_db_free(krb5_context kcontext, void *ptr)
1439*54925bf6Swillf {
1440*54925bf6Swillf     krb5_error_code status;
1441*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1442*54925bf6Swillf 
1443*54925bf6Swillf     if (kcontext->db_context == NULL) {
1444*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1445*54925bf6Swillf 	if (status) {
1446*54925bf6Swillf 	    goto clean_n_exit;
1447*54925bf6Swillf 	}
1448*54925bf6Swillf     }
1449*54925bf6Swillf 
1450*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1451*54925bf6Swillf 
1452*54925bf6Swillf     dal_handle->lib_handle->vftabl.db_free(kcontext, ptr);
1453*54925bf6Swillf 
1454*54925bf6Swillf   clean_n_exit:
1455*54925bf6Swillf     return;
1456*54925bf6Swillf }
1457*54925bf6Swillf 
1458*54925bf6Swillf /* has to be modified */
1459*54925bf6Swillf 
1460*54925bf6Swillf krb5_error_code
1461*54925bf6Swillf krb5_dbe_find_enctype(krb5_context kcontext,
1462*54925bf6Swillf 		      krb5_db_entry * dbentp,
1463*54925bf6Swillf 		      krb5_int32 ktype,
1464*54925bf6Swillf 		      krb5_int32 stype,
1465*54925bf6Swillf 		      krb5_int32 kvno, krb5_key_data ** kdatap)
1466*54925bf6Swillf {
1467*54925bf6Swillf     krb5_int32 start = 0;
1468*54925bf6Swillf     return krb5_dbe_search_enctype(kcontext, dbentp, &start, ktype, stype,
1469*54925bf6Swillf 				   kvno, kdatap);
1470*54925bf6Swillf }
1471*54925bf6Swillf 
1472*54925bf6Swillf krb5_error_code
1473*54925bf6Swillf krb5_dbe_search_enctype(krb5_context kcontext,
1474*54925bf6Swillf 			krb5_db_entry * dbentp,
1475*54925bf6Swillf 			krb5_int32 * start,
1476*54925bf6Swillf 			krb5_int32 ktype,
1477*54925bf6Swillf 			krb5_int32 stype,
1478*54925bf6Swillf 			krb5_int32 kvno, krb5_key_data ** kdatap)
1479*54925bf6Swillf {
1480*54925bf6Swillf     krb5_error_code status = 0;
1481*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1482*54925bf6Swillf 
1483*54925bf6Swillf     if (kcontext->db_context == NULL) {
1484*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1485*54925bf6Swillf 	if (status) {
1486*54925bf6Swillf 	    goto clean_n_exit;
1487*54925bf6Swillf 	}
1488*54925bf6Swillf     }
1489*54925bf6Swillf 
1490*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1491*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1492*54925bf6Swillf     if (status) {
1493*54925bf6Swillf 	goto clean_n_exit;
1494*54925bf6Swillf     }
1495*54925bf6Swillf 
1496*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.dbe_search_enctype(kcontext,
1497*54925bf6Swillf 							       dbentp,
1498*54925bf6Swillf 							       start,
1499*54925bf6Swillf 							       ktype,
1500*54925bf6Swillf 							       stype,
1501*54925bf6Swillf 							       kvno, kdatap);
1502*54925bf6Swillf     get_errmsg(kcontext, status);
1503*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1504*54925bf6Swillf 
1505*54925bf6Swillf   clean_n_exit:
1506*54925bf6Swillf     return status;
1507*54925bf6Swillf }
1508*54925bf6Swillf 
1509*54925bf6Swillf #define	REALM_SEP_STRING	"@"
1510*54925bf6Swillf 
1511*54925bf6Swillf krb5_error_code
1512*54925bf6Swillf krb5_db_setup_mkey_name(krb5_context context,
1513*54925bf6Swillf 			const char *keyname,
1514*54925bf6Swillf 			const char *realm,
1515*54925bf6Swillf 			char **fullname, krb5_principal * principal)
1516*54925bf6Swillf {
1517*54925bf6Swillf     krb5_error_code retval;
1518*54925bf6Swillf     size_t  keylen;
1519*54925bf6Swillf     size_t  rlen = strlen(realm);
1520*54925bf6Swillf     char   *fname;
1521*54925bf6Swillf 
1522*54925bf6Swillf     if (!keyname)
1523*54925bf6Swillf 	keyname = KRB5_KDB_M_NAME;	/* XXX external? */
1524*54925bf6Swillf 
1525*54925bf6Swillf     keylen = strlen(keyname);
1526*54925bf6Swillf 
1527*54925bf6Swillf     fname = malloc(keylen + rlen + strlen(REALM_SEP_STRING) + 1);
1528*54925bf6Swillf     if (!fname)
1529*54925bf6Swillf 	return ENOMEM;
1530*54925bf6Swillf 
1531*54925bf6Swillf     strcpy(fname, keyname);
1532*54925bf6Swillf     (void)strcat(fname, REALM_SEP_STRING);
1533*54925bf6Swillf     (void)strcat(fname, realm);
1534*54925bf6Swillf 
1535*54925bf6Swillf     if ((retval = krb5_parse_name(context, fname, principal)))
1536*54925bf6Swillf 	return retval;
1537*54925bf6Swillf     if (fullname)
1538*54925bf6Swillf 	*fullname = fname;
1539*54925bf6Swillf     else
1540*54925bf6Swillf 	free(fname);
1541*54925bf6Swillf     return 0;
1542*54925bf6Swillf }
1543*54925bf6Swillf 
1544*54925bf6Swillf krb5_error_code
1545*54925bf6Swillf krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
1546*54925bf6Swillf     krb5_context context;
1547*54925bf6Swillf     krb5_db_entry *entry;
1548*54925bf6Swillf     krb5_timestamp *stamp;
1549*54925bf6Swillf {
1550*54925bf6Swillf     krb5_tl_data tl_data;
1551*54925bf6Swillf     krb5_error_code code;
1552*54925bf6Swillf     krb5_int32 tmp;
1553*54925bf6Swillf 
1554*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
1555*54925bf6Swillf 
1556*54925bf6Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1557*54925bf6Swillf 	return (code);
1558*54925bf6Swillf 
1559*54925bf6Swillf     if (tl_data.tl_data_length != 4) {
1560*54925bf6Swillf 	*stamp = 0;
1561*54925bf6Swillf 	return (0);
1562*54925bf6Swillf     }
1563*54925bf6Swillf 
1564*54925bf6Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
1565*54925bf6Swillf 
1566*54925bf6Swillf     *stamp = (krb5_timestamp) tmp;
1567*54925bf6Swillf 
1568*54925bf6Swillf     return (0);
1569*54925bf6Swillf }
1570*54925bf6Swillf 
1571*54925bf6Swillf /*ARGSUSED*/
1572*54925bf6Swillf krb5_error_code
1573*54925bf6Swillf krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
1574*54925bf6Swillf     krb5_context context;
1575*54925bf6Swillf     krb5_db_entry *entry;
1576*54925bf6Swillf     krb5_tl_data *ret_tl_data;
1577*54925bf6Swillf {
1578*54925bf6Swillf     krb5_tl_data *tl_data;
1579*54925bf6Swillf 
1580*54925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
1581*54925bf6Swillf 	if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
1582*54925bf6Swillf 	    *ret_tl_data = *tl_data;
1583*54925bf6Swillf 	    return (0);
1584*54925bf6Swillf 	}
1585*54925bf6Swillf     }
1586*54925bf6Swillf 
1587*54925bf6Swillf     /* if the requested record isn't found, return zero bytes.
1588*54925bf6Swillf      * if it ever means something to have a zero-length tl_data,
1589*54925bf6Swillf      * this code and its callers will have to be changed */
1590*54925bf6Swillf 
1591*54925bf6Swillf     ret_tl_data->tl_data_length = 0;
1592*54925bf6Swillf     ret_tl_data->tl_data_contents = NULL;
1593*54925bf6Swillf     return (0);
1594*54925bf6Swillf }
1595*54925bf6Swillf 
1596*54925bf6Swillf krb5_error_code
1597*54925bf6Swillf krb5_dbe_create_key_data(context, entry)
1598*54925bf6Swillf     krb5_context context;
1599*54925bf6Swillf     krb5_db_entry *entry;
1600*54925bf6Swillf {
1601*54925bf6Swillf     if ((entry->key_data =
1602*54925bf6Swillf 	 (krb5_key_data *) krb5_db_alloc(context, entry->key_data,
1603*54925bf6Swillf 					 (sizeof(krb5_key_data) *
1604*54925bf6Swillf 					  (entry->n_key_data + 1)))) == NULL)
1605*54925bf6Swillf 	return (ENOMEM);
1606*54925bf6Swillf 
1607*54925bf6Swillf     memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
1608*54925bf6Swillf     entry->n_key_data++;
1609*54925bf6Swillf 
1610*54925bf6Swillf     return 0;
1611*54925bf6Swillf }
1612*54925bf6Swillf 
1613*54925bf6Swillf krb5_error_code
1614*54925bf6Swillf krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
1615*54925bf6Swillf     krb5_context context;
1616*54925bf6Swillf     krb5_db_entry *entry;
1617*54925bf6Swillf     krb5_timestamp mod_date;
1618*54925bf6Swillf     krb5_const_principal mod_princ;
1619*54925bf6Swillf {
1620*54925bf6Swillf     krb5_tl_data tl_data;
1621*54925bf6Swillf 
1622*54925bf6Swillf     krb5_error_code retval = 0;
1623*54925bf6Swillf     krb5_octet *nextloc = 0;
1624*54925bf6Swillf     char   *unparse_mod_princ = 0;
1625*54925bf6Swillf     unsigned int unparse_mod_princ_size;
1626*54925bf6Swillf 
1627*54925bf6Swillf     if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ)))
1628*54925bf6Swillf 	return (retval);
1629*54925bf6Swillf 
1630*54925bf6Swillf     unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
1631*54925bf6Swillf 
1632*54925bf6Swillf     if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
1633*54925bf6Swillf 	== NULL) {
1634*54925bf6Swillf 	free(unparse_mod_princ);
1635*54925bf6Swillf 	return (ENOMEM);
1636*54925bf6Swillf     }
1637*54925bf6Swillf 
1638*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
1639*54925bf6Swillf     tl_data.tl_data_length = unparse_mod_princ_size + 4;
1640*54925bf6Swillf     tl_data.tl_data_contents = nextloc;
1641*54925bf6Swillf 
1642*54925bf6Swillf     /* Mod Date */
1643*54925bf6Swillf     krb5_kdb_encode_int32(mod_date, nextloc);
1644*54925bf6Swillf 
1645*54925bf6Swillf     /* Mod Princ */
1646*54925bf6Swillf     memcpy(nextloc + 4, unparse_mod_princ, unparse_mod_princ_size);
1647*54925bf6Swillf 
1648*54925bf6Swillf     retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
1649*54925bf6Swillf 
1650*54925bf6Swillf     free(unparse_mod_princ);
1651*54925bf6Swillf     free(nextloc);
1652*54925bf6Swillf 
1653*54925bf6Swillf     return (retval);
1654*54925bf6Swillf }
1655*54925bf6Swillf 
1656*54925bf6Swillf krb5_error_code
1657*54925bf6Swillf krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
1658*54925bf6Swillf     krb5_context context;
1659*54925bf6Swillf     krb5_db_entry *entry;
1660*54925bf6Swillf     krb5_timestamp *mod_time;
1661*54925bf6Swillf     krb5_principal *mod_princ;
1662*54925bf6Swillf {
1663*54925bf6Swillf     krb5_tl_data tl_data;
1664*54925bf6Swillf     krb5_error_code code;
1665*54925bf6Swillf 
1666*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
1667*54925bf6Swillf 
1668*54925bf6Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1669*54925bf6Swillf 	return (code);
1670*54925bf6Swillf 
1671*54925bf6Swillf     if ((tl_data.tl_data_length < 5) ||
1672*54925bf6Swillf 	(tl_data.tl_data_contents[tl_data.tl_data_length - 1] != '\0'))
1673*54925bf6Swillf 	return (KRB5_KDB_TRUNCATED_RECORD);
1674*54925bf6Swillf 
1675*54925bf6Swillf     /* Mod Date */
1676*54925bf6Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
1677*54925bf6Swillf 
1678*54925bf6Swillf     /* Mod Princ */
1679*54925bf6Swillf     if ((code = krb5_parse_name(context,
1680*54925bf6Swillf 				(const char *) (tl_data.tl_data_contents + 4),
1681*54925bf6Swillf 				mod_princ)))
1682*54925bf6Swillf 	return (code);
1683*54925bf6Swillf 
1684*54925bf6Swillf     return (0);
1685*54925bf6Swillf }
1686*54925bf6Swillf 
1687*54925bf6Swillf krb5_error_code
1688*54925bf6Swillf krb5_dbe_update_last_pwd_change(context, entry, stamp)
1689*54925bf6Swillf     krb5_context context;
1690*54925bf6Swillf     krb5_db_entry *entry;
1691*54925bf6Swillf     krb5_timestamp stamp;
1692*54925bf6Swillf {
1693*54925bf6Swillf     krb5_tl_data tl_data;
1694*54925bf6Swillf     krb5_octet buf[4];		/* this is the encoded size of an int32 */
1695*54925bf6Swillf 
1696*54925bf6Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
1697*54925bf6Swillf     tl_data.tl_data_length = sizeof(buf);
1698*54925bf6Swillf     krb5_kdb_encode_int32((krb5_int32) stamp, buf);
1699*54925bf6Swillf     tl_data.tl_data_contents = buf;
1700*54925bf6Swillf 
1701*54925bf6Swillf     return (krb5_dbe_update_tl_data(context, entry, &tl_data));
1702*54925bf6Swillf }
1703*54925bf6Swillf 
1704*54925bf6Swillf krb5_error_code
1705*54925bf6Swillf krb5_dbe_update_tl_data(context, entry, new_tl_data)
1706*54925bf6Swillf     krb5_context context;
1707*54925bf6Swillf     krb5_db_entry *entry;
1708*54925bf6Swillf     krb5_tl_data *new_tl_data;
1709*54925bf6Swillf {
1710*54925bf6Swillf     krb5_tl_data *tl_data = NULL;
1711*54925bf6Swillf     krb5_octet *tmp;
1712*54925bf6Swillf 
1713*54925bf6Swillf     /* copy the new data first, so we can fail cleanly if malloc()
1714*54925bf6Swillf      * fails */
1715*54925bf6Swillf     if ((tmp =
1716*54925bf6Swillf 	 (krb5_octet *) krb5_db_alloc(context, NULL,
1717*54925bf6Swillf 				      new_tl_data->tl_data_length)) == NULL)
1718*54925bf6Swillf 	return (ENOMEM);
1719*54925bf6Swillf 
1720*54925bf6Swillf     /* Find an existing entry of the specified type and point at
1721*54925bf6Swillf      * it, or NULL if not found */
1722*54925bf6Swillf 
1723*54925bf6Swillf     if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) {	/* db_args can be multiple */
1724*54925bf6Swillf 	for (tl_data = entry->tl_data; tl_data;
1725*54925bf6Swillf 	     tl_data = tl_data->tl_data_next)
1726*54925bf6Swillf 	    if (tl_data->tl_data_type == new_tl_data->tl_data_type)
1727*54925bf6Swillf 		break;
1728*54925bf6Swillf     }
1729*54925bf6Swillf 
1730*54925bf6Swillf     /* if necessary, chain a new record in the beginning and point at it */
1731*54925bf6Swillf 
1732*54925bf6Swillf     if (!tl_data) {
1733*54925bf6Swillf 	if ((tl_data =
1734*54925bf6Swillf 	     (krb5_tl_data *) krb5_db_alloc(context, NULL,
1735*54925bf6Swillf 					    sizeof(krb5_tl_data)))
1736*54925bf6Swillf 	    == NULL) {
1737*54925bf6Swillf 	    free(tmp);
1738*54925bf6Swillf 	    return (ENOMEM);
1739*54925bf6Swillf 	}
1740*54925bf6Swillf 	memset(tl_data, 0, sizeof(krb5_tl_data));
1741*54925bf6Swillf 	tl_data->tl_data_next = entry->tl_data;
1742*54925bf6Swillf 	entry->tl_data = tl_data;
1743*54925bf6Swillf 	entry->n_tl_data++;
1744*54925bf6Swillf     }
1745*54925bf6Swillf 
1746*54925bf6Swillf     /* fill in the record */
1747*54925bf6Swillf 
1748*54925bf6Swillf     if (tl_data->tl_data_contents)
1749*54925bf6Swillf 	krb5_db_free(context, tl_data->tl_data_contents);
1750*54925bf6Swillf 
1751*54925bf6Swillf     tl_data->tl_data_type = new_tl_data->tl_data_type;
1752*54925bf6Swillf     tl_data->tl_data_length = new_tl_data->tl_data_length;
1753*54925bf6Swillf     tl_data->tl_data_contents = tmp;
1754*54925bf6Swillf     memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
1755*54925bf6Swillf 
1756*54925bf6Swillf     return (0);
1757*54925bf6Swillf }
1758*54925bf6Swillf 
1759*54925bf6Swillf /* change password functions */
1760*54925bf6Swillf krb5_error_code
1761*54925bf6Swillf krb5_dbe_cpw(krb5_context kcontext,
1762*54925bf6Swillf 	     krb5_keyblock * master_key,
1763*54925bf6Swillf 	     krb5_key_salt_tuple * ks_tuple,
1764*54925bf6Swillf 	     int ks_tuple_count,
1765*54925bf6Swillf 	     char *passwd,
1766*54925bf6Swillf 	     int new_kvno, krb5_boolean keepold, krb5_db_entry * db_entry)
1767*54925bf6Swillf {
1768*54925bf6Swillf     krb5_error_code status = 0;
1769*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1770*54925bf6Swillf 
1771*54925bf6Swillf     if (kcontext->db_context == NULL) {
1772*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1773*54925bf6Swillf 	if (status) {
1774*54925bf6Swillf 	    goto clean_n_exit;
1775*54925bf6Swillf 	}
1776*54925bf6Swillf     }
1777*54925bf6Swillf 
1778*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1779*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1780*54925bf6Swillf     if (status) {
1781*54925bf6Swillf 	goto clean_n_exit;
1782*54925bf6Swillf     }
1783*54925bf6Swillf 
1784*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_change_pwd(kcontext,
1785*54925bf6Swillf 							  master_key,
1786*54925bf6Swillf 							  ks_tuple,
1787*54925bf6Swillf 							  ks_tuple_count,
1788*54925bf6Swillf 							  passwd,
1789*54925bf6Swillf 							  new_kvno,
1790*54925bf6Swillf 							  keepold, db_entry);
1791*54925bf6Swillf     get_errmsg(kcontext, status);
1792*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1793*54925bf6Swillf 
1794*54925bf6Swillf   clean_n_exit:
1795*54925bf6Swillf     return status;
1796*54925bf6Swillf }
1797*54925bf6Swillf 
1798*54925bf6Swillf /* policy management functions */
1799*54925bf6Swillf krb5_error_code
1800*54925bf6Swillf krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)
1801*54925bf6Swillf {
1802*54925bf6Swillf     krb5_error_code status = 0;
1803*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1804*54925bf6Swillf 
1805*54925bf6Swillf     if (kcontext->db_context == NULL) {
1806*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1807*54925bf6Swillf 	if (status) {
1808*54925bf6Swillf 	    goto clean_n_exit;
1809*54925bf6Swillf 	}
1810*54925bf6Swillf     }
1811*54925bf6Swillf 
1812*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1813*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1814*54925bf6Swillf     if (status) {
1815*54925bf6Swillf 	goto clean_n_exit;
1816*54925bf6Swillf     }
1817*54925bf6Swillf 
1818*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_create_policy(kcontext, policy);
1819*54925bf6Swillf     get_errmsg(kcontext, status);
1820*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1821*54925bf6Swillf 
1822*54925bf6Swillf   clean_n_exit:
1823*54925bf6Swillf     return status;
1824*54925bf6Swillf }
1825*54925bf6Swillf 
1826*54925bf6Swillf krb5_error_code
1827*54925bf6Swillf krb5_db_get_policy(krb5_context kcontext, char *name,
1828*54925bf6Swillf 		   osa_policy_ent_t * policy, int *cnt)
1829*54925bf6Swillf {
1830*54925bf6Swillf     krb5_error_code status = 0;
1831*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1832*54925bf6Swillf 
1833*54925bf6Swillf     if (kcontext->db_context == NULL) {
1834*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1835*54925bf6Swillf 	if (status) {
1836*54925bf6Swillf 	    goto clean_n_exit;
1837*54925bf6Swillf 	}
1838*54925bf6Swillf     }
1839*54925bf6Swillf 
1840*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1841*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1842*54925bf6Swillf     if (status) {
1843*54925bf6Swillf 	goto clean_n_exit;
1844*54925bf6Swillf     }
1845*54925bf6Swillf 
1846*54925bf6Swillf     status =
1847*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_get_policy(kcontext, name, policy,
1848*54925bf6Swillf 						     cnt);
1849*54925bf6Swillf     get_errmsg(kcontext, status);
1850*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1851*54925bf6Swillf 
1852*54925bf6Swillf   clean_n_exit:
1853*54925bf6Swillf     return status;
1854*54925bf6Swillf }
1855*54925bf6Swillf 
1856*54925bf6Swillf krb5_error_code
1857*54925bf6Swillf krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)
1858*54925bf6Swillf {
1859*54925bf6Swillf     krb5_error_code status = 0;
1860*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1861*54925bf6Swillf 
1862*54925bf6Swillf     if (kcontext->db_context == NULL) {
1863*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1864*54925bf6Swillf 	if (status) {
1865*54925bf6Swillf 	    goto clean_n_exit;
1866*54925bf6Swillf 	}
1867*54925bf6Swillf     }
1868*54925bf6Swillf 
1869*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1870*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1871*54925bf6Swillf     if (status) {
1872*54925bf6Swillf 	goto clean_n_exit;
1873*54925bf6Swillf     }
1874*54925bf6Swillf 
1875*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_put_policy(kcontext, policy);
1876*54925bf6Swillf     get_errmsg(kcontext, status);
1877*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1878*54925bf6Swillf 
1879*54925bf6Swillf   clean_n_exit:
1880*54925bf6Swillf     return status;
1881*54925bf6Swillf }
1882*54925bf6Swillf 
1883*54925bf6Swillf krb5_error_code
1884*54925bf6Swillf krb5_db_iter_policy(krb5_context kcontext, char *match_entry,
1885*54925bf6Swillf 		    osa_adb_iter_policy_func func, void *data)
1886*54925bf6Swillf {
1887*54925bf6Swillf     krb5_error_code status = 0;
1888*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1889*54925bf6Swillf 
1890*54925bf6Swillf     if (kcontext->db_context == NULL) {
1891*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1892*54925bf6Swillf 	if (status) {
1893*54925bf6Swillf 	    goto clean_n_exit;
1894*54925bf6Swillf 	}
1895*54925bf6Swillf     }
1896*54925bf6Swillf 
1897*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1898*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1899*54925bf6Swillf     if (status) {
1900*54925bf6Swillf 	goto clean_n_exit;
1901*54925bf6Swillf     }
1902*54925bf6Swillf 
1903*54925bf6Swillf     status =
1904*54925bf6Swillf 	dal_handle->lib_handle->vftabl.db_iter_policy(kcontext, match_entry,
1905*54925bf6Swillf 						      func, data);
1906*54925bf6Swillf     get_errmsg(kcontext, status);
1907*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1908*54925bf6Swillf 
1909*54925bf6Swillf   clean_n_exit:
1910*54925bf6Swillf     return status;
1911*54925bf6Swillf }
1912*54925bf6Swillf 
1913*54925bf6Swillf krb5_error_code
1914*54925bf6Swillf krb5_db_delete_policy(krb5_context kcontext, char *policy)
1915*54925bf6Swillf {
1916*54925bf6Swillf     krb5_error_code status = 0;
1917*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1918*54925bf6Swillf 
1919*54925bf6Swillf     if (kcontext->db_context == NULL) {
1920*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1921*54925bf6Swillf 	if (status) {
1922*54925bf6Swillf 	    goto clean_n_exit;
1923*54925bf6Swillf 	}
1924*54925bf6Swillf     }
1925*54925bf6Swillf 
1926*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1927*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1928*54925bf6Swillf     if (status) {
1929*54925bf6Swillf 	goto clean_n_exit;
1930*54925bf6Swillf     }
1931*54925bf6Swillf 
1932*54925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_delete_policy(kcontext, policy);
1933*54925bf6Swillf     get_errmsg(kcontext, status);
1934*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1935*54925bf6Swillf 
1936*54925bf6Swillf   clean_n_exit:
1937*54925bf6Swillf     return status;
1938*54925bf6Swillf }
1939*54925bf6Swillf 
1940*54925bf6Swillf void
1941*54925bf6Swillf krb5_db_free_policy(krb5_context kcontext, osa_policy_ent_t policy)
1942*54925bf6Swillf {
1943*54925bf6Swillf     krb5_error_code status = 0;
1944*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1945*54925bf6Swillf 
1946*54925bf6Swillf     if (kcontext->db_context == NULL) {
1947*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1948*54925bf6Swillf 	if (status) {
1949*54925bf6Swillf 	    goto clean_n_exit;
1950*54925bf6Swillf 	}
1951*54925bf6Swillf     }
1952*54925bf6Swillf 
1953*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1954*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1955*54925bf6Swillf     if (status) {
1956*54925bf6Swillf 	goto clean_n_exit;
1957*54925bf6Swillf     }
1958*54925bf6Swillf 
1959*54925bf6Swillf     dal_handle->lib_handle->vftabl.db_free_policy(kcontext, policy);
1960*54925bf6Swillf     get_errmsg(kcontext, status);
1961*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1962*54925bf6Swillf 
1963*54925bf6Swillf   clean_n_exit:
1964*54925bf6Swillf     return;
1965*54925bf6Swillf }
1966*54925bf6Swillf 
1967*54925bf6Swillf krb5_error_code
1968*54925bf6Swillf krb5_db_promote(krb5_context kcontext, char **db_args)
1969*54925bf6Swillf {
1970*54925bf6Swillf     krb5_error_code status = 0;
1971*54925bf6Swillf     char   *section = NULL;
1972*54925bf6Swillf     kdb5_dal_handle *dal_handle;
1973*54925bf6Swillf 
1974*54925bf6Swillf     section = kdb_get_conf_section(kcontext);
1975*54925bf6Swillf     if (section == NULL) {
1976*54925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
1977*54925bf6Swillf 	krb5_set_error_message (kcontext, status,
1978*54925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
1979*54925bf6Swillf 		kcontext->default_realm);
1980*54925bf6Swillf 	goto clean_n_exit;
1981*54925bf6Swillf     }
1982*54925bf6Swillf 
1983*54925bf6Swillf     if (kcontext->db_context == NULL) {
1984*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
1985*54925bf6Swillf 	if (status) {
1986*54925bf6Swillf 	    goto clean_n_exit;
1987*54925bf6Swillf 	}
1988*54925bf6Swillf     }
1989*54925bf6Swillf 
1990*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1991*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1992*54925bf6Swillf     if (status) {
1993*54925bf6Swillf 	goto clean_n_exit;
1994*54925bf6Swillf     }
1995*54925bf6Swillf 
1996*54925bf6Swillf     status =
1997*54925bf6Swillf 	dal_handle->lib_handle->vftabl.promote_db(kcontext, section, db_args);
1998*54925bf6Swillf     get_errmsg(kcontext, status);
1999*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
2000*54925bf6Swillf 
2001*54925bf6Swillf   clean_n_exit:
2002*54925bf6Swillf     if (section)
2003*54925bf6Swillf 	free(section);
2004*54925bf6Swillf     return status;
2005*54925bf6Swillf }
2006*54925bf6Swillf 
2007*54925bf6Swillf /*
2008*54925bf6Swillf  * Solaris Kerberos: support for iprop
2009*54925bf6Swillf  *
2010*54925bf6Swillf  * Not all KDB plugins support iprop.
2011*54925bf6Swillf  *
2012*54925bf6Swillf  * sets iprop_supported to 1 if iprop supportd, 0 otherwise.
2013*54925bf6Swillf  */
2014*54925bf6Swillf krb5_error_code
2015*54925bf6Swillf krb5_db_supports_iprop(krb5_context kcontext, int *iprop_supported)
2016*54925bf6Swillf {
2017*54925bf6Swillf     krb5_error_code status = 0;
2018*54925bf6Swillf     kdb5_dal_handle *dal_handle;
2019*54925bf6Swillf 
2020*54925bf6Swillf     if (kcontext->db_context == NULL) {
2021*54925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
2022*54925bf6Swillf 	if (status) {
2023*54925bf6Swillf 	    goto clean_n_exit;
2024*54925bf6Swillf 	}
2025*54925bf6Swillf     }
2026*54925bf6Swillf 
2027*54925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
2028*54925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
2029*54925bf6Swillf     if (status) {
2030*54925bf6Swillf 	goto clean_n_exit;
2031*54925bf6Swillf     }
2032*54925bf6Swillf 
2033*54925bf6Swillf     *iprop_supported = dal_handle->lib_handle->vftabl.iprop_supported;
2034*54925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
2035*54925bf6Swillf 
2036*54925bf6Swillf   clean_n_exit:
2037*54925bf6Swillf     return status;
2038*54925bf6Swillf }
2039