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 (db
->hdb_master_key_set
&& (flags
& HDB_F_DECRYPT
)) {
159 if ((flags
& HDB_F_KVNO_SPECIFIED
) == 0 &&
160 (flags
& HDB_F_CURRENT_KVNO
) == 0) {
163 * Decrypt all the old keys too, since we don't know which
164 * the caller will need.
166 ret
= hdb_unseal_keys_kvno(context
, db
, 0, &entry
->entry
);
168 hdb_free_entry(context
, entry
);
171 } else if ((flags
& HDB_F_KVNO_SPECIFIED
) != 0 &&
172 kvno
!= entry
->entry
.kvno
&&
173 kvno
< entry
->entry
.kvno
&&
176 /* Decrypt the keys we were asked for, if not the current ones */
177 ret
= hdb_unseal_keys_kvno(context
, db
, kvno
, &entry
->entry
);
179 hdb_free_entry(context
, entry
);
184 /* Always decrypt the current keys too */
185 ret
= hdb_unseal_keys(context
, db
, &entry
->entry
);
187 hdb_free_entry(context
, entry
);
195 static krb5_error_code
196 hdb_remove_aliases(krb5_context context
, HDB
*db
, krb5_data
*key
)
198 const HDB_Ext_Aliases
*aliases
;
199 krb5_error_code code
;
204 code
= db
->hdb__get(context
, db
, *key
, &value
);
205 if (code
== HDB_ERR_NOENTRY
)
210 code
= hdb_value2entry(context
, &value
, &oldentry
);
211 krb5_data_free(&value
);
215 code
= hdb_entry_get_aliases(&oldentry
, &aliases
);
216 if (code
|| aliases
== NULL
) {
217 free_hdb_entry(&oldentry
);
220 for (i
= 0; i
< aliases
->aliases
.len
; i
++) {
223 hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &akey
);
224 code
= db
->hdb__del(context
, db
, akey
);
225 krb5_data_free(&akey
);
227 free_hdb_entry(&oldentry
);
231 free_hdb_entry(&oldentry
);
235 static krb5_error_code
236 hdb_add_aliases(krb5_context context
, HDB
*db
,
237 unsigned flags
, hdb_entry_ex
*entry
)
239 const HDB_Ext_Aliases
*aliases
;
240 krb5_error_code code
;
241 krb5_data key
, value
;
244 code
= hdb_entry_get_aliases(&entry
->entry
, &aliases
);
245 if (code
|| aliases
== NULL
)
248 for (i
= 0; i
< aliases
->aliases
.len
; i
++) {
249 hdb_entry_alias entryalias
;
250 entryalias
.principal
= entry
->entry
.principal
;
252 hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &key
);
253 code
= hdb_entry_alias2value(context
, &entryalias
, &value
);
255 krb5_data_free(&key
);
258 code
= db
->hdb__put(context
, db
, flags
, key
, value
);
259 krb5_data_free(&key
);
260 krb5_data_free(&value
);
267 static krb5_error_code
268 hdb_check_aliases(krb5_context context
, HDB
*db
, hdb_entry_ex
*entry
)
270 const HDB_Ext_Aliases
*aliases
;
274 /* check if new aliases already is used */
276 code
= hdb_entry_get_aliases(&entry
->entry
, &aliases
);
280 for (i
= 0; aliases
&& i
< aliases
->aliases
.len
; i
++) {
281 hdb_entry_alias alias
;
282 krb5_data akey
, value
;
284 hdb_principal2key(context
, &aliases
->aliases
.val
[i
], &akey
);
285 code
= db
->hdb__get(context
, db
, akey
, &value
);
286 krb5_data_free(&akey
);
287 if (code
== HDB_ERR_NOENTRY
)
292 code
= hdb_value2entry_alias(context
, &value
, &alias
);
293 krb5_data_free(&value
);
295 if (code
== ASN1_BAD_ID
)
296 return HDB_ERR_EXISTS
;
300 code
= krb5_principal_compare(context
, alias
.principal
,
301 entry
->entry
.principal
);
302 free_hdb_entry_alias(&alias
);
304 return HDB_ERR_EXISTS
;
310 _hdb_store(krb5_context context
, HDB
*db
, unsigned flags
, hdb_entry_ex
*entry
)
312 krb5_data key
, value
;
315 /* check if new aliases already is used */
316 code
= hdb_check_aliases(context
, db
, entry
);
320 if(entry
->entry
.generation
== NULL
) {
322 entry
->entry
.generation
= malloc(sizeof(*entry
->entry
.generation
));
323 if(entry
->entry
.generation
== NULL
) {
324 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
327 gettimeofday(&t
, NULL
);
328 entry
->entry
.generation
->time
= t
.tv_sec
;
329 entry
->entry
.generation
->usec
= t
.tv_usec
;
330 entry
->entry
.generation
->gen
= 0;
332 entry
->entry
.generation
->gen
++;
334 code
= hdb_seal_keys(context
, db
, &entry
->entry
);
338 hdb_principal2key(context
, entry
->entry
.principal
, &key
);
341 code
= hdb_remove_aliases(context
, db
, &key
);
343 krb5_data_free(&key
);
346 hdb_entry2value(context
, &entry
->entry
, &value
);
347 code
= db
->hdb__put(context
, db
, flags
& HDB_F_REPLACE
, key
, value
);
348 krb5_data_free(&value
);
349 krb5_data_free(&key
);
353 code
= hdb_add_aliases(context
, db
, flags
, entry
);
359 _hdb_remove(krb5_context context
, HDB
*db
, krb5_const_principal principal
)
364 hdb_principal2key(context
, principal
, &key
);
366 code
= hdb_remove_aliases(context
, db
, &key
);
368 krb5_data_free(&key
);
371 code
= db
->hdb__del(context
, db
, key
);
372 krb5_data_free(&key
);