2ffe7268ddc73545d9c38283f89bb194a9b59968
[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 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 "errors.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   if ( algo < 0 || algo > 110 )
335     return gpg_error (GPG_ERR_CIPHER_ALGO);
336   return gcry_cipher_test_algo (algo);
337 }
338
339 int
340 openpgp_pk_test_algo( int algo )
341 {
342   if (algo == GCRY_PK_ELG_E)
343     algo = GCRY_PK_ELG;
344
345   if (algo < 0 || algo > 110)
346     return gpg_error (GPG_ERR_PUBKEY_ALGO);
347   return gcry_pk_test_algo (algo);
348 }
349
350 int
351 openpgp_pk_test_algo2( int algo, unsigned int use )
352 {
353   size_t use_buf = use;
354
355   if (algo == GCRY_PK_ELG_E)
356     algo = GCRY_PK_ELG;
357
358   if (algo < 0 || algo > 110)
359     return gpg_error (GPG_ERR_PUBKEY_ALGO);
360
361   return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &use_buf);
362 }
363
364 int 
365 openpgp_pk_algo_usage ( int algo )
366 {
367     int use = 0; 
368     
369     /* They are hardwired in gpg 1.0. */
370     switch ( algo ) {    
371       case PUBKEY_ALGO_RSA:
372           use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
373                  | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH);
374           break;
375       case PUBKEY_ALGO_RSA_E:
376           use = PUBKEY_USAGE_ENC;
377           break;
378       case PUBKEY_ALGO_RSA_S:
379           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
380           break;
381       case PUBKEY_ALGO_ELGAMAL_E:
382           use = PUBKEY_USAGE_ENC;
383           break;
384       case PUBKEY_ALGO_DSA:  
385           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
386           break;
387       default:
388           break;
389     }
390     return use;
391 }
392
393 int
394 openpgp_md_test_algo( int algo )
395 {
396   /* Note: If the list of actual supported OpenPGP algorithms changes,
397      make sure that our hard coded values at
398      print_status_begin_signing() gets updated. */
399
400   if (algo < 0 || algo > 110)
401     return gpg_error (GPG_ERR_DIGEST_ALGO);
402   return gcry_md_test_algo (algo);
403 }
404
405 #ifdef USE_IDEA
406 /* Special warning for the IDEA cipher */
407 void
408 idea_cipher_warn(int show)
409 {
410   static int warned=0;
411
412   if(!warned || show)
413     {
414       log_info(_("the IDEA cipher plugin is not present\n"));
415       log_info(_("please see %s for more information\n"),
416                "http://www.gnupg.org/faq/why-not-idea.html");
417       warned=1;
418     }
419 }
420 #endif
421
422
423 static unsigned long 
424 get_signature_count (PKT_secret_key *sk)
425 {
426 #ifdef ENABLE_CARD_SUPPORT
427   if(sk && sk->is_protected && sk->protect.s2k.mode==1002)
428     {
429       struct agent_card_info_s info;
430       if(agent_scd_getattr("SIG-COUNTER",&info)==0)
431         return info.sig_counter;
432     }  
433 #endif
434
435   /* How to do this without a card? */
436
437   return 0;
438 }
439
440 /* Expand %-strings.  Returns a string which must be xfreed.  Returns
441    NULL if the string cannot be expanded (too large). */
442 char *
443 pct_expando(const char *string,struct expando_args *args)
444 {
445   const char *ch=string;
446   int idx=0,maxlen=0,done=0;
447   u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
448   char *ret=NULL;
449
450   if(args->pk)
451     keyid_from_pk(args->pk,pk_keyid);
452
453   if(args->sk)
454     keyid_from_sk(args->sk,sk_keyid);
455
456   /* This is used so that %k works in photoid command strings in
457      --list-secret-keys (which of course has a sk, but no pk). */
458   if(!args->pk && args->sk)
459     keyid_from_sk(args->sk,pk_keyid);
460
461   while(*ch!='\0')
462     {
463       char *str=NULL;
464
465       if(!done)
466         {
467           /* 8192 is way bigger than we'll need here */
468           if(maxlen>=8192)
469             goto fail;
470
471           maxlen+=1024;
472           ret=xrealloc(ret,maxlen);
473         }
474
475       done=0;
476
477       if(*ch=='%')
478         {
479           switch(*(ch+1))
480             {
481             case 's': /* short key id */
482               if(idx+8<maxlen)
483                 {
484                   sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
485                   idx+=8;
486                   done=1;
487                 }
488               break;
489
490             case 'S': /* long key id */
491               if(idx+16<maxlen)
492                 {
493                   sprintf(&ret[idx],"%08lX%08lX",
494                           (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
495                   idx+=16;
496                   done=1;
497                 }
498               break;
499
500             case 'k': /* short key id */
501               if(idx+8<maxlen)
502                 {
503                   sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
504                   idx+=8;
505                   done=1;
506                 }
507               break;
508
509             case 'K': /* long key id */
510               if(idx+16<maxlen)
511                 {
512                   sprintf(&ret[idx],"%08lX%08lX",
513                           (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
514                   idx+=16;
515                   done=1;
516                 }
517               break;
518
519             case 'c': /* signature count from card, if any. */
520               if(idx+10<maxlen)
521                 {
522                   sprintf(&ret[idx],"%lu",get_signature_count(args->sk));
523                   idx+=strlen(&ret[idx]);
524                   done=1;
525                 }             
526               break;
527
528             case 'p': /* primary pk fingerprint of a sk */
529             case 'f': /* pk fingerprint */
530             case 'g': /* sk fingerprint */
531               {
532                 byte array[MAX_FINGERPRINT_LEN];
533                 size_t len;
534                 int i;
535
536                 if((*(ch+1))=='p' && args->sk)
537                   {
538                     if(args->sk->is_primary)
539                       fingerprint_from_sk(args->sk,array,&len);
540                     else if(args->sk->main_keyid[0] || args->sk->main_keyid[1])
541                       {
542                         PKT_public_key *pk=
543                           xmalloc_clear(sizeof(PKT_public_key));
544
545                         if(get_pubkey_fast(pk,args->sk->main_keyid)==0)
546                           fingerprint_from_pk(pk,array,&len);
547                         else
548                           memset(array,0,(len=MAX_FINGERPRINT_LEN));
549                         free_public_key(pk);
550                       }
551                     else
552                       memset(array,0,(len=MAX_FINGERPRINT_LEN));
553                   }
554                 else if((*(ch+1))=='f' && args->pk)
555                   fingerprint_from_pk(args->pk,array,&len);
556                 else if((*(ch+1))=='g' && args->sk)
557                   fingerprint_from_sk(args->sk,array,&len);
558                 else
559                   memset(array,0,(len=MAX_FINGERPRINT_LEN));
560
561                 if(idx+(len*2)<maxlen)
562                   {
563                     for(i=0;i<len;i++)
564                       {
565                         sprintf(&ret[idx],"%02X",array[i]);
566                         idx+=2;
567                       }
568                     done=1;
569                   }
570               }
571               break;
572
573             case 't': /* e.g. "jpg" */
574               str=image_type_to_string(args->imagetype,0);
575               /* fall through */
576
577             case 'T': /* e.g. "image/jpeg" */
578               if(str==NULL)
579                 str=image_type_to_string(args->imagetype,2);
580
581               if(idx+strlen(str)<maxlen)
582                 {
583                   strcpy(&ret[idx],str);
584                   idx+=strlen(str);
585                   done=1;
586                 }
587               break;
588
589             case '%':
590               if(idx+1<maxlen)
591                 {
592                   ret[idx++]='%';
593                   ret[idx]='\0';
594                   done=1;
595                 }
596               break;
597
598               /* Any unknown %-keys (like %i, %o, %I, and %O) are
599                  passed through for later expansion.  Note this also
600                  handles the case where the last character in the
601                  string is a '%' - the terminating \0 will end up here
602                  and properly terminate the string. */
603             default:
604               if(idx+2<maxlen)
605                 {
606                   ret[idx++]='%';
607                   ret[idx++]=*(ch+1);
608                   ret[idx]='\0';
609                   done=1;
610                 }
611               break;
612               }
613
614           if(done)
615             ch++;
616         }
617       else
618         {
619           if(idx+1<maxlen)
620             {
621               ret[idx++]=*ch;
622               ret[idx]='\0';
623               done=1;
624             }
625         }
626
627       if(done)
628         ch++;
629     }
630
631   return ret;
632
633  fail:
634   xfree(ret);
635   return NULL;
636 }
637
638 void
639 deprecated_warning(const char *configname,unsigned int configlineno,
640                    const char *option,const char *repl1,const char *repl2)
641 {
642   if(configname)
643     {
644       if(strncmp("--",option,2)==0)
645         option+=2;
646
647       if(strncmp("--",repl1,2)==0)
648         repl1+=2;
649
650       log_info(_("%s:%d: deprecated option \"%s\"\n"),
651                configname,configlineno,option);
652     }
653   else
654     log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
655
656   log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
657 }
658
659
660 void
661 deprecated_command (const char *name)
662 {
663   log_info(_("WARNING: \"%s\" is a deprecated command - do not use it\n"),
664            name);
665 }
666
667
668 void
669 obsolete_option (const char *configname, unsigned int configlineno, 
670                  const char *name)
671 {
672   if(configname)
673     log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
674               configname, configlineno, name);
675   else
676     log_info (_("WARNING: \"%s\" is an obsolete option - it has no effect\n"),
677               name);
678 }
679
680
681 /*
682  * Wrapper around gcry_cipher_map_name to provide a fallback using the
683  * "Sn" syntax as used by the preference strings.
684  */
685 int 
686 string_to_cipher_algo (const char *string) 
687
688   int val;
689
690   val = gcry_cipher_map_name (string);
691   if (!val && string && (string[0]=='S' || string[0]=='s'))
692     {
693       char *endptr;
694
695       string++;
696       val = strtol (string, &endptr, 10);
697       if (!*string || *endptr || openpgp_cipher_test_algo (val))
698         val = 0;
699     }
700
701   return val;
702 }
703
704 /*
705  * Wrapper around gcry_md_map_name to provide a fallback using the
706  * "Hn" syntax as used by the preference strings.
707  */
708 int 
709 string_to_digest_algo (const char *string) 
710
711   int val;
712
713   val = gcry_md_map_name (string);
714   if (!val && string && (string[0]=='H' || string[0]=='h'))
715     {
716       char *endptr;
717
718       string++;
719       val = strtol (string, &endptr, 10);
720       if (!*string || *endptr || openpgp_md_test_algo (val))
721         val = 0;
722     }
723
724   return val;
725 }
726
727
728
729 const char *
730 compress_algo_to_string(int algo)
731 {
732   const char *s=NULL;
733
734   switch(algo)
735     {
736     case COMPRESS_ALGO_NONE:
737       s=_("Uncompressed");
738       break;
739
740     case COMPRESS_ALGO_ZIP:
741       s="ZIP";
742       break;
743
744     case COMPRESS_ALGO_ZLIB:
745       s="ZLIB";
746       break;
747
748 #ifdef HAVE_BZIP2
749     case COMPRESS_ALGO_BZIP2:
750       s="BZIP2";
751       break;
752 #endif
753     }
754
755   return s;
756 }
757
758 int
759 string_to_compress_algo(const char *string)
760 {
761   /* TRANSLATORS: See doc/TRANSLATE about this string. */
762   if(match_multistr(_("uncompressed|none"),string))
763     return 0;
764   else if(ascii_strcasecmp(string,"uncompressed")==0)
765     return 0;
766   else if(ascii_strcasecmp(string,"none")==0)
767     return 0;
768   else if(ascii_strcasecmp(string,"zip")==0)
769     return 1;
770   else if(ascii_strcasecmp(string,"zlib")==0)
771     return 2;
772 #ifdef HAVE_BZIP2
773   else if(ascii_strcasecmp(string,"bzip2")==0)
774     return 3;
775 #endif
776   else if(ascii_strcasecmp(string,"z0")==0)
777     return 0;
778   else if(ascii_strcasecmp(string,"z1")==0)
779     return 1;
780   else if(ascii_strcasecmp(string,"z2")==0)
781     return 2;
782 #ifdef HAVE_BZIP2
783   else if(ascii_strcasecmp(string,"z3")==0)
784     return 3;
785 #endif
786   else
787     return -1;
788 }
789
790 int
791 check_compress_algo(int algo)
792 {
793 #ifdef HAVE_BZIP2
794   if(algo>=0 && algo<=3)
795     return 0;
796 #else
797   if(algo>=0 && algo<=2)
798     return 0;
799 #endif
800
801   return G10ERR_COMPR_ALGO;
802 }
803
804 int
805 default_cipher_algo(void)
806 {
807   if(opt.def_cipher_algo)
808     return opt.def_cipher_algo;
809   else if(opt.personal_cipher_prefs)
810     return opt.personal_cipher_prefs[0].value;
811   else
812     return opt.s2k_cipher_algo;
813 }
814
815 /* There is no default_digest_algo function, but see
816    sign.c:hash_for() */
817
818 int
819 default_compress_algo(void)
820 {
821   if(opt.compress_algo!=-1)
822     return opt.compress_algo;
823   else if(opt.personal_compress_prefs)
824     return opt.personal_compress_prefs[0].value;
825   else
826     return DEFAULT_COMPRESS_ALGO;
827 }
828
829 const char *
830 compliance_option_string(void)
831 {
832   switch(opt.compliance)
833     {
834     case CO_RFC2440:
835       return "--openpgp";
836     case CO_PGP2:
837       return "--pgp2";
838     case CO_PGP6:
839       return "--pgp6";
840     case CO_PGP7:
841       return "--pgp7";
842     case CO_PGP8:
843       return "--pgp8";
844     default:
845       return "???";
846     }
847 }
848
849 static const char *
850 compliance_string(void)
851 {
852   switch(opt.compliance)
853     {
854     case CO_RFC2440:
855       return "OpenPGP";
856     case CO_PGP2:
857       return "PGP 2.x";
858     case CO_PGP6:
859       return "PGP 6.x";
860     case CO_PGP7:
861       return "PGP 7.x";
862     case CO_PGP8:
863       return "PGP 8.x";
864     default:
865       return "???";
866     }
867 }
868
869 void
870 compliance_failure(void)
871 {
872   log_info(_("this message may not be usable by %s\n"),compliance_string());
873   opt.compliance=CO_GNUPG;
874 }
875
876 /* Break a string into successive option pieces.  Accepts single word
877    options and key=value argument options. */
878 char *
879 optsep(char **stringp)
880 {
881   char *tok,*end;
882
883   tok=*stringp;
884   if(tok)
885     {
886       end=strpbrk(tok," ,=");
887       if(end)
888         {
889           int sawequals=0;
890           char *ptr=end;
891
892           /* what we need to do now is scan along starting with *end,
893              If the next character we see (ignoring spaces) is an =
894              sign, then there is an argument. */
895
896           while(*ptr)
897             {
898               if(*ptr=='=')
899                 sawequals=1;
900               else if(*ptr!=' ')
901                 break;
902               ptr++;
903             }
904
905           /* There is an argument, so grab that too.  At this point,
906              ptr points to the first character of the argument. */
907           if(sawequals)
908             {
909               /* Is it a quoted argument? */
910               if(*ptr=='"')
911                 {
912                   ptr++;
913                   end=strchr(ptr,'"');
914                   if(end)
915                     end++;
916                 }
917               else
918                 end=strpbrk(ptr," ,");
919             }
920
921           if(end && *end)
922             {
923               *end='\0';
924               *stringp=end+1;
925             }
926           else
927             *stringp=NULL;
928         }
929       else
930         *stringp=NULL;
931     }
932
933   return tok;
934 }
935
936 /* Breaks an option value into key and value.  Returns NULL if there
937    is no value.  Note that "string" is modified to remove the =value
938    part. */
939 char *
940 argsplit(char *string)
941 {
942   char *equals,*arg=NULL;
943
944   equals=strchr(string,'=');
945   if(equals)
946     {
947       char *quote,*space;
948
949       *equals='\0';
950       arg=equals+1;
951
952       /* Quoted arg? */
953       quote=strchr(arg,'"');
954       if(quote)
955         {
956           arg=quote+1;
957
958           quote=strchr(arg,'"');
959           if(quote)
960             *quote='\0';
961         }
962       else
963         {
964           size_t spaces;
965
966           /* Trim leading spaces off of the arg */
967           spaces=strspn(arg," ");
968           arg+=spaces;
969         }
970
971       /* Trim tailing spaces off of the tag */
972       space=strchr(string,' ');
973       if(space)
974         *space='\0';
975     }
976
977   return arg;
978 }
979
980 /* Return the length of the initial token, leaving off any
981    argument. */
982 static size_t
983 optlen(const char *s)
984 {
985   char *end=strpbrk(s," =");
986
987   if(end)
988     return end-s;
989   else
990     return strlen(s);
991 }
992
993 int
994 parse_options(char *str,unsigned int *options,
995               struct parse_options *opts,int noisy)
996 {
997   char *tok;
998
999   if (str && !strcmp (str, "help"))
1000     {
1001       int i,maxlen=0;
1002
1003       /* Figure out the longest option name so we can line these up
1004          neatly. */
1005       for(i=0;opts[i].name;i++)
1006         if(opts[i].help && maxlen<strlen(opts[i].name))
1007           maxlen=strlen(opts[i].name);
1008
1009       for(i=0;opts[i].name;i++)
1010         if(opts[i].help)
1011           printf("%s%*s%s\n",opts[i].name,
1012                  maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help));
1013
1014       g10_exit(0);
1015     }
1016
1017   while((tok=optsep(&str)))
1018     {
1019       int i,rev=0;
1020       char *otok=tok;
1021
1022       if(tok[0]=='\0')
1023         continue;
1024
1025       if(ascii_strncasecmp("no-",tok,3)==0)
1026         {
1027           rev=1;
1028           tok+=3;
1029         }
1030
1031       for(i=0;opts[i].name;i++)
1032         {
1033           size_t toklen=optlen(tok);
1034
1035           if(ascii_strncasecmp(opts[i].name,tok,toklen)==0)
1036             {
1037               /* We have a match, but it might be incomplete */
1038               if(toklen!=strlen(opts[i].name))
1039                 {
1040                   int j;
1041
1042                   for(j=i+1;opts[j].name;j++)
1043                     {
1044                       if(ascii_strncasecmp(opts[j].name,tok,toklen)==0)
1045                         {
1046                           if(noisy)
1047                             log_info(_("ambiguous option `%s'\n"),otok);
1048                           return 0;
1049                         }
1050                     }
1051                 }
1052
1053               if(rev)
1054                 {
1055                   *options&=~opts[i].bit;
1056                   if(opts[i].value)
1057                     *opts[i].value=NULL;
1058                 }
1059               else
1060                 {
1061                   *options|=opts[i].bit;
1062                   if(opts[i].value)
1063                     *opts[i].value=argsplit(tok);
1064                 }
1065               break;
1066             }
1067         }
1068
1069       if(!opts[i].name)
1070         {
1071           if(noisy)
1072             log_info(_("unknown option `%s'\n"),otok);
1073           return 0;
1074         }
1075     }
1076
1077   return 1;
1078 }
1079
1080
1081 /* Return a new malloced string by unescaping the string S.  Escaping
1082    is percent escaping and '+'/space mapping.  A binary nul will
1083    silently be replaced by a 0xFF. */
1084 char *
1085 unescape_percent_string (const unsigned char *s)
1086 {
1087   char *buffer, *d;
1088
1089   buffer = d = xmalloc (strlen (s)+1);
1090   while (*s)
1091     {
1092       if (*s == '%' && s[1] && s[2])
1093         { 
1094           s++;
1095           *d = xtoi_2 (s);
1096           if (!*d)
1097             *d = '\xff';
1098           d++;
1099           s += 2;
1100         }
1101       else if (*s == '+')
1102         {
1103           *d++ = ' ';
1104           s++;
1105         }
1106       else
1107         *d++ = *s++;
1108     }
1109   *d = 0; 
1110   return buffer;
1111 }
1112
1113
1114 int
1115 has_invalid_email_chars (const char *s)
1116 {
1117   int at_seen=0;
1118   const char *valid_chars=
1119     "01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1120
1121   for ( ; *s; s++ ) 
1122     {
1123       if ( *s & 0x80 )
1124         return 1;
1125       if ( *s == '@' )
1126         at_seen=1;
1127       else if ( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) )
1128         return 1;
1129       else if ( at_seen && !strchr( valid_chars, *s ) )
1130         return 1;
1131     }
1132   return 0;
1133 }
1134
1135
1136 /* Check whether NAME represents a valid mailbox according to
1137    RFC822. Returns true if so. */
1138 int
1139 is_valid_mailbox (const char *name)
1140 {
1141   return !( !name
1142             || !*name
1143             || has_invalid_email_chars (name)
1144             || string_count_chr (name,'@') != 1
1145             || *name == '@'
1146             || name[strlen(name)-1] == '@'
1147             || name[strlen(name)-1] == '.'
1148             || strstr (name, "..") );
1149 }
1150
1151
1152 /* Similar to access(2), but uses PATH to find the file. */
1153 int
1154 path_access(const char *file,int mode)
1155 {
1156   char *envpath;
1157   int ret=-1;
1158
1159   envpath=getenv("PATH");
1160
1161   if(!envpath
1162 #ifdef HAVE_DRIVE_LETTERS
1163      || (((file[0]>='A' && file[0]<='Z')
1164           || (file[0]>='a' && file[0]<='z'))
1165          && file[1]==':')
1166 #else
1167      || file[0]=='/'
1168 #endif
1169      )
1170     return access(file,mode);
1171   else
1172     {
1173       /* At least as large as, but most often larger than we need. */
1174       char *buffer=xmalloc(strlen(envpath)+1+strlen(file)+1);
1175       char *split,*item,*path=xstrdup(envpath);
1176
1177       split=path;
1178
1179       while((item=strsep(&split,PATHSEP_S)))
1180         {
1181           strcpy(buffer,item);
1182           strcat(buffer,"/");
1183           strcat(buffer,file);
1184           ret=access(buffer,mode);
1185           if(ret==0)
1186             break;
1187         }
1188
1189       xfree(path);
1190       xfree(buffer);
1191     }
1192
1193   return ret;
1194 }
1195
1196
1197 \f
1198 /* Temporary helper. */
1199 int
1200 pubkey_get_npkey( int algo )
1201 {
1202   size_t n;
1203
1204   if (algo == GCRY_PK_ELG_E)
1205     algo = GCRY_PK_ELG;
1206   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &n))
1207     n = 0;
1208   return n;
1209 }
1210
1211 /* Temporary helper. */
1212 int
1213 pubkey_get_nskey( int algo )
1214 {
1215   size_t n;
1216
1217   if (algo == GCRY_PK_ELG_E)
1218     algo = GCRY_PK_ELG;
1219   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &n ))
1220     n = 0;
1221   return n;
1222 }
1223
1224 /* Temporary helper. */
1225 int
1226 pubkey_get_nsig( int algo )
1227 {
1228   size_t n;
1229
1230   if (algo == GCRY_PK_ELG_E)
1231     algo = GCRY_PK_ELG;
1232   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &n))
1233     n = 0;
1234   return n;
1235 }
1236
1237 /* Temporary helper. */
1238 int
1239 pubkey_get_nenc( int algo )
1240 {
1241   size_t n;
1242   
1243   if (algo == GCRY_PK_ELG_E)
1244     algo = GCRY_PK_ELG;
1245   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &n ))
1246     n = 0;
1247   return n;
1248 }
1249
1250
1251 /* Temporary helper. */
1252 unsigned int
1253 pubkey_nbits( int algo, gcry_mpi_t *key )
1254 {
1255     int rc, nbits;
1256     gcry_sexp_t sexp;
1257
1258     if( algo == GCRY_PK_DSA ) {
1259         rc = gcry_sexp_build ( &sexp, NULL,
1260                               "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
1261                                   key[0], key[1], key[2], key[3] );
1262     }
1263     else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
1264         rc = gcry_sexp_build ( &sexp, NULL,
1265                               "(public-key(elg(p%m)(g%m)(y%m)))",
1266                                   key[0], key[1], key[2] );
1267     }
1268     else if( algo == GCRY_PK_RSA ) {
1269         rc = gcry_sexp_build ( &sexp, NULL,
1270                               "(public-key(rsa(n%m)(e%m)))",
1271                                   key[0], key[1] );
1272     }
1273     else
1274         return 0;
1275
1276     if ( rc )
1277         BUG ();
1278
1279     nbits = gcry_pk_get_nbits( sexp );
1280     gcry_sexp_release( sexp );
1281     return nbits;
1282 }
1283
1284
1285
1286 /* FIXME: Use gcry_mpi_print directly. */
1287 int
1288 mpi_print( FILE *fp, gcry_mpi_t a, int mode )
1289 {
1290     int n=0;
1291
1292     if( !a )
1293         return fprintf(fp, "[MPI_NULL]");
1294     if( !mode ) {
1295         unsigned int n1;
1296         n1 = gcry_mpi_get_nbits(a);
1297         n += fprintf(fp, "[%u bits]", n1);
1298     }
1299     else {
1300         unsigned char *buffer;
1301
1302         if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a))
1303           BUG ();
1304         fputs( buffer, fp );
1305         n += strlen(buffer);
1306         gcry_free( buffer );
1307     }
1308     return n;
1309 }
1310