1 /* $NetBSD: ext.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $ */
4 * Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
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_message(context
, HDB_ERR_MANDATORY_OPTION
,
57 "Principal have unknown "
58 "mandatory extension");
59 return HDB_ERR_MANDATORY_OPTION
;
66 hdb_find_extension(const hdb_entry
*entry
, int type
)
70 if (entry
->extensions
== NULL
)
73 for (i
= 0; i
< entry
->extensions
->len
; i
++)
74 if (entry
->extensions
->val
[i
].data
.element
== (unsigned)type
)
75 return &entry
->extensions
->val
[i
];
80 * Replace the extension `ext' in `entry'. Make a copy of the
81 * extension, so the caller must still free `ext' on both success and
82 * failure. Returns 0 or error code.
86 hdb_replace_extension(krb5_context context
,
88 const HDB_extension
*ext
)
96 if (entry
->extensions
== NULL
) {
97 entry
->extensions
= calloc(1, sizeof(*entry
->extensions
));
98 if (entry
->extensions
== NULL
) {
99 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
102 } else if (ext
->data
.element
!= choice_HDB_extension_data_asn1_ellipsis
) {
103 ext2
= hdb_find_extension(entry
, ext
->data
.element
);
106 * This is an unknown extention, and we are asked to replace a
107 * possible entry in `entry' that is of the same type. This
108 * might seem impossible, but ASN.1 CHOICE comes to our
109 * rescue. The first tag in each branch in the CHOICE is
110 * unique, so just find the element in the list that have the
111 * same tag was we are putting into the list.
113 Der_class replace_class
, list_class
;
114 Der_type replace_type
, list_type
;
115 unsigned int replace_tag
, list_tag
;
119 ret
= der_get_tag(ext
->data
.u
.asn1_ellipsis
.data
,
120 ext
->data
.u
.asn1_ellipsis
.length
,
121 &replace_class
, &replace_type
, &replace_tag
,
124 krb5_set_error_message(context
, ret
, "hdb: failed to decode "
125 "replacement hdb extention");
129 for (i
= 0; i
< entry
->extensions
->len
; i
++) {
130 HDB_extension
*ext3
= &entry
->extensions
->val
[i
];
132 if (ext3
->data
.element
!= choice_HDB_extension_data_asn1_ellipsis
)
135 ret
= der_get_tag(ext3
->data
.u
.asn1_ellipsis
.data
,
136 ext3
->data
.u
.asn1_ellipsis
.length
,
137 &list_class
, &list_type
, &list_tag
,
140 krb5_set_error_message(context
, ret
, "hdb: failed to decode "
141 "present hdb extention");
145 if (MAKE_TAG(replace_class
,replace_type
,replace_type
) ==
146 MAKE_TAG(list_class
,list_type
,list_type
)) {
154 free_HDB_extension(ext2
);
155 ret
= copy_HDB_extension(ext
, ext2
);
157 krb5_set_error_message(context
, ret
, "hdb: failed to copy replacement "
162 es
= realloc(entry
->extensions
->val
,
163 (entry
->extensions
->len
+1)*sizeof(entry
->extensions
->val
[0]));
165 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
168 entry
->extensions
->val
= es
;
170 ret
= copy_HDB_extension(ext
,
171 &entry
->extensions
->val
[entry
->extensions
->len
]);
173 entry
->extensions
->len
++;
175 krb5_set_error_message(context
, ret
, "hdb: failed to copy new extension");
181 hdb_clear_extension(krb5_context context
,
187 if (entry
->extensions
== NULL
)
190 for (i
= 0; i
< entry
->extensions
->len
; i
++) {
191 if (entry
->extensions
->val
[i
].data
.element
== (unsigned)type
) {
192 free_HDB_extension(&entry
->extensions
->val
[i
]);
193 memmove(&entry
->extensions
->val
[i
],
194 &entry
->extensions
->val
[i
+ 1],
195 sizeof(entry
->extensions
->val
[i
]) * (entry
->extensions
->len
- i
- 1));
196 entry
->extensions
->len
--;
199 if (entry
->extensions
->len
== 0) {
200 free(entry
->extensions
->val
);
201 free(entry
->extensions
);
202 entry
->extensions
= NULL
;
210 hdb_entry_get_pkinit_acl(const hdb_entry
*entry
, const HDB_Ext_PKINIT_acl
**a
)
212 const HDB_extension
*ext
;
214 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_pkinit_acl
);
216 *a
= &ext
->data
.u
.pkinit_acl
;
224 hdb_entry_get_pkinit_hash(const hdb_entry
*entry
, const HDB_Ext_PKINIT_hash
**a
)
226 const HDB_extension
*ext
;
228 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_pkinit_cert_hash
);
230 *a
= &ext
->data
.u
.pkinit_cert_hash
;
238 hdb_entry_get_pkinit_cert(const hdb_entry
*entry
, const HDB_Ext_PKINIT_cert
**a
)
240 const HDB_extension
*ext
;
242 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_pkinit_cert
);
244 *a
= &ext
->data
.u
.pkinit_cert
;
252 hdb_entry_get_pw_change_time(const hdb_entry
*entry
, time_t *t
)
254 const HDB_extension
*ext
;
256 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_last_pw_change
);
258 *t
= ext
->data
.u
.last_pw_change
;
266 hdb_entry_set_pw_change_time(krb5_context context
,
272 ext
.mandatory
= FALSE
;
273 ext
.data
.element
= choice_HDB_extension_data_last_pw_change
;
276 ext
.data
.u
.last_pw_change
= t
;
278 return hdb_replace_extension(context
, entry
, &ext
);
282 hdb_entry_get_password(krb5_context context
, HDB
*db
,
283 const hdb_entry
*entry
, char **p
)
289 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_password
);
291 heim_utf8_string xstr
;
292 heim_octet_string pw
;
294 if (db
->hdb_master_key_set
&& ext
->data
.u
.password
.mkvno
) {
297 key
= _hdb_find_master_key(ext
->data
.u
.password
.mkvno
,
301 krb5_set_error_message(context
, HDB_ERR_NO_MKEY
,
302 "master key %d missing",
303 *ext
->data
.u
.password
.mkvno
);
304 return HDB_ERR_NO_MKEY
;
307 ret
= _hdb_mkey_decrypt(context
, key
, HDB_KU_MKEY
,
308 ext
->data
.u
.password
.password
.data
,
309 ext
->data
.u
.password
.password
.length
,
312 ret
= der_copy_octet_string(&ext
->data
.u
.password
.password
, &pw
);
315 krb5_clear_error_message(context
);
320 if (xstr
[pw
.length
- 1] != '\0') {
321 krb5_set_error_message(context
, EINVAL
, "malformed password");
327 der_free_octet_string(&pw
);
329 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
335 ret
= krb5_unparse_name(context
, entry
->principal
, &str
);
337 krb5_set_error_message(context
, ENOENT
,
338 "no password attribute for %s", str
);
341 krb5_clear_error_message(context
);
347 hdb_entry_set_password(krb5_context context
, HDB
*db
,
348 hdb_entry
*entry
, const char *p
)
354 ext
.mandatory
= FALSE
;
355 ext
.data
.element
= choice_HDB_extension_data_password
;
357 if (db
->hdb_master_key_set
) {
359 key
= _hdb_find_master_key(NULL
, db
->hdb_master_key
);
361 krb5_set_error_message(context
, HDB_ERR_NO_MKEY
,
362 "hdb_entry_set_password: "
363 "failed to find masterkey");
364 return HDB_ERR_NO_MKEY
;
367 ret
= _hdb_mkey_encrypt(context
, key
, HDB_KU_MKEY
,
369 &ext
.data
.u
.password
.password
);
373 ext
.data
.u
.password
.mkvno
=
374 malloc(sizeof(*ext
.data
.u
.password
.mkvno
));
375 if (ext
.data
.u
.password
.mkvno
== NULL
) {
376 free_HDB_extension(&ext
);
377 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
380 *ext
.data
.u
.password
.mkvno
= _hdb_mkey_version(key
);
383 ext
.data
.u
.password
.mkvno
= NULL
;
385 ret
= krb5_data_copy(&ext
.data
.u
.password
.password
,
388 krb5_set_error_message(context
, ret
, "malloc: out of memory");
389 free_HDB_extension(&ext
);
394 ret
= hdb_replace_extension(context
, entry
, &ext
);
396 free_HDB_extension(&ext
);
402 hdb_entry_clear_password(krb5_context context
, hdb_entry
*entry
)
404 return hdb_clear_extension(context
, entry
,
405 choice_HDB_extension_data_password
);
409 hdb_entry_get_ConstrainedDelegACL(const hdb_entry
*entry
,
410 const HDB_Ext_Constrained_delegation_acl
**a
)
412 const HDB_extension
*ext
;
414 ext
= hdb_find_extension(entry
,
415 choice_HDB_extension_data_allowed_to_delegate_to
);
417 *a
= &ext
->data
.u
.allowed_to_delegate_to
;
425 hdb_entry_get_aliases(const hdb_entry
*entry
, const HDB_Ext_Aliases
**a
)
427 const HDB_extension
*ext
;
429 ext
= hdb_find_extension(entry
, choice_HDB_extension_data_aliases
);
431 *a
= &ext
->data
.u
.aliases
;