1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert * Copyright 2006, 2009, 2010, 2016 by the Massachusetts Institute of
4*7f2fe78bSCy Schubert * Technology.
5*7f2fe78bSCy Schubert * All Rights Reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert /*
28*7f2fe78bSCy Schubert * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
29*7f2fe78bSCy Schubert * Use is subject to license terms.
30*7f2fe78bSCy Schubert */
31*7f2fe78bSCy Schubert
32*7f2fe78bSCy Schubert /*
33*7f2fe78bSCy Schubert * This code was based on code donated to MIT by Novell for
34*7f2fe78bSCy Schubert * distribution under the MIT license.
35*7f2fe78bSCy Schubert */
36*7f2fe78bSCy Schubert
37*7f2fe78bSCy Schubert /*
38*7f2fe78bSCy Schubert * Include files
39*7f2fe78bSCy Schubert */
40*7f2fe78bSCy Schubert
41*7f2fe78bSCy Schubert #include <k5-int.h>
42*7f2fe78bSCy Schubert #include "kdb5.h"
43*7f2fe78bSCy Schubert #include "kdb_log.h"
44*7f2fe78bSCy Schubert #include "kdb5int.h"
45*7f2fe78bSCy Schubert
46*7f2fe78bSCy Schubert /* Currently DB2 policy related errors are exported from DAL. But
47*7f2fe78bSCy Schubert other databases should set_err function to return string. */
48*7f2fe78bSCy Schubert #include "adb_err.h"
49*7f2fe78bSCy Schubert
50*7f2fe78bSCy Schubert /*
51*7f2fe78bSCy Schubert * internal static variable
52*7f2fe78bSCy Schubert */
53*7f2fe78bSCy Schubert
54*7f2fe78bSCy Schubert static k5_mutex_t db_lock = K5_MUTEX_PARTIAL_INITIALIZER;
55*7f2fe78bSCy Schubert
56*7f2fe78bSCy Schubert static db_library lib_list;
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert /*
59*7f2fe78bSCy Schubert * Helper Functions
60*7f2fe78bSCy Schubert */
61*7f2fe78bSCy Schubert
62*7f2fe78bSCy Schubert MAKE_INIT_FUNCTION(kdb_init_lock_list);
63*7f2fe78bSCy Schubert MAKE_FINI_FUNCTION(kdb_fini_lock_list);
64*7f2fe78bSCy Schubert
65*7f2fe78bSCy Schubert static void
free_mkey_list(krb5_context context,krb5_keylist_node * mkey_list)66*7f2fe78bSCy Schubert free_mkey_list(krb5_context context, krb5_keylist_node *mkey_list)
67*7f2fe78bSCy Schubert {
68*7f2fe78bSCy Schubert krb5_keylist_node *cur, *next;
69*7f2fe78bSCy Schubert
70*7f2fe78bSCy Schubert for (cur = mkey_list; cur != NULL; cur = next) {
71*7f2fe78bSCy Schubert next = cur->next;
72*7f2fe78bSCy Schubert krb5_free_keyblock_contents(context, &cur->keyblock);
73*7f2fe78bSCy Schubert free(cur);
74*7f2fe78bSCy Schubert }
75*7f2fe78bSCy Schubert }
76*7f2fe78bSCy Schubert
77*7f2fe78bSCy Schubert int
kdb_init_lock_list()78*7f2fe78bSCy Schubert kdb_init_lock_list()
79*7f2fe78bSCy Schubert {
80*7f2fe78bSCy Schubert return k5_mutex_finish_init(&db_lock);
81*7f2fe78bSCy Schubert }
82*7f2fe78bSCy Schubert
83*7f2fe78bSCy Schubert static int
kdb_lock_list()84*7f2fe78bSCy Schubert kdb_lock_list()
85*7f2fe78bSCy Schubert {
86*7f2fe78bSCy Schubert int err;
87*7f2fe78bSCy Schubert err = CALL_INIT_FUNCTION (kdb_init_lock_list);
88*7f2fe78bSCy Schubert if (err)
89*7f2fe78bSCy Schubert return err;
90*7f2fe78bSCy Schubert k5_mutex_lock(&db_lock);
91*7f2fe78bSCy Schubert return 0;
92*7f2fe78bSCy Schubert }
93*7f2fe78bSCy Schubert
94*7f2fe78bSCy Schubert void
kdb_fini_lock_list()95*7f2fe78bSCy Schubert kdb_fini_lock_list()
96*7f2fe78bSCy Schubert {
97*7f2fe78bSCy Schubert if (INITIALIZER_RAN(kdb_init_lock_list))
98*7f2fe78bSCy Schubert k5_mutex_destroy(&db_lock);
99*7f2fe78bSCy Schubert }
100*7f2fe78bSCy Schubert
101*7f2fe78bSCy Schubert static void
kdb_unlock_list()102*7f2fe78bSCy Schubert kdb_unlock_list()
103*7f2fe78bSCy Schubert {
104*7f2fe78bSCy Schubert k5_mutex_unlock(&db_lock);
105*7f2fe78bSCy Schubert }
106*7f2fe78bSCy Schubert
107*7f2fe78bSCy Schubert /* Return true if the ulog is mapped in the primary role. */
108*7f2fe78bSCy Schubert static inline krb5_boolean
logging(krb5_context context)109*7f2fe78bSCy Schubert logging(krb5_context context)
110*7f2fe78bSCy Schubert {
111*7f2fe78bSCy Schubert kdb_log_context *log_ctx = context->kdblog_context;
112*7f2fe78bSCy Schubert
113*7f2fe78bSCy Schubert return log_ctx != NULL && log_ctx->iproprole == IPROP_PRIMARY &&
114*7f2fe78bSCy Schubert log_ctx->ulog != NULL;
115*7f2fe78bSCy Schubert }
116*7f2fe78bSCy Schubert
117*7f2fe78bSCy Schubert void
krb5_dbe_free_key_data_contents(krb5_context context,krb5_key_data * key)118*7f2fe78bSCy Schubert krb5_dbe_free_key_data_contents(krb5_context context, krb5_key_data *key)
119*7f2fe78bSCy Schubert {
120*7f2fe78bSCy Schubert int i, idx;
121*7f2fe78bSCy Schubert
122*7f2fe78bSCy Schubert if (key) {
123*7f2fe78bSCy Schubert idx = (key->key_data_ver == 1 ? 1 : 2);
124*7f2fe78bSCy Schubert for (i = 0; i < idx; i++) {
125*7f2fe78bSCy Schubert if (key->key_data_contents[i]) {
126*7f2fe78bSCy Schubert zap(key->key_data_contents[i], key->key_data_length[i]);
127*7f2fe78bSCy Schubert free(key->key_data_contents[i]);
128*7f2fe78bSCy Schubert }
129*7f2fe78bSCy Schubert }
130*7f2fe78bSCy Schubert }
131*7f2fe78bSCy Schubert return;
132*7f2fe78bSCy Schubert }
133*7f2fe78bSCy Schubert
134*7f2fe78bSCy Schubert void
krb5_dbe_free_key_list(krb5_context context,krb5_keylist_node * val)135*7f2fe78bSCy Schubert krb5_dbe_free_key_list(krb5_context context, krb5_keylist_node *val)
136*7f2fe78bSCy Schubert {
137*7f2fe78bSCy Schubert krb5_keylist_node *temp = val, *prev;
138*7f2fe78bSCy Schubert
139*7f2fe78bSCy Schubert while (temp != NULL) {
140*7f2fe78bSCy Schubert prev = temp;
141*7f2fe78bSCy Schubert temp = temp->next;
142*7f2fe78bSCy Schubert krb5_free_keyblock_contents(context, &(prev->keyblock));
143*7f2fe78bSCy Schubert free(prev);
144*7f2fe78bSCy Schubert }
145*7f2fe78bSCy Schubert }
146*7f2fe78bSCy Schubert
147*7f2fe78bSCy Schubert void
krb5_dbe_free_actkvno_list(krb5_context context,krb5_actkvno_node * val)148*7f2fe78bSCy Schubert krb5_dbe_free_actkvno_list(krb5_context context, krb5_actkvno_node *val)
149*7f2fe78bSCy Schubert {
150*7f2fe78bSCy Schubert krb5_actkvno_node *temp = val, *prev;
151*7f2fe78bSCy Schubert
152*7f2fe78bSCy Schubert while (temp != NULL) {
153*7f2fe78bSCy Schubert prev = temp;
154*7f2fe78bSCy Schubert temp = temp->next;
155*7f2fe78bSCy Schubert free(prev);
156*7f2fe78bSCy Schubert }
157*7f2fe78bSCy Schubert }
158*7f2fe78bSCy Schubert
159*7f2fe78bSCy Schubert void
krb5_dbe_free_mkey_aux_list(krb5_context context,krb5_mkey_aux_node * val)160*7f2fe78bSCy Schubert krb5_dbe_free_mkey_aux_list(krb5_context context, krb5_mkey_aux_node *val)
161*7f2fe78bSCy Schubert {
162*7f2fe78bSCy Schubert krb5_mkey_aux_node *temp = val, *prev;
163*7f2fe78bSCy Schubert
164*7f2fe78bSCy Schubert while (temp != NULL) {
165*7f2fe78bSCy Schubert prev = temp;
166*7f2fe78bSCy Schubert temp = temp->next;
167*7f2fe78bSCy Schubert krb5_dbe_free_key_data_contents(context, &prev->latest_mkey);
168*7f2fe78bSCy Schubert free(prev);
169*7f2fe78bSCy Schubert }
170*7f2fe78bSCy Schubert }
171*7f2fe78bSCy Schubert
172*7f2fe78bSCy Schubert void
krb5_dbe_free_tl_data(krb5_context context,krb5_tl_data * tl_data)173*7f2fe78bSCy Schubert krb5_dbe_free_tl_data(krb5_context context, krb5_tl_data *tl_data)
174*7f2fe78bSCy Schubert {
175*7f2fe78bSCy Schubert if (tl_data) {
176*7f2fe78bSCy Schubert if (tl_data->tl_data_contents)
177*7f2fe78bSCy Schubert free(tl_data->tl_data_contents);
178*7f2fe78bSCy Schubert free(tl_data);
179*7f2fe78bSCy Schubert }
180*7f2fe78bSCy Schubert }
181*7f2fe78bSCy Schubert
182*7f2fe78bSCy Schubert void
krb5_dbe_free_strings(krb5_context context,krb5_string_attr * strings,int count)183*7f2fe78bSCy Schubert krb5_dbe_free_strings(krb5_context context, krb5_string_attr *strings,
184*7f2fe78bSCy Schubert int count)
185*7f2fe78bSCy Schubert {
186*7f2fe78bSCy Schubert int i;
187*7f2fe78bSCy Schubert
188*7f2fe78bSCy Schubert if (strings == NULL)
189*7f2fe78bSCy Schubert return;
190*7f2fe78bSCy Schubert for (i = 0; i < count; i++) {
191*7f2fe78bSCy Schubert free(strings[i].key);
192*7f2fe78bSCy Schubert free(strings[i].value);
193*7f2fe78bSCy Schubert }
194*7f2fe78bSCy Schubert free(strings);
195*7f2fe78bSCy Schubert }
196*7f2fe78bSCy Schubert
197*7f2fe78bSCy Schubert void
krb5_dbe_free_string(krb5_context context,char * string)198*7f2fe78bSCy Schubert krb5_dbe_free_string(krb5_context context, char *string)
199*7f2fe78bSCy Schubert {
200*7f2fe78bSCy Schubert free(string);
201*7f2fe78bSCy Schubert }
202*7f2fe78bSCy Schubert
203*7f2fe78bSCy Schubert /* Set *section to the appropriate section to use for a database module's
204*7f2fe78bSCy Schubert * profile queries. The caller must free the result. */
205*7f2fe78bSCy Schubert static krb5_error_code
get_conf_section(krb5_context context,char ** section)206*7f2fe78bSCy Schubert get_conf_section(krb5_context context, char **section)
207*7f2fe78bSCy Schubert {
208*7f2fe78bSCy Schubert krb5_error_code status;
209*7f2fe78bSCy Schubert char *result = NULL, *value = NULL, *defrealm;
210*7f2fe78bSCy Schubert
211*7f2fe78bSCy Schubert *section = NULL;
212*7f2fe78bSCy Schubert
213*7f2fe78bSCy Schubert status = krb5_get_default_realm(context, &defrealm);
214*7f2fe78bSCy Schubert if (status) {
215*7f2fe78bSCy Schubert k5_setmsg(context, KRB5_KDB_SERVER_INTERNAL_ERR,
216*7f2fe78bSCy Schubert _("No default realm set; cannot initialize KDB"));
217*7f2fe78bSCy Schubert return KRB5_KDB_SERVER_INTERNAL_ERR;
218*7f2fe78bSCy Schubert }
219*7f2fe78bSCy Schubert status = profile_get_string(context->profile,
220*7f2fe78bSCy Schubert /* realms */
221*7f2fe78bSCy Schubert KDB_REALM_SECTION,
222*7f2fe78bSCy Schubert defrealm,
223*7f2fe78bSCy Schubert /* under the realm name, database_module */
224*7f2fe78bSCy Schubert KDB_MODULE_POINTER,
225*7f2fe78bSCy Schubert /* default value is the realm name itself */
226*7f2fe78bSCy Schubert defrealm,
227*7f2fe78bSCy Schubert &value);
228*7f2fe78bSCy Schubert krb5_free_default_realm(context, defrealm);
229*7f2fe78bSCy Schubert if (status)
230*7f2fe78bSCy Schubert return status;
231*7f2fe78bSCy Schubert result = strdup(value);
232*7f2fe78bSCy Schubert profile_release_string(value);
233*7f2fe78bSCy Schubert if (result == NULL)
234*7f2fe78bSCy Schubert return ENOMEM;
235*7f2fe78bSCy Schubert *section = result;
236*7f2fe78bSCy Schubert return 0;
237*7f2fe78bSCy Schubert }
238*7f2fe78bSCy Schubert
239*7f2fe78bSCy Schubert static krb5_error_code
kdb_get_library_name(krb5_context kcontext,char ** libname_out)240*7f2fe78bSCy Schubert kdb_get_library_name(krb5_context kcontext, char **libname_out)
241*7f2fe78bSCy Schubert {
242*7f2fe78bSCy Schubert krb5_error_code status = 0;
243*7f2fe78bSCy Schubert char *value = NULL, *lib = NULL, *defrealm = NULL;
244*7f2fe78bSCy Schubert
245*7f2fe78bSCy Schubert *libname_out = NULL;
246*7f2fe78bSCy Schubert
247*7f2fe78bSCy Schubert status = krb5_get_default_realm(kcontext, &defrealm);
248*7f2fe78bSCy Schubert if (status)
249*7f2fe78bSCy Schubert goto clean_n_exit;
250*7f2fe78bSCy Schubert status = profile_get_string(kcontext->profile,
251*7f2fe78bSCy Schubert /* realms */
252*7f2fe78bSCy Schubert KDB_REALM_SECTION,
253*7f2fe78bSCy Schubert defrealm,
254*7f2fe78bSCy Schubert /* under the realm name, database_module */
255*7f2fe78bSCy Schubert KDB_MODULE_POINTER,
256*7f2fe78bSCy Schubert /* default value is the realm name itself */
257*7f2fe78bSCy Schubert defrealm,
258*7f2fe78bSCy Schubert &value);
259*7f2fe78bSCy Schubert if (status)
260*7f2fe78bSCy Schubert goto clean_n_exit;
261*7f2fe78bSCy Schubert
262*7f2fe78bSCy Schubert #define DB2_NAME "db2"
263*7f2fe78bSCy Schubert /* we got the module section. Get the library name from the module */
264*7f2fe78bSCy Schubert status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value,
265*7f2fe78bSCy Schubert KDB_LIB_POINTER,
266*7f2fe78bSCy Schubert /* default to db2 */
267*7f2fe78bSCy Schubert DB2_NAME,
268*7f2fe78bSCy Schubert &lib);
269*7f2fe78bSCy Schubert
270*7f2fe78bSCy Schubert if (status) {
271*7f2fe78bSCy Schubert goto clean_n_exit;
272*7f2fe78bSCy Schubert }
273*7f2fe78bSCy Schubert
274*7f2fe78bSCy Schubert *libname_out = strdup(lib);
275*7f2fe78bSCy Schubert if (*libname_out == NULL)
276*7f2fe78bSCy Schubert status = ENOMEM;
277*7f2fe78bSCy Schubert
278*7f2fe78bSCy Schubert clean_n_exit:
279*7f2fe78bSCy Schubert krb5_free_default_realm(kcontext, defrealm);
280*7f2fe78bSCy Schubert profile_release_string(value);
281*7f2fe78bSCy Schubert profile_release_string(lib);
282*7f2fe78bSCy Schubert return status;
283*7f2fe78bSCy Schubert }
284*7f2fe78bSCy Schubert
285*7f2fe78bSCy Schubert static void
copy_vtable(const kdb_vftabl * in,kdb_vftabl * out)286*7f2fe78bSCy Schubert copy_vtable(const kdb_vftabl *in, kdb_vftabl *out)
287*7f2fe78bSCy Schubert {
288*7f2fe78bSCy Schubert /* Copy fields for minor version 0. */
289*7f2fe78bSCy Schubert out->maj_ver = in->maj_ver;
290*7f2fe78bSCy Schubert out->min_ver = in->min_ver;
291*7f2fe78bSCy Schubert out->init_library = in->init_library;
292*7f2fe78bSCy Schubert out->fini_library = in->fini_library;
293*7f2fe78bSCy Schubert out->init_module = in->init_module;
294*7f2fe78bSCy Schubert out->fini_module = in->fini_module;
295*7f2fe78bSCy Schubert out->create = in->create;
296*7f2fe78bSCy Schubert out->destroy = in->destroy;
297*7f2fe78bSCy Schubert out->get_age = in->get_age;
298*7f2fe78bSCy Schubert out->lock = in->lock;
299*7f2fe78bSCy Schubert out->unlock = in->unlock;
300*7f2fe78bSCy Schubert out->get_principal = in->get_principal;
301*7f2fe78bSCy Schubert out->put_principal = in->put_principal;
302*7f2fe78bSCy Schubert out->delete_principal = in->delete_principal;
303*7f2fe78bSCy Schubert out->rename_principal = in->rename_principal;
304*7f2fe78bSCy Schubert out->iterate = in->iterate;
305*7f2fe78bSCy Schubert out->create_policy = in->create_policy;
306*7f2fe78bSCy Schubert out->get_policy = in->get_policy;
307*7f2fe78bSCy Schubert out->put_policy = in->put_policy;
308*7f2fe78bSCy Schubert out->iter_policy = in->iter_policy;
309*7f2fe78bSCy Schubert out->delete_policy = in->delete_policy;
310*7f2fe78bSCy Schubert out->fetch_master_key = in->fetch_master_key;
311*7f2fe78bSCy Schubert out->fetch_master_key_list = in->fetch_master_key_list;
312*7f2fe78bSCy Schubert out->store_master_key_list = in->store_master_key_list;
313*7f2fe78bSCy Schubert out->dbe_search_enctype = in->dbe_search_enctype;
314*7f2fe78bSCy Schubert out->change_pwd = in->change_pwd;
315*7f2fe78bSCy Schubert out->promote_db = in->promote_db;
316*7f2fe78bSCy Schubert out->decrypt_key_data = in->decrypt_key_data;
317*7f2fe78bSCy Schubert out->encrypt_key_data = in->encrypt_key_data;
318*7f2fe78bSCy Schubert out->check_transited_realms = in->check_transited_realms;
319*7f2fe78bSCy Schubert out->check_policy_as = in->check_policy_as;
320*7f2fe78bSCy Schubert out->check_policy_tgs = in->check_policy_tgs;
321*7f2fe78bSCy Schubert out->audit_as_req = in->audit_as_req;
322*7f2fe78bSCy Schubert out->refresh_config = in->refresh_config;
323*7f2fe78bSCy Schubert out->check_allowed_to_delegate = in->check_allowed_to_delegate;
324*7f2fe78bSCy Schubert out->free_principal_e_data = in->free_principal_e_data;
325*7f2fe78bSCy Schubert out->get_s4u_x509_principal = in->get_s4u_x509_principal;
326*7f2fe78bSCy Schubert out->allowed_to_delegate_from = in->allowed_to_delegate_from;
327*7f2fe78bSCy Schubert out->issue_pac = in->issue_pac;
328*7f2fe78bSCy Schubert
329*7f2fe78bSCy Schubert /* Set defaults for optional fields. */
330*7f2fe78bSCy Schubert if (out->fetch_master_key == NULL)
331*7f2fe78bSCy Schubert out->fetch_master_key = krb5_db_def_fetch_mkey;
332*7f2fe78bSCy Schubert if (out->fetch_master_key_list == NULL)
333*7f2fe78bSCy Schubert out->fetch_master_key_list = krb5_def_fetch_mkey_list;
334*7f2fe78bSCy Schubert if (out->store_master_key_list == NULL)
335*7f2fe78bSCy Schubert out->store_master_key_list = krb5_def_store_mkey_list;
336*7f2fe78bSCy Schubert if (out->dbe_search_enctype == NULL)
337*7f2fe78bSCy Schubert out->dbe_search_enctype = krb5_dbe_def_search_enctype;
338*7f2fe78bSCy Schubert if (out->change_pwd == NULL)
339*7f2fe78bSCy Schubert out->change_pwd = krb5_dbe_def_cpw;
340*7f2fe78bSCy Schubert if (out->decrypt_key_data == NULL)
341*7f2fe78bSCy Schubert out->decrypt_key_data = krb5_dbe_def_decrypt_key_data;
342*7f2fe78bSCy Schubert if (out->encrypt_key_data == NULL)
343*7f2fe78bSCy Schubert out->encrypt_key_data = krb5_dbe_def_encrypt_key_data;
344*7f2fe78bSCy Schubert if (out->rename_principal == NULL)
345*7f2fe78bSCy Schubert out->rename_principal = krb5_db_def_rename_principal;
346*7f2fe78bSCy Schubert }
347*7f2fe78bSCy Schubert
348*7f2fe78bSCy Schubert #ifdef STATIC_PLUGINS
349*7f2fe78bSCy Schubert
350*7f2fe78bSCy Schubert extern kdb_vftabl krb5_db2_kdb_function_table;
351*7f2fe78bSCy Schubert #ifdef ENABLE_LDAP
352*7f2fe78bSCy Schubert extern kdb_vftabl krb5_ldap_kdb_function_table;
353*7f2fe78bSCy Schubert #endif
354*7f2fe78bSCy Schubert
355*7f2fe78bSCy Schubert static krb5_error_code
kdb_load_library(krb5_context kcontext,char * lib_name,db_library * libptr)356*7f2fe78bSCy Schubert kdb_load_library(krb5_context kcontext, char *lib_name, db_library *libptr)
357*7f2fe78bSCy Schubert {
358*7f2fe78bSCy Schubert krb5_error_code status;
359*7f2fe78bSCy Schubert db_library lib;
360*7f2fe78bSCy Schubert kdb_vftabl *vftabl_addr = NULL;
361*7f2fe78bSCy Schubert
362*7f2fe78bSCy Schubert if (strcmp(lib_name, "db2") == 0)
363*7f2fe78bSCy Schubert vftabl_addr = &krb5_db2_kdb_function_table;
364*7f2fe78bSCy Schubert #ifdef ENABLE_LDAP
365*7f2fe78bSCy Schubert if (strcmp(lib_name, "kldap") == 0)
366*7f2fe78bSCy Schubert vftabl_addr = &krb5_ldap_kdb_function_table;
367*7f2fe78bSCy Schubert #endif
368*7f2fe78bSCy Schubert if (!vftabl_addr) {
369*7f2fe78bSCy Schubert k5_setmsg(kcontext, KRB5_KDB_DBTYPE_NOTFOUND,
370*7f2fe78bSCy Schubert _("Unable to find requested database type: %s"), lib_name);
371*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
372*7f2fe78bSCy Schubert }
373*7f2fe78bSCy Schubert
374*7f2fe78bSCy Schubert lib = calloc(1, sizeof(*lib));
375*7f2fe78bSCy Schubert if (lib == NULL)
376*7f2fe78bSCy Schubert return ENOMEM;
377*7f2fe78bSCy Schubert
378*7f2fe78bSCy Schubert strlcpy(lib->name, lib_name, sizeof(lib->name));
379*7f2fe78bSCy Schubert copy_vtable(vftabl_addr, &lib->vftabl);
380*7f2fe78bSCy Schubert
381*7f2fe78bSCy Schubert status = lib->vftabl.init_library();
382*7f2fe78bSCy Schubert if (status)
383*7f2fe78bSCy Schubert goto cleanup;
384*7f2fe78bSCy Schubert
385*7f2fe78bSCy Schubert *libptr = lib;
386*7f2fe78bSCy Schubert return 0;
387*7f2fe78bSCy Schubert
388*7f2fe78bSCy Schubert cleanup:
389*7f2fe78bSCy Schubert free(lib);
390*7f2fe78bSCy Schubert return status;
391*7f2fe78bSCy Schubert }
392*7f2fe78bSCy Schubert
393*7f2fe78bSCy Schubert #else /* KDB5_STATIC_LINK*/
394*7f2fe78bSCy Schubert
395*7f2fe78bSCy Schubert static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH;
396*7f2fe78bSCy Schubert #define db_dl_n_locations (sizeof(db_dl_location) / sizeof(db_dl_location[0]))
397*7f2fe78bSCy Schubert
398*7f2fe78bSCy Schubert static krb5_error_code
kdb_load_library(krb5_context kcontext,char * lib_name,db_library * lib)399*7f2fe78bSCy Schubert kdb_load_library(krb5_context kcontext, char *lib_name, db_library *lib)
400*7f2fe78bSCy Schubert {
401*7f2fe78bSCy Schubert krb5_error_code status = 0;
402*7f2fe78bSCy Schubert int ndx;
403*7f2fe78bSCy Schubert void **vftabl_addrs = NULL;
404*7f2fe78bSCy Schubert /* N.B.: If this is "const" but not "static", the Solaris 10
405*7f2fe78bSCy Schubert native compiler has trouble building the library because of
406*7f2fe78bSCy Schubert absolute relocations needed in read-only section ".rodata".
407*7f2fe78bSCy Schubert When it's static, it goes into ".picdata", which is
408*7f2fe78bSCy Schubert read-write. */
409*7f2fe78bSCy Schubert static const char *const dbpath_names[] = {
410*7f2fe78bSCy Schubert KDB_MODULE_SECTION, KRB5_CONF_DB_MODULE_DIR, NULL,
411*7f2fe78bSCy Schubert };
412*7f2fe78bSCy Schubert const char *filebases[2];
413*7f2fe78bSCy Schubert char **profpath = NULL;
414*7f2fe78bSCy Schubert char **path = NULL;
415*7f2fe78bSCy Schubert
416*7f2fe78bSCy Schubert filebases[0] = lib_name;
417*7f2fe78bSCy Schubert filebases[1] = NULL;
418*7f2fe78bSCy Schubert
419*7f2fe78bSCy Schubert *lib = calloc((size_t) 1, sizeof(**lib));
420*7f2fe78bSCy Schubert if (*lib == NULL)
421*7f2fe78bSCy Schubert return ENOMEM;
422*7f2fe78bSCy Schubert
423*7f2fe78bSCy Schubert strlcpy((*lib)->name, lib_name, sizeof((*lib)->name));
424*7f2fe78bSCy Schubert
425*7f2fe78bSCy Schubert /* Fetch the list of directories specified in the config
426*7f2fe78bSCy Schubert file(s) first. */
427*7f2fe78bSCy Schubert status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
428*7f2fe78bSCy Schubert if (status != 0 && status != PROF_NO_RELATION)
429*7f2fe78bSCy Schubert goto clean_n_exit;
430*7f2fe78bSCy Schubert ndx = 0;
431*7f2fe78bSCy Schubert if (profpath)
432*7f2fe78bSCy Schubert while (profpath[ndx] != NULL)
433*7f2fe78bSCy Schubert ndx++;
434*7f2fe78bSCy Schubert
435*7f2fe78bSCy Schubert path = calloc(ndx + db_dl_n_locations, sizeof (char *));
436*7f2fe78bSCy Schubert if (path == NULL) {
437*7f2fe78bSCy Schubert status = ENOMEM;
438*7f2fe78bSCy Schubert goto clean_n_exit;
439*7f2fe78bSCy Schubert }
440*7f2fe78bSCy Schubert if (ndx)
441*7f2fe78bSCy Schubert memcpy(path, profpath, ndx * sizeof(profpath[0]));
442*7f2fe78bSCy Schubert memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
443*7f2fe78bSCy Schubert status = 0;
444*7f2fe78bSCy Schubert
445*7f2fe78bSCy Schubert if ((status = krb5int_open_plugin_dirs ((const char **) path,
446*7f2fe78bSCy Schubert filebases,
447*7f2fe78bSCy Schubert &(*lib)->dl_dir_handle, &kcontext->err))) {
448*7f2fe78bSCy Schubert status = KRB5_KDB_DBTYPE_NOTFOUND;
449*7f2fe78bSCy Schubert k5_prependmsg(kcontext, status,
450*7f2fe78bSCy Schubert _("Unable to find requested database type"));
451*7f2fe78bSCy Schubert goto clean_n_exit;
452*7f2fe78bSCy Schubert }
453*7f2fe78bSCy Schubert
454*7f2fe78bSCy Schubert if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
455*7f2fe78bSCy Schubert &vftabl_addrs, &kcontext->err))) {
456*7f2fe78bSCy Schubert status = KRB5_KDB_DBTYPE_INIT;
457*7f2fe78bSCy Schubert k5_prependmsg(kcontext, status,
458*7f2fe78bSCy Schubert _("plugin symbol 'kdb_function_table' lookup failed"));
459*7f2fe78bSCy Schubert goto clean_n_exit;
460*7f2fe78bSCy Schubert }
461*7f2fe78bSCy Schubert
462*7f2fe78bSCy Schubert if (vftabl_addrs[0] == NULL) {
463*7f2fe78bSCy Schubert /* No plugins! */
464*7f2fe78bSCy Schubert status = KRB5_KDB_DBTYPE_NOTFOUND;
465*7f2fe78bSCy Schubert k5_setmsg(kcontext, status,
466*7f2fe78bSCy Schubert _("Unable to load requested database module '%s': plugin "
467*7f2fe78bSCy Schubert "symbol 'kdb_function_table' not found"), lib_name);
468*7f2fe78bSCy Schubert goto clean_n_exit;
469*7f2fe78bSCy Schubert }
470*7f2fe78bSCy Schubert
471*7f2fe78bSCy Schubert if (((kdb_vftabl *)vftabl_addrs[0])->maj_ver !=
472*7f2fe78bSCy Schubert KRB5_KDB_DAL_MAJOR_VERSION) {
473*7f2fe78bSCy Schubert status = KRB5_KDB_DBTYPE_MISMATCH;
474*7f2fe78bSCy Schubert goto clean_n_exit;
475*7f2fe78bSCy Schubert }
476*7f2fe78bSCy Schubert
477*7f2fe78bSCy Schubert copy_vtable(vftabl_addrs[0], &(*lib)->vftabl);
478*7f2fe78bSCy Schubert
479*7f2fe78bSCy Schubert if ((status = (*lib)->vftabl.init_library()))
480*7f2fe78bSCy Schubert goto clean_n_exit;
481*7f2fe78bSCy Schubert
482*7f2fe78bSCy Schubert clean_n_exit:
483*7f2fe78bSCy Schubert krb5int_free_plugin_dir_data(vftabl_addrs);
484*7f2fe78bSCy Schubert /* Both of these DTRT with NULL. */
485*7f2fe78bSCy Schubert profile_free_list(profpath);
486*7f2fe78bSCy Schubert free(path);
487*7f2fe78bSCy Schubert if (status && *lib) {
488*7f2fe78bSCy Schubert if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle)))
489*7f2fe78bSCy Schubert krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
490*7f2fe78bSCy Schubert free(*lib);
491*7f2fe78bSCy Schubert *lib = NULL;
492*7f2fe78bSCy Schubert }
493*7f2fe78bSCy Schubert return status;
494*7f2fe78bSCy Schubert }
495*7f2fe78bSCy Schubert
496*7f2fe78bSCy Schubert #endif /* end of _KDB5_STATIC_LINK */
497*7f2fe78bSCy Schubert
498*7f2fe78bSCy Schubert static krb5_error_code
kdb_find_library(krb5_context kcontext,char * lib_name,db_library * lib)499*7f2fe78bSCy Schubert kdb_find_library(krb5_context kcontext, char *lib_name, db_library *lib)
500*7f2fe78bSCy Schubert {
501*7f2fe78bSCy Schubert /* lock here so that no two threads try to do the same at the same time */
502*7f2fe78bSCy Schubert krb5_error_code status = 0;
503*7f2fe78bSCy Schubert int locked = 0;
504*7f2fe78bSCy Schubert db_library curr_elt, prev_elt = NULL;
505*7f2fe78bSCy Schubert static int kdb_db2_pol_err_loaded = 0;
506*7f2fe78bSCy Schubert
507*7f2fe78bSCy Schubert if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
508*7f2fe78bSCy Schubert initialize_adb_error_table();
509*7f2fe78bSCy Schubert kdb_db2_pol_err_loaded = 1;
510*7f2fe78bSCy Schubert }
511*7f2fe78bSCy Schubert
512*7f2fe78bSCy Schubert if ((status = kdb_lock_list()) != 0)
513*7f2fe78bSCy Schubert goto clean_n_exit;
514*7f2fe78bSCy Schubert locked = 1;
515*7f2fe78bSCy Schubert
516*7f2fe78bSCy Schubert curr_elt = lib_list;
517*7f2fe78bSCy Schubert while (curr_elt != NULL) {
518*7f2fe78bSCy Schubert if (strcmp(lib_name, curr_elt->name) == 0) {
519*7f2fe78bSCy Schubert *lib = curr_elt;
520*7f2fe78bSCy Schubert goto clean_n_exit;
521*7f2fe78bSCy Schubert }
522*7f2fe78bSCy Schubert prev_elt = curr_elt;
523*7f2fe78bSCy Schubert curr_elt = curr_elt->next;
524*7f2fe78bSCy Schubert }
525*7f2fe78bSCy Schubert
526*7f2fe78bSCy Schubert /* module not found. create and add to list */
527*7f2fe78bSCy Schubert status = kdb_load_library(kcontext, lib_name, lib);
528*7f2fe78bSCy Schubert if (status)
529*7f2fe78bSCy Schubert goto clean_n_exit;
530*7f2fe78bSCy Schubert
531*7f2fe78bSCy Schubert if (prev_elt) {
532*7f2fe78bSCy Schubert /* prev_elt points to the last element in the list */
533*7f2fe78bSCy Schubert prev_elt->next = *lib;
534*7f2fe78bSCy Schubert (*lib)->prev = prev_elt;
535*7f2fe78bSCy Schubert } else {
536*7f2fe78bSCy Schubert lib_list = *lib;
537*7f2fe78bSCy Schubert }
538*7f2fe78bSCy Schubert
539*7f2fe78bSCy Schubert clean_n_exit:
540*7f2fe78bSCy Schubert if (*lib)
541*7f2fe78bSCy Schubert (*lib)->reference_cnt++;
542*7f2fe78bSCy Schubert
543*7f2fe78bSCy Schubert if (locked)
544*7f2fe78bSCy Schubert kdb_unlock_list();
545*7f2fe78bSCy Schubert
546*7f2fe78bSCy Schubert return status;
547*7f2fe78bSCy Schubert }
548*7f2fe78bSCy Schubert
549*7f2fe78bSCy Schubert static krb5_error_code
kdb_free_library(db_library lib)550*7f2fe78bSCy Schubert kdb_free_library(db_library lib)
551*7f2fe78bSCy Schubert {
552*7f2fe78bSCy Schubert krb5_error_code status = 0;
553*7f2fe78bSCy Schubert int locked = 0;
554*7f2fe78bSCy Schubert
555*7f2fe78bSCy Schubert if ((status = kdb_lock_list()) != 0)
556*7f2fe78bSCy Schubert goto clean_n_exit;
557*7f2fe78bSCy Schubert locked = 1;
558*7f2fe78bSCy Schubert
559*7f2fe78bSCy Schubert lib->reference_cnt--;
560*7f2fe78bSCy Schubert
561*7f2fe78bSCy Schubert if (lib->reference_cnt == 0) {
562*7f2fe78bSCy Schubert status = lib->vftabl.fini_library();
563*7f2fe78bSCy Schubert if (status)
564*7f2fe78bSCy Schubert goto clean_n_exit;
565*7f2fe78bSCy Schubert
566*7f2fe78bSCy Schubert /* close the library */
567*7f2fe78bSCy Schubert if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle)))
568*7f2fe78bSCy Schubert krb5int_close_plugin_dirs (&lib->dl_dir_handle);
569*7f2fe78bSCy Schubert
570*7f2fe78bSCy Schubert if (lib->prev == NULL)
571*7f2fe78bSCy Schubert lib_list = lib->next; /* first element in the list */
572*7f2fe78bSCy Schubert else
573*7f2fe78bSCy Schubert lib->prev->next = lib->next;
574*7f2fe78bSCy Schubert
575*7f2fe78bSCy Schubert if (lib->next)
576*7f2fe78bSCy Schubert lib->next->prev = lib->prev;
577*7f2fe78bSCy Schubert free(lib);
578*7f2fe78bSCy Schubert }
579*7f2fe78bSCy Schubert
580*7f2fe78bSCy Schubert clean_n_exit:
581*7f2fe78bSCy Schubert if (locked)
582*7f2fe78bSCy Schubert kdb_unlock_list();
583*7f2fe78bSCy Schubert
584*7f2fe78bSCy Schubert return status;
585*7f2fe78bSCy Schubert }
586*7f2fe78bSCy Schubert
587*7f2fe78bSCy Schubert krb5_error_code
krb5_db_setup_lib_handle(krb5_context kcontext)588*7f2fe78bSCy Schubert krb5_db_setup_lib_handle(krb5_context kcontext)
589*7f2fe78bSCy Schubert {
590*7f2fe78bSCy Schubert char *library = NULL;
591*7f2fe78bSCy Schubert krb5_error_code status = 0;
592*7f2fe78bSCy Schubert db_library lib = NULL;
593*7f2fe78bSCy Schubert kdb5_dal_handle *dal_handle = NULL;
594*7f2fe78bSCy Schubert
595*7f2fe78bSCy Schubert dal_handle = calloc((size_t) 1, sizeof(kdb5_dal_handle));
596*7f2fe78bSCy Schubert if (dal_handle == NULL) {
597*7f2fe78bSCy Schubert status = ENOMEM;
598*7f2fe78bSCy Schubert goto clean_n_exit;
599*7f2fe78bSCy Schubert }
600*7f2fe78bSCy Schubert
601*7f2fe78bSCy Schubert status = kdb_get_library_name(kcontext, &library);
602*7f2fe78bSCy Schubert if (library == NULL) {
603*7f2fe78bSCy Schubert k5_prependmsg(kcontext, status,
604*7f2fe78bSCy Schubert _("Cannot initialize database library"));
605*7f2fe78bSCy Schubert goto clean_n_exit;
606*7f2fe78bSCy Schubert }
607*7f2fe78bSCy Schubert
608*7f2fe78bSCy Schubert status = kdb_find_library(kcontext, library, &lib);
609*7f2fe78bSCy Schubert if (status)
610*7f2fe78bSCy Schubert goto clean_n_exit;
611*7f2fe78bSCy Schubert
612*7f2fe78bSCy Schubert dal_handle->lib_handle = lib;
613*7f2fe78bSCy Schubert kcontext->dal_handle = dal_handle;
614*7f2fe78bSCy Schubert
615*7f2fe78bSCy Schubert clean_n_exit:
616*7f2fe78bSCy Schubert free(library);
617*7f2fe78bSCy Schubert
618*7f2fe78bSCy Schubert if (status) {
619*7f2fe78bSCy Schubert free(dal_handle);
620*7f2fe78bSCy Schubert if (lib)
621*7f2fe78bSCy Schubert kdb_free_library(lib);
622*7f2fe78bSCy Schubert }
623*7f2fe78bSCy Schubert
624*7f2fe78bSCy Schubert return status;
625*7f2fe78bSCy Schubert }
626*7f2fe78bSCy Schubert
627*7f2fe78bSCy Schubert static krb5_error_code
kdb_free_lib_handle(krb5_context kcontext)628*7f2fe78bSCy Schubert kdb_free_lib_handle(krb5_context kcontext)
629*7f2fe78bSCy Schubert {
630*7f2fe78bSCy Schubert krb5_error_code status = 0;
631*7f2fe78bSCy Schubert
632*7f2fe78bSCy Schubert status = kdb_free_library(kcontext->dal_handle->lib_handle);
633*7f2fe78bSCy Schubert if (status)
634*7f2fe78bSCy Schubert return status;
635*7f2fe78bSCy Schubert
636*7f2fe78bSCy Schubert free_mkey_list(kcontext, kcontext->dal_handle->master_keylist);
637*7f2fe78bSCy Schubert krb5_free_principal(kcontext, kcontext->dal_handle->master_princ);
638*7f2fe78bSCy Schubert free(kcontext->dal_handle);
639*7f2fe78bSCy Schubert kcontext->dal_handle = NULL;
640*7f2fe78bSCy Schubert return 0;
641*7f2fe78bSCy Schubert }
642*7f2fe78bSCy Schubert
643*7f2fe78bSCy Schubert static krb5_error_code
get_vftabl(krb5_context kcontext,kdb_vftabl ** vftabl_ptr)644*7f2fe78bSCy Schubert get_vftabl(krb5_context kcontext, kdb_vftabl **vftabl_ptr)
645*7f2fe78bSCy Schubert {
646*7f2fe78bSCy Schubert krb5_error_code status;
647*7f2fe78bSCy Schubert
648*7f2fe78bSCy Schubert *vftabl_ptr = NULL;
649*7f2fe78bSCy Schubert if (kcontext->dal_handle == NULL) {
650*7f2fe78bSCy Schubert status = krb5_db_setup_lib_handle(kcontext);
651*7f2fe78bSCy Schubert if (status)
652*7f2fe78bSCy Schubert return status;
653*7f2fe78bSCy Schubert }
654*7f2fe78bSCy Schubert *vftabl_ptr = &kcontext->dal_handle->lib_handle->vftabl;
655*7f2fe78bSCy Schubert return 0;
656*7f2fe78bSCy Schubert }
657*7f2fe78bSCy Schubert
658*7f2fe78bSCy Schubert /*
659*7f2fe78bSCy Schubert * External functions... DAL API
660*7f2fe78bSCy Schubert */
661*7f2fe78bSCy Schubert krb5_error_code
krb5_db_open(krb5_context kcontext,char ** db_args,int mode)662*7f2fe78bSCy Schubert krb5_db_open(krb5_context kcontext, char **db_args, int mode)
663*7f2fe78bSCy Schubert {
664*7f2fe78bSCy Schubert krb5_error_code status;
665*7f2fe78bSCy Schubert char *section;
666*7f2fe78bSCy Schubert kdb_vftabl *v;
667*7f2fe78bSCy Schubert
668*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
669*7f2fe78bSCy Schubert if (status)
670*7f2fe78bSCy Schubert return status;
671*7f2fe78bSCy Schubert status = get_conf_section(kcontext, §ion);
672*7f2fe78bSCy Schubert if (status)
673*7f2fe78bSCy Schubert return status;
674*7f2fe78bSCy Schubert status = v->init_module(kcontext, section, db_args, mode);
675*7f2fe78bSCy Schubert free(section);
676*7f2fe78bSCy Schubert if (status)
677*7f2fe78bSCy Schubert (void)krb5_db_fini(kcontext);
678*7f2fe78bSCy Schubert return status;
679*7f2fe78bSCy Schubert }
680*7f2fe78bSCy Schubert
681*7f2fe78bSCy Schubert krb5_error_code
krb5_db_inited(krb5_context kcontext)682*7f2fe78bSCy Schubert krb5_db_inited(krb5_context kcontext)
683*7f2fe78bSCy Schubert {
684*7f2fe78bSCy Schubert return !(kcontext && kcontext->dal_handle &&
685*7f2fe78bSCy Schubert kcontext->dal_handle->db_context);
686*7f2fe78bSCy Schubert }
687*7f2fe78bSCy Schubert
688*7f2fe78bSCy Schubert krb5_error_code
krb5_db_create(krb5_context kcontext,char ** db_args)689*7f2fe78bSCy Schubert krb5_db_create(krb5_context kcontext, char **db_args)
690*7f2fe78bSCy Schubert {
691*7f2fe78bSCy Schubert krb5_error_code status;
692*7f2fe78bSCy Schubert char *section;
693*7f2fe78bSCy Schubert kdb_vftabl *v;
694*7f2fe78bSCy Schubert
695*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
696*7f2fe78bSCy Schubert if (status)
697*7f2fe78bSCy Schubert return status;
698*7f2fe78bSCy Schubert if (v->create == NULL)
699*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
700*7f2fe78bSCy Schubert status = get_conf_section(kcontext, §ion);
701*7f2fe78bSCy Schubert if (status)
702*7f2fe78bSCy Schubert return status;
703*7f2fe78bSCy Schubert status = v->create(kcontext, section, db_args);
704*7f2fe78bSCy Schubert free(section);
705*7f2fe78bSCy Schubert if (status)
706*7f2fe78bSCy Schubert (void)krb5_db_fini(kcontext);
707*7f2fe78bSCy Schubert return status;
708*7f2fe78bSCy Schubert }
709*7f2fe78bSCy Schubert
710*7f2fe78bSCy Schubert krb5_error_code
krb5_db_fini(krb5_context kcontext)711*7f2fe78bSCy Schubert krb5_db_fini(krb5_context kcontext)
712*7f2fe78bSCy Schubert {
713*7f2fe78bSCy Schubert krb5_error_code status = 0;
714*7f2fe78bSCy Schubert kdb_vftabl *v;
715*7f2fe78bSCy Schubert
716*7f2fe78bSCy Schubert /* Do nothing if module was never loaded. */
717*7f2fe78bSCy Schubert if (kcontext->dal_handle == NULL)
718*7f2fe78bSCy Schubert return 0;
719*7f2fe78bSCy Schubert
720*7f2fe78bSCy Schubert v = &kcontext->dal_handle->lib_handle->vftabl;
721*7f2fe78bSCy Schubert status = v->fini_module(kcontext);
722*7f2fe78bSCy Schubert
723*7f2fe78bSCy Schubert if (status)
724*7f2fe78bSCy Schubert return status;
725*7f2fe78bSCy Schubert
726*7f2fe78bSCy Schubert return kdb_free_lib_handle(kcontext);
727*7f2fe78bSCy Schubert }
728*7f2fe78bSCy Schubert
729*7f2fe78bSCy Schubert krb5_error_code
krb5_db_destroy(krb5_context kcontext,char ** db_args)730*7f2fe78bSCy Schubert krb5_db_destroy(krb5_context kcontext, char **db_args)
731*7f2fe78bSCy Schubert {
732*7f2fe78bSCy Schubert krb5_error_code status;
733*7f2fe78bSCy Schubert char *section;
734*7f2fe78bSCy Schubert kdb_vftabl *v;
735*7f2fe78bSCy Schubert
736*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
737*7f2fe78bSCy Schubert if (status)
738*7f2fe78bSCy Schubert return status;
739*7f2fe78bSCy Schubert if (v->destroy == NULL)
740*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
741*7f2fe78bSCy Schubert status = get_conf_section(kcontext, §ion);
742*7f2fe78bSCy Schubert if (status)
743*7f2fe78bSCy Schubert return status;
744*7f2fe78bSCy Schubert status = v->destroy(kcontext, section, db_args);
745*7f2fe78bSCy Schubert free(section);
746*7f2fe78bSCy Schubert return status;
747*7f2fe78bSCy Schubert }
748*7f2fe78bSCy Schubert
749*7f2fe78bSCy Schubert krb5_error_code
krb5_db_get_age(krb5_context kcontext,char * db_name,time_t * t)750*7f2fe78bSCy Schubert krb5_db_get_age(krb5_context kcontext, char *db_name, time_t *t)
751*7f2fe78bSCy Schubert {
752*7f2fe78bSCy Schubert krb5_error_code status = 0;
753*7f2fe78bSCy Schubert kdb_vftabl *v;
754*7f2fe78bSCy Schubert
755*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
756*7f2fe78bSCy Schubert if (status)
757*7f2fe78bSCy Schubert return status;
758*7f2fe78bSCy Schubert if (v->get_age == NULL)
759*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
760*7f2fe78bSCy Schubert return v->get_age(kcontext, db_name, t);
761*7f2fe78bSCy Schubert }
762*7f2fe78bSCy Schubert
763*7f2fe78bSCy Schubert krb5_error_code
krb5_db_lock(krb5_context kcontext,int lock_mode)764*7f2fe78bSCy Schubert krb5_db_lock(krb5_context kcontext, int lock_mode)
765*7f2fe78bSCy Schubert {
766*7f2fe78bSCy Schubert krb5_error_code status = 0;
767*7f2fe78bSCy Schubert kdb_vftabl *v;
768*7f2fe78bSCy Schubert
769*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
770*7f2fe78bSCy Schubert if (status)
771*7f2fe78bSCy Schubert return status;
772*7f2fe78bSCy Schubert if (v->lock == NULL)
773*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
774*7f2fe78bSCy Schubert return v->lock(kcontext, lock_mode);
775*7f2fe78bSCy Schubert }
776*7f2fe78bSCy Schubert
777*7f2fe78bSCy Schubert krb5_error_code
krb5_db_unlock(krb5_context kcontext)778*7f2fe78bSCy Schubert krb5_db_unlock(krb5_context kcontext)
779*7f2fe78bSCy Schubert {
780*7f2fe78bSCy Schubert krb5_error_code status = 0;
781*7f2fe78bSCy Schubert kdb_vftabl *v;
782*7f2fe78bSCy Schubert
783*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
784*7f2fe78bSCy Schubert if (status)
785*7f2fe78bSCy Schubert return status;
786*7f2fe78bSCy Schubert if (v->unlock == NULL)
787*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
788*7f2fe78bSCy Schubert return v->unlock(kcontext);
789*7f2fe78bSCy Schubert }
790*7f2fe78bSCy Schubert
791*7f2fe78bSCy Schubert krb5_error_code
krb5_db_get_principal(krb5_context kcontext,krb5_const_principal search_for,unsigned int flags,krb5_db_entry ** entry)792*7f2fe78bSCy Schubert krb5_db_get_principal(krb5_context kcontext, krb5_const_principal search_for,
793*7f2fe78bSCy Schubert unsigned int flags, krb5_db_entry **entry)
794*7f2fe78bSCy Schubert {
795*7f2fe78bSCy Schubert krb5_error_code status = 0;
796*7f2fe78bSCy Schubert kdb_vftabl *v;
797*7f2fe78bSCy Schubert
798*7f2fe78bSCy Schubert *entry = NULL;
799*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
800*7f2fe78bSCy Schubert if (status)
801*7f2fe78bSCy Schubert return status;
802*7f2fe78bSCy Schubert if (v->get_principal == NULL)
803*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
804*7f2fe78bSCy Schubert status = v->get_principal(kcontext, search_for, flags, entry);
805*7f2fe78bSCy Schubert if (status)
806*7f2fe78bSCy Schubert return status;
807*7f2fe78bSCy Schubert
808*7f2fe78bSCy Schubert /* Sort the keys in the db entry as some parts of krb5 expect it to be. */
809*7f2fe78bSCy Schubert if ((*entry)->key_data != NULL)
810*7f2fe78bSCy Schubert krb5_dbe_sort_key_data((*entry)->key_data, (*entry)->n_key_data);
811*7f2fe78bSCy Schubert
812*7f2fe78bSCy Schubert return 0;
813*7f2fe78bSCy Schubert }
814*7f2fe78bSCy Schubert
815*7f2fe78bSCy Schubert static void
free_tl_data(krb5_tl_data * list)816*7f2fe78bSCy Schubert free_tl_data(krb5_tl_data *list)
817*7f2fe78bSCy Schubert {
818*7f2fe78bSCy Schubert krb5_tl_data *next;
819*7f2fe78bSCy Schubert
820*7f2fe78bSCy Schubert for (; list != NULL; list = next) {
821*7f2fe78bSCy Schubert next = list->tl_data_next;
822*7f2fe78bSCy Schubert free(list->tl_data_contents);
823*7f2fe78bSCy Schubert free(list);
824*7f2fe78bSCy Schubert }
825*7f2fe78bSCy Schubert }
826*7f2fe78bSCy Schubert
827*7f2fe78bSCy Schubert void
krb5_db_free_principal(krb5_context kcontext,krb5_db_entry * entry)828*7f2fe78bSCy Schubert krb5_db_free_principal(krb5_context kcontext, krb5_db_entry *entry)
829*7f2fe78bSCy Schubert {
830*7f2fe78bSCy Schubert kdb_vftabl *v;
831*7f2fe78bSCy Schubert int i;
832*7f2fe78bSCy Schubert
833*7f2fe78bSCy Schubert if (entry == NULL)
834*7f2fe78bSCy Schubert return;
835*7f2fe78bSCy Schubert if (entry->e_data != NULL) {
836*7f2fe78bSCy Schubert if (get_vftabl(kcontext, &v) == 0 && v->free_principal_e_data != NULL)
837*7f2fe78bSCy Schubert v->free_principal_e_data(kcontext, entry->e_data);
838*7f2fe78bSCy Schubert else
839*7f2fe78bSCy Schubert free(entry->e_data);
840*7f2fe78bSCy Schubert }
841*7f2fe78bSCy Schubert krb5_free_principal(kcontext, entry->princ);
842*7f2fe78bSCy Schubert free_tl_data(entry->tl_data);
843*7f2fe78bSCy Schubert for (i = 0; i < entry->n_key_data; i++)
844*7f2fe78bSCy Schubert krb5_dbe_free_key_data_contents(kcontext, &entry->key_data[i]);
845*7f2fe78bSCy Schubert free(entry->key_data);
846*7f2fe78bSCy Schubert free(entry);
847*7f2fe78bSCy Schubert }
848*7f2fe78bSCy Schubert
849*7f2fe78bSCy Schubert static void
free_db_args(char ** db_args)850*7f2fe78bSCy Schubert free_db_args(char **db_args)
851*7f2fe78bSCy Schubert {
852*7f2fe78bSCy Schubert int i;
853*7f2fe78bSCy Schubert if (db_args) {
854*7f2fe78bSCy Schubert for (i = 0; db_args[i]; i++)
855*7f2fe78bSCy Schubert free(db_args[i]);
856*7f2fe78bSCy Schubert free(db_args);
857*7f2fe78bSCy Schubert }
858*7f2fe78bSCy Schubert }
859*7f2fe78bSCy Schubert
860*7f2fe78bSCy Schubert static krb5_error_code
extract_db_args_from_tl_data(krb5_context kcontext,krb5_tl_data ** start,krb5_int16 * count,char *** db_argsp)861*7f2fe78bSCy Schubert extract_db_args_from_tl_data(krb5_context kcontext, krb5_tl_data **start,
862*7f2fe78bSCy Schubert krb5_int16 *count, char ***db_argsp)
863*7f2fe78bSCy Schubert {
864*7f2fe78bSCy Schubert char **db_args = NULL;
865*7f2fe78bSCy Schubert int db_args_size = 0;
866*7f2fe78bSCy Schubert krb5_tl_data *prev, *curr, *next;
867*7f2fe78bSCy Schubert krb5_error_code status;
868*7f2fe78bSCy Schubert
869*7f2fe78bSCy Schubert /* Giving db_args as part of tl data causes db2 to store the
870*7f2fe78bSCy Schubert tl_data as such. To prevent this, tl_data is collated and
871*7f2fe78bSCy Schubert passed as a separate argument. Currently supports only one
872*7f2fe78bSCy Schubert principal, but passing it as a separate argument makes it
873*7f2fe78bSCy Schubert difficult for kadmin remote to pass arguments to server. */
874*7f2fe78bSCy Schubert prev = NULL, curr = *start;
875*7f2fe78bSCy Schubert while (curr) {
876*7f2fe78bSCy Schubert if (curr->tl_data_type == KRB5_TL_DB_ARGS) {
877*7f2fe78bSCy Schubert char **t;
878*7f2fe78bSCy Schubert /* Since this is expected to be NULL terminated string and
879*7f2fe78bSCy Schubert this could come from any client, do a check before
880*7f2fe78bSCy Schubert passing it to db. */
881*7f2fe78bSCy Schubert if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] !=
882*7f2fe78bSCy Schubert '\0') {
883*7f2fe78bSCy Schubert /* Not null terminated. Dangerous input. */
884*7f2fe78bSCy Schubert status = EINVAL;
885*7f2fe78bSCy Schubert goto clean_n_exit;
886*7f2fe78bSCy Schubert }
887*7f2fe78bSCy Schubert
888*7f2fe78bSCy Schubert db_args_size++;
889*7f2fe78bSCy Schubert t = realloc(db_args, sizeof(char *) * (db_args_size + 1)); /* 1 for NULL */
890*7f2fe78bSCy Schubert if (t == NULL) {
891*7f2fe78bSCy Schubert status = ENOMEM;
892*7f2fe78bSCy Schubert goto clean_n_exit;
893*7f2fe78bSCy Schubert }
894*7f2fe78bSCy Schubert
895*7f2fe78bSCy Schubert db_args = t;
896*7f2fe78bSCy Schubert db_args[db_args_size - 1] = (char *) curr->tl_data_contents;
897*7f2fe78bSCy Schubert db_args[db_args_size] = NULL;
898*7f2fe78bSCy Schubert
899*7f2fe78bSCy Schubert next = curr->tl_data_next;
900*7f2fe78bSCy Schubert if (prev == NULL) {
901*7f2fe78bSCy Schubert /* current node is the first in the linked list. remove it */
902*7f2fe78bSCy Schubert *start = curr->tl_data_next;
903*7f2fe78bSCy Schubert } else {
904*7f2fe78bSCy Schubert prev->tl_data_next = curr->tl_data_next;
905*7f2fe78bSCy Schubert }
906*7f2fe78bSCy Schubert (*count)--;
907*7f2fe78bSCy Schubert free(curr);
908*7f2fe78bSCy Schubert
909*7f2fe78bSCy Schubert /* previous does not change */
910*7f2fe78bSCy Schubert curr = next;
911*7f2fe78bSCy Schubert } else {
912*7f2fe78bSCy Schubert prev = curr;
913*7f2fe78bSCy Schubert curr = curr->tl_data_next;
914*7f2fe78bSCy Schubert }
915*7f2fe78bSCy Schubert }
916*7f2fe78bSCy Schubert status = 0;
917*7f2fe78bSCy Schubert clean_n_exit:
918*7f2fe78bSCy Schubert if (status != 0) {
919*7f2fe78bSCy Schubert free_db_args(db_args);
920*7f2fe78bSCy Schubert db_args = NULL;
921*7f2fe78bSCy Schubert }
922*7f2fe78bSCy Schubert *db_argsp = db_args;
923*7f2fe78bSCy Schubert return status;
924*7f2fe78bSCy Schubert }
925*7f2fe78bSCy Schubert
926*7f2fe78bSCy Schubert krb5_error_code
krb5int_put_principal_no_log(krb5_context kcontext,krb5_db_entry * entry)927*7f2fe78bSCy Schubert krb5int_put_principal_no_log(krb5_context kcontext, krb5_db_entry *entry)
928*7f2fe78bSCy Schubert {
929*7f2fe78bSCy Schubert kdb_vftabl *v;
930*7f2fe78bSCy Schubert krb5_error_code status;
931*7f2fe78bSCy Schubert char **db_args;
932*7f2fe78bSCy Schubert
933*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
934*7f2fe78bSCy Schubert if (status)
935*7f2fe78bSCy Schubert return status;
936*7f2fe78bSCy Schubert if (v->put_principal == NULL)
937*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
938*7f2fe78bSCy Schubert status = extract_db_args_from_tl_data(kcontext, &entry->tl_data,
939*7f2fe78bSCy Schubert &entry->n_tl_data,
940*7f2fe78bSCy Schubert &db_args);
941*7f2fe78bSCy Schubert if (status)
942*7f2fe78bSCy Schubert return status;
943*7f2fe78bSCy Schubert status = v->put_principal(kcontext, entry, db_args);
944*7f2fe78bSCy Schubert free_db_args(db_args);
945*7f2fe78bSCy Schubert return status;
946*7f2fe78bSCy Schubert }
947*7f2fe78bSCy Schubert
948*7f2fe78bSCy Schubert krb5_error_code
krb5_db_put_principal(krb5_context kcontext,krb5_db_entry * entry)949*7f2fe78bSCy Schubert krb5_db_put_principal(krb5_context kcontext, krb5_db_entry *entry)
950*7f2fe78bSCy Schubert {
951*7f2fe78bSCy Schubert krb5_error_code status = 0;
952*7f2fe78bSCy Schubert kdb_incr_update_t *upd = NULL;
953*7f2fe78bSCy Schubert char *princ_name = NULL;
954*7f2fe78bSCy Schubert
955*7f2fe78bSCy Schubert if (logging(kcontext)) {
956*7f2fe78bSCy Schubert upd = k5alloc(sizeof(*upd), &status);
957*7f2fe78bSCy Schubert if (upd == NULL)
958*7f2fe78bSCy Schubert goto cleanup;
959*7f2fe78bSCy Schubert if ((status = ulog_conv_2logentry(kcontext, entry, upd)))
960*7f2fe78bSCy Schubert goto cleanup;
961*7f2fe78bSCy Schubert
962*7f2fe78bSCy Schubert status = krb5_unparse_name(kcontext, entry->princ, &princ_name);
963*7f2fe78bSCy Schubert if (status != 0)
964*7f2fe78bSCy Schubert goto cleanup;
965*7f2fe78bSCy Schubert
966*7f2fe78bSCy Schubert upd->kdb_princ_name.utf8str_t_val = princ_name;
967*7f2fe78bSCy Schubert upd->kdb_princ_name.utf8str_t_len = strlen(princ_name);
968*7f2fe78bSCy Schubert }
969*7f2fe78bSCy Schubert
970*7f2fe78bSCy Schubert status = krb5int_put_principal_no_log(kcontext, entry);
971*7f2fe78bSCy Schubert if (status)
972*7f2fe78bSCy Schubert goto cleanup;
973*7f2fe78bSCy Schubert
974*7f2fe78bSCy Schubert if (logging(kcontext))
975*7f2fe78bSCy Schubert status = ulog_add_update(kcontext, upd);
976*7f2fe78bSCy Schubert
977*7f2fe78bSCy Schubert cleanup:
978*7f2fe78bSCy Schubert ulog_free_entries(upd, 1);
979*7f2fe78bSCy Schubert return status;
980*7f2fe78bSCy Schubert }
981*7f2fe78bSCy Schubert
982*7f2fe78bSCy Schubert krb5_error_code
krb5int_delete_principal_no_log(krb5_context kcontext,krb5_principal search_for)983*7f2fe78bSCy Schubert krb5int_delete_principal_no_log(krb5_context kcontext,
984*7f2fe78bSCy Schubert krb5_principal search_for)
985*7f2fe78bSCy Schubert {
986*7f2fe78bSCy Schubert kdb_vftabl *v;
987*7f2fe78bSCy Schubert krb5_error_code status;
988*7f2fe78bSCy Schubert
989*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
990*7f2fe78bSCy Schubert if (status)
991*7f2fe78bSCy Schubert return status;
992*7f2fe78bSCy Schubert if (v->delete_principal == NULL)
993*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
994*7f2fe78bSCy Schubert return v->delete_principal(kcontext, search_for);
995*7f2fe78bSCy Schubert }
996*7f2fe78bSCy Schubert
997*7f2fe78bSCy Schubert krb5_error_code
krb5_db_delete_principal(krb5_context kcontext,krb5_principal search_for)998*7f2fe78bSCy Schubert krb5_db_delete_principal(krb5_context kcontext, krb5_principal search_for)
999*7f2fe78bSCy Schubert {
1000*7f2fe78bSCy Schubert krb5_error_code status = 0;
1001*7f2fe78bSCy Schubert kdb_incr_update_t upd;
1002*7f2fe78bSCy Schubert char *princ_name = NULL;
1003*7f2fe78bSCy Schubert
1004*7f2fe78bSCy Schubert status = krb5int_delete_principal_no_log(kcontext, search_for);
1005*7f2fe78bSCy Schubert if (status || !logging(kcontext))
1006*7f2fe78bSCy Schubert return status;
1007*7f2fe78bSCy Schubert
1008*7f2fe78bSCy Schubert status = krb5_unparse_name(kcontext, search_for, &princ_name);
1009*7f2fe78bSCy Schubert if (status)
1010*7f2fe78bSCy Schubert return status;
1011*7f2fe78bSCy Schubert
1012*7f2fe78bSCy Schubert memset(&upd, 0, sizeof(kdb_incr_update_t));
1013*7f2fe78bSCy Schubert upd.kdb_princ_name.utf8str_t_val = princ_name;
1014*7f2fe78bSCy Schubert upd.kdb_princ_name.utf8str_t_len = strlen(princ_name);
1015*7f2fe78bSCy Schubert upd.kdb_deleted = TRUE;
1016*7f2fe78bSCy Schubert
1017*7f2fe78bSCy Schubert status = ulog_add_update(kcontext, &upd);
1018*7f2fe78bSCy Schubert free(princ_name);
1019*7f2fe78bSCy Schubert return status;
1020*7f2fe78bSCy Schubert }
1021*7f2fe78bSCy Schubert
1022*7f2fe78bSCy Schubert krb5_error_code
krb5_db_rename_principal(krb5_context kcontext,krb5_principal source,krb5_principal target)1023*7f2fe78bSCy Schubert krb5_db_rename_principal(krb5_context kcontext, krb5_principal source,
1024*7f2fe78bSCy Schubert krb5_principal target)
1025*7f2fe78bSCy Schubert {
1026*7f2fe78bSCy Schubert kdb_vftabl *v;
1027*7f2fe78bSCy Schubert krb5_error_code status;
1028*7f2fe78bSCy Schubert krb5_db_entry *entry;
1029*7f2fe78bSCy Schubert
1030*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
1031*7f2fe78bSCy Schubert if (status)
1032*7f2fe78bSCy Schubert return status;
1033*7f2fe78bSCy Schubert
1034*7f2fe78bSCy Schubert /*
1035*7f2fe78bSCy Schubert * If the default rename function isn't used and logging is enabled, iprop
1036*7f2fe78bSCy Schubert * would fail since it doesn't formally support renaming. In that case
1037*7f2fe78bSCy Schubert * return KRB5_PLUGIN_OP_NOTSUPP.
1038*7f2fe78bSCy Schubert */
1039*7f2fe78bSCy Schubert if (v->rename_principal != krb5_db_def_rename_principal &&
1040*7f2fe78bSCy Schubert logging(kcontext))
1041*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
1042*7f2fe78bSCy Schubert
1043*7f2fe78bSCy Schubert status = krb5_db_get_principal(kcontext, target, 0, &entry);
1044*7f2fe78bSCy Schubert if (status == 0) {
1045*7f2fe78bSCy Schubert krb5_db_free_principal(kcontext, entry);
1046*7f2fe78bSCy Schubert return KRB5_KDB_INUSE;
1047*7f2fe78bSCy Schubert }
1048*7f2fe78bSCy Schubert
1049*7f2fe78bSCy Schubert return v->rename_principal(kcontext, source, target);
1050*7f2fe78bSCy Schubert }
1051*7f2fe78bSCy Schubert
1052*7f2fe78bSCy Schubert /*
1053*7f2fe78bSCy Schubert * Use a proxy function for iterate so that we can sort the keys before sending
1054*7f2fe78bSCy Schubert * them to the callback.
1055*7f2fe78bSCy Schubert */
1056*7f2fe78bSCy Schubert struct callback_proxy_args {
1057*7f2fe78bSCy Schubert int (*func)(krb5_pointer, krb5_db_entry *);
1058*7f2fe78bSCy Schubert krb5_pointer func_arg;
1059*7f2fe78bSCy Schubert };
1060*7f2fe78bSCy Schubert
1061*7f2fe78bSCy Schubert static int
sort_entry_callback_proxy(krb5_pointer func_arg,krb5_db_entry * entry)1062*7f2fe78bSCy Schubert sort_entry_callback_proxy(krb5_pointer func_arg, krb5_db_entry *entry)
1063*7f2fe78bSCy Schubert {
1064*7f2fe78bSCy Schubert struct callback_proxy_args *args = (struct callback_proxy_args *)func_arg;
1065*7f2fe78bSCy Schubert
1066*7f2fe78bSCy Schubert /* Sort the keys in the db entry as some parts of krb5 expect it to be. */
1067*7f2fe78bSCy Schubert if (entry && entry->key_data)
1068*7f2fe78bSCy Schubert krb5_dbe_sort_key_data(entry->key_data, entry->n_key_data);
1069*7f2fe78bSCy Schubert return args->func(args->func_arg, entry);
1070*7f2fe78bSCy Schubert }
1071*7f2fe78bSCy Schubert
1072*7f2fe78bSCy Schubert krb5_error_code
krb5_db_iterate(krb5_context kcontext,char * match_entry,int (* func)(krb5_pointer,krb5_db_entry *),krb5_pointer func_arg,krb5_flags iterflags)1073*7f2fe78bSCy Schubert krb5_db_iterate(krb5_context kcontext, char *match_entry,
1074*7f2fe78bSCy Schubert int (*func)(krb5_pointer, krb5_db_entry *),
1075*7f2fe78bSCy Schubert krb5_pointer func_arg, krb5_flags iterflags)
1076*7f2fe78bSCy Schubert {
1077*7f2fe78bSCy Schubert krb5_error_code status = 0;
1078*7f2fe78bSCy Schubert kdb_vftabl *v;
1079*7f2fe78bSCy Schubert struct callback_proxy_args proxy_args;
1080*7f2fe78bSCy Schubert
1081*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
1082*7f2fe78bSCy Schubert if (status)
1083*7f2fe78bSCy Schubert return status;
1084*7f2fe78bSCy Schubert if (v->iterate == NULL)
1085*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
1086*7f2fe78bSCy Schubert
1087*7f2fe78bSCy Schubert /* Use the proxy function to sort key data before passing entries to
1088*7f2fe78bSCy Schubert * callback. */
1089*7f2fe78bSCy Schubert proxy_args.func = func;
1090*7f2fe78bSCy Schubert proxy_args.func_arg = func_arg;
1091*7f2fe78bSCy Schubert return v->iterate(kcontext, match_entry, sort_entry_callback_proxy,
1092*7f2fe78bSCy Schubert &proxy_args, iterflags);
1093*7f2fe78bSCy Schubert }
1094*7f2fe78bSCy Schubert
1095*7f2fe78bSCy Schubert /* Return a read only pointer alias to mkey list. Do not free this! */
1096*7f2fe78bSCy Schubert krb5_keylist_node *
krb5_db_mkey_list_alias(krb5_context kcontext)1097*7f2fe78bSCy Schubert krb5_db_mkey_list_alias(krb5_context kcontext)
1098*7f2fe78bSCy Schubert {
1099*7f2fe78bSCy Schubert return kcontext->dal_handle->master_keylist;
1100*7f2fe78bSCy Schubert }
1101*7f2fe78bSCy Schubert
1102*7f2fe78bSCy Schubert krb5_error_code
krb5_db_fetch_mkey_list(krb5_context context,krb5_principal mname,const krb5_keyblock * mkey)1103*7f2fe78bSCy Schubert krb5_db_fetch_mkey_list(krb5_context context, krb5_principal mname,
1104*7f2fe78bSCy Schubert const krb5_keyblock *mkey)
1105*7f2fe78bSCy Schubert {
1106*7f2fe78bSCy Schubert kdb_vftabl *v;
1107*7f2fe78bSCy Schubert krb5_error_code status = 0;
1108*7f2fe78bSCy Schubert krb5_keylist_node *local_keylist;
1109*7f2fe78bSCy Schubert
1110*7f2fe78bSCy Schubert status = get_vftabl(context, &v);
1111*7f2fe78bSCy Schubert if (status)
1112*7f2fe78bSCy Schubert return status;
1113*7f2fe78bSCy Schubert
1114*7f2fe78bSCy Schubert if (!context->dal_handle->master_princ) {
1115*7f2fe78bSCy Schubert status = krb5_copy_principal(context, mname,
1116*7f2fe78bSCy Schubert &context->dal_handle->master_princ);
1117*7f2fe78bSCy Schubert if (status)
1118*7f2fe78bSCy Schubert return status;
1119*7f2fe78bSCy Schubert }
1120*7f2fe78bSCy Schubert
1121*7f2fe78bSCy Schubert status = v->fetch_master_key_list(context, mname, mkey, &local_keylist);
1122*7f2fe78bSCy Schubert if (status == 0) {
1123*7f2fe78bSCy Schubert free_mkey_list(context, context->dal_handle->master_keylist);
1124*7f2fe78bSCy Schubert context->dal_handle->master_keylist = local_keylist;
1125*7f2fe78bSCy Schubert }
1126*7f2fe78bSCy Schubert return status;
1127*7f2fe78bSCy Schubert }
1128*7f2fe78bSCy Schubert
1129*7f2fe78bSCy Schubert krb5_error_code
krb5_db_store_master_key(krb5_context kcontext,char * keyfile,krb5_principal mname,krb5_kvno kvno,krb5_keyblock * key,char * master_pwd)1130*7f2fe78bSCy Schubert krb5_db_store_master_key(krb5_context kcontext, char *keyfile,
1131*7f2fe78bSCy Schubert krb5_principal mname, krb5_kvno kvno,
1132*7f2fe78bSCy Schubert krb5_keyblock * key, char *master_pwd)
1133*7f2fe78bSCy Schubert {
1134*7f2fe78bSCy Schubert krb5_error_code status = 0;
1135*7f2fe78bSCy Schubert kdb_vftabl *v;
1136*7f2fe78bSCy Schubert krb5_keylist_node list;
1137*7f2fe78bSCy Schubert
1138*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
1139*7f2fe78bSCy Schubert if (status)
1140*7f2fe78bSCy Schubert return status;
1141*7f2fe78bSCy Schubert
1142*7f2fe78bSCy Schubert if (v->store_master_key_list == NULL)
1143*7f2fe78bSCy Schubert return KRB5_KDB_DBTYPE_NOSUP;
1144*7f2fe78bSCy Schubert
1145*7f2fe78bSCy Schubert list.kvno = kvno;
1146*7f2fe78bSCy Schubert list.keyblock = *key;
1147*7f2fe78bSCy Schubert list.next = NULL;
1148*7f2fe78bSCy Schubert
1149*7f2fe78bSCy Schubert return v->store_master_key_list(kcontext, keyfile, mname,
1150*7f2fe78bSCy Schubert &list, master_pwd);
1151*7f2fe78bSCy Schubert }
1152*7f2fe78bSCy Schubert
1153*7f2fe78bSCy Schubert krb5_error_code
krb5_db_store_master_key_list(krb5_context kcontext,char * keyfile,krb5_principal mname,char * master_pwd)1154*7f2fe78bSCy Schubert krb5_db_store_master_key_list(krb5_context kcontext, char *keyfile,
1155*7f2fe78bSCy Schubert krb5_principal mname, char *master_pwd)
1156*7f2fe78bSCy Schubert {
1157*7f2fe78bSCy Schubert krb5_error_code status = 0;
1158*7f2fe78bSCy Schubert kdb_vftabl *v;
1159*7f2fe78bSCy Schubert
1160*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
1161*7f2fe78bSCy Schubert if (status)
1162*7f2fe78bSCy Schubert return status;
1163*7f2fe78bSCy Schubert
1164*7f2fe78bSCy Schubert if (v->store_master_key_list == NULL)
1165*7f2fe78bSCy Schubert return KRB5_KDB_DBTYPE_NOSUP;
1166*7f2fe78bSCy Schubert
1167*7f2fe78bSCy Schubert if (kcontext->dal_handle->master_keylist == NULL)
1168*7f2fe78bSCy Schubert return KRB5_KDB_DBNOTINITED;
1169*7f2fe78bSCy Schubert
1170*7f2fe78bSCy Schubert return v->store_master_key_list(kcontext, keyfile, mname,
1171*7f2fe78bSCy Schubert kcontext->dal_handle->master_keylist,
1172*7f2fe78bSCy Schubert master_pwd);
1173*7f2fe78bSCy Schubert }
1174*7f2fe78bSCy Schubert
1175*7f2fe78bSCy Schubert char *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
1176*7f2fe78bSCy Schubert char *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
1177*7f2fe78bSCy Schubert
1178*7f2fe78bSCy Schubert 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_kvno * kvno,krb5_data * salt,krb5_keyblock * key)1179*7f2fe78bSCy Schubert krb5_db_fetch_mkey(krb5_context context, krb5_principal mname,
1180*7f2fe78bSCy Schubert krb5_enctype etype, krb5_boolean fromkeyboard,
1181*7f2fe78bSCy Schubert krb5_boolean twice, char *db_args, krb5_kvno *kvno,
1182*7f2fe78bSCy Schubert krb5_data *salt, krb5_keyblock *key)
1183*7f2fe78bSCy Schubert {
1184*7f2fe78bSCy Schubert krb5_error_code retval;
1185*7f2fe78bSCy Schubert char password[BUFSIZ];
1186*7f2fe78bSCy Schubert krb5_data pwd;
1187*7f2fe78bSCy Schubert unsigned int size = sizeof(password);
1188*7f2fe78bSCy Schubert krb5_keyblock tmp_key;
1189*7f2fe78bSCy Schubert
1190*7f2fe78bSCy Schubert memset(&tmp_key, 0, sizeof(tmp_key));
1191*7f2fe78bSCy Schubert
1192*7f2fe78bSCy Schubert if (fromkeyboard) {
1193*7f2fe78bSCy Schubert krb5_data scratch;
1194*7f2fe78bSCy Schubert
1195*7f2fe78bSCy Schubert if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
1196*7f2fe78bSCy Schubert twice ? krb5_mkey_pwd_prompt2 : 0,
1197*7f2fe78bSCy Schubert password, &size))) {
1198*7f2fe78bSCy Schubert goto clean_n_exit;
1199*7f2fe78bSCy Schubert }
1200*7f2fe78bSCy Schubert
1201*7f2fe78bSCy Schubert pwd.data = password;
1202*7f2fe78bSCy Schubert pwd.length = size;
1203*7f2fe78bSCy Schubert if (!salt) {
1204*7f2fe78bSCy Schubert retval = krb5_principal2salt(context, mname, &scratch);
1205*7f2fe78bSCy Schubert if (retval)
1206*7f2fe78bSCy Schubert goto clean_n_exit;
1207*7f2fe78bSCy Schubert }
1208*7f2fe78bSCy Schubert retval =
1209*7f2fe78bSCy Schubert krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch,
1210*7f2fe78bSCy Schubert key);
1211*7f2fe78bSCy Schubert /*
1212*7f2fe78bSCy Schubert * If a kvno pointer was passed in and it dereferences the IGNORE_VNO
1213*7f2fe78bSCy Schubert * value then it should be assigned the value of the kvno associated
1214*7f2fe78bSCy Schubert * with the current mkey princ key if that princ entry is available
1215*7f2fe78bSCy Schubert * otherwise assign 1 which is the default kvno value for the mkey
1216*7f2fe78bSCy Schubert * princ.
1217*7f2fe78bSCy Schubert */
1218*7f2fe78bSCy Schubert if (kvno != NULL && *kvno == IGNORE_VNO) {
1219*7f2fe78bSCy Schubert krb5_error_code rc;
1220*7f2fe78bSCy Schubert krb5_db_entry *master_entry;
1221*7f2fe78bSCy Schubert
1222*7f2fe78bSCy Schubert rc = krb5_db_get_principal(context, mname, 0, &master_entry);
1223*7f2fe78bSCy Schubert if (rc == 0 && master_entry->n_key_data > 0)
1224*7f2fe78bSCy Schubert *kvno = (krb5_kvno) master_entry->key_data->key_data_kvno;
1225*7f2fe78bSCy Schubert else
1226*7f2fe78bSCy Schubert *kvno = 1;
1227*7f2fe78bSCy Schubert if (rc == 0)
1228*7f2fe78bSCy Schubert krb5_db_free_principal(context, master_entry);
1229*7f2fe78bSCy Schubert }
1230*7f2fe78bSCy Schubert
1231*7f2fe78bSCy Schubert if (!salt)
1232*7f2fe78bSCy Schubert free(scratch.data);
1233*7f2fe78bSCy Schubert zap(password, sizeof(password)); /* erase it */
1234*7f2fe78bSCy Schubert
1235*7f2fe78bSCy Schubert } else {
1236*7f2fe78bSCy Schubert kdb_vftabl *v;
1237*7f2fe78bSCy Schubert
1238*7f2fe78bSCy Schubert if (context->dal_handle == NULL) {
1239*7f2fe78bSCy Schubert retval = krb5_db_setup_lib_handle(context);
1240*7f2fe78bSCy Schubert if (retval)
1241*7f2fe78bSCy Schubert goto clean_n_exit;
1242*7f2fe78bSCy Schubert }
1243*7f2fe78bSCy Schubert
1244*7f2fe78bSCy Schubert /* get the enctype from the stash */
1245*7f2fe78bSCy Schubert tmp_key.enctype = ENCTYPE_UNKNOWN;
1246*7f2fe78bSCy Schubert
1247*7f2fe78bSCy Schubert v = &context->dal_handle->lib_handle->vftabl;
1248*7f2fe78bSCy Schubert retval = v->fetch_master_key(context, mname, &tmp_key, kvno, db_args);
1249*7f2fe78bSCy Schubert
1250*7f2fe78bSCy Schubert if (retval)
1251*7f2fe78bSCy Schubert goto clean_n_exit;
1252*7f2fe78bSCy Schubert
1253*7f2fe78bSCy Schubert key->contents = k5memdup(tmp_key.contents, tmp_key.length, &retval);
1254*7f2fe78bSCy Schubert if (key->contents == NULL)
1255*7f2fe78bSCy Schubert goto clean_n_exit;
1256*7f2fe78bSCy Schubert
1257*7f2fe78bSCy Schubert key->magic = tmp_key.magic;
1258*7f2fe78bSCy Schubert key->enctype = tmp_key.enctype;
1259*7f2fe78bSCy Schubert key->length = tmp_key.length;
1260*7f2fe78bSCy Schubert }
1261*7f2fe78bSCy Schubert
1262*7f2fe78bSCy Schubert clean_n_exit:
1263*7f2fe78bSCy Schubert zapfree(tmp_key.contents, tmp_key.length);
1264*7f2fe78bSCy Schubert return retval;
1265*7f2fe78bSCy Schubert }
1266*7f2fe78bSCy Schubert
1267*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_fetch_act_key_list(krb5_context context,krb5_principal princ,krb5_actkvno_node ** act_key_list)1268*7f2fe78bSCy Schubert krb5_dbe_fetch_act_key_list(krb5_context context, krb5_principal princ,
1269*7f2fe78bSCy Schubert krb5_actkvno_node **act_key_list)
1270*7f2fe78bSCy Schubert {
1271*7f2fe78bSCy Schubert krb5_error_code retval = 0;
1272*7f2fe78bSCy Schubert krb5_db_entry *entry;
1273*7f2fe78bSCy Schubert
1274*7f2fe78bSCy Schubert if (act_key_list == NULL)
1275*7f2fe78bSCy Schubert return (EINVAL);
1276*7f2fe78bSCy Schubert
1277*7f2fe78bSCy Schubert retval = krb5_db_get_principal(context, princ, 0, &entry);
1278*7f2fe78bSCy Schubert if (retval == KRB5_KDB_NOENTRY)
1279*7f2fe78bSCy Schubert return KRB5_KDB_NOMASTERKEY;
1280*7f2fe78bSCy Schubert else if (retval)
1281*7f2fe78bSCy Schubert return retval;
1282*7f2fe78bSCy Schubert
1283*7f2fe78bSCy Schubert retval = krb5_dbe_lookup_actkvno(context, entry, act_key_list);
1284*7f2fe78bSCy Schubert krb5_db_free_principal(context, entry);
1285*7f2fe78bSCy Schubert return retval;
1286*7f2fe78bSCy Schubert }
1287*7f2fe78bSCy Schubert
1288*7f2fe78bSCy Schubert /* Find the most recent entry in list (which must not be empty) for the given
1289*7f2fe78bSCy Schubert * timestamp, and return its kvno. */
1290*7f2fe78bSCy Schubert static krb5_kvno
find_actkvno(krb5_actkvno_node * list,krb5_timestamp now)1291*7f2fe78bSCy Schubert find_actkvno(krb5_actkvno_node *list, krb5_timestamp now)
1292*7f2fe78bSCy Schubert {
1293*7f2fe78bSCy Schubert /*
1294*7f2fe78bSCy Schubert * The list is sorted in ascending order of time. Return the kvno of the
1295*7f2fe78bSCy Schubert * predecessor of the first entry whose time is in the future. If
1296*7f2fe78bSCy Schubert * (contrary to the safety checks in kdb5_util use_mkey) all of the entries
1297*7f2fe78bSCy Schubert * are in the future, we will return the first node; if all are in the
1298*7f2fe78bSCy Schubert * past, we will return the last node.
1299*7f2fe78bSCy Schubert */
1300*7f2fe78bSCy Schubert while (list->next != NULL && !ts_after(list->next->act_time, now))
1301*7f2fe78bSCy Schubert list = list->next;
1302*7f2fe78bSCy Schubert return list->act_kvno;
1303*7f2fe78bSCy Schubert }
1304*7f2fe78bSCy Schubert
1305*7f2fe78bSCy Schubert /* Search the master keylist for the master key with the specified kvno.
1306*7f2fe78bSCy Schubert * Return the keyblock of the matching entry or NULL if it does not exist. */
1307*7f2fe78bSCy Schubert static krb5_keyblock *
find_master_key(krb5_context context,krb5_kvno kvno)1308*7f2fe78bSCy Schubert find_master_key(krb5_context context, krb5_kvno kvno)
1309*7f2fe78bSCy Schubert {
1310*7f2fe78bSCy Schubert krb5_keylist_node *n;
1311*7f2fe78bSCy Schubert
1312*7f2fe78bSCy Schubert for (n = context->dal_handle->master_keylist; n != NULL; n = n->next) {
1313*7f2fe78bSCy Schubert if (n->kvno == kvno)
1314*7f2fe78bSCy Schubert return &n->keyblock;
1315*7f2fe78bSCy Schubert }
1316*7f2fe78bSCy Schubert return NULL;
1317*7f2fe78bSCy Schubert }
1318*7f2fe78bSCy Schubert
1319*7f2fe78bSCy Schubert /*
1320*7f2fe78bSCy Schubert * Locates the "active" mkey used when encrypting a princ's keys. Note, the
1321*7f2fe78bSCy Schubert * caller must NOT free the output act_mkey.
1322*7f2fe78bSCy Schubert */
1323*7f2fe78bSCy Schubert
1324*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_find_act_mkey(krb5_context context,krb5_actkvno_node * act_mkey_list,krb5_kvno * act_kvno,krb5_keyblock ** act_mkey)1325*7f2fe78bSCy Schubert krb5_dbe_find_act_mkey(krb5_context context, krb5_actkvno_node *act_mkey_list,
1326*7f2fe78bSCy Schubert krb5_kvno *act_kvno, krb5_keyblock **act_mkey)
1327*7f2fe78bSCy Schubert {
1328*7f2fe78bSCy Schubert krb5_kvno kvno;
1329*7f2fe78bSCy Schubert krb5_error_code retval;
1330*7f2fe78bSCy Schubert krb5_keyblock *mkey, *cur_mkey;
1331*7f2fe78bSCy Schubert krb5_timestamp now;
1332*7f2fe78bSCy Schubert
1333*7f2fe78bSCy Schubert if (act_mkey_list == NULL) {
1334*7f2fe78bSCy Schubert *act_kvno = 0;
1335*7f2fe78bSCy Schubert *act_mkey = NULL;
1336*7f2fe78bSCy Schubert return 0;
1337*7f2fe78bSCy Schubert }
1338*7f2fe78bSCy Schubert
1339*7f2fe78bSCy Schubert if (context->dal_handle->master_keylist == NULL)
1340*7f2fe78bSCy Schubert return KRB5_KDB_DBNOTINITED;
1341*7f2fe78bSCy Schubert
1342*7f2fe78bSCy Schubert /* Find the currently active master key version. */
1343*7f2fe78bSCy Schubert if ((retval = krb5_timeofday(context, &now)))
1344*7f2fe78bSCy Schubert return (retval);
1345*7f2fe78bSCy Schubert kvno = find_actkvno(act_mkey_list, now);
1346*7f2fe78bSCy Schubert
1347*7f2fe78bSCy Schubert /* Find the corresponding master key. */
1348*7f2fe78bSCy Schubert mkey = find_master_key(context, kvno);
1349*7f2fe78bSCy Schubert if (mkey == NULL) {
1350*7f2fe78bSCy Schubert /* Reload the master key list and try again. */
1351*7f2fe78bSCy Schubert cur_mkey = &context->dal_handle->master_keylist->keyblock;
1352*7f2fe78bSCy Schubert if (krb5_db_fetch_mkey_list(context, context->dal_handle->master_princ,
1353*7f2fe78bSCy Schubert cur_mkey) == 0)
1354*7f2fe78bSCy Schubert mkey = find_master_key(context, kvno);
1355*7f2fe78bSCy Schubert }
1356*7f2fe78bSCy Schubert if (mkey == NULL)
1357*7f2fe78bSCy Schubert return KRB5_KDB_NO_MATCHING_KEY;
1358*7f2fe78bSCy Schubert
1359*7f2fe78bSCy Schubert *act_mkey = mkey;
1360*7f2fe78bSCy Schubert if (act_kvno != NULL)
1361*7f2fe78bSCy Schubert *act_kvno = kvno;
1362*7f2fe78bSCy Schubert return 0;
1363*7f2fe78bSCy Schubert }
1364*7f2fe78bSCy Schubert
1365*7f2fe78bSCy Schubert /*
1366*7f2fe78bSCy Schubert * Locates the mkey used to protect a princ's keys. Note, the caller must not
1367*7f2fe78bSCy Schubert * free the output key.
1368*7f2fe78bSCy Schubert */
1369*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_find_mkey(krb5_context context,krb5_db_entry * entry,krb5_keyblock ** mkey)1370*7f2fe78bSCy Schubert krb5_dbe_find_mkey(krb5_context context, krb5_db_entry *entry,
1371*7f2fe78bSCy Schubert krb5_keyblock **mkey)
1372*7f2fe78bSCy Schubert {
1373*7f2fe78bSCy Schubert krb5_kvno mkvno;
1374*7f2fe78bSCy Schubert krb5_error_code retval;
1375*7f2fe78bSCy Schubert krb5_keylist_node *cur_keyblock = context->dal_handle->master_keylist;
1376*7f2fe78bSCy Schubert
1377*7f2fe78bSCy Schubert if (!cur_keyblock)
1378*7f2fe78bSCy Schubert return KRB5_KDB_DBNOTINITED;
1379*7f2fe78bSCy Schubert
1380*7f2fe78bSCy Schubert retval = krb5_dbe_get_mkvno(context, entry, &mkvno);
1381*7f2fe78bSCy Schubert if (retval)
1382*7f2fe78bSCy Schubert return (retval);
1383*7f2fe78bSCy Schubert
1384*7f2fe78bSCy Schubert while (cur_keyblock && cur_keyblock->kvno != mkvno)
1385*7f2fe78bSCy Schubert cur_keyblock = cur_keyblock->next;
1386*7f2fe78bSCy Schubert
1387*7f2fe78bSCy Schubert if (cur_keyblock) {
1388*7f2fe78bSCy Schubert *mkey = &cur_keyblock->keyblock;
1389*7f2fe78bSCy Schubert return (0);
1390*7f2fe78bSCy Schubert } else {
1391*7f2fe78bSCy Schubert return KRB5_KDB_NO_MATCHING_KEY;
1392*7f2fe78bSCy Schubert }
1393*7f2fe78bSCy Schubert }
1394*7f2fe78bSCy Schubert
1395*7f2fe78bSCy Schubert void *
krb5_db_alloc(krb5_context kcontext,void * ptr,size_t size)1396*7f2fe78bSCy Schubert krb5_db_alloc(krb5_context kcontext, void *ptr, size_t size)
1397*7f2fe78bSCy Schubert {
1398*7f2fe78bSCy Schubert return realloc(ptr, size);
1399*7f2fe78bSCy Schubert }
1400*7f2fe78bSCy Schubert
1401*7f2fe78bSCy Schubert void
krb5_db_free(krb5_context kcontext,void * ptr)1402*7f2fe78bSCy Schubert krb5_db_free(krb5_context kcontext, void *ptr)
1403*7f2fe78bSCy Schubert {
1404*7f2fe78bSCy Schubert free(ptr);
1405*7f2fe78bSCy Schubert }
1406*7f2fe78bSCy Schubert
1407*7f2fe78bSCy Schubert /* has to be modified */
1408*7f2fe78bSCy Schubert
1409*7f2fe78bSCy Schubert 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)1410*7f2fe78bSCy Schubert krb5_dbe_find_enctype(krb5_context kcontext, krb5_db_entry *dbentp,
1411*7f2fe78bSCy Schubert krb5_int32 ktype, krb5_int32 stype, krb5_int32 kvno,
1412*7f2fe78bSCy Schubert krb5_key_data **kdatap)
1413*7f2fe78bSCy Schubert {
1414*7f2fe78bSCy Schubert krb5_int32 start = 0;
1415*7f2fe78bSCy Schubert return krb5_dbe_search_enctype(kcontext, dbentp, &start, ktype, stype,
1416*7f2fe78bSCy Schubert kvno, kdatap);
1417*7f2fe78bSCy Schubert }
1418*7f2fe78bSCy Schubert
1419*7f2fe78bSCy Schubert 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)1420*7f2fe78bSCy Schubert krb5_dbe_search_enctype(krb5_context kcontext, krb5_db_entry *dbentp,
1421*7f2fe78bSCy Schubert krb5_int32 *start, krb5_int32 ktype, krb5_int32 stype,
1422*7f2fe78bSCy Schubert krb5_int32 kvno, krb5_key_data ** kdatap)
1423*7f2fe78bSCy Schubert {
1424*7f2fe78bSCy Schubert krb5_error_code status = 0;
1425*7f2fe78bSCy Schubert kdb_vftabl *v;
1426*7f2fe78bSCy Schubert
1427*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
1428*7f2fe78bSCy Schubert if (status)
1429*7f2fe78bSCy Schubert return status;
1430*7f2fe78bSCy Schubert return v->dbe_search_enctype(kcontext, dbentp, start, ktype, stype, kvno,
1431*7f2fe78bSCy Schubert kdatap);
1432*7f2fe78bSCy Schubert }
1433*7f2fe78bSCy Schubert
1434*7f2fe78bSCy Schubert #define REALM_SEP_STRING "@"
1435*7f2fe78bSCy Schubert
1436*7f2fe78bSCy Schubert krb5_error_code
krb5_db_setup_mkey_name(krb5_context context,const char * keyname,const char * realm,char ** fullname,krb5_principal * principal)1437*7f2fe78bSCy Schubert krb5_db_setup_mkey_name(krb5_context context, const char *keyname,
1438*7f2fe78bSCy Schubert const char *realm, char **fullname,
1439*7f2fe78bSCy Schubert krb5_principal *principal)
1440*7f2fe78bSCy Schubert {
1441*7f2fe78bSCy Schubert krb5_error_code retval;
1442*7f2fe78bSCy Schubert char *fname;
1443*7f2fe78bSCy Schubert
1444*7f2fe78bSCy Schubert if (!keyname)
1445*7f2fe78bSCy Schubert keyname = KRB5_KDB_M_NAME; /* XXX external? */
1446*7f2fe78bSCy Schubert
1447*7f2fe78bSCy Schubert if (asprintf(&fname, "%s%s%s", keyname, REALM_SEP_STRING, realm) < 0)
1448*7f2fe78bSCy Schubert return ENOMEM;
1449*7f2fe78bSCy Schubert
1450*7f2fe78bSCy Schubert retval = krb5_parse_name(context, fname, principal);
1451*7f2fe78bSCy Schubert if (retval) {
1452*7f2fe78bSCy Schubert free(fname);
1453*7f2fe78bSCy Schubert return retval;
1454*7f2fe78bSCy Schubert }
1455*7f2fe78bSCy Schubert if (fullname)
1456*7f2fe78bSCy Schubert *fullname = fname;
1457*7f2fe78bSCy Schubert else
1458*7f2fe78bSCy Schubert free(fname);
1459*7f2fe78bSCy Schubert return 0;
1460*7f2fe78bSCy Schubert }
1461*7f2fe78bSCy Schubert
1462*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_lookup_last_pwd_change(krb5_context context,krb5_db_entry * entry,krb5_timestamp * stamp)1463*7f2fe78bSCy Schubert krb5_dbe_lookup_last_pwd_change(krb5_context context, krb5_db_entry *entry,
1464*7f2fe78bSCy Schubert krb5_timestamp *stamp)
1465*7f2fe78bSCy Schubert {
1466*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1467*7f2fe78bSCy Schubert krb5_error_code code;
1468*7f2fe78bSCy Schubert krb5_int32 tmp;
1469*7f2fe78bSCy Schubert
1470*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
1471*7f2fe78bSCy Schubert
1472*7f2fe78bSCy Schubert if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1473*7f2fe78bSCy Schubert return (code);
1474*7f2fe78bSCy Schubert
1475*7f2fe78bSCy Schubert if (tl_data.tl_data_length != 4) {
1476*7f2fe78bSCy Schubert *stamp = 0;
1477*7f2fe78bSCy Schubert return (0);
1478*7f2fe78bSCy Schubert }
1479*7f2fe78bSCy Schubert
1480*7f2fe78bSCy Schubert krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
1481*7f2fe78bSCy Schubert
1482*7f2fe78bSCy Schubert *stamp = (krb5_timestamp) tmp;
1483*7f2fe78bSCy Schubert
1484*7f2fe78bSCy Schubert return (0);
1485*7f2fe78bSCy Schubert }
1486*7f2fe78bSCy Schubert
1487*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_lookup_last_admin_unlock(krb5_context context,krb5_db_entry * entry,krb5_timestamp * stamp)1488*7f2fe78bSCy Schubert krb5_dbe_lookup_last_admin_unlock(krb5_context context, krb5_db_entry *entry,
1489*7f2fe78bSCy Schubert krb5_timestamp *stamp)
1490*7f2fe78bSCy Schubert {
1491*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1492*7f2fe78bSCy Schubert krb5_error_code code;
1493*7f2fe78bSCy Schubert krb5_int32 tmp;
1494*7f2fe78bSCy Schubert
1495*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_LAST_ADMIN_UNLOCK;
1496*7f2fe78bSCy Schubert
1497*7f2fe78bSCy Schubert if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1498*7f2fe78bSCy Schubert return (code);
1499*7f2fe78bSCy Schubert
1500*7f2fe78bSCy Schubert if (tl_data.tl_data_length != 4) {
1501*7f2fe78bSCy Schubert *stamp = 0;
1502*7f2fe78bSCy Schubert return (0);
1503*7f2fe78bSCy Schubert }
1504*7f2fe78bSCy Schubert
1505*7f2fe78bSCy Schubert krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
1506*7f2fe78bSCy Schubert
1507*7f2fe78bSCy Schubert *stamp = (krb5_timestamp) tmp;
1508*7f2fe78bSCy Schubert
1509*7f2fe78bSCy Schubert return (0);
1510*7f2fe78bSCy Schubert }
1511*7f2fe78bSCy Schubert
1512*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_lookup_tl_data(krb5_context context,krb5_db_entry * entry,krb5_tl_data * ret_tl_data)1513*7f2fe78bSCy Schubert krb5_dbe_lookup_tl_data(krb5_context context, krb5_db_entry *entry,
1514*7f2fe78bSCy Schubert krb5_tl_data *ret_tl_data)
1515*7f2fe78bSCy Schubert {
1516*7f2fe78bSCy Schubert krb5_tl_data *tl_data;
1517*7f2fe78bSCy Schubert
1518*7f2fe78bSCy Schubert for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
1519*7f2fe78bSCy Schubert if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
1520*7f2fe78bSCy Schubert *ret_tl_data = *tl_data;
1521*7f2fe78bSCy Schubert return (0);
1522*7f2fe78bSCy Schubert }
1523*7f2fe78bSCy Schubert }
1524*7f2fe78bSCy Schubert
1525*7f2fe78bSCy Schubert /*
1526*7f2fe78bSCy Schubert * If the requested record isn't found, return zero bytes. If it
1527*7f2fe78bSCy Schubert * ever means something to have a zero-length tl_data, this code
1528*7f2fe78bSCy Schubert * and its callers will have to be changed.
1529*7f2fe78bSCy Schubert */
1530*7f2fe78bSCy Schubert
1531*7f2fe78bSCy Schubert ret_tl_data->tl_data_length = 0;
1532*7f2fe78bSCy Schubert ret_tl_data->tl_data_contents = NULL;
1533*7f2fe78bSCy Schubert return (0);
1534*7f2fe78bSCy Schubert }
1535*7f2fe78bSCy Schubert
1536*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_create_key_data(krb5_context context,krb5_db_entry * entry)1537*7f2fe78bSCy Schubert krb5_dbe_create_key_data(krb5_context context, krb5_db_entry *entry)
1538*7f2fe78bSCy Schubert {
1539*7f2fe78bSCy Schubert krb5_key_data *newptr;
1540*7f2fe78bSCy Schubert
1541*7f2fe78bSCy Schubert newptr = realloc(entry->key_data,
1542*7f2fe78bSCy Schubert (entry->n_key_data + 1) * sizeof(*entry->key_data));
1543*7f2fe78bSCy Schubert if (newptr == NULL)
1544*7f2fe78bSCy Schubert return ENOMEM;
1545*7f2fe78bSCy Schubert entry->key_data = newptr;
1546*7f2fe78bSCy Schubert
1547*7f2fe78bSCy Schubert memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
1548*7f2fe78bSCy Schubert entry->n_key_data++;
1549*7f2fe78bSCy Schubert
1550*7f2fe78bSCy Schubert return 0;
1551*7f2fe78bSCy Schubert }
1552*7f2fe78bSCy Schubert
1553*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_update_mod_princ_data(krb5_context context,krb5_db_entry * entry,krb5_timestamp mod_date,krb5_const_principal mod_princ)1554*7f2fe78bSCy Schubert krb5_dbe_update_mod_princ_data(krb5_context context, krb5_db_entry *entry,
1555*7f2fe78bSCy Schubert krb5_timestamp mod_date,
1556*7f2fe78bSCy Schubert krb5_const_principal mod_princ)
1557*7f2fe78bSCy Schubert {
1558*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1559*7f2fe78bSCy Schubert
1560*7f2fe78bSCy Schubert krb5_error_code retval = 0;
1561*7f2fe78bSCy Schubert krb5_octet *nextloc = 0;
1562*7f2fe78bSCy Schubert char *unparse_mod_princ = 0;
1563*7f2fe78bSCy Schubert unsigned int unparse_mod_princ_size;
1564*7f2fe78bSCy Schubert
1565*7f2fe78bSCy Schubert if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ)))
1566*7f2fe78bSCy Schubert return (retval);
1567*7f2fe78bSCy Schubert
1568*7f2fe78bSCy Schubert unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
1569*7f2fe78bSCy Schubert
1570*7f2fe78bSCy Schubert if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
1571*7f2fe78bSCy Schubert == NULL) {
1572*7f2fe78bSCy Schubert free(unparse_mod_princ);
1573*7f2fe78bSCy Schubert return (ENOMEM);
1574*7f2fe78bSCy Schubert }
1575*7f2fe78bSCy Schubert
1576*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
1577*7f2fe78bSCy Schubert tl_data.tl_data_length = unparse_mod_princ_size + 4;
1578*7f2fe78bSCy Schubert tl_data.tl_data_contents = nextloc;
1579*7f2fe78bSCy Schubert
1580*7f2fe78bSCy Schubert /* Mod Date */
1581*7f2fe78bSCy Schubert krb5_kdb_encode_int32(mod_date, nextloc);
1582*7f2fe78bSCy Schubert
1583*7f2fe78bSCy Schubert /* Mod Princ */
1584*7f2fe78bSCy Schubert memcpy(nextloc + 4, unparse_mod_princ, unparse_mod_princ_size);
1585*7f2fe78bSCy Schubert
1586*7f2fe78bSCy Schubert retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
1587*7f2fe78bSCy Schubert
1588*7f2fe78bSCy Schubert free(unparse_mod_princ);
1589*7f2fe78bSCy Schubert free(nextloc);
1590*7f2fe78bSCy Schubert
1591*7f2fe78bSCy Schubert return (retval);
1592*7f2fe78bSCy Schubert }
1593*7f2fe78bSCy Schubert
1594*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_lookup_mod_princ_data(krb5_context context,krb5_db_entry * entry,krb5_timestamp * mod_time,krb5_principal * mod_princ)1595*7f2fe78bSCy Schubert krb5_dbe_lookup_mod_princ_data(krb5_context context, krb5_db_entry *entry,
1596*7f2fe78bSCy Schubert krb5_timestamp *mod_time,
1597*7f2fe78bSCy Schubert krb5_principal *mod_princ)
1598*7f2fe78bSCy Schubert {
1599*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1600*7f2fe78bSCy Schubert krb5_error_code code;
1601*7f2fe78bSCy Schubert
1602*7f2fe78bSCy Schubert *mod_princ = NULL;
1603*7f2fe78bSCy Schubert *mod_time = 0;
1604*7f2fe78bSCy Schubert
1605*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
1606*7f2fe78bSCy Schubert
1607*7f2fe78bSCy Schubert if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1608*7f2fe78bSCy Schubert return (code);
1609*7f2fe78bSCy Schubert
1610*7f2fe78bSCy Schubert if ((tl_data.tl_data_length < 5) ||
1611*7f2fe78bSCy Schubert (tl_data.tl_data_contents[tl_data.tl_data_length - 1] != '\0'))
1612*7f2fe78bSCy Schubert return (KRB5_KDB_TRUNCATED_RECORD);
1613*7f2fe78bSCy Schubert
1614*7f2fe78bSCy Schubert /* Mod Date */
1615*7f2fe78bSCy Schubert krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
1616*7f2fe78bSCy Schubert
1617*7f2fe78bSCy Schubert /* Mod Princ */
1618*7f2fe78bSCy Schubert if ((code = krb5_parse_name(context,
1619*7f2fe78bSCy Schubert (const char *) (tl_data.tl_data_contents + 4),
1620*7f2fe78bSCy Schubert mod_princ)))
1621*7f2fe78bSCy Schubert return (code);
1622*7f2fe78bSCy Schubert
1623*7f2fe78bSCy Schubert return (0);
1624*7f2fe78bSCy Schubert }
1625*7f2fe78bSCy Schubert
1626*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_lookup_mkvno(krb5_context context,krb5_db_entry * entry,krb5_kvno * mkvno)1627*7f2fe78bSCy Schubert krb5_dbe_lookup_mkvno(krb5_context context, krb5_db_entry *entry,
1628*7f2fe78bSCy Schubert krb5_kvno *mkvno)
1629*7f2fe78bSCy Schubert {
1630*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1631*7f2fe78bSCy Schubert krb5_error_code code;
1632*7f2fe78bSCy Schubert krb5_int16 tmp;
1633*7f2fe78bSCy Schubert
1634*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_MKVNO;
1635*7f2fe78bSCy Schubert
1636*7f2fe78bSCy Schubert if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1637*7f2fe78bSCy Schubert return (code);
1638*7f2fe78bSCy Schubert
1639*7f2fe78bSCy Schubert if (tl_data.tl_data_length == 0) {
1640*7f2fe78bSCy Schubert *mkvno = 0; /* Indicates KRB5_TL_MKVNO data not present */
1641*7f2fe78bSCy Schubert return (0);
1642*7f2fe78bSCy Schubert } else if (tl_data.tl_data_length != 2) {
1643*7f2fe78bSCy Schubert return (KRB5_KDB_TRUNCATED_RECORD);
1644*7f2fe78bSCy Schubert }
1645*7f2fe78bSCy Schubert
1646*7f2fe78bSCy Schubert krb5_kdb_decode_int16(tl_data.tl_data_contents, tmp);
1647*7f2fe78bSCy Schubert *mkvno = (krb5_kvno) tmp;
1648*7f2fe78bSCy Schubert return (0);
1649*7f2fe78bSCy Schubert }
1650*7f2fe78bSCy Schubert
1651*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_get_mkvno(krb5_context context,krb5_db_entry * entry,krb5_kvno * mkvno)1652*7f2fe78bSCy Schubert krb5_dbe_get_mkvno(krb5_context context, krb5_db_entry *entry,
1653*7f2fe78bSCy Schubert krb5_kvno *mkvno)
1654*7f2fe78bSCy Schubert {
1655*7f2fe78bSCy Schubert krb5_error_code code;
1656*7f2fe78bSCy Schubert krb5_kvno kvno;
1657*7f2fe78bSCy Schubert krb5_keylist_node *mkey_list = context->dal_handle->master_keylist;
1658*7f2fe78bSCy Schubert
1659*7f2fe78bSCy Schubert if (mkey_list == NULL)
1660*7f2fe78bSCy Schubert return KRB5_KDB_DBNOTINITED;
1661*7f2fe78bSCy Schubert
1662*7f2fe78bSCy Schubert /* Output the value from entry tl_data if present. */
1663*7f2fe78bSCy Schubert code = krb5_dbe_lookup_mkvno(context, entry, &kvno);
1664*7f2fe78bSCy Schubert if (code != 0)
1665*7f2fe78bSCy Schubert return code;
1666*7f2fe78bSCy Schubert if (kvno != 0) {
1667*7f2fe78bSCy Schubert *mkvno = kvno;
1668*7f2fe78bSCy Schubert return 0;
1669*7f2fe78bSCy Schubert }
1670*7f2fe78bSCy Schubert
1671*7f2fe78bSCy Schubert /* Determine the minimum kvno in mkey_list and output that. */
1672*7f2fe78bSCy Schubert kvno = (krb5_kvno) -1;
1673*7f2fe78bSCy Schubert while (mkey_list != NULL) {
1674*7f2fe78bSCy Schubert if (mkey_list->kvno < kvno)
1675*7f2fe78bSCy Schubert kvno = mkey_list->kvno;
1676*7f2fe78bSCy Schubert mkey_list = mkey_list->next;
1677*7f2fe78bSCy Schubert }
1678*7f2fe78bSCy Schubert *mkvno = kvno;
1679*7f2fe78bSCy Schubert return 0;
1680*7f2fe78bSCy Schubert }
1681*7f2fe78bSCy Schubert
1682*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_update_mkvno(krb5_context context,krb5_db_entry * entry,krb5_kvno mkvno)1683*7f2fe78bSCy Schubert krb5_dbe_update_mkvno(krb5_context context, krb5_db_entry *entry,
1684*7f2fe78bSCy Schubert krb5_kvno mkvno)
1685*7f2fe78bSCy Schubert {
1686*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1687*7f2fe78bSCy Schubert krb5_octet buf[2]; /* this is the encoded size of an int16 */
1688*7f2fe78bSCy Schubert krb5_int16 tmp_kvno = (krb5_int16) mkvno;
1689*7f2fe78bSCy Schubert
1690*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_MKVNO;
1691*7f2fe78bSCy Schubert tl_data.tl_data_length = sizeof(buf);
1692*7f2fe78bSCy Schubert krb5_kdb_encode_int16(tmp_kvno, buf);
1693*7f2fe78bSCy Schubert tl_data.tl_data_contents = buf;
1694*7f2fe78bSCy Schubert
1695*7f2fe78bSCy Schubert return (krb5_dbe_update_tl_data(context, entry, &tl_data));
1696*7f2fe78bSCy Schubert }
1697*7f2fe78bSCy Schubert
1698*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_lookup_mkey_aux(krb5_context context,krb5_db_entry * entry,krb5_mkey_aux_node ** mkey_aux_data_list)1699*7f2fe78bSCy Schubert krb5_dbe_lookup_mkey_aux(krb5_context context, krb5_db_entry *entry,
1700*7f2fe78bSCy Schubert krb5_mkey_aux_node **mkey_aux_data_list)
1701*7f2fe78bSCy Schubert {
1702*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1703*7f2fe78bSCy Schubert krb5_int16 version, mkey_kvno;
1704*7f2fe78bSCy Schubert krb5_mkey_aux_node *head_data = NULL, *new_data = NULL,
1705*7f2fe78bSCy Schubert *prev_data = NULL;
1706*7f2fe78bSCy Schubert krb5_octet *curloc; /* current location pointer */
1707*7f2fe78bSCy Schubert krb5_error_code code;
1708*7f2fe78bSCy Schubert
1709*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_MKEY_AUX;
1710*7f2fe78bSCy Schubert if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1711*7f2fe78bSCy Schubert return (code);
1712*7f2fe78bSCy Schubert
1713*7f2fe78bSCy Schubert if (tl_data.tl_data_contents == NULL) {
1714*7f2fe78bSCy Schubert *mkey_aux_data_list = NULL;
1715*7f2fe78bSCy Schubert return (0);
1716*7f2fe78bSCy Schubert } else {
1717*7f2fe78bSCy Schubert /* get version to determine how to parse the data */
1718*7f2fe78bSCy Schubert krb5_kdb_decode_int16(tl_data.tl_data_contents, version);
1719*7f2fe78bSCy Schubert if (version == 1) {
1720*7f2fe78bSCy Schubert /* variable size, must be at least 10 bytes */
1721*7f2fe78bSCy Schubert if (tl_data.tl_data_length < 10)
1722*7f2fe78bSCy Schubert return (KRB5_KDB_TRUNCATED_RECORD);
1723*7f2fe78bSCy Schubert
1724*7f2fe78bSCy Schubert /* curloc points to first tuple entry in the tl_data_contents */
1725*7f2fe78bSCy Schubert curloc = tl_data.tl_data_contents + sizeof(version);
1726*7f2fe78bSCy Schubert
1727*7f2fe78bSCy Schubert while (curloc < (tl_data.tl_data_contents + tl_data.tl_data_length)) {
1728*7f2fe78bSCy Schubert
1729*7f2fe78bSCy Schubert new_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node));
1730*7f2fe78bSCy Schubert if (new_data == NULL) {
1731*7f2fe78bSCy Schubert krb5_dbe_free_mkey_aux_list(context, head_data);
1732*7f2fe78bSCy Schubert return (ENOMEM);
1733*7f2fe78bSCy Schubert }
1734*7f2fe78bSCy Schubert memset(new_data, 0, sizeof(krb5_mkey_aux_node));
1735*7f2fe78bSCy Schubert
1736*7f2fe78bSCy Schubert krb5_kdb_decode_int16(curloc, mkey_kvno);
1737*7f2fe78bSCy Schubert new_data->mkey_kvno = mkey_kvno;
1738*7f2fe78bSCy Schubert curloc += sizeof(krb5_ui_2);
1739*7f2fe78bSCy Schubert krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_kvno);
1740*7f2fe78bSCy Schubert curloc += sizeof(krb5_ui_2);
1741*7f2fe78bSCy Schubert krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_type[0]);
1742*7f2fe78bSCy Schubert curloc += sizeof(krb5_ui_2);
1743*7f2fe78bSCy Schubert krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_length[0]);
1744*7f2fe78bSCy Schubert curloc += sizeof(krb5_ui_2);
1745*7f2fe78bSCy Schubert
1746*7f2fe78bSCy Schubert new_data->latest_mkey.key_data_contents[0] = (krb5_octet *)
1747*7f2fe78bSCy Schubert malloc(new_data->latest_mkey.key_data_length[0]);
1748*7f2fe78bSCy Schubert
1749*7f2fe78bSCy Schubert if (new_data->latest_mkey.key_data_contents[0] == NULL) {
1750*7f2fe78bSCy Schubert krb5_dbe_free_mkey_aux_list(context, head_data);
1751*7f2fe78bSCy Schubert free(new_data);
1752*7f2fe78bSCy Schubert return (ENOMEM);
1753*7f2fe78bSCy Schubert }
1754*7f2fe78bSCy Schubert memcpy(new_data->latest_mkey.key_data_contents[0], curloc,
1755*7f2fe78bSCy Schubert new_data->latest_mkey.key_data_length[0]);
1756*7f2fe78bSCy Schubert curloc += new_data->latest_mkey.key_data_length[0];
1757*7f2fe78bSCy Schubert
1758*7f2fe78bSCy Schubert /* always using key data ver 1 for mkeys */
1759*7f2fe78bSCy Schubert new_data->latest_mkey.key_data_ver = 1;
1760*7f2fe78bSCy Schubert
1761*7f2fe78bSCy Schubert new_data->next = NULL;
1762*7f2fe78bSCy Schubert if (prev_data != NULL)
1763*7f2fe78bSCy Schubert prev_data->next = new_data;
1764*7f2fe78bSCy Schubert else
1765*7f2fe78bSCy Schubert head_data = new_data;
1766*7f2fe78bSCy Schubert prev_data = new_data;
1767*7f2fe78bSCy Schubert }
1768*7f2fe78bSCy Schubert } else {
1769*7f2fe78bSCy Schubert k5_setmsg(context, KRB5_KDB_BAD_VERSION,
1770*7f2fe78bSCy Schubert _("Illegal version number for KRB5_TL_MKEY_AUX %d\n"),
1771*7f2fe78bSCy Schubert version);
1772*7f2fe78bSCy Schubert return (KRB5_KDB_BAD_VERSION);
1773*7f2fe78bSCy Schubert }
1774*7f2fe78bSCy Schubert }
1775*7f2fe78bSCy Schubert *mkey_aux_data_list = head_data;
1776*7f2fe78bSCy Schubert return (0);
1777*7f2fe78bSCy Schubert }
1778*7f2fe78bSCy Schubert
1779*7f2fe78bSCy Schubert #if KRB5_TL_MKEY_AUX_VER == 1
1780*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_update_mkey_aux(krb5_context context,krb5_db_entry * entry,krb5_mkey_aux_node * mkey_aux_data_list)1781*7f2fe78bSCy Schubert krb5_dbe_update_mkey_aux(krb5_context context, krb5_db_entry *entry,
1782*7f2fe78bSCy Schubert krb5_mkey_aux_node *mkey_aux_data_list)
1783*7f2fe78bSCy Schubert {
1784*7f2fe78bSCy Schubert krb5_error_code status;
1785*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1786*7f2fe78bSCy Schubert krb5_int16 version, tmp_kvno;
1787*7f2fe78bSCy Schubert unsigned char *nextloc;
1788*7f2fe78bSCy Schubert krb5_mkey_aux_node *aux_data_entry;
1789*7f2fe78bSCy Schubert
1790*7f2fe78bSCy Schubert if (!mkey_aux_data_list) {
1791*7f2fe78bSCy Schubert /* delete the KRB5_TL_MKEY_AUX from the entry */
1792*7f2fe78bSCy Schubert krb5_dbe_delete_tl_data(context, entry, KRB5_TL_MKEY_AUX);
1793*7f2fe78bSCy Schubert return (0);
1794*7f2fe78bSCy Schubert }
1795*7f2fe78bSCy Schubert
1796*7f2fe78bSCy Schubert memset(&tl_data, 0, sizeof(tl_data));
1797*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_MKEY_AUX;
1798*7f2fe78bSCy Schubert /*
1799*7f2fe78bSCy Schubert * determine out how much space to allocate. Note key_data_ver not stored
1800*7f2fe78bSCy Schubert * as this is hard coded to one and is accounted for in
1801*7f2fe78bSCy Schubert * krb5_dbe_lookup_mkey_aux.
1802*7f2fe78bSCy Schubert */
1803*7f2fe78bSCy Schubert tl_data.tl_data_length = sizeof(version); /* version */
1804*7f2fe78bSCy Schubert for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL;
1805*7f2fe78bSCy Schubert aux_data_entry = aux_data_entry->next) {
1806*7f2fe78bSCy Schubert
1807*7f2fe78bSCy Schubert tl_data.tl_data_length += (sizeof(krb5_ui_2) + /* mkey_kvno */
1808*7f2fe78bSCy Schubert sizeof(krb5_ui_2) + /* latest_mkey kvno */
1809*7f2fe78bSCy Schubert sizeof(krb5_ui_2) + /* latest_mkey enctype */
1810*7f2fe78bSCy Schubert sizeof(krb5_ui_2) + /* latest_mkey length */
1811*7f2fe78bSCy Schubert aux_data_entry->latest_mkey.key_data_length[0]);
1812*7f2fe78bSCy Schubert }
1813*7f2fe78bSCy Schubert
1814*7f2fe78bSCy Schubert tl_data.tl_data_contents = (krb5_octet *) malloc(tl_data.tl_data_length);
1815*7f2fe78bSCy Schubert if (tl_data.tl_data_contents == NULL)
1816*7f2fe78bSCy Schubert return (ENOMEM);
1817*7f2fe78bSCy Schubert
1818*7f2fe78bSCy Schubert nextloc = tl_data.tl_data_contents;
1819*7f2fe78bSCy Schubert version = KRB5_TL_MKEY_AUX_VER;
1820*7f2fe78bSCy Schubert krb5_kdb_encode_int16(version, nextloc);
1821*7f2fe78bSCy Schubert nextloc += sizeof(krb5_ui_2);
1822*7f2fe78bSCy Schubert
1823*7f2fe78bSCy Schubert for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL;
1824*7f2fe78bSCy Schubert aux_data_entry = aux_data_entry->next) {
1825*7f2fe78bSCy Schubert
1826*7f2fe78bSCy Schubert tmp_kvno = (krb5_int16) aux_data_entry->mkey_kvno;
1827*7f2fe78bSCy Schubert krb5_kdb_encode_int16(tmp_kvno, nextloc);
1828*7f2fe78bSCy Schubert nextloc += sizeof(krb5_ui_2);
1829*7f2fe78bSCy Schubert
1830*7f2fe78bSCy Schubert krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_kvno,
1831*7f2fe78bSCy Schubert nextloc);
1832*7f2fe78bSCy Schubert nextloc += sizeof(krb5_ui_2);
1833*7f2fe78bSCy Schubert
1834*7f2fe78bSCy Schubert krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_type[0],
1835*7f2fe78bSCy Schubert nextloc);
1836*7f2fe78bSCy Schubert nextloc += sizeof(krb5_ui_2);
1837*7f2fe78bSCy Schubert
1838*7f2fe78bSCy Schubert krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_length[0],
1839*7f2fe78bSCy Schubert nextloc);
1840*7f2fe78bSCy Schubert nextloc += sizeof(krb5_ui_2);
1841*7f2fe78bSCy Schubert
1842*7f2fe78bSCy Schubert if (aux_data_entry->latest_mkey.key_data_length[0] > 0) {
1843*7f2fe78bSCy Schubert memcpy(nextloc, aux_data_entry->latest_mkey.key_data_contents[0],
1844*7f2fe78bSCy Schubert aux_data_entry->latest_mkey.key_data_length[0]);
1845*7f2fe78bSCy Schubert nextloc += aux_data_entry->latest_mkey.key_data_length[0];
1846*7f2fe78bSCy Schubert }
1847*7f2fe78bSCy Schubert }
1848*7f2fe78bSCy Schubert
1849*7f2fe78bSCy Schubert status = krb5_dbe_update_tl_data(context, entry, &tl_data);
1850*7f2fe78bSCy Schubert free(tl_data.tl_data_contents);
1851*7f2fe78bSCy Schubert return status;
1852*7f2fe78bSCy Schubert }
1853*7f2fe78bSCy Schubert #endif /* KRB5_TL_MKEY_AUX_VER == 1 */
1854*7f2fe78bSCy Schubert
1855*7f2fe78bSCy Schubert #if KRB5_TL_ACTKVNO_VER == 1
1856*7f2fe78bSCy Schubert /*
1857*7f2fe78bSCy Schubert * If version of the KRB5_TL_ACTKVNO data is KRB5_TL_ACTKVNO_VER == 1 then size of
1858*7f2fe78bSCy Schubert * a actkvno tuple {act_kvno, act_time} entry is:
1859*7f2fe78bSCy Schubert */
1860*7f2fe78bSCy Schubert #define ACTKVNO_TUPLE_SIZE (sizeof(krb5_int16) + sizeof(krb5_int32))
1861*7f2fe78bSCy Schubert #define act_kvno(cp) (cp) /* return pointer to start of act_kvno data */
1862*7f2fe78bSCy Schubert #define act_time(cp) ((cp) + sizeof(krb5_int16)) /* return pointer to start of act_time data */
1863*7f2fe78bSCy Schubert #endif
1864*7f2fe78bSCy Schubert
1865*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_lookup_actkvno(krb5_context context,krb5_db_entry * entry,krb5_actkvno_node ** actkvno_list)1866*7f2fe78bSCy Schubert krb5_dbe_lookup_actkvno(krb5_context context, krb5_db_entry *entry,
1867*7f2fe78bSCy Schubert krb5_actkvno_node **actkvno_list)
1868*7f2fe78bSCy Schubert {
1869*7f2fe78bSCy Schubert krb5_tl_data tl_data;
1870*7f2fe78bSCy Schubert krb5_error_code code;
1871*7f2fe78bSCy Schubert krb5_int16 version, tmp_kvno;
1872*7f2fe78bSCy Schubert krb5_actkvno_node *head_data = NULL, *new_data = NULL, *prev_data = NULL;
1873*7f2fe78bSCy Schubert unsigned int num_actkvno, i;
1874*7f2fe78bSCy Schubert krb5_octet *next_tuple;
1875*7f2fe78bSCy Schubert krb5_kvno earliest_kvno;
1876*7f2fe78bSCy Schubert
1877*7f2fe78bSCy Schubert memset(&tl_data, 0, sizeof(tl_data));
1878*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_ACTKVNO;
1879*7f2fe78bSCy Schubert
1880*7f2fe78bSCy Schubert if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
1881*7f2fe78bSCy Schubert return (code);
1882*7f2fe78bSCy Schubert
1883*7f2fe78bSCy Schubert if (tl_data.tl_data_contents == NULL) {
1884*7f2fe78bSCy Schubert /*
1885*7f2fe78bSCy Schubert * If there is no KRB5_TL_ACTKVNO data (likely because the KDB was
1886*7f2fe78bSCy Schubert * created prior to 1.7), synthesize the list which should have been
1887*7f2fe78bSCy Schubert * created at KDB initialization, making the earliest master key
1888*7f2fe78bSCy Schubert * active.
1889*7f2fe78bSCy Schubert */
1890*7f2fe78bSCy Schubert
1891*7f2fe78bSCy Schubert /* Get the earliest master key version. */
1892*7f2fe78bSCy Schubert if (entry->n_key_data == 0)
1893*7f2fe78bSCy Schubert return KRB5_KDB_NOMASTERKEY;
1894*7f2fe78bSCy Schubert earliest_kvno = entry->key_data[entry->n_key_data - 1].key_data_kvno;
1895*7f2fe78bSCy Schubert
1896*7f2fe78bSCy Schubert head_data = malloc(sizeof(*head_data));
1897*7f2fe78bSCy Schubert if (head_data == NULL)
1898*7f2fe78bSCy Schubert return ENOMEM;
1899*7f2fe78bSCy Schubert memset(head_data, 0, sizeof(*head_data));
1900*7f2fe78bSCy Schubert head_data->act_time = 0; /* earliest time possible */
1901*7f2fe78bSCy Schubert head_data->act_kvno = earliest_kvno;
1902*7f2fe78bSCy Schubert } else {
1903*7f2fe78bSCy Schubert /* get version to determine how to parse the data */
1904*7f2fe78bSCy Schubert krb5_kdb_decode_int16(tl_data.tl_data_contents, version);
1905*7f2fe78bSCy Schubert if (version == 1) {
1906*7f2fe78bSCy Schubert
1907*7f2fe78bSCy Schubert /* variable size, must be at least 8 bytes */
1908*7f2fe78bSCy Schubert if (tl_data.tl_data_length < 8)
1909*7f2fe78bSCy Schubert return (KRB5_KDB_TRUNCATED_RECORD);
1910*7f2fe78bSCy Schubert
1911*7f2fe78bSCy Schubert /*
1912*7f2fe78bSCy Schubert * Find number of tuple entries, remembering to account for version
1913*7f2fe78bSCy Schubert * field.
1914*7f2fe78bSCy Schubert */
1915*7f2fe78bSCy Schubert num_actkvno = (tl_data.tl_data_length - sizeof(version)) /
1916*7f2fe78bSCy Schubert ACTKVNO_TUPLE_SIZE;
1917*7f2fe78bSCy Schubert prev_data = NULL;
1918*7f2fe78bSCy Schubert /* next_tuple points to first tuple entry in the tl_data_contents */
1919*7f2fe78bSCy Schubert next_tuple = tl_data.tl_data_contents + sizeof(version);
1920*7f2fe78bSCy Schubert for (i = 0; i < num_actkvno; i++) {
1921*7f2fe78bSCy Schubert new_data = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node));
1922*7f2fe78bSCy Schubert if (new_data == NULL) {
1923*7f2fe78bSCy Schubert krb5_dbe_free_actkvno_list(context, head_data);
1924*7f2fe78bSCy Schubert return (ENOMEM);
1925*7f2fe78bSCy Schubert }
1926*7f2fe78bSCy Schubert memset(new_data, 0, sizeof(krb5_actkvno_node));
1927*7f2fe78bSCy Schubert
1928*7f2fe78bSCy Schubert /* using tmp_kvno to avoid type mismatch */
1929*7f2fe78bSCy Schubert krb5_kdb_decode_int16(act_kvno(next_tuple), tmp_kvno);
1930*7f2fe78bSCy Schubert new_data->act_kvno = (krb5_kvno) tmp_kvno;
1931*7f2fe78bSCy Schubert krb5_kdb_decode_int32(act_time(next_tuple), new_data->act_time);
1932*7f2fe78bSCy Schubert
1933*7f2fe78bSCy Schubert if (prev_data != NULL)
1934*7f2fe78bSCy Schubert prev_data->next = new_data;
1935*7f2fe78bSCy Schubert else
1936*7f2fe78bSCy Schubert head_data = new_data;
1937*7f2fe78bSCy Schubert prev_data = new_data;
1938*7f2fe78bSCy Schubert next_tuple += ACTKVNO_TUPLE_SIZE;
1939*7f2fe78bSCy Schubert }
1940*7f2fe78bSCy Schubert } else {
1941*7f2fe78bSCy Schubert k5_setmsg(context, KRB5_KDB_BAD_VERSION,
1942*7f2fe78bSCy Schubert _("Illegal version number for KRB5_TL_ACTKVNO %d\n"),
1943*7f2fe78bSCy Schubert version);
1944*7f2fe78bSCy Schubert return (KRB5_KDB_BAD_VERSION);
1945*7f2fe78bSCy Schubert }
1946*7f2fe78bSCy Schubert }
1947*7f2fe78bSCy Schubert *actkvno_list = head_data;
1948*7f2fe78bSCy Schubert return (0);
1949*7f2fe78bSCy Schubert }
1950*7f2fe78bSCy Schubert
1951*7f2fe78bSCy Schubert /*
1952*7f2fe78bSCy Schubert * Add KRB5_TL_ACTKVNO TL data entries to krb5_db_entry *entry
1953*7f2fe78bSCy Schubert */
1954*7f2fe78bSCy Schubert #if KRB5_TL_ACTKVNO_VER == 1
1955*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_update_actkvno(krb5_context context,krb5_db_entry * entry,const krb5_actkvno_node * actkvno_list)1956*7f2fe78bSCy Schubert krb5_dbe_update_actkvno(krb5_context context, krb5_db_entry *entry,
1957*7f2fe78bSCy Schubert const krb5_actkvno_node *actkvno_list)
1958*7f2fe78bSCy Schubert {
1959*7f2fe78bSCy Schubert krb5_error_code retval = 0;
1960*7f2fe78bSCy Schubert krb5_int16 version, tmp_kvno;
1961*7f2fe78bSCy Schubert krb5_tl_data new_tl_data;
1962*7f2fe78bSCy Schubert unsigned char *nextloc;
1963*7f2fe78bSCy Schubert const krb5_actkvno_node *cur_actkvno;
1964*7f2fe78bSCy Schubert krb5_octet *tmpptr;
1965*7f2fe78bSCy Schubert
1966*7f2fe78bSCy Schubert if (actkvno_list == NULL)
1967*7f2fe78bSCy Schubert return EINVAL;
1968*7f2fe78bSCy Schubert
1969*7f2fe78bSCy Schubert memset(&new_tl_data, 0, sizeof(new_tl_data));
1970*7f2fe78bSCy Schubert /* allocate initial KRB5_TL_ACTKVNO tl_data entry */
1971*7f2fe78bSCy Schubert new_tl_data.tl_data_length = sizeof(version);
1972*7f2fe78bSCy Schubert new_tl_data.tl_data_contents = (krb5_octet *) malloc(new_tl_data.tl_data_length);
1973*7f2fe78bSCy Schubert if (new_tl_data.tl_data_contents == NULL)
1974*7f2fe78bSCy Schubert return ENOMEM;
1975*7f2fe78bSCy Schubert
1976*7f2fe78bSCy Schubert /* add the current version # for the data format used for KRB5_TL_ACTKVNO */
1977*7f2fe78bSCy Schubert version = KRB5_TL_ACTKVNO_VER;
1978*7f2fe78bSCy Schubert krb5_kdb_encode_int16(version, (unsigned char *) new_tl_data.tl_data_contents);
1979*7f2fe78bSCy Schubert
1980*7f2fe78bSCy Schubert for (cur_actkvno = actkvno_list; cur_actkvno != NULL;
1981*7f2fe78bSCy Schubert cur_actkvno = cur_actkvno->next) {
1982*7f2fe78bSCy Schubert
1983*7f2fe78bSCy Schubert new_tl_data.tl_data_length += ACTKVNO_TUPLE_SIZE;
1984*7f2fe78bSCy Schubert tmpptr = realloc(new_tl_data.tl_data_contents, new_tl_data.tl_data_length);
1985*7f2fe78bSCy Schubert if (tmpptr == NULL) {
1986*7f2fe78bSCy Schubert free(new_tl_data.tl_data_contents);
1987*7f2fe78bSCy Schubert return ENOMEM;
1988*7f2fe78bSCy Schubert } else {
1989*7f2fe78bSCy Schubert new_tl_data.tl_data_contents = tmpptr;
1990*7f2fe78bSCy Schubert }
1991*7f2fe78bSCy Schubert
1992*7f2fe78bSCy Schubert /*
1993*7f2fe78bSCy Schubert * Using realloc so tl_data_contents is required to correctly calculate
1994*7f2fe78bSCy Schubert * next location to store new tuple.
1995*7f2fe78bSCy Schubert */
1996*7f2fe78bSCy Schubert nextloc = new_tl_data.tl_data_contents + new_tl_data.tl_data_length - ACTKVNO_TUPLE_SIZE;
1997*7f2fe78bSCy Schubert /* using tmp_kvno to avoid type mismatch issues */
1998*7f2fe78bSCy Schubert tmp_kvno = (krb5_int16) cur_actkvno->act_kvno;
1999*7f2fe78bSCy Schubert krb5_kdb_encode_int16(tmp_kvno, nextloc);
2000*7f2fe78bSCy Schubert nextloc += sizeof(krb5_ui_2);
2001*7f2fe78bSCy Schubert krb5_kdb_encode_int32((krb5_ui_4)cur_actkvno->act_time, nextloc);
2002*7f2fe78bSCy Schubert }
2003*7f2fe78bSCy Schubert
2004*7f2fe78bSCy Schubert new_tl_data.tl_data_type = KRB5_TL_ACTKVNO;
2005*7f2fe78bSCy Schubert retval = krb5_dbe_update_tl_data(context, entry, &new_tl_data);
2006*7f2fe78bSCy Schubert free(new_tl_data.tl_data_contents);
2007*7f2fe78bSCy Schubert
2008*7f2fe78bSCy Schubert return (retval);
2009*7f2fe78bSCy Schubert }
2010*7f2fe78bSCy Schubert #endif /* KRB5_TL_ACTKVNO_VER == 1 */
2011*7f2fe78bSCy Schubert
2012*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_update_last_pwd_change(krb5_context context,krb5_db_entry * entry,krb5_timestamp stamp)2013*7f2fe78bSCy Schubert krb5_dbe_update_last_pwd_change(krb5_context context, krb5_db_entry *entry,
2014*7f2fe78bSCy Schubert krb5_timestamp stamp)
2015*7f2fe78bSCy Schubert {
2016*7f2fe78bSCy Schubert krb5_tl_data tl_data;
2017*7f2fe78bSCy Schubert krb5_octet buf[4]; /* this is the encoded size of an int32 */
2018*7f2fe78bSCy Schubert
2019*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
2020*7f2fe78bSCy Schubert tl_data.tl_data_length = sizeof(buf);
2021*7f2fe78bSCy Schubert krb5_kdb_encode_int32((krb5_int32) stamp, buf);
2022*7f2fe78bSCy Schubert tl_data.tl_data_contents = buf;
2023*7f2fe78bSCy Schubert
2024*7f2fe78bSCy Schubert return (krb5_dbe_update_tl_data(context, entry, &tl_data));
2025*7f2fe78bSCy Schubert }
2026*7f2fe78bSCy Schubert
2027*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_update_last_admin_unlock(krb5_context context,krb5_db_entry * entry,krb5_timestamp stamp)2028*7f2fe78bSCy Schubert krb5_dbe_update_last_admin_unlock(krb5_context context, krb5_db_entry *entry,
2029*7f2fe78bSCy Schubert krb5_timestamp stamp)
2030*7f2fe78bSCy Schubert {
2031*7f2fe78bSCy Schubert krb5_tl_data tl_data;
2032*7f2fe78bSCy Schubert krb5_octet buf[4]; /* this is the encoded size of an int32 */
2033*7f2fe78bSCy Schubert
2034*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_LAST_ADMIN_UNLOCK;
2035*7f2fe78bSCy Schubert tl_data.tl_data_length = sizeof(buf);
2036*7f2fe78bSCy Schubert krb5_kdb_encode_int32((krb5_int32) stamp, buf);
2037*7f2fe78bSCy Schubert tl_data.tl_data_contents = buf;
2038*7f2fe78bSCy Schubert
2039*7f2fe78bSCy Schubert return (krb5_dbe_update_tl_data(context, entry, &tl_data));
2040*7f2fe78bSCy Schubert }
2041*7f2fe78bSCy Schubert
2042*7f2fe78bSCy Schubert /*
2043*7f2fe78bSCy Schubert * Prepare to iterate over the string attributes of entry. The returned
2044*7f2fe78bSCy Schubert * pointers are aliases into entry's tl_data (or into an empty string literal)
2045*7f2fe78bSCy Schubert * and remain valid until the entry's tl_data is changed.
2046*7f2fe78bSCy Schubert */
2047*7f2fe78bSCy Schubert static krb5_error_code
begin_attrs(krb5_context context,krb5_db_entry * entry,const char ** pos_out,const char ** end_out)2048*7f2fe78bSCy Schubert begin_attrs(krb5_context context, krb5_db_entry *entry, const char **pos_out,
2049*7f2fe78bSCy Schubert const char **end_out)
2050*7f2fe78bSCy Schubert {
2051*7f2fe78bSCy Schubert krb5_error_code code;
2052*7f2fe78bSCy Schubert krb5_tl_data tl_data;
2053*7f2fe78bSCy Schubert
2054*7f2fe78bSCy Schubert *pos_out = *end_out = NULL;
2055*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_STRING_ATTRS;
2056*7f2fe78bSCy Schubert code = krb5_dbe_lookup_tl_data(context, entry, &tl_data);
2057*7f2fe78bSCy Schubert if (code)
2058*7f2fe78bSCy Schubert return code;
2059*7f2fe78bSCy Schubert
2060*7f2fe78bSCy Schubert /* Copy the current mapping to buf, updating key with value if found. */
2061*7f2fe78bSCy Schubert *pos_out = (const char *)tl_data.tl_data_contents;
2062*7f2fe78bSCy Schubert *end_out = *pos_out + tl_data.tl_data_length;
2063*7f2fe78bSCy Schubert return 0;
2064*7f2fe78bSCy Schubert }
2065*7f2fe78bSCy Schubert
2066*7f2fe78bSCy Schubert /* Find the next key and value pair in *pos and update *pos. */
2067*7f2fe78bSCy Schubert static krb5_boolean
next_attr(const char ** pos,const char * end,const char ** key_out,const char ** val_out)2068*7f2fe78bSCy Schubert next_attr(const char **pos, const char *end, const char **key_out,
2069*7f2fe78bSCy Schubert const char **val_out)
2070*7f2fe78bSCy Schubert {
2071*7f2fe78bSCy Schubert const char *key, *key_end, *val, *val_end;
2072*7f2fe78bSCy Schubert
2073*7f2fe78bSCy Schubert *key_out = *val_out = NULL;
2074*7f2fe78bSCy Schubert if (*pos == end)
2075*7f2fe78bSCy Schubert return FALSE;
2076*7f2fe78bSCy Schubert key = *pos;
2077*7f2fe78bSCy Schubert key_end = memchr(key, '\0', end - key);
2078*7f2fe78bSCy Schubert if (key_end == NULL) /* Malformed representation; give up. */
2079*7f2fe78bSCy Schubert return FALSE;
2080*7f2fe78bSCy Schubert val = key_end + 1;
2081*7f2fe78bSCy Schubert val_end = memchr(val, '\0', end - val);
2082*7f2fe78bSCy Schubert if (val_end == NULL) /* Malformed representation; give up. */
2083*7f2fe78bSCy Schubert return FALSE;
2084*7f2fe78bSCy Schubert
2085*7f2fe78bSCy Schubert *key_out = key;
2086*7f2fe78bSCy Schubert *val_out = val;
2087*7f2fe78bSCy Schubert *pos = val_end + 1;
2088*7f2fe78bSCy Schubert return TRUE;
2089*7f2fe78bSCy Schubert }
2090*7f2fe78bSCy Schubert
2091*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_get_strings(krb5_context context,krb5_db_entry * entry,krb5_string_attr ** strings_out,int * count_out)2092*7f2fe78bSCy Schubert krb5_dbe_get_strings(krb5_context context, krb5_db_entry *entry,
2093*7f2fe78bSCy Schubert krb5_string_attr **strings_out, int *count_out)
2094*7f2fe78bSCy Schubert {
2095*7f2fe78bSCy Schubert krb5_error_code code;
2096*7f2fe78bSCy Schubert const char *pos, *end, *mapkey, *mapval;
2097*7f2fe78bSCy Schubert char *key = NULL, *val = NULL;
2098*7f2fe78bSCy Schubert krb5_string_attr *strings = NULL, *newstrings;
2099*7f2fe78bSCy Schubert int count = 0;
2100*7f2fe78bSCy Schubert
2101*7f2fe78bSCy Schubert *strings_out = NULL;
2102*7f2fe78bSCy Schubert *count_out = 0;
2103*7f2fe78bSCy Schubert code = begin_attrs(context, entry, &pos, &end);
2104*7f2fe78bSCy Schubert if (code)
2105*7f2fe78bSCy Schubert return code;
2106*7f2fe78bSCy Schubert
2107*7f2fe78bSCy Schubert while (next_attr(&pos, end, &mapkey, &mapval)) {
2108*7f2fe78bSCy Schubert /* Add a copy of mapkey and mapvalue to strings. */
2109*7f2fe78bSCy Schubert newstrings = realloc(strings, (count + 1) * sizeof(*strings));
2110*7f2fe78bSCy Schubert if (newstrings == NULL)
2111*7f2fe78bSCy Schubert goto oom;
2112*7f2fe78bSCy Schubert strings = newstrings;
2113*7f2fe78bSCy Schubert key = strdup(mapkey);
2114*7f2fe78bSCy Schubert val = strdup(mapval);
2115*7f2fe78bSCy Schubert if (key == NULL || val == NULL)
2116*7f2fe78bSCy Schubert goto oom;
2117*7f2fe78bSCy Schubert strings[count].key = key;
2118*7f2fe78bSCy Schubert strings[count].value = val;
2119*7f2fe78bSCy Schubert count++;
2120*7f2fe78bSCy Schubert }
2121*7f2fe78bSCy Schubert
2122*7f2fe78bSCy Schubert *strings_out = strings;
2123*7f2fe78bSCy Schubert *count_out = count;
2124*7f2fe78bSCy Schubert return 0;
2125*7f2fe78bSCy Schubert
2126*7f2fe78bSCy Schubert oom:
2127*7f2fe78bSCy Schubert free(key);
2128*7f2fe78bSCy Schubert free(val);
2129*7f2fe78bSCy Schubert krb5_dbe_free_strings(context, strings, count);
2130*7f2fe78bSCy Schubert return ENOMEM;
2131*7f2fe78bSCy Schubert }
2132*7f2fe78bSCy Schubert
2133*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_get_string(krb5_context context,krb5_db_entry * entry,const char * key,char ** value_out)2134*7f2fe78bSCy Schubert krb5_dbe_get_string(krb5_context context, krb5_db_entry *entry,
2135*7f2fe78bSCy Schubert const char *key, char **value_out)
2136*7f2fe78bSCy Schubert {
2137*7f2fe78bSCy Schubert krb5_error_code code;
2138*7f2fe78bSCy Schubert const char *pos, *end, *mapkey, *mapval;
2139*7f2fe78bSCy Schubert
2140*7f2fe78bSCy Schubert *value_out = NULL;
2141*7f2fe78bSCy Schubert code = begin_attrs(context, entry, &pos, &end);
2142*7f2fe78bSCy Schubert if (code)
2143*7f2fe78bSCy Schubert return code;
2144*7f2fe78bSCy Schubert while (next_attr(&pos, end, &mapkey, &mapval)) {
2145*7f2fe78bSCy Schubert if (strcmp(mapkey, key) == 0) {
2146*7f2fe78bSCy Schubert *value_out = strdup(mapval);
2147*7f2fe78bSCy Schubert return (*value_out == NULL) ? ENOMEM : 0;
2148*7f2fe78bSCy Schubert }
2149*7f2fe78bSCy Schubert }
2150*7f2fe78bSCy Schubert
2151*7f2fe78bSCy Schubert return 0;
2152*7f2fe78bSCy Schubert }
2153*7f2fe78bSCy Schubert
2154*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_set_string(krb5_context context,krb5_db_entry * entry,const char * key,const char * value)2155*7f2fe78bSCy Schubert krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry,
2156*7f2fe78bSCy Schubert const char *key, const char *value)
2157*7f2fe78bSCy Schubert {
2158*7f2fe78bSCy Schubert krb5_error_code code;
2159*7f2fe78bSCy Schubert const char *pos, *end, *mapkey, *mapval;
2160*7f2fe78bSCy Schubert struct k5buf buf = EMPTY_K5BUF;
2161*7f2fe78bSCy Schubert krb5_boolean found = FALSE;
2162*7f2fe78bSCy Schubert krb5_tl_data tl_data;
2163*7f2fe78bSCy Schubert
2164*7f2fe78bSCy Schubert /* Copy the current mapping to buf, updating key with value if found. */
2165*7f2fe78bSCy Schubert code = begin_attrs(context, entry, &pos, &end);
2166*7f2fe78bSCy Schubert if (code)
2167*7f2fe78bSCy Schubert return code;
2168*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
2169*7f2fe78bSCy Schubert while (next_attr(&pos, end, &mapkey, &mapval)) {
2170*7f2fe78bSCy Schubert if (strcmp(mapkey, key) == 0) {
2171*7f2fe78bSCy Schubert if (value != NULL) {
2172*7f2fe78bSCy Schubert k5_buf_add_len(&buf, mapkey, strlen(mapkey) + 1);
2173*7f2fe78bSCy Schubert k5_buf_add_len(&buf, value, strlen(value) + 1);
2174*7f2fe78bSCy Schubert }
2175*7f2fe78bSCy Schubert found = TRUE;
2176*7f2fe78bSCy Schubert } else {
2177*7f2fe78bSCy Schubert k5_buf_add_len(&buf, mapkey, strlen(mapkey) + 1);
2178*7f2fe78bSCy Schubert k5_buf_add_len(&buf, mapval, strlen(mapval) + 1);
2179*7f2fe78bSCy Schubert }
2180*7f2fe78bSCy Schubert }
2181*7f2fe78bSCy Schubert
2182*7f2fe78bSCy Schubert /* If key wasn't found in the map, add a new entry for it. */
2183*7f2fe78bSCy Schubert if (!found && value != NULL) {
2184*7f2fe78bSCy Schubert k5_buf_add_len(&buf, key, strlen(key) + 1);
2185*7f2fe78bSCy Schubert k5_buf_add_len(&buf, value, strlen(value) + 1);
2186*7f2fe78bSCy Schubert }
2187*7f2fe78bSCy Schubert
2188*7f2fe78bSCy Schubert if (k5_buf_status(&buf) != 0)
2189*7f2fe78bSCy Schubert return ENOMEM;
2190*7f2fe78bSCy Schubert if (buf.len > 65535) {
2191*7f2fe78bSCy Schubert code = KRB5_KDB_STRINGS_TOOLONG;
2192*7f2fe78bSCy Schubert goto cleanup;
2193*7f2fe78bSCy Schubert }
2194*7f2fe78bSCy Schubert tl_data.tl_data_type = KRB5_TL_STRING_ATTRS;
2195*7f2fe78bSCy Schubert tl_data.tl_data_contents = buf.data;
2196*7f2fe78bSCy Schubert tl_data.tl_data_length = buf.len;
2197*7f2fe78bSCy Schubert
2198*7f2fe78bSCy Schubert code = krb5_dbe_update_tl_data(context, entry, &tl_data);
2199*7f2fe78bSCy Schubert
2200*7f2fe78bSCy Schubert cleanup:
2201*7f2fe78bSCy Schubert k5_buf_free(&buf);
2202*7f2fe78bSCy Schubert return code;
2203*7f2fe78bSCy Schubert }
2204*7f2fe78bSCy Schubert
2205*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_delete_tl_data(krb5_context context,krb5_db_entry * entry,krb5_int16 tl_data_type)2206*7f2fe78bSCy Schubert krb5_dbe_delete_tl_data(krb5_context context, krb5_db_entry *entry,
2207*7f2fe78bSCy Schubert krb5_int16 tl_data_type)
2208*7f2fe78bSCy Schubert {
2209*7f2fe78bSCy Schubert krb5_tl_data *tl_data, *prev_tl_data, *free_tl_data;
2210*7f2fe78bSCy Schubert
2211*7f2fe78bSCy Schubert /*
2212*7f2fe78bSCy Schubert * Find existing entries of the specified type and remove them from the
2213*7f2fe78bSCy Schubert * entry's tl_data list.
2214*7f2fe78bSCy Schubert */
2215*7f2fe78bSCy Schubert
2216*7f2fe78bSCy Schubert for (prev_tl_data = tl_data = entry->tl_data; tl_data != NULL;) {
2217*7f2fe78bSCy Schubert if (tl_data->tl_data_type == tl_data_type) {
2218*7f2fe78bSCy Schubert if (tl_data == entry->tl_data) {
2219*7f2fe78bSCy Schubert /* remove from head */
2220*7f2fe78bSCy Schubert entry->tl_data = tl_data->tl_data_next;
2221*7f2fe78bSCy Schubert prev_tl_data = entry->tl_data;
2222*7f2fe78bSCy Schubert } else if (tl_data->tl_data_next == NULL) {
2223*7f2fe78bSCy Schubert /* remove from tail */
2224*7f2fe78bSCy Schubert prev_tl_data->tl_data_next = NULL;
2225*7f2fe78bSCy Schubert } else {
2226*7f2fe78bSCy Schubert /* remove in between */
2227*7f2fe78bSCy Schubert prev_tl_data->tl_data_next = tl_data->tl_data_next;
2228*7f2fe78bSCy Schubert }
2229*7f2fe78bSCy Schubert free_tl_data = tl_data;
2230*7f2fe78bSCy Schubert tl_data = tl_data->tl_data_next;
2231*7f2fe78bSCy Schubert krb5_dbe_free_tl_data(context, free_tl_data);
2232*7f2fe78bSCy Schubert entry->n_tl_data--;
2233*7f2fe78bSCy Schubert } else {
2234*7f2fe78bSCy Schubert prev_tl_data = tl_data;
2235*7f2fe78bSCy Schubert tl_data = tl_data->tl_data_next;
2236*7f2fe78bSCy Schubert }
2237*7f2fe78bSCy Schubert }
2238*7f2fe78bSCy Schubert
2239*7f2fe78bSCy Schubert return (0);
2240*7f2fe78bSCy Schubert }
2241*7f2fe78bSCy Schubert
2242*7f2fe78bSCy Schubert krb5_error_code
krb5_db_update_tl_data(krb5_context context,krb5_int16 * n_tl_datap,krb5_tl_data ** tl_datap,krb5_tl_data * new_tl_data)2243*7f2fe78bSCy Schubert krb5_db_update_tl_data(krb5_context context, krb5_int16 *n_tl_datap,
2244*7f2fe78bSCy Schubert krb5_tl_data **tl_datap, krb5_tl_data *new_tl_data)
2245*7f2fe78bSCy Schubert {
2246*7f2fe78bSCy Schubert krb5_tl_data *tl_data = NULL;
2247*7f2fe78bSCy Schubert krb5_octet *tmp;
2248*7f2fe78bSCy Schubert
2249*7f2fe78bSCy Schubert /*
2250*7f2fe78bSCy Schubert * Copy the new data first, so we can fail cleanly if malloc()
2251*7f2fe78bSCy Schubert * fails.
2252*7f2fe78bSCy Schubert */
2253*7f2fe78bSCy Schubert tmp = malloc(new_tl_data->tl_data_length);
2254*7f2fe78bSCy Schubert if (tmp == NULL)
2255*7f2fe78bSCy Schubert return (ENOMEM);
2256*7f2fe78bSCy Schubert
2257*7f2fe78bSCy Schubert /*
2258*7f2fe78bSCy Schubert * Find an existing entry of the specified type and point at
2259*7f2fe78bSCy Schubert * it, or NULL if not found.
2260*7f2fe78bSCy Schubert */
2261*7f2fe78bSCy Schubert
2262*7f2fe78bSCy Schubert if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) { /* db_args can be multiple */
2263*7f2fe78bSCy Schubert for (tl_data = *tl_datap; tl_data;
2264*7f2fe78bSCy Schubert tl_data = tl_data->tl_data_next)
2265*7f2fe78bSCy Schubert if (tl_data->tl_data_type == new_tl_data->tl_data_type)
2266*7f2fe78bSCy Schubert break;
2267*7f2fe78bSCy Schubert }
2268*7f2fe78bSCy Schubert
2269*7f2fe78bSCy Schubert /* If necessary, chain a new record in the beginning and point at it. */
2270*7f2fe78bSCy Schubert
2271*7f2fe78bSCy Schubert if (!tl_data) {
2272*7f2fe78bSCy Schubert tl_data = calloc(1, sizeof(*tl_data));
2273*7f2fe78bSCy Schubert if (tl_data == NULL) {
2274*7f2fe78bSCy Schubert free(tmp);
2275*7f2fe78bSCy Schubert return (ENOMEM);
2276*7f2fe78bSCy Schubert }
2277*7f2fe78bSCy Schubert tl_data->tl_data_next = *tl_datap;
2278*7f2fe78bSCy Schubert *tl_datap = tl_data;
2279*7f2fe78bSCy Schubert (*n_tl_datap)++;
2280*7f2fe78bSCy Schubert }
2281*7f2fe78bSCy Schubert
2282*7f2fe78bSCy Schubert /* fill in the record */
2283*7f2fe78bSCy Schubert
2284*7f2fe78bSCy Schubert free(tl_data->tl_data_contents);
2285*7f2fe78bSCy Schubert
2286*7f2fe78bSCy Schubert tl_data->tl_data_type = new_tl_data->tl_data_type;
2287*7f2fe78bSCy Schubert tl_data->tl_data_length = new_tl_data->tl_data_length;
2288*7f2fe78bSCy Schubert tl_data->tl_data_contents = tmp;
2289*7f2fe78bSCy Schubert memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
2290*7f2fe78bSCy Schubert
2291*7f2fe78bSCy Schubert return (0);
2292*7f2fe78bSCy Schubert }
2293*7f2fe78bSCy Schubert
2294*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_update_tl_data(krb5_context context,krb5_db_entry * entry,krb5_tl_data * new_tl_data)2295*7f2fe78bSCy Schubert krb5_dbe_update_tl_data(krb5_context context, krb5_db_entry *entry,
2296*7f2fe78bSCy Schubert krb5_tl_data *new_tl_data)
2297*7f2fe78bSCy Schubert {
2298*7f2fe78bSCy Schubert return krb5_db_update_tl_data(context, &entry->n_tl_data, &entry->tl_data,
2299*7f2fe78bSCy Schubert new_tl_data);
2300*7f2fe78bSCy Schubert }
2301*7f2fe78bSCy Schubert
2302*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_compute_salt(krb5_context context,const krb5_key_data * key,krb5_const_principal princ,krb5_int16 * salttype_out,krb5_data ** salt_out)2303*7f2fe78bSCy Schubert krb5_dbe_compute_salt(krb5_context context, const krb5_key_data *key,
2304*7f2fe78bSCy Schubert krb5_const_principal princ, krb5_int16 *salttype_out,
2305*7f2fe78bSCy Schubert krb5_data **salt_out)
2306*7f2fe78bSCy Schubert {
2307*7f2fe78bSCy Schubert krb5_error_code retval;
2308*7f2fe78bSCy Schubert krb5_int16 stype;
2309*7f2fe78bSCy Schubert krb5_data *salt, sdata;
2310*7f2fe78bSCy Schubert
2311*7f2fe78bSCy Schubert stype = (key->key_data_ver < 2) ? KRB5_KDB_SALTTYPE_NORMAL :
2312*7f2fe78bSCy Schubert key->key_data_type[1];
2313*7f2fe78bSCy Schubert *salttype_out = stype;
2314*7f2fe78bSCy Schubert *salt_out = NULL;
2315*7f2fe78bSCy Schubert
2316*7f2fe78bSCy Schubert /* Place computed salt into sdata, or directly into salt_out and return. */
2317*7f2fe78bSCy Schubert switch (stype) {
2318*7f2fe78bSCy Schubert case KRB5_KDB_SALTTYPE_NORMAL:
2319*7f2fe78bSCy Schubert retval = krb5_principal2salt(context, princ, &sdata);
2320*7f2fe78bSCy Schubert if (retval)
2321*7f2fe78bSCy Schubert return retval;
2322*7f2fe78bSCy Schubert break;
2323*7f2fe78bSCy Schubert case KRB5_KDB_SALTTYPE_NOREALM:
2324*7f2fe78bSCy Schubert retval = krb5_principal2salt_norealm(context, princ, &sdata);
2325*7f2fe78bSCy Schubert if (retval)
2326*7f2fe78bSCy Schubert return retval;
2327*7f2fe78bSCy Schubert break;
2328*7f2fe78bSCy Schubert case KRB5_KDB_SALTTYPE_ONLYREALM:
2329*7f2fe78bSCy Schubert return krb5_copy_data(context, &princ->realm, salt_out);
2330*7f2fe78bSCy Schubert case KRB5_KDB_SALTTYPE_SPECIAL:
2331*7f2fe78bSCy Schubert sdata = make_data(key->key_data_contents[1], key->key_data_length[1]);
2332*7f2fe78bSCy Schubert return krb5_copy_data(context, &sdata, salt_out);
2333*7f2fe78bSCy Schubert default:
2334*7f2fe78bSCy Schubert return KRB5_KDB_BAD_SALTTYPE;
2335*7f2fe78bSCy Schubert }
2336*7f2fe78bSCy Schubert
2337*7f2fe78bSCy Schubert /* Make a container for sdata. */
2338*7f2fe78bSCy Schubert salt = malloc(sizeof(*salt));
2339*7f2fe78bSCy Schubert if (salt == NULL) {
2340*7f2fe78bSCy Schubert free(sdata.data);
2341*7f2fe78bSCy Schubert return ENOMEM;
2342*7f2fe78bSCy Schubert }
2343*7f2fe78bSCy Schubert *salt = sdata;
2344*7f2fe78bSCy Schubert *salt_out = salt;
2345*7f2fe78bSCy Schubert return 0;
2346*7f2fe78bSCy Schubert }
2347*7f2fe78bSCy Schubert
2348*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_specialize_salt(krb5_context context,krb5_db_entry * entry)2349*7f2fe78bSCy Schubert krb5_dbe_specialize_salt(krb5_context context, krb5_db_entry *entry)
2350*7f2fe78bSCy Schubert {
2351*7f2fe78bSCy Schubert krb5_int16 stype, i;
2352*7f2fe78bSCy Schubert krb5_data *salt;
2353*7f2fe78bSCy Schubert krb5_error_code ret;
2354*7f2fe78bSCy Schubert
2355*7f2fe78bSCy Schubert if (context == NULL || entry == NULL)
2356*7f2fe78bSCy Schubert return EINVAL;
2357*7f2fe78bSCy Schubert
2358*7f2fe78bSCy Schubert /*
2359*7f2fe78bSCy Schubert * Store salt values explicitly so that they don't depend on the principal
2360*7f2fe78bSCy Schubert * name.
2361*7f2fe78bSCy Schubert */
2362*7f2fe78bSCy Schubert for (i = 0; i < entry->n_key_data; i++) {
2363*7f2fe78bSCy Schubert ret = krb5_dbe_compute_salt(context, &entry->key_data[i], entry->princ,
2364*7f2fe78bSCy Schubert &stype, &salt);
2365*7f2fe78bSCy Schubert if (ret)
2366*7f2fe78bSCy Schubert return ret;
2367*7f2fe78bSCy Schubert
2368*7f2fe78bSCy Schubert /* Steal the data pointer from salt and free the container. */
2369*7f2fe78bSCy Schubert if (entry->key_data[i].key_data_ver >= 2)
2370*7f2fe78bSCy Schubert free(entry->key_data[i].key_data_contents[1]);
2371*7f2fe78bSCy Schubert entry->key_data[i].key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
2372*7f2fe78bSCy Schubert entry->key_data[i].key_data_contents[1] = (uint8_t *)salt->data;
2373*7f2fe78bSCy Schubert entry->key_data[i].key_data_length[1] = salt->length;
2374*7f2fe78bSCy Schubert entry->key_data[i].key_data_ver = 2;
2375*7f2fe78bSCy Schubert free(salt);
2376*7f2fe78bSCy Schubert }
2377*7f2fe78bSCy Schubert
2378*7f2fe78bSCy Schubert return 0;
2379*7f2fe78bSCy Schubert }
2380*7f2fe78bSCy Schubert
2381*7f2fe78bSCy Schubert /* change password functions */
2382*7f2fe78bSCy Schubert 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)2383*7f2fe78bSCy Schubert krb5_dbe_cpw(krb5_context kcontext, krb5_keyblock *master_key,
2384*7f2fe78bSCy Schubert krb5_key_salt_tuple *ks_tuple, int ks_tuple_count, char *passwd,
2385*7f2fe78bSCy Schubert int new_kvno, krb5_boolean keepold, krb5_db_entry *db_entry)
2386*7f2fe78bSCy Schubert {
2387*7f2fe78bSCy Schubert krb5_error_code status = 0;
2388*7f2fe78bSCy Schubert kdb_vftabl *v;
2389*7f2fe78bSCy Schubert
2390*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2391*7f2fe78bSCy Schubert if (status)
2392*7f2fe78bSCy Schubert return status;
2393*7f2fe78bSCy Schubert return v->change_pwd(kcontext, master_key, ks_tuple, ks_tuple_count,
2394*7f2fe78bSCy Schubert passwd, new_kvno, keepold, db_entry);
2395*7f2fe78bSCy Schubert }
2396*7f2fe78bSCy Schubert
2397*7f2fe78bSCy Schubert /* policy management functions */
2398*7f2fe78bSCy Schubert krb5_error_code
krb5_db_create_policy(krb5_context kcontext,osa_policy_ent_t policy)2399*7f2fe78bSCy Schubert krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)
2400*7f2fe78bSCy Schubert {
2401*7f2fe78bSCy Schubert krb5_error_code status = 0;
2402*7f2fe78bSCy Schubert kdb_vftabl *v;
2403*7f2fe78bSCy Schubert
2404*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2405*7f2fe78bSCy Schubert if (status)
2406*7f2fe78bSCy Schubert return status;
2407*7f2fe78bSCy Schubert if (v->create_policy == NULL)
2408*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2409*7f2fe78bSCy Schubert
2410*7f2fe78bSCy Schubert status = v->create_policy(kcontext, policy);
2411*7f2fe78bSCy Schubert /* iprop does not support policy mods; force full resync. */
2412*7f2fe78bSCy Schubert if (!status && logging(kcontext))
2413*7f2fe78bSCy Schubert status = ulog_init_header(kcontext);
2414*7f2fe78bSCy Schubert return status;
2415*7f2fe78bSCy Schubert }
2416*7f2fe78bSCy Schubert
2417*7f2fe78bSCy Schubert krb5_error_code
krb5_db_get_policy(krb5_context kcontext,char * name,osa_policy_ent_t * policy)2418*7f2fe78bSCy Schubert krb5_db_get_policy(krb5_context kcontext, char *name, osa_policy_ent_t *policy)
2419*7f2fe78bSCy Schubert {
2420*7f2fe78bSCy Schubert krb5_error_code status = 0;
2421*7f2fe78bSCy Schubert kdb_vftabl *v;
2422*7f2fe78bSCy Schubert
2423*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2424*7f2fe78bSCy Schubert if (status)
2425*7f2fe78bSCy Schubert return status;
2426*7f2fe78bSCy Schubert if (v->get_policy == NULL)
2427*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2428*7f2fe78bSCy Schubert return v->get_policy(kcontext, name, policy);
2429*7f2fe78bSCy Schubert }
2430*7f2fe78bSCy Schubert
2431*7f2fe78bSCy Schubert krb5_error_code
krb5_db_put_policy(krb5_context kcontext,osa_policy_ent_t policy)2432*7f2fe78bSCy Schubert krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)
2433*7f2fe78bSCy Schubert {
2434*7f2fe78bSCy Schubert krb5_error_code status = 0;
2435*7f2fe78bSCy Schubert kdb_vftabl *v;
2436*7f2fe78bSCy Schubert
2437*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2438*7f2fe78bSCy Schubert if (status)
2439*7f2fe78bSCy Schubert return status;
2440*7f2fe78bSCy Schubert if (v->put_policy == NULL)
2441*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2442*7f2fe78bSCy Schubert
2443*7f2fe78bSCy Schubert status = v->put_policy(kcontext, policy);
2444*7f2fe78bSCy Schubert /* iprop does not support policy mods; force full resync. */
2445*7f2fe78bSCy Schubert if (!status && logging(kcontext))
2446*7f2fe78bSCy Schubert status = ulog_init_header(kcontext);
2447*7f2fe78bSCy Schubert return status;
2448*7f2fe78bSCy Schubert }
2449*7f2fe78bSCy Schubert
2450*7f2fe78bSCy Schubert krb5_error_code
krb5_db_iter_policy(krb5_context kcontext,char * match_entry,osa_adb_iter_policy_func func,void * data)2451*7f2fe78bSCy Schubert krb5_db_iter_policy(krb5_context kcontext, char *match_entry,
2452*7f2fe78bSCy Schubert osa_adb_iter_policy_func func, void *data)
2453*7f2fe78bSCy Schubert {
2454*7f2fe78bSCy Schubert krb5_error_code status = 0;
2455*7f2fe78bSCy Schubert kdb_vftabl *v;
2456*7f2fe78bSCy Schubert
2457*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2458*7f2fe78bSCy Schubert if (status)
2459*7f2fe78bSCy Schubert return status;
2460*7f2fe78bSCy Schubert if (v->iter_policy == NULL)
2461*7f2fe78bSCy Schubert return 0;
2462*7f2fe78bSCy Schubert return v->iter_policy(kcontext, match_entry, func, data);
2463*7f2fe78bSCy Schubert }
2464*7f2fe78bSCy Schubert
2465*7f2fe78bSCy Schubert krb5_error_code
krb5_db_delete_policy(krb5_context kcontext,char * policy)2466*7f2fe78bSCy Schubert krb5_db_delete_policy(krb5_context kcontext, char *policy)
2467*7f2fe78bSCy Schubert {
2468*7f2fe78bSCy Schubert krb5_error_code status = 0;
2469*7f2fe78bSCy Schubert kdb_vftabl *v;
2470*7f2fe78bSCy Schubert
2471*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2472*7f2fe78bSCy Schubert if (status)
2473*7f2fe78bSCy Schubert return status;
2474*7f2fe78bSCy Schubert if (v->delete_policy == NULL)
2475*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2476*7f2fe78bSCy Schubert
2477*7f2fe78bSCy Schubert status = v->delete_policy(kcontext, policy);
2478*7f2fe78bSCy Schubert /* iprop does not support policy mods; force full resync. */
2479*7f2fe78bSCy Schubert if (!status && logging(kcontext))
2480*7f2fe78bSCy Schubert status = ulog_init_header(kcontext);
2481*7f2fe78bSCy Schubert return status;
2482*7f2fe78bSCy Schubert }
2483*7f2fe78bSCy Schubert
2484*7f2fe78bSCy Schubert void
krb5_db_free_policy(krb5_context kcontext,osa_policy_ent_t policy)2485*7f2fe78bSCy Schubert krb5_db_free_policy(krb5_context kcontext, osa_policy_ent_t policy)
2486*7f2fe78bSCy Schubert {
2487*7f2fe78bSCy Schubert if (policy == NULL)
2488*7f2fe78bSCy Schubert return;
2489*7f2fe78bSCy Schubert free(policy->name);
2490*7f2fe78bSCy Schubert free(policy->allowed_keysalts);
2491*7f2fe78bSCy Schubert free_tl_data(policy->tl_data);
2492*7f2fe78bSCy Schubert free(policy);
2493*7f2fe78bSCy Schubert }
2494*7f2fe78bSCy Schubert
2495*7f2fe78bSCy Schubert krb5_error_code
krb5_db_promote(krb5_context kcontext,char ** db_args)2496*7f2fe78bSCy Schubert krb5_db_promote(krb5_context kcontext, char **db_args)
2497*7f2fe78bSCy Schubert {
2498*7f2fe78bSCy Schubert krb5_error_code status;
2499*7f2fe78bSCy Schubert char *section;
2500*7f2fe78bSCy Schubert kdb_vftabl *v;
2501*7f2fe78bSCy Schubert
2502*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2503*7f2fe78bSCy Schubert if (status)
2504*7f2fe78bSCy Schubert return status;
2505*7f2fe78bSCy Schubert if (v->promote_db == NULL)
2506*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2507*7f2fe78bSCy Schubert status = get_conf_section(kcontext, §ion);
2508*7f2fe78bSCy Schubert if (status)
2509*7f2fe78bSCy Schubert return status;
2510*7f2fe78bSCy Schubert status = v->promote_db(kcontext, section, db_args);
2511*7f2fe78bSCy Schubert free(section);
2512*7f2fe78bSCy Schubert return status;
2513*7f2fe78bSCy Schubert }
2514*7f2fe78bSCy Schubert
2515*7f2fe78bSCy Schubert static krb5_error_code
decrypt_iterator(krb5_context kcontext,const krb5_key_data * key_data,krb5_keyblock * dbkey,krb5_keysalt * keysalt)2516*7f2fe78bSCy Schubert decrypt_iterator(krb5_context kcontext, const krb5_key_data * key_data,
2517*7f2fe78bSCy Schubert krb5_keyblock *dbkey, krb5_keysalt *keysalt)
2518*7f2fe78bSCy Schubert {
2519*7f2fe78bSCy Schubert krb5_error_code status = 0;
2520*7f2fe78bSCy Schubert kdb_vftabl *v;
2521*7f2fe78bSCy Schubert krb5_keylist_node *n = kcontext->dal_handle->master_keylist;
2522*7f2fe78bSCy Schubert
2523*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2524*7f2fe78bSCy Schubert if (status)
2525*7f2fe78bSCy Schubert return status;
2526*7f2fe78bSCy Schubert for (; n; n = n->next) {
2527*7f2fe78bSCy Schubert krb5_clear_error_message(kcontext);
2528*7f2fe78bSCy Schubert status = v->decrypt_key_data(kcontext, &n->keyblock, key_data, dbkey,
2529*7f2fe78bSCy Schubert keysalt);
2530*7f2fe78bSCy Schubert if (status == 0)
2531*7f2fe78bSCy Schubert return 0;
2532*7f2fe78bSCy Schubert }
2533*7f2fe78bSCy Schubert return status;
2534*7f2fe78bSCy Schubert }
2535*7f2fe78bSCy Schubert
2536*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_decrypt_key_data(krb5_context kcontext,const krb5_keyblock * mkey,const krb5_key_data * key_data,krb5_keyblock * dbkey,krb5_keysalt * keysalt)2537*7f2fe78bSCy Schubert krb5_dbe_decrypt_key_data(krb5_context kcontext, const krb5_keyblock *mkey,
2538*7f2fe78bSCy Schubert const krb5_key_data *key_data, krb5_keyblock *dbkey,
2539*7f2fe78bSCy Schubert krb5_keysalt *keysalt)
2540*7f2fe78bSCy Schubert {
2541*7f2fe78bSCy Schubert krb5_error_code status = 0;
2542*7f2fe78bSCy Schubert kdb_vftabl *v;
2543*7f2fe78bSCy Schubert krb5_keyblock *cur_mkey;
2544*7f2fe78bSCy Schubert
2545*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2546*7f2fe78bSCy Schubert if (status)
2547*7f2fe78bSCy Schubert return status;
2548*7f2fe78bSCy Schubert if (mkey || kcontext->dal_handle->master_keylist == NULL)
2549*7f2fe78bSCy Schubert return v->decrypt_key_data(kcontext, mkey, key_data, dbkey, keysalt);
2550*7f2fe78bSCy Schubert status = decrypt_iterator(kcontext, key_data, dbkey, keysalt);
2551*7f2fe78bSCy Schubert if (status == 0)
2552*7f2fe78bSCy Schubert return 0;
2553*7f2fe78bSCy Schubert if (kcontext->dal_handle->master_keylist) {
2554*7f2fe78bSCy Schubert /* Try reloading master keys. */
2555*7f2fe78bSCy Schubert cur_mkey = &kcontext->dal_handle->master_keylist->keyblock;
2556*7f2fe78bSCy Schubert if (krb5_db_fetch_mkey_list(kcontext,
2557*7f2fe78bSCy Schubert kcontext->dal_handle->master_princ,
2558*7f2fe78bSCy Schubert cur_mkey) == 0)
2559*7f2fe78bSCy Schubert return decrypt_iterator(kcontext, key_data, dbkey, keysalt);
2560*7f2fe78bSCy Schubert }
2561*7f2fe78bSCy Schubert return status;
2562*7f2fe78bSCy Schubert }
2563*7f2fe78bSCy Schubert
2564*7f2fe78bSCy Schubert krb5_error_code
krb5_dbe_encrypt_key_data(krb5_context kcontext,const krb5_keyblock * mkey,const krb5_keyblock * dbkey,const krb5_keysalt * keysalt,int keyver,krb5_key_data * key_data)2565*7f2fe78bSCy Schubert krb5_dbe_encrypt_key_data(krb5_context kcontext, const krb5_keyblock *mkey,
2566*7f2fe78bSCy Schubert const krb5_keyblock *dbkey,
2567*7f2fe78bSCy Schubert const krb5_keysalt *keysalt, int keyver,
2568*7f2fe78bSCy Schubert krb5_key_data *key_data)
2569*7f2fe78bSCy Schubert {
2570*7f2fe78bSCy Schubert krb5_error_code status = 0;
2571*7f2fe78bSCy Schubert kdb_vftabl *v;
2572*7f2fe78bSCy Schubert
2573*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2574*7f2fe78bSCy Schubert if (status)
2575*7f2fe78bSCy Schubert return status;
2576*7f2fe78bSCy Schubert return v->encrypt_key_data(kcontext, mkey, dbkey, keysalt, keyver,
2577*7f2fe78bSCy Schubert key_data);
2578*7f2fe78bSCy Schubert }
2579*7f2fe78bSCy Schubert
2580*7f2fe78bSCy Schubert krb5_error_code
krb5_db_get_context(krb5_context context,void ** db_context)2581*7f2fe78bSCy Schubert krb5_db_get_context(krb5_context context, void **db_context)
2582*7f2fe78bSCy Schubert {
2583*7f2fe78bSCy Schubert *db_context = KRB5_DB_GET_DB_CONTEXT(context);
2584*7f2fe78bSCy Schubert if (*db_context == NULL)
2585*7f2fe78bSCy Schubert return KRB5_KDB_DBNOTINITED;
2586*7f2fe78bSCy Schubert return 0;
2587*7f2fe78bSCy Schubert }
2588*7f2fe78bSCy Schubert
2589*7f2fe78bSCy Schubert krb5_error_code
krb5_db_set_context(krb5_context context,void * db_context)2590*7f2fe78bSCy Schubert krb5_db_set_context(krb5_context context, void *db_context)
2591*7f2fe78bSCy Schubert {
2592*7f2fe78bSCy Schubert KRB5_DB_GET_DB_CONTEXT(context) = db_context;
2593*7f2fe78bSCy Schubert
2594*7f2fe78bSCy Schubert return 0;
2595*7f2fe78bSCy Schubert }
2596*7f2fe78bSCy Schubert
2597*7f2fe78bSCy Schubert krb5_error_code
krb5_db_check_transited_realms(krb5_context kcontext,const krb5_data * tr_contents,const krb5_data * client_realm,const krb5_data * server_realm)2598*7f2fe78bSCy Schubert krb5_db_check_transited_realms(krb5_context kcontext,
2599*7f2fe78bSCy Schubert const krb5_data *tr_contents,
2600*7f2fe78bSCy Schubert const krb5_data *client_realm,
2601*7f2fe78bSCy Schubert const krb5_data *server_realm)
2602*7f2fe78bSCy Schubert {
2603*7f2fe78bSCy Schubert krb5_error_code status;
2604*7f2fe78bSCy Schubert kdb_vftabl *v;
2605*7f2fe78bSCy Schubert
2606*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2607*7f2fe78bSCy Schubert if (status)
2608*7f2fe78bSCy Schubert return status;
2609*7f2fe78bSCy Schubert if (v->check_transited_realms == NULL)
2610*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2611*7f2fe78bSCy Schubert return v->check_transited_realms(kcontext, tr_contents, client_realm,
2612*7f2fe78bSCy Schubert server_realm);
2613*7f2fe78bSCy Schubert }
2614*7f2fe78bSCy Schubert
2615*7f2fe78bSCy Schubert krb5_error_code
krb5_db_check_policy_as(krb5_context kcontext,krb5_kdc_req * request,krb5_db_entry * client,krb5_db_entry * server,krb5_timestamp kdc_time,const char ** status,krb5_pa_data *** e_data)2616*7f2fe78bSCy Schubert krb5_db_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
2617*7f2fe78bSCy Schubert krb5_db_entry *client, krb5_db_entry *server,
2618*7f2fe78bSCy Schubert krb5_timestamp kdc_time, const char **status,
2619*7f2fe78bSCy Schubert krb5_pa_data ***e_data)
2620*7f2fe78bSCy Schubert {
2621*7f2fe78bSCy Schubert krb5_error_code ret;
2622*7f2fe78bSCy Schubert kdb_vftabl *v;
2623*7f2fe78bSCy Schubert
2624*7f2fe78bSCy Schubert *status = NULL;
2625*7f2fe78bSCy Schubert *e_data = NULL;
2626*7f2fe78bSCy Schubert ret = get_vftabl(kcontext, &v);
2627*7f2fe78bSCy Schubert if (ret)
2628*7f2fe78bSCy Schubert return ret;
2629*7f2fe78bSCy Schubert if (v->check_policy_as == NULL)
2630*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2631*7f2fe78bSCy Schubert return v->check_policy_as(kcontext, request, client, server, kdc_time,
2632*7f2fe78bSCy Schubert status, e_data);
2633*7f2fe78bSCy Schubert }
2634*7f2fe78bSCy Schubert
2635*7f2fe78bSCy Schubert krb5_error_code
krb5_db_check_policy_tgs(krb5_context kcontext,krb5_kdc_req * request,krb5_db_entry * server,krb5_ticket * ticket,const char ** status,krb5_pa_data *** e_data)2636*7f2fe78bSCy Schubert krb5_db_check_policy_tgs(krb5_context kcontext, krb5_kdc_req *request,
2637*7f2fe78bSCy Schubert krb5_db_entry *server, krb5_ticket *ticket,
2638*7f2fe78bSCy Schubert const char **status, krb5_pa_data ***e_data)
2639*7f2fe78bSCy Schubert {
2640*7f2fe78bSCy Schubert krb5_error_code ret;
2641*7f2fe78bSCy Schubert kdb_vftabl *v;
2642*7f2fe78bSCy Schubert
2643*7f2fe78bSCy Schubert *status = NULL;
2644*7f2fe78bSCy Schubert *e_data = NULL;
2645*7f2fe78bSCy Schubert ret = get_vftabl(kcontext, &v);
2646*7f2fe78bSCy Schubert if (ret)
2647*7f2fe78bSCy Schubert return ret;
2648*7f2fe78bSCy Schubert if (v->check_policy_tgs == NULL)
2649*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2650*7f2fe78bSCy Schubert return v->check_policy_tgs(kcontext, request, server, ticket, status,
2651*7f2fe78bSCy Schubert e_data);
2652*7f2fe78bSCy Schubert }
2653*7f2fe78bSCy Schubert
2654*7f2fe78bSCy Schubert void
krb5_db_audit_as_req(krb5_context kcontext,krb5_kdc_req * request,const krb5_address * local_addr,const krb5_address * remote_addr,krb5_db_entry * client,krb5_db_entry * server,krb5_timestamp authtime,krb5_error_code error_code)2655*7f2fe78bSCy Schubert krb5_db_audit_as_req(krb5_context kcontext, krb5_kdc_req *request,
2656*7f2fe78bSCy Schubert const krb5_address *local_addr,
2657*7f2fe78bSCy Schubert const krb5_address *remote_addr, krb5_db_entry *client,
2658*7f2fe78bSCy Schubert krb5_db_entry *server, krb5_timestamp authtime,
2659*7f2fe78bSCy Schubert krb5_error_code error_code)
2660*7f2fe78bSCy Schubert {
2661*7f2fe78bSCy Schubert krb5_error_code status;
2662*7f2fe78bSCy Schubert kdb_vftabl *v;
2663*7f2fe78bSCy Schubert
2664*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2665*7f2fe78bSCy Schubert if (status || v->audit_as_req == NULL)
2666*7f2fe78bSCy Schubert return;
2667*7f2fe78bSCy Schubert v->audit_as_req(kcontext, request, local_addr, remote_addr,
2668*7f2fe78bSCy Schubert client, server, authtime, error_code);
2669*7f2fe78bSCy Schubert }
2670*7f2fe78bSCy Schubert
2671*7f2fe78bSCy Schubert void
krb5_db_refresh_config(krb5_context kcontext)2672*7f2fe78bSCy Schubert krb5_db_refresh_config(krb5_context kcontext)
2673*7f2fe78bSCy Schubert {
2674*7f2fe78bSCy Schubert krb5_error_code status;
2675*7f2fe78bSCy Schubert kdb_vftabl *v;
2676*7f2fe78bSCy Schubert
2677*7f2fe78bSCy Schubert status = get_vftabl(kcontext, &v);
2678*7f2fe78bSCy Schubert if (status || v->refresh_config == NULL)
2679*7f2fe78bSCy Schubert return;
2680*7f2fe78bSCy Schubert v->refresh_config(kcontext);
2681*7f2fe78bSCy Schubert }
2682*7f2fe78bSCy Schubert
2683*7f2fe78bSCy Schubert krb5_error_code
krb5_db_check_allowed_to_delegate(krb5_context kcontext,krb5_const_principal client,const krb5_db_entry * server,krb5_const_principal proxy)2684*7f2fe78bSCy Schubert krb5_db_check_allowed_to_delegate(krb5_context kcontext,
2685*7f2fe78bSCy Schubert krb5_const_principal client,
2686*7f2fe78bSCy Schubert const krb5_db_entry *server,
2687*7f2fe78bSCy Schubert krb5_const_principal proxy)
2688*7f2fe78bSCy Schubert {
2689*7f2fe78bSCy Schubert krb5_error_code ret;
2690*7f2fe78bSCy Schubert kdb_vftabl *v;
2691*7f2fe78bSCy Schubert
2692*7f2fe78bSCy Schubert ret = get_vftabl(kcontext, &v);
2693*7f2fe78bSCy Schubert if (ret)
2694*7f2fe78bSCy Schubert return ret;
2695*7f2fe78bSCy Schubert if (v->check_allowed_to_delegate == NULL)
2696*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2697*7f2fe78bSCy Schubert return v->check_allowed_to_delegate(kcontext, client, server, proxy);
2698*7f2fe78bSCy Schubert }
2699*7f2fe78bSCy Schubert
2700*7f2fe78bSCy Schubert krb5_error_code
krb5_db_get_s4u_x509_principal(krb5_context kcontext,const krb5_data * client_cert,krb5_const_principal in_princ,unsigned int flags,krb5_db_entry ** entry)2701*7f2fe78bSCy Schubert krb5_db_get_s4u_x509_principal(krb5_context kcontext,
2702*7f2fe78bSCy Schubert const krb5_data *client_cert,
2703*7f2fe78bSCy Schubert krb5_const_principal in_princ,
2704*7f2fe78bSCy Schubert unsigned int flags, krb5_db_entry **entry)
2705*7f2fe78bSCy Schubert {
2706*7f2fe78bSCy Schubert krb5_error_code ret;
2707*7f2fe78bSCy Schubert kdb_vftabl *v;
2708*7f2fe78bSCy Schubert
2709*7f2fe78bSCy Schubert ret = get_vftabl(kcontext, &v);
2710*7f2fe78bSCy Schubert if (ret)
2711*7f2fe78bSCy Schubert return ret;
2712*7f2fe78bSCy Schubert if (v->get_s4u_x509_principal == NULL)
2713*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2714*7f2fe78bSCy Schubert ret = v->get_s4u_x509_principal(kcontext, client_cert, in_princ, flags,
2715*7f2fe78bSCy Schubert entry);
2716*7f2fe78bSCy Schubert if (ret)
2717*7f2fe78bSCy Schubert return ret;
2718*7f2fe78bSCy Schubert
2719*7f2fe78bSCy Schubert /* Sort the keys in the db entry, same as get_principal(). */
2720*7f2fe78bSCy Schubert if ((*entry)->key_data != NULL)
2721*7f2fe78bSCy Schubert krb5_dbe_sort_key_data((*entry)->key_data, (*entry)->n_key_data);
2722*7f2fe78bSCy Schubert
2723*7f2fe78bSCy Schubert return 0;
2724*7f2fe78bSCy Schubert }
2725*7f2fe78bSCy Schubert
2726*7f2fe78bSCy Schubert krb5_error_code
krb5_db_allowed_to_delegate_from(krb5_context kcontext,krb5_const_principal client,krb5_const_principal server,krb5_pac server_pac,const krb5_db_entry * proxy)2727*7f2fe78bSCy Schubert krb5_db_allowed_to_delegate_from(krb5_context kcontext,
2728*7f2fe78bSCy Schubert krb5_const_principal client,
2729*7f2fe78bSCy Schubert krb5_const_principal server,
2730*7f2fe78bSCy Schubert krb5_pac server_pac,
2731*7f2fe78bSCy Schubert const krb5_db_entry *proxy)
2732*7f2fe78bSCy Schubert {
2733*7f2fe78bSCy Schubert krb5_error_code ret;
2734*7f2fe78bSCy Schubert kdb_vftabl *v;
2735*7f2fe78bSCy Schubert
2736*7f2fe78bSCy Schubert ret = get_vftabl(kcontext, &v);
2737*7f2fe78bSCy Schubert if (ret)
2738*7f2fe78bSCy Schubert return ret;
2739*7f2fe78bSCy Schubert if (v->allowed_to_delegate_from == NULL)
2740*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2741*7f2fe78bSCy Schubert return v->allowed_to_delegate_from(kcontext, client, server, server_pac,
2742*7f2fe78bSCy Schubert proxy);
2743*7f2fe78bSCy Schubert }
2744*7f2fe78bSCy Schubert
2745*7f2fe78bSCy Schubert void
krb5_dbe_sort_key_data(krb5_key_data * key_data,size_t key_data_length)2746*7f2fe78bSCy Schubert krb5_dbe_sort_key_data(krb5_key_data *key_data, size_t key_data_length)
2747*7f2fe78bSCy Schubert {
2748*7f2fe78bSCy Schubert size_t i, j;
2749*7f2fe78bSCy Schubert krb5_key_data tmp;
2750*7f2fe78bSCy Schubert
2751*7f2fe78bSCy Schubert /* Use insertion sort as a stable sort. */
2752*7f2fe78bSCy Schubert for (i = 1; i < key_data_length; i++) {
2753*7f2fe78bSCy Schubert j = i;
2754*7f2fe78bSCy Schubert while (j > 0 &&
2755*7f2fe78bSCy Schubert key_data[j - 1].key_data_kvno < key_data[j].key_data_kvno) {
2756*7f2fe78bSCy Schubert tmp = key_data[j];
2757*7f2fe78bSCy Schubert key_data[j] = key_data[j - 1];
2758*7f2fe78bSCy Schubert key_data[j - 1] = tmp;
2759*7f2fe78bSCy Schubert j--;
2760*7f2fe78bSCy Schubert }
2761*7f2fe78bSCy Schubert }
2762*7f2fe78bSCy Schubert }
2763*7f2fe78bSCy Schubert
2764*7f2fe78bSCy Schubert krb5_error_code
krb5_db_issue_pac(krb5_context context,unsigned int flags,krb5_db_entry * client,krb5_keyblock * replaced_reply_key,krb5_db_entry * server,krb5_db_entry * krbtgt,krb5_timestamp authtime,krb5_pac old_pac,krb5_pac new_pac,krb5_data *** auth_indicators)2765*7f2fe78bSCy Schubert krb5_db_issue_pac(krb5_context context, unsigned int flags,
2766*7f2fe78bSCy Schubert krb5_db_entry *client, krb5_keyblock *replaced_reply_key,
2767*7f2fe78bSCy Schubert krb5_db_entry *server, krb5_db_entry *krbtgt,
2768*7f2fe78bSCy Schubert krb5_timestamp authtime, krb5_pac old_pac, krb5_pac new_pac,
2769*7f2fe78bSCy Schubert krb5_data ***auth_indicators)
2770*7f2fe78bSCy Schubert {
2771*7f2fe78bSCy Schubert krb5_error_code ret;
2772*7f2fe78bSCy Schubert kdb_vftabl *v;
2773*7f2fe78bSCy Schubert
2774*7f2fe78bSCy Schubert ret = get_vftabl(context, &v);
2775*7f2fe78bSCy Schubert if (ret)
2776*7f2fe78bSCy Schubert return ret;
2777*7f2fe78bSCy Schubert if (v->issue_pac == NULL)
2778*7f2fe78bSCy Schubert return KRB5_PLUGIN_OP_NOTSUPP;
2779*7f2fe78bSCy Schubert return v->issue_pac(context, flags, client, replaced_reply_key, server,
2780*7f2fe78bSCy Schubert krbtgt, authtime, old_pac, new_pac, auth_indicators);
2781*7f2fe78bSCy Schubert }
2782