1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "hdb_locl.h"
35b528cefcSMark Murray
36b528cefcSMark Murray /* keytab backend for HDB databases */
37b528cefcSMark Murray
38b528cefcSMark Murray struct hdb_data {
39b528cefcSMark Murray char *dbname;
40b528cefcSMark Murray char *mkey;
41b528cefcSMark Murray };
42b528cefcSMark Murray
43*ae771770SStanislav Sedov struct hdb_cursor {
44*ae771770SStanislav Sedov HDB *db;
45*ae771770SStanislav Sedov hdb_entry_ex hdb_entry;
46*ae771770SStanislav Sedov int first, next;
47*ae771770SStanislav Sedov int key_idx;
48*ae771770SStanislav Sedov };
49*ae771770SStanislav Sedov
505e9cd1aeSAssar Westerlund /*
515e9cd1aeSAssar Westerlund * the format for HDB keytabs is:
52*ae771770SStanislav Sedov * HDB:[HDBFORMAT:database-specific-data[:mkey=mkey-file]]
535e9cd1aeSAssar Westerlund */
545e9cd1aeSAssar Westerlund
55*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
hdb_resolve(krb5_context context,const char * name,krb5_keytab id)56b528cefcSMark Murray hdb_resolve(krb5_context context, const char *name, krb5_keytab id)
57b528cefcSMark Murray {
58b528cefcSMark Murray struct hdb_data *d;
59b528cefcSMark Murray const char *db, *mkey;
605e9cd1aeSAssar Westerlund
61b528cefcSMark Murray d = malloc(sizeof(*d));
624137ff4cSJacques Vidrine if(d == NULL) {
63*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
64b528cefcSMark Murray return ENOMEM;
654137ff4cSJacques Vidrine }
66b528cefcSMark Murray db = name;
67*ae771770SStanislav Sedov mkey = strstr(name, ":mkey=");
68*ae771770SStanislav Sedov if(mkey == NULL || mkey[5] == '\0') {
69b528cefcSMark Murray if(*name == '\0')
70b528cefcSMark Murray d->dbname = NULL;
71b528cefcSMark Murray else {
72b528cefcSMark Murray d->dbname = strdup(name);
73b528cefcSMark Murray if(d->dbname == NULL) {
74b528cefcSMark Murray free(d);
75*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
76b528cefcSMark Murray return ENOMEM;
77b528cefcSMark Murray }
78b528cefcSMark Murray }
79b528cefcSMark Murray d->mkey = NULL;
80b528cefcSMark Murray } else {
81c19800e8SDoug Rabson d->dbname = malloc(mkey - db + 1);
82b528cefcSMark Murray if(d->dbname == NULL) {
83b528cefcSMark Murray free(d);
84*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
85b528cefcSMark Murray return ENOMEM;
86b528cefcSMark Murray }
875e9cd1aeSAssar Westerlund memmove(d->dbname, db, mkey - db);
88b528cefcSMark Murray d->dbname[mkey - db] = '\0';
89*ae771770SStanislav Sedov
90*ae771770SStanislav Sedov d->mkey = strdup(mkey + 5);
91b528cefcSMark Murray if(d->mkey == NULL) {
92b528cefcSMark Murray free(d->dbname);
93b528cefcSMark Murray free(d);
94*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
95b528cefcSMark Murray return ENOMEM;
96b528cefcSMark Murray }
97b528cefcSMark Murray }
98b528cefcSMark Murray id->data = d;
99b528cefcSMark Murray return 0;
100b528cefcSMark Murray }
101b528cefcSMark Murray
102*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
hdb_close(krb5_context context,krb5_keytab id)103b528cefcSMark Murray hdb_close(krb5_context context, krb5_keytab id)
104b528cefcSMark Murray {
105b528cefcSMark Murray struct hdb_data *d = id->data;
1065e9cd1aeSAssar Westerlund
1075e9cd1aeSAssar Westerlund free(d->dbname);
1085e9cd1aeSAssar Westerlund free(d->mkey);
109b528cefcSMark Murray free(d);
110b528cefcSMark Murray return 0;
111b528cefcSMark Murray }
112b528cefcSMark Murray
113*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
hdb_get_name(krb5_context context,krb5_keytab id,char * name,size_t namesize)114b528cefcSMark Murray hdb_get_name(krb5_context context,
115b528cefcSMark Murray krb5_keytab id,
116b528cefcSMark Murray char *name,
117b528cefcSMark Murray size_t namesize)
118b528cefcSMark Murray {
119b528cefcSMark Murray struct hdb_data *d = id->data;
1205e9cd1aeSAssar Westerlund
121b528cefcSMark Murray snprintf(name, namesize, "%s%s%s",
122b528cefcSMark Murray d->dbname ? d->dbname : "",
123b528cefcSMark Murray (d->dbname || d->mkey) ? ":" : "",
124b528cefcSMark Murray d->mkey ? d->mkey : "");
125b528cefcSMark Murray return 0;
126b528cefcSMark Murray }
127b528cefcSMark Murray
1285e9cd1aeSAssar Westerlund /*
1295e9cd1aeSAssar Westerlund * try to figure out the database (`dbname') and master-key (`mkey')
1305e9cd1aeSAssar Westerlund * that should be used for `principal'.
1315e9cd1aeSAssar Westerlund */
1325e9cd1aeSAssar Westerlund
133*ae771770SStanislav Sedov static krb5_error_code
find_db(krb5_context context,char ** dbname,char ** mkey,krb5_const_principal principal)1345e9cd1aeSAssar Westerlund find_db (krb5_context context,
135*ae771770SStanislav Sedov char **dbname,
136*ae771770SStanislav Sedov char **mkey,
1375e9cd1aeSAssar Westerlund krb5_const_principal principal)
1385e9cd1aeSAssar Westerlund {
139*ae771770SStanislav Sedov krb5_const_realm realm = krb5_principal_get_realm(context, principal);
140*ae771770SStanislav Sedov krb5_error_code ret;
141*ae771770SStanislav Sedov struct hdb_dbinfo *head, *dbinfo = NULL;
1425e9cd1aeSAssar Westerlund
1435e9cd1aeSAssar Westerlund *dbname = *mkey = NULL;
1445e9cd1aeSAssar Westerlund
145*ae771770SStanislav Sedov ret = hdb_get_dbinfo(context, &head);
146*ae771770SStanislav Sedov if (ret)
147*ae771770SStanislav Sedov return ret;
1485e9cd1aeSAssar Westerlund
149*ae771770SStanislav Sedov while ((dbinfo = hdb_dbinfo_get_next(head, dbinfo)) != NULL) {
150*ae771770SStanislav Sedov const char *p = hdb_dbinfo_get_realm(context, dbinfo);
151*ae771770SStanislav Sedov if (p && strcmp (realm, p) == 0) {
152*ae771770SStanislav Sedov p = hdb_dbinfo_get_dbname(context, dbinfo);
153*ae771770SStanislav Sedov if (p)
154*ae771770SStanislav Sedov *dbname = strdup(p);
155*ae771770SStanislav Sedov p = hdb_dbinfo_get_mkey_file(context, dbinfo);
156*ae771770SStanislav Sedov if (p)
157*ae771770SStanislav Sedov *mkey = strdup(p);
1585e9cd1aeSAssar Westerlund break;
1595e9cd1aeSAssar Westerlund }
1605e9cd1aeSAssar Westerlund }
161*ae771770SStanislav Sedov hdb_free_dbinfo(context, &head);
1625e9cd1aeSAssar Westerlund if (*dbname == NULL)
163*ae771770SStanislav Sedov *dbname = strdup(HDB_DEFAULT_DB);
164*ae771770SStanislav Sedov return 0;
1655e9cd1aeSAssar Westerlund }
1665e9cd1aeSAssar Westerlund
1675e9cd1aeSAssar Westerlund /*
1685e9cd1aeSAssar Westerlund * find the keytab entry in `id' for `principal, kvno, enctype' and return
1695e9cd1aeSAssar Westerlund * it in `entry'. return 0 or an error code
1705e9cd1aeSAssar Westerlund */
1715e9cd1aeSAssar Westerlund
172*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
hdb_get_entry(krb5_context context,krb5_keytab id,krb5_const_principal principal,krb5_kvno kvno,krb5_enctype enctype,krb5_keytab_entry * entry)173b528cefcSMark Murray hdb_get_entry(krb5_context context,
174b528cefcSMark Murray krb5_keytab id,
175b528cefcSMark Murray krb5_const_principal principal,
176b528cefcSMark Murray krb5_kvno kvno,
177b528cefcSMark Murray krb5_enctype enctype,
178b528cefcSMark Murray krb5_keytab_entry *entry)
179b528cefcSMark Murray {
180c19800e8SDoug Rabson hdb_entry_ex ent;
181b528cefcSMark Murray krb5_error_code ret;
182b528cefcSMark Murray struct hdb_data *d = id->data;
1835e9cd1aeSAssar Westerlund const char *dbname = d->dbname;
1845e9cd1aeSAssar Westerlund const char *mkey = d->mkey;
185*ae771770SStanislav Sedov char *fdbname = NULL, *fmkey = NULL;
186*ae771770SStanislav Sedov HDB *db;
187*ae771770SStanislav Sedov size_t i;
188b528cefcSMark Murray
189c19800e8SDoug Rabson memset(&ent, 0, sizeof(ent));
190c19800e8SDoug Rabson
191*ae771770SStanislav Sedov if (dbname == NULL) {
192*ae771770SStanislav Sedov ret = find_db(context, &fdbname, &fmkey, principal);
193*ae771770SStanislav Sedov if (ret)
194*ae771770SStanislav Sedov return ret;
195*ae771770SStanislav Sedov dbname = fdbname;
196*ae771770SStanislav Sedov mkey = fmkey;
197*ae771770SStanislav Sedov }
1985e9cd1aeSAssar Westerlund
1995e9cd1aeSAssar Westerlund ret = hdb_create (context, &db, dbname);
200b528cefcSMark Murray if (ret)
201*ae771770SStanislav Sedov goto out2;
2025e9cd1aeSAssar Westerlund ret = hdb_set_master_keyfile (context, db, mkey);
2035e9cd1aeSAssar Westerlund if (ret) {
204c19800e8SDoug Rabson (*db->hdb_destroy)(context, db);
205*ae771770SStanislav Sedov goto out2;
2065e9cd1aeSAssar Westerlund }
2075e9cd1aeSAssar Westerlund
208c19800e8SDoug Rabson ret = (*db->hdb_open)(context, db, O_RDONLY, 0);
2095e9cd1aeSAssar Westerlund if (ret) {
210c19800e8SDoug Rabson (*db->hdb_destroy)(context, db);
211*ae771770SStanislav Sedov goto out2;
2125e9cd1aeSAssar Westerlund }
213*ae771770SStanislav Sedov
214*ae771770SStanislav Sedov ret = (*db->hdb_fetch_kvno)(context, db, principal,
215*ae771770SStanislav Sedov HDB_F_DECRYPT|HDB_F_KVNO_SPECIFIED|
216c19800e8SDoug Rabson HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
217*ae771770SStanislav Sedov kvno, &ent);
2185e9cd1aeSAssar Westerlund
219c19800e8SDoug Rabson if(ret == HDB_ERR_NOENTRY) {
220c19800e8SDoug Rabson ret = KRB5_KT_NOTFOUND;
221c19800e8SDoug Rabson goto out;
222c19800e8SDoug Rabson }else if(ret)
223c19800e8SDoug Rabson goto out;
224c19800e8SDoug Rabson
225*ae771770SStanislav Sedov if(kvno && (krb5_kvno)ent.entry.kvno != kvno) {
226b528cefcSMark Murray hdb_free_entry(context, &ent);
227c19800e8SDoug Rabson ret = KRB5_KT_NOTFOUND;
228c19800e8SDoug Rabson goto out;
229b528cefcSMark Murray }
230b528cefcSMark Murray if(enctype == 0)
231c19800e8SDoug Rabson if(ent.entry.keys.len > 0)
232c19800e8SDoug Rabson enctype = ent.entry.keys.val[0].key.keytype;
233b528cefcSMark Murray ret = KRB5_KT_NOTFOUND;
234c19800e8SDoug Rabson for(i = 0; i < ent.entry.keys.len; i++) {
235c19800e8SDoug Rabson if(ent.entry.keys.val[i].key.keytype == enctype) {
236b528cefcSMark Murray krb5_copy_principal(context, principal, &entry->principal);
237c19800e8SDoug Rabson entry->vno = ent.entry.kvno;
238b528cefcSMark Murray krb5_copy_keyblock_contents(context,
239c19800e8SDoug Rabson &ent.entry.keys.val[i].key,
240b528cefcSMark Murray &entry->keyblock);
241b528cefcSMark Murray ret = 0;
242b528cefcSMark Murray break;
243b528cefcSMark Murray }
244b528cefcSMark Murray }
245b528cefcSMark Murray hdb_free_entry(context, &ent);
246c19800e8SDoug Rabson out:
247c19800e8SDoug Rabson (*db->hdb_close)(context, db);
248c19800e8SDoug Rabson (*db->hdb_destroy)(context, db);
249*ae771770SStanislav Sedov out2:
250*ae771770SStanislav Sedov free(fdbname);
251*ae771770SStanislav Sedov free(fmkey);
252b528cefcSMark Murray return ret;
253b528cefcSMark Murray }
254b528cefcSMark Murray
255*ae771770SStanislav Sedov /*
256*ae771770SStanislav Sedov * find the keytab entry in `id' for `principal, kvno, enctype' and return
257*ae771770SStanislav Sedov * it in `entry'. return 0 or an error code
258*ae771770SStanislav Sedov */
259*ae771770SStanislav Sedov
260*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
hdb_start_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)261*ae771770SStanislav Sedov hdb_start_seq_get(krb5_context context,
262*ae771770SStanislav Sedov krb5_keytab id,
263*ae771770SStanislav Sedov krb5_kt_cursor *cursor)
264*ae771770SStanislav Sedov {
265*ae771770SStanislav Sedov krb5_error_code ret;
266*ae771770SStanislav Sedov struct hdb_cursor *c;
267*ae771770SStanislav Sedov struct hdb_data *d = id->data;
268*ae771770SStanislav Sedov const char *dbname = d->dbname;
269*ae771770SStanislav Sedov const char *mkey = d->mkey;
270*ae771770SStanislav Sedov HDB *db;
271*ae771770SStanislav Sedov
272*ae771770SStanislav Sedov if (dbname == NULL) {
273*ae771770SStanislav Sedov /*
274*ae771770SStanislav Sedov * We don't support enumerating without being told what
275*ae771770SStanislav Sedov * backend to enumerate on
276*ae771770SStanislav Sedov */
277*ae771770SStanislav Sedov ret = KRB5_KT_NOTFOUND;
278*ae771770SStanislav Sedov return ret;
279*ae771770SStanislav Sedov }
280*ae771770SStanislav Sedov
281*ae771770SStanislav Sedov ret = hdb_create (context, &db, dbname);
282*ae771770SStanislav Sedov if (ret)
283*ae771770SStanislav Sedov return ret;
284*ae771770SStanislav Sedov ret = hdb_set_master_keyfile (context, db, mkey);
285*ae771770SStanislav Sedov if (ret) {
286*ae771770SStanislav Sedov (*db->hdb_destroy)(context, db);
287*ae771770SStanislav Sedov return ret;
288*ae771770SStanislav Sedov }
289*ae771770SStanislav Sedov
290*ae771770SStanislav Sedov ret = (*db->hdb_open)(context, db, O_RDONLY, 0);
291*ae771770SStanislav Sedov if (ret) {
292*ae771770SStanislav Sedov (*db->hdb_destroy)(context, db);
293*ae771770SStanislav Sedov return ret;
294*ae771770SStanislav Sedov }
295*ae771770SStanislav Sedov
296*ae771770SStanislav Sedov cursor->data = c = malloc (sizeof(*c));
297*ae771770SStanislav Sedov if(c == NULL){
298*ae771770SStanislav Sedov (*db->hdb_close)(context, db);
299*ae771770SStanislav Sedov (*db->hdb_destroy)(context, db);
300*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
301*ae771770SStanislav Sedov return ENOMEM;
302*ae771770SStanislav Sedov }
303*ae771770SStanislav Sedov
304*ae771770SStanislav Sedov c->db = db;
305*ae771770SStanislav Sedov c->first = TRUE;
306*ae771770SStanislav Sedov c->next = TRUE;
307*ae771770SStanislav Sedov c->key_idx = 0;
308*ae771770SStanislav Sedov
309*ae771770SStanislav Sedov cursor->data = c;
310*ae771770SStanislav Sedov return ret;
311*ae771770SStanislav Sedov }
312*ae771770SStanislav Sedov
313*ae771770SStanislav Sedov static int KRB5_CALLCONV
hdb_next_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry,krb5_kt_cursor * cursor)314*ae771770SStanislav Sedov hdb_next_entry(krb5_context context,
315*ae771770SStanislav Sedov krb5_keytab id,
316*ae771770SStanislav Sedov krb5_keytab_entry *entry,
317*ae771770SStanislav Sedov krb5_kt_cursor *cursor)
318*ae771770SStanislav Sedov {
319*ae771770SStanislav Sedov struct hdb_cursor *c = cursor->data;
320*ae771770SStanislav Sedov krb5_error_code ret;
321*ae771770SStanislav Sedov
322*ae771770SStanislav Sedov memset(entry, 0, sizeof(*entry));
323*ae771770SStanislav Sedov
324*ae771770SStanislav Sedov if (c->first) {
325*ae771770SStanislav Sedov c->first = FALSE;
326*ae771770SStanislav Sedov ret = (c->db->hdb_firstkey)(context, c->db,
327*ae771770SStanislav Sedov HDB_F_DECRYPT|
328*ae771770SStanislav Sedov HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
329*ae771770SStanislav Sedov &c->hdb_entry);
330*ae771770SStanislav Sedov if (ret == HDB_ERR_NOENTRY)
331*ae771770SStanislav Sedov return KRB5_KT_END;
332*ae771770SStanislav Sedov else if (ret)
333*ae771770SStanislav Sedov return ret;
334*ae771770SStanislav Sedov
335*ae771770SStanislav Sedov if (c->hdb_entry.entry.keys.len == 0)
336*ae771770SStanislav Sedov hdb_free_entry(context, &c->hdb_entry);
337*ae771770SStanislav Sedov else
338*ae771770SStanislav Sedov c->next = FALSE;
339*ae771770SStanislav Sedov }
340*ae771770SStanislav Sedov
341*ae771770SStanislav Sedov while (c->next) {
342*ae771770SStanislav Sedov ret = (c->db->hdb_nextkey)(context, c->db,
343*ae771770SStanislav Sedov HDB_F_DECRYPT|
344*ae771770SStanislav Sedov HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
345*ae771770SStanislav Sedov &c->hdb_entry);
346*ae771770SStanislav Sedov if (ret == HDB_ERR_NOENTRY)
347*ae771770SStanislav Sedov return KRB5_KT_END;
348*ae771770SStanislav Sedov else if (ret)
349*ae771770SStanislav Sedov return ret;
350*ae771770SStanislav Sedov
351*ae771770SStanislav Sedov /* If no keys on this entry, try again */
352*ae771770SStanislav Sedov if (c->hdb_entry.entry.keys.len == 0)
353*ae771770SStanislav Sedov hdb_free_entry(context, &c->hdb_entry);
354*ae771770SStanislav Sedov else
355*ae771770SStanislav Sedov c->next = FALSE;
356*ae771770SStanislav Sedov }
357*ae771770SStanislav Sedov
358*ae771770SStanislav Sedov /*
359*ae771770SStanislav Sedov * Return next enc type (keytabs are one slot per key, while
360*ae771770SStanislav Sedov * hdb is one record per principal.
361*ae771770SStanislav Sedov */
362*ae771770SStanislav Sedov
363*ae771770SStanislav Sedov ret = krb5_copy_principal(context,
364*ae771770SStanislav Sedov c->hdb_entry.entry.principal,
365*ae771770SStanislav Sedov &entry->principal);
366*ae771770SStanislav Sedov if (ret)
367*ae771770SStanislav Sedov return ret;
368*ae771770SStanislav Sedov
369*ae771770SStanislav Sedov entry->vno = c->hdb_entry.entry.kvno;
370*ae771770SStanislav Sedov ret = krb5_copy_keyblock_contents(context,
371*ae771770SStanislav Sedov &c->hdb_entry.entry.keys.val[c->key_idx].key,
372*ae771770SStanislav Sedov &entry->keyblock);
373*ae771770SStanislav Sedov if (ret) {
374*ae771770SStanislav Sedov krb5_free_principal(context, entry->principal);
375*ae771770SStanislav Sedov memset(entry, 0, sizeof(*entry));
376*ae771770SStanislav Sedov return ret;
377*ae771770SStanislav Sedov }
378*ae771770SStanislav Sedov c->key_idx++;
379*ae771770SStanislav Sedov
380*ae771770SStanislav Sedov /*
381*ae771770SStanislav Sedov * Once we get to the end of the list, signal that we want the
382*ae771770SStanislav Sedov * next entry
383*ae771770SStanislav Sedov */
384*ae771770SStanislav Sedov
385*ae771770SStanislav Sedov if ((size_t)c->key_idx == c->hdb_entry.entry.keys.len) {
386*ae771770SStanislav Sedov hdb_free_entry(context, &c->hdb_entry);
387*ae771770SStanislav Sedov c->next = TRUE;
388*ae771770SStanislav Sedov c->key_idx = 0;
389*ae771770SStanislav Sedov }
390*ae771770SStanislav Sedov
391*ae771770SStanislav Sedov return 0;
392*ae771770SStanislav Sedov }
393*ae771770SStanislav Sedov
394*ae771770SStanislav Sedov
395*ae771770SStanislav Sedov static int KRB5_CALLCONV
hdb_end_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)396*ae771770SStanislav Sedov hdb_end_seq_get(krb5_context context,
397*ae771770SStanislav Sedov krb5_keytab id,
398*ae771770SStanislav Sedov krb5_kt_cursor *cursor)
399*ae771770SStanislav Sedov {
400*ae771770SStanislav Sedov struct hdb_cursor *c = cursor->data;
401*ae771770SStanislav Sedov
402*ae771770SStanislav Sedov if (!c->next)
403*ae771770SStanislav Sedov hdb_free_entry(context, &c->hdb_entry);
404*ae771770SStanislav Sedov
405*ae771770SStanislav Sedov (c->db->hdb_close)(context, c->db);
406*ae771770SStanislav Sedov (c->db->hdb_destroy)(context, c->db);
407*ae771770SStanislav Sedov
408*ae771770SStanislav Sedov free(c);
409*ae771770SStanislav Sedov return 0;
410*ae771770SStanislav Sedov }
411*ae771770SStanislav Sedov
412b528cefcSMark Murray krb5_kt_ops hdb_kt_ops = {
413b528cefcSMark Murray "HDB",
414b528cefcSMark Murray hdb_resolve,
415b528cefcSMark Murray hdb_get_name,
416b528cefcSMark Murray hdb_close,
417*ae771770SStanislav Sedov NULL, /* destroy */
418b528cefcSMark Murray hdb_get_entry,
419*ae771770SStanislav Sedov hdb_start_seq_get,
420*ae771770SStanislav Sedov hdb_next_entry,
421*ae771770SStanislav Sedov hdb_end_seq_get,
422b528cefcSMark Murray NULL, /* add */
423b528cefcSMark Murray NULL /* remove */
424b528cefcSMark Murray };
425