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