2010-06-10 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
54 #include <assuan.h>
55
56 #include "setenv.h"   /* Gnulib replacement.  */
57
58 #include "util.h"
59 #include "i18n.h"
60
61 #include "sysutils.h"
62
63 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
64
65
66 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
67 #warning using trap_unaligned
68 static int
69 setsysinfo(unsigned long op, void *buffer, unsigned long size,
70                      int *start, void *arg, unsigned long flag)
71 {
72     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
73 }
74
75 void
76 trap_unaligned(void)
77 {
78     unsigned int buf[2];
79
80     buf[0] = SSIN_UACPROC;
81     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
82     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
83 }
84 #else
85 void
86 trap_unaligned(void)
87 {  /* dummy */
88 }
89 #endif
90
91
92 int
93 disable_core_dumps (void)
94 {
95 #ifdef HAVE_DOSISH_SYSTEM
96     return 0;
97 #else
98 # ifdef HAVE_SETRLIMIT
99     struct rlimit limit;
100
101     /* We only set the current limit unless we were not able to
102        retrieve the old value. */
103     if (getrlimit (RLIMIT_CORE, &limit))
104       limit.rlim_max = 0;
105     limit.rlim_cur = 0;
106     if( !setrlimit (RLIMIT_CORE, &limit) )
107         return 0;
108     if( errno != EINVAL && errno != ENOSYS )
109         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
110 #endif
111     return 1;
112 #endif
113 }
114
115 int
116 enable_core_dumps (void)
117 {
118 #ifdef HAVE_DOSISH_SYSTEM
119     return 0;
120 #else
121 # ifdef HAVE_SETRLIMIT
122     struct rlimit limit;
123
124     if (getrlimit (RLIMIT_CORE, &limit))
125       return 1;
126     limit.rlim_cur = limit.rlim_max;
127     setrlimit (RLIMIT_CORE, &limit);
128     return 1; /* We always return true because this function is
129                  merely a debugging aid. */
130 # endif
131     return 1;
132 #endif
133 }
134
135
136
137 /* Return a string which is used as a kind of process ID.  */
138 const byte *
139 get_session_marker (size_t *rlen)
140 {
141   static byte marker[SIZEOF_UNSIGNED_LONG*2];
142   static int initialized;
143   
144   if (!initialized)
145     {
146       gcry_create_nonce (marker, sizeof marker);
147       initialized = 1;
148     }
149   *rlen = sizeof (marker);
150   return marker;
151 }
152
153
154 #if 0 /* not yet needed - Note that this will require inclusion of
155          cmacros.am in Makefile.am */
156 int
157 check_permissions(const char *path,int extension,int checkonly)
158 {
159 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
160   char *tmppath;
161   struct stat statbuf;
162   int ret=1;
163   int isdir=0;
164
165   if(opt.no_perm_warn)
166     return 0;
167
168   if(extension && path[0]!=DIRSEP_C)
169     {
170       if(strchr(path,DIRSEP_C))
171         tmppath=make_filename(path,NULL);
172       else
173         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
174     }
175   else
176     tmppath=m_strdup(path);
177
178   /* It's okay if the file doesn't exist */
179   if(stat(tmppath,&statbuf)!=0)
180     {
181       ret=0;
182       goto end;
183     }
184
185   isdir=S_ISDIR(statbuf.st_mode);
186
187   /* Per-user files must be owned by the user.  Extensions must be
188      owned by the user or root. */
189   if((!extension && statbuf.st_uid != getuid()) ||
190      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
191     {
192       if(!checkonly)
193         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
194                  isdir?"directory":extension?"extension":"file",path);
195       goto end;
196     }
197
198   /* This works for both directories and files - basically, we don't
199      care what the owner permissions are, so long as the group and
200      other permissions are 0 for per-user files, and non-writable for
201      extensions. */
202   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
203      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
204     {
205       char *dir;
206
207       /* However, if the directory the directory/file is in is owned
208          by the user and is 700, then this is not a problem.
209          Theoretically, we could walk this test up to the root
210          directory /, but for the sake of sanity, I'm stopping at one
211          level down. */
212
213       dir= make_dirname (tmppath);
214       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
215          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
216         {
217           xfree (dir);
218           ret=0;
219           goto end;
220         }
221
222       m_free(dir);
223
224       if(!checkonly)
225         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
226                  isdir?"directory":extension?"extension":"file",path);
227       goto end;
228     }
229
230   ret=0;
231
232  end:
233   m_free(tmppath);
234
235   return ret;
236
237 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
238
239   return 0;
240 }
241 #endif
242
243
244 /* Wrapper around the usual sleep fucntion.  This one won't wake up
245    before the sleep time has really elapsed.  When build with Pth it
246    merely calls pth_sleep and thus suspends only the current
247    thread. */
248 void
249 gnupg_sleep (unsigned int seconds)
250 {
251 #ifdef HAVE_PTH
252   /* With Pth we force a regular sleep for seconds == 0 so that also
253      the process will give up its timeslot.  */
254   if (!seconds)
255     {
256 # ifdef HAVE_W32_SYSTEM    
257       Sleep (0);
258 # else
259       sleep (0);
260 # endif
261     }
262   pth_sleep (seconds);
263 #else
264   /* Fixme:  make sure that a sleep won't wake up to early.  */
265 # ifdef HAVE_W32_SYSTEM    
266   Sleep (seconds*1000);
267 # else
268   sleep (seconds);
269 # endif
270 #endif
271 }
272
273
274 /* This function is a NOP for POSIX systems but required under Windows
275    as the file handles as returned by OS calls (like CreateFile) are
276    different from the libc file descriptors (like open). This function
277    translates system file handles to libc file handles.  FOR_WRITE
278    gives the direction of the handle.  */
279 int
280 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
281 {
282 #if defined(HAVE_W32CE_SYSTEM)
283   return (int) _assuan_w32ce_finish_pipe ((int)fd, for_write);
284 #elif defined(HAVE_W32_SYSTEM)
285   int x;
286
287   if (fd == GNUPG_INVALID_FD)
288     return -1;
289   
290   /* Note that _open_osfhandle is currently defined to take and return
291      a long.  */
292   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
293   if (x == -1)
294     log_error ("failed to translate osfhandle %p\n", (void *) fd);
295   return x;
296 #else /*!HAVE_W32_SYSTEM */
297   (void)for_write;
298   return fd;
299 #endif
300 }
301
302 /* This is the same as translate_sys2libc_fd but takes an integer
303    which is assumed to be such an system handle.  On WindowsCE the
304    passed FD is a rendezvous ID and the function finishes the pipe
305    creation. */
306 int
307 translate_sys2libc_fd_int (int fd, int for_write)
308 {
309 #if HAVE_W32CE_SYSTEM
310   return (int) _assuan_w32ce_finish_pipe (fd, for_write);
311 #elif 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   (void)for_write;
318   return fd;
319 #endif
320 }
321
322
323
324 /* Replacement for tmpfile().  This is required because the tmpfile
325    function of Windows' runtime library is broken, insecure, ignores
326    TMPDIR and so on.  In addition we create a file with an inheritable
327    handle.  */
328 FILE *
329 gnupg_tmpfile (void)
330 {
331 #ifdef HAVE_W32_SYSTEM
332   int attempts, n;
333 #ifdef HAVE_W32CE_SYSTEM
334   wchar_t buffer[MAX_PATH+7+12+1];
335 # define mystrlen(a) wcslen (a)
336   wchar_t *name, *p;
337 #else
338   char buffer[MAX_PATH+7+12+1];
339 # define mystrlen(a) strlen (a)
340   char *name, *p;
341 #endif
342   HANDLE file;
343   int pid = GetCurrentProcessId ();
344   unsigned int value;
345   int i;
346   SECURITY_ATTRIBUTES sec_attr;
347
348   memset (&sec_attr, 0, sizeof sec_attr );
349   sec_attr.nLength = sizeof sec_attr;
350   sec_attr.bInheritHandle = TRUE;
351
352   n = GetTempPath (MAX_PATH+1, buffer);
353   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
354     {
355       gpg_err_set_errno (ENOENT);
356       return NULL;
357     }
358   p = buffer + mystrlen (buffer);
359 #ifdef HAVE_W32CE_SYSTEM
360   wcscpy (p, L"_gnupg");
361   p += 7;
362 #else
363   p = stpcpy (p, "_gnupg");
364 #endif
365   /* We try to create the directory but don't care about an error as
366      it may already exist and the CreateFile would throw an error
367      anyway.  */
368   CreateDirectory (buffer, NULL);
369   *p++ = '\\';
370   name = p;
371   for (attempts=0; attempts < 10; attempts++)
372     {
373       p = name;
374       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
375       for (i=0; i < 8; i++)
376         {
377           *p++ = tohex (((value >> 28) & 0x0f));
378           value <<= 4;
379         }
380 #ifdef HAVE_W32CE_SYSTEM
381       wcscpy (p, L".tmp");
382 #else
383       strcpy (p, ".tmp");
384 #endif
385       file = CreateFile (buffer,
386                          GENERIC_READ | GENERIC_WRITE,
387                          0,
388                          &sec_attr,
389                          CREATE_NEW,
390                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
391                          NULL);
392       if (file != INVALID_HANDLE_VALUE)
393         {
394           FILE *fp;
395 #ifdef HAVE_W32CE_SYSTEM
396           int fd = (int)file;
397           fp = _wfdopen (fd, L"w+b");
398 #else
399           int fd = _open_osfhandle ((long)file, 0);
400           if (fd == -1)
401             {
402               CloseHandle (file);
403               return NULL;
404             }
405           fp = fdopen (fd, "w+b");
406 #endif
407           if (!fp)
408             {
409               int save = errno;
410               close (fd);
411               gpg_err_set_errno (save);
412               return NULL;
413             }
414           return fp;
415         }
416       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
417     }
418   gpg_err_set_errno (ENOENT);
419   return NULL;
420 #undef mystrlen
421 #else /*!HAVE_W32_SYSTEM*/
422   return tmpfile ();
423 #endif /*!HAVE_W32_SYSTEM*/
424 }
425
426
427 /* Make sure that the standard file descriptors are opened. Obviously
428    some folks close them before an exec and the next file we open will
429    get one of them assigned and thus any output (i.e. diagnostics) end
430    up in that file (e.g. the trustdb).  Not actually a gpg problem as
431    this will hapen with almost all utilities when called in a wrong
432    way.  However we try to minimize the damage here and raise
433    awareness of the problem.
434
435    Must be called before we open any files! */
436 void
437 gnupg_reopen_std (const char *pgmname)
438 {  
439 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
440   struct stat statbuf;
441   int did_stdin = 0;
442   int did_stdout = 0;
443   int did_stderr = 0;
444   FILE *complain;
445
446   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
447     {
448       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
449         did_stdin = 1;
450       else
451         did_stdin = 2;
452     }
453   
454   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
455     {
456       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
457         did_stdout = 1;
458       else
459         did_stdout = 2;
460     }
461
462   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
463     {
464       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
465         did_stderr = 1;
466       else
467         did_stderr = 2;
468     }
469
470   /* It's hard to log this sort of thing since the filehandle we would
471      complain to may be closed... */
472   if (!did_stderr)
473     complain = stderr;
474   else if (!did_stdout)
475     complain = stdout;
476   else
477     complain = NULL;
478
479   if (complain)
480     {
481       if (did_stdin == 1)
482         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
483       if (did_stdout == 1)
484         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
485       if (did_stderr == 1)
486         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
487
488       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
489         fprintf(complain,"%s: fatal: unable to reopen standard input,"
490                 " output, or error\n", pgmname);
491     }
492
493   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
494     exit (3);
495 #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
496   (void)pgmname;
497 #endif
498 }
499
500
501 /* Hack required for Windows.  */
502 void 
503 gnupg_allow_set_foregound_window (pid_t pid)
504 {
505   if (!pid)
506     log_info ("%s called with invalid pid %lu\n",
507               "gnupg_allow_set_foregound_window", (unsigned long)pid);
508 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
509   else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
510     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
511                (unsigned long)pid, w32_strerror (-1));
512 #endif
513 }
514
515 int
516 gnupg_remove (const char *fname)
517 {
518 #ifdef HAVE_W32CE_SYSTEM
519   int rc;
520   wchar_t *wfname;
521
522   wfname = utf8_to_wchar (fname);
523   if (!wfname)
524     rc = 0;
525   else
526     {
527       rc = DeleteFile (wfname);
528       xfree (wfname);
529     }
530   if (!rc)
531     gpg_err_set_errno (EIO);
532   return !rc;
533 #else
534   return remove (fname);
535 #endif
536 }
537
538
539 /* A wrapper around mkdir which takes a string for the mode argument.
540    This makes it easier to handle the mode argument which is not
541    defined on all systems.  The format of the modestring is
542
543       "-rwxrwxrwx"
544       
545    '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
546    write allowed, execution allowed with the first group for the user,
547    the second for the group and the third for all others.  If the
548    string is shorter than above the missing mode characters are meant
549    to be not set.  */
550 int
551 gnupg_mkdir (const char *name, const char *modestr)
552 {
553 #ifdef HAVE_W32CE_SYSTEM
554   wchar_t *wname;
555   (void)modestr;
556   
557   wname = utf8_to_wchar (name);
558   if (!wname)
559     return -1;
560   if (!CreateDirectoryW (wname, NULL))
561     {
562       xfree (wname);
563       return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
564     }
565   xfree (wname);
566   return 0;
567 #elif MKDIR_TAKES_ONE_ARG
568   (void)modestr;
569   /* Note: In the case of W32 we better use CreateDirectory and try to
570      set appropriate permissions.  However using mkdir is easier
571      because this sets ERRNO.  */
572   return mkdir (name);
573 #else
574   mode_t mode = 0;
575
576   if (modestr && *modestr)
577     {
578       modestr++;
579       if (*modestr && *modestr++ == 'r')
580         mode |= S_IRUSR;
581       if (*modestr && *modestr++ == 'w')
582         mode |= S_IWUSR;
583       if (*modestr && *modestr++ == 'x')
584         mode |= S_IXUSR;
585       if (*modestr && *modestr++ == 'r')
586         mode |= S_IRGRP;
587       if (*modestr && *modestr++ == 'w')
588         mode |= S_IWGRP;
589       if (*modestr && *modestr++ == 'x')
590         mode |= S_IXGRP;
591       if (*modestr && *modestr++ == 'r')
592         mode |= S_IROTH;
593       if (*modestr && *modestr++ == 'w')
594         mode |= S_IWOTH;
595       if (*modestr && *modestr++ == 'x')
596         mode |= S_IXOTH;
597     }
598   return mkdir (name, mode);
599 #endif
600 }
601
602
603 int
604 gnupg_setenv (const char *name, const char *value, int overwrite)
605 {
606 #ifdef HAVE_W32CE_SYSTEM
607   (void)name;
608   (void)value;
609   (void)overwrite;
610   return 0;
611 #else
612   return setenv (name, value, overwrite);
613 #endif
614 }
615
616 int 
617 gnupg_unsetenv (const char *name)
618 {
619 #ifdef HAVE_W32CE_SYSTEM
620   (void)name;
621   return 0;
622 #else
623 # ifdef HAVE_UNSETENV
624   return unsetenv (name);
625 # else
626   return putenv (name);
627 # endif
628 #endif
629 }
630
631 #ifdef HAVE_W32CE_SYSTEM
632 /* There is a isatty function declaration in cegcc but it does not
633    make sense, thus we redefine it.  */
634 int 
635 _gnupg_isatty (int fd)
636 {
637   (void)fd;
638   return 0;
639 }
640 #endif
641
642
643 #ifdef HAVE_W32CE_SYSTEM
644 /* Replacement for getenv which takes care of the our use of getenv.
645    The code is not thread safe but we expect it to work in all cases
646    because it is called for the first time early enough.  */
647 char *
648 _gnupg_getenv (const char *name)
649 {
650   static int initialized;
651   static char *assuan_debug;
652   
653   if (!initialized)
654     {
655       assuan_debug = read_w32_registry_string (NULL, 
656                                                "\\Software\\GNU\\libassuan",
657                                                "debug");
658       initialized = 1;
659     }
660
661   if (!strcmp (name, "ASSUAN_DEBUG"))
662     return assuan_debug;
663   else
664     return NULL;
665 }
666
667 #endif /*HAVE_W32CE_SYSTEM*/
668