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