* keygen.c (keygen_set_std_prefs): Properly handle an empty preference
[gnupg.git] / g10 / misc.c
1 /* misc.c -  miscellaneous functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <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 #include "util.h"
37 #include "main.h"
38 #include "photoid.h"
39 #include "options.h"
40 #include "i18n.h"
41
42
43 const char *g10m_revision_string(int);
44 const char *g10c_revision_string(int);
45 const char *g10u_revision_string(int);
46
47 #ifdef __GNUC__
48 volatile
49 #endif
50          void
51 pull_in_libs(void)
52 {
53     g10m_revision_string(0);
54     g10c_revision_string(0);
55     g10u_revision_string(0);
56 }
57
58
59 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
60 static int
61 setsysinfo(unsigned long op, void *buffer, unsigned long size,
62                      int *start, void *arg, unsigned long flag)
63 {
64     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
65 }
66
67 void
68 trap_unaligned(void)
69 {
70     unsigned int buf[2];
71
72     buf[0] = SSIN_UACPROC;
73     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
74     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
75 }
76 #else
77 void
78 trap_unaligned(void)
79 {  /* dummy */
80 }
81 #endif
82
83
84 int
85 disable_core_dumps()
86 {
87  #ifdef HAVE_DOSISH_SYSTEM
88     return 0;
89  #else
90   #ifdef HAVE_SETRLIMIT
91     struct rlimit limit;
92
93     limit.rlim_cur = 0;
94     limit.rlim_max = 0;
95     if( !setrlimit( RLIMIT_CORE, &limit ) )
96         return 0;
97     if( errno != EINVAL && errno != ENOSYS )
98         log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
99   #endif
100     return 1;
101  #endif
102 }
103
104
105
106 u16
107 checksum_u16( unsigned n )
108 {
109     u16 a;
110
111     a  = (n >> 8) & 0xff;
112     a += n & 0xff;
113     return a;
114 }
115
116
117 u16
118 checksum( byte *p, unsigned n )
119 {
120     u16 a;
121
122     for(a=0; n; n-- )
123         a += *p++;
124     return a;
125 }
126
127 u16
128 checksum_mpi( MPI a )
129 {
130     u16 csum;
131     byte *buffer;
132     unsigned nbytes;
133     unsigned nbits;
134
135     buffer = mpi_get_buffer( a, &nbytes, NULL );
136     nbits = mpi_get_nbits(a);
137     csum = checksum_u16( nbits );
138     csum += checksum( buffer, nbytes );
139     m_free( buffer );
140     return csum;
141 }
142
143 u32
144 buffer_to_u32( const byte *buffer )
145 {
146     unsigned long a;
147     a =  *buffer << 24;
148     a |= buffer[1] << 16;
149     a |= buffer[2] << 8;
150     a |= buffer[3];
151     return a;
152 }
153
154
155 static void
156 no_exp_algo(void)
157 {
158     static int did_note = 0;
159
160     if( !did_note ) {
161         did_note = 1;
162         log_info(_("Experimental algorithms should not be used!\n"));
163     }
164 }
165
166 void
167 print_pubkey_algo_note( int algo )
168 {
169     if( algo >= 100 && algo <= 110 )
170         no_exp_algo();
171 }
172
173 void
174 print_cipher_algo_note( int algo )
175 {
176     if( algo >= 100 && algo <= 110 )
177         no_exp_algo();
178     else if(    algo == CIPHER_ALGO_3DES
179              || algo == CIPHER_ALGO_CAST5
180              || algo == CIPHER_ALGO_BLOWFISH
181              || algo == CIPHER_ALGO_TWOFISH
182              || algo == CIPHER_ALGO_RIJNDAEL
183              || algo == CIPHER_ALGO_RIJNDAEL192
184              || algo == CIPHER_ALGO_RIJNDAEL256
185            )
186         ;
187     else {
188         static int did_note = 0;
189
190         if( !did_note ) {
191             did_note = 1;
192             log_info(_("this cipher algorithm is deprecated; "
193                        "please use a more standard one!\n"));
194         }
195     }
196 }
197
198 void
199 print_digest_algo_note( int algo )
200 {
201     if( algo >= 100 && algo <= 110 )
202         no_exp_algo();
203 }
204
205
206 /* Return a string which is used as a kind of process ID */
207 const byte *
208 get_session_marker( size_t *rlen )
209 {
210     static byte marker[SIZEOF_UNSIGNED_LONG*2];
211     static int initialized;
212
213     if ( !initialized ) {
214         volatile ulong aa, bb; /* we really want the uninitialized value */
215         ulong a, b;
216
217         initialized = 1;
218         /* also this marker is guessable it is not easy to use this 
219          * for a faked control packet because an attacker does not
220          * have enough control about the time the verification does 
221          * take place.  Of course, we can add just more random but 
222          * than we need the random generator even for verification
223          * tasks - which does not make sense. */
224         a = aa ^ (ulong)getpid();
225         b = bb ^ (ulong)time(NULL);
226         memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
227         memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
228     }
229     *rlen = sizeof(marker);
230     return marker;
231 }
232
233 /****************
234  * Wrapper around the libgcrypt function with addional checks on
235  * openPGP contraints for the algo ID.
236  */
237 int
238 openpgp_cipher_test_algo( int algo )
239 {
240     if( algo < 0 || algo > 110 )
241         return G10ERR_CIPHER_ALGO;
242     return check_cipher_algo(algo);
243 }
244
245 int
246 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
247 {
248     if( algo < 0 || algo > 110 )
249         return G10ERR_PUBKEY_ALGO;
250     return check_pubkey_algo2( algo, usage_flags );
251 }
252
253 int 
254 openpgp_pk_algo_usage ( int algo )
255 {
256     int use = 0; 
257     
258     /* they are hardwired in gpg 1.0 */
259     switch ( algo ) {    
260       case PUBKEY_ALGO_RSA:
261           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
262           break;
263       case PUBKEY_ALGO_RSA_E:
264           use = PUBKEY_USAGE_ENC;
265           break;
266       case PUBKEY_ALGO_RSA_S:
267           use = PUBKEY_USAGE_SIG;
268           break;
269       case PUBKEY_ALGO_ELGAMAL_E:
270           use = PUBKEY_USAGE_ENC;
271           break;
272       case PUBKEY_ALGO_DSA:  
273           use = PUBKEY_USAGE_SIG;
274           break;
275       case PUBKEY_ALGO_ELGAMAL:
276           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
277           break;
278       default:
279           break;
280     }
281     return use;
282 }
283
284 int
285 openpgp_md_test_algo( int algo )
286 {
287     if( algo < 0 || algo > 110 )
288         return G10ERR_DIGEST_ALGO;
289     return check_digest_algo(algo);
290 }
291
292 /* Special warning for the IDEA cipher */
293 void
294 idea_cipher_warn(int show)
295 {
296   static int warned=0;
297
298   if(!warned || show)
299     {
300       log_info(_("the IDEA cipher plugin is not present\n"));
301       log_info(_("please see http://www.gnupg.org/why-not-idea.html "
302                  "for more information\n"));
303       warned=1;
304     }
305 }
306
307 /* Expand %-strings.  Returns a string which must be m_freed.  Returns
308    NULL if the string cannot be expanded (too large). */
309 char *
310 pct_expando(const char *string,struct expando_args *args)
311 {
312   const char *ch=string;
313   int idx=0,maxlen=0,done=0;
314   u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
315   char *ret=NULL;
316
317   if(args->pk)
318     keyid_from_pk(args->pk,pk_keyid);
319
320   if(args->sk)
321     keyid_from_sk(args->sk,sk_keyid);
322
323   if(!args->pk && args->sk)
324     keyid_from_sk(args->sk,pk_keyid);
325
326   while(*ch!='\0')
327     {
328       char *str=NULL;
329
330       if(!done)
331         {
332           /* 8192 is way bigger than we'll need here */
333           if(maxlen>=8192)
334             goto fail;
335
336           maxlen+=1024;
337           ret=m_realloc(ret,maxlen);
338         }
339
340       done=0;
341
342       if(*ch=='%')
343         {
344           switch(*(ch+1))
345             {
346             case 's': /* short key id */
347               if(idx+8<maxlen)
348                 {
349                   sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
350                   idx+=8;
351                   done=1;
352                 }
353               break;
354
355             case 'S': /* long key id */
356               if(idx+16<maxlen)
357                 {
358                   sprintf(&ret[idx],"%08lX%08lX",
359                           (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
360                   idx+=16;
361                   done=1;
362                 }
363               break;
364
365             case 'k': /* short key id */
366               if(idx+8<maxlen)
367                 {
368                   sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
369                   idx+=8;
370                   done=1;
371                 }
372               break;
373
374             case 'K': /* long key id */
375               if(idx+16<maxlen)
376                 {
377                   sprintf(&ret[idx],"%08lX%08lX",
378                           (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
379                   idx+=16;
380                   done=1;
381                 }
382               break;
383
384             case 'f': /* fingerprint */
385               {
386                 byte array[MAX_FINGERPRINT_LEN];
387                 size_t len;
388                 int i;
389
390                 if(args->pk)
391                   fingerprint_from_pk(args->pk,array,&len);
392                 else
393                   memset(array,0, (len=MAX_FINGERPRINT_LEN));
394
395                 if(idx+(len*2)<maxlen)
396                   {
397                     for(i=0;i<len;i++)
398                       {
399                         sprintf(&ret[idx],"%02X",array[i]);
400                         idx+=2;
401                       }
402                     done=1;
403                   }
404               }
405               break;
406
407             case 't': /* e.g. "jpg" */
408               str=image_type_to_string(args->imagetype,0);
409               /* fall through */
410
411             case 'T': /* e.g. "image/jpeg" */
412               if(str==NULL)
413                 str=image_type_to_string(args->imagetype,2);
414
415               if(idx+strlen(str)<maxlen)
416                 {
417                   strcpy(&ret[idx],str);
418                   idx+=strlen(str);
419                   done=1;
420                 }
421               break;
422
423             case '%':
424               if(idx+1<maxlen)
425                 {
426                   ret[idx++]='%';
427                   ret[idx]='\0';
428                   done=1;
429                 }
430               break;
431
432               /* Any unknown %-keys (like %i, %o, %I, and %O) are
433                  passed through for later expansion.  Note this also
434                  handles the case where the last character in the
435                  string is a '%' - the terminating \0 will end up here
436                  and properly terminate the string. */
437             default:
438               if(idx+2<maxlen)
439                 {
440                   ret[idx++]='%';
441                   ret[idx++]=*(ch+1);
442                   ret[idx]='\0';
443                   done=1;
444                 }
445               break;
446               }
447
448           if(done)
449             ch++;
450         }
451       else
452         {
453           if(idx+1<maxlen)
454             {
455               ret[idx++]=*ch;
456               ret[idx]='\0';
457               done=1;
458             }
459         }
460
461       if(done)
462         ch++;
463     }
464
465   return ret;
466
467  fail:
468   m_free(ret);
469   return NULL;
470 }
471
472 int
473 hextobyte( const char *s )
474 {
475     int c;
476
477     if( *s >= '0' && *s <= '9' )
478         c = 16 * (*s - '0');
479     else if( *s >= 'A' && *s <= 'F' )
480         c = 16 * (10 + *s - 'A');
481     else if( *s >= 'a' && *s <= 'f' )
482         c = 16 * (10 + *s - 'a');
483     else
484         return -1;
485     s++;
486     if( *s >= '0' && *s <= '9' )
487         c += *s - '0';
488     else if( *s >= 'A' && *s <= 'F' )
489         c += 10 + *s - 'A';
490     else if( *s >= 'a' && *s <= 'f' )
491         c += 10 + *s - 'a';
492     else
493         return -1;
494     return c;
495 }
496
497 void
498 deprecated_warning(const char *configname,unsigned int configlineno,
499                    const char *option,const char *repl1,const char *repl2)
500 {
501   if(configname)
502     {
503       if(strncmp("--",option,2)==0)
504         option+=2;
505
506       if(strncmp("--",repl1,2)==0)
507         repl1+=2;
508
509       log_info(_("%s:%d: deprecated option \"%s\"\n"),
510                configname,configlineno,option);
511     }
512   else
513     log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
514
515   log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
516 }
517
518 const char *
519 compress_algo_to_string(int algo)
520 {
521   const char *s="?";
522
523   switch(algo)
524     {
525     case 0:
526       s="Uncompressed";
527       break;
528
529     case 1:
530       s="ZIP";
531       break;
532
533     case 2:
534       s="ZLIB";
535       break;
536     }
537
538   return s;
539 }
540
541 int
542 string_to_compress_algo(const char *string)
543 {
544   if(ascii_strcasecmp(string,"uncompressed")==0)
545     return 0;
546   else if(ascii_strcasecmp(string,"zip")==0)
547     return 1;
548   else if(ascii_strcasecmp(string,"zlib")==0)
549     return 2;
550   else if(ascii_strcasecmp(string,"z0")==0)
551     return 0;
552   else if(ascii_strcasecmp(string,"z1")==0)
553     return 1;
554   else if(ascii_strcasecmp(string,"z2")==0)
555     return 2;
556   else
557     return -1;
558 }
559
560 int
561 check_compress_algo(int algo)
562 {
563   if(algo>=0 && algo<=2)
564     return 0;
565
566   return G10ERR_COMPR_ALGO;
567 }