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