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