1/*	$NetBSD$	*/
2
3/*
4 * Copyright (c) 2009 Kungliga Tekniska H�gskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 *
21 * 3. Neither the name of the Institute nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#include "hdb_locl.h"
39#include <assert.h>
40
41typedef struct {
42    char *path;
43    krb5_keytab keytab;
44} *hdb_keytab;
45
46/*
47 *
48 */
49
50static krb5_error_code
51hkt_close(krb5_context context, HDB *db)
52{
53    hdb_keytab k = (hdb_keytab)db->hdb_db;
54    krb5_error_code ret;
55
56    assert(k->keytab);
57
58    ret = krb5_kt_close(context, k->keytab);
59    k->keytab = NULL;
60
61    return ret;
62}
63
64static krb5_error_code
65hkt_destroy(krb5_context context, HDB *db)
66{
67    hdb_keytab k = (hdb_keytab)db->hdb_db;
68    krb5_error_code ret;
69
70    ret = hdb_clear_master_key (context, db);
71
72    free(k->path);
73    free(k);
74
75    free(db->hdb_name);
76    free(db);
77    return ret;
78}
79
80static krb5_error_code
81hkt_lock(krb5_context context, HDB *db, int operation)
82{
83    return 0;
84}
85
86static krb5_error_code
87hkt_unlock(krb5_context context, HDB *db)
88{
89    return 0;
90}
91
92static krb5_error_code
93hkt_firstkey(krb5_context context, HDB *db,
94	     unsigned flags, hdb_entry_ex *entry)
95{
96    return HDB_ERR_DB_INUSE;
97}
98
99static krb5_error_code
100hkt_nextkey(krb5_context context, HDB * db, unsigned flags,
101	     hdb_entry_ex * entry)
102{
103    return HDB_ERR_DB_INUSE;
104}
105
106static krb5_error_code
107hkt_open(krb5_context context, HDB * db, int flags, mode_t mode)
108{
109    hdb_keytab k = (hdb_keytab)db->hdb_db;
110    krb5_error_code ret;
111
112    assert(k->keytab == NULL);
113
114    ret = krb5_kt_resolve(context, k->path, &k->keytab);
115    if (ret)
116	return ret;
117
118    return 0;
119}
120
121static krb5_error_code
122hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
123	       unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry)
124{
125    hdb_keytab k = (hdb_keytab)db->hdb_db;
126    krb5_error_code ret;
127    krb5_keytab_entry ktentry;
128
129    if (!(flags & HDB_F_KVNO_SPECIFIED)) {
130	    /* Preserve previous behaviour if no kvno specified */
131	    kvno = 0;
132    }
133
134    memset(&ktentry, 0, sizeof(ktentry));
135
136    entry->entry.flags.server = 1;
137    entry->entry.flags.forwardable = 1;
138    entry->entry.flags.renewable = 1;
139
140    /* Not recorded in the OD backend, make something up */
141    ret = krb5_parse_name(context, "hdb/keytab@WELL-KNOWN:KEYTAB-BACKEND",
142			  &entry->entry.created_by.principal);
143    if (ret)
144	goto out;
145
146    /*
147     * XXX really needs to try all enctypes and just not pick the
148     * first one, even if that happens to be des3-cbc-sha1 (ie best
149     * enctype) in the Apple case. A while loop over all known
150     * enctypes should work.
151     */
152
153    ret = krb5_kt_get_entry(context, k->keytab, principal, kvno, 0, &ktentry);
154    if (ret) {
155	ret = HDB_ERR_NOENTRY;
156	goto out;
157    }
158
159    ret = krb5_copy_principal(context, principal, &entry->entry.principal);
160    if (ret)
161	goto out;
162
163    ret = _hdb_keytab2hdb_entry(context, &ktentry, entry);
164
165 out:
166    if (ret) {
167	free_hdb_entry(&entry->entry);
168	memset(&entry->entry, 0, sizeof(entry->entry));
169    }
170    krb5_kt_free_entry(context, &ktentry);
171
172    return ret;
173}
174
175static krb5_error_code
176hkt_store(krb5_context context, HDB * db, unsigned flags,
177	  hdb_entry_ex * entry)
178{
179    return HDB_ERR_DB_INUSE;
180}
181
182
183krb5_error_code
184hdb_keytab_create(krb5_context context, HDB ** db, const char *arg)
185{
186    hdb_keytab k;
187
188    *db = calloc(1, sizeof(**db));
189    if (*db == NULL) {
190	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
191	return ENOMEM;
192    }
193    memset(*db, 0, sizeof(**db));
194
195    k = calloc(1, sizeof(*k));
196    if (k == NULL) {
197	free(*db);
198	*db = NULL;
199	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
200	return ENOMEM;
201    }
202
203    k->path = strdup(arg);
204    if (k->path == NULL) {
205	free(k);
206	free(*db);
207	*db = NULL;
208	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
209	return ENOMEM;
210    }
211
212
213    (*db)->hdb_db = k;
214
215    (*db)->hdb_master_key_set = 0;
216    (*db)->hdb_openp = 0;
217    (*db)->hdb_open = hkt_open;
218    (*db)->hdb_close = hkt_close;
219    (*db)->hdb_fetch_kvno = hkt_fetch_kvno;
220    (*db)->hdb_store = hkt_store;
221    (*db)->hdb_remove = NULL;
222    (*db)->hdb_firstkey = hkt_firstkey;
223    (*db)->hdb_nextkey = hkt_nextkey;
224    (*db)->hdb_lock = hkt_lock;
225    (*db)->hdb_unlock = hkt_unlock;
226    (*db)->hdb_rename = NULL;
227    (*db)->hdb__get = NULL;
228    (*db)->hdb__put = NULL;
229    (*db)->hdb__del = NULL;
230    (*db)->hdb_destroy = hkt_destroy;
231
232    return 0;
233}
234