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