Started with keybox implementation by basing it on code from the GnuPG
[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 static int
50 dump_header_blob (const byte *buffer, size_t length, FILE *fp)
51 {
52   fprintf (fp, "Version: %d\n", buffer[5]);
53   if ( memcmp (buffer+8, "KBXf", 4))
54     fprintf (fp, "[Error: invalid magic number]\n");
55   return 0;
56 }
57
58 \f
59 /* Dump one block to FP */
60 int
61 _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
62 {
63   const byte *buffer;
64   size_t length;
65   int type;
66   ulong n, nkeys, keyinfolen;
67   ulong nuids, uidinfolen;
68   ulong nsigs, siginfolen;
69   ulong rawdata_off, rawdata_len;
70   const byte *p;
71
72   buffer = _keybox_get_blob_image (blob, &length);
73   
74   if (length < 40)
75     {
76       fprintf (fp, "[blob too short]\n");
77       return -1;
78     }
79
80   n = get32( buffer );
81   if (n > length) 
82     fprintf (fp, "[blob larger than length - output truncated]\n");
83   else
84     length = n;  /* ignore the rest */
85
86   fprintf (fp, "Length: %lu\n", n );
87   type = buffer[4];
88   switch (type)
89     {
90     case BLOBTYPE_HEADER:
91       fprintf (fp, "Type:   Header\n");
92       return dump_header_blob (buffer, length, fp);
93     case BLOBTYPE_PGP:
94       fprintf (fp, "Type:   OpenPGP\n");
95       break;
96     case BLOBTYPE_X509:
97       fprintf (fp, "Type:   X.509\n");
98       break;
99     default:
100       fprintf (fp, "Type:   %d\n", type);
101       fprintf (fp, "[can't dump this blob type]\n");
102       return 0;
103     }
104   fprintf (fp, "Version: %d\n", buffer[5]);
105   
106   n = get16 (buffer + 6);
107   fprintf( fp, "Blob-Flags: %04lX\n", n);
108   
109   rawdata_off = get32 (buffer + 8);
110   rawdata_len = get32 (buffer + 12);
111
112   fprintf( fp, "Data-Offset: %lu\n", rawdata_off );
113   fprintf( fp, "Data-Length: %lu\n", rawdata_len );
114
115   nkeys = get16 (buffer + 16);
116   fprintf (fp, "Key-Count: %lu\n", nkeys );
117   if (!nkeys)
118     fprintf (fp, "[Error: no keys]\n");
119   if (nkeys > 1 && type == BLOBTYPE_X509)
120     fprintf (fp, "[Error: only one key allowed for X509]\n");
121
122   keyinfolen = get16 (buffer + 18 );
123   fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen);
124   /* fixme: check bounds */
125   p = buffer + 20;
126   for (n=0; n < nkeys; n++, p += keyinfolen)
127     {
128       int i;
129       ulong kidoff, kflags;
130     
131       fprintf (fp, "Key-%lu-Fpr: ", n );
132       for (i=0; i < 20; i++ )
133         fprintf (fp, "%02X", p[i]);
134       kidoff = get32 (p + 20);
135       fprintf (fp, "\nKey-%lu-Kid-Off: %lu\n", n, kidoff );
136       fprintf (fp, "Key-%lu-Kid: ", n );
137       /* fixme: check bounds */
138       for (i=0; i < 8; i++ )
139         fprintf (fp, "%02X", buffer[kidoff+i] );
140       kflags = get16 (p + 24 );
141       fprintf( fp, "\nKey-%lu-Flags: %04lX\n", n, kflags);
142     }
143   
144   nuids = get16 (p);
145   fprintf (fp, "Uid-Count: %lu\n", nuids );
146   uidinfolen = get16  (p + 2);
147   fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen);
148   /* fixme: check bounds */
149   p += 4;
150   for (n=0; n < nuids; n++, p += uidinfolen)
151     {
152       ulong uidoff, uidlen, uflags;
153       
154       uidoff = get32( p );
155       uidlen = get32( p+4 );
156       fprintf (fp, "Uid-%lu-Off: %lu\n", n, uidoff );
157       fprintf (fp, "Uid-%lu-Len: %lu\n", n, uidlen );
158       fprintf (fp, "Uid-%lu: \"", n );
159       /*print_string (fp, buffer+uidoff, uidlen, '\"');*/
160       fputs ("\"\n", fp);
161       uflags = get16 (p + 8);
162       fprintf (fp, "Uid-%lu-Flags: %04lX\n", n, uflags );
163       fprintf (fp, "Uid-%lu-Validity: %d\n", n, p[10] );
164     }
165   
166   nsigs = get16 (p);
167   fprintf (fp, "Sig-Count: %lu\n", nsigs );
168   siginfolen = get16 (p + 2);
169   fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen );
170   /* fixme: check bounds  */
171   p += 4;
172   for (n=0; n < nsigs; n++, p += siginfolen)
173     {
174       ulong sflags;
175     
176       sflags = get32 (p);
177       fprintf (fp, "Sig-%lu-Expire: ", n );
178       if (!sflags)
179         fputs ("[not checked]", fp);
180       else if (sflags == 1 )
181         fputs ("[missing key]", fp);
182       else if (sflags == 2 )
183         fputs ("[bad signature]", fp);
184       else if (sflags < 0x10000000)
185         fprintf (fp, "[bad flag %0lx]", sflags);
186       else if (sflags == 0xffffffff)
187         fputs ("0", fp );
188       else
189         fputs ("a time"/*strtimestamp( sflags )*/, fp );
190       putc ('\n', fp );
191     }
192
193   fprintf (fp, "Ownertrust: %d\n", p[0] );
194   fprintf (fp, "All-Validity: %d\n", p[1] );
195   p += 4;
196   n = get32 (p); p += 4;
197   fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" );
198   n = get32 (p ); p += 4;
199   fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ );
200   n = get32 (p ); p += 4;
201   fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ );
202   n = get32 (p ); p += 4;
203   fprintf (fp, "Reserved-Space: %lu\n", n );
204
205   /* check that the keyblock is at the correct offset and other bounds */
206   /*fprintf (fp, "Blob-Checksum: [MD5-hash]\n");*/
207   return 0;
208 }
209
210
211 \f
212 int
213 _keybox_dump_file (const char *filename, FILE *outfp)
214 {
215   FILE *fp;
216   KEYBOXBLOB blob;
217   int rc;
218   unsigned long count = 0;
219
220   if (!filename)
221     {
222       filename = "-";
223       fp = stdin;
224     }
225   else
226     fp = fopen (filename, "rb");
227   if (!fp)
228     {
229       fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno));
230       return KEYBOX_File_Error;
231     }
232
233   while ( !(rc = _keybox_read_blob (&blob, fp)) )
234     {
235       fprintf (outfp, "BEGIN-RECORD: %lu\n", count );
236       _keybox_dump_blob (blob, outfp);
237       _keybox_release_blob (blob);
238       fprintf (outfp, "END-RECORD\n");
239       count++;
240     }
241   if (rc == -1)
242     rc = 0;
243   if (rc)
244     fprintf (outfp, "error reading `%s': %s\n", filename,
245              rc == KEYBOX_Read_Error? keybox_strerror(rc):strerror (errno));
246   
247   if (fp != stdin)
248     fclose (fp);
249   return rc;
250 }