* keybox-init.c (keybox_set_ephemeral): New.
[gnupg.git] / kbx / keybox-dump.c
1 /* keybox-dump.c - Debug helpers
2  *      Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG 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.
10  *
11  * GnuPG 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26
27 #include "keybox-defs.h"
28
29 static ulong
30 get32 (const byte *buffer)
31 {
32   ulong a;
33   a =  *buffer << 24;
34   a |= buffer[1] << 16;
35   a |= buffer[2] << 8;
36   a |= buffer[3];
37   return a;
38 }
39
40 static ulong
41 get16 (const byte *buffer)
42 {
43   ulong a;
44   a =  *buffer << 8;
45   a |= buffer[1];
46   return a;
47 }
48
49 void
50 print_string (FILE *fp, const byte *p, size_t n, int delim)
51 {
52   for ( ; n; n--, p++ )
53     {
54       if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim)
55         {
56           putc('\\', fp);
57           if( *p == '\n' )
58             putc('n', fp);
59           else if( *p == '\r' )
60             putc('r', fp);
61           else if( *p == '\f' )
62             putc('f', fp);
63           else if( *p == '\v' )
64             putc('v', fp);
65           else if( *p == '\b' )
66             putc('b', fp);
67           else if( !*p )
68             putc('0', fp);
69           else
70             fprintf(fp, "x%02x", *p );
71         }
72       else
73         putc(*p, fp);
74     }
75 }
76
77
78 static int
79 dump_header_blob (const byte *buffer, size_t length, FILE *fp)
80 {
81   fprintf (fp, "Version: %d\n", buffer[5]);
82   if ( memcmp (buffer+8, "KBXf", 4))
83     fprintf (fp, "[Error: invalid magic number]\n");
84   return 0;
85 }
86
87 \f
88 /* Dump one block to FP */
89 int
90 _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
91 {
92   const byte *buffer;
93   size_t length;
94   int type;
95   ulong n, nkeys, keyinfolen;
96   ulong nuids, uidinfolen;
97   ulong nsigs, siginfolen;
98   ulong rawdata_off, rawdata_len;
99   ulong nserial;
100   const byte *p;
101
102   buffer = _keybox_get_blob_image (blob, &length);
103   
104   if (length < 40)
105     {
106       fprintf (fp, "[blob too short]\n");
107       return -1;
108     }
109
110   n = get32( buffer );
111   if (n > length) 
112     fprintf (fp, "[blob larger than length - output truncated]\n");
113   else
114     length = n;  /* ignore the rest */
115
116   fprintf (fp, "Length: %lu\n", n );
117   type = buffer[4];
118   switch (type)
119     {
120     case BLOBTYPE_HEADER:
121       fprintf (fp, "Type:   Header\n");
122       return dump_header_blob (buffer, length, fp);
123     case BLOBTYPE_PGP:
124       fprintf (fp, "Type:   OpenPGP\n");
125       break;
126     case BLOBTYPE_X509:
127       fprintf (fp, "Type:   X.509\n");
128       break;
129     default:
130       fprintf (fp, "Type:   %d\n", type);
131       fprintf (fp, "[can't dump this blob type]\n");
132       return 0;
133     }
134   fprintf (fp, "Version: %d\n", buffer[5]);
135   
136   n = get16 (buffer + 6);
137   fprintf( fp, "Blob-Flags: %04lX", n);
138   if (n)
139     {
140       int any = 0;
141
142       fputs (" (", fp);
143       if ((n & 1))
144         {
145           fputs ("secret", fp);
146           any++;
147         }
148       if ((n & 2))
149         {
150           if (any)
151             putc (',', fp);
152           fputs ("ephemeral", fp);
153           any++;
154         }
155       putc (')', fp);
156     }
157   putc ('\n', fp);
158
159   rawdata_off = get32 (buffer + 8);
160   rawdata_len = get32 (buffer + 12);
161
162   fprintf( fp, "Data-Offset: %lu\n", rawdata_off );
163   fprintf( fp, "Data-Length: %lu\n", rawdata_len );
164
165   nkeys = get16 (buffer + 16);
166   fprintf (fp, "Key-Count: %lu\n", nkeys );
167   if (!nkeys)
168     fprintf (fp, "[Error: no keys]\n");
169   if (nkeys > 1 && type == BLOBTYPE_X509)
170     fprintf (fp, "[Error: only one key allowed for X509]\n");
171
172   keyinfolen = get16 (buffer + 18 );
173   fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen);
174   /* fixme: check bounds */
175   p = buffer + 20;
176   for (n=0; n < nkeys; n++, p += keyinfolen)
177     {
178       int i;
179       ulong kidoff, kflags;
180     
181       fprintf (fp, "Key-Fpr[%lu]: ", n );
182       for (i=0; i < 20; i++ )
183         fprintf (fp, "%02X", p[i]);
184       kidoff = get32 (p + 20);
185       fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
186       fprintf (fp, "Key-Kid[%lu]: ", n );
187       /* fixme: check bounds */
188       for (i=0; i < 8; i++ )
189         fprintf (fp, "%02X", buffer[kidoff+i] );
190       kflags = get16 (p + 24 );
191       fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
192     }
193   
194   /* serial number */
195   fputs ("Serial-No: ", fp);
196   nserial = get16 (p);
197   p += 2;
198   if (!nserial)
199     fputs ("none", fp);
200   else
201     {
202       for (; nserial; nserial--, p++)
203         fprintf (fp, "%02X", *p);
204     }
205   putc ('\n', fp);
206
207   /* user IDs */
208   nuids = get16 (p);
209   fprintf (fp, "Uid-Count: %lu\n", nuids );
210   uidinfolen = get16  (p + 2);
211   fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen);
212   /* fixme: check bounds */
213   p += 4;
214   for (n=0; n < nuids; n++, p += uidinfolen)
215     {
216       ulong uidoff, uidlen, uflags;
217       
218       uidoff = get32( p );
219       uidlen = get32( p+4 );
220       if (type == BLOBTYPE_X509 && !n)
221         {
222           fprintf (fp, "Issuer-Off: %lu\n", uidoff );
223           fprintf (fp, "Issuer-Len: %lu\n", uidlen );
224           fprintf (fp, "Issuer: \"");
225         }
226       else if (type == BLOBTYPE_X509 && n == 1)
227         {
228           fprintf (fp, "Subject-Off: %lu\n", uidoff );
229           fprintf (fp, "Subject-Len: %lu\n", uidlen );
230           fprintf (fp, "Subject: \"");
231         }
232       else
233         {
234           fprintf (fp, "Uid-Off[%lu]: %lu\n", n, uidoff );
235           fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen );
236           fprintf (fp, "Uid[%lu]: \"", n );
237         }
238       print_string (fp, buffer+uidoff, uidlen, '\"');
239       fputs ("\"\n", fp);
240       uflags = get16 (p + 8);
241       if (type == BLOBTYPE_X509 && !n)
242         {
243           fprintf (fp, "Issuer-Flags: %04lX\n", uflags );
244           fprintf (fp, "Issuer-Validity: %d\n", p[10] );
245         }
246       else if (type == BLOBTYPE_X509 && n == 1)
247         {
248           fprintf (fp, "Subject-Flags: %04lX\n", uflags );
249           fprintf (fp, "Subject-Validity: %d\n", p[10] );
250         }
251       else
252         {
253           fprintf (fp, "Uid-Flags[%lu]: %04lX\n", n, uflags );
254           fprintf (fp, "Uid-Validity[%lu]: %d\n", n, p[10] );
255         }
256     }
257   
258   nsigs = get16 (p);
259   fprintf (fp, "Sig-Count: %lu\n", nsigs );
260   siginfolen = get16 (p + 2);
261   fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen );
262   /* fixme: check bounds  */
263   p += 4;
264   for (n=0; n < nsigs; n++, p += siginfolen)
265     {
266       ulong sflags;
267     
268       sflags = get32 (p);
269       fprintf (fp, "Sig-Expire[%lu]: ", n );
270       if (!sflags)
271         fputs ("[not checked]", fp);
272       else if (sflags == 1 )
273         fputs ("[missing key]", fp);
274       else if (sflags == 2 )
275         fputs ("[bad signature]", fp);
276       else if (sflags < 0x10000000)
277         fprintf (fp, "[bad flag %0lx]", sflags);
278       else if (sflags == 0xffffffff)
279         fputs ("0", fp );
280       else
281         fputs ("a time"/*strtimestamp( sflags )*/, fp );
282       putc ('\n', fp );
283     }
284
285   fprintf (fp, "Ownertrust: %d\n", p[0] );
286   fprintf (fp, "All-Validity: %d\n", p[1] );
287   p += 4;
288   n = get32 (p); p += 4;
289   fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" );
290   n = get32 (p ); p += 4;
291   fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ );
292   n = get32 (p ); p += 4;
293   fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ );
294   n = get32 (p ); p += 4;
295   fprintf (fp, "Reserved-Space: %lu\n", n );
296
297   /* check that the keyblock is at the correct offset and other bounds */
298   /*fprintf (fp, "Blob-Checksum: [MD5-hash]\n");*/
299   return 0;
300 }
301
302
303 \f
304 int
305 _keybox_dump_file (const char *filename, FILE *outfp)
306 {
307   FILE *fp;
308   KEYBOXBLOB blob;
309   int rc;
310   unsigned long count = 0;
311
312   if (!filename)
313     {
314       filename = "-";
315       fp = stdin;
316     }
317   else
318     fp = fopen (filename, "rb");
319   if (!fp)
320     {
321       fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno));
322       return KEYBOX_File_Error;
323     }
324
325   while ( !(rc = _keybox_read_blob (&blob, fp)) )
326     {
327       fprintf (outfp, "BEGIN-RECORD: %lu\n", count );
328       _keybox_dump_blob (blob, outfp);
329       _keybox_release_blob (blob);
330       fprintf (outfp, "END-RECORD\n");
331       count++;
332     }
333   if (rc == -1)
334     rc = 0;
335   if (rc)
336     fprintf (outfp, "error reading `%s': %s\n", filename,
337              rc == KEYBOX_Read_Error? keybox_strerror(rc):strerror (errno));
338   
339   if (fp != stdin)
340     fclose (fp);
341   return rc;
342 }