]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/heimdal/lib/krb5/keytab_krb4.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / crypto / heimdal / lib / krb5 / keytab_krb4.c
1 /*
2  * Copyright (c) 1997, 1998, 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 "krb5_locl.h"
35 #include <krb.h>
36
37 RCSID("$Id: keytab_krb4.c,v 1.5 2000/01/06 08:04:58 assar Exp $");
38
39 struct krb4_kt_data {
40     char *filename;
41 };
42
43 static krb5_error_code
44 krb4_kt_resolve(krb5_context context, const char *name, krb5_keytab id)
45 {
46     struct krb4_kt_data *d;
47
48     d = malloc (sizeof(*d));
49     if (d == NULL)
50         return ENOMEM;
51     d->filename = strdup (name);
52     if (d->filename == NULL) {
53         free(d);
54         return ENOMEM;
55     }
56     id->data = d;
57     return 0;
58 }
59
60 static krb5_error_code
61 krb4_kt_get_name (krb5_context context,
62                   krb5_keytab id,
63                   char *name,
64                   size_t name_sz)
65 {
66     struct krb4_kt_data *d = id->data;
67
68     strlcpy (name, d->filename, name_sz);
69     return 0;
70 }
71
72 static krb5_error_code
73 krb4_kt_close (krb5_context context,
74                krb5_keytab id)
75 {
76     struct krb4_kt_data *d = id->data;
77
78     free (d->filename);
79     free (d);
80     return 0;
81 }
82
83 struct krb4_cursor_extra_data {
84     krb5_keytab_entry entry;
85     int num;
86 };
87
88 static krb5_error_code
89 krb4_kt_start_seq_get_int (krb5_context context,
90                            krb5_keytab id,
91                            int flags,
92                            krb5_kt_cursor *c)
93 {
94     struct krb4_kt_data *d = id->data;
95     struct krb4_cursor_extra_data *ed;
96
97     ed = malloc (sizeof(*ed));
98     if (ed == NULL)
99         return ENOMEM;
100     ed->entry.principal = NULL;
101     ed->num = -1;
102     c->data = ed;
103     c->fd = open (d->filename, flags);
104     if (c->fd < 0) {
105         free (ed);
106         return errno;
107     }
108     c->sp = krb5_storage_from_fd(c->fd);
109     return 0;
110 }
111
112 static krb5_error_code
113 krb4_kt_start_seq_get (krb5_context context,
114                        krb5_keytab id,
115                        krb5_kt_cursor *c)
116 {
117     return krb4_kt_start_seq_get_int (context, id, O_BINARY | O_RDONLY, c);
118 }
119
120 static krb5_error_code
121 read_v4_entry (krb5_context context,
122                struct krb4_kt_data *d,
123                krb5_kt_cursor *c,
124                struct krb4_cursor_extra_data *ed)
125 {
126     krb5_error_code ret;
127     char *service, *instance, *realm;
128     int8_t kvno;
129     des_cblock key;
130
131     ret = krb5_ret_stringz(c->sp, &service);
132     if (ret)
133         return ret;
134     ret = krb5_ret_stringz(c->sp, &instance);
135     if (ret) {
136         free (service);
137         return ret;
138     }
139     ret = krb5_ret_stringz(c->sp, &realm);
140     if (ret) {
141         free (service);
142         free (instance);
143         return ret;
144     }
145     ret = krb5_425_conv_principal (context, service, instance, realm,
146                                    &ed->entry.principal);
147     free (service);
148     free (instance);
149     free (realm);
150     if (ret)
151         return ret;
152     ret = krb5_ret_int8(c->sp, &kvno);
153     if (ret) {
154         krb5_free_principal (context, ed->entry.principal);
155         return ret;
156     }
157     ret = c->sp->fetch(c->sp, key, 8);
158     if (ret < 0) {
159         krb5_free_principal(context, ed->entry.principal);
160         return ret;
161     }
162     if (ret < 8) {
163         krb5_free_principal(context, ed->entry.principal);
164         return EINVAL;
165     }
166     ed->entry.vno = kvno;
167     ret = krb5_data_copy (&ed->entry.keyblock.keyvalue,
168                           key, 8);
169     if (ret)
170         return ret;
171     ed->entry.timestamp = time(NULL);
172     ed->num = 0;
173     return 0;
174 }
175
176 static krb5_error_code
177 krb4_kt_next_entry (krb5_context context,
178                     krb5_keytab id,
179                     krb5_keytab_entry *entry,
180                     krb5_kt_cursor *c)
181 {
182     krb5_error_code ret;
183     struct krb4_kt_data *d = id->data;
184     struct krb4_cursor_extra_data *ed = c->data;
185     const krb5_enctype keytypes[] = {ETYPE_DES_CBC_MD5,
186                                      ETYPE_DES_CBC_MD4,
187                                      ETYPE_DES_CBC_CRC};
188
189     if (ed->num == -1) {
190         ret = read_v4_entry (context, d, c, ed);
191         if (ret)
192             return ret;
193     }
194     ret = krb5_kt_copy_entry_contents (context,
195                                        &ed->entry,
196                                        entry);
197     if (ret)
198         return ret;
199     entry->keyblock.keytype = keytypes[ed->num];
200     if (++ed->num == 3) {
201         krb5_kt_free_entry (context, &ed->entry);
202         ed->num = -1;
203     }
204     return 0;
205 }
206
207 static krb5_error_code
208 krb4_kt_end_seq_get (krb5_context context,
209                      krb5_keytab id,
210                      krb5_kt_cursor *c)
211 {
212     struct krb4_cursor_extra_data *ed = c->data;
213
214     krb5_storage_free (c->sp);
215     if (ed->num != -1)
216         krb5_kt_free_entry (context, &ed->entry);
217     free (c->data);
218     close (c->fd);
219     return 0;
220 }
221
222 static krb5_error_code
223 krb4_kt_add_entry (krb5_context context,
224                    krb5_keytab id,
225                    krb5_keytab_entry *entry)
226 {
227     struct krb4_kt_data *d = id->data;
228     krb5_error_code ret;
229     int fd;
230     char service[ANAME_SZ];
231     char instance[INST_SZ];
232     char realm[REALM_SZ];
233     int8_t kvno;
234
235     fd = open (d->filename, O_WRONLY | O_APPEND | O_BINARY);
236     if (fd < 0) {
237         fd = open (d->filename,
238                    O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600);
239         if (fd < 0)
240             return errno;
241     }
242     ret = krb5_524_conv_principal (context, entry->principal,
243                                    service, instance, realm);
244     if (ret) {
245         close (fd);
246         return ret;
247     }
248     if (entry->keyblock.keyvalue.length == 8
249         && entry->keyblock.keytype == ETYPE_DES_CBC_MD5) {
250         write(fd, service, strlen(service)+1);
251         write(fd, instance, strlen(instance)+1);
252         write(fd, realm, strlen(realm)+1);
253         kvno = entry->vno;
254         write(fd, &kvno, sizeof(kvno));
255         write(fd, entry->keyblock.keyvalue.data, 8);
256     }
257     close (fd);
258     return 0;
259 }
260
261 krb5_kt_ops krb4_fkt_ops = {
262     "krb4",
263     krb4_kt_resolve,
264     krb4_kt_get_name,
265     krb4_kt_close,
266     NULL,                       /* get */
267     krb4_kt_start_seq_get,
268     krb4_kt_next_entry,
269     krb4_kt_end_seq_get,
270     krb4_kt_add_entry,          /* add_entry */
271     NULL                        /* remove_entry */
272 };