xref: /freebsd/crypto/heimdal/lib/hdb/hdb-keytab.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
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