/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "native_client/src/include/portability.h"
#include "native_client/src/include/nacl_macros.h"

#include "native_client/src/trusted/service_runtime/env_cleanser.h"
#include "native_client/src/trusted/service_runtime/env_cleanser_test.h"

/*
 * Everything that starts with this prefix is allowed (but the prefix is
 * stripped away).
*/
#define NACL_ENV_PREFIX "NACLENV_"
#define NACL_ENV_PREFIX_LENGTH 8

void NaClEnvCleanserCtor(struct NaClEnvCleanser *self, int with_whitelist) {
  self->with_whitelist = with_whitelist;
  self->cleansed_environ = (char const **) NULL;
}

/*
 * Environment variables names are from IEEE Std 1003.1-2001, with
 * additional ones from locale(7) from glibc / linux.  The entries
 * must be sorted, in ASCII order, for the bsearch to run correctly.
 */
/* static -- not static for testing */
char const *const kNaClEnvWhitelist[] = {
  "LANG",
  "LC_ADDRESS",
  "LC_ALL",
  "LC_COLLATE",
  "LC_CTYPE",
  "LC_IDENTIFICATION",
  "LC_MEASUREMENT",
  "LC_MESSAGES",
  "LC_MONETARY",
  "LC_NAME",
  "LC_NUMERIC",
  "LC_PAPER",
  "LC_TELEPHONE",
  "LC_TIME",
  "NACLVERBOSITY",
  "NACL_PLUGIN_DEBUG",      /* Chromium's plugin/utility.cc */
  "NACL_SRPC_DEBUG",        /* src/shared/srpc/utility.c */
  NULL,
};

/* left arg is key, right arg is table entry */
static int EnvCmp(void const *vleft, void const *vright) {
  char const *left = *(char const *const *) vleft;
  char const *right = *(char const *const *) vright;
  char cleft, cright;

  while ((cleft = *left) == (cright = *right)
         && '\0' != cleft
         && '\0' != cright) {
    ++left;
    ++right;
  }
  if ('=' == cleft && '\0' == cright) {
    return 0;
  }
  return (0xff & cleft) - (0xff & cright);
}

int NaClEnvIsPassThroughVar(char const *env_entry) {
  return strlen(env_entry) > NACL_ENV_PREFIX_LENGTH &&
      0 == strncmp(env_entry, NACL_ENV_PREFIX,
          NACL_ENV_PREFIX_LENGTH);
}

int NaClEnvInWhitelist(char const *env_entry) {
  return NULL != bsearch((void const *) &env_entry,
                         (void const *) kNaClEnvWhitelist,
                         NACL_ARRAY_SIZE(kNaClEnvWhitelist) - 1,  /* NULL */
                         sizeof kNaClEnvWhitelist[0],
                         EnvCmp);
}

/* PRE: sizeof(char *) is a power of 2 */

/*
 * Initializes the object with a filtered environment.
 *
 * May return false on errors, e.g., out-of-memory.
 */
int NaClEnvCleanserInit(struct NaClEnvCleanser *self, char const *const *envp,
    char const * const *extra_env) {
  char const *const *p;
  size_t num_env = 0;
  size_t ptr_bytes = 0;
  const size_t kMaxSize = ~(size_t) 0;
  const size_t ptr_size_mult_overflow_mask = ~(kMaxSize / sizeof *envp);
  char const **ptr_tbl;
  size_t env;

  /*
   * let n be a size_t.  if n & ptr_size_mult_overflow_mask is set,
   * then n*sizeof(void *) will have an arithmetic overflow.
   */

  if (NULL == envp || NULL == *envp) {
    self->cleansed_environ = NULL;
    return 1;
  }
  for (p = envp; NULL != *p; ++p) {
    if (!(self->with_whitelist && NaClEnvInWhitelist(*p)) &&
        !NaClEnvIsPassThroughVar(*p)) {
      continue;
    }
    if (num_env == kMaxSize) {
      /* would overflow */
      return 0;
    }
    ++num_env;
  }

  if (extra_env) {
    for (p = extra_env; NULL != *p; ++p) {
      if (num_env == kMaxSize) {
        /* would overflow */
        return 0;
      }
      ++num_env;
    }
  }

  /* pointer table -- NULL pointer terminated */
  if (0 != ((1 + num_env) & ptr_size_mult_overflow_mask)) {
    return 0;
  }
  ptr_bytes = (1 + num_env) * sizeof(*envp);

  ptr_tbl = (char const **) malloc(ptr_bytes);
  if (NULL == ptr_tbl) {
    return 0;
  }

  /* this assumes no other thread is tweaking envp */
  for (env = 0, p = envp; NULL != *p; ++p) {
    if (NaClEnvIsPassThroughVar(*p)) {
      ptr_tbl[env] = *p + NACL_ENV_PREFIX_LENGTH;
    } else if (self->with_whitelist && NaClEnvInWhitelist(*p)) {
      ptr_tbl[env] = *p;
    } else {
      continue;
    }
    ++env;
  }
  if (extra_env) {
    for (p = extra_env; NULL != *p; ++p) {
      ptr_tbl[env] = *p;
      ++env;
    }
  }
  if (num_env != env) {
    free((void *) ptr_tbl);
    return 0;
  }
  ptr_tbl[env] = NULL;
  self->cleansed_environ = ptr_tbl;

  return 1;
}

char const *const *NaClEnvCleanserEnvironment(struct NaClEnvCleanser *self) {
  return (char const *const *) self->cleansed_environ;
}

void NaClEnvCleanserDtor(struct NaClEnvCleanser *self) {
  free((void *) self->cleansed_environ);
  self->cleansed_environ = NULL;
}
