LCOV - code coverage report
Current view: top level - common - sysutils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 95 147 64.6 %
Date: 2016-09-12 12:29:17 Functions: 16 19 84.2 %

          Line data    Source code
       1             : /* sysutils.c -  system helpers
       2             :  * Copyright (C) 1991-2001, 2003-2004,
       3             :  *               2006-2008  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013-2014 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 <stdint.h>
      42             : #include <string.h>
      43             : #include <unistd.h>
      44             : #include <errno.h>
      45             : #ifdef HAVE_STAT
      46             : # include <sys/stat.h>
      47             : #endif
      48             : #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
      49             : # include <asm/sysinfo.h>
      50             : # include <asm/unistd.h>
      51             : #endif
      52             : #ifdef HAVE_SETRLIMIT
      53             : # include <time.h>
      54             : # include <sys/time.h>
      55             : # include <sys/resource.h>
      56             : #endif
      57             : #ifdef HAVE_W32_SYSTEM
      58             : # if WINVER < 0x0500
      59             : #   define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
      60             : # endif
      61             : # ifdef HAVE_WINSOCK2_H
      62             : #  include <winsock2.h>
      63             : # endif
      64             : # include <windows.h>
      65             : #endif
      66             : #ifdef HAVE_NPTH
      67             : # include <npth.h>
      68             : #endif
      69             : #include <fcntl.h>
      70             : 
      71             : #include <assuan.h>
      72             : 
      73             : #include "util.h"
      74             : #include "i18n.h"
      75             : 
      76             : #include "sysutils.h"
      77             : 
      78             : #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
      79             : 
      80             : 
      81             : #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
      82             : #warning using trap_unaligned
      83             : static int
      84             : setsysinfo(unsigned long op, void *buffer, unsigned long size,
      85             :                      int *start, void *arg, unsigned long flag)
      86             : {
      87             :     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
      88             : }
      89             : 
      90             : void
      91             : trap_unaligned(void)
      92             : {
      93             :     unsigned int buf[2];
      94             : 
      95             :     buf[0] = SSIN_UACPROC;
      96             :     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
      97             :     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
      98             : }
      99             : #else
     100             : void
     101        1827 : trap_unaligned(void)
     102             : {  /* dummy */
     103        1827 : }
     104             : #endif
     105             : 
     106             : 
     107             : int
     108        1878 : disable_core_dumps (void)
     109             : {
     110             : #ifdef HAVE_DOSISH_SYSTEM
     111             :     return 0;
     112             : #else
     113             : # ifdef HAVE_SETRLIMIT
     114             :     struct rlimit limit;
     115             : 
     116             :     /* We only set the current limit unless we were not able to
     117             :        retrieve the old value. */
     118        1878 :     if (getrlimit (RLIMIT_CORE, &limit))
     119           0 :       limit.rlim_max = 0;
     120        1878 :     limit.rlim_cur = 0;
     121        1878 :     if( !setrlimit (RLIMIT_CORE, &limit) )
     122        1878 :         return 0;
     123           0 :     if( errno != EINVAL && errno != ENOSYS )
     124           0 :         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
     125             : #endif
     126           0 :     return 1;
     127             : #endif
     128             : }
     129             : 
     130             : int
     131           0 : enable_core_dumps (void)
     132             : {
     133             : #ifdef HAVE_DOSISH_SYSTEM
     134             :     return 0;
     135             : #else
     136             : # ifdef HAVE_SETRLIMIT
     137             :     struct rlimit limit;
     138             : 
     139           0 :     if (getrlimit (RLIMIT_CORE, &limit))
     140           0 :       return 1;
     141           0 :     limit.rlim_cur = limit.rlim_max;
     142           0 :     setrlimit (RLIMIT_CORE, &limit);
     143           0 :     return 1; /* We always return true because this function is
     144             :                  merely a debugging aid. */
     145             : # endif
     146             :     return 1;
     147             : #endif
     148             : }
     149             : 
     150             : 
     151             : 
     152             : /* Return a string which is used as a kind of process ID.  */
     153             : const byte *
     154          34 : get_session_marker (size_t *rlen)
     155             : {
     156             :   static byte marker[SIZEOF_UNSIGNED_LONG*2];
     157             :   static int initialized;
     158             : 
     159          34 :   if (!initialized)
     160             :     {
     161          16 :       gcry_create_nonce (marker, sizeof marker);
     162          16 :       initialized = 1;
     163             :     }
     164          34 :   *rlen = sizeof (marker);
     165          34 :   return marker;
     166             : }
     167             : 
     168             : /* Return a random number in an unsigned int. */
     169             : unsigned int
     170           0 : get_uint_nonce (void)
     171             : {
     172             :   unsigned int value;
     173             : 
     174           0 :   gcry_create_nonce (&value, sizeof value);
     175           0 :   return value;
     176             : }
     177             : 
     178             : 
     179             : 
     180             : #if 0 /* not yet needed - Note that this will require inclusion of
     181             :          cmacros.am in Makefile.am */
     182             : int
     183             : check_permissions(const char *path,int extension,int checkonly)
     184             : {
     185             : #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
     186             :   char *tmppath;
     187             :   struct stat statbuf;
     188             :   int ret=1;
     189             :   int isdir=0;
     190             : 
     191             :   if(opt.no_perm_warn)
     192             :     return 0;
     193             : 
     194             :   if(extension && path[0]!=DIRSEP_C)
     195             :     {
     196             :       if(strchr(path,DIRSEP_C))
     197             :         tmppath=make_filename(path,NULL);
     198             :       else
     199             :         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
     200             :     }
     201             :   else
     202             :     tmppath=m_strdup(path);
     203             : 
     204             :   /* It's okay if the file doesn't exist */
     205             :   if(stat(tmppath,&statbuf)!=0)
     206             :     {
     207             :       ret=0;
     208             :       goto end;
     209             :     }
     210             : 
     211             :   isdir=S_ISDIR(statbuf.st_mode);
     212             : 
     213             :   /* Per-user files must be owned by the user.  Extensions must be
     214             :      owned by the user or root. */
     215             :   if((!extension && statbuf.st_uid != getuid()) ||
     216             :      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
     217             :     {
     218             :       if(!checkonly)
     219             :         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
     220             :                  isdir?"directory":extension?"extension":"file",path);
     221             :       goto end;
     222             :     }
     223             : 
     224             :   /* This works for both directories and files - basically, we don't
     225             :      care what the owner permissions are, so long as the group and
     226             :      other permissions are 0 for per-user files, and non-writable for
     227             :      extensions. */
     228             :   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
     229             :      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
     230             :     {
     231             :       char *dir;
     232             : 
     233             :       /* However, if the directory the directory/file is in is owned
     234             :          by the user and is 700, then this is not a problem.
     235             :          Theoretically, we could walk this test up to the root
     236             :          directory /, but for the sake of sanity, I'm stopping at one
     237             :          level down. */
     238             : 
     239             :       dir= make_dirname (tmppath);
     240             :       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
     241             :          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
     242             :         {
     243             :           xfree (dir);
     244             :           ret=0;
     245             :           goto end;
     246             :         }
     247             : 
     248             :       m_free(dir);
     249             : 
     250             :       if(!checkonly)
     251             :         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
     252             :                  isdir?"directory":extension?"extension":"file",path);
     253             :       goto end;
     254             :     }
     255             : 
     256             :   ret=0;
     257             : 
     258             :  end:
     259             :   m_free(tmppath);
     260             : 
     261             :   return ret;
     262             : 
     263             : #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
     264             : 
     265             :   return 0;
     266             : }
     267             : #endif
     268             : 
     269             : 
     270             : /* Wrapper around the usual sleep function.  This one won't wake up
     271             :    before the sleep time has really elapsed.  When build with Pth it
     272             :    merely calls pth_sleep and thus suspends only the current
     273             :    thread. */
     274             : void
     275          48 : gnupg_sleep (unsigned int seconds)
     276             : {
     277             : #ifdef USE_NPTH
     278           0 :   npth_sleep (seconds);
     279             : #else
     280             :   /* Fixme:  make sure that a sleep won't wake up to early.  */
     281             : # ifdef HAVE_W32_SYSTEM
     282             :   Sleep (seconds*1000);
     283             : # else
     284          48 :   sleep (seconds);
     285             : # endif
     286             : #endif
     287          48 : }
     288             : 
     289             : 
     290             : /* This function is a NOP for POSIX systems but required under Windows
     291             :    as the file handles as returned by OS calls (like CreateFile) are
     292             :    different from the libc file descriptors (like open). This function
     293             :    translates system file handles to libc file handles.  FOR_WRITE
     294             :    gives the direction of the handle.  */
     295             : int
     296           0 : translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
     297             : {
     298             : #if defined(HAVE_W32CE_SYSTEM)
     299             :   (void)for_write;
     300             :   return (int) fd;
     301             : #elif defined(HAVE_W32_SYSTEM)
     302             :   int x;
     303             : 
     304             :   if (fd == GNUPG_INVALID_FD)
     305             :     return -1;
     306             : 
     307             :   /* Note that _open_osfhandle is currently defined to take and return
     308             :      a long.  */
     309             :   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
     310             :   if (x == -1)
     311             :     log_error ("failed to translate osfhandle %p\n", (void *) fd);
     312             :   return x;
     313             : #else /*!HAVE_W32_SYSTEM */
     314             :   (void)for_write;
     315           0 :   return fd;
     316             : #endif
     317             : }
     318             : 
     319             : /* This is the same as translate_sys2libc_fd but takes an integer
     320             :    which is assumed to be such an system handle.  On WindowsCE the
     321             :    passed FD is a rendezvous ID and the function finishes the pipe
     322             :    creation. */
     323             : int
     324         523 : translate_sys2libc_fd_int (int fd, int for_write)
     325             : {
     326             : #if HAVE_W32CE_SYSTEM
     327             :   fd = (int) _assuan_w32ce_finish_pipe (fd, for_write);
     328             :   return translate_sys2libc_fd ((void*)fd, for_write);
     329             : #elif HAVE_W32_SYSTEM
     330             :   if (fd <= 2)
     331             :     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
     332             : 
     333             :   return translate_sys2libc_fd ((void*)fd, for_write);
     334             : #else
     335             :   (void)for_write;
     336         523 :   return fd;
     337             : #endif
     338             : }
     339             : 
     340             : 
     341             : 
     342             : /* Replacement for tmpfile().  This is required because the tmpfile
     343             :    function of Windows' runtime library is broken, insecure, ignores
     344             :    TMPDIR and so on.  In addition we create a file with an inheritable
     345             :    handle.  */
     346             : FILE *
     347          10 : gnupg_tmpfile (void)
     348             : {
     349             : #ifdef HAVE_W32_SYSTEM
     350             :   int attempts, n;
     351             : #ifdef HAVE_W32CE_SYSTEM
     352             :   wchar_t buffer[MAX_PATH+7+12+1];
     353             : # define mystrlen(a) wcslen (a)
     354             :   wchar_t *name, *p;
     355             : #else
     356             :   char buffer[MAX_PATH+7+12+1];
     357             : # define mystrlen(a) strlen (a)
     358             :   char *name, *p;
     359             : #endif
     360             :   HANDLE file;
     361             :   int pid = GetCurrentProcessId ();
     362             :   unsigned int value;
     363             :   int i;
     364             :   SECURITY_ATTRIBUTES sec_attr;
     365             : 
     366             :   memset (&sec_attr, 0, sizeof sec_attr );
     367             :   sec_attr.nLength = sizeof sec_attr;
     368             :   sec_attr.bInheritHandle = TRUE;
     369             : 
     370             :   n = GetTempPath (MAX_PATH+1, buffer);
     371             :   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
     372             :     {
     373             :       gpg_err_set_errno (ENOENT);
     374             :       return NULL;
     375             :     }
     376             :   p = buffer + mystrlen (buffer);
     377             : #ifdef HAVE_W32CE_SYSTEM
     378             :   wcscpy (p, L"_gnupg");
     379             :   p += 7;
     380             : #else
     381             :   p = stpcpy (p, "_gnupg");
     382             : #endif
     383             :   /* We try to create the directory but don't care about an error as
     384             :      it may already exist and the CreateFile would throw an error
     385             :      anyway.  */
     386             :   CreateDirectory (buffer, NULL);
     387             :   *p++ = '\\';
     388             :   name = p;
     389             :   for (attempts=0; attempts < 10; attempts++)
     390             :     {
     391             :       p = name;
     392             :       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
     393             :       for (i=0; i < 8; i++)
     394             :         {
     395             :           *p++ = tohex (((value >> 28) & 0x0f));
     396             :           value <<= 4;
     397             :         }
     398             : #ifdef HAVE_W32CE_SYSTEM
     399             :       wcscpy (p, L".tmp");
     400             : #else
     401             :       strcpy (p, ".tmp");
     402             : #endif
     403             :       file = CreateFile (buffer,
     404             :                          GENERIC_READ | GENERIC_WRITE,
     405             :                          0,
     406             :                          &sec_attr,
     407             :                          CREATE_NEW,
     408             :                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
     409             :                          NULL);
     410             :       if (file != INVALID_HANDLE_VALUE)
     411             :         {
     412             :           FILE *fp;
     413             : #ifdef HAVE_W32CE_SYSTEM
     414             :           int fd = (int)file;
     415             :           fp = _wfdopen (fd, L"w+b");
     416             : #else
     417             :           int fd = _open_osfhandle ((long)file, 0);
     418             :           if (fd == -1)
     419             :             {
     420             :               CloseHandle (file);
     421             :               return NULL;
     422             :             }
     423             :           fp = fdopen (fd, "w+b");
     424             : #endif
     425             :           if (!fp)
     426             :             {
     427             :               int save = errno;
     428             :               close (fd);
     429             :               gpg_err_set_errno (save);
     430             :               return NULL;
     431             :             }
     432             :           return fp;
     433             :         }
     434             :       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
     435             :     }
     436             :   gpg_err_set_errno (ENOENT);
     437             :   return NULL;
     438             : #undef mystrlen
     439             : #else /*!HAVE_W32_SYSTEM*/
     440          10 :   return tmpfile ();
     441             : #endif /*!HAVE_W32_SYSTEM*/
     442             : }
     443             : 
     444             : 
     445             : /* Make sure that the standard file descriptors are opened. Obviously
     446             :    some folks close them before an exec and the next file we open will
     447             :    get one of them assigned and thus any output (i.e. diagnostics) end
     448             :    up in that file (e.g. the trustdb).  Not actually a gpg problem as
     449             :    this will happen with almost all utilities when called in a wrong
     450             :    way.  However we try to minimize the damage here and raise
     451             :    awareness of the problem.
     452             : 
     453             :    Must be called before we open any files! */
     454             : void
     455        1906 : gnupg_reopen_std (const char *pgmname)
     456             : {
     457             : #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
     458             :   struct stat statbuf;
     459        1906 :   int did_stdin = 0;
     460        1906 :   int did_stdout = 0;
     461        1906 :   int did_stderr = 0;
     462             :   FILE *complain;
     463             : 
     464        1906 :   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
     465             :     {
     466           0 :       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
     467           0 :         did_stdin = 1;
     468             :       else
     469           0 :         did_stdin = 2;
     470             :     }
     471             : 
     472        1906 :   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
     473             :     {
     474           0 :       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
     475           0 :         did_stdout = 1;
     476             :       else
     477           0 :         did_stdout = 2;
     478             :     }
     479             : 
     480        1906 :   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
     481             :     {
     482           0 :       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
     483           0 :         did_stderr = 1;
     484             :       else
     485           0 :         did_stderr = 2;
     486             :     }
     487             : 
     488             :   /* It's hard to log this sort of thing since the filehandle we would
     489             :      complain to may be closed... */
     490        1906 :   if (!did_stderr)
     491        1906 :     complain = stderr;
     492           0 :   else if (!did_stdout)
     493           0 :     complain = stdout;
     494             :   else
     495           0 :     complain = NULL;
     496             : 
     497        1906 :   if (complain)
     498             :     {
     499        1906 :       if (did_stdin == 1)
     500           0 :         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
     501        1906 :       if (did_stdout == 1)
     502           0 :         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
     503        1906 :       if (did_stderr == 1)
     504           0 :         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
     505             : 
     506        1906 :       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
     507           0 :         fprintf(complain,"%s: fatal: unable to reopen standard input,"
     508             :                 " output, or error\n", pgmname);
     509             :     }
     510             : 
     511        1906 :   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
     512           0 :     exit (3);
     513             : #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
     514             :   (void)pgmname;
     515             : #endif
     516        1906 : }
     517             : 
     518             : 
     519             : /* Hack required for Windows.  */
     520             : void
     521           1 : gnupg_allow_set_foregound_window (pid_t pid)
     522             : {
     523           1 :   if (!pid)
     524           0 :     log_info ("%s called with invalid pid %lu\n",
     525             :               "gnupg_allow_set_foregound_window", (unsigned long)pid);
     526             : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
     527             :   else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
     528             :     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
     529             :                (unsigned long)pid, w32_strerror (-1));
     530             : #endif
     531           1 : }
     532             : 
     533             : int
     534          89 : gnupg_remove (const char *fname)
     535             : {
     536             : #ifdef HAVE_W32CE_SYSTEM
     537             :   int rc;
     538             :   wchar_t *wfname;
     539             : 
     540             :   wfname = utf8_to_wchar (fname);
     541             :   if (!wfname)
     542             :     rc = 0;
     543             :   else
     544             :     {
     545             :       rc = DeleteFile (wfname);
     546             :       xfree (wfname);
     547             :     }
     548             :   if (!rc)
     549             :     return -1; /* ERRNO is automagically provided by gpg-error.h.  */
     550             :   return 0;
     551             : #else
     552          89 :   return remove (fname);
     553             : #endif
     554             : }
     555             : 
     556             : 
     557             : #ifndef HAVE_W32_SYSTEM
     558             : static mode_t
     559        1395 : modestr_to_mode (const char *modestr)
     560             : {
     561        1395 :   mode_t mode = 0;
     562             : 
     563        1395 :   if (modestr && *modestr)
     564             :     {
     565        1394 :       modestr++;
     566        1394 :       if (*modestr && *modestr++ == 'r')
     567        1394 :         mode |= S_IRUSR;
     568        1394 :       if (*modestr && *modestr++ == 'w')
     569        1394 :         mode |= S_IWUSR;
     570        1394 :       if (*modestr && *modestr++ == 'x')
     571        1394 :         mode |= S_IXUSR;
     572        1394 :       if (*modestr && *modestr++ == 'r')
     573           0 :         mode |= S_IRGRP;
     574        1394 :       if (*modestr && *modestr++ == 'w')
     575           0 :         mode |= S_IWGRP;
     576        1394 :       if (*modestr && *modestr++ == 'x')
     577           0 :         mode |= S_IXGRP;
     578        1394 :       if (*modestr && *modestr++ == 'r')
     579           0 :         mode |= S_IROTH;
     580        1394 :       if (*modestr && *modestr++ == 'w')
     581           0 :         mode |= S_IWOTH;
     582        1394 :       if (*modestr && *modestr++ == 'x')
     583           0 :         mode |= S_IXOTH;
     584             :     }
     585             : 
     586        1395 :   return mode;
     587             : }
     588             : #endif
     589             : 
     590             : 
     591             : /* A wrapper around mkdir which takes a string for the mode argument.
     592             :    This makes it easier to handle the mode argument which is not
     593             :    defined on all systems.  The format of the modestring is
     594             : 
     595             :       "-rwxrwxrwx"
     596             : 
     597             :    '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
     598             :    write allowed, execution allowed with the first group for the user,
     599             :    the second for the group and the third for all others.  If the
     600             :    string is shorter than above the missing mode characters are meant
     601             :    to be not set.  */
     602             : int
     603        1255 : gnupg_mkdir (const char *name, const char *modestr)
     604             : {
     605             : #ifdef HAVE_W32CE_SYSTEM
     606             :   wchar_t *wname;
     607             :   (void)modestr;
     608             : 
     609             :   wname = utf8_to_wchar (name);
     610             :   if (!wname)
     611             :     return -1;
     612             :   if (!CreateDirectoryW (wname, NULL))
     613             :     {
     614             :       xfree (wname);
     615             :       return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
     616             :     }
     617             :   xfree (wname);
     618             :   return 0;
     619             : #elif MKDIR_TAKES_ONE_ARG
     620             :   (void)modestr;
     621             :   /* Note: In the case of W32 we better use CreateDirectory and try to
     622             :      set appropriate permissions.  However using mkdir is easier
     623             :      because this sets ERRNO.  */
     624             :   return mkdir (name);
     625             : #else
     626        1255 :   return mkdir (name, modestr_to_mode (modestr));
     627             : #endif
     628             : }
     629             : 
     630             : 
     631             : /* A wrapper around chmod which takes a string for the mode argument.
     632             :    This makes it easier to handle the mode argument which is not
     633             :    defined on all systems.  The format of the modestring is the same
     634             :    as for gnupg_mkdir.  */
     635             : int
     636         140 : gnupg_chmod (const char *name, const char *modestr)
     637             : {
     638             : #ifdef HAVE_W32_SYSTEM
     639             :   (void)name;
     640             :   (void)modestr;
     641             :   return 0;
     642             : #else
     643         140 :   return chmod (name, modestr_to_mode (modestr));
     644             : #endif
     645             : }
     646             : 
     647             : 
     648             : /* Our version of mkdtemp.  The API is identical to POSIX.1-2008
     649             :    version.  We do not use a system provided mkdtemp because we have a
     650             :    good RNG instantly available and this way we don't have diverging
     651             :    versions.  */
     652             : char *
     653        1206 : gnupg_mkdtemp (char *tmpl)
     654             : {
     655             :   /* A lower bound on the number of temporary files to attempt to
     656             :      generate.  The maximum total number of temporary file names that
     657             :      can exist for a given template is 62**6 (5*36**3 for Windows).
     658             :      It should never be necessary to try all these combinations.
     659             :      Instead if a reasonable number of names is tried (we define
     660             :      reasonable as 62**3 or 5*36**3) fail to give the system
     661             :      administrator the chance to remove the problems.  */
     662             : #ifdef HAVE_W32_SYSTEM
     663             :   static const char letters[] =
     664             :     "abcdefghijklmnopqrstuvwxyz0123456789";
     665             : # define NUMBER_OF_LETTERS 36
     666             : # define ATTEMPTS_MIN (5 * 36 * 36 * 36)
     667             : #else
     668             :   static const char letters[] =
     669             :     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     670             : # define NUMBER_OF_LETTERS 62
     671             : # define ATTEMPTS_MIN (62 * 62 * 62)
     672             : #endif
     673             :   int len;
     674             :   char *XXXXXX;
     675             :   uint64_t value;
     676             :   unsigned int count;
     677        1206 :   int save_errno = errno;
     678             :   /* The number of times to attempt to generate a temporary file.  To
     679             :      conform to POSIX, this must be no smaller than TMP_MAX.  */
     680             : #if ATTEMPTS_MIN < TMP_MAX
     681             :   unsigned int attempts = TMP_MAX;
     682             : #else
     683        1206 :   unsigned int attempts = ATTEMPTS_MIN;
     684             : #endif
     685             : 
     686        1206 :   len = strlen (tmpl);
     687        1206 :   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
     688             :     {
     689           0 :       gpg_err_set_errno (EINVAL);
     690           0 :       return NULL;
     691             :     }
     692             : 
     693             :   /* This is where the Xs start.  */
     694        1206 :   XXXXXX = &tmpl[len - 6];
     695             : 
     696             :   /* Get a random start value.  */
     697        1206 :   gcry_create_nonce (&value, sizeof value);
     698             : 
     699             :   /* Loop until a directory was created.  */
     700        1206 :   for (count = 0; count < attempts; value += 7777, ++count)
     701             :     {
     702        1206 :       uint64_t v = value;
     703             : 
     704             :       /* Fill in the random bits.  */
     705        1206 :       XXXXXX[0] = letters[v % NUMBER_OF_LETTERS];
     706        1206 :       v /= NUMBER_OF_LETTERS;
     707        1206 :       XXXXXX[1] = letters[v % NUMBER_OF_LETTERS];
     708        1206 :       v /= NUMBER_OF_LETTERS;
     709        1206 :       XXXXXX[2] = letters[v % NUMBER_OF_LETTERS];
     710        1206 :       v /= NUMBER_OF_LETTERS;
     711        1206 :       XXXXXX[3] = letters[v % NUMBER_OF_LETTERS];
     712        1206 :       v /= NUMBER_OF_LETTERS;
     713        1206 :       XXXXXX[4] = letters[v % NUMBER_OF_LETTERS];
     714        1206 :       v /= NUMBER_OF_LETTERS;
     715        1206 :       XXXXXX[5] = letters[v % NUMBER_OF_LETTERS];
     716             : 
     717        1206 :       if (!gnupg_mkdir (tmpl, "-rwx"))
     718             :         {
     719        1206 :           gpg_err_set_errno (save_errno);
     720        1206 :           return tmpl;
     721             :         }
     722           0 :       if (errno != EEXIST)
     723           0 :         return NULL;
     724             :     }
     725             : 
     726             :   /* We got out of the loop because we ran out of combinations to try.  */
     727           0 :   gpg_err_set_errno (EEXIST);
     728           0 :   return NULL;
     729             : }
     730             : 
     731             : 
     732             : int
     733         263 : gnupg_setenv (const char *name, const char *value, int overwrite)
     734             : {
     735             : #ifdef HAVE_W32CE_SYSTEM
     736             :   (void)name;
     737             :   (void)value;
     738             :   (void)overwrite;
     739             :   return 0;
     740             : #elif defined(HAVE_W32_SYSTEM)
     741             :   if (!overwrite)
     742             :     {
     743             :       char tmpbuf[10];
     744             :       if (GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf))
     745             :         return 0; /* Exists but overwrite was not requested.  */
     746             :     }
     747             :   if (!SetEnvironmentVariable (name, value))
     748             :     {
     749             :       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
     750             :       return -1;
     751             :     }
     752             :   return 0;
     753             : #elif defined(HAVE_SETENV)
     754         263 :   return setenv (name, value, overwrite);
     755             : #else
     756             :   char *buf;
     757             : 
     758             :   (void)overwrite;
     759             :   if (!name || !value)
     760             :     {
     761             :       gpg_err_set_errno (EINVAL);
     762             :       return -1;
     763             :     }
     764             :   buf = xtrymalloc (strlen (name) + 1 + strlen (value) + 1);
     765             :   if (!buf)
     766             :     return -1;
     767             :   strcpy (stpcpy (stpcpy (buf, name), "="), value);
     768             : #if __GNUC__
     769             : # warning no setenv - using putenv but leaking memory.
     770             : #endif
     771             :   return putenv (buf);
     772             : #endif
     773             : }
     774             : 
     775             : 
     776             : int
     777          96 : gnupg_unsetenv (const char *name)
     778             : {
     779             : #ifdef HAVE_W32CE_SYSTEM
     780             :   (void)name;
     781             :   return 0;
     782             : #elif defined(HAVE_W32_SYSTEM)
     783             :   if (!SetEnvironmentVariable (name, NULL))
     784             :     {
     785             :       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
     786             :       return -1;
     787             :     }
     788             :   return 0;
     789             : #elif defined(HAVE_UNSETENV)
     790          96 :   return unsetenv (name);
     791             : #else
     792             :   char *buf;
     793             : 
     794             :   if (!name)
     795             :     {
     796             :       gpg_err_set_errno (EINVAL);
     797             :       return -1;
     798             :     }
     799             :   buf = xtrystrdup (name);
     800             :   if (!buf)
     801             :     return -1;
     802             : #if __GNUC__
     803             : # warning no unsetenv - trying putenv but leaking memory.
     804             : #endif
     805             :   return putenv (buf);
     806             : #endif
     807             : }
     808             : 
     809             : 
     810             : /* Return the current working directory as a malloced string.  Return
     811             :    NULL and sets ERRNo on error.  */
     812             : char *
     813         291 : gnupg_getcwd (void)
     814             : {
     815             :   char *buffer;
     816         291 :   size_t size = 100;
     817             : 
     818             :   for (;;)
     819             :     {
     820         291 :       buffer = xtrymalloc (size+1);
     821         291 :       if (!buffer)
     822           0 :         return NULL;
     823             : #ifdef HAVE_W32CE_SYSTEM
     824             :       strcpy (buffer, "/");  /* Always "/".  */
     825             :       return buffer;
     826             : #else
     827         291 :       if (getcwd (buffer, size) == buffer)
     828         291 :         return buffer;
     829           0 :       xfree (buffer);
     830           0 :       if (errno != ERANGE)
     831           0 :         return NULL;
     832           0 :       size *= 2;
     833             : #endif
     834           0 :     }
     835             : }
     836             : 
     837             : 
     838             : 
     839             : #ifdef HAVE_W32CE_SYSTEM
     840             : /* There is a isatty function declaration in cegcc but it does not
     841             :    make sense, thus we redefine it.  */
     842             : int
     843             : _gnupg_isatty (int fd)
     844             : {
     845             :   (void)fd;
     846             :   return 0;
     847             : }
     848             : #endif
     849             : 
     850             : 
     851             : #ifdef HAVE_W32CE_SYSTEM
     852             : /* Replacement for getenv which takes care of the our use of getenv.
     853             :    The code is not thread safe but we expect it to work in all cases
     854             :    because it is called for the first time early enough.  */
     855             : char *
     856             : _gnupg_getenv (const char *name)
     857             : {
     858             :   static int initialized;
     859             :   static char *assuan_debug;
     860             : 
     861             :   if (!initialized)
     862             :     {
     863             :       assuan_debug = read_w32_registry_string (NULL,
     864             :                                                "\\Software\\GNU\\libassuan",
     865             :                                                "debug");
     866             :       initialized = 1;
     867             :     }
     868             : 
     869             :   if (!strcmp (name, "ASSUAN_DEBUG"))
     870             :     return assuan_debug;
     871             :   else
     872             :     return NULL;
     873             : }
     874             : 
     875             : #endif /*HAVE_W32CE_SYSTEM*/
     876             : 
     877             : 
     878             : #ifdef HAVE_W32_SYSTEM
     879             : /* Return the user's security identifier from the current process.  */
     880             : PSID
     881             : w32_get_user_sid (void)
     882             : {
     883             :   int okay = 0;
     884             :   HANDLE proc = NULL;
     885             :   HANDLE token = NULL;
     886             :   TOKEN_USER *user = NULL;
     887             :   PSID sid = NULL;
     888             :   DWORD tokenlen, sidlen;
     889             : 
     890             :   proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
     891             :   if (!proc)
     892             :     goto leave;
     893             : 
     894             :   if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
     895             :     goto leave;
     896             : 
     897             :   if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
     898             :       && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
     899             :     goto leave;
     900             : 
     901             :   user = xtrymalloc (tokenlen);
     902             :   if (!user)
     903             :     goto leave;
     904             : 
     905             :   if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
     906             :     goto leave;
     907             :   if (!IsValidSid (user->User.Sid))
     908             :     goto leave;
     909             :   sidlen = GetLengthSid (user->User.Sid);
     910             :   sid = xtrymalloc (sidlen);
     911             :   if (!sid)
     912             :     goto leave;
     913             :   if (!CopySid (sidlen, sid, user->User.Sid))
     914             :     goto leave;
     915             :   okay = 1;
     916             : 
     917             :  leave:
     918             :   xfree (user);
     919             :   if (token)
     920             :     CloseHandle (token);
     921             :   if (proc)
     922             :     CloseHandle (proc);
     923             : 
     924             :   if (!okay)
     925             :     {
     926             :       xfree (sid);
     927             :       sid = NULL;
     928             :     }
     929             :   return sid;
     930             : }
     931             : #endif /*HAVE_W32_SYSTEM*/

Generated by: LCOV version 1.11