root/openpgpsdk/trunk/examples/build-keyring.c

Revision 436 (checked in by ben, 6 years ago)

Constification, fix makefile, return key instead of keyid.

Line 
1 #include <openpgpsdk/packet.h>
2 #include <openpgpsdk/packet-parse.h>
3 #include <openpgpsdk/packet-show.h>
4 #include <openpgpsdk/configure.h>
5 #include <openpgpsdk/util.h>
6 #include <openpgpsdk/errors.h>
7 #include <openpgpsdk/armour.h>
8 #include <openpgpsdk/crypto.h>
9 #include <openpgpsdk/keyring.h>
10 #include <openpgpsdk/accumulate.h>
11
12 #include <unistd.h>
13 #include <stdio.h>
14 #include <assert.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <fcntl.h>
18
19 #include <openpgpsdk/final.h>
20
21 static int indent=0;
22 static const char *pname;
23 static ops_keyring_t keyring;
24 static ops_boolean_t passphrase_prompt;
25
26 static void print_indent()
27     {
28     int i=0;
29
30     for(i=0 ; i < indent ; i++)
31         printf("  ");
32     }
33
34 static void showtime(const char *name,time_t t)
35     {
36     printf("%s=" TIME_T_FMT " (%.24s)",name,t,ctime(&t));
37     }
38
39 static void print_bn( const char *name, const BIGNUM *bn)
40     {
41     print_indent();
42     printf("%s=",name);
43     if(bn)
44         {
45         BN_print_fp(stdout,bn);
46         putchar('\n');
47         }
48     else
49         puts("(unset)");
50     }
51
52 static void print_time( char *name, time_t time)
53     {
54     print_indent();
55     printf("%s: ",name);
56     showtime("time",time);
57     printf("\n");
58     }
59
60 static void print_duration(char *name, time_t time)
61     {
62     int mins, hours, days, years;
63
64     print_indent();
65     printf("%s: ",name);
66     printf("duration " TIME_T_FMT " seconds",time);
67
68     mins=time/60;
69     hours=mins/60;
70     days=hours/24;
71     years=days/365;
72
73     printf(" (approx. ");
74     if (years)
75         printf("%d %s",years,years==1?"year":"years");
76     else if (days)
77         printf("%d %s",days,days==1?"day":"days");
78     else if (hours)
79         printf("%d %s", hours, hours==1?"hour":"hours");
80
81     printf(")");
82     printf("\n");
83     }
84
85 static void print_name(const char *name)
86     {
87     print_indent();
88     if(name)
89         printf("%s: ",name);
90     }
91
92 static void print_text_breakdown( ops_text_t *text)
93     {
94     unsigned i;
95     char *prefix=".. ";
96
97     /* these were recognised */
98
99     for(i=0 ; i<text->known.used ; i++)
100         {
101         print_indent();
102         printf(prefix);
103         printf("%s\n",text->known.strings[i]);
104         }
105
106     /* these were not recognised. the strings will contain the hex value
107        of the unrecognised value in string format - see process_octet_str()
108     */
109
110     if(text->unknown.used)
111         {
112         printf("\n");
113         print_indent();
114         printf("Not Recognised: ");
115         }
116     for( i=0; i < text->unknown.used; i++)
117         {
118         print_indent();
119         printf(prefix);
120         printf("%s\n",text->unknown.strings[i]);
121         }
122        
123     }
124
125 static void printhex(const unsigned char *src,size_t length)
126     {
127     while(length--)
128         printf("%02X",*src++);
129     }
130
131 static void print_hexdump(const char *name,
132                           const unsigned char *data,
133                           unsigned int len)
134     {
135     print_name(name);
136
137     printf("len=%d, data=0x", len);
138     printhex(data,len);
139     printf("\n");
140     }
141
142 static void print_hexdump_data(const char *name,
143                                const unsigned char *data,
144                                unsigned int len)
145     {
146     print_name(name);
147
148     printf("0x");
149     printhex(data,len);
150     printf("\n");
151     }
152
153 static void print_data(const char *name,const ops_data_t *data)
154     {
155     print_hexdump(name,data->contents,data->len);
156     }
157
158
159 static void print_boolean(const char *name, unsigned char bool)
160     {
161     print_name(name);
162
163     if(bool)
164         printf("Yes");
165     else
166         printf("No");
167     printf("\n");
168     }
169
170 static void print_tagname(const char *str)
171     {
172     print_indent();
173     printf("%s packet\n", str);
174     }
175
176 static void print_escaped(const unsigned char *data,size_t length)
177     {
178     while(length-- > 0)
179         {
180         if((*data >= 0x20 && *data < 0x7f && *data != '%') || *data == '\n')
181             putchar(*data);
182         else
183             printf("%%%02x",*data);
184         ++data;
185         }
186     }
187
188 static void print_string(const char *name,const char *str)
189     {
190     print_name(name);
191     print_escaped((unsigned char *)str,strlen(str));
192     putchar('\n');
193     }
194
195 static void print_utf8_string(const char *name,const unsigned char *str)
196     {
197     // \todo Do this better for non-English character sets
198     print_string(name,(const char *)str);
199     }
200
201 static void print_block(const char *name,const unsigned char *str,
202                         size_t length)
203     {
204     int o=length;
205
206     print_indent();
207     printf(">>>>> %s >>>>>\n",name);
208
209     print_indent();
210     for( ; length > 0 ; --length)
211         {
212         if(*str >= 0x20 && *str < 0x7f && *str != '%')
213             putchar(*str);
214         else if(*str == '\n')
215             {
216             putchar(*str);
217             print_indent();
218             }
219         else
220             printf("%%%02x",*str);
221         ++str;
222         }
223     if(o && str[-1] != '\n')
224         {
225         putchar('\n');
226         print_indent();
227         fputs("[no newline]",stdout);
228         }
229     else
230         print_indent();
231     printf("<<<<< %s <<<<<\n",name);
232     }
233
234 static void print_headers(const ops_headers_t *headers)
235     {
236     unsigned n;
237
238     for(n=0 ; n < headers->nheaders ; ++n)
239         printf("%s=%s\n",headers->headers[n].key,headers->headers[n].value);
240     }
241
242 static void print_unsigned_int(char *name, unsigned int val)
243     {
244     print_name(name);
245     printf("%d\n", val);
246     }
247
248 static void print_string_and_value(char *name,const char *str,
249                                    unsigned char value)
250     {
251     print_name(name);
252
253     printf("%s", str);
254     printf(" (0x%x)", value);
255     printf("\n");
256     }
257
258 static void start_subpacket(unsigned type)
259     {
260     indent++;
261     print_indent();
262     printf("-- %s (type 0x%02x)\n",
263            ops_show_ss_type(type),
264            type-OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
265     }
266  
267 static void end_subpacket()
268     {
269     indent--;
270     }
271
272 static void print_packet(const ops_packet_t *packet)
273     {
274     unsigned char *cur;
275     int i;
276     int rem;
277     int blksz=4;
278
279     printf("\nhexdump of packet contents follows:\n");
280
281
282     for (i=1,cur=packet->raw; cur<(packet->raw+packet->length); cur+=blksz,i++)
283         {
284         rem = packet->raw+packet->length-cur;
285         hexdump(cur,rem<=blksz ? rem : blksz);
286         printf(" ");
287         if (!(i%8))
288             printf("\n");
289        
290         }
291    
292     printf("\n");
293     }
294
295 static void print_public_key(const ops_public_key_t *key)
296     {
297     print_unsigned_int("Version",key->version);
298     print_time("Creation Time", key->creation_time);
299     if(key->version == OPS_V3)
300         print_unsigned_int("Days Valid",key->days_valid);
301
302     print_string_and_value("Algorithm",ops_show_pka(key->algorithm),
303                            key->algorithm);
304
305     switch(key->algorithm)
306         {
307     case OPS_PKA_DSA:
308         print_bn("p",key->key.dsa.p);
309         print_bn("q",key->key.dsa.q);
310         print_bn("g",key->key.dsa.g);
311         print_bn("y",key->key.dsa.y);
312         break;
313
314     case OPS_PKA_RSA:
315     case OPS_PKA_RSA_ENCRYPT_ONLY:
316     case OPS_PKA_RSA_SIGN_ONLY:
317         print_bn("n",key->key.rsa.n);
318         print_bn("e",key->key.rsa.e);
319         break;
320
321     case OPS_PKA_ELGAMAL:
322     case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
323         print_bn("p",key->key.elgamal.p);
324         print_bn("g",key->key.elgamal.g);
325         print_bn("y",key->key.elgamal.y);
326         break;
327
328     default:
329         assert(0);
330         }
331     }
332
333 static void print_secret_key(ops_content_tag_t tag,const ops_secret_key_t *sk)
334     {
335     if(tag == OPS_PTAG_CT_SECRET_KEY)
336         print_tagname("SECRET_KEY");
337     else
338         print_tagname("ENCRYPTED_SECRET_KEY");
339     print_public_key(&sk->public_key);
340     printf("S2K Usage: %d\n",sk->s2k_usage);
341     if(sk->s2k_usage != OPS_S2KU_NONE)
342         {
343         printf("S2K Specifier: %d\n",sk->s2k_specifier);
344         printf("Symmetric algorithm: %d (%s)\n",sk->algorithm,
345                ops_show_symmetric_algorithm(sk->algorithm));
346         printf("Hash algorithm: %d (%s)\n",sk->hash_algorithm,
347                ops_show_hash_algorithm(sk->hash_algorithm));
348         if(sk->s2k_specifier != OPS_S2KS_SIMPLE)
349             print_hexdump("Salt",sk->salt,sizeof sk->salt);
350         if(sk->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED)
351             printf("Octet count: %d\n",sk->octet_count);
352         print_hexdump("IV",sk->iv,ops_block_size(sk->algorithm));
353         }
354
355     /* no more set if encrypted */
356     if(tag == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY)
357         return;
358
359     switch(sk->public_key.algorithm)
360         {
361     case OPS_PKA_RSA:
362         print_bn("d",sk->key.rsa.d);
363         print_bn("p",sk->key.rsa.p);
364         print_bn("q",sk->key.rsa.q);
365         print_bn("u",sk->key.rsa.u);
366         break;
367
368     case OPS_PKA_DSA:
369         print_bn("x",sk->key.dsa.x);
370         break;
371
372     default:
373         assert(0);
374         }
375
376     if(sk->s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
377         print_hexdump("Checkhash",sk->checkhash,OPS_CHECKHASH_SIZE);
378     else
379         printf("Checksum: %04x\n",sk->checksum);
380     }
381
382 static void print_pk_session_key(ops_content_tag_t tag,
383                                  const ops_pk_session_key_t *key)
384     {
385     if(tag == OPS_PTAG_CT_PK_SESSION_KEY)
386         print_tagname("PUBLIC KEY SESSION KEY");
387     else
388         print_tagname("ENCRYPTED PUBLIC KEY SESSION KEY");
389        
390     printf("Version: %d\n",key->version);
391     print_hexdump("Key ID",key->key_id,sizeof key->key_id);
392     printf("Algorithm: %d (%s)\n",key->algorithm,
393            ops_show_pka(key->algorithm));
394     switch(key->algorithm)
395         {
396     case OPS_PKA_RSA:
397         print_bn("encrypted_m",key->parameters.rsa.encrypted_m);
398         break;
399
400     case OPS_PKA_ELGAMAL:
401         print_bn("g_to_k",key->parameters.elgamal.g_to_k);
402         print_bn("encrypted_m",key->parameters.elgamal.encrypted_m);
403         break;
404
405     default:
406         assert(0);
407         }
408
409     if(tag != OPS_PTAG_CT_PK_SESSION_KEY)
410         return;
411
412     printf("Symmetric algorithm: %d (%s)\n",key->symmetric_algorithm,
413            ops_show_symmetric_algorithm(key->symmetric_algorithm));
414     print_hexdump("Key",key->key,ops_key_size(key->symmetric_algorithm));
415     printf("Checksum: %04x\n",key->checksum);
416     }
417
418 static ops_parse_cb_return_t callback(const ops_parser_content_t *content_,
419                                       ops_parse_cb_info_t *cbinfo)
420     {
421     const ops_parser_content_union_t *content=&content_->content;
422     ops_text_t *text;
423     const char *str;
424     const ops_key_data_t *decrypter;
425     const ops_secret_key_t *secret;
426     static ops_boolean_t unarmoured;
427
428     OPS_USED(cbinfo);
429
430     if(unarmoured && content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT)
431         {
432         unarmoured=ops_false;
433         puts("UNARMOURED TEXT ends");
434         }
435
436     switch(content_->tag)
437         {
438     case OPS_PARSER_ERROR:
439         printf("parse error: %s\n",content->error.error);
440         break;
441
442     case OPS_PARSER_ERRCODE:
443         printf("parse error: %s\n",
444                ops_errcode(content->errcode.errcode));
445         break;
446
447     case OPS_PARSER_PACKET_END:
448         print_packet(&content->packet);
449         break;
450
451     case OPS_PARSER_PTAG:
452         if(content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY)
453             {
454             indent=0;
455             printf("\n*** NEXT KEY ***\n");
456             }
457
458         printf("\n");
459         print_indent();
460         printf("==== ptag new_format=%d content_tag=%d length_type=%d"
461                " length=0x%x (%d) position=0x%x (%d)\n",content->ptag.new_format,
462                content->ptag.content_tag,content->ptag.length_type,
463                content->ptag.length,content->ptag.length,
464                content->ptag.position,content->ptag.position);
465         /*
466         print_tagname(ops_str_from_single_packet_tag(content->ptag.content_tag));
467         */
468         break;
469
470     case OPS_PTAG_CT_SE_DATA_HEADER:
471         print_tagname("SYMMETRIC ENCRYPTED DATA");
472         break;
473
474     case OPS_PTAG_CT_SE_IP_DATA_HEADER:
475         print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER");
476         printf("Version: %d\n",content->se_ip_data_header.version);
477         break;
478
479     case OPS_PTAG_CT_SE_IP_DATA_BODY:
480         print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY");
481         printf("  data body length=%d\n",
482                content->se_data_body.length);
483         printf("    data=");
484         hexdump(content->se_data_body.data,
485                 content->se_data_body.length);
486         printf("\n");
487         break;
488
489     case OPS_PTAG_CT_PUBLIC_KEY:
490     case OPS_PTAG_CT_PUBLIC_SUBKEY:
491         if (content_->tag == OPS_PTAG_CT_PUBLIC_KEY)
492             print_tagname("PUBLIC KEY");
493         else
494             print_tagname("PUBLIC SUBKEY");
495
496         print_public_key(&content->public_key);
497         break;
498
499     case OPS_PTAG_CT_TRUST:
500         print_tagname("TRUST");
501         print_data("Trust",&content->trust.data);
502         break;
503        
504     case OPS_PTAG_CT_USER_ID:
505         /* XXX: how do we print UTF-8? */
506         print_tagname("USER ID");
507         print_utf8_string("user_id",content->user_id.user_id);
508         break;
509
510     case OPS_PTAG_CT_SIGNATURE:
511         print_tagname("SIGNATURE");
512         print_indent(indent);
513         print_unsigned_int("Signature Version",
514                content->signature.version);
515         if (content->signature.creation_time_set)
516             print_time("Signature Creation Time",
517                        content->signature.creation_time);
518
519         print_string_and_value("Signature Type",
520                                ops_show_sig_type(content->signature.type),
521                                content->signature.type);
522
523         if(content->signature.signer_id_set)
524             print_hexdump_data("Signer ID",
525                                content->signature.signer_id,
526                                sizeof content->signature.signer_id);
527
528         print_string_and_value("Public Key Algorithm",
529                                ops_show_pka(content->signature.key_algorithm),
530                                content->signature.key_algorithm);
531         print_string_and_value("Hash Algorithm",
532                                ops_show_hash_algorithm(content->signature.hash_algorithm),
533                                content->signature.hash_algorithm);
534
535         print_indent();
536         print_hexdump_data("hash2",&content->signature.hash2[0],2);
537
538         switch(content->signature.key_algorithm)
539             {
540         case OPS_PKA_RSA:
541         case OPS_PKA_RSA_SIGN_ONLY:
542             print_bn("sig",content->signature.signature.rsa.sig);
543             break;
544
545         case OPS_PKA_DSA:
546             print_bn("r",content->signature.signature.dsa.r);
547             print_bn("s",content->signature.signature.dsa.s);
548             break;
549
550         case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
551             print_bn("r",content->signature.signature.elgamal.r);
552             print_bn("s",content->signature.signature.elgamal.s);
553             break;
554
555         default:
556             assert(0);
557             }
558
559         if(content->signature.hash)
560             printf("data hash is set\n");
561
562         break;
563
564     case OPS_PTAG_CT_COMPRESSED:
565         print_tagname("COMPRESSED");
566         print_unsigned_int("Compressed Data Type", content->compressed.type);
567         break;
568
569     case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
570         print_tagname("ONE PASS SIGNATURE");
571
572         print_unsigned_int("Version",content->one_pass_signature.version);
573         print_string_and_value("Signature Type",
574                                ops_show_sig_type(content->one_pass_signature.sig_type),
575                                content->one_pass_signature.sig_type);
576         print_string_and_value("Hash Algorithm",
577                                ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm),
578                                content->one_pass_signature.hash_algorithm);
579         print_string_and_value("Public Key Algorithm",
580                                ops_show_pka(content->one_pass_signature.key_algorithm),
581                                content->one_pass_signature.key_algorithm);
582         print_hexdump_data("Signer ID",
583                            content->one_pass_signature.keyid,
584                            sizeof content->one_pass_signature.keyid);
585
586         print_unsigned_int("Nested",
587                            content->one_pass_signature.nested);
588         break;
589
590     case OPS_PTAG_CT_USER_ATTRIBUTE:
591         print_tagname("USER ATTRIBUTE");
592         print_hexdump("User Attribute",
593                       content->user_attribute.data.contents,
594                       content->user_attribute.data.len);
595         break;
596
597     case OPS_PTAG_RAW_SS:
598         assert(!content_->critical);
599         start_subpacket(content_->tag);
600         print_unsigned_int("Raw Signature Subpacket: tag",
601                            content->ss_raw.tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE);
602         print_hexdump("Raw Data",
603                       content->ss_raw.raw,
604                       content->ss_raw.length);
605         break;
606
607     case OPS_PTAG_SS_CREATION_TIME:
608         start_subpacket(content_->tag);
609         print_time("Signature Creation Time",content->ss_time.time);
610         end_subpacket();
611         break;
612
613     case OPS_PTAG_SS_EXPIRATION_TIME:
614         start_subpacket(content_->tag);
615         print_duration("Signature Expiration Time",content->ss_time.time);
616         end_subpacket();
617         break;
618
619     case OPS_PTAG_SS_KEY_EXPIRATION_TIME:
620         start_subpacket(content_->tag);
621         print_duration("Key Expiration Time", content->ss_time.time);
622         end_subpacket();
623         break;
624
625     case OPS_PTAG_SS_TRUST:
626         start_subpacket(content_->tag);
627         print_string("Trust Signature","");
628         print_unsigned_int("Level",
629                            content->ss_trust.level);
630         print_unsigned_int("Amount",
631                            content->ss_trust.amount);
632         end_subpacket();
633         break;
634                
635     case OPS_PTAG_SS_REVOCABLE:
636         start_subpacket(content_->tag);
637         print_boolean("Revocable",content->ss_revocable.revocable);
638         end_subpacket();
639         break;     
640
641     case OPS_PTAG_SS_REVOCATION_KEY:
642         start_subpacket(content_->tag);
643         /* not yet tested */
644         printf ("  revocation key: class=0x%x",
645                 content->ss_revocation_key.class);
646         if (content->ss_revocation_key.class&0x40)
647             printf (" (sensitive)");
648         printf (", algid=0x%x",
649                 content->ss_revocation_key.algid);
650         printf(", fingerprint=");
651         hexdump(content->ss_revocation_key.fingerprint,20);
652         printf("\n");
653         end_subpacket();
654         break;
655    
656     case OPS_PTAG_SS_ISSUER_KEY_ID:
657         start_subpacket(content_->tag);
658         print_hexdump("Issuer Key Id",
659                       &content->ss_issuer_key_id.key_id[0],
660                       sizeof content->ss_issuer_key_id.key_id);
661         end_subpacket();
662         break;
663
664     case OPS_PTAG_SS_PREFERRED_SKA:
665         start_subpacket(content_->tag);
666         print_data( "Preferred Symmetric Algorithms",
667                    &content->ss_preferred_ska.data);
668
669         text = ops_showall_ss_preferred_ska(content->ss_preferred_ska);
670         print_text_breakdown(text);
671         ops_text_free(text);
672
673         end_subpacket();
674         break;
675
676     case OPS_PTAG_SS_PRIMARY_USER_ID:
677         start_subpacket(content_->tag);
678         print_boolean("Primary User ID",
679                       content->ss_primary_user_id.primary_user_id);
680         end_subpacket();
681         break;     
682
683     case OPS_PTAG_SS_PREFERRED_HASH:
684         start_subpacket(content_->tag);
685         print_data("Preferred Hash Algorithms",
686                    &content->ss_preferred_hash.data);
687
688         text = ops_showall_ss_preferred_hash(content->ss_preferred_hash);
689         print_text_breakdown(text);
690         ops_text_free(text);
691         end_subpacket();
692         break;
693
694     case OPS_PTAG_SS_PREFERRED_COMPRESSION:
695         start_subpacket(content_->tag);
696         print_data( "Preferred Compression Algorithms",
697                    &content->ss_preferred_compression.data);
698
699         text = ops_showall_ss_preferred_compression(content->ss_preferred_compression);
700         print_text_breakdown(text);
701         ops_text_free(text);
702         end_subpacket();
703         break;
704        
705     case OPS_PTAG_SS_KEY_FLAGS:
706         start_subpacket(content_->tag);
707         print_data( "Key Flags", &content->ss_key_flags.data);
708
709         text = ops_showall_ss_key_flags(content->ss_key_flags);
710         print_text_breakdown( text);
711         ops_text_free(text);
712
713         end_subpacket();
714         break;
715        
716     case OPS_PTAG_SS_KEY_SERVER_PREFS:
717         start_subpacket(content_->tag);
718         print_data( "Key Server Preferences",
719                    &content->ss_key_server_prefs.data);
720
721         text = ops_showall_ss_key_server_prefs(content->ss_key_server_prefs);
722         print_text_breakdown( text);
723         ops_text_free(text);
724
725         end_subpacket();
726         break;
727        
728     case OPS_PTAG_SS_FEATURES:
729         start_subpacket(content_->tag);
730         print_data( "Features",
731                    &content->ss_features.data);
732
733         text = ops_showall_ss_features(content->ss_features);
734         print_text_breakdown( text);
735         ops_text_free(text);
736
737         end_subpacket();
738         break;
739
740     case OPS_PTAG_SS_NOTATION_DATA:
741         start_subpacket(content_->tag);
742         print_indent();
743         printf("Notation Data:\n");
744
745         indent++;
746         print_data( "Flags",
747                    &content->ss_notation_data.flags);
748         text = ops_showall_ss_notation_data_flags(content->ss_notation_data);
749         print_text_breakdown( text);
750         ops_text_free(text);
751
752         /* xxx - TODO: print out UTF - rachel */
753
754         print_data( "Name",
755                    &content->ss_notation_data.name);
756
757         print_data( "Value",
758                    &content->ss_notation_data.value);
759
760         indent--;
761         end_subpacket();
762         break;
763
764     case OPS_PTAG_SS_REGEXP:
765         start_subpacket(content_->tag);
766         print_hexdump("Regular Expression",
767                       (unsigned char *)content->ss_regexp.text,
768                       strlen(content->ss_regexp.text));
769         print_string(NULL,
770                      content->ss_regexp.text);
771         end_subpacket();
772         break;
773
774     case OPS_PTAG_SS_POLICY_URL:
775         start_subpacket(content_->tag);
776         print_string("Policy URL",
777                      content->ss_policy_url.text);
778         end_subpacket();
779         break;
780
781     case OPS_PTAG_SS_SIGNERS_USER_ID:
782         start_subpacket(content_->tag);
783         print_utf8_string("Signer's User ID",content->ss_signers_user_id.user_id);
784         end_subpacket();
785         break;
786
787     case OPS_PTAG_SS_PREFERRED_KEY_SERVER:
788         start_subpacket(content_->tag);
789         print_string("Preferred Key Server",
790                      content->ss_preferred_key_server.text);
791         end_subpacket();
792         break;
793
794     case OPS_PTAG_SS_USERDEFINED00:
795     case OPS_PTAG_SS_USERDEFINED01:
796     case OPS_PTAG_SS_USERDEFINED02:
797     case OPS_PTAG_SS_USERDEFINED03:
798     case OPS_PTAG_SS_USERDEFINED04:
799     case OPS_PTAG_SS_USERDEFINED05:
800     case OPS_PTAG_SS_USERDEFINED06:
801     case OPS_PTAG_SS_USERDEFINED07:
802     case OPS_PTAG_SS_USERDEFINED08:
803     case OPS_PTAG_SS_USERDEFINED09:
804     case OPS_PTAG_SS_USERDEFINED10:
805         start_subpacket(content_->tag);
806         print_hexdump("Internal or user-defined",
807                       content->ss_userdefined.data.contents,
808                       content->ss_userdefined.data.len);
809         end_subpacket();
810         break;
811
812     case OPS_PTAG_SS_RESERVED:
813         start_subpacket(content_->tag);
814         print_hexdump("Reserved",
815                       content->ss_userdefined.data.contents,
816                       content->ss_userdefined.data.len);
817         end_subpacket();
818         break;
819
820     case OPS_PTAG_SS_REVOCATION_REASON:
821         start_subpacket(content_->tag);
822         print_hexdump("Revocation Reason",
823                       &content->ss_revocation_reason.code,
824                       1);
825         str=ops_show_ss_rr_code(content->ss_revocation_reason.code);
826         print_string(NULL,str);
827         /* xxx - todo : output text as UTF-8 string */
828         end_subpacket();
829         break;
830
831     case OPS_PTAG_CT_LITERAL_DATA_HEADER:
832         print_tagname("LITERAL DATA HEADER");
833         printf("  literal data header format=%c filename='%s'\n",
834                content->literal_data_header.format,
835                content->literal_data_header.filename);
836         showtime("    modification time",
837                  content->literal_data_header.modification_time);
838         printf("\n");
839         break;
840
841     case OPS_PTAG_CT_LITERAL_DATA_BODY:
842         print_tagname("LITERAL DATA BODY");
843         printf("  literal data body length=%d\n",
844                content->literal_data_body.length);
845         printf("    data=");
846         print_escaped(content->literal_data_body.data,
847                       content->literal_data_body.length);
848         printf("\n");
849         break;
850
851     case OPS_PTAG_CT_SIGNATURE_HEADER:
852         print_tagname("SIGNATURE");
853         print_indent(indent);
854         print_unsigned_int("Signature Version",
855                content->signature.version);
856         if(content->signature.creation_time_set)
857             print_time("Signature Creation Time", content->signature.creation_time);
858
859         print_string_and_value("Signature Type",
860                                ops_show_sig_type(content->signature.type),
861                                content->signature.type);
862
863         if(content->signature.signer_id_set)
864             print_hexdump_data("Signer ID",
865                                content->signature.signer_id,
866                                sizeof content->signature.signer_id);
867
868         print_string_and_value("Public Key Algorithm",
869                                ops_show_pka(content->signature.key_algorithm),
870                                content->signature.key_algorithm);
871         print_string_and_value("Hash Algorithm",
872                                ops_show_hash_algorithm(content->signature.hash_algorithm),
873                                content->signature.hash_algorithm);
874
875         break;
876
877     case OPS_PTAG_CT_SIGNATURE_FOOTER:
878         print_indent();
879         print_hexdump_data("hash2",&content->signature.hash2[0],2);
880
881         switch(content->signature.key_algorithm)
882             {
883         case OPS_PKA_RSA:
884             print_bn("sig",content->signature.signature.rsa.sig);
885             break;
886
887         case OPS_PKA_DSA:
888             print_bn("r",content->signature.signature.dsa.r);
889             print_bn("s",content->signature.signature.dsa.s);
890             break;
891
892         case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
893             print_bn("r",content->signature.signature.elgamal.r);
894             print_bn("s",content->signature.signature.elgamal.s);
895             break;
896
897         case OPS_PKA_PRIVATE00:
898         case OPS_PKA_PRIVATE01:
899         case OPS_PKA_PRIVATE02:
900         case OPS_PKA_PRIVATE03:
901         case OPS_PKA_PRIVATE04:
902         case OPS_PKA_PRIVATE05:
903         case OPS_PKA_PRIVATE06:
904         case OPS_PKA_PRIVATE07:
905         case OPS_PKA_PRIVATE08:
906         case OPS_PKA_PRIVATE09:
907         case OPS_PKA_PRIVATE10:
908             print_data("Private/Experimental",
909                        &content->signature.signature.unknown.data);
910             break;
911
912         default:
913             assert(0);
914             }
915         break;
916
917     case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
918         if(passphrase_prompt)
919             {
920             print_secret_key(OPS_PTAG_CT_ENCRYPTED_SECRET_KEY,
921                              content->secret_key_passphrase.secret_key);
922             *content->secret_key_passphrase.passphrase=ops_get_passphrase();
923             if(!**content->secret_key_passphrase.passphrase)
924                 break;
925             return OPS_KEEP_MEMORY;
926             }
927         else
928             printf(">>> ASKED FOR PASSPHRASE <<<\n");
929         break;
930
931     case OPS_PTAG_CT_SECRET_KEY:
932     case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
933         print_secret_key(content_->tag,&content->secret_key);
934         break;
935
936     case OPS_PTAG_CT_ARMOUR_HEADER:
937         print_tagname("ARMOUR HEADER");
938         print_string("type",content->armour_header.type);
939         break;
940
941     case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
942         print_tagname("SIGNED CLEARTEXT HEADER");
943         print_headers(&content->signed_cleartext_header.headers);
944         break;
945
946     case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
947         print_tagname("SIGNED CLEARTEXT BODY");
948         print_block("signed cleartext",content->signed_cleartext_body.data,
949                     content->signed_cleartext_body.length);
950         break;
951
952     case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
953         print_tagname("SIGNED CLEARTEXT TRAILER");
954         printf("hash algorithm: %d\n",
955                content->signed_cleartext_trailer.hash->algorithm);
956         printf("\n");
957         break;
958
959     case OPS_PTAG_CT_UNARMOURED_TEXT:
960         if(!unarmoured)
961             {
962             print_tagname("UNARMOURED TEXT");
963             unarmoured=ops_true;
964             }
965         putchar('[');
966         print_escaped(content->unarmoured_text.data,
967                       content->unarmoured_text.length);
968         putchar(']');
969         break;
970
971     case OPS_PTAG_CT_ARMOUR_TRAILER:
972         print_tagname("ARMOUR TRAILER");
973         print_string("type",content->armour_header.type);
974         break;
975
976     case OPS_PTAG_CT_PK_SESSION_KEY:
977     case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
978         print_pk_session_key(content_->tag,&content->pk_session_key);
979         break;
980
981     case OPS_PARSER_CMD_GET_SECRET_KEY:
982         print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,
983                              content->get_secret_key.pk_session_key);
984
985         decrypter=ops_keyring_find_key_by_id(&keyring,
986                                              content->get_secret_key.pk_session_key->key_id);
987         if(!decrypter || !ops_key_is_secret(decrypter))
988             break;
989
990         puts("[Decryption key found in keyring]");
991
992         secret=ops_get_secret_key_from_data(decrypter);
993         while(!secret)
994             {
995             /* then it must be encrypted */
996             char *phrase=ops_get_passphrase();
997             secret=ops_decrypt_secret_key_from_data(decrypter,phrase);
998             free(phrase);
999             }
1000
1001         *content->get_secret_key.secret_key=secret;
1002        
1003         break;
1004
1005     default:
1006         print_tagname("UNKNOWN PACKET TYPE");
1007         fprintf(stderr,"packet-dump: unknown tag=%d (0x%x)\n",content_->tag,
1008                 content_->tag);
1009         exit(1);
1010         }
1011     return OPS_RELEASE_MEMORY;
1012     }
1013
1014 static void usage()
1015     {
1016     fprintf(stderr,"%s [-a] [-b] <file name>\n\n",pname);
1017     fprintf(stderr,"-a\tRead armoured data\n"
1018             "-b\tDon't buffer stdout/stderr\n"
1019             "-B\tRead via a memory buffer\n"
1020             "-k <file>\tRead in a keyring\n"
1021             "-p\tPrompt for passphrases\n");
1022    
1023     exit(1);
1024     }
1025
1026 int main(int argc,char **argv)
1027     {
1028     ops_parse_info_t *pinfo;
1029     ops_boolean_t armour=ops_false;
1030     int ret;
1031     int ch;
1032     int fd;
1033     ops_boolean_t buffer_read=ops_false;
1034     unsigned char buffer[10240];
1035     const char *keyring_file=NULL;
1036
1037     pname=argv[0];
1038
1039     while((ch=getopt(argc,argv,"abBk:p")) != -1)
1040         switch(ch)
1041             {
1042         case 'a':
1043             armour=ops_true;
1044             break;
1045
1046         case 'b':
1047             setvbuf(stdout,NULL,_IONBF,0);
1048             setvbuf(stderr,NULL,_IONBF,0);
1049             break;
1050
1051         case 'B':
1052             buffer_read=ops_true;
1053             break;
1054
1055         case 'k':
1056             keyring_file=optarg;
1057             break;
1058
1059         case 'p':
1060             passphrase_prompt=ops_true;
1061             break;
1062
1063         default:
1064             usage();
1065             }
1066     argc-=optind;
1067     argv+=optind;
1068
1069     if(argc != 1)
1070         usage();
1071
1072     setvbuf(stdout,NULL,_IONBF,0);
1073
1074     if(keyring_file)
1075         ops_keyring_read(&keyring,keyring_file);
1076
1077     fd=open(argv[0],O_RDONLY);
1078     if(fd < 0)
1079         {
1080         perror(argv[0]);
1081         exit(2);
1082         }
1083
1084     pinfo=ops_parse_info_new();
1085     //    ops_parse_packet_options(&opt,OPS_PTAG_SS_ALL,OPS_PARSE_RAW);
1086     ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED);
1087
1088     ops_parse_cb_set(pinfo,callback,NULL);
1089
1090     if(buffer_read)
1091         {
1092         int n;
1093
1094         n=read(fd,buffer,sizeof buffer);
1095         if(n < 0)
1096             {
1097             perror(argv[0]);
1098             exit(3);
1099             }
1100         ops_reader_set_memory(pinfo,buffer,n);
1101         }
1102     else
1103         ops_reader_set_fd(pinfo,fd);
1104
1105     if(armour)
1106         ops_reader_push_dearmour(pinfo,ops_true,ops_true,ops_true);
1107
1108     ret=ops_parse_and_accumulate(&keyring,pinfo);
1109     if (!ret)
1110         ops_print_errors(ops_parse_info_get_errors(pinfo));
1111
1112     ops_parse_info_delete(pinfo);
1113
1114     ops_dump_keyring(&keyring);
1115
1116     ops_finish();
1117
1118     return 0;
1119     }
Note: See TracBrowser for help on using the browser.