Auto-start dirmngr.
[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   (void)for_write;
284   return (int) fd;
285 #elif defined(HAVE_W32_SYSTEM)
286   int x;
287
288   if (fd == GNUPG_INVALID_FD)
289     return -1;
290   
291   /* Note that _open_osfhandle is currently defined to take and return
292      a long.  */
293   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
294   if (x == -1)
295     log_error ("failed to translate osfhandle %p\n", (void *) fd);
296   return x;
297 #else /*!HAVE_W32_SYSTEM */
298   (void)for_write;
299   return fd;
300 #endif
301 }
302
303 /* This is the same as translate_sys2libc_fd but takes an integer
304    which is assumed to be such an system handle.  On WindowsCE the
305    passed FD is a rendezvous ID and the function finishes the pipe
306    creation. */
307 int
308 translate_sys2libc_fd_int (int fd, int for_write)
309 {
310 #if HAVE_W32CE_SYSTEM
311   fd = (int) _assuan_w32ce_finish_pipe (fd, for_write);
312   return translate_sys2libc_fd ((void*)fd, for_write);
313 #elif HAVE_W32_SYSTEM
314   if (fd <= 2)
315     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
316
317   return translate_sys2libc_fd ((void*)fd, for_write);
318 #else
319   (void)for_write;
320   return fd;
321 #endif
322 }
323
324
325
326 /* Replacement for tmpfile().  This is required because the tmpfile
327    function of Windows' runtime library is broken, insecure, ignores
328    TMPDIR and so on.  In addition we create a file with an inheritable
329    handle.  */
330 FILE *
331 gnupg_tmpfile (void)
332 {
333 #ifdef HAVE_W32_SYSTEM
334   int attempts, n;
335 #ifdef HAVE_W32CE_SYSTEM
336   wchar_t buffer[MAX_PATH+7+12+1];
337 # define mystrlen(a) wcslen (a)
338   wchar_t *name, *p;
339 #else
340   char buffer[MAX_PATH+7+12+1];
341 # define mystrlen(a) strlen (a)
342   char *name, *p;
343 #endif
344   HANDLE file;
345   int pid = GetCurrentProcessId ();
346   unsigned int value;
347   int i;
348   SECURITY_ATTRIBUTES sec_attr;
349
350   memset (&sec_attr, 0, sizeof sec_attr );
351   sec_attr.nLength = sizeof sec_attr;
352   sec_attr.bInheritHandle = TRUE;
353
354   n = GetTempPath (MAX_PATH+1, buffer);
355   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
356     {
357       gpg_err_set_errno (ENOENT);
358       return NULL;
359     }
360   p = buffer + mystrlen (buffer);
361 #ifdef HAVE_W32CE_SYSTEM
362   wcscpy (p, L"_gnupg");
363   p += 7;
364 #else
365   p = stpcpy (p, "_gnupg");
366 #endif
367   /* We try to create the directory but don't care about an error as
368      it may already exist and the CreateFile would throw an error
369      anyway.  */
370   CreateDirectory (buffer, NULL);
371   *p++ = '\\';
372   name = p;
373   for (attempts=0; attempts < 10; attempts++)
374     {
375       p = name;
376       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
377       for (i=0; i < 8; i++)
378         {
379           *p++ = tohex (((value >> 28) & 0x0f));
380           value <<= 4;
381         }
382 #ifdef HAVE_W32CE_SYSTEM
383       wcscpy (p, L".tmp");
384 #else
385       strcpy (p, ".tmp");
386 #endif
387       file = CreateFile (buffer,
388                          GENERIC_READ | GENERIC_WRITE,
389                          0,
390                          &sec_attr,
391                          CREATE_NEW,
392                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
393                          NULL);
394       if (file != INVALID_HANDLE_VALUE)
395         {
396           FILE *fp;
397 #ifdef HAVE_W32CE_SYSTEM
398           int fd = (int)file;
399           fp = _wfdopen (fd, L"w+b");
400 #else
401           int fd = _open_osfhandle ((long)file, 0);
402           if (fd == -1)
403             {
404               CloseHandle (file);
405               return NULL;
406             }
407           fp = fdopen (fd, "w+b");
408 #endif
409           if (!fp)
410             {
411               int save = errno;
412               close (fd);
413               gpg_err_set_errno (save);
414               return NULL;
415             }
416           return fp;
417         }
418       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
419     }
420   gpg_err_set_errno (ENOENT);
421   return NULL;
422 #undef mystrlen
423 #else /*!HAVE_W32_SYSTEM*/
424   return tmpfile ();
425 #endif /*!HAVE_W32_SYSTEM*/
426 }
427
428
429 /* Make sure that the standard file descriptors are opened. Obviously
430    some folks close them before an exec and the next file we open will
431    get one of them assigned and thus any output (i.e. diagnostics) end
432    up in that file (e.g. the trustdb).  Not actually a gpg problem as
433    this will hapen with almost all utilities when called in a wrong
434    way.  However we try to minimize the damage here and raise
435    awareness of the problem.
436
437    Must be called before we open any files! */
438 void
439 gnupg_reopen_std (const char *pgmname)
440 {  
441 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
442   struct stat statbuf;
443   int did_stdin = 0;
444   int did_stdout = 0;
445   int did_stderr = 0;
446   FILE *complain;
447
448   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
449     {
450       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
451         did_stdin = 1;
452       else
453         did_stdin = 2;
454     }
455   
456   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
457     {
458       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
459         did_stdout = 1;
460       else
461         did_stdout = 2;
462     }
463
464   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
465     {
466       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
467         did_stderr = 1;
468       else
469         did_stderr = 2;
470     }
471
472   /* It's hard to log this sort of thing since the filehandle we would
473      complain to may be closed... */
474   if (!did_stderr)
475     complain = stderr;
476   else if (!did_stdout)
477     complain = stdout;
478   else
479     complain = NULL;
480
481   if (complain)
482     {
483       if (did_stdin == 1)
484         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
485       if (did_stdout == 1)
486         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
487       if (did_stderr == 1)
488         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
489
490       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
491         fprintf(complain,"%s: fatal: unable to reopen standard input,"
492                 " output, or error\n", pgmname);
493     }
494
495   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
496     exit (3);
497 #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
498   (void)pgmname;
499 #endif
500 }
501
502
503 /* Hack required for Windows.  */
504 void 
505 gnupg_allow_set_foregound_window (pid_t pid)
506 {
507   if (!pid)
508     log_info ("%s called with invalid pid %lu\n",
509               "gnupg_allow_set_foregound_window", (unsigned long)pid);
510 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
511   else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
512     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
513                (unsigned long)pid, w32_strerror (-1));
514 #endif
515 }
516
517 int
518 gnupg_remove (const char *fname)
519 {
520 #ifdef HAVE_W32CE_SYSTEM
521   int rc;
522   wchar_t *wfname;
523
524   wfname = utf8_to_wchar (fname);
525   if (!wfname)
526     rc = 0;
527   else
528     {
529       rc = DeleteFile (wfname);
530       xfree (wfname);
531     }
532   if (!rc)
533     return -1; /* ERRNO is automagically provided by gpg-error.h.  */
534   return 0;
535 #else
536   return remove (fname);
537 #endif
538 }
539
540
541 /* A wrapper around mkdir which takes a string for the mode argument.
542    This makes it easier to handle the mode argument which is not
543    defined on all systems.  The format of the modestring is
544
545       "-rwxrwxrwx"
546       
547    '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
548    write allowed, execution allowed with the first group for the user,
549    the second for the group and the third for all others.  If the
550    string is shorter than above the missing mode characters are meant
551    to be not set.  */
552 int
553 gnupg_mkdir (const char *name, const char *modestr)
554 {
555 #ifdef HAVE_W32CE_SYSTEM
556   wchar_t *wname;
557   (void)modestr;
558   
559   wname = utf8_to_wchar (name);
560   if (!wname)
561     return -1;
562   if (!CreateDirectoryW (wname, NULL))
563     {
564       xfree (wname);
565       return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
566     }
567   xfree (wname);
568   return 0;
569 #elif MKDIR_TAKES_ONE_ARG
570   (void)modestr;
571   /* Note: In the case of W32 we better use CreateDirectory and try to
572      set appropriate permissions.  However using mkdir is easier
573      because this sets ERRNO.  */
574   return mkdir (name);
575 #else
576   mode_t mode = 0;
577
578   if (modestr && *modestr)
579     {
580       modestr++;
581       if (*modestr && *modestr++ == 'r')
582         mode |= S_IRUSR;
583       if (*modestr && *modestr++ == 'w')
584         mode |= S_IWUSR;
585       if (*modestr && *modestr++ == 'x')
586         mode |= S_IXUSR;
587       if (*modestr && *modestr++ == 'r')
588         mode |= S_IRGRP;
589       if (*modestr && *modestr++ == 'w')
590         mode |= S_IWGRP;
591       if (*modestr && *modestr++ == 'x')
592         mode |= S_IXGRP;
593       if (*modestr && *modestr++ == 'r')
594         mode |= S_IROTH;
595       if (*modestr && *modestr++ == 'w')
596         mode |= S_IWOTH;
597       if (*modestr && *modestr++ == 'x')
598         mode |= S_IXOTH;
599     }
600   return mkdir (name, mode);
601 #endif
602 }
603
604
605 int
606 gnupg_setenv (const char *name, const char *value, int overwrite)
607 {
608 #ifdef HAVE_W32CE_SYSTEM
609   (void)name;
610   (void)value;
611   (void)overwrite;
612   return 0;
613 #else
614   return setenv (name, value, overwrite);
615 #endif
616 }
617
618 int 
619 gnupg_unsetenv (const char *name)
620 {
621 #ifdef HAVE_W32CE_SYSTEM
622   (void)name;
623   return 0;
624 #else
625 # ifdef HAVE_UNSETENV
626   return unsetenv (name);
627 # else
628   return putenv (name);
629 # endif
630 #endif
631 }
632
633 #ifdef HAVE_W32CE_SYSTEM
634 /* There is a isatty function declaration in cegcc but it does not
635    make sense, thus we redefine it.  */
636 int 
637 _gnupg_isatty (int fd)
638 {
639   (void)fd;
640   return 0;
641 }
642 #endif
643
644
645 #ifdef HAVE_W32CE_SYSTEM
646 /* Replacement for getenv which takes care of the our use of getenv.
647    The code is not thread safe but we expect it to work in all cases
648    because it is called for the first time early enough.  */
649 char *
650 _gnupg_getenv (const char *name)
651 {
652   static int initialized;
653   static char *assuan_debug;
654   
655   if (!initialized)
656     {
657       assuan_debug = read_w32_registry_string (NULL, 
658                                                "\\Software\\GNU\\libassuan",
659                                                "debug");
660       initialized = 1;
661     }
662
663   if (!strcmp (name, "ASSUAN_DEBUG"))
664     return assuan_debug;
665   else
666     return NULL;
667 }
668
669 #endif /*HAVE_W32CE_SYSTEM*/
670