Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

349 lines
11 KiB

  1. /*
  2. * s a f e r u n . c p p
  3. *
  4. * Purpose:
  5. * Athena's version of shdocvw's saferun dialog
  6. *
  7. * Owner:
  8. * brettm.
  9. *
  10. * History:
  11. * Created: March 1997
  12. *
  13. * Copyright (C) Microsoft Corp. 1996.
  14. */
  15. #include "pch.hxx"
  16. #include <pch.hxx>
  17. #include "dllmain.h"
  18. #include "resource.h"
  19. #include "util.h"
  20. #include "attrun.h"
  21. #include "saferun.h"
  22. #include "strconst.h"
  23. #include <wintrust.h>
  24. #include "demand.h"
  25. #include "shlwapip.h"
  26. /*
  27. * c o n s t a n t s
  28. */
  29. #define FTA_OpenIsSafe 0x00010000 // 17. the file class's open verb may be safely invoked for downloaded files
  30. #define FTA_NoEdit 0x00000008 // 4. no editing of file type
  31. /*
  32. * t y p e d e f s
  33. */
  34. typedef struct SAFEOPENPARAM_tag
  35. {
  36. LPCWSTR lpszFileName;
  37. LPCWSTR lpszFileClass;
  38. LPCWSTR lpszExt;
  39. HRESULT hr;
  40. } SAFEOPENPARAM, *LPSAFEOPENPARAM;
  41. /*
  42. * p r o t o t y p e s
  43. */
  44. LRESULT SetRegKeyValue(HKEY hkeyParent, PCWSTR pcszSubKey, LPCWSTR pcszValue, DWORD dwType, const BYTE *pcbyte, DWORD dwcb);
  45. LRESULT GetRegKeyValue(HKEY hkeyParent, PCWSTR pcszSubKey, PCWSTR pcszValue, PDWORD pdwValueType, PBYTE pbyteBuf, PDWORD pdwcbBufLen);
  46. BOOL RememberFileIsSafeToOpen(LPCWSTR szFileClass);
  47. BOOL FIsExtBad(LPCWSTR lpszExt);
  48. HRESULT SafeOpenDialog(HWND hwnd, LPSAFEOPENPARAM pSafeOpen);
  49. INT_PTR CALLBACK SafeOpenDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  50. /*
  51. * return codes:
  52. * S_OPENFILE : file should be opened
  53. * S_SAVEFILE : file should be saved
  54. *
  55. * errors:
  56. * E_FAIL, E_INVALIDARG, hrUserCancel
  57. *
  58. */
  59. HRESULT IsSafeToRun(HWND hwnd, LPCWSTR lpszFileName, BOOL fPrompt)
  60. {
  61. BOOL fSafe;
  62. DWORD dwValueType,
  63. dwEditFlags;
  64. ULONG cb;
  65. WCHAR *szExt,
  66. szFileClass[MAX_PATH];
  67. SAFEOPENPARAM rSafeOpen={0};
  68. if (lpszFileName == NULL || *lpszFileName == NULL)
  69. return E_INVALIDARG;
  70. *szFileClass = 0;
  71. szExt = PathFindExtensionW(lpszFileName);
  72. if (*szExt)
  73. {
  74. cb = sizeof(szFileClass);
  75. RegQueryValueWrapW(HKEY_CLASSES_ROOT, szExt, szFileClass, (LONG*)&cb);
  76. }
  77. cb = sizeof(dwEditFlags);
  78. // $34489. Make HTML files ALWAYS unsafe
  79. if (PathIsHTMLFileW(lpszFileName))
  80. fSafe = FALSE;
  81. else
  82. fSafe = ((GetRegKeyValue(HKEY_CLASSES_ROOT, szFileClass, L"EditFlags", &dwValueType, (PBYTE)&dwEditFlags, &cb) == ERROR_SUCCESS) &&
  83. (dwValueType == REG_BINARY || dwValueType == REG_DWORD) &&
  84. (dwEditFlags & FTA_OpenIsSafe)) && !FIsExtBad(szExt);
  85. rSafeOpen.lpszFileName = lpszFileName;
  86. rSafeOpen.lpszFileClass = szFileClass;
  87. rSafeOpen.lpszExt = szExt;
  88. return fSafe ? MIMEEDIT_S_OPENFILE : (fPrompt ? SafeOpenDialog(hwnd, &rSafeOpen) : MIMEEDIT_E_USERCANCEL);
  89. }
  90. HRESULT SafeOpenDialog(HWND hwnd, LPSAFEOPENPARAM pSafeOpen)
  91. {
  92. pSafeOpen->hr = E_FAIL; // incase we fail
  93. DialogBoxParamWrapW(g_hLocRes, MAKEINTRESOURCEW(iddSafeOpen), hwnd, SafeOpenDlgProc, (LPARAM)pSafeOpen);
  94. return pSafeOpen->hr;
  95. }
  96. #define MAXDISPLAYNAMELEN 64
  97. INT_PTR CALLBACK SafeOpenDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  98. {
  99. LPSAFEOPENPARAM pSafeOpen;
  100. switch(msg)
  101. {
  102. case WM_INITDIALOG:
  103. {
  104. Assert (lParam);
  105. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  106. pSafeOpen = (LPSAFEOPENPARAM)lParam;
  107. // if an UNSAFE extension type, don't allow user to set edit flags
  108. if (FIsExtBad(pSafeOpen->lpszExt))
  109. EnableWindow(GetDlgItem(hwnd, IDC_SAFEOPEN_ALWAYS), FALSE);
  110. CheckDlgButton(hwnd, IDC_SAFEOPEN_ALWAYS, TRUE);
  111. CheckDlgButton(hwnd, IDC_SAFEOPEN_AUTOSAVE, TRUE);
  112. WCHAR szBuf[32];
  113. WCHAR szBuf2[MAX_PATH+32]; // ok with MAX_PATH
  114. WCHAR szBuf3[MAX_PATH+32]; // ok with MAX_PATH
  115. int length = 0;
  116. StrCpyNW(szBuf3, pSafeOpen->lpszFileName, ARRAYSIZE(szBuf3));
  117. PathStripPathW(szBuf3);
  118. length = lstrlenW(szBuf3);
  119. if (length > MAXDISPLAYNAMELEN)
  120. {
  121. WCHAR *szExt;
  122. szExt = PathFindExtensionW(pSafeOpen->lpszFileName);
  123. if (*szExt)
  124. {
  125. int cExt = lstrlenW(szExt);
  126. if (cExt < MAXDISPLAYNAMELEN-3)
  127. {
  128. PathCompactPathExW(szBuf2, szBuf3, MAXDISPLAYNAMELEN-cExt, 0);
  129. StrCatBuffW(szBuf2, szExt, ARRAYSIZE(szBuf2));
  130. }
  131. else
  132. PathCompactPathExW(szBuf2, szBuf3, MAXDISPLAYNAMELEN, 0);
  133. }
  134. else
  135. {
  136. PathCompactPathExW(szBuf2, szBuf3, MAXDISPLAYNAMELEN, 0);
  137. }
  138. StrCpyNW(szBuf3, szBuf2, ARRAYSIZE(szBuf3));
  139. }
  140. GetDlgItemTextWrapW(hwnd, IDC_SAFEOPEN_EXPL, szBuf, ARRAYSIZE(szBuf));
  141. wnsprintfW(szBuf2, ARRAYSIZE(szBuf2), szBuf, szBuf3);
  142. SetDlgItemTextWrapW(hwnd, IDC_SAFEOPEN_EXPL, szBuf2);
  143. CenterDialog(hwnd);
  144. }
  145. return TRUE;
  146. case WM_COMMAND:
  147. switch (GET_WM_COMMAND_ID(wParam, lParam))
  148. {
  149. case IDOK:
  150. pSafeOpen = (LPSAFEOPENPARAM)GetWindowLongPtr(hwnd, DWLP_USER);
  151. if (!IsDlgButtonChecked(hwnd, IDC_SAFEOPEN_ALWAYS))
  152. RememberFileIsSafeToOpen(pSafeOpen->lpszFileClass);
  153. pSafeOpen->hr = IsDlgButtonChecked(hwnd, IDC_SAFEOPEN_AUTOSAVE) ? MIMEEDIT_S_SAVEFILE : MIMEEDIT_S_OPENFILE;
  154. EndDialog(hwnd, IDOK);
  155. break;
  156. case IDCANCEL:
  157. pSafeOpen = (LPSAFEOPENPARAM)GetWindowLongPtr(hwnd, DWLP_USER);
  158. pSafeOpen->hr = MIMEEDIT_E_USERCANCEL;
  159. EndDialog(hwnd, IDCANCEL);
  160. break;
  161. }
  162. break;
  163. }
  164. return FALSE;
  165. }
  166. LRESULT GetRegKeyValue(HKEY hkeyParent, PCWSTR pcszSubKey, PCWSTR pcszValue, PDWORD pdwValueType, PBYTE pbyteBuf, PDWORD pdwcbBufLen)
  167. {
  168. LONG lResult;
  169. HKEY hkeySubKey;
  170. if (GetSystemMetrics(SM_CLEANBOOT))
  171. return ERROR_GEN_FAILURE;
  172. lResult = RegOpenKeyExWrapW(hkeyParent, pcszSubKey, 0, KEY_QUERY_VALUE, &hkeySubKey);
  173. if (lResult == ERROR_SUCCESS)
  174. {
  175. LONG lResultClose;
  176. lResult = RegQueryValueExWrapW(hkeySubKey, pcszValue, NULL, pdwValueType,
  177. pbyteBuf, pdwcbBufLen);
  178. lResultClose = RegCloseKey(hkeySubKey);
  179. if (lResult == ERROR_SUCCESS)
  180. lResult = lResultClose;
  181. }
  182. return(lResult);
  183. }
  184. LRESULT SetRegKeyValue(HKEY hkeyParent, PCWSTR pcszSubKey, LPCWSTR pcszValue, DWORD dwType, const BYTE *pcbyte, DWORD dwcb)
  185. {
  186. LONG lResult;
  187. HKEY hkeySubKey;
  188. lResult = RegCreateKeyExWrapW(hkeyParent, pcszSubKey, 0, NULL, 0, KEY_SET_VALUE,
  189. NULL, &hkeySubKey, NULL);
  190. if (lResult == ERROR_SUCCESS)
  191. {
  192. LONG lResultClose;
  193. lResult = RegSetValueExWrapW(hkeySubKey, pcszValue, 0, dwType, pcbyte, dwcb);
  194. lResultClose = RegCloseKey(hkeySubKey);
  195. if (lResult == ERROR_SUCCESS)
  196. lResult = lResultClose;
  197. }
  198. return(lResult);
  199. }
  200. BOOL RememberFileIsSafeToOpen(LPCWSTR szFileClass)
  201. {
  202. DWORD dwValueType, dwEditFlags;
  203. ULONG cb = sizeof(dwEditFlags);
  204. if (szFileClass==NULL || *szFileClass == NULL)
  205. return FALSE;
  206. if (GetRegKeyValue(HKEY_CLASSES_ROOT, szFileClass, L"EditFlags",
  207. &dwValueType, (PBYTE)&dwEditFlags, &cb) == ERROR_SUCCESS &&
  208. (dwValueType == REG_BINARY || dwValueType == REG_DWORD))
  209. {
  210. dwEditFlags &= ~FTA_NoEdit;
  211. dwEditFlags |= FTA_OpenIsSafe;
  212. }
  213. else
  214. {
  215. dwEditFlags = FTA_OpenIsSafe;
  216. }
  217. return (SetRegKeyValue(HKEY_CLASSES_ROOT, szFileClass, L"EditFlags",
  218. REG_BINARY, (BYTE*)&dwEditFlags,
  219. sizeof(dwEditFlags)) == ERROR_SUCCESS);
  220. }
  221. // Keep in sync with c_arszUnsafeExts in shell\shdocvw\download.cpp
  222. // @todo [NeilBren, TonyC] Move this to the registry and have IE and OE share it
  223. static const LPWSTR szBadExt[] =
  224. { L".exe", L".com", L".bat", L".lnk", L".url",
  225. L".cmd", L".inf", L".reg", L".isp", L".bas", L".pcd",
  226. L".mst", L".pif", L".scr", L".hlp", L".chm", L".hta", L".asp",
  227. L".js", L".jse", L".vbs", L".vbe", L".ws", L".wsh", L".msi",
  228. L".ade", L".adp", L".crt", L".ins", L".mdb",
  229. L".mde", L".msc", L".msp", L".sct", L".shb",
  230. L".vb", L".wsc", L".wsf", L".cpl", L".shs",
  231. L".vsd", L".vst", L".vss", L".vsw", L".its", L".tmp",
  232. L".mdw", L".mdt", L".ops", L".mda", L".mdz", L".prf",
  233. L".scf", L".ksh", L".csh", L".app", L".fxp", L".prg",
  234. L".htm", L".html",L".vsmacros"
  235. };
  236. BOOL FIsExtBad(LPCWSTR lpszExt)
  237. {
  238. if (lpszExt == NULL || *lpszExt == NULL)
  239. return TRUE;
  240. for (int i=0; i<ARRAYSIZE(szBadExt); i++)
  241. if (StrCmpIW(lpszExt, szBadExt[i]) == 0)
  242. return TRUE;
  243. return FALSE;
  244. }
  245. // Returns:
  246. //
  247. // IDOK -- If it's trusted
  248. // IDNO -- If it's not known (warning dialog requried)
  249. // IDCANCEL -- We need to stop download it
  250. //
  251. HRESULT VerifyTrust(HWND hwnd, LPCWSTR pszFileName, LPCWSTR pszPathName)
  252. {
  253. UINT uRet = IDNO; // assume unknown
  254. HANDLE hFile;
  255. HRESULT hr=E_FAIL;
  256. WCHAR *szExt;
  257. if (pszFileName==NULL || *pszFileName==NULL || pszPathName==NULL || *pszPathName==NULL)
  258. return S_OK; // REVIEW$: ?? should I fail if these are NULL ??
  259. szExt = PathFindExtensionW(pszFileName);
  260. if (StrCmpIW(szExt, c_szExeExt) != 0) // don't check for non-exe's
  261. return S_OK;
  262. hFile = CreateFileWrapW(pszPathName, GENERIC_READ, FILE_SHARE_READ,
  263. NULL, OPEN_EXISTING,
  264. FILE_ATTRIBUTE_NORMAL, 0);
  265. if (hFile == INVALID_HANDLE_VALUE)
  266. return E_HANDLE;
  267. GUID PublishedSoftware = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
  268. GUID SubjectPeImage = WIN_TRUST_SUBJTYPE_PE_IMAGE;
  269. WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT ActionData;
  270. WIN_TRUST_SUBJECT_FILE Subject;
  271. Subject.hFile = hFile;
  272. Subject.lpPath = pszFileName;
  273. ActionData.SubjectType = &SubjectPeImage;
  274. ActionData.Subject = &Subject;
  275. ActionData.hClientToken = NULL;
  276. hr = WinVerifyTrust(hwnd, &PublishedSoftware, &ActionData);
  277. CloseHandle(hFile);
  278. return hr;
  279. }