1*d3273b5bSchristos /* $NetBSD: common.c,v 1.2 2017/01/28 21:31:48 christos Exp $ */
2ca1c9b0cSelric
3ca1c9b0cSelric /*
4ca1c9b0cSelric * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
5ca1c9b0cSelric * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric * All rights reserved.
7ca1c9b0cSelric *
8ca1c9b0cSelric * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric * modification, are permitted provided that the following conditions
10ca1c9b0cSelric * are met:
11ca1c9b0cSelric *
12ca1c9b0cSelric * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric * notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric *
15ca1c9b0cSelric * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric * notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric * documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric *
19ca1c9b0cSelric * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric * may be used to endorse or promote products derived from this software
21ca1c9b0cSelric * without specific prior written permission.
22ca1c9b0cSelric *
23ca1c9b0cSelric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric * SUCH DAMAGE.
34ca1c9b0cSelric */
35ca1c9b0cSelric
36ca1c9b0cSelric #include "hdb_locl.h"
37ca1c9b0cSelric
38ca1c9b0cSelric int
hdb_principal2key(krb5_context context,krb5_const_principal p,krb5_data * key)39ca1c9b0cSelric hdb_principal2key(krb5_context context, krb5_const_principal p, krb5_data *key)
40ca1c9b0cSelric {
41ca1c9b0cSelric Principal new;
424f77a458Spettai size_t len = 0;
43ca1c9b0cSelric int ret;
44ca1c9b0cSelric
45ca1c9b0cSelric ret = copy_Principal(p, &new);
46ca1c9b0cSelric if(ret)
47ca1c9b0cSelric return ret;
48ca1c9b0cSelric new.name.name_type = 0;
49ca1c9b0cSelric
50ca1c9b0cSelric ASN1_MALLOC_ENCODE(Principal, key->data, key->length, &new, &len, ret);
51ca1c9b0cSelric if (ret == 0 && key->length != len)
52ca1c9b0cSelric krb5_abortx(context, "internal asn.1 encoder error");
53ca1c9b0cSelric free_Principal(&new);
54ca1c9b0cSelric return ret;
55ca1c9b0cSelric }
56ca1c9b0cSelric
57ca1c9b0cSelric int
hdb_key2principal(krb5_context context,krb5_data * key,krb5_principal p)58ca1c9b0cSelric hdb_key2principal(krb5_context context, krb5_data *key, krb5_principal p)
59ca1c9b0cSelric {
60ca1c9b0cSelric return decode_Principal(key->data, key->length, p, NULL);
61ca1c9b0cSelric }
62ca1c9b0cSelric
63ca1c9b0cSelric int
hdb_entry2value(krb5_context context,const hdb_entry * ent,krb5_data * value)64ca1c9b0cSelric hdb_entry2value(krb5_context context, const hdb_entry *ent, krb5_data *value)
65ca1c9b0cSelric {
664f77a458Spettai size_t len = 0;
67ca1c9b0cSelric int ret;
68ca1c9b0cSelric
69ca1c9b0cSelric ASN1_MALLOC_ENCODE(hdb_entry, value->data, value->length, ent, &len, ret);
70ca1c9b0cSelric if (ret == 0 && value->length != len)
71ca1c9b0cSelric krb5_abortx(context, "internal asn.1 encoder error");
72ca1c9b0cSelric return ret;
73ca1c9b0cSelric }
74ca1c9b0cSelric
75ca1c9b0cSelric int
hdb_value2entry(krb5_context context,krb5_data * value,hdb_entry * ent)76ca1c9b0cSelric hdb_value2entry(krb5_context context, krb5_data *value, hdb_entry *ent)
77ca1c9b0cSelric {
78ca1c9b0cSelric return decode_hdb_entry(value->data, value->length, ent, NULL);
79ca1c9b0cSelric }
80ca1c9b0cSelric
81ca1c9b0cSelric int
hdb_entry_alias2value(krb5_context context,const hdb_entry_alias * alias,krb5_data * value)82ca1c9b0cSelric hdb_entry_alias2value(krb5_context context,
83ca1c9b0cSelric const hdb_entry_alias *alias,
84ca1c9b0cSelric krb5_data *value)
85ca1c9b0cSelric {
864f77a458Spettai size_t len = 0;
87ca1c9b0cSelric int ret;
88ca1c9b0cSelric
89ca1c9b0cSelric ASN1_MALLOC_ENCODE(hdb_entry_alias, value->data, value->length,
90ca1c9b0cSelric alias, &len, ret);
91ca1c9b0cSelric if (ret == 0 && value->length != len)
92ca1c9b0cSelric krb5_abortx(context, "internal asn.1 encoder error");
93ca1c9b0cSelric return ret;
94ca1c9b0cSelric }
95ca1c9b0cSelric
96ca1c9b0cSelric int
hdb_value2entry_alias(krb5_context context,krb5_data * value,hdb_entry_alias * ent)97ca1c9b0cSelric hdb_value2entry_alias(krb5_context context, krb5_data *value,
98ca1c9b0cSelric hdb_entry_alias *ent)
99ca1c9b0cSelric {
100ca1c9b0cSelric return decode_hdb_entry_alias(value->data, value->length, ent, NULL);
101ca1c9b0cSelric }
102ca1c9b0cSelric
103ca1c9b0cSelric krb5_error_code
_hdb_fetch_kvno(krb5_context context,HDB * db,krb5_const_principal principal,unsigned flags,krb5_kvno kvno,hdb_entry_ex * entry)104ca1c9b0cSelric _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
105ca1c9b0cSelric unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry)
106ca1c9b0cSelric {
107ca1c9b0cSelric krb5_principal enterprise_principal = NULL;
108ca1c9b0cSelric krb5_data key, value;
109ca1c9b0cSelric krb5_error_code ret;
110ca1c9b0cSelric
111ca1c9b0cSelric if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
112ca1c9b0cSelric if (principal->name.name_string.len != 1) {
113ca1c9b0cSelric ret = KRB5_PARSE_MALFORMED;
114ca1c9b0cSelric krb5_set_error_message(context, ret, "malformed principal: "
115ca1c9b0cSelric "enterprise name with %d name components",
116ca1c9b0cSelric principal->name.name_string.len);
117ca1c9b0cSelric return ret;
118ca1c9b0cSelric }
119ca1c9b0cSelric ret = krb5_parse_name(context, principal->name.name_string.val[0],
120ca1c9b0cSelric &enterprise_principal);
121ca1c9b0cSelric if (ret)
122ca1c9b0cSelric return ret;
123ca1c9b0cSelric principal = enterprise_principal;
124ca1c9b0cSelric }
125ca1c9b0cSelric
126ca1c9b0cSelric hdb_principal2key(context, principal, &key);
127ca1c9b0cSelric if (enterprise_principal)
128ca1c9b0cSelric krb5_free_principal(context, enterprise_principal);
129b9d004c6Schristos ret = db->hdb__get(context, db, key, &value);
130ca1c9b0cSelric krb5_data_free(&key);
131b9d004c6Schristos if(ret)
132b9d004c6Schristos return ret;
133b9d004c6Schristos ret = hdb_value2entry(context, &value, &entry->entry);
134b9d004c6Schristos if (ret == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) {
135ca1c9b0cSelric krb5_data_free(&value);
136ca1c9b0cSelric return HDB_ERR_NOENTRY;
137b9d004c6Schristos } else if (ret == ASN1_BAD_ID) {
138ca1c9b0cSelric hdb_entry_alias alias;
139ca1c9b0cSelric
140b9d004c6Schristos ret = hdb_value2entry_alias(context, &value, &alias);
141b9d004c6Schristos if (ret) {
142ca1c9b0cSelric krb5_data_free(&value);
143b9d004c6Schristos return ret;
144ca1c9b0cSelric }
145ca1c9b0cSelric hdb_principal2key(context, alias.principal, &key);
146ca1c9b0cSelric krb5_data_free(&value);
147ca1c9b0cSelric free_hdb_entry_alias(&alias);
148ca1c9b0cSelric
149b9d004c6Schristos ret = db->hdb__get(context, db, key, &value);
150ca1c9b0cSelric krb5_data_free(&key);
151b9d004c6Schristos if (ret)
152b9d004c6Schristos return ret;
153b9d004c6Schristos ret = hdb_value2entry(context, &value, &entry->entry);
154b9d004c6Schristos if (ret) {
155ca1c9b0cSelric krb5_data_free(&value);
156b9d004c6Schristos return ret;
157ca1c9b0cSelric }
158ca1c9b0cSelric }
159ca1c9b0cSelric krb5_data_free(&value);
160b9d004c6Schristos if ((flags & HDB_F_DECRYPT) && (flags & HDB_F_ALL_KVNOS)) {
161b9d004c6Schristos /* Decrypt the current keys */
162b9d004c6Schristos ret = hdb_unseal_keys(context, db, &entry->entry);
163b9d004c6Schristos if (ret) {
164ca1c9b0cSelric hdb_free_entry(context, entry);
165b9d004c6Schristos return ret;
166ca1c9b0cSelric }
167b9d004c6Schristos /* Decrypt the key history too */
168b9d004c6Schristos ret = hdb_unseal_keys_kvno(context, db, 0, flags, &entry->entry);
169b9d004c6Schristos if (ret) {
170b9d004c6Schristos hdb_free_entry(context, entry);
171b9d004c6Schristos return ret;
172b9d004c6Schristos }
173b9d004c6Schristos } else if ((flags & HDB_F_DECRYPT)) {
174b9d004c6Schristos if ((flags & HDB_F_KVNO_SPECIFIED) == 0 || kvno == entry->entry.kvno) {
175b9d004c6Schristos /* Decrypt the current keys */
176b9d004c6Schristos ret = hdb_unseal_keys(context, db, &entry->entry);
177b9d004c6Schristos if (ret) {
178b9d004c6Schristos hdb_free_entry(context, entry);
179b9d004c6Schristos return ret;
180b9d004c6Schristos }
181b9d004c6Schristos } else {
182b9d004c6Schristos if ((flags & HDB_F_ALL_KVNOS))
183b9d004c6Schristos kvno = 0;
184b9d004c6Schristos /*
185b9d004c6Schristos * Find and decrypt the keys from the history that we want,
186b9d004c6Schristos * and swap them with the current keys
187b9d004c6Schristos */
188b9d004c6Schristos ret = hdb_unseal_keys_kvno(context, db, kvno, flags, &entry->entry);
189b9d004c6Schristos if (ret) {
190b9d004c6Schristos hdb_free_entry(context, entry);
191b9d004c6Schristos return ret;
192b9d004c6Schristos }
193b9d004c6Schristos }
194b9d004c6Schristos }
195b9d004c6Schristos
196b9d004c6Schristos return 0;
197ca1c9b0cSelric }
198ca1c9b0cSelric
199ca1c9b0cSelric static krb5_error_code
hdb_remove_aliases(krb5_context context,HDB * db,krb5_data * key)200ca1c9b0cSelric hdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key)
201ca1c9b0cSelric {
202ca1c9b0cSelric const HDB_Ext_Aliases *aliases;
203ca1c9b0cSelric krb5_error_code code;
204ca1c9b0cSelric hdb_entry oldentry;
205ca1c9b0cSelric krb5_data value;
2064f77a458Spettai size_t i;
207ca1c9b0cSelric
208ca1c9b0cSelric code = db->hdb__get(context, db, *key, &value);
209ca1c9b0cSelric if (code == HDB_ERR_NOENTRY)
210ca1c9b0cSelric return 0;
211ca1c9b0cSelric else if (code)
212ca1c9b0cSelric return code;
213ca1c9b0cSelric
214ca1c9b0cSelric code = hdb_value2entry(context, &value, &oldentry);
215ca1c9b0cSelric krb5_data_free(&value);
216ca1c9b0cSelric if (code)
217ca1c9b0cSelric return code;
218ca1c9b0cSelric
219ca1c9b0cSelric code = hdb_entry_get_aliases(&oldentry, &aliases);
220ca1c9b0cSelric if (code || aliases == NULL) {
221ca1c9b0cSelric free_hdb_entry(&oldentry);
222ca1c9b0cSelric return code;
223ca1c9b0cSelric }
224ca1c9b0cSelric for (i = 0; i < aliases->aliases.len; i++) {
225ca1c9b0cSelric krb5_data akey;
226ca1c9b0cSelric
227b9d004c6Schristos code = hdb_principal2key(context, &aliases->aliases.val[i], &akey);
228b9d004c6Schristos if (code == 0) {
229ca1c9b0cSelric code = db->hdb__del(context, db, akey);
230ca1c9b0cSelric krb5_data_free(&akey);
231b9d004c6Schristos }
232ca1c9b0cSelric if (code) {
233ca1c9b0cSelric free_hdb_entry(&oldentry);
234ca1c9b0cSelric return code;
235ca1c9b0cSelric }
236ca1c9b0cSelric }
237ca1c9b0cSelric free_hdb_entry(&oldentry);
238ca1c9b0cSelric return 0;
239ca1c9b0cSelric }
240ca1c9b0cSelric
241ca1c9b0cSelric static krb5_error_code
hdb_add_aliases(krb5_context context,HDB * db,unsigned flags,hdb_entry_ex * entry)242ca1c9b0cSelric hdb_add_aliases(krb5_context context, HDB *db,
243ca1c9b0cSelric unsigned flags, hdb_entry_ex *entry)
244ca1c9b0cSelric {
245ca1c9b0cSelric const HDB_Ext_Aliases *aliases;
246ca1c9b0cSelric krb5_error_code code;
247ca1c9b0cSelric krb5_data key, value;
2484f77a458Spettai size_t i;
249ca1c9b0cSelric
250ca1c9b0cSelric code = hdb_entry_get_aliases(&entry->entry, &aliases);
251ca1c9b0cSelric if (code || aliases == NULL)
252ca1c9b0cSelric return code;
253ca1c9b0cSelric
254ca1c9b0cSelric for (i = 0; i < aliases->aliases.len; i++) {
255ca1c9b0cSelric hdb_entry_alias entryalias;
256ca1c9b0cSelric entryalias.principal = entry->entry.principal;
257ca1c9b0cSelric
258ca1c9b0cSelric code = hdb_entry_alias2value(context, &entryalias, &value);
259b9d004c6Schristos if (code)
260ca1c9b0cSelric return code;
261b9d004c6Schristos
262b9d004c6Schristos code = hdb_principal2key(context, &aliases->aliases.val[i], &key);
263b9d004c6Schristos if (code == 0) {
264ca1c9b0cSelric code = db->hdb__put(context, db, flags, key, value);
265ca1c9b0cSelric krb5_data_free(&key);
266b9d004c6Schristos }
267ca1c9b0cSelric krb5_data_free(&value);
268ca1c9b0cSelric if (code)
269ca1c9b0cSelric return code;
270ca1c9b0cSelric }
271ca1c9b0cSelric return 0;
272ca1c9b0cSelric }
273ca1c9b0cSelric
274ca1c9b0cSelric static krb5_error_code
hdb_check_aliases(krb5_context context,HDB * db,hdb_entry_ex * entry)275ca1c9b0cSelric hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry)
276ca1c9b0cSelric {
277ca1c9b0cSelric const HDB_Ext_Aliases *aliases;
2784f77a458Spettai int code;
2794f77a458Spettai size_t i;
280ca1c9b0cSelric
281ca1c9b0cSelric /* check if new aliases already is used */
282ca1c9b0cSelric
283ca1c9b0cSelric code = hdb_entry_get_aliases(&entry->entry, &aliases);
284ca1c9b0cSelric if (code)
285ca1c9b0cSelric return code;
286ca1c9b0cSelric
287ca1c9b0cSelric for (i = 0; aliases && i < aliases->aliases.len; i++) {
288ca1c9b0cSelric hdb_entry_alias alias;
289ca1c9b0cSelric krb5_data akey, value;
290ca1c9b0cSelric
291b9d004c6Schristos code = hdb_principal2key(context, &aliases->aliases.val[i], &akey);
292b9d004c6Schristos if (code == 0) {
293ca1c9b0cSelric code = db->hdb__get(context, db, akey, &value);
294ca1c9b0cSelric krb5_data_free(&akey);
295b9d004c6Schristos }
296ca1c9b0cSelric if (code == HDB_ERR_NOENTRY)
297ca1c9b0cSelric continue;
298ca1c9b0cSelric else if (code)
299ca1c9b0cSelric return code;
300ca1c9b0cSelric
301ca1c9b0cSelric code = hdb_value2entry_alias(context, &value, &alias);
302ca1c9b0cSelric krb5_data_free(&value);
303ca1c9b0cSelric
304ca1c9b0cSelric if (code == ASN1_BAD_ID)
305ca1c9b0cSelric return HDB_ERR_EXISTS;
306ca1c9b0cSelric else if (code)
307ca1c9b0cSelric return code;
308ca1c9b0cSelric
309ca1c9b0cSelric code = krb5_principal_compare(context, alias.principal,
310ca1c9b0cSelric entry->entry.principal);
311ca1c9b0cSelric free_hdb_entry_alias(&alias);
312ca1c9b0cSelric if (code == 0)
313ca1c9b0cSelric return HDB_ERR_EXISTS;
314ca1c9b0cSelric }
315ca1c9b0cSelric return 0;
316ca1c9b0cSelric }
317ca1c9b0cSelric
318ca1c9b0cSelric krb5_error_code
_hdb_store(krb5_context context,HDB * db,unsigned flags,hdb_entry_ex * entry)319ca1c9b0cSelric _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
320ca1c9b0cSelric {
321ca1c9b0cSelric krb5_data key, value;
322ca1c9b0cSelric int code;
323ca1c9b0cSelric
324b9d004c6Schristos if (entry->entry.flags.do_not_store)
325b9d004c6Schristos return HDB_ERR_MISUSE;
326ca1c9b0cSelric /* check if new aliases already is used */
327ca1c9b0cSelric code = hdb_check_aliases(context, db, entry);
328ca1c9b0cSelric if (code)
329ca1c9b0cSelric return code;
330ca1c9b0cSelric
331b9d004c6Schristos if ((flags & HDB_F_PRECHECK) && (flags & HDB_F_REPLACE))
332b9d004c6Schristos return 0;
333b9d004c6Schristos
334b9d004c6Schristos if ((flags & HDB_F_PRECHECK)) {
335b9d004c6Schristos code = hdb_principal2key(context, entry->entry.principal, &key);
336b9d004c6Schristos if (code)
337b9d004c6Schristos return code;
338b9d004c6Schristos code = db->hdb__get(context, db, key, &value);
339b9d004c6Schristos krb5_data_free(&key);
340b9d004c6Schristos if (code == 0)
341b9d004c6Schristos krb5_data_free(&value);
342b9d004c6Schristos if (code == HDB_ERR_NOENTRY)
343b9d004c6Schristos return 0;
344b9d004c6Schristos return code ? code : HDB_ERR_EXISTS;
345b9d004c6Schristos }
346b9d004c6Schristos
347ca1c9b0cSelric if(entry->entry.generation == NULL) {
348ca1c9b0cSelric struct timeval t;
349ca1c9b0cSelric entry->entry.generation = malloc(sizeof(*entry->entry.generation));
350ca1c9b0cSelric if(entry->entry.generation == NULL) {
351ca1c9b0cSelric krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
352ca1c9b0cSelric return ENOMEM;
353ca1c9b0cSelric }
354ca1c9b0cSelric gettimeofday(&t, NULL);
355ca1c9b0cSelric entry->entry.generation->time = t.tv_sec;
356ca1c9b0cSelric entry->entry.generation->usec = t.tv_usec;
357ca1c9b0cSelric entry->entry.generation->gen = 0;
358ca1c9b0cSelric } else
359ca1c9b0cSelric entry->entry.generation->gen++;
360ca1c9b0cSelric
361ca1c9b0cSelric code = hdb_seal_keys(context, db, &entry->entry);
362ca1c9b0cSelric if (code)
363ca1c9b0cSelric return code;
364ca1c9b0cSelric
365ca1c9b0cSelric hdb_principal2key(context, entry->entry.principal, &key);
366ca1c9b0cSelric
367ca1c9b0cSelric /* remove aliases */
368ca1c9b0cSelric code = hdb_remove_aliases(context, db, &key);
369ca1c9b0cSelric if (code) {
370ca1c9b0cSelric krb5_data_free(&key);
371ca1c9b0cSelric return code;
372ca1c9b0cSelric }
373ca1c9b0cSelric hdb_entry2value(context, &entry->entry, &value);
374ca1c9b0cSelric code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value);
375ca1c9b0cSelric krb5_data_free(&value);
376ca1c9b0cSelric krb5_data_free(&key);
377ca1c9b0cSelric if (code)
378ca1c9b0cSelric return code;
379ca1c9b0cSelric
380ca1c9b0cSelric code = hdb_add_aliases(context, db, flags, entry);
381ca1c9b0cSelric
382ca1c9b0cSelric return code;
383ca1c9b0cSelric }
384ca1c9b0cSelric
385ca1c9b0cSelric krb5_error_code
_hdb_remove(krb5_context context,HDB * db,unsigned flags,krb5_const_principal principal)386b9d004c6Schristos _hdb_remove(krb5_context context, HDB *db,
387b9d004c6Schristos unsigned flags, krb5_const_principal principal)
388ca1c9b0cSelric {
389b9d004c6Schristos krb5_data key, value;
390ca1c9b0cSelric int code;
391ca1c9b0cSelric
392ca1c9b0cSelric hdb_principal2key(context, principal, &key);
393ca1c9b0cSelric
394b9d004c6Schristos if ((flags & HDB_F_PRECHECK)) {
395b9d004c6Schristos /*
396b9d004c6Schristos * We don't check that we can delete the aliases because we
397b9d004c6Schristos * assume that the DB is consistent. If we did check for alias
398b9d004c6Schristos * consistency we'd also have to provide a way to fsck the DB,
399b9d004c6Schristos * otherwise admins would have no way to recover -- papering
400b9d004c6Schristos * over this here is less work, but we really ought to provide
401b9d004c6Schristos * an HDB fsck.
402b9d004c6Schristos */
403b9d004c6Schristos code = db->hdb__get(context, db, key, &value);
404b9d004c6Schristos krb5_data_free(&key);
405b9d004c6Schristos if (code == 0) {
406b9d004c6Schristos krb5_data_free(&value);
407b9d004c6Schristos return 0;
408b9d004c6Schristos }
409b9d004c6Schristos return code;
410b9d004c6Schristos }
411b9d004c6Schristos
412ca1c9b0cSelric code = hdb_remove_aliases(context, db, &key);
413ca1c9b0cSelric if (code) {
414ca1c9b0cSelric krb5_data_free(&key);
415ca1c9b0cSelric return code;
416ca1c9b0cSelric }
417ca1c9b0cSelric code = db->hdb__del(context, db, key);
418ca1c9b0cSelric krb5_data_free(&key);
419ca1c9b0cSelric return code;
420ca1c9b0cSelric }
421ca1c9b0cSelric
422