xref: /onnv-gate/usr/src/lib/krb5/kdb/kdb5.c (revision 6426:a88591926d3d)
14960Swillf /*
25916Swillf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
34960Swillf  * Use is subject to license terms.
44960Swillf  */
54960Swillf 
64960Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
74960Swillf /*
84960Swillf  * Copyright 2006 by the Massachusetts Institute of Technology.
94960Swillf  * All Rights Reserved.
104960Swillf  *
114960Swillf  * Export of this software from the United States of America may
124960Swillf  *   require a specific license from the United States Government.
134960Swillf  *   It is the responsibility of any person or organization contemplating
144960Swillf  *   export to obtain such a license before exporting.
154960Swillf  *
164960Swillf  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
174960Swillf  * distribute this software and its documentation for any purpose and
184960Swillf  * without fee is hereby granted, provided that the above copyright
194960Swillf  * notice appear in all copies and that both that copyright notice and
204960Swillf  * this permission notice appear in supporting documentation, and that
214960Swillf  * the name of M.I.T. not be used in advertising or publicity pertaining
224960Swillf  * to distribution of the software without specific, written prior
234960Swillf  * permission.  Furthermore if you modify this software you must label
244960Swillf  * your software as modified software and not distribute it in such a
254960Swillf  * fashion that it might be confused with the original M.I.T. software.
264960Swillf  * M.I.T. makes no representations about the suitability of
274960Swillf  * this software for any purpose.  It is provided "as is" without express
284960Swillf  * or implied warranty.
294960Swillf  */
304960Swillf 
314960Swillf /*
324960Swillf  * This code was based on code donated to MIT by Novell for
334960Swillf  * distribution under the MIT license.
344960Swillf  */
354960Swillf 
364960Swillf /*
374960Swillf  * Include files
384960Swillf  */
394960Swillf 
404960Swillf #include <stdio.h>
414960Swillf #include <string.h>
424960Swillf #include <k5-int.h>
434960Swillf #include <osconf.h>
444960Swillf #include "kdb5.h"
454960Swillf #include <assert.h>
464960Swillf #include "k5-platform.h"
474960Swillf #include <libintl.h>
484960Swillf 
494960Swillf /* Currently DB2 policy related errors are exported from DAL.  But
504960Swillf    other databases should set_err function to return string.  */
514960Swillf #include "adb_err.h"
524960Swillf 
534960Swillf /*
544960Swillf  * Type definitions
554960Swillf  */
564960Swillf #define KRB5_TL_DB_ARGS                 0x7fff
574960Swillf 
584960Swillf /*
594960Swillf  * internal static variable
604960Swillf  */
614960Swillf 
624960Swillf static k5_mutex_t db_lock = K5_MUTEX_PARTIAL_INITIALIZER;
634960Swillf 
644960Swillf #ifdef _KDB5_STATIC_LINK
654960Swillf #undef _KDB5_DYNAMIC_LINK
664960Swillf #else
674960Swillf #undef _KDB5_DYNAMIC_LINK
684960Swillf /* to avoid redefinition problem */
694960Swillf #define _KDB5_DYNAMIC_LINK
704960Swillf #endif
714960Swillf 
724960Swillf static db_library lib_list;
734960Swillf 
744960Swillf /*
754960Swillf  * Helper Functions
764960Swillf  */
774960Swillf 
784960Swillf MAKE_INIT_FUNCTION(kdb_init_lock_list);
794960Swillf MAKE_FINI_FUNCTION(kdb_fini_lock_list);
804960Swillf 
814960Swillf int
kdb_init_lock_list(void)824960Swillf kdb_init_lock_list(void)
834960Swillf {
844960Swillf     return k5_mutex_finish_init(&db_lock);
854960Swillf }
864960Swillf 
874960Swillf static int
kdb_lock_list()884960Swillf kdb_lock_list()
894960Swillf {
904960Swillf     int err;
914960Swillf     err = CALL_INIT_FUNCTION (kdb_init_lock_list);
924960Swillf     if (err)
934960Swillf 	return err;
944960Swillf     return k5_mutex_lock(&db_lock);
954960Swillf }
964960Swillf 
974960Swillf void
kdb_fini_lock_list(void)984960Swillf kdb_fini_lock_list(void)
994960Swillf {
1004960Swillf     if (INITIALIZER_RAN(kdb_init_lock_list))
1014960Swillf 	k5_mutex_destroy(&db_lock);
1024960Swillf }
1034960Swillf 
1044960Swillf static int
kdb_unlock_list()1054960Swillf kdb_unlock_list()
1064960Swillf {
1074960Swillf     return k5_mutex_unlock(&db_lock);
1084960Swillf }
1094960Swillf 
1104960Swillf #define kdb_init_lib_lock(a) 0
1114960Swillf #define kdb_destroy_lib_lock(a) (void)0
1124960Swillf #define kdb_lock_lib_lock(a, b) 0
1134960Swillf #define kdb_unlock_lib_lock(a, b) (void)0
1144960Swillf 
1154960Swillf /* Caller must free result*/
1164960Swillf 
1174960Swillf static char *
kdb_get_conf_section(krb5_context kcontext)1184960Swillf kdb_get_conf_section(krb5_context kcontext)
1194960Swillf {
1204960Swillf     krb5_error_code status = 0;
1214960Swillf     char   *result = NULL;
1224960Swillf     char   *value = NULL;
1234960Swillf 
1244960Swillf     if (kcontext->default_realm == NULL)
1254960Swillf 	return NULL;
1264960Swillf     /* The profile has to have been initialized.  If the profile was
1274960Swillf        not initialized, expect nothing less than a crash.  */
1284960Swillf     status = profile_get_string(kcontext->profile,
1294960Swillf 				/* realms */
1304960Swillf 				KDB_REALM_SECTION,
1314960Swillf 				kcontext->default_realm,
1324960Swillf 				/* under the realm name, database_module */
1334960Swillf 				KDB_MODULE_POINTER,
1344960Swillf 				/* default value is the realm name itself */
1354960Swillf 				kcontext->default_realm,
1364960Swillf 				&value);
1374960Swillf 
1384960Swillf     if (status) {
1394960Swillf 	/* some problem */
1404960Swillf 	result = strdup(kcontext->default_realm);
1414960Swillf 	/* let NULL be handled by the caller */
1424960Swillf     } else {
1434960Swillf 	result = strdup(value);
1444960Swillf 	/* free profile string */
1454960Swillf 	profile_release_string(value);
1464960Swillf     }
1474960Swillf 
1484960Swillf     return result;
1494960Swillf }
1504960Swillf 
1514960Swillf static char *
kdb_get_library_name(krb5_context kcontext)1524960Swillf kdb_get_library_name(krb5_context kcontext)
1534960Swillf {
1544960Swillf     krb5_error_code status = 0;
1554960Swillf     char   *result = NULL;
1564960Swillf     char   *value = NULL;
1574960Swillf     char   *lib = NULL;
1584960Swillf 
1594960Swillf     status = profile_get_string(kcontext->profile,
1604960Swillf 				/* realms */
1614960Swillf 				KDB_REALM_SECTION,
1624960Swillf 				kcontext->default_realm,
1634960Swillf 				/* under the realm name, database_module */
1644960Swillf 				KDB_MODULE_POINTER,
1654960Swillf 				/* default value is the realm name itself */
1664960Swillf 				kcontext->default_realm,
1674960Swillf 				&value);
1684960Swillf     if (status) {
1694960Swillf 	goto clean_n_exit;
1704960Swillf     }
1714960Swillf 
1724960Swillf #define DB2_NAME "db2"
1734960Swillf     /* we got the module section. Get the library name from the module */
1744960Swillf     status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value,
1754960Swillf 				KDB_LIB_POINTER,
1764960Swillf 				/* default to db2 */
1774960Swillf 				DB2_NAME,
1784960Swillf 				&lib);
1794960Swillf 
1804960Swillf     if (status) {
1814960Swillf 	goto clean_n_exit;
1824960Swillf     }
1834960Swillf 
1844960Swillf     result = strdup(lib);
1854960Swillf   clean_n_exit:
1864960Swillf     if (value) {
1874960Swillf 	/* free profile string */
1884960Swillf 	profile_release_string(value);
1894960Swillf     }
1904960Swillf 
1914960Swillf     if (lib) {
1924960Swillf 	/* free profile string */
1934960Swillf 	profile_release_string(lib);
1944960Swillf     }
1954960Swillf     return result;
1964960Swillf }
1974960Swillf 
1984960Swillf static void
kdb_setup_opt_functions(db_library lib)1994960Swillf kdb_setup_opt_functions(db_library lib)
2004960Swillf {
2014960Swillf     if (lib->vftabl.set_master_key == NULL) {
2024960Swillf 	lib->vftabl.set_master_key = kdb_def_set_mkey;
2034960Swillf     }
2044960Swillf 
2054960Swillf     if (lib->vftabl.get_master_key == NULL) {
2064960Swillf 	lib->vftabl.get_master_key = kdb_def_get_mkey;
2074960Swillf     }
2084960Swillf 
2094960Swillf     if (lib->vftabl.fetch_master_key == NULL) {
2104960Swillf 	lib->vftabl.fetch_master_key = krb5_db_def_fetch_mkey;
2114960Swillf     }
2124960Swillf 
2134960Swillf     if (lib->vftabl.verify_master_key == NULL) {
2144960Swillf 	lib->vftabl.verify_master_key = krb5_def_verify_master_key;
2154960Swillf     }
2164960Swillf 
2174960Swillf     if (lib->vftabl.dbe_search_enctype == NULL) {
2184960Swillf 	lib->vftabl.dbe_search_enctype = krb5_dbe_def_search_enctype;
2194960Swillf     }
2204960Swillf 
2214960Swillf     if (lib->vftabl.db_change_pwd == NULL) {
2224960Swillf 	lib->vftabl.db_change_pwd = krb5_dbe_def_cpw;
2234960Swillf     }
2244960Swillf 
2254960Swillf     if (lib->vftabl.store_master_key == NULL) {
2264960Swillf 	lib->vftabl.store_master_key = krb5_def_store_mkey;
2274960Swillf     }
2284960Swillf 
2294960Swillf     if (lib->vftabl.promote_db == NULL) {
2304960Swillf 	lib->vftabl.promote_db = krb5_def_promote_db;
2314960Swillf     }
2324960Swillf }
2334960Swillf 
2344960Swillf static int kdb_db2_pol_err_loaded = 0;
2354960Swillf #ifdef _KDB5_STATIC_LINK
2364960Swillf #define DEF_SYMBOL(a) extern kdb_vftabl krb5_db_vftabl_ ## a
2374960Swillf #define GET_SYMBOL(a) (krb5_db_vftabl_ ## a)
2384960Swillf static krb5_error_code
kdb_load_library(krb5_context kcontext,char * lib_name,db_library * lib)2394960Swillf kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
2404960Swillf {
2414960Swillf     krb5_error_code status;
2424960Swillf     void   *vftabl_addr = NULL;
2434960Swillf     char    buf[KRB5_MAX_ERR_STR];
2444960Swillf 
2454960Swillf     if (!strcmp("kdb_db2", lib_name) && (kdb_db2_pol_err_loaded == 0)) {
2464960Swillf 	initialize_adb_error_table();
2474960Swillf 	kdb_db2_pol_err_loaded = 1;
2484960Swillf     }
2494960Swillf 
2504960Swillf     *lib = calloc((size_t) 1, sizeof(**lib));
2514960Swillf     if (*lib == NULL) {
2524960Swillf 	status = ENOMEM;
2534960Swillf 	goto clean_n_exit;
2544960Swillf     }
2554960Swillf 
2564960Swillf     status = kdb_init_lib_lock(*lib);
2574960Swillf     if (status) {
2584960Swillf 	goto clean_n_exit;
2594960Swillf     }
2604960Swillf 
2614960Swillf     strcpy((*lib)->name, lib_name);
2624960Swillf 
2634960Swillf #if !defined(KDB5_USE_LIB_KDB_DB2) && !defined(KDB5_USE_LIB_TEST)
2644960Swillf #error No database module defined
2654960Swillf #endif
2664960Swillf 
2674960Swillf #ifdef KDB5_USE_LIB_KDB_DB2
2684960Swillf     if (strcmp(lib_name, "kdb_db2") == 0) {
2694960Swillf 	DEF_SYMBOL(kdb_db2);
2704960Swillf 	vftabl_addr = (void *) &GET_SYMBOL(kdb_db2);
2714960Swillf     } else
2724960Swillf #endif
2734960Swillf #ifdef KDB5_USE_LIB_TEST
2744960Swillf     if (strcmp(lib_name, "test") == 0) {
2754960Swillf 	DEF_SYMBOL(test);
2764960Swillf 	vftabl_addr = (void *) &GET_SYMBOL(test);
2774960Swillf     } else
2784960Swillf #endif
2794960Swillf     {
2804960Swillf 	snprintf(buf, sizeof(buf), gettext("Program not built to support %s database type\n"),
2814960Swillf 		lib_name);
2824960Swillf 	status = KRB5_KDB_DBTYPE_NOSUP;
2834960Swillf 	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
2844960Swillf 	goto clean_n_exit;
2854960Swillf     }
2864960Swillf 
2874960Swillf     memcpy(&(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
2884960Swillf 
2894960Swillf     kdb_setup_opt_functions(*lib);
2904960Swillf 
2914960Swillf     if ((status = (*lib)->vftabl.init_library())) {
2924960Swillf 	/* ERROR. library not initialized cleanly */
2934960Swillf 	snprintf(buf, sizeof(buf), gettext("%s library initialization failed, error code %ld\n"),
2944960Swillf 		lib_name, status);
2954960Swillf 	status = KRB5_KDB_DBTYPE_INIT;
2964960Swillf 	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
2974960Swillf 	goto clean_n_exit;
2984960Swillf     }
2994960Swillf 
3004960Swillf   clean_n_exit:
3014960Swillf     if (status) {
3024960Swillf 	free(*lib), *lib = NULL;
3034960Swillf     }
3044960Swillf     return status;
3054960Swillf }
3064960Swillf 
3074960Swillf #else /* KDB5_STATIC_LINK*/
3084960Swillf 
3094960Swillf static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH;
3104960Swillf #define db_dl_n_locations (sizeof(db_dl_location) / sizeof(db_dl_location[0]))
3114960Swillf 
3124960Swillf static krb5_error_code
kdb_load_library(krb5_context kcontext,char * lib_name,db_library * lib)3134960Swillf kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
3144960Swillf {
3154960Swillf     krb5_error_code status = 0;
3164960Swillf     int     ndx;
3174960Swillf     void  **vftabl_addrs = NULL;
3184960Swillf     /* N.B.: If this is "const" but not "static", the Solaris 10
3194960Swillf        native compiler has trouble building the library because of
3204960Swillf        absolute relocations needed in read-only section ".rodata".
3214960Swillf        When it's static, it goes into ".picdata", which is
3224960Swillf        read-write.  */
3234960Swillf     static const char *const dbpath_names[] = {
3244960Swillf 	KDB_MODULE_SECTION, "db_module_dir", NULL,
3254960Swillf     };
3264960Swillf     const char *filebases[2];
3274960Swillf     char **profpath = NULL;
3284960Swillf     char **path = NULL;
3294960Swillf 
3304960Swillf     filebases[0] = lib_name;
3314960Swillf     filebases[1] = NULL;
3324960Swillf 
3334960Swillf     if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
3344960Swillf 	initialize_adb_error_table();
3354960Swillf 	kdb_db2_pol_err_loaded = 1;
3364960Swillf     }
3374960Swillf 
3384960Swillf     *lib = calloc((size_t) 1, sizeof(**lib));
3394960Swillf     if (*lib == NULL) {
3404960Swillf 	status = ENOMEM;
3414960Swillf 	goto clean_n_exit;
3424960Swillf     }
3434960Swillf 
3444960Swillf     status = kdb_init_lib_lock(*lib);
3454960Swillf     if (status) {
3464960Swillf 	goto clean_n_exit;
3474960Swillf     }
3484960Swillf 
3494960Swillf     strcpy((*lib)->name, lib_name);
3504960Swillf 
3514960Swillf     /* Fetch the list of directories specified in the config
3524960Swillf        file(s) first.  */
3534960Swillf     status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
3544960Swillf     if (status != 0 && status != PROF_NO_RELATION)
3554960Swillf 	goto clean_n_exit;
3564960Swillf     ndx = 0;
3574960Swillf     if (profpath)
3584960Swillf 	while (profpath[ndx] != NULL)
3594960Swillf 	    ndx++;
3604960Swillf 
3614960Swillf     path = calloc(ndx + db_dl_n_locations, sizeof (char *));
3624960Swillf     if (path == NULL) {
3634960Swillf 	status = errno;
3644960Swillf 	goto clean_n_exit;
3654960Swillf     }
3664960Swillf     if (ndx)
3674960Swillf 	memcpy(path, profpath, ndx * sizeof(profpath[0]));
3684960Swillf     memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
3694960Swillf     status = 0;
3704960Swillf 
3714960Swillf     if ((status = krb5int_open_plugin_dirs ((const char **) path,
3724960Swillf                                             filebases,
3734960Swillf                                             &(*lib)->dl_dir_handle, &kcontext->err))) {
3744960Swillf         const char *err_str = krb5_get_error_message(kcontext, status);
3754960Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
3764960Swillf 	krb5_set_error_message (kcontext, status,
3774960Swillf 				gettext("Unable to find requested database type: %s"), err_str);
3784960Swillf 	krb5_free_error_message (kcontext, err_str);
3794960Swillf 	goto clean_n_exit;
3804960Swillf     }
3814960Swillf 
3824960Swillf     if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
3834960Swillf                                                &vftabl_addrs, &kcontext->err))) {
3844960Swillf         const char *err_str = krb5_get_error_message(kcontext, status);
3854960Swillf         status = KRB5_KDB_DBTYPE_INIT;
3864960Swillf         krb5_set_error_message (kcontext, status,
3874960Swillf                                 gettext("plugin symbol 'kdb_function_table' lookup failed: %s"), err_str);
3884960Swillf         krb5_free_error_message (kcontext, err_str);
3894960Swillf 	goto clean_n_exit;
3904960Swillf     }
3914960Swillf 
3924960Swillf     if (vftabl_addrs[0] == NULL) {
3934960Swillf 	/* No plugins! */
3944960Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
3954960Swillf 	krb5_set_error_message (kcontext, status,
3964960Swillf 				gettext("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"),
3974960Swillf 				lib_name);
3984960Swillf 	goto clean_n_exit;
3994960Swillf     }
4004960Swillf 
4014960Swillf     memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl));
4024960Swillf     kdb_setup_opt_functions(*lib);
4034960Swillf 
4044960Swillf     if ((status = (*lib)->vftabl.init_library())) {
4054960Swillf         /* ERROR. library not initialized cleanly */
4064960Swillf         goto clean_n_exit;
4074960Swillf     }
4084960Swillf 
4094960Swillf clean_n_exit:
4104960Swillf     if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); }
4114960Swillf     /* Both of these DTRT with NULL.  */
4124960Swillf     profile_free_list(profpath);
4134960Swillf     free(path);
4144960Swillf     if (status) {
4154960Swillf         if (*lib) {
4164960Swillf 	    kdb_destroy_lib_lock(*lib);
4174960Swillf             if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
4184960Swillf                 krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
4194960Swillf             }
4204960Swillf 	    free(*lib);
4214960Swillf 	    *lib = NULL;
4224960Swillf 	}
4234960Swillf     }
4244960Swillf     return status;
4254960Swillf }
4264960Swillf 
4274960Swillf #endif /* end of _KDB5_STATIC_LINK */
4284960Swillf 
4294960Swillf static krb5_error_code
kdb_find_library(krb5_context kcontext,char * lib_name,db_library * lib)4304960Swillf kdb_find_library(krb5_context kcontext, char *lib_name, db_library * lib)
4314960Swillf {
4324960Swillf     /* lock here so that no two threads try to do the same at the same time */
4334960Swillf     krb5_error_code status = 0;
4344960Swillf     int     locked = 0;
4354960Swillf     db_library curr_elt, prev_elt = NULL;
4364960Swillf 
4374960Swillf     if ((status = kdb_lock_list()) != 0) {
4384960Swillf 	goto clean_n_exit;
4394960Swillf     }
4404960Swillf     locked = 1;
4414960Swillf 
4424960Swillf     curr_elt = lib_list;
4434960Swillf     while (curr_elt != NULL) {
4444960Swillf 	if (strcmp(lib_name, curr_elt->name) == 0) {
4454960Swillf 	    *lib = curr_elt;
4464960Swillf 	    goto clean_n_exit;
4474960Swillf 	}
4484960Swillf 	prev_elt = curr_elt;
4494960Swillf 	curr_elt = curr_elt->next;
4504960Swillf     }
4514960Swillf 
4524960Swillf     /* module not found. create and add to list */
4534960Swillf     status = kdb_load_library(kcontext, lib_name, lib);
4544960Swillf     if (status) {
4554960Swillf 	goto clean_n_exit;
4564960Swillf     }
4574960Swillf 
4584960Swillf     if (prev_elt) {
4594960Swillf 	/* prev_elt points to the last element in the list */
4604960Swillf 	prev_elt->next = *lib;
4614960Swillf 	(*lib)->prev = prev_elt;
4624960Swillf     } else {
4634960Swillf 	lib_list = *lib;
4644960Swillf     }
4654960Swillf 
4664960Swillf   clean_n_exit:
4674960Swillf     if (*lib) {
4684960Swillf 	(*lib)->reference_cnt++;
4694960Swillf     }
4704960Swillf 
4714960Swillf     if (locked) {
4724960Swillf 	(void)kdb_unlock_list();
4734960Swillf     }
4744960Swillf 
4754960Swillf     return status;
4764960Swillf }
4774960Swillf 
4784960Swillf static krb5_error_code
kdb_free_library(db_library lib)4794960Swillf kdb_free_library(db_library lib)
4804960Swillf {
4814960Swillf     krb5_error_code status = 0;
4824960Swillf     int     locked = 0;
4834960Swillf 
4844960Swillf     if ((status = kdb_lock_list()) != 0) {
4854960Swillf 	goto clean_n_exit;
4864960Swillf     }
4874960Swillf     locked = 1;
4884960Swillf 
4894960Swillf     lib->reference_cnt--;
4904960Swillf 
4914960Swillf     if (lib->reference_cnt == 0) {
4924960Swillf 	status = lib->vftabl.fini_library();
4934960Swillf 	if (status) {
4944960Swillf 	    goto clean_n_exit;
4954960Swillf 	}
4964960Swillf 
4974960Swillf 	/* close the library */
4984960Swillf         if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle))) {
4994960Swillf             krb5int_close_plugin_dirs (&lib->dl_dir_handle);
5004960Swillf         }
5014960Swillf 
5024960Swillf 	kdb_destroy_lib_lock(lib);
5034960Swillf 
5044960Swillf 	if (lib->prev == NULL) {
5054960Swillf 	    /* first element in the list */
5064960Swillf 	    lib_list = lib->next;
5074960Swillf 	} else {
5084960Swillf 	    lib->prev->next = lib->next;
5094960Swillf 	}
5104960Swillf 
5114960Swillf 	if (lib->next) {
5124960Swillf 	    lib->next->prev = lib->prev;
5134960Swillf 	}
5144960Swillf 	free(lib);
5154960Swillf     }
5164960Swillf 
5174960Swillf   clean_n_exit:
5184960Swillf     if (locked) {
5194960Swillf 	(void)kdb_unlock_list();
5204960Swillf     }
5214960Swillf 
5224960Swillf     return status;
5234960Swillf }
5244960Swillf 
5254960Swillf static krb5_error_code
kdb_setup_lib_handle(krb5_context kcontext)5264960Swillf kdb_setup_lib_handle(krb5_context kcontext)
5274960Swillf {
5284960Swillf     char   *library = NULL;
5294960Swillf     krb5_error_code status = 0;
5304960Swillf     db_library lib = NULL;
5314960Swillf     kdb5_dal_handle *dal_handle = NULL;
5324960Swillf 
5334960Swillf     dal_handle = calloc((size_t) 1, sizeof(kdb5_dal_handle));
5344960Swillf     if (dal_handle == NULL) {
5354960Swillf 	status = ENOMEM;
5364960Swillf 	goto clean_n_exit;
5374960Swillf     }
5384960Swillf 
5394960Swillf     library = kdb_get_library_name(kcontext);
5404960Swillf     if (library == NULL) {
5414960Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
5424960Swillf 	goto clean_n_exit;
5434960Swillf     }
5444960Swillf 
5454960Swillf     status = kdb_find_library(kcontext, library, &lib);
5464960Swillf     if (status) {
5474960Swillf 	goto clean_n_exit;
5484960Swillf     }
5494960Swillf 
5504960Swillf     dal_handle->lib_handle = lib;
5514960Swillf     kcontext->db_context = (void *) dal_handle;
5524960Swillf 
5534960Swillf   clean_n_exit:
5544960Swillf     free(library);
5554960Swillf 
5564960Swillf     if (status) {
5574960Swillf 	free(dal_handle);
5584960Swillf 	if (lib) {
5594960Swillf 	    (void)kdb_free_library(lib);
5604960Swillf 	}
5614960Swillf     }
5624960Swillf 
5634960Swillf     return status;
5644960Swillf }
5654960Swillf 
5664960Swillf static krb5_error_code
kdb_free_lib_handle(krb5_context kcontext)5674960Swillf kdb_free_lib_handle(krb5_context kcontext)
5684960Swillf {
5694960Swillf     krb5_error_code status = 0;
5704960Swillf 
5714960Swillf     status =
5724960Swillf 	kdb_free_library(((kdb5_dal_handle *) kcontext->db_context)->
5734960Swillf 			 lib_handle);
5744960Swillf     if (status) {
5754960Swillf 	goto clean_n_exit;
5764960Swillf     }
5774960Swillf 
5784960Swillf     free(kcontext->db_context);
5794960Swillf     kcontext->db_context = NULL;
5804960Swillf 
5814960Swillf   clean_n_exit:
5824960Swillf     return status;
5834960Swillf }
5844960Swillf 
5854960Swillf static void
get_errmsg(krb5_context kcontext,krb5_error_code err_code)5864960Swillf get_errmsg (krb5_context kcontext, krb5_error_code err_code)
5874960Swillf {
5884960Swillf     kdb5_dal_handle *dal_handle;
5894960Swillf     const char *e;
5904960Swillf     if (err_code == 0)
5914960Swillf 	return;
5924960Swillf     assert(kcontext != NULL);
5934960Swillf     /* Must be called with dal_handle->lib_handle locked!  */
5944960Swillf     assert(kcontext->db_context != NULL);
5954960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
5964960Swillf     if (dal_handle->lib_handle->vftabl.errcode_2_string == NULL)
5974960Swillf 	return;
5984960Swillf     e = dal_handle->lib_handle->vftabl.errcode_2_string(kcontext, err_code);
5994960Swillf     assert (e != NULL);
6004960Swillf     krb5_set_error_message(kcontext, err_code, "%s", e);
6014960Swillf     if (dal_handle->lib_handle->vftabl.release_errcode_string)
6024960Swillf 	dal_handle->lib_handle->vftabl.release_errcode_string(kcontext, e);
6034960Swillf }
6044960Swillf 
6054960Swillf /*
6064960Swillf  *      External functions... DAL API
6074960Swillf  */
6084960Swillf krb5_error_code
krb5_db_open(krb5_context kcontext,char ** db_args,int mode)6094960Swillf krb5_db_open(krb5_context kcontext, char **db_args, int mode)
6104960Swillf {
6114960Swillf     krb5_error_code status = 0;
6124960Swillf     char   *section = NULL;
6134960Swillf     kdb5_dal_handle *dal_handle;
6144960Swillf 
6154960Swillf     section = kdb_get_conf_section(kcontext);
6164960Swillf     if (section == NULL) {
6174960Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
6184960Swillf 	krb5_set_error_message (kcontext, status,
6194960Swillf 		gettext("unable to determine configuration section for realm %s\n"),
6204960Swillf 		kcontext->default_realm ? kcontext->default_realm : "[UNSET]");
6214960Swillf 	goto clean_n_exit;
6224960Swillf     }
6234960Swillf 
6244960Swillf     if (kcontext->db_context == NULL) {
6254960Swillf 	status = kdb_setup_lib_handle(kcontext);
6264960Swillf 	if (status) {
6274960Swillf 	    goto clean_n_exit;
6284960Swillf 	}
6294960Swillf     }
6304960Swillf 
6314960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
6324960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
6334960Swillf     if (status) {
634*6426Smp153739 	/* Solaris Kerberos */
635*6426Smp153739 	kdb_free_lib_handle(kcontext);
6364960Swillf 	goto clean_n_exit;
6374960Swillf     }
6384960Swillf 
6394960Swillf     status =
6404960Swillf 	dal_handle->lib_handle->vftabl.init_module(kcontext, section, db_args,
6414960Swillf 						   mode);
6424960Swillf     get_errmsg(kcontext, status);
6434960Swillf 
6444960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
6454960Swillf 
646*6426Smp153739     /* Solaris Kerberos */
647*6426Smp153739     if (status)
648*6426Smp153739 	kdb_free_lib_handle(kcontext);
649*6426Smp153739 
6504960Swillf   clean_n_exit:
6514960Swillf     if (section)
6524960Swillf 	free(section);
6534960Swillf     return status;
6544960Swillf }
6554960Swillf 
6564960Swillf krb5_error_code
krb5_db_inited(krb5_context kcontext)6574960Swillf krb5_db_inited(krb5_context kcontext)
6584960Swillf {
6594960Swillf     return !(kcontext && kcontext->db_context &&
6604960Swillf 	     ((kdb5_dal_handle *) kcontext->db_context)->db_context);
6614960Swillf }
6624960Swillf 
6634960Swillf krb5_error_code
krb5_db_create(krb5_context kcontext,char ** db_args)6644960Swillf krb5_db_create(krb5_context kcontext, char **db_args)
6654960Swillf {
6664960Swillf     krb5_error_code status = 0;
6674960Swillf     char   *section = NULL;
6684960Swillf     kdb5_dal_handle *dal_handle;
6694960Swillf 
6704960Swillf     section = kdb_get_conf_section(kcontext);
6714960Swillf     if (section == NULL) {
6724960Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
6734960Swillf 	krb5_set_error_message (kcontext, status,
6744960Swillf 		gettext("unable to determine configuration section for realm %s\n"),
6754960Swillf 		kcontext->default_realm);
6764960Swillf 	goto clean_n_exit;
6774960Swillf     }
6784960Swillf 
6794960Swillf     if (kcontext->db_context == NULL) {
6804960Swillf 	status = kdb_setup_lib_handle(kcontext);
6814960Swillf 	if (status) {
6824960Swillf 	    goto clean_n_exit;
6834960Swillf 	}
6844960Swillf     }
6854960Swillf 
6864960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
6874960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
6884960Swillf     if (status) {
6894960Swillf 	goto clean_n_exit;
6904960Swillf     }
6914960Swillf 
6924960Swillf     status =
6934960Swillf 	dal_handle->lib_handle->vftabl.db_create(kcontext, section, db_args);
6944960Swillf     get_errmsg(kcontext, status);
6954960Swillf 
6964960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
6974960Swillf 
6984960Swillf   clean_n_exit:
6994960Swillf     if (section)
7004960Swillf 	free(section);
7014960Swillf     return status;
7024960Swillf }
7034960Swillf 
7044960Swillf krb5_error_code
krb5_db_fini(krb5_context kcontext)7054960Swillf krb5_db_fini(krb5_context kcontext)
7064960Swillf {
7074960Swillf     krb5_error_code status = 0;
7084960Swillf     kdb5_dal_handle *dal_handle;
7094960Swillf 
7104960Swillf     if (kcontext->db_context == NULL) {
7114960Swillf 	/* module not loaded. So nothing to be done */
7124960Swillf 	goto clean_n_exit;
7134960Swillf     }
7144960Swillf 
7154960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
7164960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
7174960Swillf     if (status) {
7184960Swillf 	goto clean_n_exit;
7194960Swillf     }
7204960Swillf 
7214960Swillf     status = dal_handle->lib_handle->vftabl.fini_module(kcontext);
7224960Swillf     get_errmsg(kcontext, status);
7234960Swillf 
7244960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
7254960Swillf 
7264960Swillf     if (status) {
7274960Swillf 	goto clean_n_exit;
7284960Swillf     }
7294960Swillf 
7304960Swillf     status = kdb_free_lib_handle(kcontext);
7314960Swillf 
7324960Swillf   clean_n_exit:
7334960Swillf     return status;
7344960Swillf }
7354960Swillf 
7364960Swillf krb5_error_code
krb5_db_destroy(krb5_context kcontext,char ** db_args)7374960Swillf krb5_db_destroy(krb5_context kcontext, char **db_args)
7384960Swillf {
7394960Swillf     krb5_error_code status = 0;
7404960Swillf     char   *section = NULL;
7414960Swillf     kdb5_dal_handle *dal_handle;
7424960Swillf 
7434960Swillf     section = kdb_get_conf_section(kcontext);
7444960Swillf     if (section == NULL) {
7454960Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
7464960Swillf 	krb5_set_error_message (kcontext, status,
7474960Swillf 		gettext("unable to determine configuration section for realm %s\n"),
7484960Swillf 		kcontext->default_realm);
7494960Swillf 	goto clean_n_exit;
7504960Swillf     }
7514960Swillf 
7524960Swillf     if (kcontext->db_context == NULL) {
7534960Swillf 	status = kdb_setup_lib_handle(kcontext);
7544960Swillf 	if (status) {
7554960Swillf 	    goto clean_n_exit;
7564960Swillf 	}
7574960Swillf     }
7584960Swillf 
7594960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
7604960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
7614960Swillf     if (status) {
7624960Swillf 	goto clean_n_exit;
7634960Swillf     }
7644960Swillf 
7654960Swillf     status =
7664960Swillf 	dal_handle->lib_handle->vftabl.db_destroy(kcontext, section, db_args);
7674960Swillf     get_errmsg(kcontext, status);
7684960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
7694960Swillf 
7704960Swillf   clean_n_exit:
7714960Swillf     if (section)
7724960Swillf 	free(section);
7734960Swillf     return status;
7744960Swillf }
7754960Swillf 
7764960Swillf krb5_error_code
krb5_db_get_age(krb5_context kcontext,char * db_name,time_t * t)7774960Swillf krb5_db_get_age(krb5_context kcontext, char *db_name, time_t * t)
7784960Swillf {
7794960Swillf     krb5_error_code status = 0;
7804960Swillf     kdb5_dal_handle *dal_handle;
7814960Swillf 
7824960Swillf     if (kcontext->db_context == NULL) {
7834960Swillf 	status = kdb_setup_lib_handle(kcontext);
7844960Swillf 	if (status) {
7854960Swillf 	    goto clean_n_exit;
7864960Swillf 	}
7874960Swillf     }
7884960Swillf 
7894960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
7904960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
7914960Swillf     if (status) {
7924960Swillf 	goto clean_n_exit;
7934960Swillf     }
7944960Swillf 
7954960Swillf     status = dal_handle->lib_handle->vftabl.db_get_age(kcontext, db_name, t);
7964960Swillf     get_errmsg(kcontext, status);
7974960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
7984960Swillf 
7994960Swillf   clean_n_exit:
8004960Swillf     return status;
8014960Swillf }
8024960Swillf 
8034960Swillf krb5_error_code
krb5_db_set_option(krb5_context kcontext,int option,void * value)8044960Swillf krb5_db_set_option(krb5_context kcontext, int option, void *value)
8054960Swillf {
8064960Swillf     krb5_error_code status = 0;
8074960Swillf     kdb5_dal_handle *dal_handle;
8084960Swillf 
8094960Swillf     if (kcontext->db_context == NULL) {
8104960Swillf 	status = kdb_setup_lib_handle(kcontext);
8114960Swillf 	if (status) {
8124960Swillf 	    goto clean_n_exit;
8134960Swillf 	}
8144960Swillf     }
8154960Swillf 
8164960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
8174960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
8184960Swillf     if (status) {
8194960Swillf 	goto clean_n_exit;
8204960Swillf     }
8214960Swillf 
8224960Swillf     status =
8234960Swillf 	dal_handle->lib_handle->vftabl.db_set_option(kcontext, option, value);
8244960Swillf     get_errmsg(kcontext, status);
8254960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
8264960Swillf 
8274960Swillf   clean_n_exit:
8284960Swillf     return status;
8294960Swillf }
8304960Swillf 
8314960Swillf krb5_error_code
krb5_db_lock(krb5_context kcontext,int lock_mode)8324960Swillf krb5_db_lock(krb5_context kcontext, int lock_mode)
8334960Swillf {
8344960Swillf     krb5_error_code status = 0;
8354960Swillf     kdb5_dal_handle *dal_handle;
8364960Swillf 
8374960Swillf     if (kcontext->db_context == NULL) {
8384960Swillf 	status = kdb_setup_lib_handle(kcontext);
8394960Swillf 	if (status) {
8404960Swillf 	    goto clean_n_exit;
8414960Swillf 	}
8424960Swillf     }
8434960Swillf 
8444960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
8454960Swillf     /* acquire an exclusive lock, ensures no other thread uses this context */
8464960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, TRUE);
8474960Swillf     if (status) {
8484960Swillf 	goto clean_n_exit;
8494960Swillf     }
8504960Swillf 
8514960Swillf     status = dal_handle->lib_handle->vftabl.db_lock(kcontext, lock_mode);
8524960Swillf     get_errmsg(kcontext, status);
8534960Swillf 
8544960Swillf     /* exclusive lock is still held, so no other thread could use this context */
8554960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
8564960Swillf 
8574960Swillf   clean_n_exit:
8584960Swillf     return status;
8594960Swillf }
8604960Swillf 
8614960Swillf krb5_error_code
krb5_db_unlock(krb5_context kcontext)8624960Swillf krb5_db_unlock(krb5_context kcontext)
8634960Swillf {
8644960Swillf     krb5_error_code status = 0;
8654960Swillf     kdb5_dal_handle *dal_handle;
8664960Swillf 
8674960Swillf     if (kcontext->db_context == NULL) {
8684960Swillf 	status = kdb_setup_lib_handle(kcontext);
8694960Swillf 	if (status) {
8704960Swillf 	    goto clean_n_exit;
8714960Swillf 	}
8724960Swillf     }
8734960Swillf 
8744960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
8754960Swillf     /* normal lock acquired and exclusive lock released */
8764960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
8774960Swillf     if (status) {
8784960Swillf 	goto clean_n_exit;
8794960Swillf     }
8804960Swillf 
8814960Swillf     status = dal_handle->lib_handle->vftabl.db_unlock(kcontext);
8824960Swillf     get_errmsg(kcontext, status);
8834960Swillf 
8844960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, TRUE);
8854960Swillf 
8864960Swillf   clean_n_exit:
8874960Swillf     return status;
8884960Swillf }
8894960Swillf 
8904960Swillf krb5_error_code
krb5_db_get_principal(krb5_context kcontext,krb5_const_principal search_for,krb5_db_entry * entries,int * nentries,krb5_boolean * more)8914960Swillf krb5_db_get_principal(krb5_context kcontext,
8924960Swillf 		      krb5_const_principal search_for,
8934960Swillf 		      krb5_db_entry * entries,
8944960Swillf 		      int *nentries, krb5_boolean * more)
8954960Swillf {
8964960Swillf     krb5_error_code status = 0;
8974960Swillf     kdb5_dal_handle *dal_handle;
8984960Swillf 
8994960Swillf     if (kcontext->db_context == NULL) {
9004960Swillf 	status = kdb_setup_lib_handle(kcontext);
9014960Swillf 	if (status) {
9024960Swillf 	    goto clean_n_exit;
9034960Swillf 	}
9044960Swillf     }
9054960Swillf 
9064960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
9074960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
9084960Swillf     if (status) {
9094960Swillf 	goto clean_n_exit;
9104960Swillf     }
9114960Swillf 
9124960Swillf     status =
9134960Swillf 	dal_handle->lib_handle->vftabl.db_get_principal(kcontext, search_for,
9144960Swillf 							entries, nentries,
9154960Swillf 							more);
9164960Swillf     get_errmsg(kcontext, status);
9174960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
9184960Swillf 
9194960Swillf   clean_n_exit:
9204960Swillf     return status;
9214960Swillf }
9224960Swillf 
9234960Swillf krb5_error_code
krb5_db_get_principal_nolock(krb5_context kcontext,krb5_const_principal search_for,krb5_db_entry * entries,int * nentries,krb5_boolean * more)9244960Swillf krb5_db_get_principal_nolock(krb5_context kcontext,
9254960Swillf 		      krb5_const_principal search_for,
9264960Swillf 		      krb5_db_entry * entries,
9274960Swillf 		      int *nentries, krb5_boolean * more)
9284960Swillf {
9294960Swillf     krb5_error_code status = 0;
9304960Swillf     kdb5_dal_handle *dal_handle;
9314960Swillf 
9324960Swillf     if (kcontext->db_context == NULL) {
9334960Swillf 	status = kdb_setup_lib_handle(kcontext);
9344960Swillf 	if (status) {
9354960Swillf 	    goto clean_n_exit;
9364960Swillf 	}
9374960Swillf     }
9384960Swillf 
9394960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
9404960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
9414960Swillf     if (status) {
9424960Swillf 	goto clean_n_exit;
9434960Swillf     }
9444960Swillf 
9454960Swillf     status =
9464960Swillf 	dal_handle->lib_handle->vftabl.db_get_principal_nolock(kcontext,
9474960Swillf 							search_for,
9484960Swillf 							entries, nentries,
9494960Swillf 							more);
9504960Swillf     get_errmsg(kcontext, status);
9514960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
9524960Swillf 
9534960Swillf   clean_n_exit:
9544960Swillf     return status;
9554960Swillf }
9564960Swillf 
9574960Swillf krb5_error_code
krb5_db_free_principal(krb5_context kcontext,krb5_db_entry * entry,int count)9584960Swillf krb5_db_free_principal(krb5_context kcontext, krb5_db_entry * entry, int count)
9594960Swillf {
9604960Swillf     krb5_error_code status = 0;
9614960Swillf     kdb5_dal_handle *dal_handle;
9624960Swillf 
9634960Swillf     if (kcontext->db_context == NULL) {
9644960Swillf 	status = kdb_setup_lib_handle(kcontext);
9654960Swillf 	if (status) {
9664960Swillf 	    goto clean_n_exit;
9674960Swillf 	}
9684960Swillf     }
9694960Swillf 
9704960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
9714960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
9724960Swillf     if (status) {
9734960Swillf 	goto clean_n_exit;
9744960Swillf     }
9754960Swillf 
9764960Swillf     status =
9774960Swillf 	dal_handle->lib_handle->vftabl.db_free_principal(kcontext, entry,
9784960Swillf 							 count);
9794960Swillf     get_errmsg(kcontext, status);
9804960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
9814960Swillf 
9824960Swillf   clean_n_exit:
9834960Swillf     return status;
9844960Swillf }
9854960Swillf 
9864960Swillf krb5_error_code
krb5_db_put_principal(krb5_context kcontext,krb5_db_entry * entries,int * nentries)9874960Swillf krb5_db_put_principal(krb5_context kcontext,
9884960Swillf 		      krb5_db_entry * entries, int *nentries)
9894960Swillf {
9904960Swillf     krb5_error_code status = 0;
9914960Swillf     kdb5_dal_handle *dal_handle;
9924960Swillf     char  **db_args = NULL;
9934960Swillf     krb5_tl_data *prev, *curr, *next;
9944960Swillf     int     db_args_size = 0;
9954960Swillf 
9964960Swillf     if (kcontext->db_context == NULL) {
9974960Swillf 	status = kdb_setup_lib_handle(kcontext);
9984960Swillf 	if (status) {
9994960Swillf 	    goto clean_n_exit;
10004960Swillf 	}
10014960Swillf     }
10024960Swillf 
10034960Swillf     /* Giving db_args as part of tl data causes, db2 to store the
10044960Swillf        tl_data as such.  To prevent this, tl_data is collated and
10054960Swillf        passed as a sepearte argument. Currently supports only one
10064960Swillf        principal.  but passing it as a seperate argument makes it
10074960Swillf        difficult for kadmin remote to pass arguments to server.  */
10084960Swillf     prev = NULL, curr = entries->tl_data;
10094960Swillf     while (curr) {
10104960Swillf 	if (curr->tl_data_type == KRB5_TL_DB_ARGS) {
10114960Swillf 	    char  **t;
10124960Swillf 	    /* Since this is expected to be NULL terminated string and
10134960Swillf 	       this could come from any client, do a check before
10144960Swillf 	       passing it to db.  */
10154960Swillf 	    if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] !=
10164960Swillf 		'\0') {
10174960Swillf 		/* not null terminated. Dangerous input */
10184960Swillf 		status = EINVAL;
10194960Swillf 		goto clean_n_exit;
10204960Swillf 	    }
10214960Swillf 
10224960Swillf 	    db_args_size++;
10234960Swillf 	    t = realloc(db_args, sizeof(char *) * (db_args_size + 1));	/* 1 for NULL */
10244960Swillf 	    if (t == NULL) {
10254960Swillf 		status = ENOMEM;
10264960Swillf 		goto clean_n_exit;
10274960Swillf 	    }
10284960Swillf 
10294960Swillf 	    db_args = t;
10304960Swillf 	    db_args[db_args_size - 1] = (char *) curr->tl_data_contents;
10314960Swillf 	    db_args[db_args_size] = NULL;
10324960Swillf 
10334960Swillf 	    next = curr->tl_data_next;
10344960Swillf 	    if (prev == NULL) {
10354960Swillf 		/* current node is the first in the linked list. remove it */
10364960Swillf 		entries->tl_data = curr->tl_data_next;
10374960Swillf 	    } else {
10384960Swillf 		prev->tl_data_next = curr->tl_data_next;
10394960Swillf 	    }
10404960Swillf 	    entries->n_tl_data--;
10414960Swillf 	    krb5_db_free(kcontext, curr);
10424960Swillf 
10434960Swillf 	    /* previous does not change */
10444960Swillf 	    curr = next;
10454960Swillf 	} else {
10464960Swillf 	    prev = curr;
10474960Swillf 	    curr = curr->tl_data_next;
10484960Swillf 	}
10494960Swillf     }
10504960Swillf 
10514960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
10524960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
10534960Swillf     if (status) {
10544960Swillf 	goto clean_n_exit;
10554960Swillf     }
10564960Swillf 
10574960Swillf     status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries,
10584960Swillf 							     nentries,
10594960Swillf 							     db_args);
10604960Swillf     get_errmsg(kcontext, status);
10614960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
10624960Swillf 
10634960Swillf   clean_n_exit:
10644960Swillf     while (db_args_size) {
10654960Swillf 	if (db_args[db_args_size - 1])
10664960Swillf 	    krb5_db_free(kcontext, db_args[db_args_size - 1]);
10674960Swillf 
10684960Swillf 	db_args_size--;
10694960Swillf     }
10704960Swillf 
10714960Swillf     if (db_args)
10724960Swillf 	free(db_args);
10734960Swillf 
10744960Swillf     return status;
10754960Swillf }
10764960Swillf 
10774960Swillf krb5_error_code
krb5_db_delete_principal(krb5_context kcontext,krb5_principal search_for,int * nentries)10784960Swillf krb5_db_delete_principal(krb5_context kcontext,
10794960Swillf 			 krb5_principal search_for, int *nentries)
10804960Swillf {
10814960Swillf     krb5_error_code status = 0;
10824960Swillf     kdb5_dal_handle *dal_handle;
10834960Swillf 
10844960Swillf     if (kcontext->db_context == NULL) {
10854960Swillf 	status = kdb_setup_lib_handle(kcontext);
10864960Swillf 	if (status) {
10874960Swillf 	    goto clean_n_exit;
10884960Swillf 	}
10894960Swillf     }
10904960Swillf 
10914960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
10924960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
10934960Swillf     if (status) {
10944960Swillf 	goto clean_n_exit;
10954960Swillf     }
10964960Swillf 
10974960Swillf     status =
10984960Swillf 	dal_handle->lib_handle->vftabl.db_delete_principal(kcontext,
10994960Swillf 							   search_for,
11004960Swillf 							   nentries);
11014960Swillf     get_errmsg(kcontext, status);
11024960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
11034960Swillf 
11044960Swillf   clean_n_exit:
11054960Swillf     return status;
11064960Swillf }
11074960Swillf 
11084960Swillf krb5_error_code
krb5_db_iterate(krb5_context kcontext,char * match_entry,int (* func)(krb5_pointer,krb5_db_entry *),krb5_pointer func_arg,char ** db_args)11094960Swillf krb5_db_iterate(krb5_context kcontext,
11104960Swillf 		char *match_entry,
11114960Swillf 		int (*func) (krb5_pointer, krb5_db_entry *),
11125916Swillf 		krb5_pointer func_arg,
11135916Swillf 		/* Solaris Kerberos: adding support for db_args */
11145916Swillf 		char **db_args)
11154960Swillf {
11164960Swillf     krb5_error_code status = 0;
11174960Swillf     kdb5_dal_handle *dal_handle;
11184960Swillf 
11194960Swillf     if (kcontext->db_context == NULL) {
11204960Swillf 	status = kdb_setup_lib_handle(kcontext);
11214960Swillf 	if (status) {
11224960Swillf 	    goto clean_n_exit;
11234960Swillf 	}
11244960Swillf     }
11254960Swillf 
11264960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
11274960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
11284960Swillf     if (status) {
11294960Swillf 	goto clean_n_exit;
11304960Swillf     }
11314960Swillf 
11325916Swillf     /* Solaris Kerberos: adding support for db_args */
11334960Swillf     status = dal_handle->lib_handle->vftabl.db_iterate(kcontext,
11344960Swillf 						       match_entry,
11355916Swillf 						       func, func_arg,
11365916Swillf 						       db_args);
11374960Swillf     get_errmsg(kcontext, status);
11384960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
11394960Swillf 
11404960Swillf   clean_n_exit:
11414960Swillf     return status;
11424960Swillf }
11434960Swillf 
11444960Swillf krb5_error_code
krb5_supported_realms(krb5_context kcontext,char ** realms)11454960Swillf krb5_supported_realms(krb5_context kcontext, char **realms)
11464960Swillf {
11474960Swillf     krb5_error_code status = 0;
11484960Swillf     kdb5_dal_handle *dal_handle;
11494960Swillf 
11504960Swillf     if (kcontext->db_context == NULL) {
11514960Swillf 	status = kdb_setup_lib_handle(kcontext);
11524960Swillf 	if (status) {
11534960Swillf 	    goto clean_n_exit;
11544960Swillf 	}
11554960Swillf     }
11564960Swillf 
11574960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
11584960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
11594960Swillf     if (status) {
11604960Swillf 	goto clean_n_exit;
11614960Swillf     }
11624960Swillf 
11634960Swillf     status =
11644960Swillf 	dal_handle->lib_handle->vftabl.db_supported_realms(kcontext, realms);
11654960Swillf     get_errmsg(kcontext, status);
11664960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
11674960Swillf 
11684960Swillf   clean_n_exit:
11694960Swillf     return status;
11704960Swillf }
11714960Swillf 
11724960Swillf krb5_error_code
krb5_free_supported_realms(krb5_context kcontext,char ** realms)11734960Swillf krb5_free_supported_realms(krb5_context kcontext, char **realms)
11744960Swillf {
11754960Swillf     krb5_error_code status = 0;
11764960Swillf     kdb5_dal_handle *dal_handle;
11774960Swillf 
11784960Swillf     if (kcontext->db_context == NULL) {
11794960Swillf 	status = kdb_setup_lib_handle(kcontext);
11804960Swillf 	if (status) {
11814960Swillf 	    goto clean_n_exit;
11824960Swillf 	}
11834960Swillf     }
11844960Swillf 
11854960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
11864960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
11874960Swillf     if (status) {
11884960Swillf 	goto clean_n_exit;
11894960Swillf     }
11904960Swillf 
11914960Swillf     status =
11924960Swillf 	dal_handle->lib_handle->vftabl.db_free_supported_realms(kcontext,
11934960Swillf 								realms);
11944960Swillf     get_errmsg(kcontext, status);
11954960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
11964960Swillf 
11974960Swillf   clean_n_exit:
11984960Swillf     return status;
11994960Swillf }
12004960Swillf 
12014960Swillf krb5_error_code
krb5_db_set_master_key_ext(krb5_context kcontext,char * pwd,krb5_keyblock * key)12024960Swillf krb5_db_set_master_key_ext(krb5_context kcontext,
12034960Swillf 			   char *pwd, krb5_keyblock * key)
12044960Swillf {
12054960Swillf     krb5_error_code status = 0;
12064960Swillf     kdb5_dal_handle *dal_handle;
12074960Swillf 
12084960Swillf     if (kcontext->db_context == NULL) {
12094960Swillf 	status = kdb_setup_lib_handle(kcontext);
12104960Swillf 	if (status) {
12114960Swillf 	    goto clean_n_exit;
12124960Swillf 	}
12134960Swillf     }
12144960Swillf 
12154960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
12164960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
12174960Swillf     if (status) {
12184960Swillf 	goto clean_n_exit;
12194960Swillf     }
12204960Swillf 
12214960Swillf     status = dal_handle->lib_handle->vftabl.set_master_key(kcontext, pwd, key);
12224960Swillf     get_errmsg(kcontext, status);
12234960Swillf 
12244960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
12254960Swillf 
12264960Swillf   clean_n_exit:
12274960Swillf     return status;
12284960Swillf }
12294960Swillf 
12304960Swillf krb5_error_code
krb5_db_set_mkey(krb5_context context,krb5_keyblock * key)12314960Swillf krb5_db_set_mkey(krb5_context context, krb5_keyblock * key)
12324960Swillf {
12334960Swillf     return krb5_db_set_master_key_ext(context, NULL, key);
12344960Swillf }
12354960Swillf 
12364960Swillf krb5_error_code
krb5_db_get_mkey(krb5_context kcontext,krb5_keyblock ** key)12374960Swillf krb5_db_get_mkey(krb5_context kcontext, krb5_keyblock ** key)
12384960Swillf {
12394960Swillf     krb5_error_code status = 0;
12404960Swillf     kdb5_dal_handle *dal_handle;
12414960Swillf 
12424960Swillf     if (kcontext->db_context == NULL) {
12434960Swillf 	status = kdb_setup_lib_handle(kcontext);
12444960Swillf 	if (status) {
12454960Swillf 	    goto clean_n_exit;
12464960Swillf 	}
12474960Swillf     }
12484960Swillf 
12494960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
12504960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
12514960Swillf     if (status) {
12524960Swillf 	goto clean_n_exit;
12534960Swillf     }
12544960Swillf 
12554960Swillf     /* Lets use temp key and copy it later to avoid memory problems
12564960Swillf        when freed by the caller.  */
12574960Swillf     status = dal_handle->lib_handle->vftabl.get_master_key(kcontext, key);
12584960Swillf     get_errmsg(kcontext, status);
12594960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
12604960Swillf 
12614960Swillf   clean_n_exit:
12624960Swillf     return status;
12634960Swillf }
12644960Swillf 
12654960Swillf krb5_error_code
krb5_db_store_master_key(krb5_context kcontext,char * db_arg,krb5_principal mname,krb5_keyblock * key,char * master_pwd)12664960Swillf krb5_db_store_master_key(krb5_context kcontext,
12674960Swillf 			 char *db_arg,
12684960Swillf 			 krb5_principal mname,
12694960Swillf 			 krb5_keyblock * key, char *master_pwd)
12704960Swillf {
12714960Swillf     krb5_error_code status = 0;
12724960Swillf     kdb5_dal_handle *dal_handle;
12734960Swillf 
12744960Swillf     if (kcontext->db_context == NULL) {
12754960Swillf 	status = kdb_setup_lib_handle(kcontext);
12764960Swillf 	if (status) {
12774960Swillf 	    goto clean_n_exit;
12784960Swillf 	}
12794960Swillf     }
12804960Swillf 
12814960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
12824960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
12834960Swillf     if (status) {
12844960Swillf 	goto clean_n_exit;
12854960Swillf     }
12864960Swillf 
12874960Swillf     status = dal_handle->lib_handle->vftabl.store_master_key(kcontext,
12884960Swillf 							     db_arg,
12894960Swillf 							     mname,
12904960Swillf 							     key, master_pwd);
12914960Swillf     get_errmsg(kcontext, status);
12924960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
12934960Swillf 
12944960Swillf   clean_n_exit:
12954960Swillf     return status;
12964960Swillf }
12974960Swillf 
12984960Swillf char   *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
12994960Swillf char   *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
13004960Swillf 
13014960Swillf krb5_error_code
krb5_db_fetch_mkey(krb5_context context,krb5_principal mname,krb5_enctype etype,krb5_boolean fromkeyboard,krb5_boolean twice,char * db_args,krb5_data * salt,krb5_keyblock * key)13024960Swillf krb5_db_fetch_mkey(krb5_context context,
13034960Swillf 		   krb5_principal mname,
13044960Swillf 		   krb5_enctype etype,
13054960Swillf 		   krb5_boolean fromkeyboard,
13064960Swillf 		   krb5_boolean twice,
13074960Swillf 		   char *db_args, krb5_data * salt, krb5_keyblock * key)
13084960Swillf {
13094960Swillf     krb5_error_code retval;
13104960Swillf     char    password[BUFSIZ];
13114960Swillf     krb5_data pwd;
13124960Swillf     unsigned int size = sizeof(password);
13134960Swillf     int     kvno;
13144960Swillf     krb5_keyblock tmp_key;
13154960Swillf 
13164960Swillf     memset(&tmp_key, 0, sizeof(tmp_key));
13174960Swillf 
13184960Swillf     if (fromkeyboard) {
13194960Swillf 	krb5_data scratch;
13204960Swillf 
13214960Swillf 	if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
13224960Swillf 					 twice ? krb5_mkey_pwd_prompt2 : 0,
13234960Swillf 					 password, &size))) {
13244960Swillf 	    goto clean_n_exit;
13254960Swillf 	}
13264960Swillf 
13274960Swillf 	pwd.data = password;
13284960Swillf 	pwd.length = size;
13294960Swillf 	if (!salt) {
13304960Swillf 	    retval = krb5_principal2salt(context, mname, &scratch);
13314960Swillf 	    if (retval)
13324960Swillf 		goto clean_n_exit;
13334960Swillf 	}
13344960Swillf 	retval =
13354960Swillf 	    krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch,
13364960Swillf 				 key);
13374960Swillf 
13384960Swillf 	if (!salt)
13394960Swillf 	    krb5_xfree(scratch.data);
13404960Swillf 	memset(password, 0, sizeof(password));	/* erase it */
13414960Swillf 
13424960Swillf     } else {
13434960Swillf 	kdb5_dal_handle *dal_handle;
13444960Swillf 
13454960Swillf 	if (context->db_context == NULL) {
13464960Swillf 	    retval = kdb_setup_lib_handle(context);
13474960Swillf 	    if (retval) {
13484960Swillf 		goto clean_n_exit;
13494960Swillf 	    }
13504960Swillf 	}
13514960Swillf 
13524960Swillf 	dal_handle = (kdb5_dal_handle *) context->db_context;
13534960Swillf 	retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
13544960Swillf 	if (retval) {
13554960Swillf 	    goto clean_n_exit;
13564960Swillf 	}
13574960Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
13584960Swillf 	/* Orig MIT */
13594960Swillf 	tmp_key.enctype = key->enctype;
13604960Swillf #else
13614960Swillf 	/* Solaris Kerberos: need to use etype */
13624960Swillf 	tmp_key.enctype = etype;
13634960Swillf #endif /**************** END IFDEF'ed OUT *******************************/
13644960Swillf 	retval = dal_handle->lib_handle->vftabl.fetch_master_key(context,
13654960Swillf 								 mname,
13664960Swillf 								 &tmp_key,
13674960Swillf 								 &kvno,
13684960Swillf 								 db_args);
13694960Swillf 	get_errmsg(context, retval);
13704960Swillf 	kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
13714960Swillf 
13724960Swillf 	if (retval) {
13734960Swillf 	    goto clean_n_exit;
13744960Swillf 	}
13754960Swillf 
13764960Swillf 	key->contents = malloc(tmp_key.length);
13774960Swillf 	if (key->contents == NULL) {
13784960Swillf 	    retval = ENOMEM;
13794960Swillf 	    goto clean_n_exit;
13804960Swillf 	}
13814960Swillf 
13824960Swillf 	key->magic = tmp_key.magic;
13834960Swillf 	key->enctype = tmp_key.enctype;
13844960Swillf 	key->length = tmp_key.length;
13854960Swillf 	memcpy(key->contents, tmp_key.contents, tmp_key.length);
13864960Swillf     }
13874960Swillf 
13884960Swillf   clean_n_exit:
13894960Swillf     if (tmp_key.contents) {
13904960Swillf 	memset(tmp_key.contents, 0, tmp_key.length);
13914960Swillf 	krb5_db_free(context, tmp_key.contents);
13924960Swillf     }
13934960Swillf     return retval;
13944960Swillf }
13954960Swillf 
13964960Swillf krb5_error_code
krb5_db_verify_master_key(krb5_context kcontext,krb5_principal mprinc,krb5_keyblock * mkey)13974960Swillf krb5_db_verify_master_key(krb5_context kcontext,
13984960Swillf 			  krb5_principal mprinc, krb5_keyblock * mkey)
13994960Swillf {
14004960Swillf     krb5_error_code status = 0;
14014960Swillf     kdb5_dal_handle *dal_handle;
14024960Swillf 
14034960Swillf     if (kcontext->db_context == NULL) {
14044960Swillf 	status = kdb_setup_lib_handle(kcontext);
14054960Swillf 	if (status) {
14064960Swillf 	    goto clean_n_exit;
14074960Swillf 	}
14084960Swillf     }
14094960Swillf 
14104960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
14114960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
14124960Swillf     if (status) {
14134960Swillf 	goto clean_n_exit;
14144960Swillf     }
14154960Swillf 
14164960Swillf     status = dal_handle->lib_handle->vftabl.verify_master_key(kcontext,
14174960Swillf 							      mprinc, mkey);
14184960Swillf     get_errmsg(kcontext, status);
14194960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
14204960Swillf 
14214960Swillf   clean_n_exit:
14224960Swillf     return status;
14234960Swillf }
14244960Swillf 
14254960Swillf void   *
krb5_db_alloc(krb5_context kcontext,void * ptr,size_t size)14264960Swillf krb5_db_alloc(krb5_context kcontext, void *ptr, size_t size)
14274960Swillf {
14284960Swillf     krb5_error_code status;
14294960Swillf     kdb5_dal_handle *dal_handle;
14304960Swillf     void   *new_ptr = NULL;
14314960Swillf 
14324960Swillf     if (kcontext->db_context == NULL) {
14334960Swillf 	status = kdb_setup_lib_handle(kcontext);
14344960Swillf 	if (status) {
14354960Swillf 	    goto clean_n_exit;
14364960Swillf 	}
14374960Swillf     }
14384960Swillf 
14394960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
14404960Swillf 
14414960Swillf     new_ptr = dal_handle->lib_handle->vftabl.db_alloc(kcontext, ptr, size);
14424960Swillf 
14434960Swillf   clean_n_exit:
14444960Swillf     return new_ptr;
14454960Swillf }
14464960Swillf 
14474960Swillf void
krb5_db_free(krb5_context kcontext,void * ptr)14484960Swillf krb5_db_free(krb5_context kcontext, void *ptr)
14494960Swillf {
14504960Swillf     krb5_error_code status;
14514960Swillf     kdb5_dal_handle *dal_handle;
14524960Swillf 
14534960Swillf     if (kcontext->db_context == NULL) {
14544960Swillf 	status = kdb_setup_lib_handle(kcontext);
14554960Swillf 	if (status) {
14564960Swillf 	    goto clean_n_exit;
14574960Swillf 	}
14584960Swillf     }
14594960Swillf 
14604960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
14614960Swillf 
14624960Swillf     dal_handle->lib_handle->vftabl.db_free(kcontext, ptr);
14634960Swillf 
14644960Swillf   clean_n_exit:
14654960Swillf     return;
14664960Swillf }
14674960Swillf 
14684960Swillf /* has to be modified */
14694960Swillf 
14704960Swillf krb5_error_code
krb5_dbe_find_enctype(krb5_context kcontext,krb5_db_entry * dbentp,krb5_int32 ktype,krb5_int32 stype,krb5_int32 kvno,krb5_key_data ** kdatap)14714960Swillf krb5_dbe_find_enctype(krb5_context kcontext,
14724960Swillf 		      krb5_db_entry * dbentp,
14734960Swillf 		      krb5_int32 ktype,
14744960Swillf 		      krb5_int32 stype,
14754960Swillf 		      krb5_int32 kvno, krb5_key_data ** kdatap)
14764960Swillf {
14774960Swillf     krb5_int32 start = 0;
14784960Swillf     return krb5_dbe_search_enctype(kcontext, dbentp, &start, ktype, stype,
14794960Swillf 				   kvno, kdatap);
14804960Swillf }
14814960Swillf 
14824960Swillf krb5_error_code
krb5_dbe_search_enctype(krb5_context kcontext,krb5_db_entry * dbentp,krb5_int32 * start,krb5_int32 ktype,krb5_int32 stype,krb5_int32 kvno,krb5_key_data ** kdatap)14834960Swillf krb5_dbe_search_enctype(krb5_context kcontext,
14844960Swillf 			krb5_db_entry * dbentp,
14854960Swillf 			krb5_int32 * start,
14864960Swillf 			krb5_int32 ktype,
14874960Swillf 			krb5_int32 stype,
14884960Swillf 			krb5_int32 kvno, krb5_key_data ** kdatap)
14894960Swillf {
14904960Swillf     krb5_error_code status = 0;
14914960Swillf     kdb5_dal_handle *dal_handle;
14924960Swillf 
14934960Swillf     if (kcontext->db_context == NULL) {
14944960Swillf 	status = kdb_setup_lib_handle(kcontext);
14954960Swillf 	if (status) {
14964960Swillf 	    goto clean_n_exit;
14974960Swillf 	}
14984960Swillf     }
14994960Swillf 
15004960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
15014960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
15024960Swillf     if (status) {
15034960Swillf 	goto clean_n_exit;
15044960Swillf     }
15054960Swillf 
15064960Swillf     status = dal_handle->lib_handle->vftabl.dbe_search_enctype(kcontext,
15074960Swillf 							       dbentp,
15084960Swillf 							       start,
15094960Swillf 							       ktype,
15104960Swillf 							       stype,
15114960Swillf 							       kvno, kdatap);
15124960Swillf     get_errmsg(kcontext, status);
15134960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
15144960Swillf 
15154960Swillf   clean_n_exit:
15164960Swillf     return status;
15174960Swillf }
15184960Swillf 
15194960Swillf #define	REALM_SEP_STRING	"@"
15204960Swillf 
15214960Swillf krb5_error_code
krb5_db_setup_mkey_name(krb5_context context,const char * keyname,const char * realm,char ** fullname,krb5_principal * principal)15224960Swillf krb5_db_setup_mkey_name(krb5_context context,
15234960Swillf 			const char *keyname,
15244960Swillf 			const char *realm,
15254960Swillf 			char **fullname, krb5_principal * principal)
15264960Swillf {
15274960Swillf     krb5_error_code retval;
15284960Swillf     size_t  keylen;
15294960Swillf     size_t  rlen = strlen(realm);
15304960Swillf     char   *fname;
15314960Swillf 
15324960Swillf     if (!keyname)
15334960Swillf 	keyname = KRB5_KDB_M_NAME;	/* XXX external? */
15344960Swillf 
15354960Swillf     keylen = strlen(keyname);
15364960Swillf 
15374960Swillf     fname = malloc(keylen + rlen + strlen(REALM_SEP_STRING) + 1);
15384960Swillf     if (!fname)
15394960Swillf 	return ENOMEM;
15404960Swillf 
15414960Swillf     strcpy(fname, keyname);
15424960Swillf     (void)strcat(fname, REALM_SEP_STRING);
15434960Swillf     (void)strcat(fname, realm);
15444960Swillf 
15454960Swillf     if ((retval = krb5_parse_name(context, fname, principal)))
15464960Swillf 	return retval;
15474960Swillf     if (fullname)
15484960Swillf 	*fullname = fname;
15494960Swillf     else
15504960Swillf 	free(fname);
15514960Swillf     return 0;
15524960Swillf }
15534960Swillf 
15544960Swillf krb5_error_code
krb5_dbe_lookup_last_pwd_change(context,entry,stamp)15554960Swillf krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
15564960Swillf     krb5_context context;
15574960Swillf     krb5_db_entry *entry;
15584960Swillf     krb5_timestamp *stamp;
15594960Swillf {
15604960Swillf     krb5_tl_data tl_data;
15614960Swillf     krb5_error_code code;
15624960Swillf     krb5_int32 tmp;
15634960Swillf 
15644960Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
15654960Swillf 
15664960Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
15674960Swillf 	return (code);
15684960Swillf 
15694960Swillf     if (tl_data.tl_data_length != 4) {
15704960Swillf 	*stamp = 0;
15714960Swillf 	return (0);
15724960Swillf     }
15734960Swillf 
15744960Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
15754960Swillf 
15764960Swillf     *stamp = (krb5_timestamp) tmp;
15774960Swillf 
15784960Swillf     return (0);
15794960Swillf }
15804960Swillf 
15814960Swillf /*ARGSUSED*/
15824960Swillf krb5_error_code
krb5_dbe_lookup_tl_data(context,entry,ret_tl_data)15834960Swillf krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
15844960Swillf     krb5_context context;
15854960Swillf     krb5_db_entry *entry;
15864960Swillf     krb5_tl_data *ret_tl_data;
15874960Swillf {
15884960Swillf     krb5_tl_data *tl_data;
15894960Swillf 
15904960Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
15914960Swillf 	if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
15924960Swillf 	    *ret_tl_data = *tl_data;
15934960Swillf 	    return (0);
15944960Swillf 	}
15954960Swillf     }
15964960Swillf 
15974960Swillf     /* if the requested record isn't found, return zero bytes.
15984960Swillf      * if it ever means something to have a zero-length tl_data,
15994960Swillf      * this code and its callers will have to be changed */
16004960Swillf 
16014960Swillf     ret_tl_data->tl_data_length = 0;
16024960Swillf     ret_tl_data->tl_data_contents = NULL;
16034960Swillf     return (0);
16044960Swillf }
16054960Swillf 
16064960Swillf krb5_error_code
krb5_dbe_create_key_data(context,entry)16074960Swillf krb5_dbe_create_key_data(context, entry)
16084960Swillf     krb5_context context;
16094960Swillf     krb5_db_entry *entry;
16104960Swillf {
16114960Swillf     if ((entry->key_data =
16124960Swillf 	 (krb5_key_data *) krb5_db_alloc(context, entry->key_data,
16134960Swillf 					 (sizeof(krb5_key_data) *
16144960Swillf 					  (entry->n_key_data + 1)))) == NULL)
16154960Swillf 	return (ENOMEM);
16164960Swillf 
16174960Swillf     memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
16184960Swillf     entry->n_key_data++;
16194960Swillf 
16204960Swillf     return 0;
16214960Swillf }
16224960Swillf 
16234960Swillf krb5_error_code
krb5_dbe_update_mod_princ_data(context,entry,mod_date,mod_princ)16244960Swillf krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
16254960Swillf     krb5_context context;
16264960Swillf     krb5_db_entry *entry;
16274960Swillf     krb5_timestamp mod_date;
16284960Swillf     krb5_const_principal mod_princ;
16294960Swillf {
16304960Swillf     krb5_tl_data tl_data;
16314960Swillf 
16324960Swillf     krb5_error_code retval = 0;
16334960Swillf     krb5_octet *nextloc = 0;
16344960Swillf     char   *unparse_mod_princ = 0;
16354960Swillf     unsigned int unparse_mod_princ_size;
16364960Swillf 
16374960Swillf     if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ)))
16384960Swillf 	return (retval);
16394960Swillf 
16404960Swillf     unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
16414960Swillf 
16424960Swillf     if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
16434960Swillf 	== NULL) {
16444960Swillf 	free(unparse_mod_princ);
16454960Swillf 	return (ENOMEM);
16464960Swillf     }
16474960Swillf 
16484960Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
16494960Swillf     tl_data.tl_data_length = unparse_mod_princ_size + 4;
16504960Swillf     tl_data.tl_data_contents = nextloc;
16514960Swillf 
16524960Swillf     /* Mod Date */
16534960Swillf     krb5_kdb_encode_int32(mod_date, nextloc);
16544960Swillf 
16554960Swillf     /* Mod Princ */
16564960Swillf     memcpy(nextloc + 4, unparse_mod_princ, unparse_mod_princ_size);
16574960Swillf 
16584960Swillf     retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
16594960Swillf 
16604960Swillf     free(unparse_mod_princ);
16614960Swillf     free(nextloc);
16624960Swillf 
16634960Swillf     return (retval);
16644960Swillf }
16654960Swillf 
16664960Swillf krb5_error_code
krb5_dbe_lookup_mod_princ_data(context,entry,mod_time,mod_princ)16674960Swillf krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
16684960Swillf     krb5_context context;
16694960Swillf     krb5_db_entry *entry;
16704960Swillf     krb5_timestamp *mod_time;
16714960Swillf     krb5_principal *mod_princ;
16724960Swillf {
16734960Swillf     krb5_tl_data tl_data;
16744960Swillf     krb5_error_code code;
16754960Swillf 
16764960Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
16774960Swillf 
16784960Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
16794960Swillf 	return (code);
16804960Swillf 
16814960Swillf     if ((tl_data.tl_data_length < 5) ||
16824960Swillf 	(tl_data.tl_data_contents[tl_data.tl_data_length - 1] != '\0'))
16834960Swillf 	return (KRB5_KDB_TRUNCATED_RECORD);
16844960Swillf 
16854960Swillf     /* Mod Date */
16864960Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
16874960Swillf 
16884960Swillf     /* Mod Princ */
16894960Swillf     if ((code = krb5_parse_name(context,
16904960Swillf 				(const char *) (tl_data.tl_data_contents + 4),
16914960Swillf 				mod_princ)))
16924960Swillf 	return (code);
16934960Swillf 
16944960Swillf     return (0);
16954960Swillf }
16964960Swillf 
16974960Swillf krb5_error_code
krb5_dbe_update_last_pwd_change(context,entry,stamp)16984960Swillf krb5_dbe_update_last_pwd_change(context, entry, stamp)
16994960Swillf     krb5_context context;
17004960Swillf     krb5_db_entry *entry;
17014960Swillf     krb5_timestamp stamp;
17024960Swillf {
17034960Swillf     krb5_tl_data tl_data;
17044960Swillf     krb5_octet buf[4];		/* this is the encoded size of an int32 */
17054960Swillf 
17064960Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
17074960Swillf     tl_data.tl_data_length = sizeof(buf);
17084960Swillf     krb5_kdb_encode_int32((krb5_int32) stamp, buf);
17094960Swillf     tl_data.tl_data_contents = buf;
17104960Swillf 
17114960Swillf     return (krb5_dbe_update_tl_data(context, entry, &tl_data));
17124960Swillf }
17134960Swillf 
17144960Swillf krb5_error_code
krb5_dbe_update_tl_data(context,entry,new_tl_data)17154960Swillf krb5_dbe_update_tl_data(context, entry, new_tl_data)
17164960Swillf     krb5_context context;
17174960Swillf     krb5_db_entry *entry;
17184960Swillf     krb5_tl_data *new_tl_data;
17194960Swillf {
17204960Swillf     krb5_tl_data *tl_data = NULL;
17214960Swillf     krb5_octet *tmp;
17224960Swillf 
17234960Swillf     /* copy the new data first, so we can fail cleanly if malloc()
17244960Swillf      * fails */
17254960Swillf     if ((tmp =
17264960Swillf 	 (krb5_octet *) krb5_db_alloc(context, NULL,
17274960Swillf 				      new_tl_data->tl_data_length)) == NULL)
17284960Swillf 	return (ENOMEM);
17294960Swillf 
17304960Swillf     /* Find an existing entry of the specified type and point at
17314960Swillf      * it, or NULL if not found */
17324960Swillf 
17334960Swillf     if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) {	/* db_args can be multiple */
17344960Swillf 	for (tl_data = entry->tl_data; tl_data;
17354960Swillf 	     tl_data = tl_data->tl_data_next)
17364960Swillf 	    if (tl_data->tl_data_type == new_tl_data->tl_data_type)
17374960Swillf 		break;
17384960Swillf     }
17394960Swillf 
17404960Swillf     /* if necessary, chain a new record in the beginning and point at it */
17414960Swillf 
17424960Swillf     if (!tl_data) {
17434960Swillf 	if ((tl_data =
17444960Swillf 	     (krb5_tl_data *) krb5_db_alloc(context, NULL,
17454960Swillf 					    sizeof(krb5_tl_data)))
17464960Swillf 	    == NULL) {
17474960Swillf 	    free(tmp);
17484960Swillf 	    return (ENOMEM);
17494960Swillf 	}
17504960Swillf 	memset(tl_data, 0, sizeof(krb5_tl_data));
17514960Swillf 	tl_data->tl_data_next = entry->tl_data;
17524960Swillf 	entry->tl_data = tl_data;
17534960Swillf 	entry->n_tl_data++;
17544960Swillf     }
17554960Swillf 
17564960Swillf     /* fill in the record */
17574960Swillf 
17584960Swillf     if (tl_data->tl_data_contents)
17594960Swillf 	krb5_db_free(context, tl_data->tl_data_contents);
17604960Swillf 
17614960Swillf     tl_data->tl_data_type = new_tl_data->tl_data_type;
17624960Swillf     tl_data->tl_data_length = new_tl_data->tl_data_length;
17634960Swillf     tl_data->tl_data_contents = tmp;
17644960Swillf     memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
17654960Swillf 
17664960Swillf     return (0);
17674960Swillf }
17684960Swillf 
17694960Swillf /* change password functions */
17704960Swillf krb5_error_code
krb5_dbe_cpw(krb5_context kcontext,krb5_keyblock * master_key,krb5_key_salt_tuple * ks_tuple,int ks_tuple_count,char * passwd,int new_kvno,krb5_boolean keepold,krb5_db_entry * db_entry)17714960Swillf krb5_dbe_cpw(krb5_context kcontext,
17724960Swillf 	     krb5_keyblock * master_key,
17734960Swillf 	     krb5_key_salt_tuple * ks_tuple,
17744960Swillf 	     int ks_tuple_count,
17754960Swillf 	     char *passwd,
17764960Swillf 	     int new_kvno, krb5_boolean keepold, krb5_db_entry * db_entry)
17774960Swillf {
17784960Swillf     krb5_error_code status = 0;
17794960Swillf     kdb5_dal_handle *dal_handle;
17804960Swillf 
17814960Swillf     if (kcontext->db_context == NULL) {
17824960Swillf 	status = kdb_setup_lib_handle(kcontext);
17834960Swillf 	if (status) {
17844960Swillf 	    goto clean_n_exit;
17854960Swillf 	}
17864960Swillf     }
17874960Swillf 
17884960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
17894960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
17904960Swillf     if (status) {
17914960Swillf 	goto clean_n_exit;
17924960Swillf     }
17934960Swillf 
17944960Swillf     status = dal_handle->lib_handle->vftabl.db_change_pwd(kcontext,
17954960Swillf 							  master_key,
17964960Swillf 							  ks_tuple,
17974960Swillf 							  ks_tuple_count,
17984960Swillf 							  passwd,
17994960Swillf 							  new_kvno,
18004960Swillf 							  keepold, db_entry);
18014960Swillf     get_errmsg(kcontext, status);
18024960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
18034960Swillf 
18044960Swillf   clean_n_exit:
18054960Swillf     return status;
18064960Swillf }
18074960Swillf 
18084960Swillf /* policy management functions */
18094960Swillf krb5_error_code
krb5_db_create_policy(krb5_context kcontext,osa_policy_ent_t policy)18104960Swillf krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)
18114960Swillf {
18124960Swillf     krb5_error_code status = 0;
18134960Swillf     kdb5_dal_handle *dal_handle;
18144960Swillf 
18154960Swillf     if (kcontext->db_context == NULL) {
18164960Swillf 	status = kdb_setup_lib_handle(kcontext);
18174960Swillf 	if (status) {
18184960Swillf 	    goto clean_n_exit;
18194960Swillf 	}
18204960Swillf     }
18214960Swillf 
18224960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
18234960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
18244960Swillf     if (status) {
18254960Swillf 	goto clean_n_exit;
18264960Swillf     }
18274960Swillf 
18284960Swillf     status = dal_handle->lib_handle->vftabl.db_create_policy(kcontext, policy);
18294960Swillf     get_errmsg(kcontext, status);
18304960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
18314960Swillf 
18324960Swillf   clean_n_exit:
18334960Swillf     return status;
18344960Swillf }
18354960Swillf 
18364960Swillf krb5_error_code
krb5_db_get_policy(krb5_context kcontext,char * name,osa_policy_ent_t * policy,int * cnt)18374960Swillf krb5_db_get_policy(krb5_context kcontext, char *name,
18384960Swillf 		   osa_policy_ent_t * policy, int *cnt)
18394960Swillf {
18404960Swillf     krb5_error_code status = 0;
18414960Swillf     kdb5_dal_handle *dal_handle;
18424960Swillf 
18434960Swillf     if (kcontext->db_context == NULL) {
18444960Swillf 	status = kdb_setup_lib_handle(kcontext);
18454960Swillf 	if (status) {
18464960Swillf 	    goto clean_n_exit;
18474960Swillf 	}
18484960Swillf     }
18494960Swillf 
18504960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
18514960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
18524960Swillf     if (status) {
18534960Swillf 	goto clean_n_exit;
18544960Swillf     }
18554960Swillf 
18564960Swillf     status =
18574960Swillf 	dal_handle->lib_handle->vftabl.db_get_policy(kcontext, name, policy,
18584960Swillf 						     cnt);
18594960Swillf     get_errmsg(kcontext, status);
18604960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
18614960Swillf 
18624960Swillf   clean_n_exit:
18634960Swillf     return status;
18644960Swillf }
18654960Swillf 
18664960Swillf krb5_error_code
krb5_db_put_policy(krb5_context kcontext,osa_policy_ent_t policy)18674960Swillf krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)
18684960Swillf {
18694960Swillf     krb5_error_code status = 0;
18704960Swillf     kdb5_dal_handle *dal_handle;
18714960Swillf 
18724960Swillf     if (kcontext->db_context == NULL) {
18734960Swillf 	status = kdb_setup_lib_handle(kcontext);
18744960Swillf 	if (status) {
18754960Swillf 	    goto clean_n_exit;
18764960Swillf 	}
18774960Swillf     }
18784960Swillf 
18794960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
18804960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
18814960Swillf     if (status) {
18824960Swillf 	goto clean_n_exit;
18834960Swillf     }
18844960Swillf 
18854960Swillf     status = dal_handle->lib_handle->vftabl.db_put_policy(kcontext, policy);
18864960Swillf     get_errmsg(kcontext, status);
18874960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
18884960Swillf 
18894960Swillf   clean_n_exit:
18904960Swillf     return status;
18914960Swillf }
18924960Swillf 
18934960Swillf krb5_error_code
krb5_db_iter_policy(krb5_context kcontext,char * match_entry,osa_adb_iter_policy_func func,void * data)18944960Swillf krb5_db_iter_policy(krb5_context kcontext, char *match_entry,
18954960Swillf 		    osa_adb_iter_policy_func func, void *data)
18964960Swillf {
18974960Swillf     krb5_error_code status = 0;
18984960Swillf     kdb5_dal_handle *dal_handle;
18994960Swillf 
19004960Swillf     if (kcontext->db_context == NULL) {
19014960Swillf 	status = kdb_setup_lib_handle(kcontext);
19024960Swillf 	if (status) {
19034960Swillf 	    goto clean_n_exit;
19044960Swillf 	}
19054960Swillf     }
19064960Swillf 
19074960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
19084960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
19094960Swillf     if (status) {
19104960Swillf 	goto clean_n_exit;
19114960Swillf     }
19124960Swillf 
19134960Swillf     status =
19144960Swillf 	dal_handle->lib_handle->vftabl.db_iter_policy(kcontext, match_entry,
19154960Swillf 						      func, data);
19164960Swillf     get_errmsg(kcontext, status);
19174960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
19184960Swillf 
19194960Swillf   clean_n_exit:
19204960Swillf     return status;
19214960Swillf }
19224960Swillf 
19234960Swillf krb5_error_code
krb5_db_delete_policy(krb5_context kcontext,char * policy)19244960Swillf krb5_db_delete_policy(krb5_context kcontext, char *policy)
19254960Swillf {
19264960Swillf     krb5_error_code status = 0;
19274960Swillf     kdb5_dal_handle *dal_handle;
19284960Swillf 
19294960Swillf     if (kcontext->db_context == NULL) {
19304960Swillf 	status = kdb_setup_lib_handle(kcontext);
19314960Swillf 	if (status) {
19324960Swillf 	    goto clean_n_exit;
19334960Swillf 	}
19344960Swillf     }
19354960Swillf 
19364960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
19374960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
19384960Swillf     if (status) {
19394960Swillf 	goto clean_n_exit;
19404960Swillf     }
19414960Swillf 
19424960Swillf     status = dal_handle->lib_handle->vftabl.db_delete_policy(kcontext, policy);
19434960Swillf     get_errmsg(kcontext, status);
19444960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
19454960Swillf 
19464960Swillf   clean_n_exit:
19474960Swillf     return status;
19484960Swillf }
19494960Swillf 
19504960Swillf void
krb5_db_free_policy(krb5_context kcontext,osa_policy_ent_t policy)19514960Swillf krb5_db_free_policy(krb5_context kcontext, osa_policy_ent_t policy)
19524960Swillf {
19534960Swillf     krb5_error_code status = 0;
19544960Swillf     kdb5_dal_handle *dal_handle;
19554960Swillf 
19564960Swillf     if (kcontext->db_context == NULL) {
19574960Swillf 	status = kdb_setup_lib_handle(kcontext);
19584960Swillf 	if (status) {
19594960Swillf 	    goto clean_n_exit;
19604960Swillf 	}
19614960Swillf     }
19624960Swillf 
19634960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
19644960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
19654960Swillf     if (status) {
19664960Swillf 	goto clean_n_exit;
19674960Swillf     }
19684960Swillf 
19694960Swillf     dal_handle->lib_handle->vftabl.db_free_policy(kcontext, policy);
19704960Swillf     get_errmsg(kcontext, status);
19714960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
19724960Swillf 
19734960Swillf   clean_n_exit:
19744960Swillf     return;
19754960Swillf }
19764960Swillf 
19774960Swillf krb5_error_code
krb5_db_promote(krb5_context kcontext,char ** db_args)19784960Swillf krb5_db_promote(krb5_context kcontext, char **db_args)
19794960Swillf {
19804960Swillf     krb5_error_code status = 0;
19814960Swillf     char   *section = NULL;
19824960Swillf     kdb5_dal_handle *dal_handle;
19834960Swillf 
19844960Swillf     section = kdb_get_conf_section(kcontext);
19854960Swillf     if (section == NULL) {
19864960Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
19874960Swillf 	krb5_set_error_message (kcontext, status,
19884960Swillf 		gettext("unable to determine configuration section for realm %s\n"),
19894960Swillf 		kcontext->default_realm);
19904960Swillf 	goto clean_n_exit;
19914960Swillf     }
19924960Swillf 
19934960Swillf     if (kcontext->db_context == NULL) {
19944960Swillf 	status = kdb_setup_lib_handle(kcontext);
19954960Swillf 	if (status) {
19964960Swillf 	    goto clean_n_exit;
19974960Swillf 	}
19984960Swillf     }
19994960Swillf 
20004960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
20014960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
20024960Swillf     if (status) {
20034960Swillf 	goto clean_n_exit;
20044960Swillf     }
20054960Swillf 
20064960Swillf     status =
20074960Swillf 	dal_handle->lib_handle->vftabl.promote_db(kcontext, section, db_args);
20084960Swillf     get_errmsg(kcontext, status);
20094960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
20104960Swillf 
20114960Swillf   clean_n_exit:
20124960Swillf     if (section)
20134960Swillf 	free(section);
20144960Swillf     return status;
20154960Swillf }
20164960Swillf 
20174960Swillf /*
20184960Swillf  * Solaris Kerberos: support for iprop
20194960Swillf  *
20204960Swillf  * Not all KDB plugins support iprop.
20214960Swillf  *
20224960Swillf  * sets iprop_supported to 1 if iprop supportd, 0 otherwise.
20234960Swillf  */
20244960Swillf krb5_error_code
krb5_db_supports_iprop(krb5_context kcontext,int * iprop_supported)20254960Swillf krb5_db_supports_iprop(krb5_context kcontext, int *iprop_supported)
20264960Swillf {
20274960Swillf     krb5_error_code status = 0;
20284960Swillf     kdb5_dal_handle *dal_handle;
20294960Swillf 
20304960Swillf     if (kcontext->db_context == NULL) {
20314960Swillf 	status = kdb_setup_lib_handle(kcontext);
20324960Swillf 	if (status) {
20334960Swillf 	    goto clean_n_exit;
20344960Swillf 	}
20354960Swillf     }
20364960Swillf 
20374960Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
20384960Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
20394960Swillf     if (status) {
20404960Swillf 	goto clean_n_exit;
20414960Swillf     }
20424960Swillf 
20434960Swillf     *iprop_supported = dal_handle->lib_handle->vftabl.iprop_supported;
20444960Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
20454960Swillf 
20464960Swillf   clean_n_exit:
20474960Swillf     return status;
20484960Swillf }
2049