xref: /freebsd/crypto/krb5/src/lib/kdb/kdb5.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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, &section);
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, &section);
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, &section);
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, &section);
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