Try to make sure that the standard descriptors are connected when calling
[gnupg.git] / common / sysutils.c
1 /* sysutils.c -  system helpers
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004,
3  *               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
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 # include <windows.h>
47 #endif
48 #ifdef HAVE_PTH      
49 # include <pth.h>
50 #endif
51 #include <fcntl.h>
52
53 #include "util.h"
54 #include "i18n.h"
55
56 #include "sysutils.h"
57
58 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
59
60
61 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
62 #warning using trap_unaligned
63 static int
64 setsysinfo(unsigned long op, void *buffer, unsigned long size,
65                      int *start, void *arg, unsigned long flag)
66 {
67     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
68 }
69
70 void
71 trap_unaligned(void)
72 {
73     unsigned int buf[2];
74
75     buf[0] = SSIN_UACPROC;
76     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
77     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
78 }
79 #else
80 void
81 trap_unaligned(void)
82 {  /* dummy */
83 }
84 #endif
85
86
87 int
88 disable_core_dumps (void)
89 {
90 #ifdef HAVE_DOSISH_SYSTEM
91     return 0;
92 #else
93 # ifdef HAVE_SETRLIMIT
94     struct rlimit limit;
95
96     /* We only set the current limit unless we were not able to
97        retrieve the old value. */
98     if (getrlimit (RLIMIT_CORE, &limit))
99       limit.rlim_max = 0;
100     limit.rlim_cur = 0;
101     if( !setrlimit (RLIMIT_CORE, &limit) )
102         return 0;
103     if( errno != EINVAL && errno != ENOSYS )
104         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
105 #endif
106     return 1;
107 #endif
108 }
109
110 int
111 enable_core_dumps (void)
112 {
113 #ifdef HAVE_DOSISH_SYSTEM
114     return 0;
115 #else
116 # ifdef HAVE_SETRLIMIT
117     struct rlimit limit;
118
119     if (getrlimit (RLIMIT_CORE, &limit))
120       return 1;
121     limit.rlim_cur = limit.rlim_max;
122     setrlimit (RLIMIT_CORE, &limit);
123     return 1; /* We always return true because this function is
124                  merely a debugging aid. */
125 # endif
126     return 1;
127 #endif
128 }
129
130
131
132 /* Return a string which is used as a kind of process ID */
133 const byte *
134 get_session_marker( size_t *rlen )
135 {
136     static byte marker[SIZEOF_UNSIGNED_LONG*2];
137     static int initialized;
138
139     if ( !initialized ) {
140         volatile ulong aa, bb; /* we really want the uninitialized value */
141         ulong a, b;
142
143         initialized = 1;
144         /* Although this marker is guessable it is not easy to use
145          * for a faked control packet because an attacker does not
146          * have enough control about the time the verification does 
147          * take place.  Of course, we can add just more random but 
148          * than we need the random generator even for verification
149          * tasks - which does not make sense. */
150         a = aa ^ (ulong)getpid();
151         b = bb ^ (ulong)time(NULL);
152         memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
153         memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
154     }
155     *rlen = sizeof(marker);
156     return marker;
157 }
158
159
160 #if 0 /* not yet needed - Note that this will require inclusion of
161          cmacros.am in Makefile.am */
162 int
163 check_permissions(const char *path,int extension,int checkonly)
164 {
165 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
166   char *tmppath;
167   struct stat statbuf;
168   int ret=1;
169   int isdir=0;
170
171   if(opt.no_perm_warn)
172     return 0;
173
174   if(extension && path[0]!=DIRSEP_C)
175     {
176       if(strchr(path,DIRSEP_C))
177         tmppath=make_filename(path,NULL);
178       else
179         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
180     }
181   else
182     tmppath=m_strdup(path);
183
184   /* It's okay if the file doesn't exist */
185   if(stat(tmppath,&statbuf)!=0)
186     {
187       ret=0;
188       goto end;
189     }
190
191   isdir=S_ISDIR(statbuf.st_mode);
192
193   /* Per-user files must be owned by the user.  Extensions must be
194      owned by the user or root. */
195   if((!extension && statbuf.st_uid != getuid()) ||
196      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
197     {
198       if(!checkonly)
199         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
200                  isdir?"directory":extension?"extension":"file",path);
201       goto end;
202     }
203
204   /* This works for both directories and files - basically, we don't
205      care what the owner permissions are, so long as the group and
206      other permissions are 0 for per-user files, and non-writable for
207      extensions. */
208   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
209      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
210     {
211       char *dir;
212
213       /* However, if the directory the directory/file is in is owned
214          by the user and is 700, then this is not a problem.
215          Theoretically, we could walk this test up to the root
216          directory /, but for the sake of sanity, I'm stopping at one
217          level down. */
218
219       dir= make_dirname (tmppath);
220       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
221          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
222         {
223           xfree (dir);
224           ret=0;
225           goto end;
226         }
227
228       m_free(dir);
229
230       if(!checkonly)
231         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
232                  isdir?"directory":extension?"extension":"file",path);
233       goto end;
234     }
235
236   ret=0;
237
238  end:
239   m_free(tmppath);
240
241   return ret;
242
243 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
244
245   return 0;
246 }
247 #endif
248
249
250 /* Wrapper around the usual sleep fucntion.  This one won't wake up
251    before the sleep time has really elapsed.  When build with Pth it
252    merely calls pth_sleep and thus suspends only the current
253    thread. */
254 void
255 gnupg_sleep (unsigned int seconds)
256 {
257 #ifdef HAVE_PTH
258   /* With Pth we force a regular sleep for seconds == 0 so that also
259      the process will give up its timeslot.  */
260   if (!seconds)
261     {
262 # ifdef HAVE_W32_SYSTEM    
263       Sleep (0);
264 # else
265       sleep (0);
266 # endif
267     }
268   pth_sleep (seconds);
269 #else
270   /* Fixme:  make sure that a sleep won't wake up to early.  */
271 # ifdef HAVE_W32_SYSTEM    
272   Sleep (seconds*1000);
273 # else
274   sleep (seconds);
275 # endif
276 #endif
277 }
278
279
280 /* This function is a NOP for POSIX systems but required under Windows
281    as the file handles as returned by OS calls (like CreateFile) are
282    different from the libc file descriptors (like open). This function
283    translates system file handles to libc file handles.  FOR_WRITE
284    gives the direction of the handle.  */
285 int
286 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
287 {
288 #ifdef HAVE_W32_SYSTEM
289   int x;
290
291   if (fd == GNUPG_INVALID_FD)
292     return -1;
293   
294   /* Note that _open_osfhandle is currently defined to take and return
295      a long.  */
296   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
297   if (x == -1)
298     log_error ("failed to translate osfhandle %p\n", (void *) fd);
299   return x;
300 #else /*!HAVE_W32_SYSTEM */
301   return fd;
302 #endif
303 }
304
305 /* This is the same as translate_sys2libc_fd but takes an integer
306    which is assumed to be such an system handle.  */
307 int
308 translate_sys2libc_fd_int (int fd, int for_write)
309 {
310 #ifdef HAVE_W32_SYSTEM
311   if (fd <= 2)
312     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
313
314   return translate_sys2libc_fd ((void*)fd, for_write);
315 #else
316   return fd;
317 #endif
318 }
319
320
321
322 /* Replacement for tmpfile().  This is required because the tmpfile
323    function of Windows' runtime library is broken, insecure, ignores
324    TMPDIR and so on.  In addition we create a file with an inheritable
325    handle.  */
326 FILE *
327 gnupg_tmpfile (void)
328 {
329 #ifdef HAVE_W32_SYSTEM
330   int attempts, n;
331   char buffer[MAX_PATH+7+12+1];
332   char *name, *p;
333   HANDLE file;
334   int pid = GetCurrentProcessId ();
335   unsigned int value;
336   int i;
337   SECURITY_ATTRIBUTES sec_attr;
338
339   memset (&sec_attr, 0, sizeof sec_attr );
340   sec_attr.nLength = sizeof sec_attr;
341   sec_attr.bInheritHandle = TRUE;
342
343   n = GetTempPath (MAX_PATH+1, buffer);
344   if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
345     {
346       errno = ENOENT;
347       return NULL;
348     }
349   p = buffer + strlen (buffer);
350   p = stpcpy (p, "_gnupg");
351   /* We try to create the directory but don't care about an error as
352      it may already exist and the CreateFile would throw an error
353      anyway.  */
354   CreateDirectory (buffer, NULL);
355   *p++ = '\\';
356   name = p;
357   for (attempts=0; attempts < 10; attempts++)
358     {
359       p = name;
360       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
361       for (i=0; i < 8; i++)
362         {
363           *p++ = tohex (((value >> 28) & 0x0f));
364           value <<= 4;
365         }
366       strcpy (p, ".tmp");
367       file = CreateFile (buffer,
368                          GENERIC_READ | GENERIC_WRITE,
369                          0,
370                          &sec_attr,
371                          CREATE_NEW,
372                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
373                          NULL);
374       if (file != INVALID_HANDLE_VALUE)
375         {
376           FILE *fp;
377           int fd = _open_osfhandle ((long)file, 0);
378           if (fd == -1)
379             {
380               CloseHandle (file);
381               return NULL;
382             }
383           fp = fdopen (fd, "w+b");
384           if (!fp)
385             {
386               int save = errno;
387               close (fd);
388               errno = save;
389               return NULL;
390             }
391           return fp;
392         }
393       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
394     }
395   errno = ENOENT;
396   return NULL;
397 #else /*!HAVE_W32_SYSTEM*/
398   return tmpfile ();
399 #endif /*!HAVE_W32_SYSTEM*/
400 }
401
402
403 /* Make sure that the standard file descriptors are opened. Obviously
404    some folks close them before an exec and the next file we open will
405    get one of them assigned and thus any output (i.e. diagnostics) end
406    up in that file (e.g. the trustdb).  Not actually a gpg problem as
407    this will hapen with almost all utilities when called in a wrong
408    way.  However we try to minimize the damage here and raise
409    awareness of the problem.
410
411    Must be called before we open any files! */
412 void
413 gnupg_reopen_std (const char *pgmname)
414 {  
415 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
416   struct stat statbuf;
417   int did_stdin = 0;
418   int did_stdout = 0;
419   int did_stderr = 0;
420   FILE *complain;
421
422   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
423     {
424       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
425         did_stdin = 1;
426       else
427         did_stdin = 2;
428     }
429   
430   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
431     {
432       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
433         did_stdout = 1;
434       else
435         did_stdout = 2;
436     }
437
438   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
439     {
440       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
441         did_stderr = 1;
442       else
443         did_stderr = 2;
444     }
445
446   /* It's hard to log this sort of thing since the filehandle we would
447      complain to may be closed... */
448   if (!did_stderr)
449     complain = stderr;
450   else if (!did_stdout)
451     complain = stdout;
452   else
453     complain = NULL;
454
455   if (complain)
456     {
457       if (did_stdin == 1)
458         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
459       if (did_stdout == 1)
460         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
461       if (did_stderr == 1)
462         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
463
464       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
465         fprintf(complain,"%s: fatal: unable to reopen standard input,"
466                 " output, or error\n", pgmname);
467     }
468
469   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
470     exit (3);
471 #endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
472 }
473