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_priv_input (Shishi
* handle
, FILE * fh
, Shishi_asn1
* priv
, int type
)
757 b64len
= sizeof (b64der
);
758 res
= _shishi_read_armored_data (handle
, fh
, b64der
, b64len
,
760 if (res
!= SHISHI_OK
)
762 shishi_error_printf (handle
, "armor data read fail\n");
766 derlen
= base64_from (&der
[0], b64der
);
770 derlen
= fread (der
, sizeof (der
[0]),
771 sizeof (der
) / sizeof (der
[0]), fh
);
772 if (derlen
<= 0 || !feof (fh
) || ferror (fh
))
774 shishi_error_printf (handle
,
775 "Error reading from file (got %d bytes)...",
781 *priv
= shishi_der2asn1_priv (handle
, der
, derlen
);
784 printf ("bad magic %s\n", shishi_error (handle
));
785 shishi_error_printf (handle
, "Could not DER decode KRB-PRIV\n");
794 shishi_key_parse (Shishi
* handle
, FILE * fh
, Shishi_key
** key
)
799 char armorbegin
[BUFSIZ
];
800 char armorend
[BUFSIZ
];
801 int in_key
= 0, in_body
= 0;
804 Shishi_key
*lkey
= NULL
;
806 sprintf (armorbegin
, HEADERBEG
, "KEY");
807 sprintf (armorend
, HEADEREND
, "KEY");
810 while (fgets (line
, sizeof (line
), fh
))
813 line
[sizeof (line
) - 1] = '\0';
814 if (!*line
|| line
[strlen (line
) - 1] != '\n')
816 fprintf (stderr
, "input line %u too long or missing LF\n", lno
);
819 line
[strlen (line
) - 1] = '\0';
820 if (VERBOSENOICE (handle
))
821 printf ("line %d read %d bytes: %s\n", lno
, strlen (line
), line
);
825 in_key
= strncmp (line
, armorbegin
, strlen (armorbegin
)) == 0;
828 res
= shishi_key (handle
, &lkey
);
829 if (res
!= SHISHI_OK
)
836 if (strcmp (line
, armorend
) == 0)
841 buflen
= base64_from (buffer
, line
);
842 shishi_key_value_set (lkey
, buffer
);
846 if (strcmp (line
, "") == 0 || strcmp (line
, " ") == 0)
849 if (strncmp (line
, "Keytype: ", strlen ("Keytype: ")) == 0)
852 if (sscanf (line
, "Keytype: %d (", &type
) == 1)
853 shishi_key_type_set (lkey
, type
);
855 else if (strncmp (line
, "Key-Version-Number: ",
856 strlen ("Key-Version-Number: ")) == 0)
859 if (sscanf (line
, "Key-Version-Number: %d", &type
) == 1)
860 shishi_key_version_set (lkey
, type
);
862 else if (strncmp (line
, "Realm: ", strlen ("Realm: ")) == 0)
864 shishi_key_realm_set (lkey
, line
+ strlen ("Realm: "));
866 else if (strncmp (line
, "Principal: ", strlen ("Principal: ")) == 0)
868 shishi_key_principal_set (lkey
, line
+ strlen ("Principal: "));
883 * @handle: shishi handle as allocated by shishi_init().
884 * @fh: file handle opened for writing.
885 * @key: key to print.
887 * Print an ASCII representation of a key structure to file
888 * descriptor. Example output:
890 * -----BEGIN SHISHI KEY-----
891 * Keytype: 18 (aes256-cts-hmac-sha1-96)
892 * Principal: host/latte.josefsson.org
893 * Realm: JOSEFSSON.ORG
894 * Key-Version-Number: 1
896 * P1QdeW/oSiag/bTyVEBAY2msiGSTmgLXlopuCKoppDs=
897 * -----END SHISHI KEY-----
899 * Return value: Returns SHISHI_OK iff successful.
902 shishi_key_print (Shishi
* handle
, FILE * fh
, Shishi_key
* key
)
907 base64_to (b64key
, shishi_key_value (key
),
908 shishi_key_length (key
), sizeof (b64key
));
910 fprintf (fh
, HEADERBEG
"\n", "KEY");
912 fprintf (fh
, "Keytype: %d (%s)\n", shishi_key_type (key
),
913 shishi_cipher_name (shishi_key_type (key
)));
914 if (shishi_key_principal (key
))
915 fprintf (fh
, "Principal: %s\n", shishi_key_principal (key
));
916 if (shishi_key_realm (key
))
917 fprintf (fh
, "Realm: %s\n", shishi_key_realm (key
));
918 if (shishi_key_version (key
))
919 fprintf (fh
, "Key-Version-Number: %d\n", shishi_key_version (key
));
922 for (i
= 0; i
< strlen (b64key
); i
++)
924 fprintf (fh
, "%c", b64key
[i
]);
925 if ((i
+ 1) % 64 == 0)
928 if ((i
+ 1) % 64 != 0)
932 if (VERBOSENOICE (handle
))
934 for (i
= 0; i
< shishi_key_length (key
); i
++)
935 fprintf (stdout
, "%02x", shishi_key_value (key
)[i
] & 0xFF);
936 fprintf (stdout
, "\n");
940 fprintf (fh
, HEADEREND
"\n", "KEY");
946 * shishi_key_to_file:
947 * @handle: shishi handle as allocated by shishi_init().
948 * @filename: filename to append key to.
949 * @key: key to print.
951 * Print an ASCII representation of a key structure to a file. The
952 * file is appended to if it exists. See shishi_key_print() for
955 * Return value: Returns SHISHI_OK iff successful.
958 shishi_key_to_file (Shishi
* handle
, const char *filename
, Shishi_key
* key
)
963 if (VERBOSE (handle
))
964 printf (_("Writing KEY to %s...\n"), filename
);
966 fh
= fopen (filename
, "a");
968 return SHISHI_FOPEN_ERROR
;
970 res
= shishi_key_print (handle
, fh
, key
);
971 if (res
!= SHISHI_OK
)
976 return SHISHI_FCLOSE_ERROR
;
978 if (VERBOSE (handle
))
979 printf (_("Writing KEY to %s...done\n"), filename
);