Add.
[shishi.git] / lib / keytab.c
blob4958943d7d99b8d06c3f4b5070b5e2c15de6be0a
1 /* keys.c --- Functions for reading /etc/krb5.keytab style key files.
2 * Copyright (C) 2002, 2003, 2004, 2006 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "internal.h"
24 /**
25 * shishi_keys_add_keytab_mem:
26 * @handle: shishi handle as allocated by shishi_init().
27 * @data: constant memory buffer with keytab of @len size.
28 * @len: size of memory buffer with keytab data.
29 * @keys: allocated key set to store keys in.
31 * Read keys from a MIT keytab data structure, and add them to the key
32 * set.
34 * The format of keytab's is proprietary, and this function support
35 * the 0x0501 and 0x0502 formats. See the section The MIT Kerberos
36 * Keytab Binary File Format in the Shishi manual for a description of
37 * the reverse-engineered format.
39 * Returns: Returns %SHISHI_KEYTAB_ERROR if the data does not
40 * represent a valid keytab structure, and %SHISHI_OK on success.
41 **/
42 int
43 shishi_keys_add_keytab_mem (Shishi * handle,
44 const char *data, size_t len,
45 Shishi_keys *keys)
47 int rc;
48 uint16_t file_format_version;
49 size_t entrystartpos;
50 uint16_t num_components; /* sub 1 if version 0x501 */
51 char *principal;
52 size_t i, l;
53 Shishi_key *key;
55 if (VERBOSENOISE (handle))
57 printf ("keytab len %d (0x%x)\n", len, len);
58 _shishi_hexprint (data, len);
61 /* Check file format. */
62 file_format_version = (data[0] << 8) | data[1];
64 if (VERBOSENOISE (handle))
65 printf ("keytab file_format_version %04X\n", file_format_version);
67 if (file_format_version != 0x0501 && file_format_version != 0x0502)
68 return SHISHI_KEYTAB_ERROR;
70 /* Check file integrity first, to avoid error-checking below. */
71 entrystartpos = 2;
72 while (entrystartpos < len)
74 int32_t size = data[entrystartpos] << 24 | data[entrystartpos+1] << 16
75 | data[entrystartpos+2] << 8 | data[entrystartpos+3];
76 entrystartpos += 4;
78 if (VERBOSENOISE (handle))
80 printf ("keytab size %d (%x)\n", size, size);
81 printf ("keytab pos %d < %d\n", entrystartpos + size, len);
84 if (entrystartpos + size > len)
85 return SHISHI_KEYTAB_ERROR;
87 /* Go to next entry... */
88 entrystartpos += size;
90 if (entrystartpos != len)
91 return SHISHI_KEYTAB_ERROR;
93 rc = shishi_key (handle, &key);
94 if (rc != SHISHI_OK)
95 return rc;
97 entrystartpos = 2;
98 while (entrystartpos < len)
100 size_t pos = entrystartpos;
101 uint16_t size = data[pos] << 24 | data[pos+1] << 16
102 | data[pos+2] << 8 | data[pos+3];
103 pos += 4;
105 if (VERBOSENOISE (handle))
106 printf ("keytab size %d (%x)\n", size, size);
108 /* Num_components */
109 num_components = data[pos] << 8 | data[pos+1];
110 pos += 2;
112 if (file_format_version == 0x0501)
113 num_components--;
115 /* Realm */
117 uint16_t realmlen = data[pos] << 8 | data[pos+1];
118 char *realm = xstrndup (&data[pos + 2], realmlen);;
120 pos += 2 + realmlen;
122 shishi_key_realm_set (key, realm);
123 free (realm);
126 /* Principal components. */
128 char *name = NULL;
129 size_t namelen = 0;
131 for (i = 0; i < num_components; i++)
133 size_t l;
135 l = data[pos] << 8 | data[pos+1];
136 pos += 2;
138 name = xrealloc (name, namelen + l + 1);
139 memcpy (name + namelen, &data[pos], l);
140 name[namelen + l] = '/';
142 namelen += l + 1;
143 pos += l;
146 name[namelen - 1] = '\0';
147 shishi_key_principal_set (key, name);
148 free (name);
151 /* Name_type */
153 uint32_t name_type /* not present if version 0x501 */
154 = data[pos] << 24 | data[pos+1] << 16
155 | data[pos+2] << 8 | data[pos+3];
156 pos += 4;
158 if (VERBOSENOISE (handle))
159 printf ("keytab nametype %d (0x%08x)\n", name_type, name_type);
162 /* Timestamp */
164 uint32_t timestamp = data[pos] << 24 | data[pos+1] << 16
165 | data[pos+2] << 8 | data[pos+3];
166 pos += 4;
168 if (VERBOSENOISE (handle))
169 printf ("keytab timestamp %u (0x%08ux)\n", timestamp, timestamp);
172 /* keyvno8 */
174 uint8_t vno8 = data[pos++];
176 if (VERBOSENOISE (handle))
177 printf ("keytab kvno8 %d (0x%02x)\n", vno8, vno8);
179 shishi_key_version_set (key, vno8);
182 /* key, keytype */
184 uint32_t keytype = data[pos] << 8 | data[pos+1];
185 pos += 2;
187 if (VERBOSENOISE (handle))
188 printf ("keytab keytype %d (0x%x)\n", keytype, keytype);
190 shishi_key_type_set (key, keytype);
193 /* key, length and data */
195 uint16_t keylen = data[pos] << 8 | data[pos+1];
196 pos += 2;
198 if (VERBOSENOISE (handle))
199 printf ("keytab keylen %d (0x%x) eq? %d\n", keylen, keylen,
200 shishi_key_length (key));
202 if (VERBOSENOISE (handle))
203 _shishi_hexprint (data + pos, keylen);
205 shishi_key_value_set (key, data + pos);
206 pos += keylen;
209 if (pos - entrystartpos < size + 4)
211 uint32_t vno /* only present if >= 4 bytes left in entry */
212 = data[pos] << 24 | data[pos+1] << 16
213 | data[pos+2] << 8 | data[pos+3];
214 pos += 4;
216 if (VERBOSENOISE (handle))
217 printf ("keytab kvno %d (0x%08x)\n", vno, vno);
219 shishi_key_version_set (key, vno);
222 if (VERBOSECRYPTONOISE (handle))
223 shishi_key_print (handle, stdout, key);
225 rc = shishi_keys_add (keys, key);
226 if (rc != SHISHI_OK)
227 goto done;
229 /* Go to next entry... */
230 entrystartpos += size + 4;
233 rc = SHISHI_OK;
235 done:
236 shishi_key_done (key);
238 return rc;
242 * shishi_keys_add_keytab_file:
243 * @handle: shishi handle as allocated by shishi_init().
244 * @filename: name of file to read.
245 * @keys: allocated key set to store keys in.
247 * Read keys from a MIT keytab data structure from a file, and add the
248 * keys to the key set.
250 * The format of keytab's is proprietary, and this function support
251 * the 0x0501 and 0x0502 formats. See the section The MIT Kerberos
252 * Keytab Binary File Format in the Shishi manual for a description of
253 * the reverse-engineered format.
255 * Returns: Returns %SHISHI_IO_ERROR if the file cannot be read,
256 * %SHISHI_KEYTAB_ERROR if the data cannot be parsed as a valid keytab
257 * structure, and %SHISHI_OK on success.
260 shishi_keys_add_keytab_file (Shishi * handle,
261 const char *filename,
262 Shishi_keys *keys)
264 size_t len;
265 char *keytab = read_file (filename, &len);
266 int rc;
268 if (!keytab)
269 return SHISHI_IO_ERROR;
271 rc = shishi_keys_add_keytab_mem (handle, keytab, len, keys);
273 free (keytab);
275 return rc;
279 * shishi_keys_from_keytab_mem:
280 * @handle: shishi handle as allocated by shishi_init().
281 * @data: constant memory buffer with keytab of @len size.
282 * @len: size of memory buffer with keytab data.
283 * @outkeys: pointer to key set that will be allocated and populated,
284 * must be deallocated by caller on succes.
286 * Create a new key set populated with keys from a MIT keytab data
287 * structure read from a memory block.
289 * The format of keytab's is proprietary, and this function support
290 * the 0x0501 and 0x0502 formats. See the section The MIT Kerberos
291 * Keytab Binary File Format in the Shishi manual for a description of
292 * the reverse-engineered format.
294 * Returns: Returns %SHISHI_KEYTAB_ERROR if the data does not
295 * represent a valid keytab structure, and %SHISHI_OK on success.
298 shishi_keys_from_keytab_mem (Shishi * handle,
299 const char *data, size_t len,
300 Shishi_keys **outkeys)
302 int rc;
304 rc = shishi_keys (handle, outkeys);
305 if (rc != SHISHI_OK)
306 return rc;
308 rc = shishi_keys_add_keytab_mem (handle, data, len, *outkeys);
309 if (rc != SHISHI_OK)
311 shishi_keys_done (outkeys);
312 return rc;
315 return SHISHI_OK;
319 * shishi_keys_from_keytab_file:
320 * @handle: shishi handle as allocated by shishi_init().
321 * @filename: name of file to read.
322 * @outkeys: pointer to key set that will be allocated and populated,
323 * must be deallocated by caller on succes.
325 * Create a new key set populated with keys from a MIT keytab data
326 * structure read from a file.
328 * The format of keytab's is proprietary, and this function support
329 * the 0x0501 and 0x0502 formats. See the section The MIT Kerberos
330 * Keytab Binary File Format in the Shishi manual for a description of
331 * the reverse-engineered format.
333 * Returns: Returns %SHISHI_IO_ERROR if the file cannot be read,
334 * %SHISHI_KEYTAB_ERROR if the data cannot be parsed as a valid keytab
335 * structure, and %SHISHI_OK on success.
338 shishi_keys_from_keytab_file (Shishi * handle,
339 const char *filename,
340 Shishi_keys **outkeys)
342 int rc;
344 rc = shishi_keys (handle, outkeys);
345 if (rc != SHISHI_OK)
346 return rc;
348 rc = shishi_keys_add_keytab_file (handle, filename, *outkeys);
349 if (rc != SHISHI_OK)
351 shishi_keys_done (outkeys);
352 return rc;
355 return SHISHI_OK;