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