1004388ebScasper /*
2159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3004388ebScasper  * Use is subject to license terms.
4004388ebScasper  */
5505d05c7Sgtb 
6505d05c7Sgtb /*
7505d05c7Sgtb  * lib/krb5/keytab/srvtab/kts_resolv.c
8505d05c7Sgtb  *
9505d05c7Sgtb  * Copyright 1990,1991,2002 by the Massachusetts Institute of Technology.
10505d05c7Sgtb  * All Rights Reserved.
11505d05c7Sgtb  *
12505d05c7Sgtb  * Export of this software from the United States of America may
13505d05c7Sgtb  *   require a specific license from the United States Government.
14505d05c7Sgtb  *   It is the responsibility of any person or organization contemplating
15505d05c7Sgtb  *   export to obtain such a license before exporting.
16*55fea89dSDan Cross  *
17505d05c7Sgtb  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18505d05c7Sgtb  * distribute this software and its documentation for any purpose and
19505d05c7Sgtb  * without fee is hereby granted, provided that the above copyright
20505d05c7Sgtb  * notice appear in all copies and that both that copyright notice and
21505d05c7Sgtb  * this permission notice appear in supporting documentation, and that
22505d05c7Sgtb  * the name of M.I.T. not be used in advertising or publicity pertaining
23505d05c7Sgtb  * to distribution of the software without specific, written prior
24505d05c7Sgtb  * permission.  Furthermore if you modify this software you must label
25505d05c7Sgtb  * your software as modified software and not distribute it in such a
26505d05c7Sgtb  * fashion that it might be confused with the original M.I.T. software.
27505d05c7Sgtb  * M.I.T. makes no representations about the suitability of
28505d05c7Sgtb  * this software for any purpose.  It is provided "as is" without express
29505d05c7Sgtb  * or implied warranty.
30505d05c7Sgtb  */
31505d05c7Sgtb 
32505d05c7Sgtb #include "k5-int.h"
33505d05c7Sgtb #include <stdio.h>
34505d05c7Sgtb 
35505d05c7Sgtb /*
36505d05c7Sgtb  * Constants
37505d05c7Sgtb  */
38505d05c7Sgtb #define IGNORE_VNO 0
39505d05c7Sgtb #define IGNORE_ENCTYPE 0
40505d05c7Sgtb 
41505d05c7Sgtb #define KRB5_KT_VNO_1	0x0501	/* krb v5, keytab version 1 (DCE compat) */
42505d05c7Sgtb #define KRB5_KT_VNO	0x0502	/* krb v5, keytab version 2 (standard)  */
43505d05c7Sgtb 
44505d05c7Sgtb #define KRB5_KT_DEFAULT_VNO KRB5_KT_VNO
45505d05c7Sgtb 
46*55fea89dSDan Cross /*
47505d05c7Sgtb  * Types
48505d05c7Sgtb  */
49505d05c7Sgtb typedef struct _krb5_ktsrvtab_data {
50505d05c7Sgtb     char *name;			/* Name of the file */
51505d05c7Sgtb     FILE *openf;		/* open file, if any. */
52505d05c7Sgtb } krb5_ktsrvtab_data;
53505d05c7Sgtb 
54505d05c7Sgtb /*
55505d05c7Sgtb  * Macros
56505d05c7Sgtb  */
57505d05c7Sgtb #define KTPRIVATE(id) ((krb5_ktsrvtab_data *)(id)->data)
58505d05c7Sgtb #define KTFILENAME(id) (((krb5_ktsrvtab_data *)(id)->data)->name)
59505d05c7Sgtb #define KTFILEP(id) (((krb5_ktsrvtab_data *)(id)->data)->openf)
60505d05c7Sgtb 
61505d05c7Sgtb extern const struct _krb5_kt_ops krb5_kts_ops;
62505d05c7Sgtb 
63505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_resolve
64505d05c7Sgtb 	(krb5_context,
65505d05c7Sgtb 		   const char *,
66505d05c7Sgtb 		   krb5_keytab *);
67505d05c7Sgtb 
68505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_get_name
69505d05c7Sgtb 	(krb5_context,
70505d05c7Sgtb 		   krb5_keytab,
71505d05c7Sgtb 		   char *,
72505d05c7Sgtb 		   unsigned int);
73505d05c7Sgtb 
74505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_close
75505d05c7Sgtb 	(krb5_context,
76505d05c7Sgtb 		   krb5_keytab);
77505d05c7Sgtb 
78505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_get_entry
79505d05c7Sgtb 	(krb5_context,
80505d05c7Sgtb 		   krb5_keytab,
81505d05c7Sgtb 		   krb5_const_principal,
82505d05c7Sgtb 		   krb5_kvno,
83505d05c7Sgtb 		   krb5_enctype,
84505d05c7Sgtb 		   krb5_keytab_entry *);
85505d05c7Sgtb 
86505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_start_seq_get
87505d05c7Sgtb 	(krb5_context,
88505d05c7Sgtb 		   krb5_keytab,
89505d05c7Sgtb 		   krb5_kt_cursor *);
90505d05c7Sgtb 
91505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_get_next
92505d05c7Sgtb 	(krb5_context,
93505d05c7Sgtb 		   krb5_keytab,
94505d05c7Sgtb 		   krb5_keytab_entry *,
95505d05c7Sgtb 		   krb5_kt_cursor *);
96505d05c7Sgtb 
97505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_end_get
98505d05c7Sgtb 	(krb5_context,
99505d05c7Sgtb 		   krb5_keytab,
100505d05c7Sgtb 		   krb5_kt_cursor *);
101505d05c7Sgtb 
102505d05c7Sgtb static krb5_error_code krb5_ktsrvint_open
103505d05c7Sgtb 	(krb5_context,
104505d05c7Sgtb 		   krb5_keytab);
105505d05c7Sgtb 
106505d05c7Sgtb static krb5_error_code krb5_ktsrvint_close
107505d05c7Sgtb 	(krb5_context,
108505d05c7Sgtb 		   krb5_keytab);
109505d05c7Sgtb 
110*55fea89dSDan Cross static krb5_error_code krb5_ktsrvint_read_entry
111505d05c7Sgtb 	(krb5_context,
112505d05c7Sgtb 		   krb5_keytab,
113505d05c7Sgtb 		   krb5_keytab_entry *);
114505d05c7Sgtb 
115505d05c7Sgtb /*
116*55fea89dSDan Cross  * This is an implementation specific resolver.  It returns a keytab id
117505d05c7Sgtb  * initialized with srvtab keytab routines.
118505d05c7Sgtb  */
119505d05c7Sgtb 
120505d05c7Sgtb static krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_resolve(krb5_context context,const char * name,krb5_keytab * id)121505d05c7Sgtb krb5_ktsrvtab_resolve(krb5_context context, const char *name, krb5_keytab *id)
122505d05c7Sgtb {
123505d05c7Sgtb     krb5_ktsrvtab_data *data;
124505d05c7Sgtb     FILE *fp;
125505d05c7Sgtb 
126505d05c7Sgtb     /* Make sure we can open the srvtab file for reading. */
127159d09a2SMark Phalan     /* Solaris Kerberos */
128004388ebScasper     fp = fopen(name, "rF");
129505d05c7Sgtb     if (!fp)
130505d05c7Sgtb 	return(errno);
131505d05c7Sgtb     fclose(fp);
132505d05c7Sgtb 
133505d05c7Sgtb     if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
134505d05c7Sgtb 	return(ENOMEM);
135*55fea89dSDan Cross 
136505d05c7Sgtb     (*id)->ops = &krb5_kts_ops;
137505d05c7Sgtb     data = (krb5_ktsrvtab_data *)malloc(sizeof(krb5_ktsrvtab_data));
138505d05c7Sgtb     if (data == NULL) {
139505d05c7Sgtb 	krb5_xfree(*id);
140505d05c7Sgtb 	return(ENOMEM);
141505d05c7Sgtb     }
142505d05c7Sgtb 
143505d05c7Sgtb     data->name = (char *)malloc(strlen(name) + 1);
144505d05c7Sgtb     if (data->name == NULL) {
145505d05c7Sgtb 	krb5_xfree(data);
146505d05c7Sgtb 	krb5_xfree(*id);
147505d05c7Sgtb 	return(ENOMEM);
148505d05c7Sgtb     }
149505d05c7Sgtb 
150505d05c7Sgtb     (void) strcpy(data->name, name);
151505d05c7Sgtb     data->openf = 0;
152505d05c7Sgtb 
153505d05c7Sgtb     (*id)->data = (krb5_pointer)data;
154505d05c7Sgtb     (*id)->magic = KV5M_KEYTAB;
155505d05c7Sgtb     return(0);
156505d05c7Sgtb }
157505d05c7Sgtb 
158505d05c7Sgtb /*
159505d05c7Sgtb  * "Close" a file-based keytab and invalidate the id.  This means
160505d05c7Sgtb  * free memory hidden in the structures.
161505d05c7Sgtb  */
162505d05c7Sgtb 
163505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_close(krb5_context context,krb5_keytab id)164505d05c7Sgtb krb5_ktsrvtab_close(krb5_context context, krb5_keytab id)
165505d05c7Sgtb   /*
166*55fea89dSDan Cross    * This routine is responsible for freeing all memory allocated
167505d05c7Sgtb    * for this keytab.  There are no system resources that need
168505d05c7Sgtb    * to be freed nor are there any open files.
169505d05c7Sgtb    *
170505d05c7Sgtb    * This routine should undo anything done by krb5_ktsrvtab_resolve().
171505d05c7Sgtb    */
172505d05c7Sgtb {
173505d05c7Sgtb     krb5_xfree(KTFILENAME(id));
174505d05c7Sgtb     krb5_xfree(id->data);
175505d05c7Sgtb     id->ops = 0;
176505d05c7Sgtb     krb5_xfree(id);
177505d05c7Sgtb     return (0);
178505d05c7Sgtb }
179505d05c7Sgtb 
180505d05c7Sgtb /*
181505d05c7Sgtb  * This is the get_entry routine for the file based keytab implementation.
182505d05c7Sgtb  * It opens the keytab file, and either retrieves the entry or returns
183505d05c7Sgtb  * an error.
184505d05c7Sgtb  */
185505d05c7Sgtb 
186505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_get_entry(krb5_context context,krb5_keytab id,krb5_const_principal principal,krb5_kvno kvno,krb5_enctype enctype,krb5_keytab_entry * entry)187505d05c7Sgtb krb5_ktsrvtab_get_entry(krb5_context context, krb5_keytab id, krb5_const_principal principal, krb5_kvno kvno, krb5_enctype enctype, krb5_keytab_entry *entry)
188505d05c7Sgtb {
189505d05c7Sgtb     krb5_keytab_entry best_entry, ent;
190505d05c7Sgtb     krb5_error_code kerror = 0;
191505d05c7Sgtb     int found_wrong_kvno = 0;
192505d05c7Sgtb 
193505d05c7Sgtb     /* Open the srvtab. */
194505d05c7Sgtb     if ((kerror = krb5_ktsrvint_open(context, id)))
195505d05c7Sgtb 	return(kerror);
196505d05c7Sgtb 
197505d05c7Sgtb     /* srvtab files only have DES_CBC_CRC keys. */
198505d05c7Sgtb     switch (enctype) {
199505d05c7Sgtb     case ENCTYPE_DES_CBC_CRC:
200505d05c7Sgtb     case ENCTYPE_DES_CBC_MD5:
201505d05c7Sgtb     case ENCTYPE_DES_CBC_MD4:
202505d05c7Sgtb     case ENCTYPE_DES_CBC_RAW:
203505d05c7Sgtb     case IGNORE_ENCTYPE:
204505d05c7Sgtb 	break;
205505d05c7Sgtb     default:
206505d05c7Sgtb 	return KRB5_KT_NOTFOUND;
207505d05c7Sgtb     }
208505d05c7Sgtb 
209505d05c7Sgtb     best_entry.principal = 0;
210505d05c7Sgtb     best_entry.vno = 0;
211505d05c7Sgtb     best_entry.key.contents = 0;
212505d05c7Sgtb     while ((kerror = krb5_ktsrvint_read_entry(context, id, &ent)) == 0) {
213505d05c7Sgtb 	ent.key.enctype = enctype;
214505d05c7Sgtb 	if (krb5_principal_compare(context, principal, ent.principal)) {
215505d05c7Sgtb 	    if (kvno == IGNORE_VNO) {
216505d05c7Sgtb 		if (!best_entry.principal || (best_entry.vno < ent.vno)) {
217505d05c7Sgtb 		    krb5_kt_free_entry(context, &best_entry);
218505d05c7Sgtb 		    best_entry = ent;
219505d05c7Sgtb 		}
220505d05c7Sgtb 	    } else {
221505d05c7Sgtb 		if (ent.vno == kvno) {
222505d05c7Sgtb 		    best_entry = ent;
223505d05c7Sgtb 		    break;
224505d05c7Sgtb 		} else {
225505d05c7Sgtb 		    found_wrong_kvno = 1;
226505d05c7Sgtb 		}
227505d05c7Sgtb 	    }
228505d05c7Sgtb 	} else {
229505d05c7Sgtb 	    krb5_kt_free_entry(context, &ent);
230505d05c7Sgtb 	}
231505d05c7Sgtb     }
232505d05c7Sgtb     if (kerror == KRB5_KT_END) {
233505d05c7Sgtb 	 if (best_entry.principal)
234505d05c7Sgtb 	      kerror = 0;
235505d05c7Sgtb 	 else if (found_wrong_kvno)
236505d05c7Sgtb 	      kerror = KRB5_KT_KVNONOTFOUND;
237505d05c7Sgtb 	 else
238505d05c7Sgtb 	      kerror = KRB5_KT_NOTFOUND;
239505d05c7Sgtb     }
240505d05c7Sgtb     if (kerror) {
241505d05c7Sgtb 	(void) krb5_ktsrvint_close(context, id);
242505d05c7Sgtb 	krb5_kt_free_entry(context, &best_entry);
243505d05c7Sgtb 	return kerror;
244505d05c7Sgtb     }
245505d05c7Sgtb     if ((kerror = krb5_ktsrvint_close(context, id)) != 0) {
246505d05c7Sgtb 	krb5_kt_free_entry(context, &best_entry);
247505d05c7Sgtb 	return kerror;
248505d05c7Sgtb     }
249505d05c7Sgtb     *entry = best_entry;
250505d05c7Sgtb     return 0;
251505d05c7Sgtb }
252505d05c7Sgtb 
253505d05c7Sgtb /*
254505d05c7Sgtb  * Get the name of the file containing a srvtab-based keytab.
255505d05c7Sgtb  */
256505d05c7Sgtb 
257505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_get_name(krb5_context context,krb5_keytab id,char * name,unsigned int len)258505d05c7Sgtb krb5_ktsrvtab_get_name(krb5_context context, krb5_keytab id, char *name, unsigned int len)
259*55fea89dSDan Cross   /*
260505d05c7Sgtb    * This routine returns the name of the name of the file associated with
261505d05c7Sgtb    * this srvtab-based keytab.  The name is prefixed with PREFIX:, so that
262505d05c7Sgtb    * trt will happen if the name is passed back to resolve.
263505d05c7Sgtb    */
264505d05c7Sgtb {
265505d05c7Sgtb     memset(name, 0, len);
266505d05c7Sgtb 
267505d05c7Sgtb     if (len < strlen(id->ops->prefix)+2)
268505d05c7Sgtb 	return(KRB5_KT_NAME_TOOLONG);
269505d05c7Sgtb     strcpy(name, id->ops->prefix);
270505d05c7Sgtb     name += strlen(id->ops->prefix);
271505d05c7Sgtb     name[0] = ':';
272505d05c7Sgtb     name++;
273505d05c7Sgtb     len -= strlen(id->ops->prefix)+1;
274505d05c7Sgtb 
275159d09a2SMark Phalan     /* Solaris Kerberos */
27654925bf6Swillf     if (len < strlen(KTFILENAME(id))+1)
277505d05c7Sgtb 	return(KRB5_KT_NAME_TOOLONG);
278505d05c7Sgtb     strcpy(name, KTFILENAME(id));
279505d05c7Sgtb     /* strcpy will NUL-terminate the destination */
280505d05c7Sgtb 
281505d05c7Sgtb     return(0);
282505d05c7Sgtb }
283505d05c7Sgtb 
284505d05c7Sgtb /*
285505d05c7Sgtb  * krb5_ktsrvtab_start_seq_get()
286505d05c7Sgtb  */
287505d05c7Sgtb 
288505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_start_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursorp)289505d05c7Sgtb krb5_ktsrvtab_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursorp)
290505d05c7Sgtb {
291505d05c7Sgtb     krb5_error_code retval;
292505d05c7Sgtb     long *fileoff;
293505d05c7Sgtb 
294505d05c7Sgtb     if ((retval = krb5_ktsrvint_open(context, id)))
295505d05c7Sgtb 	return retval;
296505d05c7Sgtb 
297505d05c7Sgtb     if (!(fileoff = (long *)malloc(sizeof(*fileoff)))) {
298505d05c7Sgtb 	krb5_ktsrvint_close(context, id);
299505d05c7Sgtb 	return ENOMEM;
300505d05c7Sgtb     }
301505d05c7Sgtb     *fileoff = ftell(KTFILEP(id));
302505d05c7Sgtb     *cursorp = (krb5_kt_cursor)fileoff;
303505d05c7Sgtb 
304505d05c7Sgtb     return 0;
305505d05c7Sgtb }
306505d05c7Sgtb 
307505d05c7Sgtb /*
308505d05c7Sgtb  * krb5_ktsrvtab_get_next()
309505d05c7Sgtb  */
310505d05c7Sgtb 
311505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_get_next(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry,krb5_kt_cursor * cursor)312505d05c7Sgtb krb5_ktsrvtab_get_next(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor)
313505d05c7Sgtb {
314505d05c7Sgtb     long *fileoff = (long *)*cursor;
315505d05c7Sgtb     krb5_keytab_entry cur_entry;
316505d05c7Sgtb     krb5_error_code kerror;
317505d05c7Sgtb 
318505d05c7Sgtb     if (fseek(KTFILEP(id), *fileoff, 0) == -1)
319505d05c7Sgtb 	return KRB5_KT_END;
320505d05c7Sgtb     if ((kerror = krb5_ktsrvint_read_entry(context, id, &cur_entry)))
321505d05c7Sgtb 	return kerror;
322505d05c7Sgtb     *fileoff = ftell(KTFILEP(id));
323505d05c7Sgtb     *entry = cur_entry;
324505d05c7Sgtb     return 0;
325505d05c7Sgtb }
326505d05c7Sgtb 
327505d05c7Sgtb /*
328505d05c7Sgtb  * krb5_ktsrvtab_end_get()
329505d05c7Sgtb  */
330505d05c7Sgtb 
331505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_ktsrvtab_end_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)332505d05c7Sgtb krb5_ktsrvtab_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor)
333505d05c7Sgtb {
334505d05c7Sgtb     krb5_xfree(*cursor);
335505d05c7Sgtb     return krb5_ktsrvint_close(context, id);
336505d05c7Sgtb }
337505d05c7Sgtb 
338505d05c7Sgtb /*
339505d05c7Sgtb  * krb5_kts_ops
340505d05c7Sgtb  */
341505d05c7Sgtb 
342505d05c7Sgtb const struct _krb5_kt_ops krb5_kts_ops = {
343505d05c7Sgtb     0,
344505d05c7Sgtb     "SRVTAB", 	/* Prefix -- this string should not appear anywhere else! */
345505d05c7Sgtb     krb5_ktsrvtab_resolve,
346*55fea89dSDan Cross     krb5_ktsrvtab_get_name,
347505d05c7Sgtb     krb5_ktsrvtab_close,
348505d05c7Sgtb     krb5_ktsrvtab_get_entry,
349505d05c7Sgtb     krb5_ktsrvtab_start_seq_get,
350505d05c7Sgtb     krb5_ktsrvtab_get_next,
351505d05c7Sgtb     krb5_ktsrvtab_end_get,
352505d05c7Sgtb     0,
353505d05c7Sgtb     0,
354505d05c7Sgtb     0
355505d05c7Sgtb };
356505d05c7Sgtb 
357505d05c7Sgtb /*
358505d05c7Sgtb  * formerly: lib/krb5/keytab/srvtab/kts_util.c
359505d05c7Sgtb  *
360505d05c7Sgtb  * Copyright (c) Hewlett-Packard Company 1991
361505d05c7Sgtb  * Released to the Massachusetts Institute of Technology for inclusion
362505d05c7Sgtb  * in the Kerberos source code distribution.
363505d05c7Sgtb  *
364505d05c7Sgtb  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
365505d05c7Sgtb  * All Rights Reserved.
366505d05c7Sgtb  *
367505d05c7Sgtb  * Export of this software from the United States of America may
368505d05c7Sgtb  *   require a specific license from the United States Government.
369505d05c7Sgtb  *   It is the responsibility of any person or organization contemplating
370505d05c7Sgtb  *   export to obtain such a license before exporting.
371*55fea89dSDan Cross  *
372505d05c7Sgtb  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
373505d05c7Sgtb  * distribute this software and its documentation for any purpose and
374505d05c7Sgtb  * without fee is hereby granted, provided that the above copyright
375505d05c7Sgtb  * notice appear in all copies and that both that copyright notice and
376505d05c7Sgtb  * this permission notice appear in supporting documentation, and that
377505d05c7Sgtb  * the name of M.I.T. not be used in advertising or publicity pertaining
378505d05c7Sgtb  * to distribution of the software without specific, written prior
379505d05c7Sgtb  * permission.  Furthermore if you modify this software you must label
380505d05c7Sgtb  * your software as modified software and not distribute it in such a
381505d05c7Sgtb  * fashion that it might be confused with the original M.I.T. software.
382505d05c7Sgtb  * M.I.T. makes no representations about the suitability of
383505d05c7Sgtb  * this software for any purpose.  It is provided "as is" without express
384505d05c7Sgtb  * or implied warranty.
385*55fea89dSDan Cross  *
386505d05c7Sgtb  *
387505d05c7Sgtb  * This function contains utilities for the srvtab based implementation
388505d05c7Sgtb  * of the keytab.  There are no public functions in this file.
389505d05c7Sgtb  */
390505d05c7Sgtb 
391505d05c7Sgtb #include <stdio.h>
392505d05c7Sgtb 
393505d05c7Sgtb #ifdef ANSI_STDIO
394159d09a2SMark Phalan /* Solaris Kerberos */
395004388ebScasper #define		READ_MODE	"rbF"
396505d05c7Sgtb #else
397159d09a2SMark Phalan /* Solaris Kerberos */
398004388ebScasper #define		READ_MODE	"rF"
399505d05c7Sgtb #endif
400505d05c7Sgtb 
401505d05c7Sgtb /* The maximum sizes for V4 aname, realm, sname, and instance +1 */
402505d05c7Sgtb /* Taken from krb.h */
403505d05c7Sgtb #define 	ANAME_SZ	40
404505d05c7Sgtb #define		REALM_SZ	40
405505d05c7Sgtb #define		SNAME_SZ	40
406505d05c7Sgtb #define		INST_SZ		40
407505d05c7Sgtb 
408505d05c7Sgtb static krb5_error_code
read_field(FILE * fp,char * s,int len)409505d05c7Sgtb read_field(FILE *fp, char *s, int len)
410505d05c7Sgtb {
411505d05c7Sgtb     int c;
412505d05c7Sgtb 
413505d05c7Sgtb     while ((c = getc(fp)) != 0) {
414505d05c7Sgtb 	if (c == EOF || len <= 1)
415505d05c7Sgtb 	    return KRB5_KT_END;
416505d05c7Sgtb 	*s = c;
417505d05c7Sgtb 	s++;
418505d05c7Sgtb 	len--;
419505d05c7Sgtb     }
420505d05c7Sgtb     *s = 0;
421505d05c7Sgtb     return 0;
422505d05c7Sgtb }
423505d05c7Sgtb 
424505d05c7Sgtb krb5_error_code
krb5_ktsrvint_open(krb5_context context,krb5_keytab id)425505d05c7Sgtb krb5_ktsrvint_open(krb5_context context, krb5_keytab id)
426505d05c7Sgtb {
427505d05c7Sgtb     KTFILEP(id) = fopen(KTFILENAME(id), READ_MODE);
428505d05c7Sgtb     if (!KTFILEP(id))
429505d05c7Sgtb 	return errno;
430505d05c7Sgtb     return 0;
431505d05c7Sgtb }
432505d05c7Sgtb 
433505d05c7Sgtb krb5_error_code
krb5_ktsrvint_close(krb5_context context,krb5_keytab id)434505d05c7Sgtb krb5_ktsrvint_close(krb5_context context, krb5_keytab id)
435505d05c7Sgtb {
436505d05c7Sgtb     if (!KTFILEP(id))
437505d05c7Sgtb 	return 0;
438505d05c7Sgtb     (void) fclose(KTFILEP(id));
439505d05c7Sgtb     KTFILEP(id) = 0;
440505d05c7Sgtb     return 0;
441505d05c7Sgtb }
442505d05c7Sgtb 
443505d05c7Sgtb krb5_error_code
krb5_ktsrvint_read_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * ret_entry)444505d05c7Sgtb krb5_ktsrvint_read_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *ret_entry)
445505d05c7Sgtb {
446505d05c7Sgtb     FILE *fp;
447505d05c7Sgtb     char name[SNAME_SZ], instance[INST_SZ], realm[REALM_SZ];
448505d05c7Sgtb     unsigned char key[8];
449505d05c7Sgtb     int vno;
450505d05c7Sgtb     krb5_error_code kerror;
451505d05c7Sgtb 
452505d05c7Sgtb     /* Read in an entry from the srvtab file. */
453505d05c7Sgtb     fp = KTFILEP(id);
454505d05c7Sgtb     kerror = read_field(fp, name, sizeof(name));
455505d05c7Sgtb     if (kerror != 0)
456505d05c7Sgtb 	return kerror;
457505d05c7Sgtb     kerror = read_field(fp, instance, sizeof(instance));
458505d05c7Sgtb     if (kerror != 0)
459505d05c7Sgtb 	return kerror;
460505d05c7Sgtb     kerror = read_field(fp, realm, sizeof(realm));
461505d05c7Sgtb     if (kerror != 0)
462505d05c7Sgtb 	return kerror;
463505d05c7Sgtb     vno = getc(fp);
464505d05c7Sgtb     if (vno == EOF)
465505d05c7Sgtb 	return KRB5_KT_END;
466505d05c7Sgtb     if (fread(key, 1, sizeof(key), fp) != sizeof(key))
467505d05c7Sgtb 	return KRB5_KT_END;
468505d05c7Sgtb 
469505d05c7Sgtb     /* Fill in ret_entry with the data we read.  Everything maps well
470505d05c7Sgtb      * except for the timestamp, which we don't have a value for.  For
471505d05c7Sgtb      * now we just set it to 0. */
472505d05c7Sgtb     memset(ret_entry, 0, sizeof(*ret_entry));
473505d05c7Sgtb     ret_entry->magic = KV5M_KEYTAB_ENTRY;
474505d05c7Sgtb     kerror = krb5_425_conv_principal(context, name, instance, realm,
475505d05c7Sgtb 				     &ret_entry->principal);
476505d05c7Sgtb     if (kerror != 0)
477505d05c7Sgtb 	return kerror;
478505d05c7Sgtb     ret_entry->vno = vno;
479505d05c7Sgtb     ret_entry->timestamp = 0;
480505d05c7Sgtb     ret_entry->key.enctype = ENCTYPE_DES_CBC_CRC;
481505d05c7Sgtb     ret_entry->key.magic = KV5M_KEYBLOCK;
482505d05c7Sgtb     ret_entry->key.length = sizeof(key);
483505d05c7Sgtb     ret_entry->key.contents = malloc(sizeof(key));
484505d05c7Sgtb     if (!ret_entry->key.contents) {
485505d05c7Sgtb 	krb5_free_principal(context, ret_entry->principal);
486505d05c7Sgtb 	return ENOMEM;
487505d05c7Sgtb     }
488505d05c7Sgtb     memcpy(ret_entry->key.contents, key, sizeof(key));
489505d05c7Sgtb 
490505d05c7Sgtb     return 0;
491505d05c7Sgtb }
492