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