2 * Copyright (c) 1999 - 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
36 /* keytab backend for HDB databases */
44 * the format for HDB keytabs is:
45 * HDB:[database:file:mkey]
48 static krb5_error_code
49 hdb_resolve(krb5_context context
, const char *name
, krb5_keytab id
)
52 const char *db
, *mkey
;
54 d
= malloc(sizeof(*d
));
56 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
60 mkey
= strchr(name
, ':');
61 if(mkey
== NULL
|| mkey
[1] == '\0') {
65 d
->dbname
= strdup(name
);
66 if(d
->dbname
== NULL
) {
68 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
74 if((mkey
- db
) == 0) {
77 d
->dbname
= malloc(mkey
- db
+ 1);
78 if(d
->dbname
== NULL
) {
80 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
83 memmove(d
->dbname
, db
, mkey
- db
);
84 d
->dbname
[mkey
- db
] = '\0';
86 d
->mkey
= strdup(mkey
+ 1);
90 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
98 static krb5_error_code
99 hdb_close(krb5_context context
, krb5_keytab id
)
101 struct hdb_data
*d
= id
->data
;
109 static krb5_error_code
110 hdb_get_name(krb5_context context
,
115 struct hdb_data
*d
= id
->data
;
117 snprintf(name
, namesize
, "%s%s%s",
118 d
->dbname
? d
->dbname
: "",
119 (d
->dbname
|| d
->mkey
) ? ":" : "",
120 d
->mkey
? d
->mkey
: "");
125 set_config (krb5_context context
,
126 const krb5_config_binding
*binding
,
130 *dbname
= krb5_config_get_string(context
, binding
, "dbname", NULL
);
131 *mkey
= krb5_config_get_string(context
, binding
, "mkey_file", NULL
);
135 * try to figure out the database (`dbname') and master-key (`mkey')
136 * that should be used for `principal'.
140 find_db (krb5_context context
,
143 krb5_const_principal principal
)
145 const krb5_config_binding
*top_bind
= NULL
;
146 const krb5_config_binding
*default_binding
= NULL
;
147 const krb5_config_binding
*db
;
148 krb5_const_realm realm
= krb5_principal_get_realm(context
, principal
);
150 *dbname
= *mkey
= NULL
;
153 krb5_config_get_next(context
,
162 p
= krb5_config_get_string (context
, db
, "realm", NULL
);
164 if(default_binding
) {
165 krb5_warnx(context
, "WARNING: more than one realm-less "
166 "database specification");
167 krb5_warnx(context
, "WARNING: using the first encountered");
169 default_binding
= db
;
170 } else if (strcmp (realm
, p
) == 0) {
171 set_config (context
, db
, dbname
, mkey
);
175 if (*dbname
== NULL
&& default_binding
!= NULL
)
176 set_config (context
, default_binding
, dbname
, mkey
);
178 *dbname
= HDB_DEFAULT_DB
;
182 * find the keytab entry in `id' for `principal, kvno, enctype' and return
183 * it in `entry'. return 0 or an error code
186 static krb5_error_code
187 hdb_get_entry(krb5_context context
,
189 krb5_const_principal principal
,
191 krb5_enctype enctype
,
192 krb5_keytab_entry
*entry
)
196 struct hdb_data
*d
= id
->data
;
199 const char *dbname
= d
->dbname
;
200 const char *mkey
= d
->mkey
;
202 memset(&ent
, 0, sizeof(ent
));
205 find_db (context
, &dbname
, &mkey
, principal
);
207 ret
= hdb_create (context
, &db
, dbname
);
210 ret
= hdb_set_master_keyfile (context
, db
, mkey
);
212 (*db
->hdb_destroy
)(context
, db
);
216 ret
= (*db
->hdb_open
)(context
, db
, O_RDONLY
, 0);
218 (*db
->hdb_destroy
)(context
, db
);
221 ret
= (*db
->hdb_fetch
)(context
, db
, principal
,
223 HDB_F_GET_CLIENT
|HDB_F_GET_SERVER
|HDB_F_GET_KRBTGT
,
226 if(ret
== HDB_ERR_NOENTRY
) {
227 ret
= KRB5_KT_NOTFOUND
;
232 if(kvno
&& ent
.entry
.kvno
!= kvno
) {
233 hdb_free_entry(context
, &ent
);
234 ret
= KRB5_KT_NOTFOUND
;
238 if(ent
.entry
.keys
.len
> 0)
239 enctype
= ent
.entry
.keys
.val
[0].key
.keytype
;
240 ret
= KRB5_KT_NOTFOUND
;
241 for(i
= 0; i
< ent
.entry
.keys
.len
; i
++) {
242 if(ent
.entry
.keys
.val
[i
].key
.keytype
== enctype
) {
243 krb5_copy_principal(context
, principal
, &entry
->principal
);
244 entry
->vno
= ent
.entry
.kvno
;
245 krb5_copy_keyblock_contents(context
,
246 &ent
.entry
.keys
.val
[i
].key
,
252 hdb_free_entry(context
, &ent
);
254 (*db
->hdb_close
)(context
, db
);
255 (*db
->hdb_destroy
)(context
, db
);
259 krb5_kt_ops hdb_kt_ops
= {
266 NULL
, /* start_seq_get */
267 NULL
, /* next_entry */
268 NULL
, /* end_seq_get */