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