xref: /titanic_41/usr/src/lib/krb5/kdb/kdb5.c (revision 7c64d3750da7fda7e450b8f9b0b963905ded6379)
154925bf6Swillf /*
22dd2efa5Swillf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
354925bf6Swillf  * Use is subject to license terms.
454925bf6Swillf  */
554925bf6Swillf 
654925bf6Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
754925bf6Swillf /*
854925bf6Swillf  * Copyright 2006 by the Massachusetts Institute of Technology.
954925bf6Swillf  * All Rights Reserved.
1054925bf6Swillf  *
1154925bf6Swillf  * Export of this software from the United States of America may
1254925bf6Swillf  *   require a specific license from the United States Government.
1354925bf6Swillf  *   It is the responsibility of any person or organization contemplating
1454925bf6Swillf  *   export to obtain such a license before exporting.
1554925bf6Swillf  *
1654925bf6Swillf  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
1754925bf6Swillf  * distribute this software and its documentation for any purpose and
1854925bf6Swillf  * without fee is hereby granted, provided that the above copyright
1954925bf6Swillf  * notice appear in all copies and that both that copyright notice and
2054925bf6Swillf  * this permission notice appear in supporting documentation, and that
2154925bf6Swillf  * the name of M.I.T. not be used in advertising or publicity pertaining
2254925bf6Swillf  * to distribution of the software without specific, written prior
2354925bf6Swillf  * permission.  Furthermore if you modify this software you must label
2454925bf6Swillf  * your software as modified software and not distribute it in such a
2554925bf6Swillf  * fashion that it might be confused with the original M.I.T. software.
2654925bf6Swillf  * M.I.T. makes no representations about the suitability of
2754925bf6Swillf  * this software for any purpose.  It is provided "as is" without express
2854925bf6Swillf  * or implied warranty.
2954925bf6Swillf  */
3054925bf6Swillf 
3154925bf6Swillf /*
3254925bf6Swillf  * This code was based on code donated to MIT by Novell for
3354925bf6Swillf  * distribution under the MIT license.
3454925bf6Swillf  */
3554925bf6Swillf 
3654925bf6Swillf /*
3754925bf6Swillf  * Include files
3854925bf6Swillf  */
3954925bf6Swillf 
4054925bf6Swillf #include <stdio.h>
4154925bf6Swillf #include <string.h>
4254925bf6Swillf #include <k5-int.h>
4354925bf6Swillf #include <osconf.h>
4454925bf6Swillf #include "kdb5.h"
4554925bf6Swillf #include <assert.h>
4654925bf6Swillf #include "k5-platform.h"
4754925bf6Swillf #include <libintl.h>
4854925bf6Swillf 
4954925bf6Swillf /* Currently DB2 policy related errors are exported from DAL.  But
5054925bf6Swillf    other databases should set_err function to return string.  */
5154925bf6Swillf #include "adb_err.h"
5254925bf6Swillf 
5354925bf6Swillf /*
5454925bf6Swillf  * Type definitions
5554925bf6Swillf  */
5654925bf6Swillf #define KRB5_TL_DB_ARGS                 0x7fff
5754925bf6Swillf 
5854925bf6Swillf /*
5954925bf6Swillf  * internal static variable
6054925bf6Swillf  */
6154925bf6Swillf 
6254925bf6Swillf static k5_mutex_t db_lock = K5_MUTEX_PARTIAL_INITIALIZER;
6354925bf6Swillf 
6454925bf6Swillf #ifdef _KDB5_STATIC_LINK
6554925bf6Swillf #undef _KDB5_DYNAMIC_LINK
6654925bf6Swillf #else
6754925bf6Swillf #undef _KDB5_DYNAMIC_LINK
6854925bf6Swillf /* to avoid redefinition problem */
6954925bf6Swillf #define _KDB5_DYNAMIC_LINK
7054925bf6Swillf #endif
7154925bf6Swillf 
7254925bf6Swillf static db_library lib_list;
7354925bf6Swillf 
7454925bf6Swillf /*
7554925bf6Swillf  * Helper Functions
7654925bf6Swillf  */
7754925bf6Swillf 
7854925bf6Swillf MAKE_INIT_FUNCTION(kdb_init_lock_list);
7954925bf6Swillf MAKE_FINI_FUNCTION(kdb_fini_lock_list);
8054925bf6Swillf 
8154925bf6Swillf int
kdb_init_lock_list(void)8254925bf6Swillf kdb_init_lock_list(void)
8354925bf6Swillf {
8454925bf6Swillf     return k5_mutex_finish_init(&db_lock);
8554925bf6Swillf }
8654925bf6Swillf 
8754925bf6Swillf static int
kdb_lock_list()8854925bf6Swillf kdb_lock_list()
8954925bf6Swillf {
9054925bf6Swillf     int err;
9154925bf6Swillf     err = CALL_INIT_FUNCTION (kdb_init_lock_list);
9254925bf6Swillf     if (err)
9354925bf6Swillf 	return err;
9454925bf6Swillf     return k5_mutex_lock(&db_lock);
9554925bf6Swillf }
9654925bf6Swillf 
9754925bf6Swillf void
kdb_fini_lock_list(void)9854925bf6Swillf kdb_fini_lock_list(void)
9954925bf6Swillf {
10054925bf6Swillf     if (INITIALIZER_RAN(kdb_init_lock_list))
10154925bf6Swillf 	k5_mutex_destroy(&db_lock);
10254925bf6Swillf }
10354925bf6Swillf 
10454925bf6Swillf static int
kdb_unlock_list()10554925bf6Swillf kdb_unlock_list()
10654925bf6Swillf {
10754925bf6Swillf     return k5_mutex_unlock(&db_lock);
10854925bf6Swillf }
10954925bf6Swillf 
11054925bf6Swillf #define kdb_init_lib_lock(a) 0
11154925bf6Swillf #define kdb_destroy_lib_lock(a) (void)0
11254925bf6Swillf #define kdb_lock_lib_lock(a, b) 0
11354925bf6Swillf #define kdb_unlock_lib_lock(a, b) (void)0
11454925bf6Swillf 
11554925bf6Swillf /* Caller must free result*/
11654925bf6Swillf 
11754925bf6Swillf static char *
kdb_get_conf_section(krb5_context kcontext)11854925bf6Swillf kdb_get_conf_section(krb5_context kcontext)
11954925bf6Swillf {
12054925bf6Swillf     krb5_error_code status = 0;
12154925bf6Swillf     char   *result = NULL;
12254925bf6Swillf     char   *value = NULL;
12354925bf6Swillf 
12454925bf6Swillf     if (kcontext->default_realm == NULL)
12554925bf6Swillf 	return NULL;
12654925bf6Swillf     /* The profile has to have been initialized.  If the profile was
12754925bf6Swillf        not initialized, expect nothing less than a crash.  */
12854925bf6Swillf     status = profile_get_string(kcontext->profile,
12954925bf6Swillf 				/* realms */
13054925bf6Swillf 				KDB_REALM_SECTION,
13154925bf6Swillf 				kcontext->default_realm,
13254925bf6Swillf 				/* under the realm name, database_module */
13354925bf6Swillf 				KDB_MODULE_POINTER,
13454925bf6Swillf 				/* default value is the realm name itself */
13554925bf6Swillf 				kcontext->default_realm,
13654925bf6Swillf 				&value);
13754925bf6Swillf 
13854925bf6Swillf     if (status) {
13954925bf6Swillf 	/* some problem */
14054925bf6Swillf 	result = strdup(kcontext->default_realm);
14154925bf6Swillf 	/* let NULL be handled by the caller */
14254925bf6Swillf     } else {
14354925bf6Swillf 	result = strdup(value);
14454925bf6Swillf 	/* free profile string */
14554925bf6Swillf 	profile_release_string(value);
14654925bf6Swillf     }
14754925bf6Swillf 
14854925bf6Swillf     return result;
14954925bf6Swillf }
15054925bf6Swillf 
15154925bf6Swillf static char *
kdb_get_library_name(krb5_context kcontext)15254925bf6Swillf kdb_get_library_name(krb5_context kcontext)
15354925bf6Swillf {
15454925bf6Swillf     krb5_error_code status = 0;
15554925bf6Swillf     char   *result = NULL;
15654925bf6Swillf     char   *value = NULL;
15754925bf6Swillf     char   *lib = NULL;
15854925bf6Swillf 
15954925bf6Swillf     status = profile_get_string(kcontext->profile,
16054925bf6Swillf 				/* realms */
16154925bf6Swillf 				KDB_REALM_SECTION,
16254925bf6Swillf 				kcontext->default_realm,
16354925bf6Swillf 				/* under the realm name, database_module */
16454925bf6Swillf 				KDB_MODULE_POINTER,
16554925bf6Swillf 				/* default value is the realm name itself */
16654925bf6Swillf 				kcontext->default_realm,
16754925bf6Swillf 				&value);
16854925bf6Swillf     if (status) {
16954925bf6Swillf 	goto clean_n_exit;
17054925bf6Swillf     }
17154925bf6Swillf 
17254925bf6Swillf #define DB2_NAME "db2"
17354925bf6Swillf     /* we got the module section. Get the library name from the module */
17454925bf6Swillf     status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value,
17554925bf6Swillf 				KDB_LIB_POINTER,
17654925bf6Swillf 				/* default to db2 */
17754925bf6Swillf 				DB2_NAME,
17854925bf6Swillf 				&lib);
17954925bf6Swillf 
18054925bf6Swillf     if (status) {
18154925bf6Swillf 	goto clean_n_exit;
18254925bf6Swillf     }
18354925bf6Swillf 
18454925bf6Swillf     result = strdup(lib);
18554925bf6Swillf   clean_n_exit:
18654925bf6Swillf     if (value) {
18754925bf6Swillf 	/* free profile string */
18854925bf6Swillf 	profile_release_string(value);
18954925bf6Swillf     }
19054925bf6Swillf 
19154925bf6Swillf     if (lib) {
19254925bf6Swillf 	/* free profile string */
19354925bf6Swillf 	profile_release_string(lib);
19454925bf6Swillf     }
19554925bf6Swillf     return result;
19654925bf6Swillf }
19754925bf6Swillf 
19854925bf6Swillf static void
kdb_setup_opt_functions(db_library lib)19954925bf6Swillf kdb_setup_opt_functions(db_library lib)
20054925bf6Swillf {
20154925bf6Swillf     if (lib->vftabl.set_master_key == NULL) {
20254925bf6Swillf 	lib->vftabl.set_master_key = kdb_def_set_mkey;
20354925bf6Swillf     }
20454925bf6Swillf 
20554925bf6Swillf     if (lib->vftabl.get_master_key == NULL) {
20654925bf6Swillf 	lib->vftabl.get_master_key = kdb_def_get_mkey;
20754925bf6Swillf     }
20854925bf6Swillf 
20954925bf6Swillf     if (lib->vftabl.fetch_master_key == NULL) {
21054925bf6Swillf 	lib->vftabl.fetch_master_key = krb5_db_def_fetch_mkey;
21154925bf6Swillf     }
21254925bf6Swillf 
21354925bf6Swillf     if (lib->vftabl.verify_master_key == NULL) {
21454925bf6Swillf 	lib->vftabl.verify_master_key = krb5_def_verify_master_key;
21554925bf6Swillf     }
21654925bf6Swillf 
21754925bf6Swillf     if (lib->vftabl.dbe_search_enctype == NULL) {
21854925bf6Swillf 	lib->vftabl.dbe_search_enctype = krb5_dbe_def_search_enctype;
21954925bf6Swillf     }
22054925bf6Swillf 
22154925bf6Swillf     if (lib->vftabl.db_change_pwd == NULL) {
22254925bf6Swillf 	lib->vftabl.db_change_pwd = krb5_dbe_def_cpw;
22354925bf6Swillf     }
22454925bf6Swillf 
22554925bf6Swillf     if (lib->vftabl.store_master_key == NULL) {
22654925bf6Swillf 	lib->vftabl.store_master_key = krb5_def_store_mkey;
22754925bf6Swillf     }
22854925bf6Swillf 
22954925bf6Swillf     if (lib->vftabl.promote_db == NULL) {
23054925bf6Swillf 	lib->vftabl.promote_db = krb5_def_promote_db;
23154925bf6Swillf     }
23254925bf6Swillf }
23354925bf6Swillf 
23454925bf6Swillf static int kdb_db2_pol_err_loaded = 0;
23554925bf6Swillf #ifdef _KDB5_STATIC_LINK
23654925bf6Swillf #define DEF_SYMBOL(a) extern kdb_vftabl krb5_db_vftabl_ ## a
23754925bf6Swillf #define GET_SYMBOL(a) (krb5_db_vftabl_ ## a)
23854925bf6Swillf static krb5_error_code
kdb_load_library(krb5_context kcontext,char * lib_name,db_library * lib)23954925bf6Swillf kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
24054925bf6Swillf {
24154925bf6Swillf     krb5_error_code status;
24254925bf6Swillf     void   *vftabl_addr = NULL;
24354925bf6Swillf     char    buf[KRB5_MAX_ERR_STR];
24454925bf6Swillf 
24554925bf6Swillf     if (!strcmp("kdb_db2", lib_name) && (kdb_db2_pol_err_loaded == 0)) {
24654925bf6Swillf 	initialize_adb_error_table();
24754925bf6Swillf 	kdb_db2_pol_err_loaded = 1;
24854925bf6Swillf     }
24954925bf6Swillf 
25054925bf6Swillf     *lib = calloc((size_t) 1, sizeof(**lib));
25154925bf6Swillf     if (*lib == NULL) {
25254925bf6Swillf 	status = ENOMEM;
25354925bf6Swillf 	goto clean_n_exit;
25454925bf6Swillf     }
25554925bf6Swillf 
25654925bf6Swillf     status = kdb_init_lib_lock(*lib);
25754925bf6Swillf     if (status) {
25854925bf6Swillf 	goto clean_n_exit;
25954925bf6Swillf     }
26054925bf6Swillf 
26154925bf6Swillf     strcpy((*lib)->name, lib_name);
26254925bf6Swillf 
26354925bf6Swillf #if !defined(KDB5_USE_LIB_KDB_DB2) && !defined(KDB5_USE_LIB_TEST)
26454925bf6Swillf #error No database module defined
26554925bf6Swillf #endif
26654925bf6Swillf 
26754925bf6Swillf #ifdef KDB5_USE_LIB_KDB_DB2
26854925bf6Swillf     if (strcmp(lib_name, "kdb_db2") == 0) {
26954925bf6Swillf 	DEF_SYMBOL(kdb_db2);
27054925bf6Swillf 	vftabl_addr = (void *) &GET_SYMBOL(kdb_db2);
27154925bf6Swillf     } else
27254925bf6Swillf #endif
27354925bf6Swillf #ifdef KDB5_USE_LIB_TEST
27454925bf6Swillf     if (strcmp(lib_name, "test") == 0) {
27554925bf6Swillf 	DEF_SYMBOL(test);
27654925bf6Swillf 	vftabl_addr = (void *) &GET_SYMBOL(test);
27754925bf6Swillf     } else
27854925bf6Swillf #endif
27954925bf6Swillf     {
28054925bf6Swillf 	snprintf(buf, sizeof(buf), gettext("Program not built to support %s database type\n"),
28154925bf6Swillf 		lib_name);
28254925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOSUP;
28354925bf6Swillf 	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
28454925bf6Swillf 	goto clean_n_exit;
28554925bf6Swillf     }
28654925bf6Swillf 
28754925bf6Swillf     memcpy(&(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
28854925bf6Swillf 
28954925bf6Swillf     kdb_setup_opt_functions(*lib);
29054925bf6Swillf 
29154925bf6Swillf     if ((status = (*lib)->vftabl.init_library())) {
29254925bf6Swillf 	/* ERROR. library not initialized cleanly */
29354925bf6Swillf 	snprintf(buf, sizeof(buf), gettext("%s library initialization failed, error code %ld\n"),
29454925bf6Swillf 		lib_name, status);
29554925bf6Swillf 	status = KRB5_KDB_DBTYPE_INIT;
29654925bf6Swillf 	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
29754925bf6Swillf 	goto clean_n_exit;
29854925bf6Swillf     }
29954925bf6Swillf 
30054925bf6Swillf   clean_n_exit:
30154925bf6Swillf     if (status) {
30254925bf6Swillf 	free(*lib), *lib = NULL;
30354925bf6Swillf     }
30454925bf6Swillf     return status;
30554925bf6Swillf }
30654925bf6Swillf 
30754925bf6Swillf #else /* KDB5_STATIC_LINK*/
30854925bf6Swillf 
30954925bf6Swillf static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH;
31054925bf6Swillf #define db_dl_n_locations (sizeof(db_dl_location) / sizeof(db_dl_location[0]))
31154925bf6Swillf 
31254925bf6Swillf static krb5_error_code
kdb_load_library(krb5_context kcontext,char * lib_name,db_library * lib)31354925bf6Swillf kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
31454925bf6Swillf {
31554925bf6Swillf     krb5_error_code status = 0;
31654925bf6Swillf     int     ndx;
31754925bf6Swillf     void  **vftabl_addrs = NULL;
31854925bf6Swillf     /* N.B.: If this is "const" but not "static", the Solaris 10
31954925bf6Swillf        native compiler has trouble building the library because of
32054925bf6Swillf        absolute relocations needed in read-only section ".rodata".
32154925bf6Swillf        When it's static, it goes into ".picdata", which is
32254925bf6Swillf        read-write.  */
32354925bf6Swillf     static const char *const dbpath_names[] = {
32454925bf6Swillf 	KDB_MODULE_SECTION, "db_module_dir", NULL,
32554925bf6Swillf     };
32654925bf6Swillf     const char *filebases[2];
32754925bf6Swillf     char **profpath = NULL;
32854925bf6Swillf     char **path = NULL;
32954925bf6Swillf 
33054925bf6Swillf     filebases[0] = lib_name;
33154925bf6Swillf     filebases[1] = NULL;
33254925bf6Swillf 
33354925bf6Swillf     if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
33454925bf6Swillf 	initialize_adb_error_table();
33554925bf6Swillf 	kdb_db2_pol_err_loaded = 1;
33654925bf6Swillf     }
33754925bf6Swillf 
33854925bf6Swillf     *lib = calloc((size_t) 1, sizeof(**lib));
33954925bf6Swillf     if (*lib == NULL) {
34054925bf6Swillf 	status = ENOMEM;
34154925bf6Swillf 	goto clean_n_exit;
34254925bf6Swillf     }
34354925bf6Swillf 
34454925bf6Swillf     status = kdb_init_lib_lock(*lib);
34554925bf6Swillf     if (status) {
34654925bf6Swillf 	goto clean_n_exit;
34754925bf6Swillf     }
34854925bf6Swillf 
34954925bf6Swillf     strcpy((*lib)->name, lib_name);
35054925bf6Swillf 
35154925bf6Swillf     /* Fetch the list of directories specified in the config
35254925bf6Swillf        file(s) first.  */
35354925bf6Swillf     status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
35454925bf6Swillf     if (status != 0 && status != PROF_NO_RELATION)
35554925bf6Swillf 	goto clean_n_exit;
35654925bf6Swillf     ndx = 0;
35754925bf6Swillf     if (profpath)
35854925bf6Swillf 	while (profpath[ndx] != NULL)
35954925bf6Swillf 	    ndx++;
36054925bf6Swillf 
36154925bf6Swillf     path = calloc(ndx + db_dl_n_locations, sizeof (char *));
36254925bf6Swillf     if (path == NULL) {
36354925bf6Swillf 	status = errno;
36454925bf6Swillf 	goto clean_n_exit;
36554925bf6Swillf     }
36654925bf6Swillf     if (ndx)
36754925bf6Swillf 	memcpy(path, profpath, ndx * sizeof(profpath[0]));
36854925bf6Swillf     memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
36954925bf6Swillf     status = 0;
37054925bf6Swillf 
37154925bf6Swillf     if ((status = krb5int_open_plugin_dirs ((const char **) path,
37254925bf6Swillf                                             filebases,
37354925bf6Swillf                                             &(*lib)->dl_dir_handle, &kcontext->err))) {
37454925bf6Swillf         const char *err_str = krb5_get_error_message(kcontext, status);
37554925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
37654925bf6Swillf 	krb5_set_error_message (kcontext, status,
37754925bf6Swillf 				gettext("Unable to find requested database type: %s"), err_str);
37854925bf6Swillf 	krb5_free_error_message (kcontext, err_str);
37954925bf6Swillf 	goto clean_n_exit;
38054925bf6Swillf     }
38154925bf6Swillf 
38254925bf6Swillf     if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
38354925bf6Swillf                                                &vftabl_addrs, &kcontext->err))) {
38454925bf6Swillf         const char *err_str = krb5_get_error_message(kcontext, status);
38554925bf6Swillf         status = KRB5_KDB_DBTYPE_INIT;
38654925bf6Swillf         krb5_set_error_message (kcontext, status,
38754925bf6Swillf                                 gettext("plugin symbol 'kdb_function_table' lookup failed: %s"), err_str);
38854925bf6Swillf         krb5_free_error_message (kcontext, err_str);
38954925bf6Swillf 	goto clean_n_exit;
39054925bf6Swillf     }
39154925bf6Swillf 
39254925bf6Swillf     if (vftabl_addrs[0] == NULL) {
39354925bf6Swillf 	/* No plugins! */
39454925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
39554925bf6Swillf 	krb5_set_error_message (kcontext, status,
39654925bf6Swillf 				gettext("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"),
39754925bf6Swillf 				lib_name);
39854925bf6Swillf 	goto clean_n_exit;
39954925bf6Swillf     }
40054925bf6Swillf 
40154925bf6Swillf     memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl));
40254925bf6Swillf     kdb_setup_opt_functions(*lib);
40354925bf6Swillf 
40454925bf6Swillf     if ((status = (*lib)->vftabl.init_library())) {
40554925bf6Swillf         /* ERROR. library not initialized cleanly */
40654925bf6Swillf         goto clean_n_exit;
40754925bf6Swillf     }
40854925bf6Swillf 
40954925bf6Swillf clean_n_exit:
41054925bf6Swillf     if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); }
41154925bf6Swillf     /* Both of these DTRT with NULL.  */
41254925bf6Swillf     profile_free_list(profpath);
41354925bf6Swillf     free(path);
41454925bf6Swillf     if (status) {
41554925bf6Swillf         if (*lib) {
41654925bf6Swillf 	    kdb_destroy_lib_lock(*lib);
41754925bf6Swillf             if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
41854925bf6Swillf                 krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
41954925bf6Swillf             }
42054925bf6Swillf 	    free(*lib);
42154925bf6Swillf 	    *lib = NULL;
42254925bf6Swillf 	}
42354925bf6Swillf     }
42454925bf6Swillf     return status;
42554925bf6Swillf }
42654925bf6Swillf 
42754925bf6Swillf #endif /* end of _KDB5_STATIC_LINK */
42854925bf6Swillf 
42954925bf6Swillf static krb5_error_code
kdb_find_library(krb5_context kcontext,char * lib_name,db_library * lib)43054925bf6Swillf kdb_find_library(krb5_context kcontext, char *lib_name, db_library * lib)
43154925bf6Swillf {
43254925bf6Swillf     /* lock here so that no two threads try to do the same at the same time */
43354925bf6Swillf     krb5_error_code status = 0;
43454925bf6Swillf     int     locked = 0;
43554925bf6Swillf     db_library curr_elt, prev_elt = NULL;
43654925bf6Swillf 
43754925bf6Swillf     if ((status = kdb_lock_list()) != 0) {
43854925bf6Swillf 	goto clean_n_exit;
43954925bf6Swillf     }
44054925bf6Swillf     locked = 1;
44154925bf6Swillf 
44254925bf6Swillf     curr_elt = lib_list;
44354925bf6Swillf     while (curr_elt != NULL) {
44454925bf6Swillf 	if (strcmp(lib_name, curr_elt->name) == 0) {
44554925bf6Swillf 	    *lib = curr_elt;
44654925bf6Swillf 	    goto clean_n_exit;
44754925bf6Swillf 	}
44854925bf6Swillf 	prev_elt = curr_elt;
44954925bf6Swillf 	curr_elt = curr_elt->next;
45054925bf6Swillf     }
45154925bf6Swillf 
45254925bf6Swillf     /* module not found. create and add to list */
45354925bf6Swillf     status = kdb_load_library(kcontext, lib_name, lib);
45454925bf6Swillf     if (status) {
45554925bf6Swillf 	goto clean_n_exit;
45654925bf6Swillf     }
45754925bf6Swillf 
45854925bf6Swillf     if (prev_elt) {
45954925bf6Swillf 	/* prev_elt points to the last element in the list */
46054925bf6Swillf 	prev_elt->next = *lib;
46154925bf6Swillf 	(*lib)->prev = prev_elt;
46254925bf6Swillf     } else {
46354925bf6Swillf 	lib_list = *lib;
46454925bf6Swillf     }
46554925bf6Swillf 
46654925bf6Swillf   clean_n_exit:
46754925bf6Swillf     if (*lib) {
46854925bf6Swillf 	(*lib)->reference_cnt++;
46954925bf6Swillf     }
47054925bf6Swillf 
47154925bf6Swillf     if (locked) {
47254925bf6Swillf 	(void)kdb_unlock_list();
47354925bf6Swillf     }
47454925bf6Swillf 
47554925bf6Swillf     return status;
47654925bf6Swillf }
47754925bf6Swillf 
47854925bf6Swillf static krb5_error_code
kdb_free_library(db_library lib)47954925bf6Swillf kdb_free_library(db_library lib)
48054925bf6Swillf {
48154925bf6Swillf     krb5_error_code status = 0;
48254925bf6Swillf     int     locked = 0;
48354925bf6Swillf 
48454925bf6Swillf     if ((status = kdb_lock_list()) != 0) {
48554925bf6Swillf 	goto clean_n_exit;
48654925bf6Swillf     }
48754925bf6Swillf     locked = 1;
48854925bf6Swillf 
48954925bf6Swillf     lib->reference_cnt--;
49054925bf6Swillf 
49154925bf6Swillf     if (lib->reference_cnt == 0) {
49254925bf6Swillf 	status = lib->vftabl.fini_library();
49354925bf6Swillf 	if (status) {
49454925bf6Swillf 	    goto clean_n_exit;
49554925bf6Swillf 	}
49654925bf6Swillf 
49754925bf6Swillf 	/* close the library */
49854925bf6Swillf         if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle))) {
49954925bf6Swillf             krb5int_close_plugin_dirs (&lib->dl_dir_handle);
50054925bf6Swillf         }
50154925bf6Swillf 
50254925bf6Swillf 	kdb_destroy_lib_lock(lib);
50354925bf6Swillf 
50454925bf6Swillf 	if (lib->prev == NULL) {
50554925bf6Swillf 	    /* first element in the list */
50654925bf6Swillf 	    lib_list = lib->next;
50754925bf6Swillf 	} else {
50854925bf6Swillf 	    lib->prev->next = lib->next;
50954925bf6Swillf 	}
51054925bf6Swillf 
51154925bf6Swillf 	if (lib->next) {
51254925bf6Swillf 	    lib->next->prev = lib->prev;
51354925bf6Swillf 	}
51454925bf6Swillf 	free(lib);
51554925bf6Swillf     }
51654925bf6Swillf 
51754925bf6Swillf   clean_n_exit:
51854925bf6Swillf     if (locked) {
51954925bf6Swillf 	(void)kdb_unlock_list();
52054925bf6Swillf     }
52154925bf6Swillf 
52254925bf6Swillf     return status;
52354925bf6Swillf }
52454925bf6Swillf 
52554925bf6Swillf static krb5_error_code
kdb_setup_lib_handle(krb5_context kcontext)52654925bf6Swillf kdb_setup_lib_handle(krb5_context kcontext)
52754925bf6Swillf {
52854925bf6Swillf     char   *library = NULL;
52954925bf6Swillf     krb5_error_code status = 0;
53054925bf6Swillf     db_library lib = NULL;
53154925bf6Swillf     kdb5_dal_handle *dal_handle = NULL;
53254925bf6Swillf 
53354925bf6Swillf     dal_handle = calloc((size_t) 1, sizeof(kdb5_dal_handle));
53454925bf6Swillf     if (dal_handle == NULL) {
53554925bf6Swillf 	status = ENOMEM;
53654925bf6Swillf 	goto clean_n_exit;
53754925bf6Swillf     }
53854925bf6Swillf 
53954925bf6Swillf     library = kdb_get_library_name(kcontext);
54054925bf6Swillf     if (library == NULL) {
54154925bf6Swillf 	status = KRB5_KDB_DBTYPE_NOTFOUND;
54254925bf6Swillf 	goto clean_n_exit;
54354925bf6Swillf     }
54454925bf6Swillf 
54554925bf6Swillf     status = kdb_find_library(kcontext, library, &lib);
54654925bf6Swillf     if (status) {
54754925bf6Swillf 	goto clean_n_exit;
54854925bf6Swillf     }
54954925bf6Swillf 
55054925bf6Swillf     dal_handle->lib_handle = lib;
55154925bf6Swillf     kcontext->db_context = (void *) dal_handle;
55254925bf6Swillf 
55354925bf6Swillf   clean_n_exit:
55454925bf6Swillf     free(library);
55554925bf6Swillf 
55654925bf6Swillf     if (status) {
55754925bf6Swillf 	free(dal_handle);
55854925bf6Swillf 	if (lib) {
55954925bf6Swillf 	    (void)kdb_free_library(lib);
56054925bf6Swillf 	}
56154925bf6Swillf     }
56254925bf6Swillf 
56354925bf6Swillf     return status;
56454925bf6Swillf }
56554925bf6Swillf 
56654925bf6Swillf static krb5_error_code
kdb_free_lib_handle(krb5_context kcontext)56754925bf6Swillf kdb_free_lib_handle(krb5_context kcontext)
56854925bf6Swillf {
56954925bf6Swillf     krb5_error_code status = 0;
57054925bf6Swillf 
57154925bf6Swillf     status =
57254925bf6Swillf 	kdb_free_library(((kdb5_dal_handle *) kcontext->db_context)->
57354925bf6Swillf 			 lib_handle);
57454925bf6Swillf     if (status) {
57554925bf6Swillf 	goto clean_n_exit;
57654925bf6Swillf     }
57754925bf6Swillf 
57854925bf6Swillf     free(kcontext->db_context);
57954925bf6Swillf     kcontext->db_context = NULL;
58054925bf6Swillf 
58154925bf6Swillf   clean_n_exit:
58254925bf6Swillf     return status;
58354925bf6Swillf }
58454925bf6Swillf 
58554925bf6Swillf static void
get_errmsg(krb5_context kcontext,krb5_error_code err_code)58654925bf6Swillf get_errmsg (krb5_context kcontext, krb5_error_code err_code)
58754925bf6Swillf {
58854925bf6Swillf     kdb5_dal_handle *dal_handle;
58954925bf6Swillf     const char *e;
59054925bf6Swillf     if (err_code == 0)
59154925bf6Swillf 	return;
59254925bf6Swillf     assert(kcontext != NULL);
59354925bf6Swillf     /* Must be called with dal_handle->lib_handle locked!  */
59454925bf6Swillf     assert(kcontext->db_context != NULL);
59554925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
59654925bf6Swillf     if (dal_handle->lib_handle->vftabl.errcode_2_string == NULL)
59754925bf6Swillf 	return;
59854925bf6Swillf     e = dal_handle->lib_handle->vftabl.errcode_2_string(kcontext, err_code);
59954925bf6Swillf     assert (e != NULL);
60054925bf6Swillf     krb5_set_error_message(kcontext, err_code, "%s", e);
60154925bf6Swillf     if (dal_handle->lib_handle->vftabl.release_errcode_string)
60254925bf6Swillf 	dal_handle->lib_handle->vftabl.release_errcode_string(kcontext, e);
60354925bf6Swillf }
60454925bf6Swillf 
60554925bf6Swillf /*
60654925bf6Swillf  *      External functions... DAL API
60754925bf6Swillf  */
60854925bf6Swillf krb5_error_code
krb5_db_open(krb5_context kcontext,char ** db_args,int mode)60954925bf6Swillf krb5_db_open(krb5_context kcontext, char **db_args, int mode)
61054925bf6Swillf {
61154925bf6Swillf     krb5_error_code status = 0;
61254925bf6Swillf     char   *section = NULL;
61354925bf6Swillf     kdb5_dal_handle *dal_handle;
61454925bf6Swillf 
61554925bf6Swillf     section = kdb_get_conf_section(kcontext);
61654925bf6Swillf     if (section == NULL) {
61754925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
61854925bf6Swillf 	krb5_set_error_message (kcontext, status,
61954925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
62054925bf6Swillf 		kcontext->default_realm ? kcontext->default_realm : "[UNSET]");
62154925bf6Swillf 	goto clean_n_exit;
62254925bf6Swillf     }
62354925bf6Swillf 
62454925bf6Swillf     if (kcontext->db_context == NULL) {
62554925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
62654925bf6Swillf 	if (status) {
62754925bf6Swillf 	    goto clean_n_exit;
62854925bf6Swillf 	}
62954925bf6Swillf     }
63054925bf6Swillf 
63154925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
63254925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
63354925bf6Swillf     if (status) {
634*7c64d375Smp153739 	/* Solaris Kerberos */
635*7c64d375Smp153739 	kdb_free_lib_handle(kcontext);
63654925bf6Swillf 	goto clean_n_exit;
63754925bf6Swillf     }
63854925bf6Swillf 
63954925bf6Swillf     status =
64054925bf6Swillf 	dal_handle->lib_handle->vftabl.init_module(kcontext, section, db_args,
64154925bf6Swillf 						   mode);
64254925bf6Swillf     get_errmsg(kcontext, status);
64354925bf6Swillf 
64454925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
64554925bf6Swillf 
646*7c64d375Smp153739     /* Solaris Kerberos */
647*7c64d375Smp153739     if (status)
648*7c64d375Smp153739 	kdb_free_lib_handle(kcontext);
649*7c64d375Smp153739 
65054925bf6Swillf   clean_n_exit:
65154925bf6Swillf     if (section)
65254925bf6Swillf 	free(section);
65354925bf6Swillf     return status;
65454925bf6Swillf }
65554925bf6Swillf 
65654925bf6Swillf krb5_error_code
krb5_db_inited(krb5_context kcontext)65754925bf6Swillf krb5_db_inited(krb5_context kcontext)
65854925bf6Swillf {
65954925bf6Swillf     return !(kcontext && kcontext->db_context &&
66054925bf6Swillf 	     ((kdb5_dal_handle *) kcontext->db_context)->db_context);
66154925bf6Swillf }
66254925bf6Swillf 
66354925bf6Swillf krb5_error_code
krb5_db_create(krb5_context kcontext,char ** db_args)66454925bf6Swillf krb5_db_create(krb5_context kcontext, char **db_args)
66554925bf6Swillf {
66654925bf6Swillf     krb5_error_code status = 0;
66754925bf6Swillf     char   *section = NULL;
66854925bf6Swillf     kdb5_dal_handle *dal_handle;
66954925bf6Swillf 
67054925bf6Swillf     section = kdb_get_conf_section(kcontext);
67154925bf6Swillf     if (section == NULL) {
67254925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
67354925bf6Swillf 	krb5_set_error_message (kcontext, status,
67454925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
67554925bf6Swillf 		kcontext->default_realm);
67654925bf6Swillf 	goto clean_n_exit;
67754925bf6Swillf     }
67854925bf6Swillf 
67954925bf6Swillf     if (kcontext->db_context == NULL) {
68054925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
68154925bf6Swillf 	if (status) {
68254925bf6Swillf 	    goto clean_n_exit;
68354925bf6Swillf 	}
68454925bf6Swillf     }
68554925bf6Swillf 
68654925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
68754925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
68854925bf6Swillf     if (status) {
68954925bf6Swillf 	goto clean_n_exit;
69054925bf6Swillf     }
69154925bf6Swillf 
69254925bf6Swillf     status =
69354925bf6Swillf 	dal_handle->lib_handle->vftabl.db_create(kcontext, section, db_args);
69454925bf6Swillf     get_errmsg(kcontext, status);
69554925bf6Swillf 
69654925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
69754925bf6Swillf 
69854925bf6Swillf   clean_n_exit:
69954925bf6Swillf     if (section)
70054925bf6Swillf 	free(section);
70154925bf6Swillf     return status;
70254925bf6Swillf }
70354925bf6Swillf 
70454925bf6Swillf krb5_error_code
krb5_db_fini(krb5_context kcontext)70554925bf6Swillf krb5_db_fini(krb5_context kcontext)
70654925bf6Swillf {
70754925bf6Swillf     krb5_error_code status = 0;
70854925bf6Swillf     kdb5_dal_handle *dal_handle;
70954925bf6Swillf 
71054925bf6Swillf     if (kcontext->db_context == NULL) {
71154925bf6Swillf 	/* module not loaded. So nothing to be done */
71254925bf6Swillf 	goto clean_n_exit;
71354925bf6Swillf     }
71454925bf6Swillf 
71554925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
71654925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
71754925bf6Swillf     if (status) {
71854925bf6Swillf 	goto clean_n_exit;
71954925bf6Swillf     }
72054925bf6Swillf 
72154925bf6Swillf     status = dal_handle->lib_handle->vftabl.fini_module(kcontext);
72254925bf6Swillf     get_errmsg(kcontext, status);
72354925bf6Swillf 
72454925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
72554925bf6Swillf 
72654925bf6Swillf     if (status) {
72754925bf6Swillf 	goto clean_n_exit;
72854925bf6Swillf     }
72954925bf6Swillf 
73054925bf6Swillf     status = kdb_free_lib_handle(kcontext);
73154925bf6Swillf 
73254925bf6Swillf   clean_n_exit:
73354925bf6Swillf     return status;
73454925bf6Swillf }
73554925bf6Swillf 
73654925bf6Swillf krb5_error_code
krb5_db_destroy(krb5_context kcontext,char ** db_args)73754925bf6Swillf krb5_db_destroy(krb5_context kcontext, char **db_args)
73854925bf6Swillf {
73954925bf6Swillf     krb5_error_code status = 0;
74054925bf6Swillf     char   *section = NULL;
74154925bf6Swillf     kdb5_dal_handle *dal_handle;
74254925bf6Swillf 
74354925bf6Swillf     section = kdb_get_conf_section(kcontext);
74454925bf6Swillf     if (section == NULL) {
74554925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
74654925bf6Swillf 	krb5_set_error_message (kcontext, status,
74754925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
74854925bf6Swillf 		kcontext->default_realm);
74954925bf6Swillf 	goto clean_n_exit;
75054925bf6Swillf     }
75154925bf6Swillf 
75254925bf6Swillf     if (kcontext->db_context == NULL) {
75354925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
75454925bf6Swillf 	if (status) {
75554925bf6Swillf 	    goto clean_n_exit;
75654925bf6Swillf 	}
75754925bf6Swillf     }
75854925bf6Swillf 
75954925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
76054925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
76154925bf6Swillf     if (status) {
76254925bf6Swillf 	goto clean_n_exit;
76354925bf6Swillf     }
76454925bf6Swillf 
76554925bf6Swillf     status =
76654925bf6Swillf 	dal_handle->lib_handle->vftabl.db_destroy(kcontext, section, db_args);
76754925bf6Swillf     get_errmsg(kcontext, status);
76854925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
76954925bf6Swillf 
77054925bf6Swillf   clean_n_exit:
77154925bf6Swillf     if (section)
77254925bf6Swillf 	free(section);
77354925bf6Swillf     return status;
77454925bf6Swillf }
77554925bf6Swillf 
77654925bf6Swillf krb5_error_code
krb5_db_get_age(krb5_context kcontext,char * db_name,time_t * t)77754925bf6Swillf krb5_db_get_age(krb5_context kcontext, char *db_name, time_t * t)
77854925bf6Swillf {
77954925bf6Swillf     krb5_error_code status = 0;
78054925bf6Swillf     kdb5_dal_handle *dal_handle;
78154925bf6Swillf 
78254925bf6Swillf     if (kcontext->db_context == NULL) {
78354925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
78454925bf6Swillf 	if (status) {
78554925bf6Swillf 	    goto clean_n_exit;
78654925bf6Swillf 	}
78754925bf6Swillf     }
78854925bf6Swillf 
78954925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
79054925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
79154925bf6Swillf     if (status) {
79254925bf6Swillf 	goto clean_n_exit;
79354925bf6Swillf     }
79454925bf6Swillf 
79554925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_get_age(kcontext, db_name, t);
79654925bf6Swillf     get_errmsg(kcontext, status);
79754925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
79854925bf6Swillf 
79954925bf6Swillf   clean_n_exit:
80054925bf6Swillf     return status;
80154925bf6Swillf }
80254925bf6Swillf 
80354925bf6Swillf krb5_error_code
krb5_db_set_option(krb5_context kcontext,int option,void * value)80454925bf6Swillf krb5_db_set_option(krb5_context kcontext, int option, void *value)
80554925bf6Swillf {
80654925bf6Swillf     krb5_error_code status = 0;
80754925bf6Swillf     kdb5_dal_handle *dal_handle;
80854925bf6Swillf 
80954925bf6Swillf     if (kcontext->db_context == NULL) {
81054925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
81154925bf6Swillf 	if (status) {
81254925bf6Swillf 	    goto clean_n_exit;
81354925bf6Swillf 	}
81454925bf6Swillf     }
81554925bf6Swillf 
81654925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
81754925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
81854925bf6Swillf     if (status) {
81954925bf6Swillf 	goto clean_n_exit;
82054925bf6Swillf     }
82154925bf6Swillf 
82254925bf6Swillf     status =
82354925bf6Swillf 	dal_handle->lib_handle->vftabl.db_set_option(kcontext, option, value);
82454925bf6Swillf     get_errmsg(kcontext, status);
82554925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
82654925bf6Swillf 
82754925bf6Swillf   clean_n_exit:
82854925bf6Swillf     return status;
82954925bf6Swillf }
83054925bf6Swillf 
83154925bf6Swillf krb5_error_code
krb5_db_lock(krb5_context kcontext,int lock_mode)83254925bf6Swillf krb5_db_lock(krb5_context kcontext, int lock_mode)
83354925bf6Swillf {
83454925bf6Swillf     krb5_error_code status = 0;
83554925bf6Swillf     kdb5_dal_handle *dal_handle;
83654925bf6Swillf 
83754925bf6Swillf     if (kcontext->db_context == NULL) {
83854925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
83954925bf6Swillf 	if (status) {
84054925bf6Swillf 	    goto clean_n_exit;
84154925bf6Swillf 	}
84254925bf6Swillf     }
84354925bf6Swillf 
84454925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
84554925bf6Swillf     /* acquire an exclusive lock, ensures no other thread uses this context */
84654925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, TRUE);
84754925bf6Swillf     if (status) {
84854925bf6Swillf 	goto clean_n_exit;
84954925bf6Swillf     }
85054925bf6Swillf 
85154925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_lock(kcontext, lock_mode);
85254925bf6Swillf     get_errmsg(kcontext, status);
85354925bf6Swillf 
85454925bf6Swillf     /* exclusive lock is still held, so no other thread could use this context */
85554925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
85654925bf6Swillf 
85754925bf6Swillf   clean_n_exit:
85854925bf6Swillf     return status;
85954925bf6Swillf }
86054925bf6Swillf 
86154925bf6Swillf krb5_error_code
krb5_db_unlock(krb5_context kcontext)86254925bf6Swillf krb5_db_unlock(krb5_context kcontext)
86354925bf6Swillf {
86454925bf6Swillf     krb5_error_code status = 0;
86554925bf6Swillf     kdb5_dal_handle *dal_handle;
86654925bf6Swillf 
86754925bf6Swillf     if (kcontext->db_context == NULL) {
86854925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
86954925bf6Swillf 	if (status) {
87054925bf6Swillf 	    goto clean_n_exit;
87154925bf6Swillf 	}
87254925bf6Swillf     }
87354925bf6Swillf 
87454925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
87554925bf6Swillf     /* normal lock acquired and exclusive lock released */
87654925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
87754925bf6Swillf     if (status) {
87854925bf6Swillf 	goto clean_n_exit;
87954925bf6Swillf     }
88054925bf6Swillf 
88154925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_unlock(kcontext);
88254925bf6Swillf     get_errmsg(kcontext, status);
88354925bf6Swillf 
88454925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, TRUE);
88554925bf6Swillf 
88654925bf6Swillf   clean_n_exit:
88754925bf6Swillf     return status;
88854925bf6Swillf }
88954925bf6Swillf 
89054925bf6Swillf krb5_error_code
krb5_db_get_principal(krb5_context kcontext,krb5_const_principal search_for,krb5_db_entry * entries,int * nentries,krb5_boolean * more)89154925bf6Swillf krb5_db_get_principal(krb5_context kcontext,
89254925bf6Swillf 		      krb5_const_principal search_for,
89354925bf6Swillf 		      krb5_db_entry * entries,
89454925bf6Swillf 		      int *nentries, krb5_boolean * more)
89554925bf6Swillf {
89654925bf6Swillf     krb5_error_code status = 0;
89754925bf6Swillf     kdb5_dal_handle *dal_handle;
89854925bf6Swillf 
89954925bf6Swillf     if (kcontext->db_context == NULL) {
90054925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
90154925bf6Swillf 	if (status) {
90254925bf6Swillf 	    goto clean_n_exit;
90354925bf6Swillf 	}
90454925bf6Swillf     }
90554925bf6Swillf 
90654925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
90754925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
90854925bf6Swillf     if (status) {
90954925bf6Swillf 	goto clean_n_exit;
91054925bf6Swillf     }
91154925bf6Swillf 
91254925bf6Swillf     status =
91354925bf6Swillf 	dal_handle->lib_handle->vftabl.db_get_principal(kcontext, search_for,
91454925bf6Swillf 							entries, nentries,
91554925bf6Swillf 							more);
91654925bf6Swillf     get_errmsg(kcontext, status);
91754925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
91854925bf6Swillf 
91954925bf6Swillf   clean_n_exit:
92054925bf6Swillf     return status;
92154925bf6Swillf }
92254925bf6Swillf 
92354925bf6Swillf 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)92454925bf6Swillf krb5_db_get_principal_nolock(krb5_context kcontext,
92554925bf6Swillf 		      krb5_const_principal search_for,
92654925bf6Swillf 		      krb5_db_entry * entries,
92754925bf6Swillf 		      int *nentries, krb5_boolean * more)
92854925bf6Swillf {
92954925bf6Swillf     krb5_error_code status = 0;
93054925bf6Swillf     kdb5_dal_handle *dal_handle;
93154925bf6Swillf 
93254925bf6Swillf     if (kcontext->db_context == NULL) {
93354925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
93454925bf6Swillf 	if (status) {
93554925bf6Swillf 	    goto clean_n_exit;
93654925bf6Swillf 	}
93754925bf6Swillf     }
93854925bf6Swillf 
93954925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
94054925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
94154925bf6Swillf     if (status) {
94254925bf6Swillf 	goto clean_n_exit;
94354925bf6Swillf     }
94454925bf6Swillf 
94554925bf6Swillf     status =
94654925bf6Swillf 	dal_handle->lib_handle->vftabl.db_get_principal_nolock(kcontext,
94754925bf6Swillf 							search_for,
94854925bf6Swillf 							entries, nentries,
94954925bf6Swillf 							more);
95054925bf6Swillf     get_errmsg(kcontext, status);
95154925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
95254925bf6Swillf 
95354925bf6Swillf   clean_n_exit:
95454925bf6Swillf     return status;
95554925bf6Swillf }
95654925bf6Swillf 
95754925bf6Swillf krb5_error_code
krb5_db_free_principal(krb5_context kcontext,krb5_db_entry * entry,int count)95854925bf6Swillf krb5_db_free_principal(krb5_context kcontext, krb5_db_entry * entry, int count)
95954925bf6Swillf {
96054925bf6Swillf     krb5_error_code status = 0;
96154925bf6Swillf     kdb5_dal_handle *dal_handle;
96254925bf6Swillf 
96354925bf6Swillf     if (kcontext->db_context == NULL) {
96454925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
96554925bf6Swillf 	if (status) {
96654925bf6Swillf 	    goto clean_n_exit;
96754925bf6Swillf 	}
96854925bf6Swillf     }
96954925bf6Swillf 
97054925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
97154925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
97254925bf6Swillf     if (status) {
97354925bf6Swillf 	goto clean_n_exit;
97454925bf6Swillf     }
97554925bf6Swillf 
97654925bf6Swillf     status =
97754925bf6Swillf 	dal_handle->lib_handle->vftabl.db_free_principal(kcontext, entry,
97854925bf6Swillf 							 count);
97954925bf6Swillf     get_errmsg(kcontext, status);
98054925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
98154925bf6Swillf 
98254925bf6Swillf   clean_n_exit:
98354925bf6Swillf     return status;
98454925bf6Swillf }
98554925bf6Swillf 
98654925bf6Swillf krb5_error_code
krb5_db_put_principal(krb5_context kcontext,krb5_db_entry * entries,int * nentries)98754925bf6Swillf krb5_db_put_principal(krb5_context kcontext,
98854925bf6Swillf 		      krb5_db_entry * entries, int *nentries)
98954925bf6Swillf {
99054925bf6Swillf     krb5_error_code status = 0;
99154925bf6Swillf     kdb5_dal_handle *dal_handle;
99254925bf6Swillf     char  **db_args = NULL;
99354925bf6Swillf     krb5_tl_data *prev, *curr, *next;
99454925bf6Swillf     int     db_args_size = 0;
99554925bf6Swillf 
99654925bf6Swillf     if (kcontext->db_context == NULL) {
99754925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
99854925bf6Swillf 	if (status) {
99954925bf6Swillf 	    goto clean_n_exit;
100054925bf6Swillf 	}
100154925bf6Swillf     }
100254925bf6Swillf 
100354925bf6Swillf     /* Giving db_args as part of tl data causes, db2 to store the
100454925bf6Swillf        tl_data as such.  To prevent this, tl_data is collated and
100554925bf6Swillf        passed as a sepearte argument. Currently supports only one
100654925bf6Swillf        principal.  but passing it as a seperate argument makes it
100754925bf6Swillf        difficult for kadmin remote to pass arguments to server.  */
100854925bf6Swillf     prev = NULL, curr = entries->tl_data;
100954925bf6Swillf     while (curr) {
101054925bf6Swillf 	if (curr->tl_data_type == KRB5_TL_DB_ARGS) {
101154925bf6Swillf 	    char  **t;
101254925bf6Swillf 	    /* Since this is expected to be NULL terminated string and
101354925bf6Swillf 	       this could come from any client, do a check before
101454925bf6Swillf 	       passing it to db.  */
101554925bf6Swillf 	    if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] !=
101654925bf6Swillf 		'\0') {
101754925bf6Swillf 		/* not null terminated. Dangerous input */
101854925bf6Swillf 		status = EINVAL;
101954925bf6Swillf 		goto clean_n_exit;
102054925bf6Swillf 	    }
102154925bf6Swillf 
102254925bf6Swillf 	    db_args_size++;
102354925bf6Swillf 	    t = realloc(db_args, sizeof(char *) * (db_args_size + 1));	/* 1 for NULL */
102454925bf6Swillf 	    if (t == NULL) {
102554925bf6Swillf 		status = ENOMEM;
102654925bf6Swillf 		goto clean_n_exit;
102754925bf6Swillf 	    }
102854925bf6Swillf 
102954925bf6Swillf 	    db_args = t;
103054925bf6Swillf 	    db_args[db_args_size - 1] = (char *) curr->tl_data_contents;
103154925bf6Swillf 	    db_args[db_args_size] = NULL;
103254925bf6Swillf 
103354925bf6Swillf 	    next = curr->tl_data_next;
103454925bf6Swillf 	    if (prev == NULL) {
103554925bf6Swillf 		/* current node is the first in the linked list. remove it */
103654925bf6Swillf 		entries->tl_data = curr->tl_data_next;
103754925bf6Swillf 	    } else {
103854925bf6Swillf 		prev->tl_data_next = curr->tl_data_next;
103954925bf6Swillf 	    }
104054925bf6Swillf 	    entries->n_tl_data--;
104154925bf6Swillf 	    krb5_db_free(kcontext, curr);
104254925bf6Swillf 
104354925bf6Swillf 	    /* previous does not change */
104454925bf6Swillf 	    curr = next;
104554925bf6Swillf 	} else {
104654925bf6Swillf 	    prev = curr;
104754925bf6Swillf 	    curr = curr->tl_data_next;
104854925bf6Swillf 	}
104954925bf6Swillf     }
105054925bf6Swillf 
105154925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
105254925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
105354925bf6Swillf     if (status) {
105454925bf6Swillf 	goto clean_n_exit;
105554925bf6Swillf     }
105654925bf6Swillf 
105754925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries,
105854925bf6Swillf 							     nentries,
105954925bf6Swillf 							     db_args);
106054925bf6Swillf     get_errmsg(kcontext, status);
106154925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
106254925bf6Swillf 
106354925bf6Swillf   clean_n_exit:
106454925bf6Swillf     while (db_args_size) {
106554925bf6Swillf 	if (db_args[db_args_size - 1])
106654925bf6Swillf 	    krb5_db_free(kcontext, db_args[db_args_size - 1]);
106754925bf6Swillf 
106854925bf6Swillf 	db_args_size--;
106954925bf6Swillf     }
107054925bf6Swillf 
107154925bf6Swillf     if (db_args)
107254925bf6Swillf 	free(db_args);
107354925bf6Swillf 
107454925bf6Swillf     return status;
107554925bf6Swillf }
107654925bf6Swillf 
107754925bf6Swillf krb5_error_code
krb5_db_delete_principal(krb5_context kcontext,krb5_principal search_for,int * nentries)107854925bf6Swillf krb5_db_delete_principal(krb5_context kcontext,
107954925bf6Swillf 			 krb5_principal search_for, int *nentries)
108054925bf6Swillf {
108154925bf6Swillf     krb5_error_code status = 0;
108254925bf6Swillf     kdb5_dal_handle *dal_handle;
108354925bf6Swillf 
108454925bf6Swillf     if (kcontext->db_context == NULL) {
108554925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
108654925bf6Swillf 	if (status) {
108754925bf6Swillf 	    goto clean_n_exit;
108854925bf6Swillf 	}
108954925bf6Swillf     }
109054925bf6Swillf 
109154925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
109254925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
109354925bf6Swillf     if (status) {
109454925bf6Swillf 	goto clean_n_exit;
109554925bf6Swillf     }
109654925bf6Swillf 
109754925bf6Swillf     status =
109854925bf6Swillf 	dal_handle->lib_handle->vftabl.db_delete_principal(kcontext,
109954925bf6Swillf 							   search_for,
110054925bf6Swillf 							   nentries);
110154925bf6Swillf     get_errmsg(kcontext, status);
110254925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
110354925bf6Swillf 
110454925bf6Swillf   clean_n_exit:
110554925bf6Swillf     return status;
110654925bf6Swillf }
110754925bf6Swillf 
110854925bf6Swillf 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)110954925bf6Swillf krb5_db_iterate(krb5_context kcontext,
111054925bf6Swillf 		char *match_entry,
111154925bf6Swillf 		int (*func) (krb5_pointer, krb5_db_entry *),
11122dd2efa5Swillf 		krb5_pointer func_arg,
11132dd2efa5Swillf 		/* Solaris Kerberos: adding support for db_args */
11142dd2efa5Swillf 		char **db_args)
111554925bf6Swillf {
111654925bf6Swillf     krb5_error_code status = 0;
111754925bf6Swillf     kdb5_dal_handle *dal_handle;
111854925bf6Swillf 
111954925bf6Swillf     if (kcontext->db_context == NULL) {
112054925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
112154925bf6Swillf 	if (status) {
112254925bf6Swillf 	    goto clean_n_exit;
112354925bf6Swillf 	}
112454925bf6Swillf     }
112554925bf6Swillf 
112654925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
112754925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
112854925bf6Swillf     if (status) {
112954925bf6Swillf 	goto clean_n_exit;
113054925bf6Swillf     }
113154925bf6Swillf 
11322dd2efa5Swillf     /* Solaris Kerberos: adding support for db_args */
113354925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_iterate(kcontext,
113454925bf6Swillf 						       match_entry,
11352dd2efa5Swillf 						       func, func_arg,
11362dd2efa5Swillf 						       db_args);
113754925bf6Swillf     get_errmsg(kcontext, status);
113854925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
113954925bf6Swillf 
114054925bf6Swillf   clean_n_exit:
114154925bf6Swillf     return status;
114254925bf6Swillf }
114354925bf6Swillf 
114454925bf6Swillf krb5_error_code
krb5_supported_realms(krb5_context kcontext,char ** realms)114554925bf6Swillf krb5_supported_realms(krb5_context kcontext, char **realms)
114654925bf6Swillf {
114754925bf6Swillf     krb5_error_code status = 0;
114854925bf6Swillf     kdb5_dal_handle *dal_handle;
114954925bf6Swillf 
115054925bf6Swillf     if (kcontext->db_context == NULL) {
115154925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
115254925bf6Swillf 	if (status) {
115354925bf6Swillf 	    goto clean_n_exit;
115454925bf6Swillf 	}
115554925bf6Swillf     }
115654925bf6Swillf 
115754925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
115854925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
115954925bf6Swillf     if (status) {
116054925bf6Swillf 	goto clean_n_exit;
116154925bf6Swillf     }
116254925bf6Swillf 
116354925bf6Swillf     status =
116454925bf6Swillf 	dal_handle->lib_handle->vftabl.db_supported_realms(kcontext, realms);
116554925bf6Swillf     get_errmsg(kcontext, status);
116654925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
116754925bf6Swillf 
116854925bf6Swillf   clean_n_exit:
116954925bf6Swillf     return status;
117054925bf6Swillf }
117154925bf6Swillf 
117254925bf6Swillf krb5_error_code
krb5_free_supported_realms(krb5_context kcontext,char ** realms)117354925bf6Swillf krb5_free_supported_realms(krb5_context kcontext, char **realms)
117454925bf6Swillf {
117554925bf6Swillf     krb5_error_code status = 0;
117654925bf6Swillf     kdb5_dal_handle *dal_handle;
117754925bf6Swillf 
117854925bf6Swillf     if (kcontext->db_context == NULL) {
117954925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
118054925bf6Swillf 	if (status) {
118154925bf6Swillf 	    goto clean_n_exit;
118254925bf6Swillf 	}
118354925bf6Swillf     }
118454925bf6Swillf 
118554925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
118654925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
118754925bf6Swillf     if (status) {
118854925bf6Swillf 	goto clean_n_exit;
118954925bf6Swillf     }
119054925bf6Swillf 
119154925bf6Swillf     status =
119254925bf6Swillf 	dal_handle->lib_handle->vftabl.db_free_supported_realms(kcontext,
119354925bf6Swillf 								realms);
119454925bf6Swillf     get_errmsg(kcontext, status);
119554925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
119654925bf6Swillf 
119754925bf6Swillf   clean_n_exit:
119854925bf6Swillf     return status;
119954925bf6Swillf }
120054925bf6Swillf 
120154925bf6Swillf krb5_error_code
krb5_db_set_master_key_ext(krb5_context kcontext,char * pwd,krb5_keyblock * key)120254925bf6Swillf krb5_db_set_master_key_ext(krb5_context kcontext,
120354925bf6Swillf 			   char *pwd, krb5_keyblock * key)
120454925bf6Swillf {
120554925bf6Swillf     krb5_error_code status = 0;
120654925bf6Swillf     kdb5_dal_handle *dal_handle;
120754925bf6Swillf 
120854925bf6Swillf     if (kcontext->db_context == NULL) {
120954925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
121054925bf6Swillf 	if (status) {
121154925bf6Swillf 	    goto clean_n_exit;
121254925bf6Swillf 	}
121354925bf6Swillf     }
121454925bf6Swillf 
121554925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
121654925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
121754925bf6Swillf     if (status) {
121854925bf6Swillf 	goto clean_n_exit;
121954925bf6Swillf     }
122054925bf6Swillf 
122154925bf6Swillf     status = dal_handle->lib_handle->vftabl.set_master_key(kcontext, pwd, key);
122254925bf6Swillf     get_errmsg(kcontext, status);
122354925bf6Swillf 
122454925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
122554925bf6Swillf 
122654925bf6Swillf   clean_n_exit:
122754925bf6Swillf     return status;
122854925bf6Swillf }
122954925bf6Swillf 
123054925bf6Swillf krb5_error_code
krb5_db_set_mkey(krb5_context context,krb5_keyblock * key)123154925bf6Swillf krb5_db_set_mkey(krb5_context context, krb5_keyblock * key)
123254925bf6Swillf {
123354925bf6Swillf     return krb5_db_set_master_key_ext(context, NULL, key);
123454925bf6Swillf }
123554925bf6Swillf 
123654925bf6Swillf krb5_error_code
krb5_db_get_mkey(krb5_context kcontext,krb5_keyblock ** key)123754925bf6Swillf krb5_db_get_mkey(krb5_context kcontext, krb5_keyblock ** key)
123854925bf6Swillf {
123954925bf6Swillf     krb5_error_code status = 0;
124054925bf6Swillf     kdb5_dal_handle *dal_handle;
124154925bf6Swillf 
124254925bf6Swillf     if (kcontext->db_context == NULL) {
124354925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
124454925bf6Swillf 	if (status) {
124554925bf6Swillf 	    goto clean_n_exit;
124654925bf6Swillf 	}
124754925bf6Swillf     }
124854925bf6Swillf 
124954925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
125054925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
125154925bf6Swillf     if (status) {
125254925bf6Swillf 	goto clean_n_exit;
125354925bf6Swillf     }
125454925bf6Swillf 
125554925bf6Swillf     /* Lets use temp key and copy it later to avoid memory problems
125654925bf6Swillf        when freed by the caller.  */
125754925bf6Swillf     status = dal_handle->lib_handle->vftabl.get_master_key(kcontext, key);
125854925bf6Swillf     get_errmsg(kcontext, status);
125954925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
126054925bf6Swillf 
126154925bf6Swillf   clean_n_exit:
126254925bf6Swillf     return status;
126354925bf6Swillf }
126454925bf6Swillf 
126554925bf6Swillf krb5_error_code
krb5_db_store_master_key(krb5_context kcontext,char * db_arg,krb5_principal mname,krb5_keyblock * key,char * master_pwd)126654925bf6Swillf krb5_db_store_master_key(krb5_context kcontext,
126754925bf6Swillf 			 char *db_arg,
126854925bf6Swillf 			 krb5_principal mname,
126954925bf6Swillf 			 krb5_keyblock * key, char *master_pwd)
127054925bf6Swillf {
127154925bf6Swillf     krb5_error_code status = 0;
127254925bf6Swillf     kdb5_dal_handle *dal_handle;
127354925bf6Swillf 
127454925bf6Swillf     if (kcontext->db_context == NULL) {
127554925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
127654925bf6Swillf 	if (status) {
127754925bf6Swillf 	    goto clean_n_exit;
127854925bf6Swillf 	}
127954925bf6Swillf     }
128054925bf6Swillf 
128154925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
128254925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
128354925bf6Swillf     if (status) {
128454925bf6Swillf 	goto clean_n_exit;
128554925bf6Swillf     }
128654925bf6Swillf 
128754925bf6Swillf     status = dal_handle->lib_handle->vftabl.store_master_key(kcontext,
128854925bf6Swillf 							     db_arg,
128954925bf6Swillf 							     mname,
129054925bf6Swillf 							     key, master_pwd);
129154925bf6Swillf     get_errmsg(kcontext, status);
129254925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
129354925bf6Swillf 
129454925bf6Swillf   clean_n_exit:
129554925bf6Swillf     return status;
129654925bf6Swillf }
129754925bf6Swillf 
129854925bf6Swillf char   *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
129954925bf6Swillf char   *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
130054925bf6Swillf 
130154925bf6Swillf 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)130254925bf6Swillf krb5_db_fetch_mkey(krb5_context context,
130354925bf6Swillf 		   krb5_principal mname,
130454925bf6Swillf 		   krb5_enctype etype,
130554925bf6Swillf 		   krb5_boolean fromkeyboard,
130654925bf6Swillf 		   krb5_boolean twice,
130754925bf6Swillf 		   char *db_args, krb5_data * salt, krb5_keyblock * key)
130854925bf6Swillf {
130954925bf6Swillf     krb5_error_code retval;
131054925bf6Swillf     char    password[BUFSIZ];
131154925bf6Swillf     krb5_data pwd;
131254925bf6Swillf     unsigned int size = sizeof(password);
131354925bf6Swillf     int     kvno;
131454925bf6Swillf     krb5_keyblock tmp_key;
131554925bf6Swillf 
131654925bf6Swillf     memset(&tmp_key, 0, sizeof(tmp_key));
131754925bf6Swillf 
131854925bf6Swillf     if (fromkeyboard) {
131954925bf6Swillf 	krb5_data scratch;
132054925bf6Swillf 
132154925bf6Swillf 	if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
132254925bf6Swillf 					 twice ? krb5_mkey_pwd_prompt2 : 0,
132354925bf6Swillf 					 password, &size))) {
132454925bf6Swillf 	    goto clean_n_exit;
132554925bf6Swillf 	}
132654925bf6Swillf 
132754925bf6Swillf 	pwd.data = password;
132854925bf6Swillf 	pwd.length = size;
132954925bf6Swillf 	if (!salt) {
133054925bf6Swillf 	    retval = krb5_principal2salt(context, mname, &scratch);
133154925bf6Swillf 	    if (retval)
133254925bf6Swillf 		goto clean_n_exit;
133354925bf6Swillf 	}
133454925bf6Swillf 	retval =
133554925bf6Swillf 	    krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch,
133654925bf6Swillf 				 key);
133754925bf6Swillf 
133854925bf6Swillf 	if (!salt)
133954925bf6Swillf 	    krb5_xfree(scratch.data);
134054925bf6Swillf 	memset(password, 0, sizeof(password));	/* erase it */
134154925bf6Swillf 
134254925bf6Swillf     } else {
134354925bf6Swillf 	kdb5_dal_handle *dal_handle;
134454925bf6Swillf 
134554925bf6Swillf 	if (context->db_context == NULL) {
134654925bf6Swillf 	    retval = kdb_setup_lib_handle(context);
134754925bf6Swillf 	    if (retval) {
134854925bf6Swillf 		goto clean_n_exit;
134954925bf6Swillf 	    }
135054925bf6Swillf 	}
135154925bf6Swillf 
135254925bf6Swillf 	dal_handle = (kdb5_dal_handle *) context->db_context;
135354925bf6Swillf 	retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
135454925bf6Swillf 	if (retval) {
135554925bf6Swillf 	    goto clean_n_exit;
135654925bf6Swillf 	}
135754925bf6Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
135854925bf6Swillf 	/* Orig MIT */
135954925bf6Swillf 	tmp_key.enctype = key->enctype;
136054925bf6Swillf #else
136154925bf6Swillf 	/* Solaris Kerberos: need to use etype */
136254925bf6Swillf 	tmp_key.enctype = etype;
136354925bf6Swillf #endif /**************** END IFDEF'ed OUT *******************************/
136454925bf6Swillf 	retval = dal_handle->lib_handle->vftabl.fetch_master_key(context,
136554925bf6Swillf 								 mname,
136654925bf6Swillf 								 &tmp_key,
136754925bf6Swillf 								 &kvno,
136854925bf6Swillf 								 db_args);
136954925bf6Swillf 	get_errmsg(context, retval);
137054925bf6Swillf 	kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
137154925bf6Swillf 
137254925bf6Swillf 	if (retval) {
137354925bf6Swillf 	    goto clean_n_exit;
137454925bf6Swillf 	}
137554925bf6Swillf 
137654925bf6Swillf 	key->contents = malloc(tmp_key.length);
137754925bf6Swillf 	if (key->contents == NULL) {
137854925bf6Swillf 	    retval = ENOMEM;
137954925bf6Swillf 	    goto clean_n_exit;
138054925bf6Swillf 	}
138154925bf6Swillf 
138254925bf6Swillf 	key->magic = tmp_key.magic;
138354925bf6Swillf 	key->enctype = tmp_key.enctype;
138454925bf6Swillf 	key->length = tmp_key.length;
138554925bf6Swillf 	memcpy(key->contents, tmp_key.contents, tmp_key.length);
138654925bf6Swillf     }
138754925bf6Swillf 
138854925bf6Swillf   clean_n_exit:
138954925bf6Swillf     if (tmp_key.contents) {
139054925bf6Swillf 	memset(tmp_key.contents, 0, tmp_key.length);
139154925bf6Swillf 	krb5_db_free(context, tmp_key.contents);
139254925bf6Swillf     }
139354925bf6Swillf     return retval;
139454925bf6Swillf }
139554925bf6Swillf 
139654925bf6Swillf krb5_error_code
krb5_db_verify_master_key(krb5_context kcontext,krb5_principal mprinc,krb5_keyblock * mkey)139754925bf6Swillf krb5_db_verify_master_key(krb5_context kcontext,
139854925bf6Swillf 			  krb5_principal mprinc, krb5_keyblock * mkey)
139954925bf6Swillf {
140054925bf6Swillf     krb5_error_code status = 0;
140154925bf6Swillf     kdb5_dal_handle *dal_handle;
140254925bf6Swillf 
140354925bf6Swillf     if (kcontext->db_context == NULL) {
140454925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
140554925bf6Swillf 	if (status) {
140654925bf6Swillf 	    goto clean_n_exit;
140754925bf6Swillf 	}
140854925bf6Swillf     }
140954925bf6Swillf 
141054925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
141154925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
141254925bf6Swillf     if (status) {
141354925bf6Swillf 	goto clean_n_exit;
141454925bf6Swillf     }
141554925bf6Swillf 
141654925bf6Swillf     status = dal_handle->lib_handle->vftabl.verify_master_key(kcontext,
141754925bf6Swillf 							      mprinc, mkey);
141854925bf6Swillf     get_errmsg(kcontext, status);
141954925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
142054925bf6Swillf 
142154925bf6Swillf   clean_n_exit:
142254925bf6Swillf     return status;
142354925bf6Swillf }
142454925bf6Swillf 
142554925bf6Swillf void   *
krb5_db_alloc(krb5_context kcontext,void * ptr,size_t size)142654925bf6Swillf krb5_db_alloc(krb5_context kcontext, void *ptr, size_t size)
142754925bf6Swillf {
142854925bf6Swillf     krb5_error_code status;
142954925bf6Swillf     kdb5_dal_handle *dal_handle;
143054925bf6Swillf     void   *new_ptr = NULL;
143154925bf6Swillf 
143254925bf6Swillf     if (kcontext->db_context == NULL) {
143354925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
143454925bf6Swillf 	if (status) {
143554925bf6Swillf 	    goto clean_n_exit;
143654925bf6Swillf 	}
143754925bf6Swillf     }
143854925bf6Swillf 
143954925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
144054925bf6Swillf 
144154925bf6Swillf     new_ptr = dal_handle->lib_handle->vftabl.db_alloc(kcontext, ptr, size);
144254925bf6Swillf 
144354925bf6Swillf   clean_n_exit:
144454925bf6Swillf     return new_ptr;
144554925bf6Swillf }
144654925bf6Swillf 
144754925bf6Swillf void
krb5_db_free(krb5_context kcontext,void * ptr)144854925bf6Swillf krb5_db_free(krb5_context kcontext, void *ptr)
144954925bf6Swillf {
145054925bf6Swillf     krb5_error_code status;
145154925bf6Swillf     kdb5_dal_handle *dal_handle;
145254925bf6Swillf 
145354925bf6Swillf     if (kcontext->db_context == NULL) {
145454925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
145554925bf6Swillf 	if (status) {
145654925bf6Swillf 	    goto clean_n_exit;
145754925bf6Swillf 	}
145854925bf6Swillf     }
145954925bf6Swillf 
146054925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
146154925bf6Swillf 
146254925bf6Swillf     dal_handle->lib_handle->vftabl.db_free(kcontext, ptr);
146354925bf6Swillf 
146454925bf6Swillf   clean_n_exit:
146554925bf6Swillf     return;
146654925bf6Swillf }
146754925bf6Swillf 
146854925bf6Swillf /* has to be modified */
146954925bf6Swillf 
147054925bf6Swillf 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)147154925bf6Swillf krb5_dbe_find_enctype(krb5_context kcontext,
147254925bf6Swillf 		      krb5_db_entry * dbentp,
147354925bf6Swillf 		      krb5_int32 ktype,
147454925bf6Swillf 		      krb5_int32 stype,
147554925bf6Swillf 		      krb5_int32 kvno, krb5_key_data ** kdatap)
147654925bf6Swillf {
147754925bf6Swillf     krb5_int32 start = 0;
147854925bf6Swillf     return krb5_dbe_search_enctype(kcontext, dbentp, &start, ktype, stype,
147954925bf6Swillf 				   kvno, kdatap);
148054925bf6Swillf }
148154925bf6Swillf 
148254925bf6Swillf 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)148354925bf6Swillf krb5_dbe_search_enctype(krb5_context kcontext,
148454925bf6Swillf 			krb5_db_entry * dbentp,
148554925bf6Swillf 			krb5_int32 * start,
148654925bf6Swillf 			krb5_int32 ktype,
148754925bf6Swillf 			krb5_int32 stype,
148854925bf6Swillf 			krb5_int32 kvno, krb5_key_data ** kdatap)
148954925bf6Swillf {
149054925bf6Swillf     krb5_error_code status = 0;
149154925bf6Swillf     kdb5_dal_handle *dal_handle;
149254925bf6Swillf 
149354925bf6Swillf     if (kcontext->db_context == NULL) {
149454925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
149554925bf6Swillf 	if (status) {
149654925bf6Swillf 	    goto clean_n_exit;
149754925bf6Swillf 	}
149854925bf6Swillf     }
149954925bf6Swillf 
150054925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
150154925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
150254925bf6Swillf     if (status) {
150354925bf6Swillf 	goto clean_n_exit;
150454925bf6Swillf     }
150554925bf6Swillf 
150654925bf6Swillf     status = dal_handle->lib_handle->vftabl.dbe_search_enctype(kcontext,
150754925bf6Swillf 							       dbentp,
150854925bf6Swillf 							       start,
150954925bf6Swillf 							       ktype,
151054925bf6Swillf 							       stype,
151154925bf6Swillf 							       kvno, kdatap);
151254925bf6Swillf     get_errmsg(kcontext, status);
151354925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
151454925bf6Swillf 
151554925bf6Swillf   clean_n_exit:
151654925bf6Swillf     return status;
151754925bf6Swillf }
151854925bf6Swillf 
151954925bf6Swillf #define	REALM_SEP_STRING	"@"
152054925bf6Swillf 
152154925bf6Swillf krb5_error_code
krb5_db_setup_mkey_name(krb5_context context,const char * keyname,const char * realm,char ** fullname,krb5_principal * principal)152254925bf6Swillf krb5_db_setup_mkey_name(krb5_context context,
152354925bf6Swillf 			const char *keyname,
152454925bf6Swillf 			const char *realm,
152554925bf6Swillf 			char **fullname, krb5_principal * principal)
152654925bf6Swillf {
152754925bf6Swillf     krb5_error_code retval;
152854925bf6Swillf     size_t  keylen;
152954925bf6Swillf     size_t  rlen = strlen(realm);
153054925bf6Swillf     char   *fname;
153154925bf6Swillf 
153254925bf6Swillf     if (!keyname)
153354925bf6Swillf 	keyname = KRB5_KDB_M_NAME;	/* XXX external? */
153454925bf6Swillf 
153554925bf6Swillf     keylen = strlen(keyname);
153654925bf6Swillf 
153754925bf6Swillf     fname = malloc(keylen + rlen + strlen(REALM_SEP_STRING) + 1);
153854925bf6Swillf     if (!fname)
153954925bf6Swillf 	return ENOMEM;
154054925bf6Swillf 
154154925bf6Swillf     strcpy(fname, keyname);
154254925bf6Swillf     (void)strcat(fname, REALM_SEP_STRING);
154354925bf6Swillf     (void)strcat(fname, realm);
154454925bf6Swillf 
154554925bf6Swillf     if ((retval = krb5_parse_name(context, fname, principal)))
154654925bf6Swillf 	return retval;
154754925bf6Swillf     if (fullname)
154854925bf6Swillf 	*fullname = fname;
154954925bf6Swillf     else
155054925bf6Swillf 	free(fname);
155154925bf6Swillf     return 0;
155254925bf6Swillf }
155354925bf6Swillf 
155454925bf6Swillf krb5_error_code
krb5_dbe_lookup_last_pwd_change(context,entry,stamp)155554925bf6Swillf krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
155654925bf6Swillf     krb5_context context;
155754925bf6Swillf     krb5_db_entry *entry;
155854925bf6Swillf     krb5_timestamp *stamp;
155954925bf6Swillf {
156054925bf6Swillf     krb5_tl_data tl_data;
156154925bf6Swillf     krb5_error_code code;
156254925bf6Swillf     krb5_int32 tmp;
156354925bf6Swillf 
156454925bf6Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
156554925bf6Swillf 
156654925bf6Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
156754925bf6Swillf 	return (code);
156854925bf6Swillf 
156954925bf6Swillf     if (tl_data.tl_data_length != 4) {
157054925bf6Swillf 	*stamp = 0;
157154925bf6Swillf 	return (0);
157254925bf6Swillf     }
157354925bf6Swillf 
157454925bf6Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
157554925bf6Swillf 
157654925bf6Swillf     *stamp = (krb5_timestamp) tmp;
157754925bf6Swillf 
157854925bf6Swillf     return (0);
157954925bf6Swillf }
158054925bf6Swillf 
158154925bf6Swillf /*ARGSUSED*/
158254925bf6Swillf krb5_error_code
krb5_dbe_lookup_tl_data(context,entry,ret_tl_data)158354925bf6Swillf krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
158454925bf6Swillf     krb5_context context;
158554925bf6Swillf     krb5_db_entry *entry;
158654925bf6Swillf     krb5_tl_data *ret_tl_data;
158754925bf6Swillf {
158854925bf6Swillf     krb5_tl_data *tl_data;
158954925bf6Swillf 
159054925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
159154925bf6Swillf 	if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
159254925bf6Swillf 	    *ret_tl_data = *tl_data;
159354925bf6Swillf 	    return (0);
159454925bf6Swillf 	}
159554925bf6Swillf     }
159654925bf6Swillf 
159754925bf6Swillf     /* if the requested record isn't found, return zero bytes.
159854925bf6Swillf      * if it ever means something to have a zero-length tl_data,
159954925bf6Swillf      * this code and its callers will have to be changed */
160054925bf6Swillf 
160154925bf6Swillf     ret_tl_data->tl_data_length = 0;
160254925bf6Swillf     ret_tl_data->tl_data_contents = NULL;
160354925bf6Swillf     return (0);
160454925bf6Swillf }
160554925bf6Swillf 
160654925bf6Swillf krb5_error_code
krb5_dbe_create_key_data(context,entry)160754925bf6Swillf krb5_dbe_create_key_data(context, entry)
160854925bf6Swillf     krb5_context context;
160954925bf6Swillf     krb5_db_entry *entry;
161054925bf6Swillf {
161154925bf6Swillf     if ((entry->key_data =
161254925bf6Swillf 	 (krb5_key_data *) krb5_db_alloc(context, entry->key_data,
161354925bf6Swillf 					 (sizeof(krb5_key_data) *
161454925bf6Swillf 					  (entry->n_key_data + 1)))) == NULL)
161554925bf6Swillf 	return (ENOMEM);
161654925bf6Swillf 
161754925bf6Swillf     memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
161854925bf6Swillf     entry->n_key_data++;
161954925bf6Swillf 
162054925bf6Swillf     return 0;
162154925bf6Swillf }
162254925bf6Swillf 
162354925bf6Swillf krb5_error_code
krb5_dbe_update_mod_princ_data(context,entry,mod_date,mod_princ)162454925bf6Swillf krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
162554925bf6Swillf     krb5_context context;
162654925bf6Swillf     krb5_db_entry *entry;
162754925bf6Swillf     krb5_timestamp mod_date;
162854925bf6Swillf     krb5_const_principal mod_princ;
162954925bf6Swillf {
163054925bf6Swillf     krb5_tl_data tl_data;
163154925bf6Swillf 
163254925bf6Swillf     krb5_error_code retval = 0;
163354925bf6Swillf     krb5_octet *nextloc = 0;
163454925bf6Swillf     char   *unparse_mod_princ = 0;
163554925bf6Swillf     unsigned int unparse_mod_princ_size;
163654925bf6Swillf 
163754925bf6Swillf     if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ)))
163854925bf6Swillf 	return (retval);
163954925bf6Swillf 
164054925bf6Swillf     unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
164154925bf6Swillf 
164254925bf6Swillf     if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
164354925bf6Swillf 	== NULL) {
164454925bf6Swillf 	free(unparse_mod_princ);
164554925bf6Swillf 	return (ENOMEM);
164654925bf6Swillf     }
164754925bf6Swillf 
164854925bf6Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
164954925bf6Swillf     tl_data.tl_data_length = unparse_mod_princ_size + 4;
165054925bf6Swillf     tl_data.tl_data_contents = nextloc;
165154925bf6Swillf 
165254925bf6Swillf     /* Mod Date */
165354925bf6Swillf     krb5_kdb_encode_int32(mod_date, nextloc);
165454925bf6Swillf 
165554925bf6Swillf     /* Mod Princ */
165654925bf6Swillf     memcpy(nextloc + 4, unparse_mod_princ, unparse_mod_princ_size);
165754925bf6Swillf 
165854925bf6Swillf     retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
165954925bf6Swillf 
166054925bf6Swillf     free(unparse_mod_princ);
166154925bf6Swillf     free(nextloc);
166254925bf6Swillf 
166354925bf6Swillf     return (retval);
166454925bf6Swillf }
166554925bf6Swillf 
166654925bf6Swillf krb5_error_code
krb5_dbe_lookup_mod_princ_data(context,entry,mod_time,mod_princ)166754925bf6Swillf krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
166854925bf6Swillf     krb5_context context;
166954925bf6Swillf     krb5_db_entry *entry;
167054925bf6Swillf     krb5_timestamp *mod_time;
167154925bf6Swillf     krb5_principal *mod_princ;
167254925bf6Swillf {
167354925bf6Swillf     krb5_tl_data tl_data;
167454925bf6Swillf     krb5_error_code code;
167554925bf6Swillf 
167654925bf6Swillf     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
167754925bf6Swillf 
167854925bf6Swillf     if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
167954925bf6Swillf 	return (code);
168054925bf6Swillf 
168154925bf6Swillf     if ((tl_data.tl_data_length < 5) ||
168254925bf6Swillf 	(tl_data.tl_data_contents[tl_data.tl_data_length - 1] != '\0'))
168354925bf6Swillf 	return (KRB5_KDB_TRUNCATED_RECORD);
168454925bf6Swillf 
168554925bf6Swillf     /* Mod Date */
168654925bf6Swillf     krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
168754925bf6Swillf 
168854925bf6Swillf     /* Mod Princ */
168954925bf6Swillf     if ((code = krb5_parse_name(context,
169054925bf6Swillf 				(const char *) (tl_data.tl_data_contents + 4),
169154925bf6Swillf 				mod_princ)))
169254925bf6Swillf 	return (code);
169354925bf6Swillf 
169454925bf6Swillf     return (0);
169554925bf6Swillf }
169654925bf6Swillf 
169754925bf6Swillf krb5_error_code
krb5_dbe_update_last_pwd_change(context,entry,stamp)169854925bf6Swillf krb5_dbe_update_last_pwd_change(context, entry, stamp)
169954925bf6Swillf     krb5_context context;
170054925bf6Swillf     krb5_db_entry *entry;
170154925bf6Swillf     krb5_timestamp stamp;
170254925bf6Swillf {
170354925bf6Swillf     krb5_tl_data tl_data;
170454925bf6Swillf     krb5_octet buf[4];		/* this is the encoded size of an int32 */
170554925bf6Swillf 
170654925bf6Swillf     tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
170754925bf6Swillf     tl_data.tl_data_length = sizeof(buf);
170854925bf6Swillf     krb5_kdb_encode_int32((krb5_int32) stamp, buf);
170954925bf6Swillf     tl_data.tl_data_contents = buf;
171054925bf6Swillf 
171154925bf6Swillf     return (krb5_dbe_update_tl_data(context, entry, &tl_data));
171254925bf6Swillf }
171354925bf6Swillf 
171454925bf6Swillf krb5_error_code
krb5_dbe_update_tl_data(context,entry,new_tl_data)171554925bf6Swillf krb5_dbe_update_tl_data(context, entry, new_tl_data)
171654925bf6Swillf     krb5_context context;
171754925bf6Swillf     krb5_db_entry *entry;
171854925bf6Swillf     krb5_tl_data *new_tl_data;
171954925bf6Swillf {
172054925bf6Swillf     krb5_tl_data *tl_data = NULL;
172154925bf6Swillf     krb5_octet *tmp;
172254925bf6Swillf 
172354925bf6Swillf     /* copy the new data first, so we can fail cleanly if malloc()
172454925bf6Swillf      * fails */
172554925bf6Swillf     if ((tmp =
172654925bf6Swillf 	 (krb5_octet *) krb5_db_alloc(context, NULL,
172754925bf6Swillf 				      new_tl_data->tl_data_length)) == NULL)
172854925bf6Swillf 	return (ENOMEM);
172954925bf6Swillf 
173054925bf6Swillf     /* Find an existing entry of the specified type and point at
173154925bf6Swillf      * it, or NULL if not found */
173254925bf6Swillf 
173354925bf6Swillf     if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) {	/* db_args can be multiple */
173454925bf6Swillf 	for (tl_data = entry->tl_data; tl_data;
173554925bf6Swillf 	     tl_data = tl_data->tl_data_next)
173654925bf6Swillf 	    if (tl_data->tl_data_type == new_tl_data->tl_data_type)
173754925bf6Swillf 		break;
173854925bf6Swillf     }
173954925bf6Swillf 
174054925bf6Swillf     /* if necessary, chain a new record in the beginning and point at it */
174154925bf6Swillf 
174254925bf6Swillf     if (!tl_data) {
174354925bf6Swillf 	if ((tl_data =
174454925bf6Swillf 	     (krb5_tl_data *) krb5_db_alloc(context, NULL,
174554925bf6Swillf 					    sizeof(krb5_tl_data)))
174654925bf6Swillf 	    == NULL) {
174754925bf6Swillf 	    free(tmp);
174854925bf6Swillf 	    return (ENOMEM);
174954925bf6Swillf 	}
175054925bf6Swillf 	memset(tl_data, 0, sizeof(krb5_tl_data));
175154925bf6Swillf 	tl_data->tl_data_next = entry->tl_data;
175254925bf6Swillf 	entry->tl_data = tl_data;
175354925bf6Swillf 	entry->n_tl_data++;
175454925bf6Swillf     }
175554925bf6Swillf 
175654925bf6Swillf     /* fill in the record */
175754925bf6Swillf 
175854925bf6Swillf     if (tl_data->tl_data_contents)
175954925bf6Swillf 	krb5_db_free(context, tl_data->tl_data_contents);
176054925bf6Swillf 
176154925bf6Swillf     tl_data->tl_data_type = new_tl_data->tl_data_type;
176254925bf6Swillf     tl_data->tl_data_length = new_tl_data->tl_data_length;
176354925bf6Swillf     tl_data->tl_data_contents = tmp;
176454925bf6Swillf     memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
176554925bf6Swillf 
176654925bf6Swillf     return (0);
176754925bf6Swillf }
176854925bf6Swillf 
176954925bf6Swillf /* change password functions */
177054925bf6Swillf 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)177154925bf6Swillf krb5_dbe_cpw(krb5_context kcontext,
177254925bf6Swillf 	     krb5_keyblock * master_key,
177354925bf6Swillf 	     krb5_key_salt_tuple * ks_tuple,
177454925bf6Swillf 	     int ks_tuple_count,
177554925bf6Swillf 	     char *passwd,
177654925bf6Swillf 	     int new_kvno, krb5_boolean keepold, krb5_db_entry * db_entry)
177754925bf6Swillf {
177854925bf6Swillf     krb5_error_code status = 0;
177954925bf6Swillf     kdb5_dal_handle *dal_handle;
178054925bf6Swillf 
178154925bf6Swillf     if (kcontext->db_context == NULL) {
178254925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
178354925bf6Swillf 	if (status) {
178454925bf6Swillf 	    goto clean_n_exit;
178554925bf6Swillf 	}
178654925bf6Swillf     }
178754925bf6Swillf 
178854925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
178954925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
179054925bf6Swillf     if (status) {
179154925bf6Swillf 	goto clean_n_exit;
179254925bf6Swillf     }
179354925bf6Swillf 
179454925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_change_pwd(kcontext,
179554925bf6Swillf 							  master_key,
179654925bf6Swillf 							  ks_tuple,
179754925bf6Swillf 							  ks_tuple_count,
179854925bf6Swillf 							  passwd,
179954925bf6Swillf 							  new_kvno,
180054925bf6Swillf 							  keepold, db_entry);
180154925bf6Swillf     get_errmsg(kcontext, status);
180254925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
180354925bf6Swillf 
180454925bf6Swillf   clean_n_exit:
180554925bf6Swillf     return status;
180654925bf6Swillf }
180754925bf6Swillf 
180854925bf6Swillf /* policy management functions */
180954925bf6Swillf krb5_error_code
krb5_db_create_policy(krb5_context kcontext,osa_policy_ent_t policy)181054925bf6Swillf krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)
181154925bf6Swillf {
181254925bf6Swillf     krb5_error_code status = 0;
181354925bf6Swillf     kdb5_dal_handle *dal_handle;
181454925bf6Swillf 
181554925bf6Swillf     if (kcontext->db_context == NULL) {
181654925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
181754925bf6Swillf 	if (status) {
181854925bf6Swillf 	    goto clean_n_exit;
181954925bf6Swillf 	}
182054925bf6Swillf     }
182154925bf6Swillf 
182254925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
182354925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
182454925bf6Swillf     if (status) {
182554925bf6Swillf 	goto clean_n_exit;
182654925bf6Swillf     }
182754925bf6Swillf 
182854925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_create_policy(kcontext, policy);
182954925bf6Swillf     get_errmsg(kcontext, status);
183054925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
183154925bf6Swillf 
183254925bf6Swillf   clean_n_exit:
183354925bf6Swillf     return status;
183454925bf6Swillf }
183554925bf6Swillf 
183654925bf6Swillf krb5_error_code
krb5_db_get_policy(krb5_context kcontext,char * name,osa_policy_ent_t * policy,int * cnt)183754925bf6Swillf krb5_db_get_policy(krb5_context kcontext, char *name,
183854925bf6Swillf 		   osa_policy_ent_t * policy, int *cnt)
183954925bf6Swillf {
184054925bf6Swillf     krb5_error_code status = 0;
184154925bf6Swillf     kdb5_dal_handle *dal_handle;
184254925bf6Swillf 
184354925bf6Swillf     if (kcontext->db_context == NULL) {
184454925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
184554925bf6Swillf 	if (status) {
184654925bf6Swillf 	    goto clean_n_exit;
184754925bf6Swillf 	}
184854925bf6Swillf     }
184954925bf6Swillf 
185054925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
185154925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
185254925bf6Swillf     if (status) {
185354925bf6Swillf 	goto clean_n_exit;
185454925bf6Swillf     }
185554925bf6Swillf 
185654925bf6Swillf     status =
185754925bf6Swillf 	dal_handle->lib_handle->vftabl.db_get_policy(kcontext, name, policy,
185854925bf6Swillf 						     cnt);
185954925bf6Swillf     get_errmsg(kcontext, status);
186054925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
186154925bf6Swillf 
186254925bf6Swillf   clean_n_exit:
186354925bf6Swillf     return status;
186454925bf6Swillf }
186554925bf6Swillf 
186654925bf6Swillf krb5_error_code
krb5_db_put_policy(krb5_context kcontext,osa_policy_ent_t policy)186754925bf6Swillf krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)
186854925bf6Swillf {
186954925bf6Swillf     krb5_error_code status = 0;
187054925bf6Swillf     kdb5_dal_handle *dal_handle;
187154925bf6Swillf 
187254925bf6Swillf     if (kcontext->db_context == NULL) {
187354925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
187454925bf6Swillf 	if (status) {
187554925bf6Swillf 	    goto clean_n_exit;
187654925bf6Swillf 	}
187754925bf6Swillf     }
187854925bf6Swillf 
187954925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
188054925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
188154925bf6Swillf     if (status) {
188254925bf6Swillf 	goto clean_n_exit;
188354925bf6Swillf     }
188454925bf6Swillf 
188554925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_put_policy(kcontext, policy);
188654925bf6Swillf     get_errmsg(kcontext, status);
188754925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
188854925bf6Swillf 
188954925bf6Swillf   clean_n_exit:
189054925bf6Swillf     return status;
189154925bf6Swillf }
189254925bf6Swillf 
189354925bf6Swillf krb5_error_code
krb5_db_iter_policy(krb5_context kcontext,char * match_entry,osa_adb_iter_policy_func func,void * data)189454925bf6Swillf krb5_db_iter_policy(krb5_context kcontext, char *match_entry,
189554925bf6Swillf 		    osa_adb_iter_policy_func func, void *data)
189654925bf6Swillf {
189754925bf6Swillf     krb5_error_code status = 0;
189854925bf6Swillf     kdb5_dal_handle *dal_handle;
189954925bf6Swillf 
190054925bf6Swillf     if (kcontext->db_context == NULL) {
190154925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
190254925bf6Swillf 	if (status) {
190354925bf6Swillf 	    goto clean_n_exit;
190454925bf6Swillf 	}
190554925bf6Swillf     }
190654925bf6Swillf 
190754925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
190854925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
190954925bf6Swillf     if (status) {
191054925bf6Swillf 	goto clean_n_exit;
191154925bf6Swillf     }
191254925bf6Swillf 
191354925bf6Swillf     status =
191454925bf6Swillf 	dal_handle->lib_handle->vftabl.db_iter_policy(kcontext, match_entry,
191554925bf6Swillf 						      func, data);
191654925bf6Swillf     get_errmsg(kcontext, status);
191754925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
191854925bf6Swillf 
191954925bf6Swillf   clean_n_exit:
192054925bf6Swillf     return status;
192154925bf6Swillf }
192254925bf6Swillf 
192354925bf6Swillf krb5_error_code
krb5_db_delete_policy(krb5_context kcontext,char * policy)192454925bf6Swillf krb5_db_delete_policy(krb5_context kcontext, char *policy)
192554925bf6Swillf {
192654925bf6Swillf     krb5_error_code status = 0;
192754925bf6Swillf     kdb5_dal_handle *dal_handle;
192854925bf6Swillf 
192954925bf6Swillf     if (kcontext->db_context == NULL) {
193054925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
193154925bf6Swillf 	if (status) {
193254925bf6Swillf 	    goto clean_n_exit;
193354925bf6Swillf 	}
193454925bf6Swillf     }
193554925bf6Swillf 
193654925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
193754925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
193854925bf6Swillf     if (status) {
193954925bf6Swillf 	goto clean_n_exit;
194054925bf6Swillf     }
194154925bf6Swillf 
194254925bf6Swillf     status = dal_handle->lib_handle->vftabl.db_delete_policy(kcontext, policy);
194354925bf6Swillf     get_errmsg(kcontext, status);
194454925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
194554925bf6Swillf 
194654925bf6Swillf   clean_n_exit:
194754925bf6Swillf     return status;
194854925bf6Swillf }
194954925bf6Swillf 
195054925bf6Swillf void
krb5_db_free_policy(krb5_context kcontext,osa_policy_ent_t policy)195154925bf6Swillf krb5_db_free_policy(krb5_context kcontext, osa_policy_ent_t policy)
195254925bf6Swillf {
195354925bf6Swillf     krb5_error_code status = 0;
195454925bf6Swillf     kdb5_dal_handle *dal_handle;
195554925bf6Swillf 
195654925bf6Swillf     if (kcontext->db_context == NULL) {
195754925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
195854925bf6Swillf 	if (status) {
195954925bf6Swillf 	    goto clean_n_exit;
196054925bf6Swillf 	}
196154925bf6Swillf     }
196254925bf6Swillf 
196354925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
196454925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
196554925bf6Swillf     if (status) {
196654925bf6Swillf 	goto clean_n_exit;
196754925bf6Swillf     }
196854925bf6Swillf 
196954925bf6Swillf     dal_handle->lib_handle->vftabl.db_free_policy(kcontext, policy);
197054925bf6Swillf     get_errmsg(kcontext, status);
197154925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
197254925bf6Swillf 
197354925bf6Swillf   clean_n_exit:
197454925bf6Swillf     return;
197554925bf6Swillf }
197654925bf6Swillf 
197754925bf6Swillf krb5_error_code
krb5_db_promote(krb5_context kcontext,char ** db_args)197854925bf6Swillf krb5_db_promote(krb5_context kcontext, char **db_args)
197954925bf6Swillf {
198054925bf6Swillf     krb5_error_code status = 0;
198154925bf6Swillf     char   *section = NULL;
198254925bf6Swillf     kdb5_dal_handle *dal_handle;
198354925bf6Swillf 
198454925bf6Swillf     section = kdb_get_conf_section(kcontext);
198554925bf6Swillf     if (section == NULL) {
198654925bf6Swillf 	status = KRB5_KDB_SERVER_INTERNAL_ERR;
198754925bf6Swillf 	krb5_set_error_message (kcontext, status,
198854925bf6Swillf 		gettext("unable to determine configuration section for realm %s\n"),
198954925bf6Swillf 		kcontext->default_realm);
199054925bf6Swillf 	goto clean_n_exit;
199154925bf6Swillf     }
199254925bf6Swillf 
199354925bf6Swillf     if (kcontext->db_context == NULL) {
199454925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
199554925bf6Swillf 	if (status) {
199654925bf6Swillf 	    goto clean_n_exit;
199754925bf6Swillf 	}
199854925bf6Swillf     }
199954925bf6Swillf 
200054925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
200154925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
200254925bf6Swillf     if (status) {
200354925bf6Swillf 	goto clean_n_exit;
200454925bf6Swillf     }
200554925bf6Swillf 
200654925bf6Swillf     status =
200754925bf6Swillf 	dal_handle->lib_handle->vftabl.promote_db(kcontext, section, db_args);
200854925bf6Swillf     get_errmsg(kcontext, status);
200954925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
201054925bf6Swillf 
201154925bf6Swillf   clean_n_exit:
201254925bf6Swillf     if (section)
201354925bf6Swillf 	free(section);
201454925bf6Swillf     return status;
201554925bf6Swillf }
201654925bf6Swillf 
201754925bf6Swillf /*
201854925bf6Swillf  * Solaris Kerberos: support for iprop
201954925bf6Swillf  *
202054925bf6Swillf  * Not all KDB plugins support iprop.
202154925bf6Swillf  *
202254925bf6Swillf  * sets iprop_supported to 1 if iprop supportd, 0 otherwise.
202354925bf6Swillf  */
202454925bf6Swillf krb5_error_code
krb5_db_supports_iprop(krb5_context kcontext,int * iprop_supported)202554925bf6Swillf krb5_db_supports_iprop(krb5_context kcontext, int *iprop_supported)
202654925bf6Swillf {
202754925bf6Swillf     krb5_error_code status = 0;
202854925bf6Swillf     kdb5_dal_handle *dal_handle;
202954925bf6Swillf 
203054925bf6Swillf     if (kcontext->db_context == NULL) {
203154925bf6Swillf 	status = kdb_setup_lib_handle(kcontext);
203254925bf6Swillf 	if (status) {
203354925bf6Swillf 	    goto clean_n_exit;
203454925bf6Swillf 	}
203554925bf6Swillf     }
203654925bf6Swillf 
203754925bf6Swillf     dal_handle = (kdb5_dal_handle *) kcontext->db_context;
203854925bf6Swillf     status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
203954925bf6Swillf     if (status) {
204054925bf6Swillf 	goto clean_n_exit;
204154925bf6Swillf     }
204254925bf6Swillf 
204354925bf6Swillf     *iprop_supported = dal_handle->lib_handle->vftabl.iprop_supported;
204454925bf6Swillf     kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
204554925bf6Swillf 
204654925bf6Swillf   clean_n_exit:
204754925bf6Swillf     return status;
204854925bf6Swillf }
2049