tor-browser

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

env.c (10994B)


      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 /*
      7 ** File:        env.c
      8 ** Description: Testing environment variable operations
      9 **
     10 */
     11 #include "prenv.h"
     12 #include "prmem.h"
     13 #include "plgetopt.h"
     14 
     15 #include <stdio.h>
     16 #include <stdlib.h>
     17 #include <string.h>
     18 
     19 PRIntn debug = 0;
     20 PRIntn verbose = 0;
     21 PRIntn secure = 0;
     22 PRBool failedAlready = PR_FALSE;
     23 
     24 #define ENVNAME "NSPR_ENVIRONMENT_TEST_VARIABLE"
     25 #define ENVVALUE "The expected result"
     26 #define ENVBUFSIZE 256
     27 
     28 char* envBuf; /* buffer pointer. We leak memory here on purpose! */
     29 
     30 static char* NewBuffer(size_t size) {
     31  char* buf = malloc(size);
     32  if (NULL == buf) {
     33    printf("env: NewBuffer() failed\n");
     34    exit(1);
     35  }
     36  return (buf);
     37 } /* end NewBuffer() */
     38 
     39 int main(int argc, char** argv) {
     40  char* value;
     41  PRStatus rc;
     42 
     43  { /* Get command line options */
     44    PLOptStatus os;
     45    PLOptState* opt = PL_CreateOptState(argc, argv, "vds");
     46 
     47    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
     48      if (PL_OPT_BAD == os) {
     49        continue;
     50      }
     51      switch (opt->option) {
     52        case 'd': /* debug */
     53          debug = 1;
     54          break;
     55        case 'v': /* verbose */
     56          verbose = 1;
     57          break;
     58        case 's': /* secure / set[ug]id */
     59          /*
     60          ** To test PR_GetEnvSecure, make this executable (or a
     61          ** copy of it) setuid / setgid / otherwise inherently
     62          ** privileged (e.g., file capabilities) and run it
     63          ** with this flag.
     64          */
     65          secure = 1;
     66          break;
     67        default:
     68          break;
     69      }
     70    }
     71    PL_DestroyOptState(opt);
     72  } /* end block "Get command line options" */
     73 
     74 #if 0
     75    {
     76        /*
     77        ** This uses Windows native environment manipulation
     78        ** as an experiment. Note the separation of namespace!
     79        */
     80        BOOL rv;
     81        DWORD   size;
     82        rv = SetEnvironmentVariable( ENVNAME, ENVVALUE );
     83        if ( rv == 0 )  {
     84            if (debug) {
     85                printf("env: Shit! SetEnvironmentVariable() failed\n");
     86            }
     87            failedAlready = PR_TRUE;
     88        }
     89        if (verbose) {
     90            printf("env: SetEnvironmentVariable() worked\n");
     91        }
     92 
     93        size = GetEnvironmentVariable( ENVNAME, envBuf, ENVBUFSIZE );
     94        if ( size == 0 )  {
     95            if (debug) {
     96                printf("env: Shit! GetEnvironmentVariable() failed. Found: %s\n", envBuf );
     97            }
     98            failedAlready = PR_TRUE;
     99        }
    100        if (verbose) {
    101            printf("env: GetEnvironmentVariable() worked. Found: %s\n", envBuf);
    102        }
    103 
    104        value = PR_GetEnv( ENVNAME );
    105        if ( (NULL == value ) || (strcmp( value, ENVVALUE)))  {
    106            if (debug) {
    107                printf( "env: PR_GetEnv() failed retrieving WinNative. Found: %s\n", value);
    108            }
    109            failedAlready = PR_TRUE;
    110        }
    111        if (verbose) {
    112            printf("env: PR_GetEnv() worked. Found: %s\n", value);
    113        }
    114    }
    115 #endif
    116 
    117  /* set an environment variable, read it back */
    118  envBuf = NewBuffer(ENVBUFSIZE);
    119  sprintf(envBuf, ENVNAME "=" ENVVALUE);
    120  rc = PR_SetEnv(envBuf);
    121  if (PR_FAILURE == rc) {
    122    if (debug) {
    123      printf("env: PR_SetEnv() failed setting\n");
    124    }
    125    failedAlready = PR_TRUE;
    126  } else {
    127    if (verbose) {
    128      printf("env: PR_SetEnv() worked.\n");
    129    }
    130  }
    131 
    132  value = PR_GetEnv(ENVNAME);
    133  if ((NULL == value) || (strcmp(value, ENVVALUE))) {
    134    if (debug) {
    135      printf("env: PR_GetEnv() Failed after setting\n");
    136    }
    137    failedAlready = PR_TRUE;
    138  } else {
    139    if (verbose) {
    140      printf("env: PR_GetEnv() worked after setting it. Found: %s\n", value);
    141    }
    142  }
    143 
    144  if (secure) {
    145    /*
    146    ** In this case we've been run with elevated privileges, so
    147    ** test that PR_GetEnvSecure *doesn't* find that env var.
    148    */
    149    value = PR_GetEnvSecure(ENVNAME);
    150    if (NULL != value) {
    151      if (debug) {
    152        printf("env: PR_GetEnvSecure() failed; expected NULL, found \"%s\"\n",
    153               value);
    154      }
    155      failedAlready = PR_TRUE;
    156    } else {
    157      if (verbose) {
    158        printf("env: PR_GetEnvSecure() worked\n");
    159      }
    160    }
    161  } else {
    162    /*
    163    ** In this case the program is being run normally, so do the
    164    ** same check for PR_GetEnvSecure as for PR_GetEnv.
    165    */
    166    value = PR_GetEnvSecure(ENVNAME);
    167    if ((NULL == value) || (strcmp(value, ENVVALUE))) {
    168      if (debug) {
    169        printf("env: PR_GetEnvSecure() Failed after setting\n");
    170      }
    171      failedAlready = PR_TRUE;
    172    } else {
    173      if (verbose) {
    174        printf("env: PR_GetEnvSecure() worked after setting it. Found: %s\n",
    175               value);
    176      }
    177    }
    178  }
    179 
    180  /* ---------------------------------------------------------------------- */
    181  /* check that PR_DuplicateEnvironment() agrees with PR_GetEnv() */
    182  {
    183 #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H))
    184    static const PRBool expect_failure = PR_FALSE;
    185 #else
    186    static const PRBool expect_failure = PR_TRUE;
    187 #endif
    188    char **i, **dupenv = PR_DuplicateEnvironment();
    189 
    190    if (NULL == dupenv) {
    191      if (expect_failure) {
    192        if (verbose)
    193          printf(
    194              "env: PR_DuplicateEnvironment failed, "
    195              "as expected on this platform.\n");
    196      } else {
    197        if (debug) {
    198          printf("env: PR_DuplicateEnvironment() failed.\n");
    199        }
    200        failedAlready = PR_TRUE;
    201      }
    202    } else {
    203      unsigned found = 0;
    204 
    205      if (expect_failure) {
    206        if (debug)
    207          printf(
    208              "env: PR_DuplicateEnvironment() succeeded, "
    209              "but failure is expected on this platform.\n");
    210        failedAlready = PR_TRUE;
    211      } else {
    212        if (verbose) {
    213          printf("env: PR_DuplicateEnvironment() succeeded.\n");
    214        }
    215      }
    216      for (i = dupenv; *i; i++) {
    217        char* equals = strchr(*i, '=');
    218 
    219        if (equals == NULL) {
    220          if (debug)
    221            printf(
    222                "env: PR_DuplicateEnvironment() returned a string"
    223                " with no '=': %s\n",
    224                *i);
    225          failedAlready = PR_TRUE;
    226        } else {
    227          /* We own this string, so we can temporarily alter it */
    228          /* *i is the null-terminated name; equals + 1 is the value */
    229          *equals = '\0';
    230 
    231          if (strcmp(*i, ENVNAME) == 0) {
    232            found++;
    233            if (verbose)
    234              printf("env: PR_DuplicateEnvironment() found " ENVNAME
    235                     " (%u so far).\n",
    236                     found);
    237          }
    238 
    239          /* Multiple values for the same name can't happen, according to POSIX.
    240           */
    241          value = PR_GetEnv(*i);
    242          if (value == NULL) {
    243            if (debug)
    244              printf(
    245                  "env: PR_DuplicateEnvironment() returned a name"
    246                  " which PR_GetEnv() failed to find: %s\n",
    247                  *i);
    248            failedAlready = PR_TRUE;
    249          } else if (strcmp(equals + 1, value) != 0) {
    250            if (debug)
    251              printf(
    252                  "env: PR_DuplicateEnvironment() returned the wrong"
    253                  " value for %s: expected %s; found %s\n",
    254                  *i, value, equals + 1);
    255            failedAlready = PR_TRUE;
    256          } else {
    257            if (verbose)
    258              printf(
    259                  "env: PR_DuplicateEnvironment() agreed with"
    260                  " PR_GetEnv() about %s\n",
    261                  *i);
    262          }
    263        }
    264        PR_Free(*i);
    265      }
    266      PR_Free(dupenv);
    267 
    268      if (found != 1) {
    269        if (debug)
    270          printf("env: PR_DuplicateEnvironment() found %u entries for " ENVNAME
    271                 " (expected 1)\n",
    272                 found);
    273        failedAlready = PR_TRUE;
    274      } else {
    275        if (verbose) {
    276          printf("env: PR_DuplicateEnvironment() found 1 entry for " ENVNAME
    277                 "\n");
    278        }
    279      }
    280    }
    281  }
    282 
    283  /* ---------------------------------------------------------------------- */
    284  /* un-set the variable, using RAW name... should not work */
    285  envBuf = NewBuffer(ENVBUFSIZE);
    286  sprintf(envBuf, ENVNAME);
    287  rc = PR_SetEnv(envBuf);
    288  if (PR_FAILURE == rc) {
    289    if (verbose) {
    290      printf("env: PR_SetEnv() not un-set using RAW name. Good!\n");
    291    }
    292  } else {
    293    if (debug) {
    294      printf("env: PR_SetEnv() un-set using RAW name. Bad!\n");
    295    }
    296    failedAlready = PR_TRUE;
    297  }
    298 
    299  value = PR_GetEnv(ENVNAME);
    300  if (NULL == value) {
    301    if (debug) {
    302      printf("env: PR_GetEnv() after un-set using RAW name. Bad!\n");
    303    }
    304    failedAlready = PR_TRUE;
    305  } else {
    306    if (verbose) {
    307      printf("env: PR_GetEnv() after RAW un-set found: %s\n", value);
    308    }
    309  }
    310 
    311  /* ---------------------------------------------------------------------- */
    312  /* set it again ... */
    313  envBuf = NewBuffer(ENVBUFSIZE);
    314  sprintf(envBuf, ENVNAME "=" ENVVALUE);
    315  rc = PR_SetEnv(envBuf);
    316  if (PR_FAILURE == rc) {
    317    if (debug) {
    318      printf("env: PR_SetEnv() failed setting the second time.\n");
    319    }
    320    failedAlready = PR_TRUE;
    321  } else {
    322    if (verbose) {
    323      printf("env: PR_SetEnv() worked.\n");
    324    }
    325  }
    326 
    327  /* un-set the variable using the form name= */
    328  envBuf = NewBuffer(ENVBUFSIZE);
    329  sprintf(envBuf, ENVNAME "=");
    330  rc = PR_SetEnv(envBuf);
    331  if (PR_FAILURE == rc) {
    332    if (debug) {
    333      printf("env: PR_SetEnv() failed un-setting using name=\n");
    334    }
    335    failedAlready = PR_TRUE;
    336  } else {
    337    if (verbose) {
    338      printf("env: PR_SetEnv() un-set using name= worked\n");
    339    }
    340  }
    341 
    342  value = PR_GetEnv(ENVNAME);
    343  if ((NULL == value) || (0x00 == *value)) {
    344    if (verbose) {
    345      printf("env: PR_GetEnv() after un-set using name= worked\n");
    346    }
    347  } else {
    348    if (debug) {
    349      printf("env: PR_GetEnv() after un-set using name=. Found: %s\n", value);
    350    }
    351    failedAlready = PR_TRUE;
    352  }
    353  /* ---------------------------------------------------------------------- */
    354  /* un-set the variable using the form name= */
    355  envBuf = NewBuffer(ENVBUFSIZE);
    356  sprintf(envBuf, ENVNAME "999=");
    357  rc = PR_SetEnv(envBuf);
    358  if (PR_FAILURE == rc) {
    359    if (debug) {
    360      printf("env: PR_SetEnv() failed un-setting using name=\n");
    361    }
    362    failedAlready = PR_TRUE;
    363  } else {
    364    if (verbose) {
    365      printf("env: PR_SetEnv() un-set using name= worked\n");
    366    }
    367  }
    368 
    369  value = PR_GetEnv(ENVNAME "999");
    370  if ((NULL == value) || (0x00 == *value)) {
    371    if (verbose) {
    372      printf("env: PR_GetEnv() after un-set using name= worked\n");
    373    }
    374  } else {
    375    if (debug) {
    376      printf("env: PR_GetEnv() after un-set using name=. Found: %s\n", value);
    377    }
    378    failedAlready = PR_TRUE;
    379  }
    380 
    381  /* ---------------------------------------------------------------------- */
    382  if (debug || verbose) {
    383    printf("\n%s\n", (failedAlready) ? "FAILED" : "PASSED");
    384  }
    385  return ((failedAlready) ? 1 : 0);
    386 } /* main() */
    387 
    388 /* env.c */