1 /* diskio.c read and write data structures from disk
2 * Copyright (C) 2002, 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define _SHISHI_HAS_LIBTASN1_H 1
26 #define HEADERBEG "-----BEGIN SHISHI %s-----"
27 #define HEADEREND "-----END SHISHI %s-----"
30 * Note to self: if you change any *print* function, remember to change
31 * the corresponding *parse* function too.
36 _shishi_print_armored_data (Shishi
* handle
,
38 Shishi_asn1 asn1
, char *asn1type
, char *headers
)
49 asn1_print_structure (fh
, asn1
, "", ASN1_PRINT_NAME_TYPE_VALUE
);
51 res
= shishi_new_a2d (handle
, asn1
, &der
, &derlen
);
52 if (res
!= ASN1_SUCCESS
)
54 shishi_error_printf (handle
, "Could not DER encode %s: %s\n",
55 asn1type
, shishi_strerror (res
));
59 base64_to (b64der
, der
, derlen
, sizeof (b64der
));
61 fprintf (fh
, HEADERBEG
"\n", asn1type
);
65 fprintf (fh
, headers
);
69 for (i
= 0; i
< strlen (b64der
); i
++)
71 fprintf (fh
, "%c", b64der
[i
]);
72 if ((i
+ 1) % 64 == 0)
75 if ((i
+ 1) % 64 != 0)
78 fprintf (fh
, HEADEREND
"\n", asn1type
);
84 _shishi_save_data (Shishi
* handle
, FILE * fh
, Shishi_asn1 asn1
,
92 derlen
= sizeof (der
);
93 res
= shishi_a2d_new_field (handle
, asn1
, asn1type
, &der
, &derlen
);
96 shishi_error_printf (handle
, "Could not DER encode %s: %s\n",
97 asn1type
, shishi_strerror (res
));
98 return SHISHI_ASN1_ERROR
;
101 i
= fwrite (der
, sizeof (der
[0]), derlen
, fh
);
104 shishi_error_printf (handle
, "Short write to file (wrote %d of %d)\n",
113 shishi_enckdcreppart_print (Shishi
* handle
,
114 FILE * fh
, Shishi_asn1 enckdcreppart
)
116 return _shishi_print_armored_data (handle
, fh
, enckdcreppart
,
117 "EncKDCRepPart", NULL
);
121 shishi_enckdcreppart_save (Shishi
* handle
,
122 FILE * fh
, Shishi_asn1 enckdcreppart
)
124 return _shishi_save_data (handle
, fh
, enckdcreppart
, "EncKDCRepPart");
128 shishi_ticket_save (Shishi
* handle
, FILE * fh
, Shishi_asn1 ticket
)
130 return _shishi_save_data (handle
, fh
, ticket
, "Ticket");
134 shishi_ticket_print (Shishi
* handle
, FILE * fh
, Shishi_asn1 ticket
)
136 return _shishi_print_armored_data (handle
, fh
, ticket
, "Ticket", NULL
);
140 shishi_encticketpart_print (Shishi
* handle
, FILE * fh
,
141 Shishi_asn1 encticketpart
)
143 return _shishi_print_armored_data (handle
, fh
, encticketpart
,
144 "EncTicketPart", NULL
);
148 _shishi_read_armored_data (Shishi
* handle
,
149 FILE * fh
, char *buffer
, size_t len
, char *tag
)
152 size_t maxsize
= len
;
154 char armorbegin
[BUFSIZ
];
155 char armorend
[BUFSIZ
];
158 sprintf (armorbegin
, HEADERBEG
, tag
);
159 sprintf (armorend
, HEADEREND
, tag
);
162 while (fgets (line
, sizeof (line
), fh
))
165 line
[sizeof (line
) - 1] = '\0';
166 if (!*line
|| line
[strlen (line
) - 1] != '\n')
168 fprintf (stderr
, "input line %u too long or missing LF\n", lno
);
171 line
[strlen (line
) - 1] = '\0';
172 if (VERBOSENOICE (handle
))
173 printf ("line %d read %d bytes: %s\n", lno
, strlen (line
), line
);
175 /* XXX check if all chars in line are b64 data, otherwise bail out */
179 if (strncmp (line
, armorend
, strlen (armorend
)) == 0)
184 in_data
= strncmp (line
, armorbegin
, strlen (armorbegin
)) == 0;
188 if (len
+ strlen (line
) >= maxsize
)
190 shishi_error_printf (handle
, "too large input size on line %d\n",
195 memcpy (buffer
+ len
, line
, strlen (line
));
196 len
+= strlen (line
);
208 _shishi_ticket_input (Shishi
* handle
,
209 FILE * fh
, Shishi_asn1
* ticket
, int type
)
219 b64len
= sizeof (b64der
);
220 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
, "Ticket");
221 if (res
!= SHISHI_OK
)
223 shishi_error_printf (handle
, "armor data read fail\n");
227 derlen
= base64_from (&der
[0], b64der
);
232 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
233 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
235 shishi_error_printf (handle
,
236 "Error reading from file (got %d bytes)...",
242 *ticket
= shishi_der2asn1_ticket (handle
, der
, derlen
);
244 return SHISHI_ASN1_ERROR
;
250 shishi_ticket_parse (Shishi
* handle
, FILE * fh
, Shishi_asn1
* ticket
)
252 return _shishi_ticket_input (handle
, fh
, ticket
, 0);
256 shishi_ticket_read (Shishi
* handle
, FILE * fh
, Shishi_asn1
* ticket
)
258 return _shishi_ticket_input (handle
, fh
, ticket
, 1);
262 _shishi_enckdcreppart_input (Shishi
* handle
,
263 FILE * fh
, Shishi_asn1
* enckdcreppart
, int type
)
273 b64len
= sizeof (b64der
);
274 res
= _shishi_read_armored_data (handle
, fh
,
275 b64der
, b64len
, "EncKDCRepPart");
276 if (res
!= SHISHI_OK
)
278 shishi_error_printf (handle
, "armor data read fail\n");
282 derlen
= base64_from (&der
[0], b64der
);
287 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
288 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
290 shishi_error_printf (handle
,
291 "Error reading from file (got %d bytes)...",
297 *enckdcreppart
= shishi_der2asn1_encasreppart (handle
, der
, derlen
);
298 if (*enckdcreppart
== NULL
)
300 shishi_error_printf (handle
, "Could not DER decode Encasreppart: %s",
301 shishi_error (handle
));
303 *enckdcreppart
= shishi_der2asn1_enctgsreppart (handle
, der
, derlen
);
304 if (*enckdcreppart
== NULL
)
306 shishi_error_printf (handle
,
307 "Could not DER decode Enctgsreppart: %s",
308 shishi_error (handle
));
311 shishi_der2asn1_enckdcreppart (handle
, der
, derlen
);
312 if (*enckdcreppart
== NULL
)
314 shishi_error_printf (handle
,
315 "Could not DER decode Enckdcreppart: %s",
316 shishi_error (handle
));
326 shishi_enckdcreppart_parse (Shishi
* handle
,
327 FILE * fh
, Shishi_asn1
* enckdcreppart
)
329 return _shishi_enckdcreppart_input (handle
, fh
, enckdcreppart
, 0);
333 shishi_enckdcreppart_read (Shishi
* handle
,
334 FILE * fh
, Shishi_asn1
* enckdcreppart
)
336 return _shishi_enckdcreppart_input (handle
, fh
, enckdcreppart
, 1);
340 _shishi_kdcreq_input (Shishi
* handle
, FILE * fh
, Shishi_asn1
* asreq
,
351 b64len
= sizeof (b64der
);
352 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
, "KDC-REQ");
353 if (res
!= SHISHI_OK
)
355 shishi_error_printf (handle
, "armor data read fail\n");
359 derlen
= base64_from (&der
[0], b64der
);
364 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
365 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
367 shishi_error_printf (handle
,
368 "Error reading from file (got %d bytes)...",
374 *asreq
= shishi_der2asn1_asreq (handle
, der
, derlen
);
377 printf ("bad asreq magic\n");
378 shishi_error_printf (handle
, "Could not DER decode AS-REQ\n");
380 *asreq
= shishi_der2asn1_tgsreq (handle
, der
, derlen
);
383 printf ("bad tgsreq magic\n");
384 shishi_error_printf (handle
, "Could not DER decode TGS-REQ\n");
386 *asreq
= shishi_der2asn1_kdcreq (handle
, der
, derlen
);
389 printf ("bad kdcreq magic\n");
390 shishi_error_printf (handle
, "Could not DER decode KDC-REQ\n");
401 _shishi_kdcrep_input (Shishi
* handle
, FILE * fh
, Shishi_asn1
* asrep
,
412 b64len
= sizeof (b64der
);
413 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
, "KDC-REP");
414 if (res
!= SHISHI_OK
)
416 shishi_error_printf (handle
, "armor data read fail\n");
420 derlen
= base64_from (&der
[0], b64der
);
425 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
426 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
428 shishi_error_printf (handle
,
429 "Error reading from file (got %d bytes)...",
435 *asrep
= shishi_der2asn1_asrep (handle
, der
, derlen
);
438 *asrep
= shishi_der2asn1_tgsrep (handle
, der
, derlen
);
441 printf ("Could not DER decode KDC-REP: %s\n",
442 shishi_error (handle
));
443 printf ("Parsing AS/TGS-REP as KDC-REP (bug work around)\n");
445 *asrep
= shishi_der2asn1_kdcrep (handle
, der
, derlen
);
448 fprintf (stderr
, "Could not DER decode KDC-REP: %s\n",
449 shishi_error (handle
));
453 fprintf (stderr
, "Bug workaround code successful...\n");
461 _shishi_apreq_input (Shishi
* handle
, FILE * fh
, Shishi_asn1
* apreq
,
472 b64len
= sizeof (b64der
);
473 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
, "AP-REQ");
474 if (res
!= SHISHI_OK
)
476 shishi_error_printf (handle
, "armor data read fail\n");
480 derlen
= base64_from (&der
[0], b64der
);
485 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
486 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
488 shishi_error_printf (handle
,
489 "Error reading from file (got %d bytes)...",
495 *apreq
= shishi_der2asn1_apreq (handle
, der
, derlen
);
498 printf ("bad magic %s\n", shishi_error (handle
));
499 shishi_error_printf (handle
, "Could not DER decode AP-REQ\n");
508 _shishi_aprep_input (Shishi
* handle
, FILE * fh
, Shishi_asn1
* aprep
,
519 b64len
= sizeof (b64der
);
520 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
, "AP-REP");
521 if (res
!= SHISHI_OK
)
523 shishi_error_printf (handle
, "armor data read fail\n");
527 derlen
= base64_from (&der
[0], b64der
);
532 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
533 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
535 shishi_error_printf (handle
,
536 "Error reading from file (got %d bytes)...",
542 *aprep
= shishi_der2asn1_aprep (handle
, der
, derlen
);
545 printf ("bad magic %s\n", shishi_error (handle
));
546 shishi_error_printf (handle
, "Could not DER decode AP-REP\n");
555 _shishi_encapreppart_input (Shishi
* handle
, FILE * fh
,
556 Shishi_asn1
* encapreppart
, int type
)
566 b64len
= sizeof (b64der
);
568 _shishi_read_armored_data (handle
, fh
, b64der
, b64len
,
570 if (res
!= SHISHI_OK
)
572 shishi_error_printf (handle
, "armor data read fail\n");
576 derlen
= base64_from (&der
[0], b64der
);
581 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
582 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
584 shishi_error_printf (handle
,
585 "Error reading from file (got %d bytes)...",
591 *encapreppart
= shishi_der2asn1_encapreppart (handle
, der
, derlen
);
592 if (*encapreppart
== NULL
)
594 printf ("bad magic %s\n", shishi_error (handle
));
595 shishi_error_printf (handle
, "Could not DER decode EncAPRepPart\n");
604 _shishi_authenticator_input (Shishi
* handle
,
605 FILE * fh
, Shishi_asn1
* authenticator
, int type
)
615 b64len
= sizeof (b64der
);
616 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
,
618 if (res
!= SHISHI_OK
)
620 shishi_error_printf (handle
, "armor data read fail\n");
624 derlen
= base64_from (&der
[0], b64der
);
629 fread (der
, sizeof (der
[0]), sizeof (der
) / sizeof (der
[0]), fh
);
630 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
632 shishi_error_printf (handle
,
633 "Error reading from file (got %d bytes)...",
639 *authenticator
= shishi_der2asn1_authenticator (handle
, der
, derlen
);
640 if (*authenticator
== NULL
)
642 printf ("bad magic %s\n", shishi_error (handle
));
643 shishi_error_printf (handle
, "Could not DER decode AP-REQ\n");
652 _shishi_krberror_input (Shishi
* handle
,
653 FILE * fh
, Shishi_asn1
* krberror
, int type
)
663 b64len
= sizeof (b64der
);
664 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
,
666 if (res
!= SHISHI_OK
)
668 shishi_error_printf (handle
, "armor data read fail\n");
672 derlen
= base64_from (&der
[0], b64der
);
676 derlen
= fread (der
, sizeof (der
[0]),
677 sizeof (der
) / sizeof (der
[0]), fh
);
678 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
680 shishi_error_printf (handle
,
681 "Error reading from file (got %d bytes)...",
687 *krberror
= shishi_der2asn1_krberror (handle
, der
, derlen
);
688 if (*krberror
== NULL
)
690 printf ("bad magic %s\n", shishi_error (handle
));
691 shishi_error_printf (handle
, "Could not DER decode AP-REQ\n");
700 _shishi_safe_input (Shishi
* handle
, FILE * fh
, Shishi_asn1
* safe
, int type
)
710 b64len
= sizeof (b64der
);
711 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
,
713 if (res
!= SHISHI_OK
)
715 shishi_error_printf (handle
, "armor data read fail\n");
719 derlen
= base64_from (&der
[0], b64der
);
723 derlen
= fread (der
, sizeof (der
[0]),
724 sizeof (der
) / sizeof (der
[0]), fh
);
725 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
727 shishi_error_printf (handle
,
728 "Error reading from file (got %d bytes)...",
734 *safe
= shishi_der2asn1_krbsafe (handle
, der
, derlen
);
737 printf ("bad magic %s\n", shishi_error (handle
));
738 shishi_error_printf (handle
, "Could not DER decode KRB-SAFE\n");
747 shishi_key_parse (Shishi
* handle
, FILE * fh
, Shishi_key
** key
)
752 char armorbegin
[BUFSIZ
];
753 char armorend
[BUFSIZ
];
754 int in_key
= 0, in_body
= 0;
757 Shishi_key
*lkey
= NULL
;
759 sprintf (armorbegin
, HEADERBEG
, "KEY");
760 sprintf (armorend
, HEADEREND
, "KEY");
763 while (fgets (line
, sizeof (line
), fh
))
766 line
[sizeof (line
) - 1] = '\0';
767 if (!*line
|| line
[strlen (line
) - 1] != '\n')
769 fprintf (stderr
, "input line %u too long or missing LF\n", lno
);
772 line
[strlen (line
) - 1] = '\0';
773 if (VERBOSENOICE (handle
))
774 printf ("line %d read %d bytes: %s\n", lno
, strlen (line
), line
);
778 in_key
= strncmp (line
, armorbegin
, strlen (armorbegin
)) == 0;
781 res
= shishi_key (handle
, &lkey
);
782 if (res
!= SHISHI_OK
)
789 if (strcmp (line
, armorend
) == 0)
794 buflen
= base64_from (buffer
, line
);
795 shishi_key_value_set (lkey
, buffer
);
799 if (strcmp (line
, "") == 0 || strcmp (line
, " ") == 0)
802 if (strncmp (line
, "Keytype: ", strlen ("Keytype: ")) == 0)
805 if (sscanf (line
, "Keytype: %d (", &type
) == 1)
806 shishi_key_type_set (lkey
, type
);
808 else if (strncmp (line
, "Key-Version-Number: ",
809 strlen ("Key-Version-Number: ")) == 0)
812 if (sscanf (line
, "Key-Version-Number: %d", &type
) == 1)
813 shishi_key_version_set (lkey
, type
);
815 else if (strncmp (line
, "Realm: ", strlen ("Realm: ")) == 0)
817 shishi_key_realm_set (lkey
, line
+ strlen ("Realm: "));
819 else if (strncmp (line
, "Principal: ", strlen ("Principal: ")) == 0)
821 shishi_key_principal_set (lkey
, line
+ strlen ("Principal: "));
836 * @handle: shishi handle as allocated by shishi_init().
837 * @fh: file handle opened for writing.
838 * @key: key to print.
840 * Print an ASCII representation of a key structure to file
841 * descriptor. Example output:
843 * -----BEGIN SHISHI KEY-----
844 * Keytype: 18 (aes256-cts-hmac-sha1-96)
845 * Principal: host/latte.josefsson.org
846 * Realm: JOSEFSSON.ORG
847 * Key-Version-Number: 1
849 * P1QdeW/oSiag/bTyVEBAY2msiGSTmgLXlopuCKoppDs=
850 * -----END SHISHI KEY-----
852 * Return value: Returns SHISHI_OK iff successful.
855 shishi_key_print (Shishi
* handle
, FILE * fh
, Shishi_key
* key
)
860 base64_to (b64key
, shishi_key_value (key
),
861 shishi_key_length (key
), sizeof (b64key
));
863 fprintf (fh
, HEADERBEG
"\n", "KEY");
865 fprintf (fh
, "Keytype: %d (%s)\n", shishi_key_type (key
),
866 shishi_cipher_name (shishi_key_type (key
)));
867 if (shishi_key_principal (key
))
868 fprintf (fh
, "Principal: %s\n", shishi_key_principal (key
));
869 if (shishi_key_realm (key
))
870 fprintf (fh
, "Realm: %s\n", shishi_key_realm (key
));
871 if (shishi_key_version (key
))
872 fprintf (fh
, "Key-Version-Number: %d\n", shishi_key_version (key
));
875 for (i
= 0; i
< strlen (b64key
); i
++)
877 fprintf (fh
, "%c", b64key
[i
]);
878 if ((i
+ 1) % 64 == 0)
881 if ((i
+ 1) % 64 != 0)
885 if (VERBOSENOICE (handle
))
887 for (i
= 0; i
< shishi_key_length (key
); i
++)
888 fprintf (stdout
, "%02x", shishi_key_value (key
)[i
] & 0xFF);
889 fprintf (stdout
, "\n");
893 fprintf (fh
, HEADEREND
"\n", "KEY");
899 * shishi_key_to_file:
900 * @handle: shishi handle as allocated by shishi_init().
901 * @filename: filename to append key to.
902 * @key: key to print.
904 * Print an ASCII representation of a key structure to a file. The
905 * file is appended to if it exists. See shishi_key_print() for
908 * Return value: Returns SHISHI_OK iff successful.
911 shishi_key_to_file (Shishi
* handle
, const char *filename
, Shishi_key
* key
)
916 if (VERBOSE (handle
))
917 printf (_("Writing KEY to %s...\n"), filename
);
919 fh
= fopen (filename
, "a");
921 return SHISHI_FOPEN_ERROR
;
923 res
= shishi_key_print (handle
, fh
, key
);
924 if (res
!= SHISHI_OK
)
929 return SHISHI_FCLOSE_ERROR
;
931 if (VERBOSE (handle
))
932 printf (_("Writing KEY to %s...done\n"), filename
);