LCOV - code coverage report
Current view: top level - common - sysutils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 63 143 44.1 %
Date: 2015-11-05 17:10:59 Functions: 11 17 64.7 %

          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        1331 : trap_unaligned(void)
     102             : {  /* dummy */
     103        1331 : }
     104             : #endif
     105             : 
     106             : 
     107             : int
     108        1337 : 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        1337 :     if (getrlimit (RLIMIT_CORE, &limit))
     119           0 :       limit.rlim_max = 0;
     120        1337 :     limit.rlim_cur = 0;
     121        1337 :     if( !setrlimit (RLIMIT_CORE, &limit) )
     122        1337 :         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          32 : get_session_marker (size_t *rlen)
     155             : {
     156             :   static byte marker[SIZEOF_UNSIGNED_LONG*2];
     157             :   static int initialized;
     158             : 
     159          32 :   if (!initialized)
     160             :     {
     161          14 :       gcry_create_nonce (marker, sizeof marker);
     162          14 :       initialized = 1;
     163             :     }
     164          32 :   *rlen = sizeof (marker);
     165          32 :   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 fucntion.  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           1 : 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           1 :   sleep (seconds);
     285             : # endif
     286             : #endif
     287           1 : }
     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         493 : 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         493 :   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 hapen 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        1334 : gnupg_reopen_std (const char *pgmname)
     456             : {
     457             : #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
     458             :   struct stat statbuf;
     459        1334 :   int did_stdin = 0;
     460        1334 :   int did_stdout = 0;
     461        1334 :   int did_stderr = 0;
     462             :   FILE *complain;
     463             : 
     464        1334 :   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        1334 :   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        1334 :   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        1334 :   if (!did_stderr)
     491        1334 :     complain = stderr;
     492           0 :   else if (!did_stdout)
     493           0 :     complain = stdout;
     494             :   else
     495           0 :     complain = NULL;
     496             : 
     497        1334 :   if (complain)
     498             :     {
     499        1334 :       if (did_stdin == 1)
     500           0 :         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
     501        1334 :       if (did_stdout == 1)
     502           0 :         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
     503        1334 :       if (did_stderr == 1)
     504           0 :         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
     505             : 
     506        1334 :       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        1334 :   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        1334 : }
     517             : 
     518             : 
     519             : /* Hack required for Windows.  */
     520             : void
     521           0 : gnupg_allow_set_foregound_window (pid_t pid)
     522             : {
     523           0 :   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           0 : }
     532             : 
     533             : int
     534           2 : 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           2 :   return remove (fname);
     553             : #endif
     554             : }
     555             : 
     556             : 
     557             : /* A wrapper around mkdir which takes a string for the mode argument.
     558             :    This makes it easier to handle the mode argument which is not
     559             :    defined on all systems.  The format of the modestring is
     560             : 
     561             :       "-rwxrwxrwx"
     562             : 
     563             :    '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
     564             :    write allowed, execution allowed with the first group for the user,
     565             :    the second for the group and the third for all others.  If the
     566             :    string is shorter than above the missing mode characters are meant
     567             :    to be not set.  */
     568             : int
     569           9 : gnupg_mkdir (const char *name, const char *modestr)
     570             : {
     571             : #ifdef HAVE_W32CE_SYSTEM
     572             :   wchar_t *wname;
     573             :   (void)modestr;
     574             : 
     575             :   wname = utf8_to_wchar (name);
     576             :   if (!wname)
     577             :     return -1;
     578             :   if (!CreateDirectoryW (wname, NULL))
     579             :     {
     580             :       xfree (wname);
     581             :       return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
     582             :     }
     583             :   xfree (wname);
     584             :   return 0;
     585             : #elif MKDIR_TAKES_ONE_ARG
     586             :   (void)modestr;
     587             :   /* Note: In the case of W32 we better use CreateDirectory and try to
     588             :      set appropriate permissions.  However using mkdir is easier
     589             :      because this sets ERRNO.  */
     590             :   return mkdir (name);
     591             : #else
     592           9 :   mode_t mode = 0;
     593             : 
     594           9 :   if (modestr && *modestr)
     595             :     {
     596           9 :       modestr++;
     597           9 :       if (*modestr && *modestr++ == 'r')
     598           9 :         mode |= S_IRUSR;
     599           9 :       if (*modestr && *modestr++ == 'w')
     600           9 :         mode |= S_IWUSR;
     601           9 :       if (*modestr && *modestr++ == 'x')
     602           9 :         mode |= S_IXUSR;
     603           9 :       if (*modestr && *modestr++ == 'r')
     604           0 :         mode |= S_IRGRP;
     605           9 :       if (*modestr && *modestr++ == 'w')
     606           0 :         mode |= S_IWGRP;
     607           9 :       if (*modestr && *modestr++ == 'x')
     608           0 :         mode |= S_IXGRP;
     609           9 :       if (*modestr && *modestr++ == 'r')
     610           0 :         mode |= S_IROTH;
     611           9 :       if (*modestr && *modestr++ == 'w')
     612           0 :         mode |= S_IWOTH;
     613           9 :       if (*modestr && *modestr++ == 'x')
     614           0 :         mode |= S_IXOTH;
     615             :     }
     616           9 :   return mkdir (name, mode);
     617             : #endif
     618             : }
     619             : 
     620             : 
     621             : /* Our version of mkdtemp.  The API is identical to POSIX.1-2008
     622             :    version.  We do not use a system provided mkdtemp because we have a
     623             :    good RNG instantly available and this way we don't have diverging
     624             :    versions.  */
     625             : char *
     626           0 : gnupg_mkdtemp (char *tmpl)
     627             : {
     628             :   /* A lower bound on the number of temporary files to attempt to
     629             :      generate.  The maximum total number of temporary file names that
     630             :      can exist for a given template is 62**6 (5*36**3 for Windows).
     631             :      It should never be necessary to try all these combinations.
     632             :      Instead if a reasonable number of names is tried (we define
     633             :      reasonable as 62**3 or 5*36**3) fail to give the system
     634             :      administrator the chance to remove the problems.  */
     635             : #ifdef HAVE_W32_SYSTEM
     636             :   static const char letters[] =
     637             :     "abcdefghijklmnopqrstuvwxyz0123456789";
     638             : # define NUMBER_OF_LETTERS 36
     639             : # define ATTEMPTS_MIN (5 * 36 * 36 * 36)
     640             : #else
     641             :   static const char letters[] =
     642             :     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     643             : # define NUMBER_OF_LETTERS 62
     644             : # define ATTEMPTS_MIN (62 * 62 * 62)
     645             : #endif
     646             :   int len;
     647             :   char *XXXXXX;
     648             :   uint64_t value;
     649             :   unsigned int count;
     650           0 :   int save_errno = errno;
     651             :   /* The number of times to attempt to generate a temporary file.  To
     652             :      conform to POSIX, this must be no smaller than TMP_MAX.  */
     653             : #if ATTEMPTS_MIN < TMP_MAX
     654             :   unsigned int attempts = TMP_MAX;
     655             : #else
     656           0 :   unsigned int attempts = ATTEMPTS_MIN;
     657             : #endif
     658             : 
     659           0 :   len = strlen (tmpl);
     660           0 :   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
     661             :     {
     662           0 :       gpg_err_set_errno (EINVAL);
     663           0 :       return NULL;
     664             :     }
     665             : 
     666             :   /* This is where the Xs start.  */
     667           0 :   XXXXXX = &tmpl[len - 6];
     668             : 
     669             :   /* Get a random start value.  */
     670           0 :   gcry_create_nonce (&value, sizeof value);
     671             : 
     672             :   /* Loop until a directory was created.  */
     673           0 :   for (count = 0; count < attempts; value += 7777, ++count)
     674             :     {
     675           0 :       uint64_t v = value;
     676             : 
     677             :       /* Fill in the random bits.  */
     678           0 :       XXXXXX[0] = letters[v % NUMBER_OF_LETTERS];
     679           0 :       v /= NUMBER_OF_LETTERS;
     680           0 :       XXXXXX[1] = letters[v % NUMBER_OF_LETTERS];
     681           0 :       v /= NUMBER_OF_LETTERS;
     682           0 :       XXXXXX[2] = letters[v % NUMBER_OF_LETTERS];
     683           0 :       v /= NUMBER_OF_LETTERS;
     684           0 :       XXXXXX[3] = letters[v % NUMBER_OF_LETTERS];
     685           0 :       v /= NUMBER_OF_LETTERS;
     686           0 :       XXXXXX[4] = letters[v % NUMBER_OF_LETTERS];
     687           0 :       v /= NUMBER_OF_LETTERS;
     688           0 :       XXXXXX[5] = letters[v % NUMBER_OF_LETTERS];
     689             : 
     690           0 :       if (!gnupg_mkdir (tmpl, "-rwx"))
     691             :         {
     692           0 :           gpg_err_set_errno (save_errno);
     693           0 :           return tmpl;
     694             :         }
     695           0 :       if (errno != EEXIST)
     696           0 :         return NULL;
     697             :     }
     698             : 
     699             :   /* We got out of the loop because we ran out of combinations to try.  */
     700           0 :   gpg_err_set_errno (EEXIST);
     701           0 :   return NULL;
     702             : }
     703             : 
     704             : 
     705             : int
     706           0 : gnupg_setenv (const char *name, const char *value, int overwrite)
     707             : {
     708             : #ifdef HAVE_W32CE_SYSTEM
     709             :   (void)name;
     710             :   (void)value;
     711             :   (void)overwrite;
     712             :   return 0;
     713             : #elif defined(HAVE_W32_SYSTEM)
     714             :   if (!overwrite)
     715             :     {
     716             :       char tmpbuf[10];
     717             :       if (GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf))
     718             :         return 0; /* Exists but overwrite was not requested.  */
     719             :     }
     720             :   if (!SetEnvironmentVariable (name, value))
     721             :     {
     722             :       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
     723             :       return -1;
     724             :     }
     725             :   return 0;
     726             : #elif defined(HAVE_SETENV)
     727           0 :   return setenv (name, value, overwrite);
     728             : #else
     729             :   char *buf;
     730             : 
     731             :   (void)overwrite;
     732             :   if (!name || !value)
     733             :     {
     734             :       gpg_err_set_errno (EINVAL);
     735             :       return -1;
     736             :     }
     737             :   buf = xtrymalloc (strlen (name) + 1 + strlen (value) + 1);
     738             :   if (!buf)
     739             :     return -1;
     740             :   strcpy (stpcpy (stpcpy (buf, name), "="), value);
     741             : #if __GNUC__
     742             : # warning no setenv - using putenv but leaking memory.
     743             : #endif
     744             :   return putenv (buf);
     745             : #endif
     746             : }
     747             : 
     748             : 
     749             : int
     750           2 : gnupg_unsetenv (const char *name)
     751             : {
     752             : #ifdef HAVE_W32CE_SYSTEM
     753             :   (void)name;
     754             :   return 0;
     755             : #elif defined(HAVE_W32_SYSTEM)
     756             :   if (!SetEnvironmentVariable (name, NULL))
     757             :     {
     758             :       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
     759             :       return -1;
     760             :     }
     761             :   return 0;
     762             : #elif defined(HAVE_UNSETENV)
     763           2 :   return unsetenv (name);
     764             : #else
     765             :   char *buf;
     766             : 
     767             :   if (!name)
     768             :     {
     769             :       gpg_err_set_errno (EINVAL);
     770             :       return -1;
     771             :     }
     772             :   buf = xtrystrdup (name);
     773             :   if (!buf)
     774             :     return -1;
     775             : #if __GNUC__
     776             : # warning no unsetenv - trying putenv but leaking memory.
     777             : #endif
     778             :   return putenv (buf);
     779             : #endif
     780             : }
     781             : 
     782             : 
     783             : /* Return the current working directory as a malloced string.  Return
     784             :    NULL and sets ERRNo on error.  */
     785             : char *
     786           3 : gnupg_getcwd (void)
     787             : {
     788             :   char *buffer;
     789           3 :   size_t size = 100;
     790             : 
     791             :   for (;;)
     792             :     {
     793           3 :       buffer = xtrymalloc (size+1);
     794           3 :       if (!buffer)
     795           0 :         return NULL;
     796             : #ifdef HAVE_W32CE_SYSTEM
     797             :       strcpy (buffer, "/");  /* Always "/".  */
     798             :       return buffer;
     799             : #else
     800           3 :       if (getcwd (buffer, size) == buffer)
     801           3 :         return buffer;
     802           0 :       xfree (buffer);
     803           0 :       if (errno != ERANGE)
     804           0 :         return NULL;
     805           0 :       size *= 2;
     806             : #endif
     807           0 :     }
     808             : }
     809             : 
     810             : 
     811             : 
     812             : #ifdef HAVE_W32CE_SYSTEM
     813             : /* There is a isatty function declaration in cegcc but it does not
     814             :    make sense, thus we redefine it.  */
     815             : int
     816             : _gnupg_isatty (int fd)
     817             : {
     818             :   (void)fd;
     819             :   return 0;
     820             : }
     821             : #endif
     822             : 
     823             : 
     824             : #ifdef HAVE_W32CE_SYSTEM
     825             : /* Replacement for getenv which takes care of the our use of getenv.
     826             :    The code is not thread safe but we expect it to work in all cases
     827             :    because it is called for the first time early enough.  */
     828             : char *
     829             : _gnupg_getenv (const char *name)
     830             : {
     831             :   static int initialized;
     832             :   static char *assuan_debug;
     833             : 
     834             :   if (!initialized)
     835             :     {
     836             :       assuan_debug = read_w32_registry_string (NULL,
     837             :                                                "\\Software\\GNU\\libassuan",
     838             :                                                "debug");
     839             :       initialized = 1;
     840             :     }
     841             : 
     842             :   if (!strcmp (name, "ASSUAN_DEBUG"))
     843             :     return assuan_debug;
     844             :   else
     845             :     return NULL;
     846             : }
     847             : 
     848             : #endif /*HAVE_W32CE_SYSTEM*/
     849             : 
     850             : 
     851             : #ifdef HAVE_W32_SYSTEM
     852             : /* Return the user's security identifier from the current process.  */
     853             : PSID
     854             : w32_get_user_sid (void)
     855             : {
     856             :   int okay = 0;
     857             :   HANDLE proc = NULL;
     858             :   HANDLE token = NULL;
     859             :   TOKEN_USER *user = NULL;
     860             :   PSID sid = NULL;
     861             :   DWORD tokenlen, sidlen;
     862             : 
     863             :   proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
     864             :   if (!proc)
     865             :     goto leave;
     866             : 
     867             :   if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
     868             :     goto leave;
     869             : 
     870             :   if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
     871             :       && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
     872             :     goto leave;
     873             : 
     874             :   user = xtrymalloc (tokenlen);
     875             :   if (!user)
     876             :     goto leave;
     877             : 
     878             :   if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
     879             :     goto leave;
     880             :   if (!IsValidSid (user->User.Sid))
     881             :     goto leave;
     882             :   sidlen = GetLengthSid (user->User.Sid);
     883             :   sid = xtrymalloc (sidlen);
     884             :   if (!sid)
     885             :     goto leave;
     886             :   if (!CopySid (sidlen, sid, user->User.Sid))
     887             :     goto leave;
     888             :   okay = 1;
     889             : 
     890             :  leave:
     891             :   xfree (user);
     892             :   if (token)
     893             :     CloseHandle (token);
     894             :   if (proc)
     895             :     CloseHandle (proc);
     896             : 
     897             :   if (!okay)
     898             :     {
     899             :       xfree (sid);
     900             :       sid = NULL;
     901             :     }
     902             :   return sid;
     903             : }
     904             : #endif /*HAVE_W32_SYSTEM*/

Generated by: LCOV version 1.11