Пример #1
0
/** Removes the Tor NT service. Returns 0 if the service was successfully
 * removed, or -1 on error. */
static int
nt_service_remove(void)
{
  SC_HANDLE hSCManager = NULL;
  SC_HANDLE hService = NULL;
  char *errmsg;

  nt_service_loadlibrary();
  if ((hSCManager = nt_service_open_scm()) == NULL)
    return -1;
  if ((hService = nt_service_open(hSCManager)) == NULL) {
    service_fns.CloseServiceHandle_fn(hSCManager);
    return -1;
  }

  nt_service_stop(hService);
  if (service_fns.DeleteService_fn(hService) == FALSE) {
    errmsg = format_win32_error(GetLastError());
    printf("DeleteService() failed : %s\n", errmsg);
    tor_free(errmsg);
    service_fns.CloseServiceHandle_fn(hService);
    service_fns.CloseServiceHandle_fn(hSCManager);
    return -1;
  }

  service_fns.CloseServiceHandle_fn(hService);
  service_fns.CloseServiceHandle_fn(hSCManager);
  printf("Service removed successfully\n");

  return 0;
}
Пример #2
0
/** Stop the Tor service. Return 0 if the service is stopped or was not
 * previously running. Return -1 on error. */
static int
nt_service_stop(SC_HANDLE hService)
{
/** Wait at most 10 seconds for the service to stop. */
#define MAX_SERVICE_WAIT_TIME 10
  int wait_time;
  char *errmsg = NULL;
  nt_service_loadlibrary();

  service_fns.QueryServiceStatus_fn(hService, &service_status);
  if (service_status.dwCurrentState == SERVICE_STOPPED) {
    printf("Service is already stopped\n");
    return 0;
  }

  if (service_fns.ControlService_fn(hService, SERVICE_CONTROL_STOP,
                                    &service_status)) {
    wait_time = 0;
    while (service_fns.QueryServiceStatus_fn(hService, &service_status) &&
           (service_status.dwCurrentState != SERVICE_STOPPED) &&
           (wait_time < MAX_SERVICE_WAIT_TIME)) {
      Sleep(1000);
      wait_time++;
    }
    if (service_status.dwCurrentState == SERVICE_STOPPED) {
      printf("Service stopped successfully\n");
      return 0;
    } else if (wait_time == MAX_SERVICE_WAIT_TIME) {
      printf("Service did not stop within %d seconds.\n", wait_time);
    } else {
      errmsg = format_win32_error(GetLastError());
      printf("QueryServiceStatus() failed : %s\n",errmsg);
      tor_free(errmsg);
    }
  } else {
    errmsg = format_win32_error(GetLastError());
    printf("ControlService() failed : %s\n", errmsg);
    tor_free(errmsg);
  }
  return -1;
}
Пример #3
0
void
tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
{
  BOOL ok = TlsSetValue(threadlocal->index, value);
  if (!ok) {
    DWORD err = GetLastError();
    char *msg = format_win32_error(err);
    log_err(LD_GENERAL, "Error adjusting thread-local value: %s", msg);
    tor_free(msg);
    tor_assert(ok);
  }
}
Пример #4
0
/** Open a handle to the Tor service using <b>hSCManager</b>. Return NULL
 * on failure. */
static SC_HANDLE
nt_service_open(SC_HANDLE hSCManager)
{
  SC_HANDLE hService;
  char *errmsg = NULL;
  nt_service_loadlibrary();
  if ((hService = service_fns.OpenServiceA_fn(hSCManager, GENSRV_SERVICENAME,
                              SERVICE_ALL_ACCESS)) == NULL) {
    errmsg = format_win32_error(GetLastError());
    printf("OpenService() failed : %s\n", errmsg);
    tor_free(errmsg);
  }
  return hService;
}
Пример #5
0
/** Start the Tor service. Return 0 if the service is started or was
 * previously running. Return -1 on error. */
static int
nt_service_start(SC_HANDLE hService)
{
  char *errmsg = NULL;

  nt_service_loadlibrary();

  service_fns.QueryServiceStatus_fn(hService, &service_status);
  if (service_status.dwCurrentState == SERVICE_RUNNING) {
    printf("Service is already running\n");
    return 0;
  }

  if (service_fns.StartServiceA_fn(hService, 0, NULL)) {
    /* Loop until the service has finished attempting to start */
    while (service_fns.QueryServiceStatus_fn(hService, &service_status) &&
           (service_status.dwCurrentState == SERVICE_START_PENDING)) {
      Sleep(500);
    }

    /* Check if it started successfully or not */
    if (service_status.dwCurrentState == SERVICE_RUNNING) {
      printf("Service started successfully\n");
      return 0;
    } else {
      errmsg = format_win32_error(service_status.dwWin32ExitCode);
      printf("Service failed to start : %s\n", errmsg);
      tor_free(errmsg);
    }
  } else {
    errmsg = format_win32_error(GetLastError());
    printf("StartService() failed : %s\n", errmsg);
    tor_free(errmsg);
  }
  return -1;
}
Пример #6
0
/** Return a handle to the service control manager on success, or NULL on
 * failure. */
static SC_HANDLE
nt_service_open_scm(void)
{
  SC_HANDLE hSCManager;
  char *errmsg = NULL;

  nt_service_loadlibrary();
  if ((hSCManager = service_fns.OpenSCManagerA_fn(
                            NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) {
    errmsg = format_win32_error(GetLastError());
    printf("OpenSCManager() failed : %s\n", errmsg);
    tor_free(errmsg);
  }
  return hSCManager;
}
Пример #7
0
void *
tor_threadlocal_get(tor_threadlocal_t *threadlocal)
{
  void *value = TlsGetValue(threadlocal->index);
  if (value == NULL) {
    DWORD err = GetLastError();
    if (err != ERROR_SUCCESS) {
      char *msg = format_win32_error(err);
      log_err(LD_GENERAL, "Error retrieving thread-local value: %s", msg);
      tor_free(msg);
      tor_assert(err == ERROR_SUCCESS);
    }
  }
  return value;
}
Пример #8
0
/** Main service entry point. Starts the service control dispatcher and waits
 * until the service status is set to SERVICE_STOPPED. */
static void
nt_service_main(void)
{
  SERVICE_TABLE_ENTRYA table[2];
  DWORD result = 0;
  char *errmsg;
  nt_service_loadlibrary();
  table[0].lpServiceName = (char*)GENSRV_SERVICENAME;
  table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)nt_service_body;
  table[1].lpServiceName = NULL;
  table[1].lpServiceProc = NULL;

  if (!service_fns.StartServiceCtrlDispatcherA_fn(table)) {
    result = GetLastError();
    errmsg = format_win32_error(result);
    printf("Service error %d : %s\n", (int) result, errmsg);
    tor_free(errmsg);
    if (result == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
      if (tor_init(backup_argc, backup_argv))
        return;
      switch (get_options()->command) {
      case CMD_RUN_TOR:
        do_main_loop();
        break;
      case CMD_LIST_FINGERPRINT:
      case CMD_HASH_PASSWORD:
      case CMD_VERIFY_CONFIG:
      case CMD_DUMP_CONFIG:
      case CMD_KEYGEN:
      case CMD_KEY_EXPIRATION:
        log_err(LD_CONFIG, "Unsupported command (--list-fingerprint, "
               "--hash-password, --keygen, --dump-config, --verify-config, "
               "or --key-expiration) in NT service.");
        break;
      case CMD_RUN_UNITTESTS:
      default:
        log_err(LD_CONFIG, "Illegal command number %d: internal error.",
                get_options()->command);
      }
      tor_cleanup();
    }
  }
}
Пример #9
0
Файл: procmon.c Проект: 4ZM/Tor
/** Libevent callback to poll for the existence of the process
 * monitored by <b>procmon_</b>. */
static void
tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
                            void *procmon_)
{
  tor_process_monitor_t *procmon = (tor_process_monitor_t *)(procmon_);
  int its_dead_jim;

  (void)unused1; (void)unused2;

  tor_assert(procmon != NULL);

#ifdef MS_WINDOWS
  if (procmon->poll_hproc) {
    DWORD exit_code;
    if (!GetExitCodeProcess(procmon->hproc, &exit_code)) {
      char *errmsg = format_win32_error(GetLastError());
      log_warn(procmon->log_domain, "Error \"%s\" occurred while polling "
               "handle for monitored process %d; assuming it's dead.",
               errmsg, procmon->pid);
      tor_free(errmsg);
      its_dead_jim = 1;
    } else {
      its_dead_jim = (exit_code != STILL_ACTIVE);
    }
  } else {
    /* All we can do is try to open the process, and look at the error
     * code if it fails again. */
    procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
                                 FALSE,
                                 procmon->pid);

    if (procmon->hproc != NULL) {
      log_info(procmon->log_domain, "Successfully opened handle to monitored "
               "process %d.",
               procmon->pid);
      its_dead_jim = 0;
      procmon->poll_hproc = 1;
    } else {
      DWORD err_code = GetLastError();
      char *errmsg = format_win32_error(err_code);

      /* When I tested OpenProcess's error codes on Windows 7, I
       * received error code 5 (ERROR_ACCESS_DENIED) for PIDs of
       * existing processes that I could not open and error code 87
       * (ERROR_INVALID_PARAMETER) for PIDs that were not in use.
       * Since the nonexistent-process error code is sane, I'm going
       * to assume that all errors other than ERROR_INVALID_PARAMETER
       * mean that the process we are monitoring is still alive. */
      its_dead_jim = (err_code == ERROR_INVALID_PARAMETER);

      if (!its_dead_jim)
        log_info(procmon->log_domain, "Failed to open handle to monitored "
                 "process %d, and error code %lu (%s) is not 'invalid "
                 "parameter' -- assuming the process is still alive.",
                 procmon->pid,
                 err_code, errmsg);

      tor_free(errmsg);
    }
  }
#else
  /* Unix makes this part easy, if a bit racy. */
  its_dead_jim = kill(procmon->pid, 0);
  its_dead_jim = its_dead_jim && (errno == ESRCH);
#endif

  log(its_dead_jim ? LOG_NOTICE : LOG_INFO,
      procmon->log_domain, "Monitored process %d is %s.",
      (int)procmon->pid,
      its_dead_jim ? "dead" : "still alive");

  if (its_dead_jim) {
    procmon->cb(procmon->cb_arg);
#ifndef HAVE_EVENT2_EVENT_H
  } else {
    evtimer_add(procmon->e, &poll_interval_tv);
#endif
  }
}
Пример #10
0
/** Creates a Tor NT service, set to start on boot. The service will be
 * started if installation succeeds. Returns 0 on success, or -1 on
 * failure. */
static int
nt_service_install(int argc, char **argv)
{
  /* Notes about developing NT services:
   *
   * 1. Don't count on your CWD. If an absolute path is not given, the
   *    fopen() function goes wrong.
   * 2. The parameters given to the nt_service_body() function differ
   *    from those given to main() function.
   */

  SC_HANDLE hSCManager = NULL;
  SC_HANDLE hService = NULL;
  SERVICE_DESCRIPTIONA sdBuff;
  char *command;
  char *errmsg;
  const char *user_acct = NULL;
  const char *password = "";
  int i;
  OSVERSIONINFOEX info;
  SID_NAME_USE sidUse;
  DWORD sidLen = 0, domainLen = 0;
  int is_win2k_or_worse = 0;
  int using_default_torrc = 0;

  nt_service_loadlibrary();

  /* Open the service control manager so we can create a new service */
  if ((hSCManager = nt_service_open_scm()) == NULL)
    return -1;
  /* Build the command line used for the service */
  if ((command = nt_service_command_line(&using_default_torrc)) == NULL) {
    printf("Unable to build service command line.\n");
    service_fns.CloseServiceHandle_fn(hSCManager);
    return -1;
  }

  for (i=1; i < argc; ++i) {
    if (!strcmp(argv[i], "--user") && i+1<argc) {
      user_acct = argv[i+1];
      ++i;
    }
    if (!strcmp(argv[i], "--password") && i+1<argc) {
      password = argv[i+1];
      ++i;
    }
  }

  /* Compute our version and see whether we're running win2k or earlier. */
  memset(&info, 0, sizeof(info));
  info.dwOSVersionInfoSize = sizeof(info);
  if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
    printf("Call to GetVersionEx failed.\n");
    is_win2k_or_worse = 1;
  } else {
    if (info.dwMajorVersion < 5 ||
        (info.dwMajorVersion == 5 && info.dwMinorVersion == 0))
      is_win2k_or_worse = 1;
  }

  if (!user_acct) {
    if (is_win2k_or_worse) {
      /* On Win2k, there is no LocalService account, so we actually need to
       * fall back on NULL (the system account). */
      printf("Running on Win2K or earlier, so the LocalService account "
             "doesn't exist.  Falling back to SYSTEM account.\n");
    } else {
      /* Genericity is apparently _so_ last year in Redmond, where some
       * accounts are accounts that you can look up, and some accounts
       * are magic and undetectable via the security subsystem. See
       * http://msdn2.microsoft.com/en-us/library/ms684188.aspx
       */
      printf("Running on a Post-Win2K OS, so we'll assume that the "
             "LocalService account exists.\n");
      user_acct = GENSRV_USERACCT;
    }
  } else if (0 && service_fns.LookupAccountNameA_fn(NULL, // On this system
                            user_acct,
                            NULL, &sidLen, // Don't care about the SID
                            NULL, &domainLen, // Don't care about the domain
                            &sidUse) == 0) {
    /* XXXX For some reason, the above test segfaults. Fix that. */
    printf("User \"%s\" doesn't seem to exist.\n", user_acct);
    return -1;
  } else {
    printf("Will try to install service as user \"%s\".\n", user_acct);
  }
  /* XXXX This warning could be better about explaining how to resolve the
   * situation. */
  if (using_default_torrc)
    printf("IMPORTANT NOTE:\n"
        "    The Tor service will run under the account \"%s\".  This means\n"
        "    that Tor will look for its configuration file under that\n"
        "    account's Application Data directory, which is probably not\n"
        "    the same as yours.\n", user_acct?user_acct:"<local system>");

  /* Create the Tor service, set to auto-start on boot */
  if ((hService = service_fns.CreateServiceA_fn(hSCManager, GENSRV_SERVICENAME,
                                GENSRV_DISPLAYNAME,
                                SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
                                SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
                                command, NULL, NULL, NULL,
                                user_acct, password)) == NULL) {
    errmsg = format_win32_error(GetLastError());
    printf("CreateService() failed : %s\n", errmsg);
    service_fns.CloseServiceHandle_fn(hSCManager);
    tor_free(errmsg);
    tor_free(command);
    return -1;
  }
  printf("Done with CreateService.\n");

  /* Set the service's description */
  sdBuff.lpDescription = (char*)GENSRV_DESCRIPTION;
  service_fns.ChangeServiceConfig2A_fn(hService, SERVICE_CONFIG_DESCRIPTION,
                                       &sdBuff);
  printf("Service installed successfully\n");

  /* Start the service initially */
  nt_service_start(hService);

  service_fns.CloseServiceHandle_fn(hService);
  service_fns.CloseServiceHandle_fn(hSCManager);
  tor_free(command);

  return 0;
}
Пример #11
0
tor_mmap_t *
tor_mmap_file(const char *filename)
{
  TCHAR tfilename[MAX_PATH]= {0};
  tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
  int empty = 0;
  HANDLE file_handle = INVALID_HANDLE_VALUE;
  DWORD size_low, size_high;
  uint64_t real_size;
  res->mmap_handle = NULL;
#ifdef UNICODE
  mbstowcs(tfilename,filename,MAX_PATH);
#else
  strlcpy(tfilename,filename,MAX_PATH);
#endif
  file_handle = CreateFile(tfilename,
                           GENERIC_READ, FILE_SHARE_READ,
                           NULL,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           0);

  if (file_handle == INVALID_HANDLE_VALUE)
    goto win_err;

  size_low = GetFileSize(file_handle, &size_high);

  if (size_low == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
    log_warn(LD_FS,"Error getting size of \"%s\".",filename);
    goto win_err;
  }
  if (size_low == 0 && size_high == 0) {
    log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
    empty = 1;
    goto err;
  }
  real_size = (((uint64_t)size_high)<<32) | size_low;
  if (real_size > SIZE_MAX) {
    log_warn(LD_FS,"File \"%s\" is too big to map; not trying.",filename);
    goto err;
  }
  res->size = real_size;

  res->mmap_handle = CreateFileMapping(file_handle,
                                       NULL,
                                       PAGE_READONLY,
                                       size_high,
                                       size_low,
                                       NULL);
  if (res->mmap_handle == NULL)
    goto win_err;
  res->data = (char*) MapViewOfFile(res->mmap_handle,
                                    FILE_MAP_READ,
                                    0, 0, 0);
  if (!res->data)
    goto win_err;

  CloseHandle(file_handle);
  return res;
 win_err: {
    DWORD e = GetLastError();
    int severity = (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND) ?
      LOG_INFO : LOG_WARN;
    char *msg = format_win32_error(e);
    log_fn(severity, LD_FS, "Couldn't mmap file \"%s\": %s", filename, msg);
    tor_free(msg);
    if (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND)
      errno = ENOENT;
    else
      errno = EINVAL;
  }
 err:
  if (empty)
    errno = ERANGE;
  if (file_handle != INVALID_HANDLE_VALUE)
    CloseHandle(file_handle);
  tor_munmap_file(res);
  return NULL;
}