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 +}