7fb8b20c94595b71c06252c19c1823482eccb453
[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     {
142       gcry_create_nonce (marker, sizeof marker);
143       initialized = 1;
144     }
145   *rlen = sizeof (marker);
146   return marker;
147 }
148
149
150 #if 0 /* not yet needed - Note that this will require inclusion of
151          cmacros.am in Makefile.am */
152 int
153 check_permissions(const char *path,int extension,int checkonly)
154 {
155 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
156   char *tmppath;
157   struct stat statbuf;
158   int ret=1;
159   int isdir=0;
160
161   if(opt.no_perm_warn)
162     return 0;
163
164   if(extension && path[0]!=DIRSEP_C)
165     {
166       if(strchr(path,DIRSEP_C))
167         tmppath=make_filename(path,NULL);
168       else
169         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
170     }
171   else
172     tmppath=m_strdup(path);
173
174   /* It's okay if the file doesn't exist */
175   if(stat(tmppath,&statbuf)!=0)
176     {
177       ret=0;
178       goto end;
179     }
180
181   isdir=S_ISDIR(statbuf.st_mode);
182
183   /* Per-user files must be owned by the user.  Extensions must be
184      owned by the user or root. */
185   if((!extension && statbuf.st_uid != getuid()) ||
186      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
187     {
188       if(!checkonly)
189         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
190                  isdir?"directory":extension?"extension":"file",path);
191       goto end;
192     }
193
194   /* This works for both directories and files - basically, we don't
195      care what the owner permissions are, so long as the group and
196      other permissions are 0 for per-user files, and non-writable for
197      extensions. */
198   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
199      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
200     {
201       char *dir;
202
203       /* However, if the directory the directory/file is in is owned
204          by the user and is 700, then this is not a problem.
205          Theoretically, we could walk this test up to the root
206          directory /, but for the sake of sanity, I'm stopping at one
207          level down. */
208
209       dir= make_dirname (tmppath);
210       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
211          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
212         {
213           xfree (dir);
214           ret=0;
215           goto end;
216         }
217
218       m_free(dir);
219
220       if(!checkonly)
221         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
222                  isdir?"directory":extension?"extension":"file",path);
223       goto end;
224     }
225
226   ret=0;
227
228  end:
229   m_free(tmppath);
230
231   return ret;
232
233 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
234
235   return 0;
236 }
237 #endif
238
239
240 /* Wrapper around the usual sleep fucntion.  This one won't wake up
241    before the sleep time has really elapsed.  When build with Pth it
242    merely calls pth_sleep and thus suspends only the current
243    thread. */
244 void
245 gnupg_sleep (unsigned int seconds)
246 {
247 #ifdef HAVE_PTH
248   /* With Pth we force a regular sleep for seconds == 0 so that also
249      the process will give up its timeslot.  */
250   if (!seconds)
251     {
252 # ifdef HAVE_W32_SYSTEM    
253       Sleep (0);
254 # else
255       sleep (0);
256 # endif
257     }
258   pth_sleep (seconds);
259 #else
260   /* Fixme:  make sure that a sleep won't wake up to early.  */
261 # ifdef HAVE_W32_SYSTEM    
262   Sleep (seconds*1000);
263 # else
264   sleep (seconds);
265 # endif
266 #endif
267 }
268
269
270 /* This function is a NOP for POSIX systems but required under Windows
271    as the file handles as returned by OS calls (like CreateFile) are
272    different from the libc file descriptors (like open). This function
273    translates system file handles to libc file handles.  FOR_WRITE
274    gives the direction of the handle.  */
275 int
276 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
277 {
278 #if defined(HAVE_W32CE_SYSTEM)
279   (void)for_write;
280   return (int)fd;
281 #elif defined(HAVE_W32_SYSTEM)
282   int x;
283
284   if (fd == GNUPG_INVALID_FD)
285     return -1;
286   
287   /* Note that _open_osfhandle is currently defined to take and return
288      a long.  */
289   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
290   if (x == -1)
291     log_error ("failed to translate osfhandle %p\n", (void *) fd);
292   return x;
293 #else /*!HAVE_W32_SYSTEM */
294   (void)for_write;
295   return fd;
296 #endif
297 }
298
299 /* This is the same as translate_sys2libc_fd but takes an integer
300    which is assumed to be such an system handle.  */
301 int
302 translate_sys2libc_fd_int (int fd, int for_write)
303 {
304 #ifdef HAVE_W32_SYSTEM
305   if (fd <= 2)
306     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
307
308   return translate_sys2libc_fd ((void*)fd, for_write);
309 #else
310   (void)for_write;
311   return fd;
312 #endif
313 }
314
315
316
317 /* Replacement for tmpfile().  This is required because the tmpfile
318    function of Windows' runtime library is broken, insecure, ignores
319    TMPDIR and so on.  In addition we create a file with an inheritable
320    handle.  */
321 FILE *
322 gnupg_tmpfile (void)
323 {
324 #ifdef HAVE_W32_SYSTEM
325   int attempts, n;
326 #ifdef HAVE_W32CE_SYSTEM
327   wchar_t buffer[MAX_PATH+7+12+1];
328 # define mystrlen(a) wcslen (a)
329   wchar_t *name, *p;
330 #else
331   char buffer[MAX_PATH+7+12+1];
332 # define mystrlen(a) strlen (a)
333   char *name, *p;
334 #endif
335   HANDLE file;
336   int pid = GetCurrentProcessId ();
337   unsigned int value;
338   int i;
339   SECURITY_ATTRIBUTES sec_attr;
340
341   memset (&sec_attr, 0, sizeof sec_attr );
342   sec_attr.nLength = sizeof sec_attr;
343   sec_attr.bInheritHandle = TRUE;
344
345   n = GetTempPath (MAX_PATH+1, buffer);
346   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
347     {
348       gpg_err_set_errno (ENOENT);
349       return NULL;
350     }
351   p = buffer + mystrlen (buffer);
352 #ifdef HAVE_W32CE_SYSTEM
353   wcscpy (p, L"_gnupg");
354   p += 7;
355 #else
356   p = stpcpy (p, "_gnupg");
357 #endif
358   /* We try to create the directory but don't care about an error as
359      it may already exist and the CreateFile would throw an error
360      anyway.  */
361   CreateDirectory (buffer, NULL);
362   *p++ = '\\';
363   name = p;
364   for (attempts=0; attempts < 10; attempts++)
365     {
366       p = name;
367       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
368       for (i=0; i < 8; i++)
369         {
370           *p++ = tohex (((value >> 28) & 0x0f));
371           value <<= 4;
372         }
373 #ifdef HAVE_W32CE_SYSTEM
374       wcscpy (p, L".tmp");
375 #else
376       strcpy (p, ".tmp");
377 #endif
378       file = CreateFile (buffer,
379                          GENERIC_READ | GENERIC_WRITE,
380                          0,
381                          &sec_attr,
382                          CREATE_NEW,
383                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
384                          NULL);
385       if (file != INVALID_HANDLE_VALUE)
386         {
387           FILE *fp;
388 #ifdef HAVE_W32CE_SYSTEM
389           int fd = (int)file;
390           fp = _wfdopen (fd, L"w+b");
391 #else
392           int fd = _open_osfhandle ((long)file, 0);
393           if (fd == -1)
394             {
395               CloseHandle (file);
396               return NULL;
397             }
398           fp = fdopen (fd, "w+b");
399 #endif
400           if (!fp)
401             {
402               int save = errno;
403               close (fd);
404               gpg_err_set_errno (save);
405               return NULL;
406             }
407           return fp;
408         }
409       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
410     }
411   gpg_err_set_errno (ENOENT);
412   return NULL;
413 #undef mystrlen
414 #else /*!HAVE_W32_SYSTEM*/
415   return tmpfile ();
416 #endif /*!HAVE_W32_SYSTEM*/
417 }
418
419
420 /* Make sure that the standard file descriptors are opened. Obviously
421    some folks close them before an exec and the next file we open will
422    get one of them assigned and thus any output (i.e. diagnostics) end
423    up in that file (e.g. the trustdb).  Not actually a gpg problem as
424    this will hapen with almost all utilities when called in a wrong
425    way.  However we try to minimize the damage here and raise
426    awareness of the problem.
427
428    Must be called before we open any files! */
429 void
430 gnupg_reopen_std (const char *pgmname)
431 {  
432 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
433   struct stat statbuf;
434   int did_stdin = 0;
435   int did_stdout = 0;
436   int did_stderr = 0;
437   FILE *complain;
438
439   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
440     {
441       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
442         did_stdin = 1;
443       else
444         did_stdin = 2;
445     }
446   
447   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
448     {
449       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
450         did_stdout = 1;
451       else
452         did_stdout = 2;
453     }
454
455   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
456     {
457       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
458         did_stderr = 1;
459       else
460         did_stderr = 2;
461     }
462
463   /* It's hard to log this sort of thing since the filehandle we would
464      complain to may be closed... */
465   if (!did_stderr)
466     complain = stderr;
467   else if (!did_stdout)
468     complain = stdout;
469   else
470     complain = NULL;
471
472   if (complain)
473     {
474       if (did_stdin == 1)
475         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
476       if (did_stdout == 1)
477         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
478       if (did_stderr == 1)
479         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
480
481       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
482         fprintf(complain,"%s: fatal: unable to reopen standard input,"
483                 " output, or error\n", pgmname);
484     }
485
486   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
487     exit (3);
488 #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
489   (void)pgmname;
490 #endif
491 }
492
493
494 /* Hack required for Windows.  */
495 void 
496 gnupg_allow_set_foregound_window (pid_t pid)
497 {
498   if (!pid)
499     log_info ("%s called with invalid pid %lu\n",
500               "gnupg_allow_set_foregound_window", (unsigned long)pid);
501 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
502   else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
503     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
504                (unsigned long)pid, w32_strerror (-1));
505 #endif
506 }
507
508
509
510 #ifdef HAVE_W32CE_SYSTEM
511 /* Replacement for getenv which takes care of the our use of getenv.
512    The code is not thread safe but we expect it to work in all cases
513    because it is called for the first time early enough.  */
514 char *
515 _gnupg_getenv (const char *name)
516 {
517   (void)name;
518   return NULL;
519 }
520 #endif /*HAVE_W32CE_SYSTEM*/
521