Exemplo n.º 1
0
static void LogInit(NS_tchar *path)
{
  if (gLogFP)
    return;

  NS_tchar logFile[MAXPATHLEN];
  NS_tsnprintf(logFile, MAXPATHLEN, NS_T("%s/update.log"), path);

  gLogFP = NS_tfopen(logFile, NS_T("w"));
}
Exemplo n.º 2
0
void UpdateLog::Init(NS_tchar* sourcePath, const NS_tchar* fileName)
{
  if (logFP)
    return;

  this->sourcePath = sourcePath;
  NS_tchar logFile[MAXPATHLEN];
  NS_tsnprintf(logFile, sizeof(logFile)/sizeof(logFile[0]),
    NS_T("%s/%s"), sourcePath, fileName);

  logFP = NS_tfopen(logFile, NS_T("w"));
}
int
CVE_2014_1496_thunderbird3_1_20_PatchFile::Prepare()
{
  LOG(("PREPARE PATCH %s\n", mFile));

  // extract the patch to a temporary file
  mPatchIndex = sPatchIndex++;

  NS_tsnprintf(spath, sizeof(spath)/sizeof(spath[0]),
               NS_T("%s/%d.patch"), gSourcePath, mPatchIndex);

  NS_tremove(spath);

  FILE *fp = NS_tfopen(spath, NS_T("wb"));
  if (!fp)
    return WRITE_ERROR;

  int rv = gArchiveReader.ExtractFileToStream(mPatchFile, fp);
  fclose(fp);
  return rv;
}
Exemplo n.º 4
0
static void
WriteStatusFile(NS_tchar* path, int status)
{
  // This is how we communicate our completion status to the main application.

  NS_tchar filename[MAXPATHLEN];
  NS_tsnprintf(filename, MAXPATHLEN, NS_T("%s/update.status"), path);

  int fd = NS_topen(filename, O_WRONLY | O_TRUNC | O_CREAT | _O_BINARY, 0644);
  if (fd < 0)
    return;

  const char *text;

  char buf[32];
  if (status == OK) {
    text = "succeeded\n";
  } else {
    snprintf(buf, sizeof(buf), "failed: %d\n", status);
    text = buf;
  }
  write(fd, text, strlen(text));
  close(fd);
}
Exemplo n.º 5
0
static void
DoUpdate(NS_tchar *path)
{
  NS_tchar spath[MAXPATHLEN];
  NS_tchar dpath[MAXPATHLEN];
  NS_tchar upstatus[MAXPATHLEN];
  NS_tchar upparams[MAXPATHLEN];
  NS_tchar sysdir[MAXPATHLEN];
  NS_tchar msiexec[MAXPATHLEN];
  NS_tsnprintf(spath, MAXPATHLEN, NS_T("%s/update.mar"), path);
  NS_tsnprintf(dpath, MAXPATHLEN, NS_T("%s/update.msi"), path);
  NS_tsnprintf(upstatus, MAXPATHLEN, NS_T("%s/update.status"), path);
  NS_tsnprintf(upparams, MAXPATHLEN, NS_T("%s/../../update.params"), path);
  GetSystemDirectory(sysdir, MAXPATHLEN);
  NS_tsnprintf(msiexec, MAXPATHLEN, NS_T("%s\\msiexec.exe"), sysdir);

  int rv = NS_taccess(spath, F_OK | R_OK | W_OK);
  if (rv != OK) {
  	LOG(("failed: can't access update.mar (rv=%d)\n", rv));
	NS_tremove(spath);
	NS_tremove(upstatus);
	return;
  }

  NS_tremove(dpath);
  rv = NS_trename(spath, dpath);
  if (rv != OK) {
  	LOG(("failed: can't rename update.mar (rv=%d)\n", rv));
	NS_tremove(spath);
	NS_tremove(upstatus);
	return;
  }
 
  WCharReplace(dpath, L'/', L'\\');
  int largc = 3;
  NS_tchar* largv[16]; //16 being max
  largv[0] = msiexec; //first arg is the path to msiexec.exe
  largv[1] = NS_T("/i"); //second arg is the install-flag
  largv[2] = dpath; //third arg is the path to update.msi
  NS_tchar argbuf[MAXPATHLEN];
  int start = 0;
  int end = 0;

  rv = NS_taccess(upparams, F_OK | R_OK);
  char buf[MAXPATHLEN];
  if (rv == OK) {
      int fd = NS_topen(upparams, O_RDONLY | O_BINARY);
      if (fd >= 0) {
          int num = read(fd, buf, MAXPATHLEN - 1);
	  if (num > 0) {
	      buf[num] = '\0';
	      for (int i = 0; i <= num; ++i) {
                  if (buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\r' && buf[i] != '\0')
                      argbuf[end++] = buf[i];
	          else if (end > start) { //we had an arg
		      largv[largc++] = argbuf + start;
		      argbuf[end++] = '\0';
		      start = end;
	          }
	      }	
	  } else
              LOG(("warn: can't read update.params\n"));
      } else
  	  LOG(("warn: can't open update.params\n"));
  } else
      LOG(("warn: can't access update.params (rv=%d)\n", rv));

  //for (int i = 0; i < largc; ++i)
  //    NS_tfprintf(stderr, NS_T("arg[%d]=%s\n"), i, largv[i]);

  LOG(("info: running %ls %ls %ls\n", largv[0], largv[1], largv[2]));
  LaunchApp(path, largc, largv);

  LOG(("succeeded\n"));
  //WriteStatusFile(path, rv);
  NS_tremove(upstatus);
}
int NS_main(int argc, NS_tchar **argv)
{
  printf("Running TestAUSReadStrings tests\n");

  int rv = 0;
  int retval;
  NS_tchar inifile[MAXPATHLEN];
  StringTable testStrings;

  NS_tchar *slash = NS_tstrrchr(argv[0], PATH_SEPARATOR_CHAR);
  if (!slash) {
    fail("%s | unable to find platform specific path separator (check 1)", TEST_NAME);
    return 20;
  }

  *(++slash) = '\0';
  // Test success when the ini file exists with both Title and Info in the
  // Strings section and the values for Title and Info.
  NS_tsnprintf(inifile, sizeof(inifile), NS_T("%sTestAUSReadStrings1.ini"), argv[0]);
  retval = ReadStrings(inifile, &testStrings);
  if (retval == OK) {
    if (strcmp(testStrings.title, "Title Test - \xD0\x98\xD1\x81\xD0\xBF\xD1\x8B" \
                                  "\xD1\x82\xD0\xB0\xD0\xBD\xD0\xB8\xD0\xB5 " \
                                  "\xCE\x94\xCE\xBF\xCE\xBA\xCE\xB9\xCE\xBC\xCE\xAE " \
                                  "\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88 " \
                                  "\xE6\xB8\xAC\xE8\xA9\xA6 " \
                                  "\xE6\xB5\x8B\xE8\xAF\x95") != 0) {
      rv = 21;
      fail("%s | Title ini value incorrect (check 3)", TEST_NAME);
    }

    if (strcmp(testStrings.info, "Info Test - \xD0\x98\xD1\x81\xD0\xBF\xD1\x8B" \
                                 "\xD1\x82\xD0\xB0\xD0\xBD\xD0\xB8\xD0\xB5 " \
                                 "\xCE\x94\xCE\xBF\xCE\xBA\xCE\xB9\xCE\xBC\xCE\xAE " \
                                 "\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88 " \
                                 "\xE6\xB8\xAC\xE8\xA9\xA6 " \
                                 "\xE6\xB5\x8B\xE8\xAF\x95\xE2\x80\xA6") != 0) {
      rv = 22;
      fail("%s | Info ini value incorrect (check 4)", TEST_NAME);
    }
  }
  else {
    fail("%s | ReadStrings returned %i (check 2)", TEST_NAME, retval);
    rv = 23;
  }

  // Test failure when the ini file exists without Title and with Info in the
  // Strings section.
  NS_tsnprintf(inifile, sizeof(inifile), NS_T("%sTestAUSReadStrings2.ini"), argv[0]);
  retval = ReadStrings(inifile, &testStrings);
  if (retval != PARSE_ERROR) {
    rv = 24;
    fail("%s | ReadStrings returned %i (check 5)", TEST_NAME, retval);
  }

  // Test failure when the ini file exists with Title and without Info in the
  // Strings section.
  NS_tsnprintf(inifile, sizeof(inifile), NS_T("%sTestAUSReadStrings3.ini"), argv[0]);
  retval = ReadStrings(inifile, &testStrings);
  if (retval != PARSE_ERROR) {
    rv = 25;
    fail("%s | ReadStrings returned %i (check 6)", TEST_NAME, retval);
  }

  // Test failure when the ini file doesn't exist
  NS_tsnprintf(inifile, sizeof(inifile), NS_T("%sTestAUSReadStringsBogus.ini"), argv[0]);
  retval = ReadStrings(inifile, &testStrings);
  if (retval != READ_ERROR) {
    rv = 26;
    fail("%s | ini file doesn't exist (check 7)", TEST_NAME);
  }

  // Test reading a non-default section name
  NS_tsnprintf(inifile, sizeof(inifile), NS_T("%sTestAUSReadStrings3.ini"), argv[0]);
  retval = ReadStrings(inifile, "Title\0", 1, &testStrings.title, "BogusSection2");
  if (retval == OK) {
    if (strcmp(testStrings.title, "Bogus Title") != 0) {
      rv = 27;
      fail("%s | Title ini value incorrect (check 9)", TEST_NAME);
    }
  }
  else {
    fail("%s | ReadStrings returned %i (check 8)", TEST_NAME, retval);
    rv = 28;
  }


  if (rv == 0) {
    printf("TEST-PASS | %s | all checks passed\n", TEST_NAME);
  } else {
    fail("%s | %i out of 9 checks failed", TEST_NAME, gFailCount);
  }

  return rv;
}
int CVE_2014_1496_thunderbird24_1_0_DoUpdate()
{
  NS_tchar manifest[MAXPATHLEN];
  NS_tsnprintf(manifest, sizeof(manifest)/sizeof(manifest[0]),
               NS_T("%s/update.manifest"), gSourcePath);

  // extract the manifest
  int rv = gArchiveReader.ExtractFile("updatev2.manifest", manifest);
  if (rv) {
    rv = gArchiveReader.ExtractFile("update.manifest", manifest);
    if (rv) {
      LOG(("CVE_2014_1496_thunderbird24_1_0_DoUpdate: error extracting manifest file"));
      return rv;
    }
  }

  NS_tchar *rb = GetManifestContents(manifest);
  if (rb == NULL) {
    LOG(("CVE_2014_1496_thunderbird24_1_0_DoUpdate: error opening manifest file: " LOG_S, manifest));
    return READ_ERROR;
  }


  ActionList list;
  NS_tchar *line;
  bool isFirstAction = true;

  while((line = mstrtok(kNL, &rb)) != 0) {
    // skip comments
    if (*line == NS_T('#'))
      continue;

    NS_tchar *token = mstrtok(kWhitespace, &line);
    if (!token) {
      LOG(("CVE_2014_1496_thunderbird24_1_0_DoUpdate: token not found in manifest"));
      return PARSE_ERROR;
    }

    if (isFirstAction && NS_tstrcmp(token, NS_T("type")) == 0) {
      const NS_tchar *type = mstrtok(kQuote, &line);
      LOG(("UPDATE TYPE " LOG_S, type));
      if (NS_tstrcmp(type, NS_T("complete")) == 0) {
        rv = AddPreCompleteActions(&list);
        if (rv)
          return rv;
      }
      isFirstAction = false;
      continue;
    }

    isFirstAction = false;

    Action *action = NULL;
    if (NS_tstrcmp(token, NS_T("remove")) == 0) { // rm file
      action = new RemoveFile();
    }
    else if (NS_tstrcmp(token, NS_T("rmdir")) == 0) { // rmdir if  empty
      action = new RemoveDir();
    }
    else if (NS_tstrcmp(token, NS_T("rmrfdir")) == 0) { // rmdir recursive
      const NS_tchar *reldirpath = mstrtok(kQuote, &line);
      if (!reldirpath)
        return PARSE_ERROR;

      if (reldirpath[NS_tstrlen(reldirpath) - 1] != NS_T('/'))
        return PARSE_ERROR;

      rv = add_dir_entries(reldirpath, &list);
      if (rv)
        return rv;

      continue;
    }
    else if (NS_tstrcmp(token, NS_T("add")) == 0) {
      action = new AddFile();
    }
    else if (NS_tstrcmp(token, NS_T("patch")) == 0) {
      action = new PatchFile();
    }
    else if (NS_tstrcmp(token, NS_T("add-if")) == 0) { // Add if exists
      action = new AddIfFile();
    }
    else if (NS_tstrcmp(token, NS_T("patch-if")) == 0) { // Patch if exists
      action = new PatchIfFile();
    }
    else if (NS_tstrcmp(token, NS_T("add-cc")) == 0) { // no longer supported
      continue;
    }
    else {
      LOG(("CVE_2014_1496_thunderbird24_1_0_DoUpdate: unknown token: " LOG_S, token));
      return PARSE_ERROR;
    }

    if (!action)
      return BAD_ACTION_ERROR;

    rv = action->Parse(line);
    if (rv)
      return rv;

    list.Append(action);
  }

  rv = list.Prepare();
  if (rv)
    return rv;

  rv = list.Execute();

  list.Finish(rv);
  return rv;
}
Exemplo n.º 8
0
int NS_main(int argc, NS_tchar **argv)
{

  if (argc < 3) {
    fprintf(stderr, \
            "\n" \
            "Application Update Service Test Helper\n" \
            "\n" \
            "Usage: WORKINGDIR INFILE OUTFILE -s SECONDS [FILETOLOCK]\n"  \
            "   or: WORKINGDIR LOGFILE [ARG2 ARG3...]\n" \
            "   or: signature-check filepath\n" \
            "   or: setup-symlink dir1 dir2 file symlink\n" \
            "   or: remove-symlink dir1 dir2 file symlink\n" \
            "   or: check-symlink symlink\n" \
            "\n" \
            "  WORKINGDIR  \tThe relative path to the working directory to use.\n" \
            "  INFILE      \tThe relative path from the working directory for the file to\n" \
            "              \tread actions to perform such as finish.\n" \
            "  OUTFILE     \tThe relative path from the working directory for the file to\n" \
            "              \twrite status information.\n" \
            "  SECONDS     \tThe number of seconds to sleep.\n" \
            "  FILETOLOCK  \tThe relative path from the working directory to an existing\n" \
            "              \tfile to open exlusively.\n" \
            "              \tOnly available on Windows platforms and silently ignored on\n" \
            "              \tother platforms.\n" \
            "  LOGFILE     \tThe relative path from the working directory to log the\n" \
            "              \tcommand line arguments.\n" \
            "  ARG2 ARG3...\tArguments to write to the LOGFILE after the preceding command\n" \
            "              \tline arguments.\n" \
            "\n" \
            "Note: All paths must be relative.\n" \
            "\n");
    return 1;
  }

  if (!NS_tstrcmp(argv[1], NS_T("check-signature"))) {
#ifdef XP_WIN
    if (ERROR_SUCCESS == VerifyCertificateTrustForFile(argv[2])) {
      return 0;
    } else {
      return 1;
    }
#else 
    // Not implemented on non-Windows platforms
    return 1;
#endif
  }

  if (!NS_tstrcmp(argv[1], NS_T("setup-symlink"))) {
#ifdef XP_UNIX
    NS_tchar path[MAXPATHLEN];
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
    mkdir(path, 0755);
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
    mkdir(path, 0755);
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
    FILE * file = NS_tfopen(path, NS_T("w"));
    if (file) {
      NS_tfputs(NS_T("test"), file);
      fclose(file);
    }
    symlink(path, argv[5]);
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
    if (argc > 6 && !NS_tstrcmp(argv[6], NS_T("change-perm"))) {
      chmod(path, 0644);
    }
    return 0;
#else
    // Not implemented on non-Unix platforms
    return 1;
#endif
  }

  if (!NS_tstrcmp(argv[1], NS_T("remove-symlink"))) {
#ifdef XP_UNIX
    NS_tchar path[MAXPATHLEN];
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
    chmod(path, 0755);
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
    unlink(path);
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
    rmdir(path);
    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
    rmdir(path);
    return 0;
#else
    // Not implemented on non-Unix platforms
    return 1;
#endif
  }

  if (!NS_tstrcmp(argv[1], NS_T("check-symlink"))) {
#ifdef XP_UNIX
    struct stat ss;
    lstat(argv[2], &ss);
    return S_ISLNK(ss.st_mode) ? 0 : 1;
#else
    // Not implemented on non-Unix platforms
    return 1;
#endif
  }

  if (!NS_tstrcmp(argv[1], NS_T("wait-for-service-stop"))) {
#ifdef XP_WIN
    const int maxWaitSeconds = NS_ttoi(argv[3]);
    LPCWSTR serviceName = argv[2];
    DWORD serviceState = WaitForServiceStop(serviceName, maxWaitSeconds);
    if (SERVICE_STOPPED == serviceState) {
      return 0;
    } else {
      return serviceState;
    }
#else 
    // Not implemented on non-Windows platforms
    return 1;
#endif
  }

  if (!NS_tstrcmp(argv[1], NS_T("wait-for-application-exit"))) {
#ifdef XP_WIN
    const int maxWaitSeconds = NS_ttoi(argv[3]);
    LPCWSTR application = argv[2];
    DWORD ret = WaitForProcessExit(application, maxWaitSeconds);
    if (ERROR_SUCCESS == ret) {
      return 0;
    } else if (WAIT_TIMEOUT == ret) {
      return 1;
    } else {
      return 2;
    }
#else 
    // Not implemented on non-Windows platforms
    return 1;
#endif
  }

  int i = 0;

  if (NS_tchdir(argv[1]) != 0) {
    return 1;
  }

  // File in use test helper section
  if (!NS_tstrcmp(argv[4], NS_T("-s"))) {
    NS_tchar *cwd = NS_tgetcwd(nullptr, 0);
    NS_tchar inFilePath[MAXPATHLEN];
    NS_tsnprintf(inFilePath, sizeof(inFilePath)/sizeof(inFilePath[0]),
                 NS_T("%s/%s"), cwd, argv[2]);
    NS_tchar outFilePath[MAXPATHLEN];
    NS_tsnprintf(outFilePath, sizeof(outFilePath)/sizeof(outFilePath[0]),
                 NS_T("%s/%s"), cwd, argv[3]);

    int seconds = NS_ttoi(argv[5]);
#ifdef XP_WIN
    HANDLE hFile = INVALID_HANDLE_VALUE;
    if (argc == 7) {
      hFile = CreateFileW(argv[6],
                          DELETE | GENERIC_WRITE, 0,
                          nullptr, OPEN_EXISTING, 0, nullptr);
      if (hFile == INVALID_HANDLE_VALUE) {
        WriteMsg(outFilePath, "error_locking");
        return 1;
      }
    }

    WriteMsg(outFilePath, "sleeping");
    while (!CheckMsg(inFilePath, "finish\n") && i++ <= seconds)  {
      Sleep(1000);
    }

    if (argc == 7) {
      CloseHandle(hFile);
    }
#else
    WriteMsg(outFilePath, "sleeping");
    while (!CheckMsg(inFilePath, "finish\n") && i++ <= seconds)  {
      sleep(1);
    }
#endif
    WriteMsg(outFilePath, "finished");
    return 0;
  }

  // Command line argument test helper section
  NS_tchar logFilePath[MAXPATHLEN];
  NS_tsnprintf(logFilePath, sizeof(logFilePath)/sizeof(logFilePath[0]),
               NS_T("%s"), argv[2]);

  FILE* logFP = NS_tfopen(logFilePath, NS_T("wb"));
  for (i = 1; i < argc; ++i) {
    fprintf(logFP, LOG_S "\n", argv[i]);
  }

  fclose(logFP);
  logFP = nullptr;

  return 0;
}