1 /* $NetBSD: keytab.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $ */
4 * Copyright (c) 1999 - 2002 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
38 /* keytab backend for HDB databases */
47 hdb_entry_ex hdb_entry
;
53 * the format for HDB keytabs is:
54 * HDB:[HDBFORMAT:database-specific-data[:mkey=mkey-file]]
57 static krb5_error_code KRB5_CALLCONV
58 hdb_resolve(krb5_context context
, const char *name
, krb5_keytab id
)
61 const char *db
, *mkey
;
63 d
= malloc(sizeof(*d
));
65 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
69 mkey
= strstr(name
, ":mkey=");
70 if(mkey
== NULL
|| mkey
[5] == '\0') {
74 d
->dbname
= strdup(name
);
75 if(d
->dbname
== NULL
) {
77 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
83 d
->dbname
= malloc(mkey
- db
+ 1);
84 if(d
->dbname
== NULL
) {
86 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
89 memmove(d
->dbname
, db
, mkey
- db
);
90 d
->dbname
[mkey
- db
] = '\0';
92 d
->mkey
= strdup(mkey
+ 5);
96 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
104 static krb5_error_code KRB5_CALLCONV
105 hdb_close(krb5_context context
, krb5_keytab id
)
107 struct hdb_data
*d
= id
->data
;
115 static krb5_error_code KRB5_CALLCONV
116 hdb_get_name(krb5_context context
,
121 struct hdb_data
*d
= id
->data
;
123 snprintf(name
, namesize
, "%s%s%s",
124 d
->dbname
? d
->dbname
: "",
125 (d
->dbname
|| d
->mkey
) ? ":" : "",
126 d
->mkey
? d
->mkey
: "");
131 * try to figure out the database (`dbname') and master-key (`mkey')
132 * that should be used for `principal'.
135 static krb5_error_code
136 find_db (krb5_context context
,
139 krb5_const_principal principal
)
141 krb5_const_realm realm
= krb5_principal_get_realm(context
, principal
);
143 struct hdb_dbinfo
*head
, *dbinfo
= NULL
;
145 *dbname
= *mkey
= NULL
;
147 ret
= hdb_get_dbinfo(context
, &head
);
151 while ((dbinfo
= hdb_dbinfo_get_next(head
, dbinfo
)) != NULL
) {
152 const char *p
= hdb_dbinfo_get_realm(context
, dbinfo
);
153 if (p
&& strcmp (realm
, p
) == 0) {
154 p
= hdb_dbinfo_get_dbname(context
, dbinfo
);
157 p
= hdb_dbinfo_get_mkey_file(context
, dbinfo
);
163 hdb_free_dbinfo(context
, &head
);
165 *dbname
= strdup(HDB_DEFAULT_DB
);
170 * find the keytab entry in `id' for `principal, kvno, enctype' and return
171 * it in `entry'. return 0 or an error code
174 static krb5_error_code KRB5_CALLCONV
175 hdb_get_entry(krb5_context context
,
177 krb5_const_principal principal
,
179 krb5_enctype enctype
,
180 krb5_keytab_entry
*entry
)
184 struct hdb_data
*d
= id
->data
;
185 const char *dbname
= d
->dbname
;
186 const char *mkey
= d
->mkey
;
187 char *fdbname
= NULL
, *fmkey
= NULL
;
191 memset(&ent
, 0, sizeof(ent
));
193 if (dbname
== NULL
) {
194 ret
= find_db(context
, &fdbname
, &fmkey
, principal
);
201 ret
= hdb_create (context
, &db
, dbname
);
204 ret
= hdb_set_master_keyfile (context
, db
, mkey
);
206 (*db
->hdb_destroy
)(context
, db
);
210 ret
= (*db
->hdb_open
)(context
, db
, O_RDONLY
, 0);
212 (*db
->hdb_destroy
)(context
, db
);
216 ret
= (*db
->hdb_fetch_kvno
)(context
, db
, principal
,
217 HDB_F_DECRYPT
|HDB_F_KVNO_SPECIFIED
|
218 HDB_F_GET_CLIENT
|HDB_F_GET_SERVER
|HDB_F_GET_KRBTGT
,
221 if(ret
== HDB_ERR_NOENTRY
) {
222 ret
= KRB5_KT_NOTFOUND
;
227 if(kvno
&& (krb5_kvno
)ent
.entry
.kvno
!= kvno
) {
228 hdb_free_entry(context
, &ent
);
229 ret
= KRB5_KT_NOTFOUND
;
233 if(ent
.entry
.keys
.len
> 0)
234 enctype
= ent
.entry
.keys
.val
[0].key
.keytype
;
235 ret
= KRB5_KT_NOTFOUND
;
236 for(i
= 0; i
< ent
.entry
.keys
.len
; i
++) {
237 if(ent
.entry
.keys
.val
[i
].key
.keytype
== enctype
) {
238 krb5_copy_principal(context
, principal
, &entry
->principal
);
239 entry
->vno
= ent
.entry
.kvno
;
240 krb5_copy_keyblock_contents(context
,
241 &ent
.entry
.keys
.val
[i
].key
,
247 hdb_free_entry(context
, &ent
);
249 (*db
->hdb_close
)(context
, db
);
250 (*db
->hdb_destroy
)(context
, db
);
258 * find the keytab entry in `id' for `principal, kvno, enctype' and return
259 * it in `entry'. return 0 or an error code
262 static krb5_error_code KRB5_CALLCONV
263 hdb_start_seq_get(krb5_context context
,
265 krb5_kt_cursor
*cursor
)
268 struct hdb_cursor
*c
;
269 struct hdb_data
*d
= id
->data
;
270 const char *dbname
= d
->dbname
;
271 const char *mkey
= d
->mkey
;
274 if (dbname
== NULL
) {
276 * We don't support enumerating without being told what
277 * backend to enumerate on
279 ret
= KRB5_KT_NOTFOUND
;
283 ret
= hdb_create (context
, &db
, dbname
);
286 ret
= hdb_set_master_keyfile (context
, db
, mkey
);
288 (*db
->hdb_destroy
)(context
, db
);
292 ret
= (*db
->hdb_open
)(context
, db
, O_RDONLY
, 0);
294 (*db
->hdb_destroy
)(context
, db
);
298 cursor
->data
= c
= malloc (sizeof(*c
));
300 (*db
->hdb_close
)(context
, db
);
301 (*db
->hdb_destroy
)(context
, db
);
302 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
315 static int KRB5_CALLCONV
316 hdb_next_entry(krb5_context context
,
318 krb5_keytab_entry
*entry
,
319 krb5_kt_cursor
*cursor
)
321 struct hdb_cursor
*c
= cursor
->data
;
324 memset(entry
, 0, sizeof(*entry
));
328 ret
= (c
->db
->hdb_firstkey
)(context
, c
->db
,
330 HDB_F_GET_CLIENT
|HDB_F_GET_SERVER
|HDB_F_GET_KRBTGT
,
332 if (ret
== HDB_ERR_NOENTRY
)
337 if (c
->hdb_entry
.entry
.keys
.len
== 0)
338 hdb_free_entry(context
, &c
->hdb_entry
);
344 ret
= (c
->db
->hdb_nextkey
)(context
, c
->db
,
346 HDB_F_GET_CLIENT
|HDB_F_GET_SERVER
|HDB_F_GET_KRBTGT
,
348 if (ret
== HDB_ERR_NOENTRY
)
353 /* If no keys on this entry, try again */
354 if (c
->hdb_entry
.entry
.keys
.len
== 0)
355 hdb_free_entry(context
, &c
->hdb_entry
);
361 * Return next enc type (keytabs are one slot per key, while
362 * hdb is one record per principal.
365 ret
= krb5_copy_principal(context
,
366 c
->hdb_entry
.entry
.principal
,
371 entry
->vno
= c
->hdb_entry
.entry
.kvno
;
372 ret
= krb5_copy_keyblock_contents(context
,
373 &c
->hdb_entry
.entry
.keys
.val
[c
->key_idx
].key
,
376 krb5_free_principal(context
, entry
->principal
);
377 memset(entry
, 0, sizeof(*entry
));
383 * Once we get to the end of the list, signal that we want the
387 if ((size_t)c
->key_idx
== c
->hdb_entry
.entry
.keys
.len
) {
388 hdb_free_entry(context
, &c
->hdb_entry
);
397 static int KRB5_CALLCONV
398 hdb_end_seq_get(krb5_context context
,
400 krb5_kt_cursor
*cursor
)
402 struct hdb_cursor
*c
= cursor
->data
;
405 hdb_free_entry(context
, &c
->hdb_entry
);
407 (c
->db
->hdb_close
)(context
, c
->db
);
408 (c
->db
->hdb_destroy
)(context
, c
->db
);
414 krb5_kt_ops hdb_kt_ops
= {