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   /* Hold roughly 8 pairs of 64 bit numbers in hex notation:
318      "0xFEDCBA9876543210 0xFEDCBA9876543210".  8*19*2 - 1 = 303.  This
319      plans ahead for a time where a HANDLE is 64 bit.  */
320 #define TRANS_MAX 350
321   char line[TRANS_MAX + 1];
322   char *linep;
323   int idx;
324   int res;
325   int newl = 0;
326
327   /* We always read one line from stdin.  */
328   for (idx = 0; idx < TRANS_MAX; idx++)
329     {
330       res = read (0, &line[idx], 1);
331       if (res != 1)
332         break;
333       if (line[idx] == '\n')
334         {
335           newl = 1;
336           break;
337         }
338     }
339   if (!newl)
340     {
341       char buf[1];
342       do
343         res = read (0, buf, 1);
344       while (res == 1 && *buf != '\n');
345     }
346
347   line[idx] = '\0';
348   linep = line;
349
350   /* Now start to read mapping pairs.  */
351   for (idx = 0; idx < FD_TRANSLATE_MAX; idx++)
352     {
353       unsigned long from;
354       unsigned long to;
355       char *tail;
356
357       while (isspace (*linep))
358         linep++;
359       if (*linep == '\0')
360         break;
361       from = strtoul (linep, &tail, 0);
362       if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
363         break;
364       linep = tail;
365
366       while (isspace (*linep))
367         linep++;
368       if (*linep == '\0')
369         break;
370       to = strtoul (linep, &tail, 0);
371       if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
372         break;
373       linep = tail;
374
375       fd_translate[idx].from = from;
376       fd_translate[idx].to = to;
377       fd_translate_len++;
378     }
379 }
380
381
382 /* Translate a handle number.  */
383 int
384 translate_table_lookup (int fd)
385 {
386   int idx;
387
388   for (idx = 0; idx < fd_translate_len; idx++)
389     if (fd_translate[idx].from == fd)
390       return fd_translate[idx].to;
391   return fd;
392 }
393
394 \f
395 /* This function is a NOP for POSIX systems but required under Windows
396    as the file handles as returned by OS calls (like CreateFile) are
397    different from the libc file descriptors (like open). This function
398    translates system file handles to libc file handles.  FOR_WRITE
399    gives the direction of the handle.  */
400 int
401 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
402 {
403 #ifdef HAVE_W32_SYSTEM
404   int x;
405
406   if (fd == GNUPG_INVALID_FD)
407     return -1;
408   
409   /* Note that _open_osfhandle is currently defined to take and return
410      a long.  */
411   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
412   if (x == -1)
413     log_error ("failed to translate osfhandle %p\n", (void *) fd);
414   return x;
415 #else /*!HAVE_W32_SYSTEM */
416   return fd;
417 #endif
418 }
419
420
421 /* This is the same as translate_sys2libc_fd but takes an integer
422    which is assumed to be such an system handle.  */
423 int
424 translate_sys2libc_fd_int (int fd, int for_write)
425 {
426 #ifdef HAVE_W32_SYSTEM
427   if (fd <= 2)
428     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
429
430   /* Note: If this function is ever used in a different context than
431      option parsing in the main function, a variant that does not do
432      translation probable needs to be used.  */
433   fd = translate_table_lookup (fd);
434
435   return translate_sys2libc_fd ((void*)fd, for_write);
436 #else
437   fd = translate_table_lookup (fd);
438   return fd;
439 #endif
440 }
441
442
443
444 /* Replacement for tmpfile().  This is required because the tmpfile
445    function of Windows' runtime library is broken, insecure, ignores
446    TMPDIR and so on.  In addition we create a file with an inheritable
447    handle.  */
448 FILE *
449 gnupg_tmpfile (void)
450 {
451 #ifdef HAVE_W32_SYSTEM
452   int attempts, n;
453   char buffer[MAX_PATH+7+12+1];
454   char *name, *p;
455   HANDLE file;
456   int pid = GetCurrentProcessId ();
457   unsigned int value;
458   int i;
459   SECURITY_ATTRIBUTES sec_attr;
460
461   memset (&sec_attr, 0, sizeof sec_attr );
462   sec_attr.nLength = sizeof sec_attr;
463   sec_attr.bInheritHandle = TRUE;
464
465   n = GetTempPath (MAX_PATH+1, buffer);
466   if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
467     {
468       errno = ENOENT;
469       return NULL;
470     }
471   p = buffer + strlen (buffer);
472   p = stpcpy (p, "_gnupg");
473   /* We try to create the directory but don't care about an error as
474      it may already exist and the CreateFile would throw an error
475      anyway.  */
476   CreateDirectory (buffer, NULL);
477   *p++ = '\\';
478   name = p;
479   for (attempts=0; attempts < 10; attempts++)
480     {
481       p = name;
482       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
483       for (i=0; i < 8; i++)
484         {
485           *p++ = tohex (((value >> 28) & 0x0f));
486           value <<= 4;
487         }
488       strcpy (p, ".tmp");
489       file = CreateFile (buffer,
490                          GENERIC_READ | GENERIC_WRITE,
491                          0,
492                          &sec_attr,
493                          CREATE_NEW,
494                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
495                          NULL);
496       if (file != INVALID_HANDLE_VALUE)
497         {
498           FILE *fp;
499           int fd = _open_osfhandle ((long)file, 0);
500           if (fd == -1)
501             {
502               CloseHandle (file);
503               return NULL;
504             }
505           fp = fdopen (fd, "w+b");
506           if (!fp)
507             {
508               int save = errno;
509               close (fd);
510               errno = save;
511               return NULL;
512             }
513           return fp;
514         }
515       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
516     }
517   errno = ENOENT;
518   return NULL;
519 #else /*!HAVE_W32_SYSTEM*/
520   return tmpfile ();
521 #endif /*!HAVE_W32_SYSTEM*/
522 }
523
524
525 /* Make sure that the standard file descriptors are opened. Obviously
526    some folks close them before an exec and the next file we open will
527    get one of them assigned and thus any output (i.e. diagnostics) end
528    up in that file (e.g. the trustdb).  Not actually a gpg problem as
529    this will hapen with almost all utilities when called in a wrong
530    way.  However we try to minimize the damage here and raise
531    awareness of the problem.
532
533    Must be called before we open any files! */
534 void
535 gnupg_reopen_std (const char *pgmname)
536 {  
537 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
538   struct stat statbuf;
539   int did_stdin = 0;
540   int did_stdout = 0;
541   int did_stderr = 0;
542   FILE *complain;
543
544   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
545     {
546       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
547         did_stdin = 1;
548       else
549         did_stdin = 2;
550     }
551   
552   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
553     {
554       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
555         did_stdout = 1;
556       else
557         did_stdout = 2;
558     }
559
560   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
561     {
562       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
563         did_stderr = 1;
564       else
565         did_stderr = 2;
566     }
567
568   /* It's hard to log this sort of thing since the filehandle we would
569      complain to may be closed... */
570   if (!did_stderr)
571     complain = stderr;
572   else if (!did_stdout)
573     complain = stdout;
574   else
575     complain = NULL;
576
577   if (complain)
578     {
579       if (did_stdin == 1)
580         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
581       if (did_stdout == 1)
582         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
583       if (did_stderr == 1)
584         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
585
586       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
587         fprintf(complain,"%s: fatal: unable to reopen standard input,"
588                 " output, or error\n", pgmname);
589     }
590
591   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
592     exit (3);
593 #endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
594 }
595
596
597 /* Hack required for Windows.  */
598 void 
599 gnupg_allow_set_foregound_window (pid_t pid)
600 {
601   if (!pid || pid == (pid_t)(-1))
602     log_info ("%s called with invalid pid %lu\n",
603               "gnupg_allow_set_foregound_window", (unsigned long)pid);
604 #ifdef HAVE_W32_SYSTEM  
605   else if (!AllowSetForegroundWindow (pid))
606     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
607                (unsigned long)pid, w32_strerror (-1));
608 #endif
609 }