xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hdb/common.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
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