1 /* diskio.c --- Read and write data structures from disk.
2 * Copyright (C) 2002-2013 Simon Josefsson
3 *
4 * This file is part of Shishi.
5 *
6 * Shishi is free software; you can redistribute it and/or modify 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
12 * 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.
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 /* XXX oh, please, rewrite this file. */
24
25 #include "internal.h"
26 #include "diskio.h"
27
28 #define HEADERBEG "-----BEGIN SHISHI %s-----"
29 #define HEADEREND "-----END SHISHI %s-----"
30
31 #define BUFSIZE 5000
32
33 /*
34 * Note to self: if you change any *print* function, remember to change
35 * the corresponding *parse* function too.
36 *
37 */
38
39 static char *
armor_data(const char * data,size_t len,const char * armortype,const char * armorheaders)40 armor_data (const char *data, size_t len,
41 const char *armortype, const char *armorheaders)
42 {
43 /* Must be a multiple of 4. */
44 #define WRAP_COL 64
45 char *armorbegin, *armorend;
46 char *b64data, *out;
47 size_t wrapb64len =
48 BASE64_LENGTH (len) + BASE64_LENGTH (len) / WRAP_COL + 1;
49 size_t i;
50
51 b64data = xmalloc (wrapb64len + 1);
52
53 for (i = 0; i <= BASE64_LENGTH (len) / WRAP_COL; i++)
54 {
55 size_t readpos = i * WRAP_COL * 3 / 4;
56 size_t nread = WRAP_COL * 3 / 4;
57 size_t storepos = i * WRAP_COL + i;
58 size_t nstore = WRAP_COL;
59
60 if (readpos >= len)
61 break;
62
63 if (readpos + nread >= len)
64 {
65 nread = len - readpos;
66 nstore = BASE64_LENGTH (nread);
67 }
68
69 base64_encode (data + readpos, nread, b64data + storepos, nstore);
70 b64data[storepos + nstore] = '\n';
71 b64data[storepos + nstore + 1] = '\0';
72
73 #if 0
74 printf ("alloc %d len %d curlen %d "
75 "readpos %d nread %d storepos %d nstore %d\n",
76 wrapb64len + 1, len, strlen (b64data),
77 readpos, nread, storepos, nstore);
78 #endif
79 }
80
81 armorbegin = xasprintf (HEADERBEG, armortype);
82 armorend = xasprintf (HEADEREND, armortype);
83
84 out = xasprintf ("%s\n%s%s%s%s\n",
85 armorbegin,
86 armorheaders ? armorheaders : "",
87 armorheaders ? "\n" : "", b64data, armorend);
88
89 free (b64data);
90 free (armorend);
91 free (armorbegin);
92
93 return out;
94 }
95
96 static char *
armor_asn1(Shishi * handle,Shishi_asn1 asn1,const char * armortype,const char * armorheaders)97 armor_asn1 (Shishi * handle,
98 Shishi_asn1 asn1, const char *armortype, const char *armorheaders)
99 {
100 char *der;
101 size_t derlen;
102 char *out;
103 int rc;
104
105 rc = shishi_asn1_to_der (handle, asn1, &der, &derlen);
106 if (rc != SHISHI_OK)
107 return NULL;
108
109 out = armor_data (der, derlen, armortype, armorheaders);
110
111 free (der);
112
113 return out;
114 }
115
116 int
_shishi_print_armored_data(Shishi * handle,FILE * fh,Shishi_asn1 asn1,const char * asn1type,char * headers)117 _shishi_print_armored_data (Shishi * handle,
118 FILE * fh,
119 Shishi_asn1 asn1,
120 const char *asn1type, char *headers)
121 {
122 char *data = armor_asn1 (handle, asn1, asn1type, headers);
123
124 shishi_asn1_print (handle, asn1, fh);
125
126 fprintf (fh, "%s\n", data);
127
128 free (data);
129
130 return SHISHI_OK;
131 }
132
133 int
_shishi_save_data(Shishi * handle,FILE * fh,Shishi_asn1 asn1,const char * asn1type)134 _shishi_save_data (Shishi * handle, FILE * fh, Shishi_asn1 asn1,
135 const char *asn1type)
136 {
137 char *der;
138 size_t derlen;
139 size_t i;
140 int res;
141
142 res = shishi_asn1_to_der_field (handle, asn1, asn1type, &der, &derlen);
143 if (res != SHISHI_OK)
144 return res;
145
146 i = fwrite (der, sizeof (der[0]), derlen, fh);
147 if (i != derlen)
148 return SHISHI_IO_ERROR;
149
150 return SHISHI_OK;
151 }
152
153 int
shishi_padata_print(Shishi * handle,FILE * fh,Shishi_asn1 padata)154 shishi_padata_print (Shishi * handle, FILE * fh, Shishi_asn1 padata)
155 {
156 return _shishi_print_armored_data (handle, fh, padata, "PA-DATA", NULL);
157 }
158
159 int
shishi_methoddata_print(Shishi * handle,FILE * fh,Shishi_asn1 methoddata)160 shishi_methoddata_print (Shishi * handle, FILE * fh, Shishi_asn1 methoddata)
161 {
162 return _shishi_print_armored_data (handle, fh, methoddata,
163 "METHOD-DATA", NULL);
164 }
165
166 int
shishi_etype_info_print(Shishi * handle,FILE * fh,Shishi_asn1 etypeinfo)167 shishi_etype_info_print (Shishi * handle, FILE * fh, Shishi_asn1 etypeinfo)
168 {
169 return _shishi_print_armored_data (handle, fh, etypeinfo,
170 "ETYPE-INFO", NULL);
171 }
172
173 int
shishi_etype_info2_print(Shishi * handle,FILE * fh,Shishi_asn1 etypeinfo2)174 shishi_etype_info2_print (Shishi * handle, FILE * fh, Shishi_asn1 etypeinfo2)
175 {
176 return _shishi_print_armored_data (handle, fh, etypeinfo2,
177 "ETYPE-INFO2", NULL);
178 }
179
180 int
shishi_enckdcreppart_print(Shishi * handle,FILE * fh,Shishi_asn1 enckdcreppart)181 shishi_enckdcreppart_print (Shishi * handle,
182 FILE * fh, Shishi_asn1 enckdcreppart)
183 {
184 return _shishi_print_armored_data (handle, fh, enckdcreppart,
185 "EncKDCRepPart", NULL);
186 }
187
188 int
shishi_enckdcreppart_save(Shishi * handle,FILE * fh,Shishi_asn1 enckdcreppart)189 shishi_enckdcreppart_save (Shishi * handle,
190 FILE * fh, Shishi_asn1 enckdcreppart)
191 {
192 return _shishi_save_data (handle, fh, enckdcreppart, "EncKDCRepPart");
193 }
194
195 int
shishi_ticket_save(Shishi * handle,FILE * fh,Shishi_asn1 ticket)196 shishi_ticket_save (Shishi * handle, FILE * fh, Shishi_asn1 ticket)
197 {
198 return _shishi_save_data (handle, fh, ticket, "Ticket");
199 }
200
201 int
shishi_ticket_print(Shishi * handle,FILE * fh,Shishi_asn1 ticket)202 shishi_ticket_print (Shishi * handle, FILE * fh, Shishi_asn1 ticket)
203 {
204 return _shishi_print_armored_data (handle, fh, ticket, "Ticket", NULL);
205 }
206
207 int
shishi_encticketpart_print(Shishi * handle,FILE * fh,Shishi_asn1 encticketpart)208 shishi_encticketpart_print (Shishi * handle, FILE * fh,
209 Shishi_asn1 encticketpart)
210 {
211 return _shishi_print_armored_data (handle, fh, encticketpart,
212 "EncTicketPart", NULL);
213 }
214
215 static int
_shishi_read_armored_data(Shishi * handle,FILE * fh,char * buffer,size_t len,const char * tag)216 _shishi_read_armored_data (Shishi * handle,
217 FILE * fh, char *buffer, size_t len,
218 const char *tag)
219 {
220 char *line = NULL;
221 size_t linelen = 0;
222 char *armorbegin, *armorend;
223 int phase = 0;
224 int res = SHISHI_OK;
225
226 armorbegin = xasprintf (HEADERBEG, tag);
227 armorend = xasprintf (HEADEREND, tag);
228
229 while (getline (&line, &linelen, fh) > 0)
230 {
231 while (*line && strchr ("\n\r\t ", line[strlen (line) - 1]))
232 line[strlen (line) - 1] = '\0';
233
234 if (phase == 1)
235 {
236 if (strcmp (line, armorend) == 0)
237 {
238 phase = 2;
239 break;
240 }
241 }
242 else
243 {
244 if (strcmp (line, armorbegin) == 0)
245 phase = 1;
246 continue;
247 }
248
249 if (len <= strlen (line))
250 {
251 res = SHISHI_TOO_SMALL_BUFFER;
252 goto done;
253 }
254
255 memcpy (buffer, line, strlen (line));
256 buffer += strlen (line);
257 len -= strlen (line);
258 }
259
260 if (len == 0)
261 res = SHISHI_TOO_SMALL_BUFFER;
262 else
263 *buffer = '\0';
264
265 if (phase != 2)
266 res = SHISHI_IO_ERROR;
267
268 done:
269
270 free (armorbegin);
271 free (armorend);
272 free (line);
273
274 return res;
275 }
276
277 static int
_shishi_ticket_input(Shishi * handle,FILE * fh,Shishi_asn1 * ticket,int type)278 _shishi_ticket_input (Shishi * handle,
279 FILE * fh, Shishi_asn1 * ticket, int type)
280 {
281 char der[BUFSIZE];
282 size_t derlen;
283 char b64der[BUFSIZE];
284 size_t b64len = 0;
285 int res;
286
287 if (type == 0)
288 {
289 b64len = sizeof (b64der);
290 res = _shishi_read_armored_data (handle, fh, b64der, b64len, "Ticket");
291 if (res != SHISHI_OK)
292 {
293 shishi_error_printf (handle, "armor data read fail\n");
294 return res;
295 }
296
297 derlen = sizeof (der);
298 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
299 return SHISHI_BASE64_ERROR;
300 }
301 else
302 {
303 derlen =
304 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
305 if (derlen <= 0 || !feof (fh) || ferror (fh))
306 {
307 shishi_error_printf (handle,
308 "Error reading from file (got %ld bytes)...",
309 derlen);
310 return !SHISHI_OK;
311 }
312 }
313
314 *ticket = shishi_der2asn1_ticket (handle, der, derlen);
315 if (*ticket == NULL)
316 return SHISHI_ASN1_ERROR;
317
318 return SHISHI_OK;
319 }
320
321 int
shishi_ticket_parse(Shishi * handle,FILE * fh,Shishi_asn1 * ticket)322 shishi_ticket_parse (Shishi * handle, FILE * fh, Shishi_asn1 * ticket)
323 {
324 return _shishi_ticket_input (handle, fh, ticket, 0);
325 }
326
327 int
shishi_ticket_read(Shishi * handle,FILE * fh,Shishi_asn1 * ticket)328 shishi_ticket_read (Shishi * handle, FILE * fh, Shishi_asn1 * ticket)
329 {
330 return _shishi_ticket_input (handle, fh, ticket, 1);
331 }
332
333 static int
_shishi_enckdcreppart_input(Shishi * handle,FILE * fh,Shishi_asn1 * enckdcreppart,int type)334 _shishi_enckdcreppart_input (Shishi * handle,
335 FILE * fh, Shishi_asn1 * enckdcreppart, int type)
336 {
337 char der[BUFSIZE];
338 size_t derlen;
339 char b64der[BUFSIZE];
340 size_t b64len = 0;
341 int res;
342
343 if (type == 0)
344 {
345 b64len = sizeof (b64der);
346 res = _shishi_read_armored_data (handle, fh,
347 b64der, b64len, "EncKDCRepPart");
348 if (res != SHISHI_OK)
349 {
350 shishi_error_printf (handle, "armor data read fail\n");
351 return res;
352 }
353
354 derlen = sizeof (der);
355 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
356 return SHISHI_BASE64_ERROR;
357 }
358 else
359 {
360 derlen =
361 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
362 if (derlen <= 0 || !feof (fh) || ferror (fh))
363 {
364 shishi_error_printf (handle,
365 "Error reading from file (got %ld bytes)...",
366 derlen);
367 return !SHISHI_OK;
368 }
369 }
370
371 *enckdcreppart = shishi_der2asn1_encasreppart (handle, der, derlen);
372 if (*enckdcreppart == NULL)
373 {
374 shishi_error_printf (handle, "Could not DER decode Encasreppart: %s",
375 shishi_error (handle));
376
377 *enckdcreppart = shishi_der2asn1_enctgsreppart (handle, der, derlen);
378 if (*enckdcreppart == NULL)
379 {
380 shishi_error_printf (handle,
381 "Could not DER decode Enctgsreppart: %s",
382 shishi_error (handle));
383
384 *enckdcreppart =
385 shishi_der2asn1_enckdcreppart (handle, der, derlen);
386 if (*enckdcreppart == NULL)
387 {
388 shishi_error_printf (handle,
389 "Could not DER decode Enckdcreppart: %s",
390 shishi_error (handle));
391 return !SHISHI_OK;
392 }
393 }
394 }
395
396 return SHISHI_OK;
397 }
398
399 int
shishi_enckdcreppart_parse(Shishi * handle,FILE * fh,Shishi_asn1 * enckdcreppart)400 shishi_enckdcreppart_parse (Shishi * handle,
401 FILE * fh, Shishi_asn1 * enckdcreppart)
402 {
403 return _shishi_enckdcreppart_input (handle, fh, enckdcreppart, 0);
404 }
405
406 int
shishi_enckdcreppart_read(Shishi * handle,FILE * fh,Shishi_asn1 * enckdcreppart)407 shishi_enckdcreppart_read (Shishi * handle,
408 FILE * fh, Shishi_asn1 * enckdcreppart)
409 {
410 return _shishi_enckdcreppart_input (handle, fh, enckdcreppart, 1);
411 }
412
413 int
_shishi_kdcreq_input(Shishi * handle,FILE * fh,Shishi_asn1 * asreq,int type)414 _shishi_kdcreq_input (Shishi * handle, FILE * fh, Shishi_asn1 * asreq,
415 int type)
416 {
417 char der[BUFSIZE];
418 size_t derlen;
419 char b64der[BUFSIZE];
420 size_t b64len = 0;
421 int res;
422
423 if (type == 0)
424 {
425 b64len = sizeof (b64der);
426 res = _shishi_read_armored_data (handle, fh, b64der, b64len, "KDC-REQ");
427 if (res != SHISHI_OK)
428 {
429 shishi_error_printf (handle, "armor data read fail\n");
430 return res;
431 }
432
433 derlen = sizeof (der);
434 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
435 return SHISHI_BASE64_ERROR;
436 }
437 else
438 {
439 derlen =
440 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
441 if (derlen <= 0 || !feof (fh) || ferror (fh))
442 {
443 shishi_error_printf (handle,
444 "Error reading from file (got %ld bytes)...",
445 derlen);
446 return !SHISHI_OK;
447 }
448 }
449
450 *asreq = shishi_der2asn1_asreq (handle, der, derlen);
451 if (*asreq == NULL)
452 {
453 printf ("bad asreq magic\n");
454 shishi_error_printf (handle, "Could not DER decode AS-REQ\n");
455
456 *asreq = shishi_der2asn1_tgsreq (handle, der, derlen);
457 if (*asreq == NULL)
458 {
459 printf ("bad tgsreq magic\n");
460 shishi_error_printf (handle, "Could not DER decode TGS-REQ\n");
461
462 *asreq = shishi_der2asn1_kdcreq (handle, der, derlen);
463 if (*asreq == NULL)
464 {
465 printf ("bad kdcreq magic\n");
466 shishi_error_printf (handle, "Could not DER decode KDC-REQ\n");
467
468 return !SHISHI_OK;
469 }
470 }
471 }
472
473 return SHISHI_OK;
474 }
475
476 int
_shishi_kdcrep_input(Shishi * handle,FILE * fh,Shishi_asn1 * asrep,int type)477 _shishi_kdcrep_input (Shishi * handle, FILE * fh, Shishi_asn1 * asrep,
478 int type)
479 {
480 char der[BUFSIZE];
481 size_t derlen;
482 char b64der[BUFSIZE];
483 size_t b64len = 0;
484 int res;
485
486 if (type == 0)
487 {
488 b64len = sizeof (b64der);
489 res = _shishi_read_armored_data (handle, fh, b64der, b64len, "KDC-REP");
490 if (res != SHISHI_OK)
491 {
492 shishi_error_printf (handle, "armor data read fail\n");
493 return res;
494 }
495
496 derlen = sizeof (der);
497 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
498 return SHISHI_BASE64_ERROR;
499 }
500 else
501 {
502 derlen =
503 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
504 if (derlen <= 0 || !feof (fh) || ferror (fh))
505 {
506 shishi_error_printf (handle,
507 "Error reading from file (got %ld bytes)...",
508 derlen);
509 return !SHISHI_OK;
510 }
511 }
512
513 *asrep = shishi_der2asn1_asrep (handle, der, derlen);
514 if (*asrep == NULL)
515 {
516 *asrep = shishi_der2asn1_tgsrep (handle, der, derlen);
517 if (*asrep == NULL)
518 {
519 printf ("Could not DER decode KDC-REP: %s\n",
520 shishi_error (handle));
521 printf ("Parsing AS/TGS-REP as KDC-REP (bug work around)\n");
522
523 *asrep = shishi_der2asn1_kdcrep (handle, der, derlen);
524 if (*asrep == NULL)
525 {
526 fprintf (stderr, "Could not DER decode KDC-REP: %s\n",
527 shishi_error (handle));
528 return !SHISHI_OK;
529 }
530
531 fprintf (stderr, "Bug workaround code successful...\n");
532 }
533 }
534
535 return SHISHI_OK;
536 }
537
538 int
_shishi_apreq_input(Shishi * handle,FILE * fh,Shishi_asn1 * apreq,int type)539 _shishi_apreq_input (Shishi * handle, FILE * fh, Shishi_asn1 * apreq,
540 int type)
541 {
542 char der[BUFSIZE];
543 size_t derlen;
544 char b64der[BUFSIZE];
545 size_t b64len = 0;
546 int res;
547
548 if (type == 0)
549 {
550 b64len = sizeof (b64der);
551 res = _shishi_read_armored_data (handle, fh, b64der, b64len, "AP-REQ");
552 if (res != SHISHI_OK)
553 {
554 shishi_error_printf (handle, "armor data read fail\n");
555 return res;
556 }
557
558 derlen = sizeof (der);
559 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
560 return SHISHI_BASE64_ERROR;
561 }
562 else
563 {
564 derlen =
565 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
566 if (derlen <= 0 || !feof (fh) || ferror (fh))
567 {
568 shishi_error_printf (handle,
569 "Error reading from file (got %ld bytes)...",
570 derlen);
571 return !SHISHI_OK;
572 }
573 }
574
575 *apreq = shishi_der2asn1_apreq (handle, der, derlen);
576 if (*apreq == NULL)
577 {
578 printf ("bad magic %s\n", shishi_error (handle));
579 shishi_error_printf (handle, "Could not DER decode AP-REQ\n");
580
581 return !SHISHI_OK;
582 }
583
584 return SHISHI_OK;
585 }
586
587 int
_shishi_aprep_input(Shishi * handle,FILE * fh,Shishi_asn1 * aprep,int type)588 _shishi_aprep_input (Shishi * handle, FILE * fh, Shishi_asn1 * aprep,
589 int type)
590 {
591 char der[BUFSIZE];
592 size_t derlen;
593 char b64der[BUFSIZE];
594 size_t b64len = 0;
595 int res;
596
597 if (type == 0)
598 {
599 b64len = sizeof (b64der);
600 res = _shishi_read_armored_data (handle, fh, b64der, b64len, "AP-REP");
601 if (res != SHISHI_OK)
602 {
603 shishi_error_printf (handle, "armor data read fail\n");
604 return res;
605 }
606
607 derlen = sizeof (der);
608 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
609 return SHISHI_BASE64_ERROR;
610 }
611 else
612 {
613 derlen =
614 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
615 if (derlen <= 0 || !feof (fh) || ferror (fh))
616 {
617 shishi_error_printf (handle,
618 "Error reading from file (got %ld bytes)...",
619 derlen);
620 return !SHISHI_OK;
621 }
622 }
623
624 *aprep = shishi_der2asn1_aprep (handle, der, derlen);
625 if (*aprep == NULL)
626 {
627 printf ("bad magic %s\n", shishi_error (handle));
628 shishi_error_printf (handle, "Could not DER decode AP-REP\n");
629
630 return !SHISHI_OK;
631 }
632
633 return SHISHI_OK;
634 }
635
636 int
_shishi_encapreppart_input(Shishi * handle,FILE * fh,Shishi_asn1 * encapreppart,int type)637 _shishi_encapreppart_input (Shishi * handle, FILE * fh,
638 Shishi_asn1 * encapreppart, int type)
639 {
640 char der[BUFSIZE];
641 size_t derlen;
642 char b64der[BUFSIZE];
643 size_t b64len = 0;
644 int res;
645
646 if (type == 0)
647 {
648 b64len = sizeof (b64der);
649 res =
650 _shishi_read_armored_data (handle, fh, b64der, b64len,
651 "EncAPRepPart");
652 if (res != SHISHI_OK)
653 {
654 shishi_error_printf (handle, "armor data read fail\n");
655 return res;
656 }
657
658 derlen = sizeof (der);
659 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
660 return SHISHI_BASE64_ERROR;
661 }
662 else
663 {
664 derlen =
665 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
666 if (derlen <= 0 || !feof (fh) || ferror (fh))
667 {
668 shishi_error_printf (handle,
669 "Error reading from file (got %ld bytes)...",
670 derlen);
671 return !SHISHI_OK;
672 }
673 }
674
675 *encapreppart = shishi_der2asn1_encapreppart (handle, der, derlen);
676 if (*encapreppart == NULL)
677 {
678 printf ("bad magic %s\n", shishi_error (handle));
679 shishi_error_printf (handle, "Could not DER decode EncAPRepPart\n");
680
681 return !SHISHI_OK;
682 }
683
684 return SHISHI_OK;
685 }
686
687 int
_shishi_authenticator_input(Shishi * handle,FILE * fh,Shishi_asn1 * authenticator,int type)688 _shishi_authenticator_input (Shishi * handle,
689 FILE * fh, Shishi_asn1 * authenticator, int type)
690 {
691 char der[BUFSIZE];
692 size_t derlen;
693 char b64der[BUFSIZE];
694 size_t b64len = 0;
695 int res;
696
697 if (type == 0)
698 {
699 b64len = sizeof (b64der);
700 res = _shishi_read_armored_data (handle, fh, b64der, b64len,
701 "Authenticator");
702 if (res != SHISHI_OK)
703 {
704 shishi_error_printf (handle, "armor data read fail\n");
705 return res;
706 }
707
708 derlen = sizeof (der);
709 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
710 return SHISHI_BASE64_ERROR;
711 }
712 else
713 {
714 derlen =
715 fread (der, sizeof (der[0]), sizeof (der) / sizeof (der[0]), fh);
716 if (derlen <= 0 || !feof (fh) || ferror (fh))
717 {
718 shishi_error_printf (handle,
719 "Error reading from file (got %ld bytes)...",
720 derlen);
721 return !SHISHI_OK;
722 }
723 }
724
725 *authenticator = shishi_der2asn1_authenticator (handle, der, derlen);
726 if (*authenticator == NULL)
727 {
728 printf ("bad magic %s\n", shishi_error (handle));
729 shishi_error_printf (handle, "Could not DER decode AP-REQ\n");
730
731 return !SHISHI_OK;
732 }
733
734 return SHISHI_OK;
735 }
736
737 int
_shishi_krberror_input(Shishi * handle,FILE * fh,Shishi_asn1 * krberror,int type)738 _shishi_krberror_input (Shishi * handle,
739 FILE * fh, Shishi_asn1 * krberror, int type)
740 {
741 char der[BUFSIZE];
742 size_t derlen;
743 char b64der[BUFSIZE];
744 size_t b64len = 0;
745 int res;
746
747 if (type == 0)
748 {
749 b64len = sizeof (b64der);
750 res = _shishi_read_armored_data (handle, fh, b64der, b64len,
751 "KRB-ERROR");
752 if (res != SHISHI_OK)
753 {
754 shishi_error_printf (handle, "armor data read fail\n");
755 return res;
756 }
757
758 derlen = sizeof (der);
759 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
760 return SHISHI_BASE64_ERROR;
761 }
762 else
763 {
764 derlen = fread (der, sizeof (der[0]),
765 sizeof (der) / sizeof (der[0]), fh);
766 if (derlen <= 0 || !feof (fh) || ferror (fh))
767 {
768 shishi_error_printf (handle,
769 "Error reading from file (got %ld bytes)...",
770 derlen);
771 return !SHISHI_OK;
772 }
773 }
774
775 *krberror = shishi_der2asn1_krberror (handle, der, derlen);
776 if (*krberror == NULL)
777 {
778 printf ("bad magic %s\n", shishi_error (handle));
779 shishi_error_printf (handle, "Could not DER decode AP-REQ\n");
780
781 return !SHISHI_OK;
782 }
783
784 return SHISHI_OK;
785 }
786
787 int
_shishi_safe_input(Shishi * handle,FILE * fh,Shishi_asn1 * safe,int type)788 _shishi_safe_input (Shishi * handle, FILE * fh, Shishi_asn1 * safe, int type)
789 {
790 char der[BUFSIZE];
791 size_t derlen;
792 char b64der[BUFSIZE];
793 size_t b64len = 0;
794 int res;
795
796 if (type == 0)
797 {
798 b64len = sizeof (b64der);
799 res = _shishi_read_armored_data (handle, fh, b64der, b64len,
800 "KRB-SAFE");
801 if (res != SHISHI_OK)
802 {
803 shishi_error_printf (handle, "armor data read fail\n");
804 return res;
805 }
806
807 derlen = sizeof (der);
808 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
809 return SHISHI_BASE64_ERROR;
810 }
811 else
812 {
813 derlen = fread (der, sizeof (der[0]),
814 sizeof (der) / sizeof (der[0]), fh);
815 if (derlen <= 0 || !feof (fh) || ferror (fh))
816 {
817 shishi_error_printf (handle,
818 "Error reading from file (got %ld bytes)...",
819 derlen);
820 return !SHISHI_OK;
821 }
822 }
823
824 *safe = shishi_der2asn1_krbsafe (handle, der, derlen);
825 if (*safe == NULL)
826 {
827 printf ("bad magic %s\n", shishi_error (handle));
828 shishi_error_printf (handle, "Could not DER decode KRB-SAFE\n");
829
830 return !SHISHI_OK;
831 }
832
833 return SHISHI_OK;
834 }
835
836 int
_shishi_priv_input(Shishi * handle,FILE * fh,Shishi_asn1 * priv,int type)837 _shishi_priv_input (Shishi * handle, FILE * fh, Shishi_asn1 * priv, int type)
838 {
839 char der[BUFSIZE];
840 size_t derlen;
841 char b64der[BUFSIZE];
842 size_t b64len = 0;
843 int res;
844
845 if (type == 0)
846 {
847 b64len = sizeof (b64der);
848 res = _shishi_read_armored_data (handle, fh, b64der, b64len,
849 "KRB-PRIV");
850 if (res != SHISHI_OK)
851 {
852 shishi_error_printf (handle, "armor data read fail\n");
853 return res;
854 }
855
856 derlen = sizeof (der);
857 if (!base64_decode (b64der, strlen (b64der), der, &derlen))
858 return SHISHI_BASE64_ERROR;
859 }
860 else
861 {
862 derlen = fread (der, sizeof (der[0]),
863 sizeof (der) / sizeof (der[0]), fh);
864 if (derlen <= 0 || !feof (fh) || ferror (fh))
865 {
866 shishi_error_printf (handle,
867 "Error reading from file (got %ld bytes)...",
868 derlen);
869 return !SHISHI_OK;
870 }
871 }
872
873 *priv = shishi_der2asn1_priv (handle, der, derlen);
874 if (*priv == NULL)
875 {
876 printf ("bad magic %s\n", shishi_error (handle));
877 shishi_error_printf (handle, "Could not DER decode KRB-PRIV\n");
878
879 return !SHISHI_OK;
880 }
881
882 return SHISHI_OK;
883 }
884
885 int
shishi_key_parse(Shishi * handle,FILE * fh,Shishi_key ** key)886 shishi_key_parse (Shishi * handle, FILE * fh, Shishi_key ** key)
887 {
888 int lno = 0;
889 char line[BUFSIZE];
890 char *b64buffer;
891 char armorbegin[BUFSIZE];
892 char armorend[BUFSIZE];
893 int in_key = 0, in_body = 0;
894 int res;
895 Shishi_key *lkey = NULL;
896
897 sprintf (armorbegin, HEADERBEG, "KEY");
898 sprintf (armorend, HEADEREND, "KEY");
899
900 while (fgets (line, sizeof (line), fh))
901 {
902 lno++;
903 line[sizeof (line) - 1] = '\0';
904 if (!*line || line[strlen (line) - 1] != '\n')
905 {
906 fprintf (stderr, "input line %u too long or missing LF\n", lno);
907 continue;
908 }
909 line[strlen (line) - 1] = '\0';
910 if (VERBOSENOISE (handle))
911 printf ("line %d read %ld bytes: %s\n", lno, strlen (line), line);
912
913 if (!in_key)
914 {
915 in_key = strncmp (line, armorbegin, strlen (armorbegin)) == 0;
916 if (in_key)
917 {
918 res = shishi_key (handle, &lkey);
919 if (res != SHISHI_OK)
920 return res;
921
922 }
923 continue;
924 }
925
926 if (strcmp (line, armorend) == 0)
927 break;
928
929 if (in_body)
930 {
931 int ok =
932 base64_decode_alloc (line, strlen (line), &b64buffer, NULL);
933 if (!ok)
934 return SHISHI_BASE64_ERROR;
935 shishi_key_value_set (lkey, b64buffer);
936 }
937 else
938 {
939 if (strcmp (line, "") == 0 || strcmp (line, " ") == 0)
940 in_body = 1;
941
942 if (strncmp (line, "Keytype: ", strlen ("Keytype: ")) == 0)
943 {
944 int type;
945 if (sscanf (line, "Keytype: %d (", &type) == 1)
946 shishi_key_type_set (lkey, type);
947 }
948 else if (strncmp (line, "Key-Version-Number: ",
949 strlen ("Key-Version-Number: ")) == 0)
950 {
951 int type;
952 if (sscanf (line, "Key-Version-Number: %d", &type) == 1)
953 shishi_key_version_set (lkey, type);
954 }
955 else if (strncmp (line, "Realm: ", strlen ("Realm: ")) == 0)
956 {
957 shishi_key_realm_set (lkey, line + strlen ("Realm: "));
958 }
959 else if (strncmp (line, "Principal: ", strlen ("Principal: ")) == 0)
960 {
961 shishi_key_principal_set (lkey, line + strlen ("Principal: "));
962 }
963 }
964 }
965
966 if (!lkey)
967 return SHISHI_OK;
968
969 *key = lkey;
970
971 return SHISHI_OK;
972 }
973
974 /**
975 * shishi_key_print:
976 * @handle: shishi handle as allocated by shishi_init().
977 * @fh: file handle opened for writing.
978 * @key: key to print.
979 *
980 * Print an ASCII representation of a key structure to file
981 * descriptor. Example output:
982 *
983 * -----BEGIN SHISHI KEY-----
984 * Keytype: 18 (aes256-cts-hmac-sha1-96)
985 * Principal: host/latte.josefsson.org
986 * Realm: JOSEFSSON.ORG
987 * Key-Version-Number: 1
988 *
989 * P1QdeW/oSiag/bTyVEBAY2msiGSTmgLXlopuCKoppDs=
990 * -----END SHISHI KEY-----
991 *
992 * Return value: Returns SHISHI_OK iff successful.
993 **/
994 int
shishi_key_print(Shishi * handle,FILE * fh,const Shishi_key * key)995 shishi_key_print (Shishi * handle, FILE * fh, const Shishi_key * key)
996 {
997 char *b64key;
998 size_t i;
999
1000 base64_encode_alloc (shishi_key_value (key), shishi_key_length (key),
1001 &b64key);
1002
1003 if (!b64key)
1004 return SHISHI_MALLOC_ERROR;
1005
1006 fprintf (fh, HEADERBEG "\n", "KEY");
1007
1008 fprintf (fh, "Keytype: %d (%s)\n", shishi_key_type (key),
1009 shishi_cipher_name (shishi_key_type (key)));
1010 if (shishi_key_principal (key))
1011 fprintf (fh, "Principal: %s\n", shishi_key_principal (key));
1012 if (shishi_key_realm (key))
1013 fprintf (fh, "Realm: %s\n", shishi_key_realm (key));
1014 if (shishi_key_version (key) != UINT32_MAX)
1015 fprintf (fh, "Key-Version-Number: %d\n", shishi_key_version (key));
1016 fprintf (fh, "\n");
1017
1018 for (i = 0; i < strlen (b64key); i++)
1019 {
1020 fprintf (fh, "%c", b64key[i]);
1021 if ((i + 1) % 64 == 0)
1022 fprintf (fh, "\n");
1023 }
1024 if ((i + 1) % 64 != 0)
1025 fprintf (fh, "\n");
1026
1027 free (b64key);
1028
1029 #if 0
1030 if (VERBOSENOISE (handle))
1031 {
1032 for (i = 0; i < shishi_key_length (key); i++)
1033 fprintf (stdout, "%02x", shishi_key_value (key)[i] & 0xFF);
1034 fprintf (stdout, "\n");
1035 }
1036 #endif
1037
1038 fprintf (fh, HEADEREND "\n", "KEY");
1039
1040 return SHISHI_OK;
1041 }
1042
1043 /**
1044 * shishi_key_to_file:
1045 * @handle: shishi handle as allocated by shishi_init().
1046 * @filename: filename to append key to.
1047 * @key: key to print.
1048 *
1049 * Print an ASCII representation of a key structure to a file. The
1050 * file is appended to if it exists. See shishi_key_print() for
1051 * format of output.
1052 *
1053 * Return value: Returns SHISHI_OK iff successful.
1054 **/
1055 int
shishi_key_to_file(Shishi * handle,const char * filename,Shishi_key * key)1056 shishi_key_to_file (Shishi * handle, const char *filename, Shishi_key * key)
1057 {
1058 FILE *fh;
1059 int res;
1060
1061 if (VERBOSE (handle))
1062 printf (_("Writing KEY to %s...\n"), filename);
1063
1064 fh = fopen (filename, "a");
1065 if (fh == NULL)
1066 return SHISHI_FOPEN_ERROR;
1067
1068 res = shishi_key_print (handle, fh, key);
1069 if (res != SHISHI_OK)
1070 return res;
1071
1072 res = fclose (fh);
1073 if (res != 0)
1074 return SHISHI_IO_ERROR;
1075
1076 if (VERBOSE (handle))
1077 printf (_("Writing KEY to %s...done\n"), filename);
1078
1079 return SHISHI_OK;
1080 }
1081