keytab.c revision 55682
1/*
2 * Copyright (c) 1999 Kungliga Tekniska H�gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
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.
16 *
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.
20 *
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
31 * SUCH DAMAGE.
32 */
33
34#include "hdb_locl.h"
35
36/* keytab backend for HDB databases */
37
38RCSID("$Id: keytab.c,v 1.2 1999/08/26 13:24:05 joda Exp $");
39
40struct hdb_data {
41    char *dbname;
42    char *mkey;
43    HDB *db;
44};
45
46static krb5_error_code
47hdb_resolve(krb5_context context, const char *name, krb5_keytab id)
48{
49    krb5_error_code ret;
50    struct hdb_data *d;
51    const char *db, *mkey;
52    d = malloc(sizeof(*d));
53    if(d == NULL)
54	return ENOMEM;
55    db = name;
56    mkey = strchr(name, ':');
57    if(mkey == NULL || mkey[1] == '\0') {
58	if(*name == '\0')
59	    d->dbname = NULL;
60	else {
61	    d->dbname = strdup(name);
62	    if(d->dbname == NULL) {
63		free(d);
64		return ENOMEM;
65	    }
66	}
67	d->mkey = NULL;
68    } else {
69	if((mkey - db) == 0) {
70	    d->dbname = NULL;
71	} else {
72	    d->dbname = malloc(mkey - db);
73	    if(d->dbname == NULL) {
74		free(d);
75		return ENOMEM;
76	    }
77	    strncpy(d->dbname, db, mkey - db);
78	    d->dbname[mkey - db] = '\0';
79	}
80	d->mkey = strdup(mkey + 1);
81	if(d->mkey == NULL) {
82	    free(d->dbname);
83	    free(d);
84	    return ENOMEM;
85	}
86    }
87    ret = hdb_create(context, &d->db, d->dbname);
88    if(ret) {
89	free(d->dbname);
90	free(d->mkey);
91	free(d);
92	return ret;
93    }
94    ret = hdb_set_master_keyfile (context, d->db, d->mkey);
95    if(ret) {
96	(*d->db->destroy)(context, d->db);
97	free(d->dbname);
98	free(d->mkey);
99	free(d);
100	return ret;
101    }
102    id->data = d;
103    return 0;
104}
105
106static krb5_error_code
107hdb_close(krb5_context context, krb5_keytab id)
108{
109    struct hdb_data *d = id->data;
110    (*d->db->destroy)(context, d->db);
111    free(d);
112    return 0;
113}
114
115static krb5_error_code
116hdb_get_name(krb5_context context,
117	     krb5_keytab id,
118	     char *name,
119	     size_t namesize)
120{
121    struct hdb_data *d = id->data;
122    snprintf(name, namesize, "%s%s%s",
123	     d->dbname ? d->dbname : "",
124	     (d->dbname || d->mkey) ? ":" : "",
125	     d->mkey ? d->mkey : "");
126    return 0;
127}
128
129static krb5_error_code
130hdb_get_entry(krb5_context context,
131	      krb5_keytab id,
132	      krb5_const_principal principal,
133	      krb5_kvno kvno,
134	      krb5_enctype enctype,
135	      krb5_keytab_entry *entry)
136{
137    hdb_entry ent;
138    krb5_error_code ret;
139    struct hdb_data *d = id->data;
140    int i;
141
142    ret = (*d->db->open)(context, d->db, O_RDONLY, 0);
143    if (ret)
144	return ret;
145    ent.principal = (krb5_principal)principal;
146    ret = (*d->db->fetch)(context, d->db, HDB_F_DECRYPT, &ent);
147    (*d->db->close)(context, d->db);
148    if(ret == HDB_ERR_NOENTRY)
149	return KRB5_KT_NOTFOUND;
150    else if(ret)
151	return ret;
152    if(kvno && ent.kvno != kvno) {
153	hdb_free_entry(context, &ent);
154 	return KRB5_KT_NOTFOUND;
155    }
156    if(enctype == 0)
157	if(ent.keys.len > 0)
158	    enctype = ent.keys.val[0].key.keytype;
159    ret = KRB5_KT_NOTFOUND;
160    for(i = 0; i < ent.keys.len; i++) {
161	if(ent.keys.val[i].key.keytype == enctype) {
162	    krb5_copy_principal(context, principal, &entry->principal);
163	    entry->vno = ent.kvno;
164	    krb5_copy_keyblock_contents(context,
165					&ent.keys.val[i].key,
166					&entry->keyblock);
167	    ret = 0;
168	    break;
169	}
170    }
171    hdb_free_entry(context, &ent);
172    return ret;
173}
174
175krb5_kt_ops hdb_kt_ops = {
176    "HDB",
177    hdb_resolve,
178    hdb_get_name,
179    hdb_close,
180    hdb_get_entry,
181    NULL,		/* start_seq_get */
182    NULL,		/* next_entry */
183    NULL,		/* end_seq_get */
184    NULL,		/* add */
185    NULL		/* remove */
186};
187
188