Don't declare *_print by default.
[krb5dissect.git] / keytab.c
bloba219080d72655aa864e415aca0654852694fbc39
1 /* keytab.c --- Read MIT style Kerberos hostkey files.
2 * Copyright (C) 2006, 2007 Simon Josefsson
4 * This file is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This file is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this file; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
21 #include "keytab.h"
22 #include <stdio.h>
24 /* See keytab.txt for a description of the file format.
27 static int
28 get_uint8 (const char **data, size_t * len, uint8_t * i)
30 const char *p = *data;
31 if (*len < 1)
32 return -1;
33 *i = p[0];
34 *data += 1;
35 *len -= 1;
36 return 0;
39 static int
40 get_uint16 (const char **data, size_t * len, uint16_t * i)
42 const char *p = *data;
43 if (*len < 2)
44 return -1;
45 *i = p[0] << 8 | p[1];
46 *data += 2;
47 *len -= 2;
48 return 0;
51 static int
52 get_uint32 (const char **data, size_t * len, uint32_t * i)
54 const char *p = *data;
55 if (*len < 4)
56 return -1;
57 *i = ((p[0] << 24) & 0xFF000000)
58 | ((p[1] << 16) & 0xFF0000) | ((p[2] << 8) & 0xFF00) | (p[3] & 0xFF);
59 *data += 4;
60 *len -= 4;
61 return 0;
64 static int
65 parse_principal (const char **data, size_t * len,
66 struct keytab_principal *out)
68 size_t n;
69 int rc;
71 rc = get_uint16 (data, len, &out->num_components);
72 if (rc < 0)
73 return rc;
75 if (out->num_components >= KEYTAB_MAX_COMPONENTS)
76 return -1;
78 rc = get_uint16 (data, len, &out->realm.length);
79 if (rc < 0)
80 return rc;
82 if (*len < out->realm.length)
83 return -1;
84 out->realm.data = *data;
85 *data += out->realm.length;
86 *len -= out->realm.length;
88 /* Make sure realm will be zero terminated. This limits the initial
89 component length to 2^24 bytes. */
90 if (!*len || **(char**)data != '\0')
91 return -1;
93 for (n = 0; n < out->num_components; n++)
95 rc = get_uint16 (data, len, &out->components[n].length);
96 if (rc < 0)
97 return rc;
99 if (*len < out->components[n].length)
100 return -1;
101 out->components[n].data = *data;
102 *data += out->components[n].length;
103 *len -= out->components[n].length;
105 /* Make sure component is zero terminated. This limits the name
106 type to values below 2^24. */
107 if (!*len || **(char**)data != '\0')
108 return -1;
111 rc = get_uint32 (data, len, &out->name_type);
112 if (rc < 0)
113 return rc;
115 return 0;
118 static int
119 parse_entry (const char **data, size_t * len,
120 struct keytab_entry *out)
122 struct keytab_principal princ;
123 uint32_t num_address;
124 uint32_t num_authdata;
125 int32_t size;
126 int rc;
128 rc = get_uint32 (data, len, &size);
129 if (rc < 0)
130 return rc;
132 if (*len < size)
133 return -1;
135 out->size = size;
137 *len -= size;
139 rc = parse_principal (data, &size, &out->name);
140 if (rc < 0)
141 return rc;
143 rc = get_uint32 (data, &size, &out->timestamp);
144 if (rc < 0)
145 return rc;
147 rc = get_uint8 (data, &size, &out->key.vno8);
148 if (rc < 0)
149 return rc;
151 rc = get_uint16 (data, &size, &out->key.type);
152 if (rc < 0)
153 return rc;
155 rc = get_uint16 (data, &size, &out->key.keylen);
156 if (rc < 0)
157 return rc;
159 if (size < out->key.keylen)
160 return -1;
162 out->key.keyvalue = *data;
164 *data += out->key.keylen;
165 size -= out->key.keylen;
167 if (size == 4)
169 rc = get_uint32 (data, &size, &out->key.vno);
170 if (rc < 0)
171 return rc;
173 else
174 out->key.vno = -1;
176 if (size != 0)
177 return -1;
179 return 0;
183 keytab_parse (const char *data, size_t len, struct keytab *out)
185 size_t pos = 0;
186 int rc;
187 size_t size;
189 rc = get_uint16 (&data, &len, &out->file_format_version);
190 if (rc < 0)
191 return rc;
193 out->keytabs = data;
194 out->keytabslen = len;
196 /* Validate size integrity of file. */
199 rc = get_uint32 (&data, &len, &size);
200 if (rc < 0)
201 return rc;
203 if (len < size)
204 return -1;
206 data += size;
207 len -= size;
209 while (len > 0);
211 return 0;
215 keytab_parse_entry (const char *data, size_t len,
216 struct keytab_entry *out, size_t * n)
218 size_t savelen = len;
219 int rc = parse_entry (&data, &len, out);
221 if (rc < 0)
222 return rc;
224 *n = savelen - len;
225 return 0;
228 #if defined (TEST) || defined (ENABLE_PRINT)
229 void
230 keytab_print (struct keytab *keytab)
232 size_t n;
234 printf ("file_format_version %04x\n", keytab->file_format_version);
237 void
238 keytab_print_principal (struct keytab_principal *princ)
240 size_t n;
242 printf ("\tnum_components %04x\n", princ->num_components);
243 printf ("\trealmlen %04x\n", princ->realm.length);
244 printf ("\trealm %.*s\n", princ->realm.length, princ->realm.data);
246 for (n = 0; n < princ->num_components; n++)
248 printf ("\t\tcomponentlen %04x\n", princ->components[n].length);
249 printf ("\t\tcomponent %.*s\n", princ->components[n].length,
250 princ->components[n].data);
252 printf ("\tname_type %04x\n", princ->name_type);
255 void
256 keytab_print_entry (struct keytab_entry *keytab)
258 size_t i;
259 printf ("\tsize %04x\n", keytab->size);
260 printf ("\tnum_components %04x\n", keytab->num_components);
261 keytab_print_principal (&keytab->name);
262 printf ("\tkey:\n");
263 printf ("\t\tvno8 %04x\n", keytab->key.vno8);
264 printf ("\t\tkeytype %04x\n", keytab->key.type);
265 printf ("\t\tkeylen %04x\n", keytab->key.keylen);
266 printf ("\t\tkey value: ");
267 for (i = 0; i < keytab->key.keylen; i++)
268 printf ("%02x", ((char *) keytab->key.keyvalue)[i] & 0xFF);
269 printf ("\n");
270 if (keytab->key.vno != -1)
271 printf ("\t\tvno %04x\n", keytab->key.vno);
273 #endif
275 #ifdef TEST
277 main (int argc, char *argv[])
279 char buf[10240];
280 size_t len;
281 FILE *fh;
282 int rc;
283 struct keytab keytab;
284 struct keytab_entry entry;
285 size_t i = 0;
287 if (argc <= 1)
289 printf ("Usage: %s <krb5keytab-file>\n", argv[0]);
290 return 1;
293 fh = fopen (argv[1], "rb");
294 if (!fh)
296 puts ("Error: cannot open file");
297 return 1;
300 len = fread (buf, 1, sizeof (buf), fh);
302 if (len >= sizeof (buf))
304 puts ("Error: file too large");
305 return 1;
308 rc = keytab_parse (buf, len, &keytab);
309 if (rc < 0)
311 puts ("Error: syntax error");
312 return 1;
315 keytab_print (&keytab);
317 while (keytab.keytabslen)
319 size_t n;
321 rc = keytab_parse_entry (keytab.keytabs,
322 keytab.keytabslen, &entry, &n);
323 if (rc < 0)
325 printf ("Error: cannot parse credential %d\n", i);
326 return rc;
329 printf ("\nCredential %d:\n", i++);
331 keytab_print_entry (&entry);
333 keytab.keytabs += n;
334 keytab.keytabslen -= n;
337 if (fclose (fh))
339 puts ("Error: cannot close file");
340 return 1;
343 return 0;
345 #endif