2 * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 hdb_principal2key(krb5_context context
, krb5_const_principal p
, krb5_data
*key
)
43 ret
= copy_Principal(p
, &new);
46 new.name
.name_type
= 0;
48 ASN1_MALLOC_ENCODE(Principal
, key
->data
, key
->length
, &new, &len
, ret
);
49 if (ret
== 0 && key
->length
!= len
)
50 krb5_abortx(context
, "internal asn.1 encoder error");
56 hdb_key2principal(krb5_context context
, krb5_data
*key
, krb5_principal p
)
58 return decode_Principal(key
->data
, key
->length
, p
, NULL
);
62 hdb_entry2value(krb5_context context
, const hdb_entry
*ent
, krb5_data
*value
)
67 ASN1_MALLOC_ENCODE(hdb_entry
, value
->data
, value
->length
, ent
, &len
, ret
);
68 if (ret
== 0 && value
->length
!= len
)
69 krb5_abortx(context
, "internal asn.1 encoder error");
74 hdb_value2entry(krb5_context context
, krb5_data
*value
, hdb_entry
*ent
)
76 return decode_hdb_entry(value
->data
, value
->length
, ent
, NULL
);
80 hdb_entry_alias2value(krb5_context context
,
81 const hdb_entry_alias
*alias
,
87 ASN1_MALLOC_ENCODE(hdb_entry_alias
, value
->data
, value
->length
,
89 if (ret
== 0 && value
->length
!= len
)
90 krb5_abortx(context
, "internal asn.1 encoder error");
95 hdb_value2entry_alias(krb5_context context
, krb5_data
*value
,
98 return decode_hdb_entry_alias(value
->data
, value
->length
, ent
, NULL
);
102 _hdb_fetch_kvno(krb5_context context
, HDB
*db
, krb5_const_principal principal
,
103 unsigned flags
, krb5_kvno kvno
, hdb_entry_ex
*entry
)
105 krb5_principal enterprise_principal
= NULL
;
106 krb5_data key
, value
;
109 if (principal
->name
.name_type
== KRB5_NT_ENTERPRISE_PRINCIPAL
) {
110 if (principal
->name
.name_string
.len
!= 1) {
111 ret
= KRB5_PARSE_MALFORMED
;
112 krb5_set_error_message(context
, ret
, "malformed principal: "
113 "enterprise name with %d name components",
114 principal
->name
.name_string
.len
);
117 ret
= krb5_parse_name(context
, principal
->name
.name_string
.val
[0],
118 &enterprise_principal
);
121 principal
= enterprise_principal
;
124 hdb_principal2key(context
, principal
, &key
);
125 if (enterprise_principal
)
126 krb5_free_principal(context
, enterprise_principal
);
127 ret
= db
->hdb__get(context
, db
, key
, &value
);
128 krb5_data_free(&key
);
131 ret
= hdb_value2entry(context
, &value
, &entry
->entry
);
132 if (ret
== ASN1_BAD_ID
&& (flags
& HDB_F_CANON
) == 0) {
133 krb5_data_free(&value
);
134 return HDB_ERR_NOENTRY
;
135 } else if (ret
== ASN1_BAD_ID
) {
136 hdb_entry_alias alias
;
138 ret
= hdb_value2entry_alias(context
, &value
, &alias
);
140 krb5_data_free(&value
);
143 hdb_principal2key(context
, alias
.principal
, &key
);
144 krb5_data_free(&value
);
145 free_hdb_entry_alias(&alias
);
147 ret
= db
->hdb__get(context
, db
, key
, &value
);
148 krb5_data_free(&key
);
151 ret
= hdb_value2entry(context
, &value
, &entry
->entry
);
153 krb5_data_free(&value
);
157 krb5_data_free(&value
);
158 if ((flags
& HDB_F_DECRYPT
) && (flags
& HDB_F_ALL_KVNOS
)) {
159 /* Decrypt the current keys */
160 ret
= hdb_unseal_keys(context
, db
, &entry
->entry
);
162 hdb_free_entry(context
, entry
);
165 /* Decrypt the key history too */
166 ret
= hdb_unseal_keys_kvno(context
, db
, 0, flags
, &entry
->entry
);
168 hdb_free_entry(context
, entry
);
171 } else if ((flags
& HDB_F_DECRYPT
)) {
172 if ((flags
& HDB_F_KVNO_SPECIFIED
) == 0 || kvno
== entry
->entry
.kvno
) {
173 /* Decrypt the current keys */
174 ret
= hdb_unseal_keys(context
, db
, &entry
->entry
);
176 hdb_free_entry(context
, entry
);
180 if ((flags
& HDB_F_ALL_KVNOS
))
183 * Find and decrypt the keys from the history that we want,
184 * and swap them with the current keys
186 ret
= hdb_unseal_keys_kvno(context
, db
, kvno
, flags
, &entry
->entry
);
188 hdb_free_entry(context
, entry
);
197 static krb5_error_code
198 hdb_remove_aliases(krb5_context context
, HDB
*db
, krb5_data
*key
)
200 const HDB_Ext_Aliases
*aliases
;
201 krb5_error_code code
;
206 code
= db
->hdb__get(context
, db
, *key
, &value
);
207 if (code
== HDB_ERR_NOENTRY
)
212 code
= hdb_value2entry(context
, &value
, &oldentry
);
213 krb5_data_free(&value
);
217 code
= hdb_entry_get_aliases(&oldentry
, &aliases
);
218 if (code
|| aliases
== NULL
) {
219 free_hdb_entry(&oldentry
);
222 for (i
= 0; i
< aliases
->aliases
.len
; i
++) {
225 hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &akey
);
226 code
= db
->hdb__del(context
, db
, akey
);
227 krb5_data_free(&akey
);
229 free_hdb_entry(&oldentry
);
233 free_hdb_entry(&oldentry
);
237 static krb5_error_code
238 hdb_add_aliases(krb5_context context
, HDB
*db
,
239 unsigned flags
, hdb_entry_ex
*entry
)
241 const HDB_Ext_Aliases
*aliases
;
242 krb5_error_code code
;
243 krb5_data key
, value
;
246 code
= hdb_entry_get_aliases(&entry
->entry
, &aliases
);
247 if (code
|| aliases
== NULL
)
250 for (i
= 0; i
< aliases
->aliases
.len
; i
++) {
251 hdb_entry_alias entryalias
;
252 entryalias
.principal
= entry
->entry
.principal
;
254 hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &key
);
255 code
= hdb_entry_alias2value(context
, &entryalias
, &value
);
257 krb5_data_free(&key
);
260 code
= db
->hdb__put(context
, db
, flags
, key
, value
);
261 krb5_data_free(&key
);
262 krb5_data_free(&value
);
269 static krb5_error_code
270 hdb_check_aliases(krb5_context context
, HDB
*db
, hdb_entry_ex
*entry
)
272 const HDB_Ext_Aliases
*aliases
;
276 /* check if new aliases already is used */
278 code
= hdb_entry_get_aliases(&entry
->entry
, &aliases
);
282 for (i
= 0; aliases
&& i
< aliases
->aliases
.len
; i
++) {
283 hdb_entry_alias alias
;
284 krb5_data akey
, value
;
286 hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &akey
);
287 code
= db
->hdb__get(context
, db
, akey
, &value
);
288 krb5_data_free(&akey
);
289 if (code
== HDB_ERR_NOENTRY
)
294 code
= hdb_value2entry_alias(context
, &value
, &alias
);
295 krb5_data_free(&value
);
297 if (code
== ASN1_BAD_ID
)
298 return HDB_ERR_EXISTS
;
302 code
= krb5_principal_compare(context
, alias
.principal
,
303 entry
->entry
.principal
);
304 free_hdb_entry_alias(&alias
);
306 return HDB_ERR_EXISTS
;
312 _hdb_store(krb5_context context
, HDB
*db
, unsigned flags
, hdb_entry_ex
*entry
)
314 krb5_data key
, value
;
317 if (entry
->entry
.flags
.do_not_store
)
318 return HDB_ERR_MISUSE
;
319 /* check if new aliases already is used */
320 code
= hdb_check_aliases(context
, db
, entry
);
324 if(entry
->entry
.generation
== NULL
) {
326 entry
->entry
.generation
= malloc(sizeof(*entry
->entry
.generation
));
327 if(entry
->entry
.generation
== NULL
) {
328 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
331 gettimeofday(&t
, NULL
);
332 entry
->entry
.generation
->time
= t
.tv_sec
;
333 entry
->entry
.generation
->usec
= t
.tv_usec
;
334 entry
->entry
.generation
->gen
= 0;
336 entry
->entry
.generation
->gen
++;
338 code
= hdb_seal_keys(context
, db
, &entry
->entry
);
342 hdb_principal2key(context
, entry
->entry
.principal
, &key
);
345 code
= hdb_remove_aliases(context
, db
, &key
);
347 krb5_data_free(&key
);
350 hdb_entry2value(context
, &entry
->entry
, &value
);
351 code
= db
->hdb__put(context
, db
, flags
& HDB_F_REPLACE
, key
, value
);
352 krb5_data_free(&value
);
353 krb5_data_free(&key
);
357 code
= hdb_add_aliases(context
, db
, flags
, entry
);
363 _hdb_remove(krb5_context context
, HDB
*db
, krb5_const_principal principal
)
368 hdb_principal2key(context
, principal
, &key
);
370 code
= hdb_remove_aliases(context
, db
, &key
);
372 krb5_data_free(&key
);
375 code
= db
->hdb__del(context
, db
, key
);
376 krb5_data_free(&key
);