Branch data Line data Source code
1 : : /* aprep.c --- AP-REP functions.
2 : : * Copyright (C) 2002, 2003, 2004, 2007 Simon Josefsson
3 : : *
4 : : * This file is part of Shishi.
5 : : *
6 : : * Shishi is free software; you can redistribute it and/or modify it it
7 : : * under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 3 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * Shishi is distributed in the hope that it will be useful, but but
12 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with Shishi; if not, see http://www.gnu.org/licenses or write
18 : : * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 : : * Floor, Boston, MA 02110-1301, USA
20 : : *
21 : : */
22 : :
23 : : #include "internal.h"
24 : :
25 : : /* Get _shishi_print_armored_data, etc. */
26 : : #include "diskio.h"
27 : :
28 : : #define SHISHI_APREP_DEFAULT_PVNO "5"
29 : : #define SHISHI_APREP_DEFAULT_PVNO_LEN 0
30 : : #define SHISHI_APREP_DEFAULT_MSG_TYPE "15" /* KRB_AP_REP */
31 : : #define SHISHI_APREP_DEFAULT_MSG_TYPE_LEN 0
32 : : #define SHISHI_APREP_DEFAULT_ENC_PART_ETYPE "0"
33 : : #define SHISHI_APREP_DEFAULT_ENC_PART_ETYPE_LEN 0
34 : : #define SHISHI_APREP_DEFAULT_ENC_PART_KVNO "0"
35 : : #define SHISHI_APREP_DEFAULT_ENC_PART_KVNO_LEN 0
36 : : #define SHISHI_APREP_DEFAULT_ENC_PART_CIPHER ""
37 : : #define SHISHI_APREP_DEFAULT_ENC_PART_CIPHER_LEN 0
38 : :
39 : : /**
40 : : * shishi_aprep:
41 : : * @handle: shishi handle as allocated by shishi_init().
42 : : *
43 : : * This function creates a new AP-REP, populated with some default
44 : : * values.
45 : : *
46 : : * Return value: Returns the authenticator or NULL on
47 : : * failure.
48 : : **/
49 : : Shishi_asn1
50 : 0 : shishi_aprep (Shishi * handle)
51 : : {
52 : : Shishi_asn1 node;
53 : : int res;
54 : :
55 : 0 : node = shishi_asn1_aprep (handle);
56 [ # # ]: 0 : if (!node)
57 : 0 : return NULL;
58 : :
59 : 0 : res = shishi_asn1_write (handle, node, "pvno",
60 : : SHISHI_APREP_DEFAULT_PVNO,
61 : : SHISHI_APREP_DEFAULT_PVNO_LEN);
62 [ # # ]: 0 : if (res != SHISHI_OK)
63 : 0 : goto error;
64 : :
65 : 0 : res = shishi_asn1_write (handle, node, "msg-type",
66 : : SHISHI_APREP_DEFAULT_MSG_TYPE,
67 : : SHISHI_APREP_DEFAULT_MSG_TYPE_LEN);
68 [ # # ]: 0 : if (res != SHISHI_OK)
69 : 0 : goto error;
70 : :
71 : 0 : res = shishi_asn1_write (handle, node, "enc-part.etype",
72 : : SHISHI_APREP_DEFAULT_ENC_PART_ETYPE,
73 : : SHISHI_APREP_DEFAULT_ENC_PART_ETYPE_LEN);
74 [ # # ]: 0 : if (res != SHISHI_OK)
75 : 0 : goto error;
76 : :
77 : 0 : res = shishi_asn1_write (handle, node, "enc-part.kvno",
78 : : SHISHI_APREP_DEFAULT_ENC_PART_KVNO,
79 : : SHISHI_APREP_DEFAULT_ENC_PART_KVNO_LEN);
80 [ # # ]: 0 : if (res != SHISHI_OK)
81 : 0 : goto error;
82 : :
83 : 0 : res = shishi_asn1_write (handle, node, "enc-part.cipher",
84 : : SHISHI_APREP_DEFAULT_ENC_PART_CIPHER,
85 : : SHISHI_APREP_DEFAULT_ENC_PART_CIPHER_LEN);
86 [ # # ]: 0 : if (res != SHISHI_OK)
87 : 0 : goto error;
88 : :
89 : 0 : return node;
90 : :
91 : : error:
92 : 0 : shishi_asn1_done (handle, node);
93 : 0 : return NULL;
94 : : }
95 : :
96 : : /**
97 : : * shishi_aprep_print:
98 : : * @handle: shishi handle as allocated by shishi_init().
99 : : * @fh: file handle open for writing.
100 : : * @aprep: AP-REP to print.
101 : : *
102 : : * Print ASCII armored DER encoding of AP-REP to file.
103 : : *
104 : : * Return value: Returns SHISHI_OK iff successful.
105 : : **/
106 : : int
107 : 0 : shishi_aprep_print (Shishi * handle, FILE * fh, Shishi_asn1 aprep)
108 : : {
109 : 0 : return _shishi_print_armored_data (handle, fh, aprep, "AP-REP", NULL);
110 : : }
111 : :
112 : : /**
113 : : * shishi_aprep_save:
114 : : * @handle: shishi handle as allocated by shishi_init().
115 : : * @fh: file handle open for writing.
116 : : * @aprep: AP-REP to save.
117 : : *
118 : : * Save DER encoding of AP-REP to file.
119 : : *
120 : : * Return value: Returns SHISHI_OK iff successful.
121 : : **/
122 : : int
123 : 0 : shishi_aprep_save (Shishi * handle, FILE * fh, Shishi_asn1 aprep)
124 : : {
125 : 0 : return _shishi_save_data (handle, fh, aprep, "AP-REP");
126 : : }
127 : :
128 : : /**
129 : : * shishi_aprep_to_file:
130 : : * @handle: shishi handle as allocated by shishi_init().
131 : : * @aprep: AP-REP to save.
132 : : * @filetype: input variable specifying type of file to be written,
133 : : * see Shishi_filetype.
134 : : * @filename: input variable with filename to write to.
135 : : *
136 : : * Write AP-REP to file in specified TYPE. The file will be
137 : : * truncated if it exists.
138 : : *
139 : : * Return value: Returns SHISHI_OK iff successful.
140 : : **/
141 : : int
142 : 0 : shishi_aprep_to_file (Shishi * handle, Shishi_asn1 aprep,
143 : : int filetype, const char *filename)
144 : : {
145 : : FILE *fh;
146 : : int res;
147 : :
148 [ # # ]: 0 : if (VERBOSE (handle))
149 : 0 : printf (_("Writing AP-REP to %s...\n"), filename);
150 : :
151 : 0 : fh = fopen (filename, "w");
152 [ # # ]: 0 : if (fh == NULL)
153 : 0 : return SHISHI_FOPEN_ERROR;
154 : :
155 [ # # ]: 0 : if (VERBOSE (handle))
156 [ # # ]: 0 : printf (_("Writing AP-REP in %s format...\n"),
157 : : filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
158 : :
159 [ # # ]: 0 : if (filetype == SHISHI_FILETYPE_TEXT)
160 : 0 : res = shishi_aprep_print (handle, fh, aprep);
161 : : else
162 : 0 : res = shishi_aprep_save (handle, fh, aprep);
163 [ # # ]: 0 : if (res != SHISHI_OK)
164 : 0 : return res;
165 : :
166 : 0 : res = fclose (fh);
167 [ # # ]: 0 : if (res != 0)
168 : 0 : return SHISHI_IO_ERROR;
169 : :
170 [ # # ]: 0 : if (VERBOSE (handle))
171 : 0 : printf (_("Writing AP-REP to %s...done\n"), filename);
172 : :
173 : 0 : return SHISHI_OK;
174 : : }
175 : :
176 : : /**
177 : : * shishi_aprep_parse:
178 : : * @handle: shishi handle as allocated by shishi_init().
179 : : * @fh: file handle open for reading.
180 : : * @aprep: output variable with newly allocated AP-REP.
181 : : *
182 : : * Read ASCII armored DER encoded AP-REP from file and populate given
183 : : * variable.
184 : : *
185 : : * Return value: Returns SHISHI_OK iff successful.
186 : : **/
187 : : int
188 : 0 : shishi_aprep_parse (Shishi * handle, FILE * fh, Shishi_asn1 * aprep)
189 : : {
190 : 0 : return _shishi_aprep_input (handle, fh, aprep, 0);
191 : : }
192 : :
193 : : /**
194 : : * shishi_aprep_read:
195 : : * @handle: shishi handle as allocated by shishi_init().
196 : : * @fh: file handle open for reading.
197 : : * @aprep: output variable with newly allocated AP-REP.
198 : : *
199 : : * Read DER encoded AP-REP from file and populate given variable.
200 : : *
201 : : * Return value: Returns SHISHI_OK iff successful.
202 : : **/
203 : : int
204 : 0 : shishi_aprep_read (Shishi * handle, FILE * fh, Shishi_asn1 * aprep)
205 : : {
206 : 0 : return _shishi_aprep_input (handle, fh, aprep, 1);
207 : : }
208 : :
209 : : /**
210 : : * shishi_aprep_from_file:
211 : : * @handle: shishi handle as allocated by shishi_init().
212 : : * @aprep: output variable with newly allocated AP-REP.
213 : : * @filetype: input variable specifying type of file to be read,
214 : : * see Shishi_filetype.
215 : : * @filename: input variable with filename to read from.
216 : : *
217 : : * Read AP-REP from file in specified TYPE.
218 : : *
219 : : * Return value: Returns SHISHI_OK iff successful.
220 : : **/
221 : : int
222 : 0 : shishi_aprep_from_file (Shishi * handle, Shishi_asn1 * aprep,
223 : : int filetype, const char *filename)
224 : : {
225 : : int res;
226 : : FILE *fh;
227 : :
228 [ # # ]: 0 : if (VERBOSE (handle))
229 : 0 : printf (_("Reading AP-REP from %s...\n"), filename);
230 : :
231 : 0 : fh = fopen (filename, "r");
232 [ # # ]: 0 : if (fh == NULL)
233 : 0 : return SHISHI_FOPEN_ERROR;
234 : :
235 [ # # ]: 0 : if (VERBOSE (handle))
236 [ # # ]: 0 : printf (_("Reading AP-REP in %s format...\n"),
237 : : filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
238 : :
239 [ # # ]: 0 : if (filetype == SHISHI_FILETYPE_TEXT)
240 : 0 : res = shishi_aprep_parse (handle, fh, aprep);
241 : : else
242 : 0 : res = shishi_aprep_read (handle, fh, aprep);
243 [ # # ]: 0 : if (res != SHISHI_OK)
244 : 0 : return res;
245 : :
246 : 0 : res = fclose (fh);
247 [ # # ]: 0 : if (res != 0)
248 : 0 : return SHISHI_IO_ERROR;
249 : :
250 [ # # ]: 0 : if (VERBOSE (handle))
251 : 0 : printf (_("Reading AP-REP from %s...done\n"), filename);
252 : :
253 : 0 : return SHISHI_OK;
254 : : }
255 : :
256 : : int
257 : 0 : shishi_aprep_enc_part_set (Shishi * handle,
258 : : Shishi_asn1 aprep,
259 : : int etype, const char *buf, size_t buflen)
260 : : {
261 : : int res;
262 : :
263 : 0 : res = shishi_asn1_write (handle, aprep, "enc-part.cipher", buf, buflen);
264 [ # # ]: 0 : if (res != SHISHI_OK)
265 : 0 : return res;
266 : :
267 : 0 : res = shishi_asn1_write_integer (handle, aprep, "enc-part.etype", etype);
268 [ # # ]: 0 : if (res != SHISHI_OK)
269 : 0 : return res;
270 : :
271 : 0 : return SHISHI_OK;
272 : : }
273 : :
274 : : int
275 : 0 : shishi_aprep_enc_part_add (Shishi * handle,
276 : : Shishi_asn1 aprep,
277 : : Shishi_asn1 encticketpart,
278 : : Shishi_asn1 encapreppart)
279 : : {
280 : : int res;
281 : : char *buf;
282 : : size_t buflen;
283 : : char *der;
284 : : size_t derlen;
285 : : Shishi_key *key;
286 : :
287 : 0 : res = shishi_encticketpart_get_key (handle, encticketpart, &key);
288 [ # # ]: 0 : if (res != SHISHI_OK)
289 : 0 : return res;
290 : :
291 : 0 : res = shishi_asn1_to_der (handle, encapreppart, &der, &derlen);
292 [ # # ]: 0 : if (res != SHISHI_OK)
293 : : {
294 : 0 : shishi_error_printf (handle, "Could not DER encode authenticator: %s\n",
295 : : shishi_strerror (res));
296 : 0 : return !SHISHI_OK;
297 : : }
298 : :
299 : 0 : der = xrealloc (der, derlen + 8);
300 : :
301 [ # # ]: 0 : while ((derlen % 8) != 0)
302 : : {
303 : 0 : der[derlen] = '\0';
304 : 0 : derlen++;
305 : : }
306 : :
307 : 0 : res = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ENCAPREPPART,
308 : : der, derlen, &buf, &buflen);
309 : :
310 : 0 : free (der);
311 : :
312 [ # # ]: 0 : if (res != SHISHI_OK)
313 : : {
314 : 0 : shishi_error_printf (handle, "APRep encryption failed\n");
315 : 0 : return res;
316 : : }
317 : :
318 : 0 : res = shishi_aprep_enc_part_set (handle, aprep, shishi_key_type (key),
319 : : buf, buflen);
320 : :
321 : 0 : free (buf);
322 : :
323 : 0 : return res;
324 : : }
325 : :
326 : : int
327 : 0 : shishi_aprep_enc_part_make (Shishi * handle,
328 : : Shishi_asn1 aprep,
329 : : Shishi_asn1 encapreppart,
330 : : Shishi_asn1 authenticator,
331 : : Shishi_asn1 encticketpart)
332 : : {
333 : : int res;
334 : :
335 : 0 : res = shishi_encapreppart_time_copy (handle, encapreppart, authenticator);
336 [ # # ]: 0 : if (res != SHISHI_OK)
337 : : {
338 : 0 : shishi_error_printf (handle, "Could not copy time: %s\n",
339 : : shishi_error (handle));
340 : 0 : return res;
341 : : }
342 : :
343 : 0 : res = shishi_aprep_enc_part_add (handle, aprep, encticketpart,
344 : : encapreppart);
345 [ # # ]: 0 : if (res != SHISHI_OK)
346 : : {
347 : 0 : shishi_error_printf (handle, "Could not add encapreppart: %s\n",
348 : : shishi_error (handle));
349 : 0 : return res;
350 : : }
351 : :
352 : 0 : return SHISHI_OK;
353 : : }
354 : :
355 : : /**
356 : : * shishi_aprep_get_enc_part_etype:
357 : : * @handle: shishi handle as allocated by shishi_init().
358 : : * @aprep: AP-REP variable to get value from.
359 : : * @etype: output variable that holds the value.
360 : : *
361 : : * Extract AP-REP.enc-part.etype.
362 : : *
363 : : * Return value: Returns SHISHI_OK iff successful.
364 : : **/
365 : : int
366 : 0 : shishi_aprep_get_enc_part_etype (Shishi * handle,
367 : : Shishi_asn1 aprep, int32_t * etype)
368 : : {
369 : 0 : return shishi_asn1_read_int32 (handle, aprep, "enc-part.etype", etype);
370 : : }
371 : :
372 : : int
373 : 0 : shishi_aprep_decrypt (Shishi * handle,
374 : : Shishi_asn1 aprep,
375 : : Shishi_key * key,
376 : : int keyusage, Shishi_asn1 * encapreppart)
377 : : {
378 : : int res;
379 : : int i;
380 : : char *buf;
381 : : size_t buflen;
382 : : char *cipher;
383 : : size_t cipherlen;
384 : : int etype;
385 : :
386 : 0 : res = shishi_aprep_get_enc_part_etype (handle, aprep, &etype);
387 [ # # ]: 0 : if (res != SHISHI_OK)
388 : 0 : return res;
389 : :
390 [ # # ]: 0 : if (etype != shishi_key_type (key))
391 : 0 : return SHISHI_APREP_BAD_KEYTYPE;
392 : :
393 : 0 : res = shishi_asn1_read (handle, aprep, "enc-part.cipher",
394 : : &cipher, &cipherlen);
395 [ # # ]: 0 : if (res != SHISHI_OK)
396 : 0 : return res;
397 : :
398 : 0 : res = shishi_decrypt (handle, key, keyusage, cipher, cipherlen,
399 : : &buf, &buflen);
400 : 0 : free (cipher);
401 [ # # ]: 0 : if (res != SHISHI_OK)
402 : : {
403 : 0 : shishi_error_printf (handle,
404 : : "APRep decryption failed, wrong password?\n");
405 : 0 : return res;
406 : : }
407 : :
408 : : /* The crypto is so 1980; no length indicator. Trim off pad bytes
409 : : until we can parse it. */
410 [ # # ]: 0 : for (i = 0; i < 8; i++)
411 : : {
412 [ # # ]: 0 : if (VERBOSEASN1 (handle))
413 : 0 : printf ("Trying with %d pad in enckdcrep...\n", i);
414 : :
415 : 0 : *encapreppart = shishi_der2asn1_encapreppart (handle, &buf[0],
416 : : buflen - i);
417 [ # # ]: 0 : if (*encapreppart != NULL)
418 : 0 : break;
419 : : }
420 : :
421 [ # # ]: 0 : if (*encapreppart == NULL)
422 : : {
423 : 0 : shishi_error_printf (handle, "Could not DER decode EncAPRepPart. "
424 : : "Password probably correct (decrypt ok) though\n");
425 : 0 : return SHISHI_ASN1_ERROR;
426 : : }
427 : :
428 : 0 : return SHISHI_OK;
429 : : }
430 : :
431 : : int
432 : 0 : shishi_aprep_verify (Shishi * handle,
433 : : Shishi_asn1 authenticator, Shishi_asn1 encapreppart)
434 : : {
435 : : char *authenticatorctime;
436 : : char *encapreppartctime;
437 : : uint32_t authenticatorcusec, encapreppartcusec;
438 : : int res;
439 : : int different;
440 : :
441 : : /*
442 : : 3.2.5. Receipt of KRB_AP_REP message
443 : :
444 : : If a KRB_AP_REP message is returned, the client uses the session key from
445 : : the credentials obtained for the server[3.10] to decrypt the message, and
446 : : verifies that the timestamp and microsecond fields match those in the
447 : : Authenticator it sent to the server. If they match, then the client is
448 : : assured that the server is genuine. The sequence number and subkey (if
449 : : present) are retained for later use.
450 : :
451 : : */
452 : :
453 : 0 : res = shishi_authenticator_ctime (handle, authenticator,
454 : : &authenticatorctime);
455 [ # # ]: 0 : if (res != SHISHI_OK)
456 : 0 : return res;
457 : :
458 : 0 : res = shishi_authenticator_cusec_get (handle, authenticator,
459 : : &authenticatorcusec);
460 [ # # ]: 0 : if (res != SHISHI_OK)
461 : 0 : return res;
462 : :
463 : 0 : res = shishi_encapreppart_ctime (handle, encapreppart, &encapreppartctime);
464 [ # # ]: 0 : if (res != SHISHI_OK)
465 : 0 : return res;
466 : :
467 : 0 : res = shishi_encapreppart_cusec_get (handle, encapreppart,
468 : : &encapreppartcusec);
469 [ # # ]: 0 : if (res != SHISHI_OK)
470 : 0 : return res;
471 : :
472 [ # # ]: 0 : if (VERBOSE (handle))
473 : : {
474 : 0 : printf ("authenticator cusec %08x ctime %s\n", authenticatorcusec,
475 : : authenticatorctime);
476 : 0 : printf ("encapreppart cusec %08x ctime %s\n", encapreppartcusec,
477 : : encapreppartctime);
478 : : }
479 : :
480 [ # # ][ # # ]: 0 : different = authenticatorcusec != encapreppartcusec ||
481 : 0 : strcmp (authenticatorctime, encapreppartctime) != 0;
482 : :
483 : 0 : free (authenticatorctime);
484 : 0 : free (encapreppartctime);
485 : :
486 [ # # ]: 0 : if (different)
487 : 0 : return SHISHI_APREP_VERIFY_FAILED;
488 : :
489 : 0 : return SHISHI_OK;
490 : : }
|