toolkit/mozapps/update/tests/TestAUSHelper.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/mozapps/update/tests/TestAUSHelper.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,368 @@
     1.4 +/* Any copyright is dedicated to the Public Domain.
     1.5 + * http://creativecommons.org/publicdomain/zero/1.0/
     1.6 + */
     1.7 +
     1.8 +#ifdef XP_WIN
     1.9 +# include <windows.h>
    1.10 +# include <wintrust.h>
    1.11 +# include <tlhelp32.h>
    1.12 +# include <softpub.h>
    1.13 +# include <direct.h>
    1.14 +# include <io.h>
    1.15 +  typedef WCHAR NS_tchar;
    1.16 +# define NS_main wmain
    1.17 +# define F_OK 00
    1.18 +# define W_OK 02
    1.19 +# define R_OK 04
    1.20 +# define stat _stat
    1.21 +# define NS_T(str) L ## str
    1.22 +# define NS_tsnprintf(dest, count, fmt, ...) \
    1.23 +  { \
    1.24 +    int _count = count - 1; \
    1.25 +    _snwprintf(dest, _count, fmt, ##__VA_ARGS__); \
    1.26 +    dest[_count] = L'\0'; \
    1.27 +  }
    1.28 +# define NS_taccess _waccess
    1.29 +# define NS_tchdir _wchdir
    1.30 +# define NS_tfopen _wfopen
    1.31 +# define NS_tstrcmp wcscmp
    1.32 +# define NS_ttoi _wtoi
    1.33 +# define NS_tstat _wstat
    1.34 +# define NS_tgetcwd _wgetcwd
    1.35 +# define LOG_S "%S"
    1.36 +
    1.37 +#include "../common/updatehelper.h"
    1.38 +
    1.39 +#else
    1.40 +# include <unistd.h>
    1.41 +# define NS_main main
    1.42 +  typedef char NS_tchar;
    1.43 +# define NS_T(str) str
    1.44 +# define NS_tsnprintf snprintf
    1.45 +# define NS_taccess access
    1.46 +# define NS_tchdir chdir
    1.47 +# define NS_tfopen fopen
    1.48 +# define NS_tstrcmp strcmp
    1.49 +# define NS_ttoi atoi
    1.50 +# define NS_tstat stat
    1.51 +# define NS_tgetcwd getcwd
    1.52 +# define NS_tfputs fputs
    1.53 +# define LOG_S "%s"
    1.54 +#endif
    1.55 +
    1.56 +#include "mozilla/NullPtr.h"
    1.57 +#include <stdlib.h>
    1.58 +#include <stdio.h>
    1.59 +#include <string.h>
    1.60 +#include <sys/types.h>
    1.61 +#include <sys/stat.h>
    1.62 +
    1.63 +#ifndef MAXPATHLEN
    1.64 +# ifdef PATH_MAX
    1.65 +#  define MAXPATHLEN PATH_MAX
    1.66 +# elif defined(MAX_PATH)
    1.67 +#  define MAXPATHLEN MAX_PATH
    1.68 +# elif defined(_MAX_PATH)
    1.69 +#  define MAXPATHLEN _MAX_PATH
    1.70 +# elif defined(CCHMAXPATH)
    1.71 +#  define MAXPATHLEN CCHMAXPATH
    1.72 +# else
    1.73 +#  define MAXPATHLEN 1024
    1.74 +# endif
    1.75 +#endif
    1.76 +
    1.77 +static void
    1.78 +WriteMsg(const NS_tchar *path, const char *status)
    1.79 +{
    1.80 +  FILE* outFP = NS_tfopen(path, NS_T("wb"));
    1.81 +  if (!outFP)
    1.82 +    return;
    1.83 +
    1.84 +  fprintf(outFP, "%s\n", status);
    1.85 +  fclose(outFP);
    1.86 +  outFP = nullptr;
    1.87 +}
    1.88 +
    1.89 +static bool
    1.90 +CheckMsg(const NS_tchar *path, const char *expected)
    1.91 +{
    1.92 +  if (NS_taccess(path, F_OK)) {
    1.93 +    return false;
    1.94 +  }
    1.95 +
    1.96 +  FILE *inFP = NS_tfopen(path, NS_T("rb"));
    1.97 +  if (!inFP) {
    1.98 +    return false;
    1.99 +  }
   1.100 +
   1.101 +  struct stat ms;
   1.102 +  if (fstat(fileno(inFP), &ms)) {
   1.103 +    return false;
   1.104 +  }
   1.105 +
   1.106 +  char *mbuf = (char *) malloc(ms.st_size + 1);
   1.107 +  if (!mbuf) {
   1.108 +    return false;
   1.109 +  }
   1.110 +
   1.111 +  size_t r = ms.st_size;
   1.112 +  char *rb = mbuf;
   1.113 +  size_t c = fread(rb, sizeof(char), 50, inFP);
   1.114 +  r -= c;
   1.115 +  rb += c;
   1.116 +  if (c == 0 && r) {
   1.117 +    return false;
   1.118 +  }
   1.119 +  mbuf[ms.st_size] = '\0';
   1.120 +  rb = mbuf;
   1.121 +
   1.122 +  fclose(inFP);
   1.123 +  inFP = nullptr;
   1.124 +  return strcmp(rb, expected) == 0;
   1.125 +}
   1.126 +
   1.127 +#ifdef XP_WIN
   1.128 +/**
   1.129 + * Verifies the trust of the specified file path.
   1.130 + *
   1.131 + * @param  filePath  The file path to check.
   1.132 + * @return ERROR_SUCCESS if successful, or the last error code otherwise.
   1.133 + */
   1.134 +DWORD
   1.135 +VerifyCertificateTrustForFile(LPCWSTR filePath)
   1.136 +{
   1.137 +  // Setup the file to check.
   1.138 +  WINTRUST_FILE_INFO fileToCheck;
   1.139 +  ZeroMemory(&fileToCheck, sizeof(fileToCheck));
   1.140 +  fileToCheck.cbStruct = sizeof(WINTRUST_FILE_INFO);
   1.141 +  fileToCheck.pcwszFilePath = filePath;
   1.142 +
   1.143 +  // Setup what to check, we want to check it is signed and trusted.
   1.144 +  WINTRUST_DATA trustData;
   1.145 +  ZeroMemory(&trustData, sizeof(trustData));
   1.146 +  trustData.cbStruct = sizeof(trustData);
   1.147 +  trustData.pPolicyCallbackData = nullptr;
   1.148 +  trustData.pSIPClientData = nullptr;
   1.149 +  trustData.dwUIChoice = WTD_UI_NONE;
   1.150 +  trustData.fdwRevocationChecks = WTD_REVOKE_NONE; 
   1.151 +  trustData.dwUnionChoice = WTD_CHOICE_FILE;
   1.152 +  trustData.dwStateAction = 0;
   1.153 +  trustData.hWVTStateData = nullptr;
   1.154 +  trustData.pwszURLReference = nullptr;
   1.155 +  // no UI
   1.156 +  trustData.dwUIContext = 0;
   1.157 +  trustData.pFile = &fileToCheck;
   1.158 +
   1.159 +  GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
   1.160 +  // Check if the file is signed by something that is trusted.
   1.161 +  return WinVerifyTrust(nullptr, &policyGUID, &trustData);
   1.162 +}
   1.163 +
   1.164 +#endif
   1.165 +
   1.166 +int NS_main(int argc, NS_tchar **argv)
   1.167 +{
   1.168 +
   1.169 +  if (argc < 3) {
   1.170 +    fprintf(stderr, \
   1.171 +            "\n" \
   1.172 +            "Application Update Service Test Helper\n" \
   1.173 +            "\n" \
   1.174 +            "Usage: WORKINGDIR INFILE OUTFILE -s SECONDS [FILETOLOCK]\n"  \
   1.175 +            "   or: WORKINGDIR LOGFILE [ARG2 ARG3...]\n" \
   1.176 +            "   or: signature-check filepath\n" \
   1.177 +            "   or: setup-symlink dir1 dir2 file symlink\n" \
   1.178 +            "   or: remove-symlink dir1 dir2 file symlink\n" \
   1.179 +            "   or: check-symlink symlink\n" \
   1.180 +            "\n" \
   1.181 +            "  WORKINGDIR  \tThe relative path to the working directory to use.\n" \
   1.182 +            "  INFILE      \tThe relative path from the working directory for the file to\n" \
   1.183 +            "              \tread actions to perform such as finish.\n" \
   1.184 +            "  OUTFILE     \tThe relative path from the working directory for the file to\n" \
   1.185 +            "              \twrite status information.\n" \
   1.186 +            "  SECONDS     \tThe number of seconds to sleep.\n" \
   1.187 +            "  FILETOLOCK  \tThe relative path from the working directory to an existing\n" \
   1.188 +            "              \tfile to open exlusively.\n" \
   1.189 +            "              \tOnly available on Windows platforms and silently ignored on\n" \
   1.190 +            "              \tother platforms.\n" \
   1.191 +            "  LOGFILE     \tThe relative path from the working directory to log the\n" \
   1.192 +            "              \tcommand line arguments.\n" \
   1.193 +            "  ARG2 ARG3...\tArguments to write to the LOGFILE after the preceding command\n" \
   1.194 +            "              \tline arguments.\n" \
   1.195 +            "\n" \
   1.196 +            "Note: All paths must be relative.\n" \
   1.197 +            "\n");
   1.198 +    return 1;
   1.199 +  }
   1.200 +
   1.201 +  if (!NS_tstrcmp(argv[1], NS_T("check-signature"))) {
   1.202 +#ifdef XP_WIN
   1.203 +    if (ERROR_SUCCESS == VerifyCertificateTrustForFile(argv[2])) {
   1.204 +      return 0;
   1.205 +    } else {
   1.206 +      return 1;
   1.207 +    }
   1.208 +#else 
   1.209 +    // Not implemented on non-Windows platforms
   1.210 +    return 1;
   1.211 +#endif
   1.212 +  }
   1.213 +
   1.214 +  if (!NS_tstrcmp(argv[1], NS_T("setup-symlink"))) {
   1.215 +#ifdef XP_UNIX
   1.216 +    NS_tchar path[MAXPATHLEN];
   1.217 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.218 +                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
   1.219 +    mkdir(path, 0755);
   1.220 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.221 +                 NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
   1.222 +    mkdir(path, 0755);
   1.223 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.224 +                 NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
   1.225 +    FILE * file = NS_tfopen(path, NS_T("w"));
   1.226 +    if (file) {
   1.227 +      NS_tfputs(NS_T("test"), file);
   1.228 +      fclose(file);
   1.229 +    }
   1.230 +    symlink(path, argv[5]);
   1.231 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.232 +                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
   1.233 +    if (argc > 6 && !NS_tstrcmp(argv[6], NS_T("change-perm"))) {
   1.234 +      chmod(path, 0644);
   1.235 +    }
   1.236 +    return 0;
   1.237 +#else
   1.238 +    // Not implemented on non-Unix platforms
   1.239 +    return 1;
   1.240 +#endif
   1.241 +  }
   1.242 +
   1.243 +  if (!NS_tstrcmp(argv[1], NS_T("remove-symlink"))) {
   1.244 +#ifdef XP_UNIX
   1.245 +    NS_tchar path[MAXPATHLEN];
   1.246 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.247 +                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
   1.248 +    chmod(path, 0755);
   1.249 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.250 +                 NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
   1.251 +    unlink(path);
   1.252 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.253 +                 NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
   1.254 +    rmdir(path);
   1.255 +    NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
   1.256 +                 NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
   1.257 +    rmdir(path);
   1.258 +    return 0;
   1.259 +#else
   1.260 +    // Not implemented on non-Unix platforms
   1.261 +    return 1;
   1.262 +#endif
   1.263 +  }
   1.264 +
   1.265 +  if (!NS_tstrcmp(argv[1], NS_T("check-symlink"))) {
   1.266 +#ifdef XP_UNIX
   1.267 +    struct stat ss;
   1.268 +    lstat(argv[2], &ss);
   1.269 +    return S_ISLNK(ss.st_mode) ? 0 : 1;
   1.270 +#else
   1.271 +    // Not implemented on non-Unix platforms
   1.272 +    return 1;
   1.273 +#endif
   1.274 +  }
   1.275 +
   1.276 +  if (!NS_tstrcmp(argv[1], NS_T("wait-for-service-stop"))) {
   1.277 +#ifdef XP_WIN
   1.278 +    const int maxWaitSeconds = NS_ttoi(argv[3]);
   1.279 +    LPCWSTR serviceName = argv[2];
   1.280 +    DWORD serviceState = WaitForServiceStop(serviceName, maxWaitSeconds);
   1.281 +    if (SERVICE_STOPPED == serviceState) {
   1.282 +      return 0;
   1.283 +    } else {
   1.284 +      return serviceState;
   1.285 +    }
   1.286 +#else 
   1.287 +    // Not implemented on non-Windows platforms
   1.288 +    return 1;
   1.289 +#endif
   1.290 +  }
   1.291 +
   1.292 +  if (!NS_tstrcmp(argv[1], NS_T("wait-for-application-exit"))) {
   1.293 +#ifdef XP_WIN
   1.294 +    const int maxWaitSeconds = NS_ttoi(argv[3]);
   1.295 +    LPCWSTR application = argv[2];
   1.296 +    DWORD ret = WaitForProcessExit(application, maxWaitSeconds);
   1.297 +    if (ERROR_SUCCESS == ret) {
   1.298 +      return 0;
   1.299 +    } else if (WAIT_TIMEOUT == ret) {
   1.300 +      return 1;
   1.301 +    } else {
   1.302 +      return 2;
   1.303 +    }
   1.304 +#else 
   1.305 +    // Not implemented on non-Windows platforms
   1.306 +    return 1;
   1.307 +#endif
   1.308 +  }
   1.309 +
   1.310 +  int i = 0;
   1.311 +
   1.312 +  if (NS_tchdir(argv[1]) != 0) {
   1.313 +    return 1;
   1.314 +  }
   1.315 +
   1.316 +  // File in use test helper section
   1.317 +  if (!NS_tstrcmp(argv[4], NS_T("-s"))) {
   1.318 +    NS_tchar *cwd = NS_tgetcwd(nullptr, 0);
   1.319 +    NS_tchar inFilePath[MAXPATHLEN];
   1.320 +    NS_tsnprintf(inFilePath, sizeof(inFilePath)/sizeof(inFilePath[0]),
   1.321 +                 NS_T("%s/%s"), cwd, argv[2]);
   1.322 +    NS_tchar outFilePath[MAXPATHLEN];
   1.323 +    NS_tsnprintf(outFilePath, sizeof(outFilePath)/sizeof(outFilePath[0]),
   1.324 +                 NS_T("%s/%s"), cwd, argv[3]);
   1.325 +
   1.326 +    int seconds = NS_ttoi(argv[5]);
   1.327 +#ifdef XP_WIN
   1.328 +    HANDLE hFile = INVALID_HANDLE_VALUE;
   1.329 +    if (argc == 7) {
   1.330 +      hFile = CreateFileW(argv[6],
   1.331 +                          DELETE | GENERIC_WRITE, 0,
   1.332 +                          nullptr, OPEN_EXISTING, 0, nullptr);
   1.333 +      if (hFile == INVALID_HANDLE_VALUE) {
   1.334 +        WriteMsg(outFilePath, "error_locking");
   1.335 +        return 1;
   1.336 +      }
   1.337 +    }
   1.338 +
   1.339 +    WriteMsg(outFilePath, "sleeping");
   1.340 +    while (!CheckMsg(inFilePath, "finish\n") && i++ <= seconds)  {
   1.341 +      Sleep(1000);
   1.342 +    }
   1.343 +
   1.344 +    if (argc == 7) {
   1.345 +      CloseHandle(hFile);
   1.346 +    }
   1.347 +#else
   1.348 +    WriteMsg(outFilePath, "sleeping");
   1.349 +    while (!CheckMsg(inFilePath, "finish\n") && i++ <= seconds)  {
   1.350 +      sleep(1);
   1.351 +    }
   1.352 +#endif
   1.353 +    WriteMsg(outFilePath, "finished");
   1.354 +    return 0;
   1.355 +  }
   1.356 +
   1.357 +  // Command line argument test helper section
   1.358 +  NS_tchar logFilePath[MAXPATHLEN];
   1.359 +  NS_tsnprintf(logFilePath, sizeof(logFilePath)/sizeof(logFilePath[0]),
   1.360 +               NS_T("%s"), argv[2]);
   1.361 +
   1.362 +  FILE* logFP = NS_tfopen(logFilePath, NS_T("wb"));
   1.363 +  for (i = 1; i < argc; ++i) {
   1.364 +    fprintf(logFP, LOG_S "\n", argv[i]);
   1.365 +  }
   1.366 +
   1.367 +  fclose(logFP);
   1.368 +  logFP = nullptr;
   1.369 +
   1.370 +  return 0;
   1.371 +} 

mercurial