[w32] gpg-agent is now started automagically by gpgsm.
[gnupg.git] / g10 / misc.c
1 /* misc.c - miscellaneous functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3  *               2005, 2006 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
30 #include <asm/sysinfo.h>
31 #include <asm/unistd.h>
32 #endif
33 #ifdef HAVE_SETRLIMIT
34 #include <time.h>
35 #include <sys/time.h>
36 #include <sys/resource.h>
37 #endif
38 #ifdef ENABLE_SELINUX_HACKS
39 #include <sys/stat.h>
40 #endif
41
42 #ifdef HAVE_W32_SYSTEM
43 #include <time.h>
44 #include <process.h>
45 #include <windows.h> 
46 #include <shlobj.h>
47 #ifndef CSIDL_APPDATA
48 #define CSIDL_APPDATA 0x001a
49 #endif
50 #ifndef CSIDL_LOCAL_APPDATA
51 #define CSIDL_LOCAL_APPDATA 0x001c
52 #endif
53 #ifndef CSIDL_FLAG_CREATE
54 #define CSIDL_FLAG_CREATE 0x8000
55 #endif
56 #endif /*HAVE_W32_SYSTEM*/
57
58 #include "gpg.h"
59 #ifdef HAVE_W32_SYSTEM
60 # include "errors.h"
61 #endif /*HAVE_W32_SYSTEM*/
62 #include "util.h"
63 #include "main.h"
64 #include "photoid.h"
65 #include "options.h"
66 #include "call-agent.h"
67 #include "i18n.h"
68
69
70 static int
71 string_count_chr (const char *string, int c)
72 {
73   int count;
74
75   for (count=0; *string; string++ )
76     if ( *string == c )
77       count++;
78   return count;
79 }
80
81
82
83 #ifdef ENABLE_SELINUX_HACKS
84 /* A object and a global variable to keep track of files marked as
85    secured. */
86 struct secured_file_item 
87 {
88   struct secured_file_item *next;
89   ino_t ino;
90   dev_t dev;
91 };
92 static struct secured_file_item *secured_files;
93 #endif /*ENABLE_SELINUX_HACKS*/
94
95
96
97
98 /* For the sake of SELinux we want to restrict access through gpg to
99    certain files we keep under our own control.  This function
100    registers such a file and is_secured_file may then be used to
101    check whether a file has ben registered as secured. */
102 void
103 register_secured_file (const char *fname)
104 {
105 #ifdef ENABLE_SELINUX_HACKS
106   struct stat buf;
107   struct secured_file_item *sf;
108
109   /* Note that we stop immediatley if something goes wrong here. */
110   if (stat (fname, &buf))
111     log_fatal (_("fstat of `%s' failed in %s: %s\n"), fname, 
112                "register_secured_file", strerror (errno));
113 /*   log_debug ("registering `%s' i=%lu.%lu\n", fname, */
114 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
115   for (sf=secured_files; sf; sf = sf->next)
116     {
117       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
118         return; /* Already registered.  */
119     }
120
121   sf = xmalloc (sizeof *sf);
122   sf->ino = buf.st_ino;
123   sf->dev = buf.st_dev;
124   sf->next = secured_files;
125   secured_files = sf;
126 #endif /*ENABLE_SELINUX_HACKS*/
127 }
128
129 /* Remove a file registered as secure. */
130 void
131 unregister_secured_file (const char *fname)
132 {
133 #ifdef ENABLE_SELINUX_HACKS
134   struct stat buf;
135   struct secured_file_item *sf, *sfprev;
136
137   if (stat (fname, &buf))
138     {
139       log_error (_("fstat of `%s' failed in %s: %s\n"), fname,
140                  "unregister_secured_file", strerror (errno));
141       return;
142     }
143 /*   log_debug ("unregistering `%s' i=%lu.%lu\n", fname,  */
144 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
145   for (sfprev=NULL,sf=secured_files; sf; sfprev=sf, sf = sf->next)
146     {
147       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
148         {
149           if (sfprev)
150             sfprev->next = sf->next;
151           else
152             secured_files = sf->next;
153           xfree (sf);
154           return;
155         }
156     }
157 #endif /*ENABLE_SELINUX_HACKS*/
158 }
159
160 /* Return true if FD is corresponds to a secured file.  Using -1 for
161    FS is allowed and will return false. */ 
162 int 
163 is_secured_file (int fd)
164 {
165 #ifdef ENABLE_SELINUX_HACKS
166   struct stat buf;
167   struct secured_file_item *sf;
168
169   if (fd == -1)
170     return 0; /* No file descriptor so it can't be secured either.  */
171
172   /* Note that we print out a error here and claim that a file is
173      secure if something went wrong. */
174   if (fstat (fd, &buf))
175     {
176       log_error (_("fstat(%d) failed in %s: %s\n"), fd, 
177                  "is_secured_file", strerror (errno));
178       return 1;
179     }
180 /*   log_debug ("is_secured_file (%d) i=%lu.%lu\n", fd, */
181 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
182   for (sf=secured_files; sf; sf = sf->next)
183     {
184       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
185         return 1; /* Yes.  */
186     }
187 #endif /*ENABLE_SELINUX_HACKS*/
188   return 0; /* No. */
189 }
190
191 /* Return true if FNAME is corresponds to a secured file.  Using NULL,
192    "" or "-" for FS is allowed and will return false. This function is
193    used before creating a file, thus it won't fail if the file does
194    not exist. */ 
195 int 
196 is_secured_filename (const char *fname)
197 {
198 #ifdef ENABLE_SELINUX_HACKS
199   struct stat buf;
200   struct secured_file_item *sf;
201
202   if (iobuf_is_pipe_filename (fname) || !*fname)
203     return 0; 
204
205   /* Note that we print out a error here and claim that a file is
206      secure if something went wrong. */
207   if (stat (fname, &buf))
208     {
209       if (errno == ENOENT || errno == EPERM || errno == EACCES)
210         return 0;
211       log_error (_("fstat of `%s' failed in %s: %s\n"), fname,
212                  "is_secured_filename", strerror (errno));
213       return 1;
214     }
215 /*   log_debug ("is_secured_filename (%s) i=%lu.%lu\n", fname, */
216 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
217   for (sf=secured_files; sf; sf = sf->next)
218     {
219       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
220         return 1; /* Yes.  */
221     }
222 #endif /*ENABLE_SELINUX_HACKS*/
223   return 0; /* No. */
224 }
225
226
227
228 u16
229 checksum_u16( unsigned n )
230 {
231     u16 a;
232
233     a  = (n >> 8) & 0xff;
234     a += n & 0xff;
235     return a;
236 }
237
238
239 u16
240 checksum( byte *p, unsigned n )
241 {
242     u16 a;
243
244     for(a=0; n; n-- )
245         a += *p++;
246     return a;
247 }
248
249 u16
250 checksum_mpi (gcry_mpi_t a)
251 {
252   u16 csum;
253   byte *buffer;
254   size_t nbytes;
255
256   if ( gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a) )
257     BUG ();
258   /* Fixme: For numbers not in secure memory we should use a stack
259    * based buffer and only allocate a larger one if mpi_print returns
260    * an error. */
261   buffer = (gcry_is_secure(a)?
262             gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes));
263   if ( gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a) )
264     BUG ();
265   csum = checksum (buffer, nbytes);
266   xfree (buffer);
267   return csum;
268 }
269
270 u32
271 buffer_to_u32( const byte *buffer )
272 {
273     unsigned long a;
274     a =  *buffer << 24;
275     a |= buffer[1] << 16;
276     a |= buffer[2] << 8;
277     a |= buffer[3];
278     return a;
279 }
280
281 void
282 print_pubkey_algo_note( int algo )
283 {
284   if(algo >= 100 && algo <= 110)
285     {
286       static int warn=0;
287       if(!warn)
288         {
289           warn=1;
290           log_info (_("WARNING: using experimental public key algorithm %s\n"),
291                     gcry_pk_algo_name (algo));
292         }
293     }
294 }
295
296 void
297 print_cipher_algo_note( int algo )
298 {
299   if(algo >= 100 && algo <= 110)
300     {
301       static int warn=0;
302       if(!warn)
303         {
304           warn=1;
305           log_info (_("WARNING: using experimental cipher algorithm %s\n"),
306                     gcry_cipher_algo_name (algo));
307         }
308     }
309 }
310
311 void
312 print_digest_algo_note( int algo )
313 {
314   if(algo >= 100 && algo <= 110)
315     {
316       static int warn=0;
317       if(!warn)
318         {
319           warn=1;
320           log_info (_("WARNING: using experimental digest algorithm %s\n"),
321                     gcry_md_algo_name (algo));
322         }
323     }
324   else if(algo==DIGEST_ALGO_MD5)
325     log_info (_("WARNING: digest algorithm %s is deprecated\n"),
326               gcry_md_algo_name (algo));
327 }
328
329 /****************
330  * Wrapper around the libgcrypt function with additonal checks on
331  * the OpenPGP contraints for the algo ID.
332  */
333 int
334 openpgp_cipher_test_algo( int algo )
335 {
336   if ( algo < 0 || algo > 110 )
337     return gpg_error (GPG_ERR_CIPHER_ALGO);
338   return gcry_cipher_test_algo (algo);
339 }
340
341 int
342 openpgp_pk_test_algo( int algo )
343 {
344   if (algo == GCRY_PK_ELG_E)
345     algo = GCRY_PK_ELG;
346
347   if (algo < 0 || algo > 110)
348     return gpg_error (GPG_ERR_PUBKEY_ALGO);
349   return gcry_pk_test_algo (algo);
350 }
351
352 int
353 openpgp_pk_test_algo2( int algo, unsigned int use )
354 {
355   size_t use_buf = use;
356
357   if (algo == GCRY_PK_ELG_E)
358     algo = GCRY_PK_ELG;
359
360   if (algo < 0 || algo > 110)
361     return gpg_error (GPG_ERR_PUBKEY_ALGO);
362
363   return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &use_buf);
364 }
365
366 int 
367 openpgp_pk_algo_usage ( int algo )
368 {
369     int use = 0; 
370     
371     /* They are hardwired in gpg 1.0. */
372     switch ( algo ) {    
373       case PUBKEY_ALGO_RSA:
374           use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
375                  | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH);
376           break;
377       case PUBKEY_ALGO_RSA_E:
378           use = PUBKEY_USAGE_ENC;
379           break;
380       case PUBKEY_ALGO_RSA_S:
381           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
382           break;
383       case PUBKEY_ALGO_ELGAMAL_E:
384           use = PUBKEY_USAGE_ENC;
385           break;
386       case PUBKEY_ALGO_DSA:  
387           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
388           break;
389       default:
390           break;
391     }
392     return use;
393 }
394
395 int
396 openpgp_md_test_algo( int algo )
397 {
398   /* Note: If the list of actual supported OpenPGP algorithms changes,
399      make sure that our hard coded values at
400      print_status_begin_signing() gets updated. */
401
402   if (algo < 0 || algo > 110)
403     return gpg_error (GPG_ERR_DIGEST_ALGO);
404   return gcry_md_test_algo (algo);
405 }
406
407 #ifdef USE_IDEA
408 /* Special warning for the IDEA cipher */
409 void
410 idea_cipher_warn(int show)
411 {
412   static int warned=0;
413
414   if(!warned || show)
415     {
416       log_info(_("the IDEA cipher plugin is not present\n"));
417       log_info(_("please see %s for more information\n"),
418                "http://www.gnupg.org/faq/why-not-idea.html");
419       warned=1;
420     }
421 }
422 #endif
423
424
425 static unsigned long 
426 get_signature_count (PKT_secret_key *sk)
427 {
428 #ifdef ENABLE_CARD_SUPPORT
429   if(sk && sk->is_protected && sk->protect.s2k.mode==1002)
430     {
431       struct agent_card_info_s info;
432       if(agent_scd_getattr("SIG-COUNTER",&info)==0)
433         return info.sig_counter;
434     }  
435 #endif
436
437   /* How to do this without a card? */
438
439   return 0;
440 }
441
442 /* Expand %-strings.  Returns a string which must be xfreed.  Returns
443    NULL if the string cannot be expanded (too large). */
444 char *
445 pct_expando(const char *string,struct expando_args *args)
446 {
447   const char *ch=string;
448   int idx=0,maxlen=0,done=0;
449   u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
450   char *ret=NULL;
451
452   if(args->pk)
453     keyid_from_pk(args->pk,pk_keyid);
454
455   if(args->sk)
456     keyid_from_sk(args->sk,sk_keyid);
457
458   /* This is used so that %k works in photoid command strings in
459      --list-secret-keys (which of course has a sk, but no pk). */
460   if(!args->pk && args->sk)
461     keyid_from_sk(args->sk,pk_keyid);
462
463   while(*ch!='\0')
464     {
465       char *str=NULL;
466
467       if(!done)
468         {
469           /* 8192 is way bigger than we'll need here */
470           if(maxlen>=8192)
471             goto fail;
472
473           maxlen+=1024;
474           ret=xrealloc(ret,maxlen);
475         }
476
477       done=0;
478
479       if(*ch=='%')
480         {
481           switch(*(ch+1))
482             {
483             case 's': /* short key id */
484               if(idx+8<maxlen)
485                 {
486                   sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
487                   idx+=8;
488                   done=1;
489                 }
490               break;
491
492             case 'S': /* long key id */
493               if(idx+16<maxlen)
494                 {
495                   sprintf(&ret[idx],"%08lX%08lX",
496                           (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
497                   idx+=16;
498                   done=1;
499                 }
500               break;
501
502             case 'k': /* short key id */
503               if(idx+8<maxlen)
504                 {
505                   sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
506                   idx+=8;
507                   done=1;
508                 }
509               break;
510
511             case 'K': /* long key id */
512               if(idx+16<maxlen)
513                 {
514                   sprintf(&ret[idx],"%08lX%08lX",
515                           (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
516                   idx+=16;
517                   done=1;
518                 }
519               break;
520
521             case 'c': /* signature count from card, if any. */
522               if(idx+10<maxlen)
523                 {
524                   sprintf(&ret[idx],"%lu",get_signature_count(args->sk));
525                   idx+=strlen(&ret[idx]);
526                   done=1;
527                 }             
528               break;
529
530             case 'p': /* primary pk fingerprint of a sk */
531             case 'f': /* pk fingerprint */
532             case 'g': /* sk fingerprint */
533               {
534                 byte array[MAX_FINGERPRINT_LEN];
535                 size_t len;
536                 int i;
537
538                 if((*(ch+1))=='p' && args->sk)
539                   {
540                     if(args->sk->is_primary)
541                       fingerprint_from_sk(args->sk,array,&len);
542                     else if(args->sk->main_keyid[0] || args->sk->main_keyid[1])
543                       {
544                         PKT_public_key *pk=
545                           xmalloc_clear(sizeof(PKT_public_key));
546
547                         if(get_pubkey_fast(pk,args->sk->main_keyid)==0)
548                           fingerprint_from_pk(pk,array,&len);
549                         else
550                           memset(array,0,(len=MAX_FINGERPRINT_LEN));
551                         free_public_key(pk);
552                       }
553                     else
554                       memset(array,0,(len=MAX_FINGERPRINT_LEN));
555                   }
556                 else if((*(ch+1))=='f' && args->pk)
557                   fingerprint_from_pk(args->pk,array,&len);
558                 else if((*(ch+1))=='g' && args->sk)
559                   fingerprint_from_sk(args->sk,array,&len);
560                 else
561                   memset(array,0,(len=MAX_FINGERPRINT_LEN));
562
563                 if(idx+(len*2)<maxlen)
564                   {
565                     for(i=0;i<len;i++)
566                       {
567                         sprintf(&ret[idx],"%02X",array[i]);
568                         idx+=2;
569                       }
570                     done=1;
571                   }
572               }
573               break;
574
575             case 't': /* e.g. "jpg" */
576               str=image_type_to_string(args->imagetype,0);
577               /* fall through */
578
579             case 'T': /* e.g. "image/jpeg" */
580               if(str==NULL)
581                 str=image_type_to_string(args->imagetype,2);
582
583               if(idx+strlen(str)<maxlen)
584                 {
585                   strcpy(&ret[idx],str);
586                   idx+=strlen(str);
587                   done=1;
588                 }
589               break;
590
591             case '%':
592               if(idx+1<maxlen)
593                 {
594                   ret[idx++]='%';
595                   ret[idx]='\0';
596                   done=1;
597                 }
598               break;
599
600               /* Any unknown %-keys (like %i, %o, %I, and %O) are
601                  passed through for later expansion.  Note this also
602                  handles the case where the last character in the
603                  string is a '%' - the terminating \0 will end up here
604                  and properly terminate the string. */
605             default:
606               if(idx+2<maxlen)
607                 {
608                   ret[idx++]='%';
609                   ret[idx++]=*(ch+1);
610                   ret[idx]='\0';
611                   done=1;
612                 }
613               break;
614               }
615
616           if(done)
617             ch++;
618         }
619       else
620         {
621           if(idx+1<maxlen)
622             {
623               ret[idx++]=*ch;
624               ret[idx]='\0';
625               done=1;
626             }
627         }
628
629       if(done)
630         ch++;
631     }
632
633   return ret;
634
635  fail:
636   xfree(ret);
637   return NULL;
638 }
639
640 void
641 deprecated_warning(const char *configname,unsigned int configlineno,
642                    const char *option,const char *repl1,const char *repl2)
643 {
644   if(configname)
645     {
646       if(strncmp("--",option,2)==0)
647         option+=2;
648
649       if(strncmp("--",repl1,2)==0)
650         repl1+=2;
651
652       log_info(_("%s:%d: deprecated option \"%s\"\n"),
653                configname,configlineno,option);
654     }
655   else
656     log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
657
658   log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
659 }
660
661
662 void
663 deprecated_command (const char *name)
664 {
665   log_info(_("WARNING: \"%s\" is a deprecated command - do not use it\n"),
666            name);
667 }
668
669
670 void
671 obsolete_option (const char *configname, unsigned int configlineno, 
672                  const char *name)
673 {
674   if(configname)
675     log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
676               configname, configlineno, name);
677   else
678     log_info (_("WARNING: \"%s\" is an obsolete option - it has no effect\n"),
679               name);
680 }
681
682
683 /*
684  * Wrapper around gcry_cipher_map_name to provide a fallback using the
685  * "Sn" syntax as used by the preference strings.
686  */
687 int 
688 string_to_cipher_algo (const char *string) 
689
690   int val;
691
692   val = gcry_cipher_map_name (string);
693   if (!val && string && (string[0]=='S' || string[0]=='s'))
694     {
695       char *endptr;
696
697       string++;
698       val = strtol (string, &endptr, 10);
699       if (!*string || *endptr || openpgp_cipher_test_algo (val))
700         val = 0;
701     }
702
703   return val;
704 }
705
706 /*
707  * Wrapper around gcry_md_map_name to provide a fallback using the
708  * "Hn" syntax as used by the preference strings.
709  */
710 int 
711 string_to_digest_algo (const char *string) 
712
713   int val;
714
715   val = gcry_md_map_name (string);
716   if (!val && string && (string[0]=='H' || string[0]=='h'))
717     {
718       char *endptr;
719
720       string++;
721       val = strtol (string, &endptr, 10);
722       if (!*string || *endptr || openpgp_md_test_algo (val))
723         val = 0;
724     }
725
726   return val;
727 }
728
729
730
731 const char *
732 compress_algo_to_string(int algo)
733 {
734   const char *s=NULL;
735
736   switch(algo)
737     {
738     case COMPRESS_ALGO_NONE:
739       s=_("Uncompressed");
740       break;
741
742     case COMPRESS_ALGO_ZIP:
743       s="ZIP";
744       break;
745
746     case COMPRESS_ALGO_ZLIB:
747       s="ZLIB";
748       break;
749
750 #ifdef HAVE_BZIP2
751     case COMPRESS_ALGO_BZIP2:
752       s="BZIP2";
753       break;
754 #endif
755     }
756
757   return s;
758 }
759
760 int
761 string_to_compress_algo(const char *string)
762 {
763   /* TRANSLATORS: See doc/TRANSLATE about this string. */
764   if(match_multistr(_("uncompressed|none"),string))
765     return 0;
766   else if(ascii_strcasecmp(string,"uncompressed")==0)
767     return 0;
768   else if(ascii_strcasecmp(string,"none")==0)
769     return 0;
770   else if(ascii_strcasecmp(string,"zip")==0)
771     return 1;
772   else if(ascii_strcasecmp(string,"zlib")==0)
773     return 2;
774 #ifdef HAVE_BZIP2
775   else if(ascii_strcasecmp(string,"bzip2")==0)
776     return 3;
777 #endif
778   else if(ascii_strcasecmp(string,"z0")==0)
779     return 0;
780   else if(ascii_strcasecmp(string,"z1")==0)
781     return 1;
782   else if(ascii_strcasecmp(string,"z2")==0)
783     return 2;
784 #ifdef HAVE_BZIP2
785   else if(ascii_strcasecmp(string,"z3")==0)
786     return 3;
787 #endif
788   else
789     return -1;
790 }
791
792 int
793 check_compress_algo(int algo)
794 {
795 #ifdef HAVE_BZIP2
796   if(algo>=0 && algo<=3)
797     return 0;
798 #else
799   if(algo>=0 && algo<=2)
800     return 0;
801 #endif
802
803   return G10ERR_COMPR_ALGO;
804 }
805
806 int
807 default_cipher_algo(void)
808 {
809   if(opt.def_cipher_algo)
810     return opt.def_cipher_algo;
811   else if(opt.personal_cipher_prefs)
812     return opt.personal_cipher_prefs[0].value;
813   else
814     return opt.s2k_cipher_algo;
815 }
816
817 /* There is no default_digest_algo function, but see
818    sign.c:hash_for() */
819
820 int
821 default_compress_algo(void)
822 {
823   if(opt.compress_algo!=-1)
824     return opt.compress_algo;
825   else if(opt.personal_compress_prefs)
826     return opt.personal_compress_prefs[0].value;
827   else
828     return DEFAULT_COMPRESS_ALGO;
829 }
830
831 const char *
832 compliance_option_string(void)
833 {
834   switch(opt.compliance)
835     {
836     case CO_RFC2440:
837       return "--openpgp";
838     case CO_PGP2:
839       return "--pgp2";
840     case CO_PGP6:
841       return "--pgp6";
842     case CO_PGP7:
843       return "--pgp7";
844     case CO_PGP8:
845       return "--pgp8";
846     default:
847       return "???";
848     }
849 }
850
851 static const char *
852 compliance_string(void)
853 {
854   switch(opt.compliance)
855     {
856     case CO_RFC2440:
857       return "OpenPGP";
858     case CO_PGP2:
859       return "PGP 2.x";
860     case CO_PGP6:
861       return "PGP 6.x";
862     case CO_PGP7:
863       return "PGP 7.x";
864     case CO_PGP8:
865       return "PGP 8.x";
866     default:
867       return "???";
868     }
869 }
870
871 void
872 compliance_failure(void)
873 {
874   log_info(_("this message may not be usable by %s\n"),compliance_string());
875   opt.compliance=CO_GNUPG;
876 }
877
878 /* Break a string into successive option pieces.  Accepts single word
879    options and key=value argument options. */
880 char *
881 optsep(char **stringp)
882 {
883   char *tok,*end;
884
885   tok=*stringp;
886   if(tok)
887     {
888       end=strpbrk(tok," ,=");
889       if(end)
890         {
891           int sawequals=0;
892           char *ptr=end;
893
894           /* what we need to do now is scan along starting with *end,
895              If the next character we see (ignoring spaces) is an =
896              sign, then there is an argument. */
897
898           while(*ptr)
899             {
900               if(*ptr=='=')
901                 sawequals=1;
902               else if(*ptr!=' ')
903                 break;
904               ptr++;
905             }
906
907           /* There is an argument, so grab that too.  At this point,
908              ptr points to the first character of the argument. */
909           if(sawequals)
910             {
911               /* Is it a quoted argument? */
912               if(*ptr=='"')
913                 {
914                   ptr++;
915                   end=strchr(ptr,'"');
916                   if(end)
917                     end++;
918                 }
919               else
920                 end=strpbrk(ptr," ,");
921             }
922
923           if(end && *end)
924             {
925               *end='\0';
926               *stringp=end+1;
927             }
928           else
929             *stringp=NULL;
930         }
931       else
932         *stringp=NULL;
933     }
934
935   return tok;
936 }
937
938 /* Breaks an option value into key and value.  Returns NULL if there
939    is no value.  Note that "string" is modified to remove the =value
940    part. */
941 char *
942 argsplit(char *string)
943 {
944   char *equals,*arg=NULL;
945
946   equals=strchr(string,'=');
947   if(equals)
948     {
949       char *quote,*space;
950
951       *equals='\0';
952       arg=equals+1;
953
954       /* Quoted arg? */
955       quote=strchr(arg,'"');
956       if(quote)
957         {
958           arg=quote+1;
959
960           quote=strchr(arg,'"');
961           if(quote)
962             *quote='\0';
963         }
964       else
965         {
966           size_t spaces;
967
968           /* Trim leading spaces off of the arg */
969           spaces=strspn(arg," ");
970           arg+=spaces;
971         }
972
973       /* Trim tailing spaces off of the tag */
974       space=strchr(string,' ');
975       if(space)
976         *space='\0';
977     }
978
979   return arg;
980 }
981
982 /* Return the length of the initial token, leaving off any
983    argument. */
984 static size_t
985 optlen(const char *s)
986 {
987   char *end=strpbrk(s," =");
988
989   if(end)
990     return end-s;
991   else
992     return strlen(s);
993 }
994
995 int
996 parse_options(char *str,unsigned int *options,
997               struct parse_options *opts,int noisy)
998 {
999   char *tok;
1000
1001   if (str && !strcmp (str, "help"))
1002     {
1003       int i,maxlen=0;
1004
1005       /* Figure out the longest option name so we can line these up
1006          neatly. */
1007       for(i=0;opts[i].name;i++)
1008         if(opts[i].help && maxlen<strlen(opts[i].name))
1009           maxlen=strlen(opts[i].name);
1010
1011       for(i=0;opts[i].name;i++)
1012         if(opts[i].help)
1013           printf("%s%*s%s\n",opts[i].name,
1014                  maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help));
1015
1016       g10_exit(0);
1017     }
1018
1019   while((tok=optsep(&str)))
1020     {
1021       int i,rev=0;
1022       char *otok=tok;
1023
1024       if(tok[0]=='\0')
1025         continue;
1026
1027       if(ascii_strncasecmp("no-",tok,3)==0)
1028         {
1029           rev=1;
1030           tok+=3;
1031         }
1032
1033       for(i=0;opts[i].name;i++)
1034         {
1035           size_t toklen=optlen(tok);
1036
1037           if(ascii_strncasecmp(opts[i].name,tok,toklen)==0)
1038             {
1039               /* We have a match, but it might be incomplete */
1040               if(toklen!=strlen(opts[i].name))
1041                 {
1042                   int j;
1043
1044                   for(j=i+1;opts[j].name;j++)
1045                     {
1046                       if(ascii_strncasecmp(opts[j].name,tok,toklen)==0)
1047                         {
1048                           if(noisy)
1049                             log_info(_("ambiguous option `%s'\n"),otok);
1050                           return 0;
1051                         }
1052                     }
1053                 }
1054
1055               if(rev)
1056                 {
1057                   *options&=~opts[i].bit;
1058                   if(opts[i].value)
1059                     *opts[i].value=NULL;
1060                 }
1061               else
1062                 {
1063                   *options|=opts[i].bit;
1064                   if(opts[i].value)
1065                     *opts[i].value=argsplit(tok);
1066                 }
1067               break;
1068             }
1069         }
1070
1071       if(!opts[i].name)
1072         {
1073           if(noisy)
1074             log_info(_("unknown option `%s'\n"),otok);
1075           return 0;
1076         }
1077     }
1078
1079   return 1;
1080 }
1081
1082
1083 /* Return a new malloced string by unescaping the string S.  Escaping
1084    is percent escaping and '+'/space mapping.  A binary nul will
1085    silently be replaced by a 0xFF. */
1086 char *
1087 unescape_percent_string (const unsigned char *s)
1088 {
1089   char *buffer, *d;
1090
1091   buffer = d = xmalloc (strlen (s)+1);
1092   while (*s)
1093     {
1094       if (*s == '%' && s[1] && s[2])
1095         { 
1096           s++;
1097           *d = xtoi_2 (s);
1098           if (!*d)
1099             *d = '\xff';
1100           d++;
1101           s += 2;
1102         }
1103       else if (*s == '+')
1104         {
1105           *d++ = ' ';
1106           s++;
1107         }
1108       else
1109         *d++ = *s++;
1110     }
1111   *d = 0; 
1112   return buffer;
1113 }
1114
1115
1116 int
1117 has_invalid_email_chars (const char *s)
1118 {
1119   int at_seen=0;
1120   const char *valid_chars=
1121     "01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1122
1123   for ( ; *s; s++ ) 
1124     {
1125       if ( *s & 0x80 )
1126         return 1;
1127       if ( *s == '@' )
1128         at_seen=1;
1129       else if ( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) )
1130         return 1;
1131       else if ( at_seen && !strchr( valid_chars, *s ) )
1132         return 1;
1133     }
1134   return 0;
1135 }
1136
1137
1138 /* Check whether NAME represents a valid mailbox according to
1139    RFC822. Returns true if so. */
1140 int
1141 is_valid_mailbox (const char *name)
1142 {
1143   return !( !name
1144             || !*name
1145             || has_invalid_email_chars (name)
1146             || string_count_chr (name,'@') != 1
1147             || *name == '@'
1148             || name[strlen(name)-1] == '@'
1149             || name[strlen(name)-1] == '.'
1150             || strstr (name, "..") );
1151 }
1152
1153
1154 /* Similar to access(2), but uses PATH to find the file. */
1155 int
1156 path_access(const char *file,int mode)
1157 {
1158   char *envpath;
1159   int ret=-1;
1160
1161   envpath=getenv("PATH");
1162
1163   if(!envpath
1164 #ifdef HAVE_DRIVE_LETTERS
1165      || (((file[0]>='A' && file[0]<='Z')
1166           || (file[0]>='a' && file[0]<='z'))
1167          && file[1]==':')
1168 #else
1169      || file[0]=='/'
1170 #endif
1171      )
1172     return access(file,mode);
1173   else
1174     {
1175       /* At least as large as, but most often larger than we need. */
1176       char *buffer=xmalloc(strlen(envpath)+1+strlen(file)+1);
1177       char *split,*item,*path=xstrdup(envpath);
1178
1179       split=path;
1180
1181       while((item=strsep(&split,PATHSEP_S)))
1182         {
1183           strcpy(buffer,item);
1184           strcat(buffer,"/");
1185           strcat(buffer,file);
1186           ret=access(buffer,mode);
1187           if(ret==0)
1188             break;
1189         }
1190
1191       xfree(path);
1192       xfree(buffer);
1193     }
1194
1195   return ret;
1196 }
1197
1198
1199 \f
1200 /* Temporary helper. */
1201 int
1202 pubkey_get_npkey( int algo )
1203 {
1204   size_t n;
1205
1206   if (algo == GCRY_PK_ELG_E)
1207     algo = GCRY_PK_ELG;
1208   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &n))
1209     n = 0;
1210   return n;
1211 }
1212
1213 /* Temporary helper. */
1214 int
1215 pubkey_get_nskey( int algo )
1216 {
1217   size_t n;
1218
1219   if (algo == GCRY_PK_ELG_E)
1220     algo = GCRY_PK_ELG;
1221   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &n ))
1222     n = 0;
1223   return n;
1224 }
1225
1226 /* Temporary helper. */
1227 int
1228 pubkey_get_nsig( int algo )
1229 {
1230   size_t n;
1231
1232   if (algo == GCRY_PK_ELG_E)
1233     algo = GCRY_PK_ELG;
1234   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &n))
1235     n = 0;
1236   return n;
1237 }
1238
1239 /* Temporary helper. */
1240 int
1241 pubkey_get_nenc( int algo )
1242 {
1243   size_t n;
1244   
1245   if (algo == GCRY_PK_ELG_E)
1246     algo = GCRY_PK_ELG;
1247   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &n ))
1248     n = 0;
1249   return n;
1250 }
1251
1252
1253 /* Temporary helper. */
1254 unsigned int
1255 pubkey_nbits( int algo, gcry_mpi_t *key )
1256 {
1257     int rc, nbits;
1258     gcry_sexp_t sexp;
1259
1260     if( algo == GCRY_PK_DSA ) {
1261         rc = gcry_sexp_build ( &sexp, NULL,
1262                               "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
1263                                   key[0], key[1], key[2], key[3] );
1264     }
1265     else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
1266         rc = gcry_sexp_build ( &sexp, NULL,
1267                               "(public-key(elg(p%m)(g%m)(y%m)))",
1268                                   key[0], key[1], key[2] );
1269     }
1270     else if( algo == GCRY_PK_RSA ) {
1271         rc = gcry_sexp_build ( &sexp, NULL,
1272                               "(public-key(rsa(n%m)(e%m)))",
1273                                   key[0], key[1] );
1274     }
1275     else
1276         return 0;
1277
1278     if ( rc )
1279         BUG ();
1280
1281     nbits = gcry_pk_get_nbits( sexp );
1282     gcry_sexp_release( sexp );
1283     return nbits;
1284 }
1285
1286
1287
1288 /* FIXME: Use gcry_mpi_print directly. */
1289 int
1290 mpi_print( FILE *fp, gcry_mpi_t a, int mode )
1291 {
1292     int n=0;
1293
1294     if( !a )
1295         return fprintf(fp, "[MPI_NULL]");
1296     if( !mode ) {
1297         unsigned int n1;
1298         n1 = gcry_mpi_get_nbits(a);
1299         n += fprintf(fp, "[%u bits]", n1);
1300     }
1301     else {
1302         unsigned char *buffer;
1303
1304         if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a))
1305           BUG ();
1306         fputs( buffer, fp );
1307         n += strlen(buffer);
1308         gcry_free( buffer );
1309     }
1310     return n;
1311 }
1312