dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / krb5 / kdb / kdb5.c
blob69d2a5679da3df2ab33775010047799e2514e57b
1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * Copyright 2006 by the Massachusetts Institute of Technology.
8 * All Rights Reserved.
10 * Export of this software from the United States of America may
11 * require a specific license from the United States Government.
12 * It is the responsibility of any person or organization contemplating
13 * export to obtain such a license before exporting.
15 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
16 * distribute this software and its documentation for any purpose and
17 * without fee is hereby granted, provided that the above copyright
18 * notice appear in all copies and that both that copyright notice and
19 * this permission notice appear in supporting documentation, and that
20 * the name of M.I.T. not be used in advertising or publicity pertaining
21 * to distribution of the software without specific, written prior
22 * permission. Furthermore if you modify this software you must label
23 * your software as modified software and not distribute it in such a
24 * fashion that it might be confused with the original M.I.T. software.
25 * M.I.T. makes no representations about the suitability of
26 * this software for any purpose. It is provided "as is" without express
27 * or implied warranty.
31 * This code was based on code donated to MIT by Novell for
32 * distribution under the MIT license.
35 /*
36 * Include files
39 #include <stdio.h>
40 #include <string.h>
41 #include <k5-int.h>
42 #include <osconf.h>
43 #include "kdb5.h"
44 #include <assert.h>
45 #include "k5-platform.h"
46 #include <libintl.h>
48 /* Currently DB2 policy related errors are exported from DAL. But
49 other databases should set_err function to return string. */
50 #include "adb_err.h"
53 * Type definitions
55 #define KRB5_TL_DB_ARGS 0x7fff
58 * internal static variable
61 static k5_mutex_t db_lock = K5_MUTEX_PARTIAL_INITIALIZER;
63 #ifdef _KDB5_STATIC_LINK
64 #undef _KDB5_DYNAMIC_LINK
65 #else
66 #undef _KDB5_DYNAMIC_LINK
67 /* to avoid redefinition problem */
68 #define _KDB5_DYNAMIC_LINK
69 #endif
71 static db_library lib_list;
74 * Helper Functions
77 MAKE_INIT_FUNCTION(kdb_init_lock_list);
78 MAKE_FINI_FUNCTION(kdb_fini_lock_list);
80 int
81 kdb_init_lock_list(void)
83 return k5_mutex_finish_init(&db_lock);
86 static int
87 kdb_lock_list()
89 int err;
90 err = CALL_INIT_FUNCTION (kdb_init_lock_list);
91 if (err)
92 return err;
93 return k5_mutex_lock(&db_lock);
96 void
97 kdb_fini_lock_list(void)
99 if (INITIALIZER_RAN(kdb_init_lock_list))
100 k5_mutex_destroy(&db_lock);
103 static int
104 kdb_unlock_list()
106 return k5_mutex_unlock(&db_lock);
109 #define kdb_init_lib_lock(a) 0
110 #define kdb_destroy_lib_lock(a) (void)0
111 #define kdb_lock_lib_lock(a, b) 0
112 #define kdb_unlock_lib_lock(a, b) (void)0
114 /* Caller must free result*/
116 static char *
117 kdb_get_conf_section(krb5_context kcontext)
119 krb5_error_code status = 0;
120 char *result = NULL;
121 char *value = NULL;
123 if (kcontext->default_realm == NULL)
124 return NULL;
125 /* The profile has to have been initialized. If the profile was
126 not initialized, expect nothing less than a crash. */
127 status = profile_get_string(kcontext->profile,
128 /* realms */
129 KDB_REALM_SECTION,
130 kcontext->default_realm,
131 /* under the realm name, database_module */
132 KDB_MODULE_POINTER,
133 /* default value is the realm name itself */
134 kcontext->default_realm,
135 &value);
137 if (status) {
138 /* some problem */
139 result = strdup(kcontext->default_realm);
140 /* let NULL be handled by the caller */
141 } else {
142 result = strdup(value);
143 /* free profile string */
144 profile_release_string(value);
147 return result;
150 static char *
151 kdb_get_library_name(krb5_context kcontext)
153 krb5_error_code status = 0;
154 char *result = NULL;
155 char *value = NULL;
156 char *lib = NULL;
158 status = profile_get_string(kcontext->profile,
159 /* realms */
160 KDB_REALM_SECTION,
161 kcontext->default_realm,
162 /* under the realm name, database_module */
163 KDB_MODULE_POINTER,
164 /* default value is the realm name itself */
165 kcontext->default_realm,
166 &value);
167 if (status) {
168 goto clean_n_exit;
171 #define DB2_NAME "db2"
172 /* we got the module section. Get the library name from the module */
173 status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value,
174 KDB_LIB_POINTER,
175 /* default to db2 */
176 DB2_NAME,
177 &lib);
179 if (status) {
180 goto clean_n_exit;
183 result = strdup(lib);
184 clean_n_exit:
185 if (value) {
186 /* free profile string */
187 profile_release_string(value);
190 if (lib) {
191 /* free profile string */
192 profile_release_string(lib);
194 return result;
197 static void
198 kdb_setup_opt_functions(db_library lib)
200 if (lib->vftabl.set_master_key == NULL) {
201 lib->vftabl.set_master_key = kdb_def_set_mkey;
204 if (lib->vftabl.get_master_key == NULL) {
205 lib->vftabl.get_master_key = kdb_def_get_mkey;
208 if (lib->vftabl.fetch_master_key == NULL) {
209 lib->vftabl.fetch_master_key = krb5_db_def_fetch_mkey;
212 if (lib->vftabl.verify_master_key == NULL) {
213 lib->vftabl.verify_master_key = krb5_def_verify_master_key;
216 if (lib->vftabl.dbe_search_enctype == NULL) {
217 lib->vftabl.dbe_search_enctype = krb5_dbe_def_search_enctype;
220 if (lib->vftabl.db_change_pwd == NULL) {
221 lib->vftabl.db_change_pwd = krb5_dbe_def_cpw;
224 if (lib->vftabl.store_master_key == NULL) {
225 lib->vftabl.store_master_key = krb5_def_store_mkey;
228 if (lib->vftabl.promote_db == NULL) {
229 lib->vftabl.promote_db = krb5_def_promote_db;
233 static int kdb_db2_pol_err_loaded = 0;
234 #ifdef _KDB5_STATIC_LINK
235 #define DEF_SYMBOL(a) extern kdb_vftabl krb5_db_vftabl_ ## a
236 #define GET_SYMBOL(a) (krb5_db_vftabl_ ## a)
237 static krb5_error_code
238 kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
240 krb5_error_code status;
241 void *vftabl_addr = NULL;
242 char buf[KRB5_MAX_ERR_STR];
244 if (!strcmp("kdb_db2", lib_name) && (kdb_db2_pol_err_loaded == 0)) {
245 initialize_adb_error_table();
246 kdb_db2_pol_err_loaded = 1;
249 *lib = calloc((size_t) 1, sizeof(**lib));
250 if (*lib == NULL) {
251 status = ENOMEM;
252 goto clean_n_exit;
255 status = kdb_init_lib_lock(*lib);
256 if (status) {
257 goto clean_n_exit;
260 strcpy((*lib)->name, lib_name);
262 #if !defined(KDB5_USE_LIB_KDB_DB2) && !defined(KDB5_USE_LIB_TEST)
263 #error No database module defined
264 #endif
266 #ifdef KDB5_USE_LIB_KDB_DB2
267 if (strcmp(lib_name, "kdb_db2") == 0) {
268 DEF_SYMBOL(kdb_db2);
269 vftabl_addr = (void *) &GET_SYMBOL(kdb_db2);
270 } else
271 #endif
272 #ifdef KDB5_USE_LIB_TEST
273 if (strcmp(lib_name, "test") == 0) {
274 DEF_SYMBOL(test);
275 vftabl_addr = (void *) &GET_SYMBOL(test);
276 } else
277 #endif
279 snprintf(buf, sizeof(buf), gettext("Program not built to support %s database type\n"),
280 lib_name);
281 status = KRB5_KDB_DBTYPE_NOSUP;
282 krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
283 goto clean_n_exit;
286 memcpy(&(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
288 kdb_setup_opt_functions(*lib);
290 if ((status = (*lib)->vftabl.init_library())) {
291 /* ERROR. library not initialized cleanly */
292 snprintf(buf, sizeof(buf), gettext("%s library initialization failed, error code %ld\n"),
293 lib_name, status);
294 status = KRB5_KDB_DBTYPE_INIT;
295 krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
296 goto clean_n_exit;
299 clean_n_exit:
300 if (status) {
301 free(*lib), *lib = NULL;
303 return status;
306 #else /* KDB5_STATIC_LINK*/
308 static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH;
309 #define db_dl_n_locations (sizeof(db_dl_location) / sizeof(db_dl_location[0]))
311 static krb5_error_code
312 kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
314 krb5_error_code status = 0;
315 int ndx;
316 void **vftabl_addrs = NULL;
317 /* N.B.: If this is "const" but not "static", the Solaris 10
318 native compiler has trouble building the library because of
319 absolute relocations needed in read-only section ".rodata".
320 When it's static, it goes into ".picdata", which is
321 read-write. */
322 static const char *const dbpath_names[] = {
323 KDB_MODULE_SECTION, "db_module_dir", NULL,
325 const char *filebases[2];
326 char **profpath = NULL;
327 char **path = NULL;
329 filebases[0] = lib_name;
330 filebases[1] = NULL;
332 if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
333 initialize_adb_error_table();
334 kdb_db2_pol_err_loaded = 1;
337 *lib = calloc((size_t) 1, sizeof(**lib));
338 if (*lib == NULL) {
339 status = ENOMEM;
340 goto clean_n_exit;
343 status = kdb_init_lib_lock(*lib);
344 if (status) {
345 goto clean_n_exit;
348 strcpy((*lib)->name, lib_name);
350 /* Fetch the list of directories specified in the config
351 file(s) first. */
352 status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
353 if (status != 0 && status != PROF_NO_RELATION)
354 goto clean_n_exit;
355 ndx = 0;
356 if (profpath)
357 while (profpath[ndx] != NULL)
358 ndx++;
360 path = calloc(ndx + db_dl_n_locations, sizeof (char *));
361 if (path == NULL) {
362 status = errno;
363 goto clean_n_exit;
365 if (ndx)
366 memcpy(path, profpath, ndx * sizeof(profpath[0]));
367 memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
368 status = 0;
370 if ((status = krb5int_open_plugin_dirs ((const char **) path,
371 filebases,
372 &(*lib)->dl_dir_handle, &kcontext->err))) {
373 const char *err_str = krb5_get_error_message(kcontext, status);
374 status = KRB5_KDB_DBTYPE_NOTFOUND;
375 krb5_set_error_message (kcontext, status,
376 gettext("Unable to find requested database type: %s"), err_str);
377 krb5_free_error_message (kcontext, err_str);
378 goto clean_n_exit;
381 if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
382 &vftabl_addrs, &kcontext->err))) {
383 const char *err_str = krb5_get_error_message(kcontext, status);
384 status = KRB5_KDB_DBTYPE_INIT;
385 krb5_set_error_message (kcontext, status,
386 gettext("plugin symbol 'kdb_function_table' lookup failed: %s"), err_str);
387 krb5_free_error_message (kcontext, err_str);
388 goto clean_n_exit;
391 if (vftabl_addrs[0] == NULL) {
392 /* No plugins! */
393 status = KRB5_KDB_DBTYPE_NOTFOUND;
394 krb5_set_error_message (kcontext, status,
395 gettext("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"),
396 lib_name);
397 goto clean_n_exit;
400 memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl));
401 kdb_setup_opt_functions(*lib);
403 if ((status = (*lib)->vftabl.init_library())) {
404 /* ERROR. library not initialized cleanly */
405 goto clean_n_exit;
408 clean_n_exit:
409 if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); }
410 /* Both of these DTRT with NULL. */
411 profile_free_list(profpath);
412 free(path);
413 if (status) {
414 if (*lib) {
415 kdb_destroy_lib_lock(*lib);
416 if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
417 krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
419 free(*lib);
420 *lib = NULL;
423 return status;
426 #endif /* end of _KDB5_STATIC_LINK */
428 static krb5_error_code
429 kdb_find_library(krb5_context kcontext, char *lib_name, db_library * lib)
431 /* lock here so that no two threads try to do the same at the same time */
432 krb5_error_code status = 0;
433 int locked = 0;
434 db_library curr_elt, prev_elt = NULL;
436 if ((status = kdb_lock_list()) != 0) {
437 goto clean_n_exit;
439 locked = 1;
441 curr_elt = lib_list;
442 while (curr_elt != NULL) {
443 if (strcmp(lib_name, curr_elt->name) == 0) {
444 *lib = curr_elt;
445 goto clean_n_exit;
447 prev_elt = curr_elt;
448 curr_elt = curr_elt->next;
451 /* module not found. create and add to list */
452 status = kdb_load_library(kcontext, lib_name, lib);
453 if (status) {
454 goto clean_n_exit;
457 if (prev_elt) {
458 /* prev_elt points to the last element in the list */
459 prev_elt->next = *lib;
460 (*lib)->prev = prev_elt;
461 } else {
462 lib_list = *lib;
465 clean_n_exit:
466 if (*lib) {
467 (*lib)->reference_cnt++;
470 if (locked) {
471 (void)kdb_unlock_list();
474 return status;
477 static krb5_error_code
478 kdb_free_library(db_library lib)
480 krb5_error_code status = 0;
481 int locked = 0;
483 if ((status = kdb_lock_list()) != 0) {
484 goto clean_n_exit;
486 locked = 1;
488 lib->reference_cnt--;
490 if (lib->reference_cnt == 0) {
491 status = lib->vftabl.fini_library();
492 if (status) {
493 goto clean_n_exit;
496 /* close the library */
497 if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle))) {
498 krb5int_close_plugin_dirs (&lib->dl_dir_handle);
501 kdb_destroy_lib_lock(lib);
503 if (lib->prev == NULL) {
504 /* first element in the list */
505 lib_list = lib->next;
506 } else {
507 lib->prev->next = lib->next;
510 if (lib->next) {
511 lib->next->prev = lib->prev;
513 free(lib);
516 clean_n_exit:
517 if (locked) {
518 (void)kdb_unlock_list();
521 return status;
524 static krb5_error_code
525 kdb_setup_lib_handle(krb5_context kcontext)
527 char *library = NULL;
528 krb5_error_code status = 0;
529 db_library lib = NULL;
530 kdb5_dal_handle *dal_handle = NULL;
532 dal_handle = calloc((size_t) 1, sizeof(kdb5_dal_handle));
533 if (dal_handle == NULL) {
534 status = ENOMEM;
535 goto clean_n_exit;
538 library = kdb_get_library_name(kcontext);
539 if (library == NULL) {
540 status = KRB5_KDB_DBTYPE_NOTFOUND;
541 goto clean_n_exit;
544 status = kdb_find_library(kcontext, library, &lib);
545 if (status) {
546 goto clean_n_exit;
549 dal_handle->lib_handle = lib;
550 kcontext->db_context = (void *) dal_handle;
552 clean_n_exit:
553 free(library);
555 if (status) {
556 free(dal_handle);
557 if (lib) {
558 (void)kdb_free_library(lib);
562 return status;
565 static krb5_error_code
566 kdb_free_lib_handle(krb5_context kcontext)
568 krb5_error_code status = 0;
570 status =
571 kdb_free_library(((kdb5_dal_handle *) kcontext->db_context)->
572 lib_handle);
573 if (status) {
574 goto clean_n_exit;
577 free(kcontext->db_context);
578 kcontext->db_context = NULL;
580 clean_n_exit:
581 return status;
584 static void
585 get_errmsg (krb5_context kcontext, krb5_error_code err_code)
587 kdb5_dal_handle *dal_handle;
588 const char *e;
589 if (err_code == 0)
590 return;
591 assert(kcontext != NULL);
592 /* Must be called with dal_handle->lib_handle locked! */
593 assert(kcontext->db_context != NULL);
594 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
595 if (dal_handle->lib_handle->vftabl.errcode_2_string == NULL)
596 return;
597 e = dal_handle->lib_handle->vftabl.errcode_2_string(kcontext, err_code);
598 assert (e != NULL);
599 krb5_set_error_message(kcontext, err_code, "%s", e);
600 if (dal_handle->lib_handle->vftabl.release_errcode_string)
601 dal_handle->lib_handle->vftabl.release_errcode_string(kcontext, e);
605 * External functions... DAL API
607 krb5_error_code
608 krb5_db_open(krb5_context kcontext, char **db_args, int mode)
610 krb5_error_code status = 0;
611 char *section = NULL;
612 kdb5_dal_handle *dal_handle;
614 section = kdb_get_conf_section(kcontext);
615 if (section == NULL) {
616 status = KRB5_KDB_SERVER_INTERNAL_ERR;
617 krb5_set_error_message (kcontext, status,
618 gettext("unable to determine configuration section for realm %s\n"),
619 kcontext->default_realm ? kcontext->default_realm : "[UNSET]");
620 goto clean_n_exit;
623 if (kcontext->db_context == NULL) {
624 status = kdb_setup_lib_handle(kcontext);
625 if (status) {
626 goto clean_n_exit;
630 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
631 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
632 if (status) {
633 /* Solaris Kerberos */
634 kdb_free_lib_handle(kcontext);
635 goto clean_n_exit;
638 status =
639 dal_handle->lib_handle->vftabl.init_module(kcontext, section, db_args,
640 mode);
641 get_errmsg(kcontext, status);
643 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
645 /* Solaris Kerberos */
646 if (status)
647 kdb_free_lib_handle(kcontext);
649 clean_n_exit:
650 free(section);
651 return status;
654 krb5_error_code
655 krb5_db_inited(krb5_context kcontext)
657 return !(kcontext && kcontext->db_context &&
658 ((kdb5_dal_handle *) kcontext->db_context)->db_context);
661 krb5_error_code
662 krb5_db_create(krb5_context kcontext, char **db_args)
664 krb5_error_code status = 0;
665 char *section = NULL;
666 kdb5_dal_handle *dal_handle;
668 section = kdb_get_conf_section(kcontext);
669 if (section == NULL) {
670 status = KRB5_KDB_SERVER_INTERNAL_ERR;
671 krb5_set_error_message (kcontext, status,
672 gettext("unable to determine configuration section for realm %s\n"),
673 kcontext->default_realm);
674 goto clean_n_exit;
677 if (kcontext->db_context == NULL) {
678 status = kdb_setup_lib_handle(kcontext);
679 if (status) {
680 goto clean_n_exit;
684 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
685 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
686 if (status) {
687 goto clean_n_exit;
690 status =
691 dal_handle->lib_handle->vftabl.db_create(kcontext, section, db_args);
692 get_errmsg(kcontext, status);
694 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
696 clean_n_exit:
697 free(section);
698 return status;
701 krb5_error_code
702 krb5_db_fini(krb5_context kcontext)
704 krb5_error_code status = 0;
705 kdb5_dal_handle *dal_handle;
707 if (kcontext->db_context == NULL) {
708 /* module not loaded. So nothing to be done */
709 goto clean_n_exit;
712 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
713 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
714 if (status) {
715 goto clean_n_exit;
718 status = dal_handle->lib_handle->vftabl.fini_module(kcontext);
719 get_errmsg(kcontext, status);
721 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
723 if (status) {
724 goto clean_n_exit;
727 status = kdb_free_lib_handle(kcontext);
729 clean_n_exit:
730 return status;
733 krb5_error_code
734 krb5_db_destroy(krb5_context kcontext, char **db_args)
736 krb5_error_code status = 0;
737 char *section = NULL;
738 kdb5_dal_handle *dal_handle;
740 section = kdb_get_conf_section(kcontext);
741 if (section == NULL) {
742 status = KRB5_KDB_SERVER_INTERNAL_ERR;
743 krb5_set_error_message (kcontext, status,
744 gettext("unable to determine configuration section for realm %s\n"),
745 kcontext->default_realm);
746 goto clean_n_exit;
749 if (kcontext->db_context == NULL) {
750 status = kdb_setup_lib_handle(kcontext);
751 if (status) {
752 goto clean_n_exit;
756 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
757 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
758 if (status) {
759 goto clean_n_exit;
762 status =
763 dal_handle->lib_handle->vftabl.db_destroy(kcontext, section, db_args);
764 get_errmsg(kcontext, status);
765 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
767 clean_n_exit:
768 free(section);
769 return status;
772 krb5_error_code
773 krb5_db_get_age(krb5_context kcontext, char *db_name, time_t * t)
775 krb5_error_code status = 0;
776 kdb5_dal_handle *dal_handle;
778 if (kcontext->db_context == NULL) {
779 status = kdb_setup_lib_handle(kcontext);
780 if (status) {
781 goto clean_n_exit;
785 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
786 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
787 if (status) {
788 goto clean_n_exit;
791 status = dal_handle->lib_handle->vftabl.db_get_age(kcontext, db_name, t);
792 get_errmsg(kcontext, status);
793 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
795 clean_n_exit:
796 return status;
799 krb5_error_code
800 krb5_db_set_option(krb5_context kcontext, int option, void *value)
802 krb5_error_code status = 0;
803 kdb5_dal_handle *dal_handle;
805 if (kcontext->db_context == NULL) {
806 status = kdb_setup_lib_handle(kcontext);
807 if (status) {
808 goto clean_n_exit;
812 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
813 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
814 if (status) {
815 goto clean_n_exit;
818 status =
819 dal_handle->lib_handle->vftabl.db_set_option(kcontext, option, value);
820 get_errmsg(kcontext, status);
821 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
823 clean_n_exit:
824 return status;
827 krb5_error_code
828 krb5_db_lock(krb5_context kcontext, int lock_mode)
830 krb5_error_code status = 0;
831 kdb5_dal_handle *dal_handle;
833 if (kcontext->db_context == NULL) {
834 status = kdb_setup_lib_handle(kcontext);
835 if (status) {
836 goto clean_n_exit;
840 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
841 /* acquire an exclusive lock, ensures no other thread uses this context */
842 status = kdb_lock_lib_lock(dal_handle->lib_handle, TRUE);
843 if (status) {
844 goto clean_n_exit;
847 status = dal_handle->lib_handle->vftabl.db_lock(kcontext, lock_mode);
848 get_errmsg(kcontext, status);
850 /* exclusive lock is still held, so no other thread could use this context */
851 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
853 clean_n_exit:
854 return status;
857 krb5_error_code
858 krb5_db_unlock(krb5_context kcontext)
860 krb5_error_code status = 0;
861 kdb5_dal_handle *dal_handle;
863 if (kcontext->db_context == NULL) {
864 status = kdb_setup_lib_handle(kcontext);
865 if (status) {
866 goto clean_n_exit;
870 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
871 /* normal lock acquired and exclusive lock released */
872 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
873 if (status) {
874 goto clean_n_exit;
877 status = dal_handle->lib_handle->vftabl.db_unlock(kcontext);
878 get_errmsg(kcontext, status);
880 kdb_unlock_lib_lock(dal_handle->lib_handle, TRUE);
882 clean_n_exit:
883 return status;
886 krb5_error_code
887 krb5_db_get_principal(krb5_context kcontext,
888 krb5_const_principal search_for,
889 krb5_db_entry * entries,
890 int *nentries, krb5_boolean * more)
892 krb5_error_code status = 0;
893 kdb5_dal_handle *dal_handle;
895 if (kcontext->db_context == NULL) {
896 status = kdb_setup_lib_handle(kcontext);
897 if (status) {
898 goto clean_n_exit;
902 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
903 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
904 if (status) {
905 goto clean_n_exit;
908 status =
909 dal_handle->lib_handle->vftabl.db_get_principal(kcontext, search_for,
910 entries, nentries,
911 more);
912 get_errmsg(kcontext, status);
913 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
915 clean_n_exit:
916 return status;
919 krb5_error_code
920 krb5_db_get_principal_nolock(krb5_context kcontext,
921 krb5_const_principal search_for,
922 krb5_db_entry * entries,
923 int *nentries, krb5_boolean * more)
925 krb5_error_code status = 0;
926 kdb5_dal_handle *dal_handle;
928 if (kcontext->db_context == NULL) {
929 status = kdb_setup_lib_handle(kcontext);
930 if (status) {
931 goto clean_n_exit;
935 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
936 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
937 if (status) {
938 goto clean_n_exit;
941 status =
942 dal_handle->lib_handle->vftabl.db_get_principal_nolock(kcontext,
943 search_for,
944 entries, nentries,
945 more);
946 get_errmsg(kcontext, status);
947 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
949 clean_n_exit:
950 return status;
953 krb5_error_code
954 krb5_db_free_principal(krb5_context kcontext, krb5_db_entry * entry, int count)
956 krb5_error_code status = 0;
957 kdb5_dal_handle *dal_handle;
959 if (kcontext->db_context == NULL) {
960 status = kdb_setup_lib_handle(kcontext);
961 if (status) {
962 goto clean_n_exit;
966 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
967 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
968 if (status) {
969 goto clean_n_exit;
972 status =
973 dal_handle->lib_handle->vftabl.db_free_principal(kcontext, entry,
974 count);
975 get_errmsg(kcontext, status);
976 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
978 clean_n_exit:
979 return status;
982 krb5_error_code
983 krb5_db_put_principal(krb5_context kcontext,
984 krb5_db_entry * entries, int *nentries)
986 krb5_error_code status = 0;
987 kdb5_dal_handle *dal_handle;
988 char **db_args = NULL;
989 krb5_tl_data *prev, *curr, *next;
990 int db_args_size = 0;
992 if (kcontext->db_context == NULL) {
993 status = kdb_setup_lib_handle(kcontext);
994 if (status) {
995 goto clean_n_exit;
999 /* Giving db_args as part of tl data causes, db2 to store the
1000 tl_data as such. To prevent this, tl_data is collated and
1001 passed as a sepearte argument. Currently supports only one
1002 principal. but passing it as a seperate argument makes it
1003 difficult for kadmin remote to pass arguments to server. */
1004 prev = NULL, curr = entries->tl_data;
1005 while (curr) {
1006 if (curr->tl_data_type == KRB5_TL_DB_ARGS) {
1007 char **t;
1008 /* Since this is expected to be NULL terminated string and
1009 this could come from any client, do a check before
1010 passing it to db. */
1011 if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] !=
1012 '\0') {
1013 /* not null terminated. Dangerous input */
1014 status = EINVAL;
1015 goto clean_n_exit;
1018 db_args_size++;
1019 t = reallocarray(db_args, (db_args_size + 1), sizeof(char *)); /* 1 for NULL */
1020 if (t == NULL) {
1021 status = ENOMEM;
1022 goto clean_n_exit;
1025 db_args = t;
1026 db_args[db_args_size - 1] = (char *) curr->tl_data_contents;
1027 db_args[db_args_size] = NULL;
1029 next = curr->tl_data_next;
1030 if (prev == NULL) {
1031 /* current node is the first in the linked list. remove it */
1032 entries->tl_data = curr->tl_data_next;
1033 } else {
1034 prev->tl_data_next = curr->tl_data_next;
1036 entries->n_tl_data--;
1037 krb5_db_free(kcontext, curr);
1039 /* previous does not change */
1040 curr = next;
1041 } else {
1042 prev = curr;
1043 curr = curr->tl_data_next;
1047 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1048 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1049 if (status) {
1050 goto clean_n_exit;
1053 status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries,
1054 nentries,
1055 db_args);
1056 get_errmsg(kcontext, status);
1057 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1059 clean_n_exit:
1060 while (db_args_size) {
1061 if (db_args[db_args_size - 1])
1062 krb5_db_free(kcontext, db_args[db_args_size - 1]);
1064 db_args_size--;
1067 free(db_args);
1069 return status;
1072 krb5_error_code
1073 krb5_db_delete_principal(krb5_context kcontext,
1074 krb5_principal search_for, int *nentries)
1076 krb5_error_code status = 0;
1077 kdb5_dal_handle *dal_handle;
1079 if (kcontext->db_context == NULL) {
1080 status = kdb_setup_lib_handle(kcontext);
1081 if (status) {
1082 goto clean_n_exit;
1086 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1087 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1088 if (status) {
1089 goto clean_n_exit;
1092 status =
1093 dal_handle->lib_handle->vftabl.db_delete_principal(kcontext,
1094 search_for,
1095 nentries);
1096 get_errmsg(kcontext, status);
1097 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1099 clean_n_exit:
1100 return status;
1103 krb5_error_code
1104 krb5_db_iterate(krb5_context kcontext,
1105 char *match_entry,
1106 int (*func) (krb5_pointer, krb5_db_entry *),
1107 krb5_pointer func_arg,
1108 /* Solaris Kerberos: adding support for db_args */
1109 char **db_args)
1111 krb5_error_code status = 0;
1112 kdb5_dal_handle *dal_handle;
1114 if (kcontext->db_context == NULL) {
1115 status = kdb_setup_lib_handle(kcontext);
1116 if (status) {
1117 goto clean_n_exit;
1121 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1122 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1123 if (status) {
1124 goto clean_n_exit;
1127 /* Solaris Kerberos: adding support for db_args */
1128 status = dal_handle->lib_handle->vftabl.db_iterate(kcontext,
1129 match_entry,
1130 func, func_arg,
1131 db_args);
1132 get_errmsg(kcontext, status);
1133 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1135 clean_n_exit:
1136 return status;
1139 krb5_error_code
1140 krb5_supported_realms(krb5_context kcontext, char **realms)
1142 krb5_error_code status = 0;
1143 kdb5_dal_handle *dal_handle;
1145 if (kcontext->db_context == NULL) {
1146 status = kdb_setup_lib_handle(kcontext);
1147 if (status) {
1148 goto clean_n_exit;
1152 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1153 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1154 if (status) {
1155 goto clean_n_exit;
1158 status =
1159 dal_handle->lib_handle->vftabl.db_supported_realms(kcontext, realms);
1160 get_errmsg(kcontext, status);
1161 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1163 clean_n_exit:
1164 return status;
1167 krb5_error_code
1168 krb5_free_supported_realms(krb5_context kcontext, char **realms)
1170 krb5_error_code status = 0;
1171 kdb5_dal_handle *dal_handle;
1173 if (kcontext->db_context == NULL) {
1174 status = kdb_setup_lib_handle(kcontext);
1175 if (status) {
1176 goto clean_n_exit;
1180 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1181 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1182 if (status) {
1183 goto clean_n_exit;
1186 status =
1187 dal_handle->lib_handle->vftabl.db_free_supported_realms(kcontext,
1188 realms);
1189 get_errmsg(kcontext, status);
1190 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1192 clean_n_exit:
1193 return status;
1196 krb5_error_code
1197 krb5_db_set_master_key_ext(krb5_context kcontext,
1198 char *pwd, krb5_keyblock * key)
1200 krb5_error_code status = 0;
1201 kdb5_dal_handle *dal_handle;
1203 if (kcontext->db_context == NULL) {
1204 status = kdb_setup_lib_handle(kcontext);
1205 if (status) {
1206 goto clean_n_exit;
1210 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1211 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1212 if (status) {
1213 goto clean_n_exit;
1216 status = dal_handle->lib_handle->vftabl.set_master_key(kcontext, pwd, key);
1217 get_errmsg(kcontext, status);
1219 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1221 clean_n_exit:
1222 return status;
1225 krb5_error_code
1226 krb5_db_set_mkey(krb5_context context, krb5_keyblock * key)
1228 return krb5_db_set_master_key_ext(context, NULL, key);
1231 krb5_error_code
1232 krb5_db_get_mkey(krb5_context kcontext, krb5_keyblock ** key)
1234 krb5_error_code status = 0;
1235 kdb5_dal_handle *dal_handle;
1237 if (kcontext->db_context == NULL) {
1238 status = kdb_setup_lib_handle(kcontext);
1239 if (status) {
1240 goto clean_n_exit;
1244 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1245 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1246 if (status) {
1247 goto clean_n_exit;
1250 /* Lets use temp key and copy it later to avoid memory problems
1251 when freed by the caller. */
1252 status = dal_handle->lib_handle->vftabl.get_master_key(kcontext, key);
1253 get_errmsg(kcontext, status);
1254 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1256 clean_n_exit:
1257 return status;
1260 krb5_error_code
1261 krb5_db_store_master_key(krb5_context kcontext,
1262 char *db_arg,
1263 krb5_principal mname,
1264 krb5_keyblock * key, char *master_pwd)
1266 krb5_error_code status = 0;
1267 kdb5_dal_handle *dal_handle;
1269 if (kcontext->db_context == NULL) {
1270 status = kdb_setup_lib_handle(kcontext);
1271 if (status) {
1272 goto clean_n_exit;
1276 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1277 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1278 if (status) {
1279 goto clean_n_exit;
1282 status = dal_handle->lib_handle->vftabl.store_master_key(kcontext,
1283 db_arg,
1284 mname,
1285 key, master_pwd);
1286 get_errmsg(kcontext, status);
1287 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1289 clean_n_exit:
1290 return status;
1293 char *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
1294 char *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
1296 krb5_error_code
1297 krb5_db_fetch_mkey(krb5_context context,
1298 krb5_principal mname,
1299 krb5_enctype etype,
1300 krb5_boolean fromkeyboard,
1301 krb5_boolean twice,
1302 char *db_args, krb5_data * salt, krb5_keyblock * key)
1304 krb5_error_code retval;
1305 char password[BUFSIZ];
1306 krb5_data pwd;
1307 unsigned int size = sizeof(password);
1308 int kvno;
1309 krb5_keyblock tmp_key;
1311 memset(&tmp_key, 0, sizeof(tmp_key));
1313 if (fromkeyboard) {
1314 krb5_data scratch;
1316 if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
1317 twice ? krb5_mkey_pwd_prompt2 : 0,
1318 password, &size))) {
1319 goto clean_n_exit;
1322 pwd.data = password;
1323 pwd.length = size;
1324 if (!salt) {
1325 retval = krb5_principal2salt(context, mname, &scratch);
1326 if (retval)
1327 goto clean_n_exit;
1329 retval =
1330 krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch,
1331 key);
1333 if (!salt)
1334 krb5_xfree(scratch.data);
1335 memset(password, 0, sizeof(password)); /* erase it */
1337 } else {
1338 kdb5_dal_handle *dal_handle;
1340 if (context->db_context == NULL) {
1341 retval = kdb_setup_lib_handle(context);
1342 if (retval) {
1343 goto clean_n_exit;
1347 dal_handle = (kdb5_dal_handle *) context->db_context;
1348 retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1349 if (retval) {
1350 goto clean_n_exit;
1352 #if 0 /************** Begin IFDEF'ed OUT *******************************/
1353 /* Orig MIT */
1354 tmp_key.enctype = key->enctype;
1355 #else
1356 /* Solaris Kerberos: need to use etype */
1357 tmp_key.enctype = etype;
1358 #endif /**************** END IFDEF'ed OUT *******************************/
1359 retval = dal_handle->lib_handle->vftabl.fetch_master_key(context,
1360 mname,
1361 &tmp_key,
1362 &kvno,
1363 db_args);
1364 get_errmsg(context, retval);
1365 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1367 if (retval) {
1368 goto clean_n_exit;
1371 key->contents = malloc(tmp_key.length);
1372 if (key->contents == NULL) {
1373 retval = ENOMEM;
1374 goto clean_n_exit;
1377 key->magic = tmp_key.magic;
1378 key->enctype = tmp_key.enctype;
1379 key->length = tmp_key.length;
1380 memcpy(key->contents, tmp_key.contents, tmp_key.length);
1383 clean_n_exit:
1384 if (tmp_key.contents) {
1385 memset(tmp_key.contents, 0, tmp_key.length);
1386 krb5_db_free(context, tmp_key.contents);
1388 return retval;
1391 krb5_error_code
1392 krb5_db_verify_master_key(krb5_context kcontext,
1393 krb5_principal mprinc, krb5_keyblock * mkey)
1395 krb5_error_code status = 0;
1396 kdb5_dal_handle *dal_handle;
1398 if (kcontext->db_context == NULL) {
1399 status = kdb_setup_lib_handle(kcontext);
1400 if (status) {
1401 goto clean_n_exit;
1405 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1406 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1407 if (status) {
1408 goto clean_n_exit;
1411 status = dal_handle->lib_handle->vftabl.verify_master_key(kcontext,
1412 mprinc, mkey);
1413 get_errmsg(kcontext, status);
1414 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1416 clean_n_exit:
1417 return status;
1420 void *
1421 krb5_db_alloc(krb5_context kcontext, void *ptr, size_t size)
1423 krb5_error_code status;
1424 kdb5_dal_handle *dal_handle;
1425 void *new_ptr = NULL;
1427 if (kcontext->db_context == NULL) {
1428 status = kdb_setup_lib_handle(kcontext);
1429 if (status) {
1430 goto clean_n_exit;
1434 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1436 new_ptr = dal_handle->lib_handle->vftabl.db_alloc(kcontext, ptr, size);
1438 clean_n_exit:
1439 return new_ptr;
1442 void
1443 krb5_db_free(krb5_context kcontext, void *ptr)
1445 krb5_error_code status;
1446 kdb5_dal_handle *dal_handle;
1448 if (kcontext->db_context == NULL) {
1449 status = kdb_setup_lib_handle(kcontext);
1450 if (status) {
1451 goto clean_n_exit;
1455 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1457 dal_handle->lib_handle->vftabl.db_free(kcontext, ptr);
1459 clean_n_exit:
1460 return;
1463 /* has to be modified */
1465 krb5_error_code
1466 krb5_dbe_find_enctype(krb5_context kcontext,
1467 krb5_db_entry * dbentp,
1468 krb5_int32 ktype,
1469 krb5_int32 stype,
1470 krb5_int32 kvno, krb5_key_data ** kdatap)
1472 krb5_int32 start = 0;
1473 return krb5_dbe_search_enctype(kcontext, dbentp, &start, ktype, stype,
1474 kvno, kdatap);
1477 krb5_error_code
1478 krb5_dbe_search_enctype(krb5_context kcontext,
1479 krb5_db_entry * dbentp,
1480 krb5_int32 * start,
1481 krb5_int32 ktype,
1482 krb5_int32 stype,
1483 krb5_int32 kvno, krb5_key_data ** kdatap)
1485 krb5_error_code status = 0;
1486 kdb5_dal_handle *dal_handle;
1488 if (kcontext->db_context == NULL) {
1489 status = kdb_setup_lib_handle(kcontext);
1490 if (status) {
1491 goto clean_n_exit;
1495 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1496 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1497 if (status) {
1498 goto clean_n_exit;
1501 status = dal_handle->lib_handle->vftabl.dbe_search_enctype(kcontext,
1502 dbentp,
1503 start,
1504 ktype,
1505 stype,
1506 kvno, kdatap);
1507 get_errmsg(kcontext, status);
1508 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1510 clean_n_exit:
1511 return status;
1514 #define REALM_SEP_STRING "@"
1516 krb5_error_code
1517 krb5_db_setup_mkey_name(krb5_context context,
1518 const char *keyname,
1519 const char *realm,
1520 char **fullname, krb5_principal * principal)
1522 krb5_error_code retval;
1523 size_t keylen;
1524 size_t rlen = strlen(realm);
1525 char *fname;
1527 if (!keyname)
1528 keyname = KRB5_KDB_M_NAME; /* XXX external? */
1530 keylen = strlen(keyname);
1532 fname = malloc(keylen + rlen + strlen(REALM_SEP_STRING) + 1);
1533 if (!fname)
1534 return ENOMEM;
1536 strcpy(fname, keyname);
1537 (void)strcat(fname, REALM_SEP_STRING);
1538 (void)strcat(fname, realm);
1540 if ((retval = krb5_parse_name(context, fname, principal)))
1541 return retval;
1542 if (fullname)
1543 *fullname = fname;
1544 else
1545 free(fname);
1546 return 0;
1549 krb5_error_code
1550 krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
1551 krb5_context context;
1552 krb5_db_entry *entry;
1553 krb5_timestamp *stamp;
1555 krb5_tl_data tl_data;
1556 krb5_error_code code;
1557 krb5_int32 tmp;
1559 tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
1561 if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1562 return (code);
1564 if (tl_data.tl_data_length != 4) {
1565 *stamp = 0;
1566 return (0);
1569 krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
1571 *stamp = (krb5_timestamp) tmp;
1573 return (0);
1576 /*ARGSUSED*/
1577 krb5_error_code
1578 krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
1579 krb5_context context;
1580 krb5_db_entry *entry;
1581 krb5_tl_data *ret_tl_data;
1583 krb5_tl_data *tl_data;
1585 for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
1586 if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
1587 *ret_tl_data = *tl_data;
1588 return (0);
1592 /* if the requested record isn't found, return zero bytes.
1593 * if it ever means something to have a zero-length tl_data,
1594 * this code and its callers will have to be changed */
1596 ret_tl_data->tl_data_length = 0;
1597 ret_tl_data->tl_data_contents = NULL;
1598 return (0);
1601 krb5_error_code
1602 krb5_dbe_create_key_data(context, entry)
1603 krb5_context context;
1604 krb5_db_entry *entry;
1606 if ((entry->key_data =
1607 (krb5_key_data *) krb5_db_alloc(context, entry->key_data,
1608 (sizeof(krb5_key_data) *
1609 (entry->n_key_data + 1)))) == NULL)
1610 return (ENOMEM);
1612 memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
1613 entry->n_key_data++;
1615 return 0;
1618 krb5_error_code
1619 krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
1620 krb5_context context;
1621 krb5_db_entry *entry;
1622 krb5_timestamp mod_date;
1623 krb5_const_principal mod_princ;
1625 krb5_tl_data tl_data;
1627 krb5_error_code retval = 0;
1628 krb5_octet *nextloc = 0;
1629 char *unparse_mod_princ = 0;
1630 unsigned int unparse_mod_princ_size;
1632 if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ)))
1633 return (retval);
1635 unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
1637 if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
1638 == NULL) {
1639 free(unparse_mod_princ);
1640 return (ENOMEM);
1643 tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
1644 tl_data.tl_data_length = unparse_mod_princ_size + 4;
1645 tl_data.tl_data_contents = nextloc;
1647 /* Mod Date */
1648 krb5_kdb_encode_int32(mod_date, nextloc);
1650 /* Mod Princ */
1651 memcpy(nextloc + 4, unparse_mod_princ, unparse_mod_princ_size);
1653 retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
1655 free(unparse_mod_princ);
1656 free(nextloc);
1658 return (retval);
1661 krb5_error_code
1662 krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
1663 krb5_context context;
1664 krb5_db_entry *entry;
1665 krb5_timestamp *mod_time;
1666 krb5_principal *mod_princ;
1668 krb5_tl_data tl_data;
1669 krb5_error_code code;
1671 tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
1673 if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1674 return (code);
1676 if ((tl_data.tl_data_length < 5) ||
1677 (tl_data.tl_data_contents[tl_data.tl_data_length - 1] != '\0'))
1678 return (KRB5_KDB_TRUNCATED_RECORD);
1680 /* Mod Date */
1681 krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
1683 /* Mod Princ */
1684 if ((code = krb5_parse_name(context,
1685 (const char *) (tl_data.tl_data_contents + 4),
1686 mod_princ)))
1687 return (code);
1689 return (0);
1692 krb5_error_code
1693 krb5_dbe_update_last_pwd_change(context, entry, stamp)
1694 krb5_context context;
1695 krb5_db_entry *entry;
1696 krb5_timestamp stamp;
1698 krb5_tl_data tl_data;
1699 krb5_octet buf[4]; /* this is the encoded size of an int32 */
1701 tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
1702 tl_data.tl_data_length = sizeof(buf);
1703 krb5_kdb_encode_int32((krb5_int32) stamp, buf);
1704 tl_data.tl_data_contents = buf;
1706 return (krb5_dbe_update_tl_data(context, entry, &tl_data));
1709 krb5_error_code
1710 krb5_dbe_update_tl_data(context, entry, new_tl_data)
1711 krb5_context context;
1712 krb5_db_entry *entry;
1713 krb5_tl_data *new_tl_data;
1715 krb5_tl_data *tl_data = NULL;
1716 krb5_octet *tmp;
1718 /* copy the new data first, so we can fail cleanly if malloc()
1719 * fails */
1720 if ((tmp =
1721 (krb5_octet *) krb5_db_alloc(context, NULL,
1722 new_tl_data->tl_data_length)) == NULL)
1723 return (ENOMEM);
1725 /* Find an existing entry of the specified type and point at
1726 * it, or NULL if not found */
1728 if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) { /* db_args can be multiple */
1729 for (tl_data = entry->tl_data; tl_data;
1730 tl_data = tl_data->tl_data_next)
1731 if (tl_data->tl_data_type == new_tl_data->tl_data_type)
1732 break;
1735 /* if necessary, chain a new record in the beginning and point at it */
1737 if (!tl_data) {
1738 if ((tl_data =
1739 (krb5_tl_data *) krb5_db_alloc(context, NULL,
1740 sizeof(krb5_tl_data)))
1741 == NULL) {
1742 free(tmp);
1743 return (ENOMEM);
1745 memset(tl_data, 0, sizeof(krb5_tl_data));
1746 tl_data->tl_data_next = entry->tl_data;
1747 entry->tl_data = tl_data;
1748 entry->n_tl_data++;
1751 /* fill in the record */
1753 if (tl_data->tl_data_contents)
1754 krb5_db_free(context, tl_data->tl_data_contents);
1756 tl_data->tl_data_type = new_tl_data->tl_data_type;
1757 tl_data->tl_data_length = new_tl_data->tl_data_length;
1758 tl_data->tl_data_contents = tmp;
1759 memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
1761 return (0);
1764 /* change password functions */
1765 krb5_error_code
1766 krb5_dbe_cpw(krb5_context kcontext,
1767 krb5_keyblock * master_key,
1768 krb5_key_salt_tuple * ks_tuple,
1769 int ks_tuple_count,
1770 char *passwd,
1771 int new_kvno, krb5_boolean keepold, krb5_db_entry * db_entry)
1773 krb5_error_code status = 0;
1774 kdb5_dal_handle *dal_handle;
1776 if (kcontext->db_context == NULL) {
1777 status = kdb_setup_lib_handle(kcontext);
1778 if (status) {
1779 goto clean_n_exit;
1783 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1784 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1785 if (status) {
1786 goto clean_n_exit;
1789 status = dal_handle->lib_handle->vftabl.db_change_pwd(kcontext,
1790 master_key,
1791 ks_tuple,
1792 ks_tuple_count,
1793 passwd,
1794 new_kvno,
1795 keepold, db_entry);
1796 get_errmsg(kcontext, status);
1797 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1799 clean_n_exit:
1800 return status;
1803 /* policy management functions */
1804 krb5_error_code
1805 krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)
1807 krb5_error_code status = 0;
1808 kdb5_dal_handle *dal_handle;
1810 if (kcontext->db_context == NULL) {
1811 status = kdb_setup_lib_handle(kcontext);
1812 if (status) {
1813 goto clean_n_exit;
1817 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1818 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1819 if (status) {
1820 goto clean_n_exit;
1823 status = dal_handle->lib_handle->vftabl.db_create_policy(kcontext, policy);
1824 get_errmsg(kcontext, status);
1825 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1827 clean_n_exit:
1828 return status;
1831 krb5_error_code
1832 krb5_db_get_policy(krb5_context kcontext, char *name,
1833 osa_policy_ent_t * policy, int *cnt)
1835 krb5_error_code status = 0;
1836 kdb5_dal_handle *dal_handle;
1838 if (kcontext->db_context == NULL) {
1839 status = kdb_setup_lib_handle(kcontext);
1840 if (status) {
1841 goto clean_n_exit;
1845 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1846 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1847 if (status) {
1848 goto clean_n_exit;
1851 status =
1852 dal_handle->lib_handle->vftabl.db_get_policy(kcontext, name, policy,
1853 cnt);
1854 get_errmsg(kcontext, status);
1855 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1857 clean_n_exit:
1858 return status;
1861 krb5_error_code
1862 krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)
1864 krb5_error_code status = 0;
1865 kdb5_dal_handle *dal_handle;
1867 if (kcontext->db_context == NULL) {
1868 status = kdb_setup_lib_handle(kcontext);
1869 if (status) {
1870 goto clean_n_exit;
1874 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1875 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1876 if (status) {
1877 goto clean_n_exit;
1880 status = dal_handle->lib_handle->vftabl.db_put_policy(kcontext, policy);
1881 get_errmsg(kcontext, status);
1882 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1884 clean_n_exit:
1885 return status;
1888 krb5_error_code
1889 krb5_db_iter_policy(krb5_context kcontext, char *match_entry,
1890 osa_adb_iter_policy_func func, void *data)
1892 krb5_error_code status = 0;
1893 kdb5_dal_handle *dal_handle;
1895 if (kcontext->db_context == NULL) {
1896 status = kdb_setup_lib_handle(kcontext);
1897 if (status) {
1898 goto clean_n_exit;
1902 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1903 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1904 if (status) {
1905 goto clean_n_exit;
1908 status =
1909 dal_handle->lib_handle->vftabl.db_iter_policy(kcontext, match_entry,
1910 func, data);
1911 get_errmsg(kcontext, status);
1912 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1914 clean_n_exit:
1915 return status;
1918 krb5_error_code
1919 krb5_db_delete_policy(krb5_context kcontext, char *policy)
1921 krb5_error_code status = 0;
1922 kdb5_dal_handle *dal_handle;
1924 if (kcontext->db_context == NULL) {
1925 status = kdb_setup_lib_handle(kcontext);
1926 if (status) {
1927 goto clean_n_exit;
1931 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1932 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1933 if (status) {
1934 goto clean_n_exit;
1937 status = dal_handle->lib_handle->vftabl.db_delete_policy(kcontext, policy);
1938 get_errmsg(kcontext, status);
1939 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1941 clean_n_exit:
1942 return status;
1945 void
1946 krb5_db_free_policy(krb5_context kcontext, osa_policy_ent_t policy)
1948 krb5_error_code status = 0;
1949 kdb5_dal_handle *dal_handle;
1951 if (kcontext->db_context == NULL) {
1952 status = kdb_setup_lib_handle(kcontext);
1953 if (status) {
1954 goto clean_n_exit;
1958 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1959 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1960 if (status) {
1961 goto clean_n_exit;
1964 dal_handle->lib_handle->vftabl.db_free_policy(kcontext, policy);
1965 get_errmsg(kcontext, status);
1966 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
1968 clean_n_exit:
1969 return;
1972 krb5_error_code
1973 krb5_db_promote(krb5_context kcontext, char **db_args)
1975 krb5_error_code status = 0;
1976 char *section = NULL;
1977 kdb5_dal_handle *dal_handle;
1979 section = kdb_get_conf_section(kcontext);
1980 if (section == NULL) {
1981 status = KRB5_KDB_SERVER_INTERNAL_ERR;
1982 krb5_set_error_message (kcontext, status,
1983 gettext("unable to determine configuration section for realm %s\n"),
1984 kcontext->default_realm);
1985 goto clean_n_exit;
1988 if (kcontext->db_context == NULL) {
1989 status = kdb_setup_lib_handle(kcontext);
1990 if (status) {
1991 goto clean_n_exit;
1995 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
1996 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
1997 if (status) {
1998 goto clean_n_exit;
2001 status =
2002 dal_handle->lib_handle->vftabl.promote_db(kcontext, section, db_args);
2003 get_errmsg(kcontext, status);
2004 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
2006 clean_n_exit:
2007 free(section);
2008 return status;
2012 * Solaris Kerberos: support for iprop
2014 * Not all KDB plugins support iprop.
2016 * sets iprop_supported to 1 if iprop supportd, 0 otherwise.
2018 krb5_error_code
2019 krb5_db_supports_iprop(krb5_context kcontext, int *iprop_supported)
2021 krb5_error_code status = 0;
2022 kdb5_dal_handle *dal_handle;
2024 if (kcontext->db_context == NULL) {
2025 status = kdb_setup_lib_handle(kcontext);
2026 if (status) {
2027 goto clean_n_exit;
2031 dal_handle = (kdb5_dal_handle *) kcontext->db_context;
2032 status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
2033 if (status) {
2034 goto clean_n_exit;
2037 *iprop_supported = dal_handle->lib_handle->vftabl.iprop_supported;
2038 kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
2040 clean_n_exit:
2041 return status;