tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

prenv.c (4475B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include <string.h>
      7 #include <stdlib.h>
      8 #include "primpl.h"
      9 #include "prmem.h"
     10 
     11 #if defined(XP_UNIX)
     12 #  include <unistd.h>
     13 #  if defined(DARWIN)
     14 #    if defined(HAVE_CRT_EXTERNS_H)
     15 #      include <crt_externs.h>
     16 #    endif /* HAVE_CRT_EXTERNS_H */
     17 #  else    /* DARWIN */
     18 PR_IMPORT_DATA(char**) environ;
     19 #  endif   /* DARWIN */
     20 #endif     /* XP_UNIX */
     21 
     22 #if !defined(HAVE_SECURE_GETENV) && defined(HAVE___SECURE_GETENV)
     23 #  define secure_getenv __secure_getenv
     24 #  define HAVE_SECURE_GETENV 1
     25 #endif
     26 
     27 /* Lock used to lock the environment */
     28 #if defined(_PR_NO_PREEMPT)
     29 #  define _PR_NEW_LOCK_ENV()
     30 #  define _PR_DELETE_LOCK_ENV()
     31 #  define _PR_LOCK_ENV()
     32 #  define _PR_UNLOCK_ENV()
     33 #elif defined(_PR_LOCAL_THREADS_ONLY)
     34 extern _PRCPU* _pr_primordialCPU;
     35 static PRIntn _is;
     36 #  define _PR_NEW_LOCK_ENV()
     37 #  define _PR_DELETE_LOCK_ENV()
     38 #  define _PR_LOCK_ENV() \
     39    if (_pr_primordialCPU) _PR_INTSOFF(_is);
     40 #  define _PR_UNLOCK_ENV() \
     41    if (_pr_primordialCPU) _PR_INTSON(_is);
     42 #else
     43 static PRLock* _pr_envLock = NULL;
     44 #  define _PR_NEW_LOCK_ENV() \
     45    { _pr_envLock = PR_NewLock(); }
     46 #  define _PR_DELETE_LOCK_ENV()      \
     47    {                                \
     48      if (_pr_envLock) {             \
     49        PR_DestroyLock(_pr_envLock); \
     50        _pr_envLock = NULL;          \
     51      }                              \
     52    }
     53 #  define _PR_LOCK_ENV()                     \
     54    {                                        \
     55      if (_pr_envLock) PR_Lock(_pr_envLock); \
     56    }
     57 #  define _PR_UNLOCK_ENV()                     \
     58    {                                          \
     59      if (_pr_envLock) PR_Unlock(_pr_envLock); \
     60    }
     61 #endif
     62 
     63 /************************************************************************/
     64 
     65 void _PR_InitEnv(void) { _PR_NEW_LOCK_ENV(); }
     66 
     67 void _PR_CleanupEnv(void) { _PR_DELETE_LOCK_ENV(); }
     68 
     69 PR_IMPLEMENT(char*) PR_GetEnv(const char* var) {
     70  char* ev;
     71 
     72  if (!_pr_initialized) {
     73    _PR_ImplicitInitialization();
     74  }
     75 
     76  _PR_LOCK_ENV();
     77  ev = _PR_MD_GET_ENV(var);
     78  _PR_UNLOCK_ENV();
     79  return ev;
     80 }
     81 
     82 PR_IMPLEMENT(char*) PR_GetEnvSecure(const char* var) {
     83 #ifdef HAVE_SECURE_GETENV
     84  char* ev;
     85 
     86  if (!_pr_initialized) {
     87    _PR_ImplicitInitialization();
     88  }
     89 
     90  _PR_LOCK_ENV();
     91  ev = secure_getenv(var);
     92  _PR_UNLOCK_ENV();
     93 
     94  return ev;
     95 #else
     96 #  ifdef XP_UNIX
     97  /*
     98  ** Fall back to checking uids and gids.  This won't detect any other
     99  ** privilege-granting mechanisms the platform may have.  This also
    100  ** can't detect the case where the process already called
    101  ** setuid(geteuid()) and/or setgid(getegid()).
    102  */
    103  if (getuid() != geteuid() || getgid() != getegid()) {
    104    return NULL;
    105  }
    106 #  endif /* XP_UNIX */
    107  return PR_GetEnv(var);
    108 #endif   /* HAVE_SECURE_GETENV */
    109 }
    110 
    111 PR_IMPLEMENT(PRStatus) PR_SetEnv(const char* string) {
    112  PRIntn result;
    113 
    114  if (!_pr_initialized) {
    115    _PR_ImplicitInitialization();
    116  }
    117 
    118  if (!strchr(string, '=')) {
    119    return (PR_FAILURE);
    120  }
    121 
    122  _PR_LOCK_ENV();
    123  result = _PR_MD_PUT_ENV((char*)string);
    124  _PR_UNLOCK_ENV();
    125  return result ? PR_FAILURE : PR_SUCCESS;
    126 }
    127 
    128 #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H))
    129 PR_IMPLEMENT(char**) PR_DuplicateEnvironment(void) {
    130  char **the_environ, **result, **end, **src, **dst;
    131 
    132  _PR_LOCK_ENV();
    133 #  ifdef DARWIN
    134  the_environ = *(_NSGetEnviron());
    135 #  else
    136  the_environ = environ;
    137 #  endif
    138 
    139  for (end = the_environ; *end != NULL; end++) /* empty loop body */;
    140 
    141  result = (char**)PR_Malloc(sizeof(char*) * (end - the_environ + 1));
    142  if (result != NULL) {
    143    for (src = the_environ, dst = result; src != end; src++, dst++) {
    144      size_t len;
    145 
    146      len = strlen(*src) + 1;
    147      *dst = PR_Malloc(len);
    148      if (*dst == NULL) {
    149        /* Allocation failed.  Must clean up the half-copied env. */
    150        char** to_delete;
    151 
    152        for (to_delete = result; to_delete != dst; to_delete++) {
    153          PR_Free(*to_delete);
    154        }
    155        PR_Free(result);
    156        result = NULL;
    157        goto out;
    158      }
    159      memcpy(*dst, *src, len);
    160    }
    161    *dst = NULL;
    162  }
    163 out:
    164  _PR_UNLOCK_ENV();
    165  return result;
    166 }
    167 #else
    168 /* This platform doesn't support raw access to the environ block. */
    169 PR_IMPLEMENT(char**) PR_DuplicateEnvironment(void) { return NULL; }
    170 #endif