2 * Copyright (c) 2004 - 2005 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 RCSID("$Id: ext.c,v 1.1 2005/08/11 20:49:31 lha Exp $");
40 hdb_entry_check_mandatory(krb5_context context
, const hdb_entry
*ent
)
44 if (ent
->extensions
== NULL
)
48 * check for unknown extensions and if they where tagged mandatory
51 for (i
= 0; i
< ent
->extensions
->len
; i
++) {
52 if (ent
->extensions
->val
[i
].data
.element
!=
53 choice_HDB_extension_data_asn1_ellipsis
)
55 if (ent
->extensions
->val
[i
].mandatory
) {
56 krb5_set_error_string(context
, "Principal have unknown "
57 "mandatory extension");
58 return HDB_ERR_MANDATORY_OPTION
;
65 hdb_find_extension(const hdb_entry
*entry
, int type
)
69 if (entry
->extensions
== NULL
)
72 for (i
= 0; i
< entry
->extensions
->len
; i
++)
73 if (entry
->extensions
->val
[i
].data
.element
== type
)
74 return &entry
->extensions
->val
[i
];
79 * Replace the extension `ext' in `entry'. Make a copy of the
80 * extension, so the caller must still free `ext' on both success and
81 * failure. Returns 0 or error code.
85 hdb_replace_extension(krb5_context context
,
87 const HDB_extension
*ext
)
95 if (entry
->extensions
== NULL
) {
96 entry
->extensions
= calloc(1, sizeof(*entry
->extensions
));
97 if (entry
->extensions
== NULL
) {
98 krb5_set_error_string(context
, "malloc: out of memory");
101 } else if (ext
->data
.element
!= choice_HDB_extension_data_asn1_ellipsis
) {
102 ext2
= hdb_find_extension(entry
, ext
->data
.element
);
105 * This is an unknown extention, and we are asked to replace a
106 * possible entry in `entry' that is of the same type. This
107 * might seem impossible, but ASN.1 CHOICE comes to our
108 * rescue. The first tag in each branch in the CHOICE is
109 * unique, so just find the element in the list that have the
110 * same tag was we are putting into the list.
112 Der_class replace_class
, list_class
;
113 Der_type replace_type
, list_type
;
114 unsigned int replace_tag
, list_tag
;
118 ret
= der_get_tag(ext
->data
.u
.asn1_ellipsis
.data
,
119 ext
->data
.u
.asn1_ellipsis
.length
,
120 &replace_class
, &replace_type
, &replace_tag
,
123 krb5_set_error_string(context
, "hdb: failed to decode "
124 "replacement hdb extention");
128 for (i
= 0; i
< entry
->extensions
->len
; i
++) {
129 HDB_extension
*ext3
= &entry
->extensions
->val
[i
];
131 if (ext3
->data
.element
!= choice_HDB_extension_data_asn1_ellipsis
)
134 ret
= der_get_tag(ext3
->data
.u
.asn1_ellipsis
.data
,
135 ext3
->data
.u
.asn1_ellipsis
.length
,
136 &list_class
, &list_type
, &list_tag
,
139 krb5_set_error_string(context
, "hdb: failed to decode "
140 "present hdb extention");
144 if (MAKE_TAG(replace_class
,replace_type
,replace_type
) ==
145 MAKE_TAG(list_class
,list_type
,list_type
)) {
153 free_HDB_extension(ext2
);
154 ret
= copy_HDB_extension(ext
, ext2
);
156 krb5_set_error_string(context
, "hdb: failed to copy replacement "
161 es
= realloc(entry
->extensions
->val
,
162 (entry
->extensions
->len
+1)*sizeof(entry
->extensions
->val
[0]));
164 krb5_set_error_string(context
, "malloc: out of memory");
167 entry
->extensions
->val
= es
;
169 ret
= copy_HDB_extension(ext
,
170 &entry
->extensions
->val
[entry
->extensions
->len
]);
172 entry
->extensions
->len
++;
173 krb5_set_error_string(context
, "hdb: failed to copy new extension");
180 hdb_clear_extension(krb5_context context
,
186 if (entry
->extensions
== NULL
)
189 for (i
= 0; i
< entry
->extensions
->len
; i
++) {
190 if (entry
->extensions
->val
[i
].data
.element
== type
) {
191 free_HDB_extension(&entry
->extensions
->val
[i
]);
192 memmove(&entry
->extensions
->val
[i
],
193 &entry
->extensions
->val
[i
+ 1],
194 sizeof(entry
->extensions
->val
[i
]) * (entry
->extensions
->len
- i
- 1));
195 entry
->extensions
->len
--;
198 if (entry
->extensions
->len
== 0) {
199 free(entry
->extensions
->val
);
200 free(entry
->extensions
);
201 entry
->extensions
= NULL
;
209 hdb_entry_get_pkinit_acl(const hdb_entry
*entry
, const HDB_Ext_PKINIT_acl
**a
)
211 const HDB_extension
*ext
;
213 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_pkinit_acl
);
215 *a
= &ext
->data
.u
.pkinit_acl
;
223 hdb_entry_get_pw_change_time(const hdb_entry
*entry
, time_t *t
)
225 const HDB_extension
*ext
;
227 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_last_pw_change
);
229 *t
= ext
->data
.u
.last_pw_change
;
237 hdb_entry_set_pw_change_time(krb5_context context
,
243 ext
.mandatory
= FALSE
;
244 ext
.data
.element
= choice_HDB_extension_data_last_pw_change
;
247 ext
.data
.u
.last_pw_change
= t
;
249 return hdb_replace_extension(context
, entry
, &ext
);
253 hdb_entry_get_password(krb5_context context
, HDB
*db
,
254 const hdb_entry
*entry
, char **p
)
259 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_password
);
261 heim_utf8_string str
;
262 heim_octet_string pw
;
264 if (db
->hdb_master_key_set
&& ext
->data
.u
.password
.mkvno
) {
267 key
= _hdb_find_master_key(ext
->data
.u
.password
.mkvno
,
271 krb5_set_error_string(context
, "master key %d missing",
272 *ext
->data
.u
.password
.mkvno
);
273 return HDB_ERR_NO_MKEY
;
276 ret
= _hdb_mkey_decrypt(context
, key
, HDB_KU_MKEY
,
277 ext
->data
.u
.password
.password
.data
,
278 ext
->data
.u
.password
.password
.length
,
281 ret
= copy_octet_string(&ext
->data
.u
.password
.password
, &pw
);
284 krb5_clear_error_string(context
);
289 if (str
[pw
.length
- 1] != '\0') {
290 krb5_set_error_string(context
, "password malformated");
296 free_octet_string(&pw
);
298 krb5_set_error_string(context
, "malloc: out of memory");
303 krb5_set_error_string(context
, "password attribute not found");
308 hdb_entry_set_password(krb5_context context
, HDB
*db
,
309 hdb_entry
*entry
, const char *p
)
315 ext
.mandatory
= FALSE
;
316 ext
.data
.element
= choice_HDB_extension_data_password
;
318 if (db
->hdb_master_key_set
) {
320 key
= _hdb_find_master_key(NULL
, db
->hdb_master_key
);
322 krb5_set_error_string(context
, "hdb_entry_set_password: "
323 "failed to find masterkey");
324 return HDB_ERR_NO_MKEY
;
327 ret
= _hdb_mkey_encrypt(context
, key
, HDB_KU_MKEY
,
329 &ext
.data
.u
.password
.password
);
333 ext
.data
.u
.password
.mkvno
=
334 malloc(sizeof(*ext
.data
.u
.password
.mkvno
));
335 if (ext
.data
.u
.password
.mkvno
== NULL
) {
336 free_HDB_extension(&ext
);
337 krb5_set_error_string(context
, "malloc: out of memory");
340 *ext
.data
.u
.password
.mkvno
= _hdb_mkey_version(key
);
343 ext
.data
.u
.password
.mkvno
= NULL
;
345 ret
= krb5_data_copy(&ext
.data
.u
.password
.password
,
348 krb5_set_error_string(context
, "malloc: out of memory");
349 free_HDB_extension(&ext
);
354 ret
= hdb_replace_extension(context
, entry
, &ext
);
356 free_HDB_extension(&ext
);
362 hdb_entry_clear_password(krb5_context context
, hdb_entry
*entry
)
364 return hdb_clear_extension(context
, entry
,
365 choice_HDB_extension_data_password
);