2008-06-18 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / common / sysutils.c
1 /* sysutils.c -  system helpers
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004,
3  *               2007, 2008  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
23 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
24 # undef HAVE_PTH
25 # undef USE_GNU_PTH
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #ifdef HAVE_STAT
34 # include <sys/stat.h>
35 #endif
36 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
37 # include <asm/sysinfo.h>
38 # include <asm/unistd.h>
39 #endif
40 #ifdef HAVE_SETRLIMIT
41 # include <time.h>
42 # include <sys/time.h>
43 # include <sys/resource.h>
44 #endif
45 #ifdef HAVE_W32_SYSTEM
46 # define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
47 # include <windows.h>
48 #endif
49 #ifdef HAVE_PTH      
50 # include <pth.h>
51 #endif
52 #include <fcntl.h>
53 #include <ctype.h>
54
55 #include "util.h"
56 #include "i18n.h"
57
58 #include "sysutils.h"
59
60 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
61
62
63 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
64 #warning using trap_unaligned
65 static int
66 setsysinfo(unsigned long op, void *buffer, unsigned long size,
67                      int *start, void *arg, unsigned long flag)
68 {
69     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
70 }
71
72 void
73 trap_unaligned(void)
74 {
75     unsigned int buf[2];
76
77     buf[0] = SSIN_UACPROC;
78     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
79     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
80 }
81 #else
82 void
83 trap_unaligned(void)
84 {  /* dummy */
85 }
86 #endif
87
88
89 int
90 disable_core_dumps (void)
91 {
92 #ifdef HAVE_DOSISH_SYSTEM
93     return 0;
94 #else
95 # ifdef HAVE_SETRLIMIT
96     struct rlimit limit;
97
98     /* We only set the current limit unless we were not able to
99        retrieve the old value. */
100     if (getrlimit (RLIMIT_CORE, &limit))
101       limit.rlim_max = 0;
102     limit.rlim_cur = 0;
103     if( !setrlimit (RLIMIT_CORE, &limit) )
104         return 0;
105     if( errno != EINVAL && errno != ENOSYS )
106         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
107 #endif
108     return 1;
109 #endif
110 }
111
112 int
113 enable_core_dumps (void)
114 {
115 #ifdef HAVE_DOSISH_SYSTEM
116     return 0;
117 #else
118 # ifdef HAVE_SETRLIMIT
119     struct rlimit limit;
120
121     if (getrlimit (RLIMIT_CORE, &limit))
122       return 1;
123     limit.rlim_cur = limit.rlim_max;
124     setrlimit (RLIMIT_CORE, &limit);
125     return 1; /* We always return true because this function is
126                  merely a debugging aid. */
127 # endif
128     return 1;
129 #endif
130 }
131
132
133
134 /* Return a string which is used as a kind of process ID */
135 const byte *
136 get_session_marker( size_t *rlen )
137 {
138     static byte marker[SIZEOF_UNSIGNED_LONG*2];
139     static int initialized;
140
141     if ( !initialized ) {
142         volatile ulong aa, bb; /* we really want the uninitialized value */
143         ulong a, b;
144
145         initialized = 1;
146         /* Although this marker is guessable it is not easy to use
147          * for a faked control packet because an attacker does not
148          * have enough control about the time the verification does 
149          * take place.  Of course, we can add just more random but 
150          * than we need the random generator even for verification
151          * tasks - which does not make sense. */
152         a = aa ^ (ulong)getpid();
153         b = bb ^ (ulong)time(NULL);
154         memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
155         memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
156     }
157     *rlen = sizeof(marker);
158     return marker;
159 }
160
161
162 #if 0 /* not yet needed - Note that this will require inclusion of
163          cmacros.am in Makefile.am */
164 int
165 check_permissions(const char *path,int extension,int checkonly)
166 {
167 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
168   char *tmppath;
169   struct stat statbuf;
170   int ret=1;
171   int isdir=0;
172
173   if(opt.no_perm_warn)
174     return 0;
175
176   if(extension && path[0]!=DIRSEP_C)
177     {
178       if(strchr(path,DIRSEP_C))
179         tmppath=make_filename(path,NULL);
180       else
181         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
182     }
183   else
184     tmppath=m_strdup(path);
185
186   /* It's okay if the file doesn't exist */
187   if(stat(tmppath,&statbuf)!=0)
188     {
189       ret=0;
190       goto end;
191     }
192
193   isdir=S_ISDIR(statbuf.st_mode);
194
195   /* Per-user files must be owned by the user.  Extensions must be
196      owned by the user or root. */
197   if((!extension && statbuf.st_uid != getuid()) ||
198      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
199     {
200       if(!checkonly)
201         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
202                  isdir?"directory":extension?"extension":"file",path);
203       goto end;
204     }
205
206   /* This works for both directories and files - basically, we don't
207      care what the owner permissions are, so long as the group and
208      other permissions are 0 for per-user files, and non-writable for
209      extensions. */
210   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
211      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
212     {
213       char *dir;
214
215       /* However, if the directory the directory/file is in is owned
216          by the user and is 700, then this is not a problem.
217          Theoretically, we could walk this test up to the root
218          directory /, but for the sake of sanity, I'm stopping at one
219          level down. */
220
221       dir= make_dirname (tmppath);
222       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
223          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
224         {
225           xfree (dir);
226           ret=0;
227           goto end;
228         }
229
230       m_free(dir);
231
232       if(!checkonly)
233         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
234                  isdir?"directory":extension?"extension":"file",path);
235       goto end;
236     }
237
238   ret=0;
239
240  end:
241   m_free(tmppath);
242
243   return ret;
244
245 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
246
247   return 0;
248 }
249 #endif
250
251
252 /* Wrapper around the usual sleep fucntion.  This one won't wake up
253    before the sleep time has really elapsed.  When build with Pth it
254    merely calls pth_sleep and thus suspends only the current
255    thread. */
256 void
257 gnupg_sleep (unsigned int seconds)
258 {
259 #ifdef HAVE_PTH
260   /* With Pth we force a regular sleep for seconds == 0 so that also
261      the process will give up its timeslot.  */
262   if (!seconds)
263     {
264 # ifdef HAVE_W32_SYSTEM    
265       Sleep (0);
266 # else
267       sleep (0);
268 # endif
269     }
270   pth_sleep (seconds);
271 #else
272   /* Fixme:  make sure that a sleep won't wake up to early.  */
273 # ifdef HAVE_W32_SYSTEM    
274   Sleep (seconds*1000);
275 # else
276   sleep (seconds);
277 # endif
278 #endif
279 }
280
281
282 \f
283 /* Handle translation.  On W32, we provide handle values on the
284    command line directly and using special file names such as
285    "-&HANDLE".  However, in GPGME we can not directly inherit the
286    handles as this may interfere with other components in a
287    multithreaded application.  Thus, we inject the handles after
288    creating the GPG process.  The problem is that the handle numbers
289    change at injection, but it is too late to change the command line.
290    Hence this hack, which allows us to translate the handle values
291    in the command line to their new values after injection.
292
293    Handles that must be translated are those occuring in special file
294    names (see iobuf.c::check_special_filename) as well as those given
295    directly to options (see translate_sys2libc_fd_int).  */
296
297 /* For W32, we may have to translate handle values given on the
298    command line.  */
299 #define FD_TRANSLATE_MAX 8
300 static struct
301 {
302   int from;
303   int to;
304 } fd_translate[8];
305
306 /* Number of entries used in fd_translate.  */
307 static int fd_translate_len;
308
309
310 /* Initialize the fd translation table.  This reads one line from
311    stdin which is expected to be in the format "FROM TO [...]" where
312    each "FROM TO" pair are two handle numbers.  Handle number FROM on
313    the command line is translated to handle number TO.  */
314 void
315 translate_table_init (void)
316 {
317 #define TRANS_MAX 100
318   char line[TRANS_MAX + 1];
319   char *linep;
320   int idx;
321   int res;
322   int newl = 0;
323
324   /* We always read one line from stdin.  */
325   for (idx = 0; idx < TRANS_MAX; idx++)
326     {
327       res = read (0, &line[idx], 1);
328       if (res != 1)
329         break;
330       if (line[idx] == '\n')
331         {
332           newl = 1;
333           break;
334         }
335     }
336   if (!newl)
337     {
338       char buf[1];
339       do
340         res = read (0, buf, 1);
341       while (res == 1 && *buf != '\n');
342     }
343
344   line[idx] = '\0';
345   linep = line;
346
347   /* Now start to read mapping pairs.  */
348   for (idx = 0; idx < FD_TRANSLATE_MAX; idx++)
349     {
350       unsigned long from;
351       unsigned long to;
352       char *tail;
353
354       while (isspace (*linep))
355         linep++;
356       if (*linep == '\0')
357         break;
358       from = strtoul (linep, &tail, 0);
359       if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
360         break;
361       linep = tail;
362
363       while (isspace (*linep))
364         linep++;
365       if (*linep == '\0')
366         break;
367       to = strtoul (linep, &tail, 0);
368       if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
369         break;
370       linep = tail;
371
372       fd_translate[idx].from = from;
373       fd_translate[idx].to = to;
374       fd_translate_len++;
375     }
376 }
377
378
379 /* Translate a handle number.  */
380 int
381 translate_table_lookup (int fd)
382 {
383   int idx;
384
385   for (idx = 0; idx < fd_translate_len; idx++)
386     if (fd_translate[idx].from == fd)
387       return fd_translate[idx].to;
388   return fd;
389 }
390
391 \f
392 /* This function is a NOP for POSIX systems but required under Windows
393    as the file handles as returned by OS calls (like CreateFile) are
394    different from the libc file descriptors (like open). This function
395    translates system file handles to libc file handles.  FOR_WRITE
396    gives the direction of the handle.  */
397 int
398 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
399 {
400 #ifdef HAVE_W32_SYSTEM
401   int x;
402
403   if (fd == GNUPG_INVALID_FD)
404     return -1;
405   
406   /* Note that _open_osfhandle is currently defined to take and return
407      a long.  */
408   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
409   if (x == -1)
410     log_error ("failed to translate osfhandle %p\n", (void *) fd);
411   return x;
412 #else /*!HAVE_W32_SYSTEM */
413   return fd;
414 #endif
415 }
416
417
418 /* This is the same as translate_sys2libc_fd but takes an integer
419    which is assumed to be such an system handle.  */
420 int
421 translate_sys2libc_fd_int (int fd, int for_write)
422 {
423 #ifdef HAVE_W32_SYSTEM
424   if (fd <= 2)
425     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
426
427   /* Note: If this function is ever used in a different context than
428      option parsing in the main function, a variant that does not do
429      translation probable needs to be used.  */
430   fd = translate_table_lookup (fd);
431
432   return translate_sys2libc_fd ((void*)fd, for_write);
433 #else
434   fd = translate_table_lookup (fd);
435   return fd;
436 #endif
437 }
438
439
440
441 /* Replacement for tmpfile().  This is required because the tmpfile
442    function of Windows' runtime library is broken, insecure, ignores
443    TMPDIR and so on.  In addition we create a file with an inheritable
444    handle.  */
445 FILE *
446 gnupg_tmpfile (void)
447 {
448 #ifdef HAVE_W32_SYSTEM
449   int attempts, n;
450   char buffer[MAX_PATH+7+12+1];
451   char *name, *p;
452   HANDLE file;
453   int pid = GetCurrentProcessId ();
454   unsigned int value;
455   int i;
456   SECURITY_ATTRIBUTES sec_attr;
457
458   memset (&sec_attr, 0, sizeof sec_attr );
459   sec_attr.nLength = sizeof sec_attr;
460   sec_attr.bInheritHandle = TRUE;
461
462   n = GetTempPath (MAX_PATH+1, buffer);
463   if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
464     {
465       errno = ENOENT;
466       return NULL;
467     }
468   p = buffer + strlen (buffer);
469   p = stpcpy (p, "_gnupg");
470   /* We try to create the directory but don't care about an error as
471      it may already exist and the CreateFile would throw an error
472      anyway.  */
473   CreateDirectory (buffer, NULL);
474   *p++ = '\\';
475   name = p;
476   for (attempts=0; attempts < 10; attempts++)
477     {
478       p = name;
479       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
480       for (i=0; i < 8; i++)
481         {
482           *p++ = tohex (((value >> 28) & 0x0f));
483           value <<= 4;
484         }
485       strcpy (p, ".tmp");
486       file = CreateFile (buffer,
487                          GENERIC_READ | GENERIC_WRITE,
488                          0,
489                          &sec_attr,
490                          CREATE_NEW,
491                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
492                          NULL);
493       if (file != INVALID_HANDLE_VALUE)
494         {
495           FILE *fp;
496           int fd = _open_osfhandle ((long)file, 0);
497           if (fd == -1)
498             {
499               CloseHandle (file);
500               return NULL;
501             }
502           fp = fdopen (fd, "w+b");
503           if (!fp)
504             {
505               int save = errno;
506               close (fd);
507               errno = save;
508               return NULL;
509             }
510           return fp;
511         }
512       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
513     }
514   errno = ENOENT;
515   return NULL;
516 #else /*!HAVE_W32_SYSTEM*/
517   return tmpfile ();
518 #endif /*!HAVE_W32_SYSTEM*/
519 }
520
521
522 /* Make sure that the standard file descriptors are opened. Obviously
523    some folks close them before an exec and the next file we open will
524    get one of them assigned and thus any output (i.e. diagnostics) end
525    up in that file (e.g. the trustdb).  Not actually a gpg problem as
526    this will hapen with almost all utilities when called in a wrong
527    way.  However we try to minimize the damage here and raise
528    awareness of the problem.
529
530    Must be called before we open any files! */
531 void
532 gnupg_reopen_std (const char *pgmname)
533 {  
534 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
535   struct stat statbuf;
536   int did_stdin = 0;
537   int did_stdout = 0;
538   int did_stderr = 0;
539   FILE *complain;
540
541   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
542     {
543       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
544         did_stdin = 1;
545       else
546         did_stdin = 2;
547     }
548   
549   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
550     {
551       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
552         did_stdout = 1;
553       else
554         did_stdout = 2;
555     }
556
557   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
558     {
559       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
560         did_stderr = 1;
561       else
562         did_stderr = 2;
563     }
564
565   /* It's hard to log this sort of thing since the filehandle we would
566      complain to may be closed... */
567   if (!did_stderr)
568     complain = stderr;
569   else if (!did_stdout)
570     complain = stdout;
571   else
572     complain = NULL;
573
574   if (complain)
575     {
576       if (did_stdin == 1)
577         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
578       if (did_stdout == 1)
579         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
580       if (did_stderr == 1)
581         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
582
583       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
584         fprintf(complain,"%s: fatal: unable to reopen standard input,"
585                 " output, or error\n", pgmname);
586     }
587
588   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
589     exit (3);
590 #endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
591 }
592
593
594 /* Hack required for Windows.  */
595 void 
596 gnupg_allow_set_foregound_window (pid_t pid)
597 {
598   if (!pid || pid == (pid_t)(-1))
599     log_info ("%s called with invalid pid %lu\n",
600               "gnupg_allow_set_foregound_window", (unsigned long)pid);
601 #ifdef HAVE_W32_SYSTEM  
602   else if (!AllowSetForegroundWindow (pid))
603     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
604                (unsigned long)pid, w32_strerror (-1));
605 #endif
606 }