PageRenderTime 25ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/qwaqvm/platforms/win32/plugins/SecurityPlugin/sqWin32Security.c

http://openqwaq.googlecode.com/
C | 344 lines | 238 code | 46 blank | 60 comment | 68 complexity | ca9407e9767adca8441bcc21bc2bdf54 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0, BSD-3-Clause
  1. #include <windows.h>
  2. #include <shlobj.h> /* CSIDL_XXX */
  3. #include "sq.h"
  4. #ifndef HKEY_SQUEAK_ROOT
  5. /* the default place in the registry to look for */
  6. #define HKEY_SQUEAK_ROOT "SOFTWARE\\Squeak"
  7. #endif
  8. /*
  9. 15 June 2008 - Changed to use SHGetFolderPath() instead of GetProcAddress() version, at
  10. least for MSC - MinGW doesn't have it yet. Also added code for SHGetKnownFolderPath()
  11. which MSC doc says is preferred over SHGetFolderPath() for Vista and beyond; put behind an
  12. ifdef for now - could be #ifdef'd for Vista
  13. -- jdm
  14. */
  15. #ifdef _MSC_VER
  16. # if _MSC_VER < 1300 // VC6 declares SHGetFolderPath but lacks the import lib
  17. # define USE_DYNAMIC_SHGETFOLDERPATH
  18. # else
  19. # if WINVER>=0x0600 // Vista
  20. // UNTESTED - #define USE_GETKNOWNFOLDERPATH
  21. # else
  22. // use SHGetFolderPath() function defined in ShFolder.lib
  23. # endif
  24. # endif /* _MSC_VER < 1300 */
  25. #else
  26. // As of this writing (June 2008) MinGW doesn't support SHGetFolderPath(), requiring the old-style
  27. // shGetFolderPath = GetProcAddress(LoadLibrary("SHFolder.dll"));
  28. # define USE_DYNAMIC_SHGETFOLDERPATH
  29. #endif
  30. #ifdef USE_GETKNOWNFOLDERPATH
  31. #include "knownfolders.h"
  32. #endif
  33. #ifdef USE_DYNAMIC_SHGETFOLDERPATH
  34. static HRESULT (__stdcall *shGetFolderPath)(HWND, int, HANDLE, DWORD, WCHAR*);
  35. #endif
  36. static TCHAR untrustedUserDirectory[MAX_PATH];
  37. static TCHAR secureUserDirectory[MAX_PATH];
  38. /* imported from sqWin32Prefs.c */
  39. extern TCHAR squeakIniName[MAX_PATH];
  40. /***************************************************************************/
  41. /***************************************************************************/
  42. /***************************************************************************/
  43. /***************************************************************************/
  44. /* file security */
  45. static int allowFileAccess = 1; /* full access to files */
  46. static const TCHAR U_DOT[] = TEXT(".");
  47. static int isAccessiblePathName(TCHAR *pathName) {
  48. int i;
  49. /* Check if the path/file name is subdirectory of the image path */
  50. for(i=0; i<lstrlen(untrustedUserDirectory)-1; i++)
  51. if(untrustedUserDirectory[i] != pathName[i]) return 0;
  52. /* special check for the trusted directory */
  53. if(pathName[i] == 0) return 1; /* allow access to trusted directory */
  54. /* check last character in image path (e.g., backslash) */
  55. if(untrustedUserDirectory[i] != pathName[i]) return 0;
  56. /* check if somebody wants to trick us into using relative
  57. paths ala c:\My Squeak\allowed\..\..\" */
  58. while(pathName[i]) {
  59. if(pathName[i] == U_DOT[0]) {
  60. if(pathName[i+1] == U_DOT[0])
  61. return 0; /* Gotcha! */
  62. }
  63. i++;
  64. }
  65. return 1;
  66. }
  67. static int isAccessibleFileName(TCHAR *fileName) {
  68. int i;
  69. /* Check if the path/file name is subdirectory of the image path */
  70. for(i=0; i<lstrlen(untrustedUserDirectory); i++)
  71. if(untrustedUserDirectory[i] != fileName[i]) return 0;
  72. /* check if somebody wants to trick us into using relative
  73. paths ala c:\My Squeak\allowed\..\..\" */
  74. while(fileName[i]) {
  75. if(fileName[i] == U_DOT[0]) {
  76. if(fileName[i+1] == U_DOT[0])
  77. return 0; /* Gotcha! */
  78. }
  79. i++;
  80. }
  81. return 1;
  82. }
  83. /* directory access */
  84. int ioCanCreatePathOfSize(char* pathString, int pathStringLength) {
  85. if(allowFileAccess) return 1;
  86. return isAccessiblePathName(fromSqueak(pathString, pathStringLength));
  87. }
  88. int ioCanListPathOfSize(char* pathString, int pathStringLength) {
  89. if(allowFileAccess) return 1;
  90. return isAccessiblePathName(fromSqueak(pathString, pathStringLength));
  91. }
  92. int ioCanDeletePathOfSize(char* pathString, int pathStringLength) {
  93. if(allowFileAccess) return 1;
  94. return isAccessiblePathName(fromSqueak(pathString, pathStringLength));
  95. }
  96. /* file access */
  97. int ioCanOpenFileOfSizeWritable(char* pathString, int pathStringLength, int writeFlag) {
  98. if(allowFileAccess) return 1;
  99. return isAccessibleFileName(fromSqueak(pathString, pathStringLength));
  100. }
  101. int ioCanOpenAsyncFileOfSizeWritable(char* pathString, int pathStringLength, int writeFlag) {
  102. return ioCanOpenFileOfSizeWritable(pathString,pathStringLength,writeFlag);
  103. }
  104. int ioCanDeleteFileOfSize(char* pathString, int pathStringLength) {
  105. if(allowFileAccess) return 1;
  106. return isAccessibleFileName(fromSqueak(pathString, pathStringLength));
  107. }
  108. int ioCanRenameFileOfSize(char* pathString, int pathStringLength) {
  109. if(allowFileAccess) return 1;
  110. return isAccessibleFileName(fromSqueak(pathString, pathStringLength));
  111. }
  112. int ioCanGetFileTypeOfSize(char* pathString, int pathStringLength) {
  113. return 1; /* of no importance here */
  114. }
  115. int ioCanSetFileTypeOfSize(char* pathString, int pathStringLength) {
  116. return 1; /* of no importance here */
  117. }
  118. /* disabling/querying */
  119. int ioDisableFileAccess(void) {
  120. allowFileAccess = 0;
  121. }
  122. int ioHasFileAccess(void) {
  123. return allowFileAccess;
  124. }
  125. /***************************************************************************/
  126. /***************************************************************************/
  127. /***************************************************************************/
  128. /***************************************************************************/
  129. /* image security */
  130. static int allowImageWrite = 1; /* allow writing the image */
  131. int ioCanRenameImage(void) {
  132. return allowImageWrite; /* only when we're allowed to save the image */
  133. }
  134. int ioCanWriteImage(void) {
  135. return allowImageWrite;
  136. }
  137. int ioDisableImageWrite(void) {
  138. allowImageWrite = 0;
  139. }
  140. /***************************************************************************/
  141. /***************************************************************************/
  142. /***************************************************************************/
  143. /***************************************************************************/
  144. /* socket security - for now it's all or nothing */
  145. static int allowSocketAccess = 1; /* allow access to sockets */
  146. int ioCanCreateSocketOfType(int netType, int socketType) {
  147. return allowSocketAccess;
  148. }
  149. int ioCanConnectToPort(int netAddr, int port) {
  150. return allowSocketAccess;
  151. }
  152. int ioCanListenOnPort(void* s, int port) {
  153. return allowSocketAccess;
  154. }
  155. int ioDisableSocketAccess() {
  156. allowSocketAccess = 0;
  157. }
  158. int ioHasSocketAccess() {
  159. return allowSocketAccess;
  160. }
  161. /***************************************************************************/
  162. /***************************************************************************/
  163. /***************************************************************************/
  164. /***************************************************************************/
  165. /* SecurityPlugin primitive support */
  166. char *ioGetSecureUserDirectory(void) {
  167. return secureUserDirectory;
  168. }
  169. char *ioGetUntrustedUserDirectory(void) {
  170. return untrustedUserDirectory;
  171. }
  172. /* note: following is called from VM directly, not from plugin */
  173. int ioInitSecurity(void) {
  174. DWORD dwType, dwSize, ok;
  175. TCHAR tmp[MAX_PATH+1];
  176. HKEY hk;
  177. int dirLen;
  178. /* establish the secure user directory */
  179. lstrcpy(secureUserDirectory, imagePath);
  180. dirLen = lstrlen(secureUserDirectory);
  181. dwSize = MAX_PATH-dirLen;
  182. GetUserName(secureUserDirectory+dirLen, &dwSize);
  183. /* establish untrusted user directory */
  184. lstrcpy(untrustedUserDirectory, TEXT("C:\\My Squeak\\%USERNAME%"));
  185. dirLen = lstrlen(untrustedUserDirectory);
  186. #ifdef USE_DYNAMIC_SHGETFOLDERPATH
  187. /* Look up shGetFolderPathW */
  188. shGetFolderPath = (void*)GetProcAddress(LoadLibrary("SHFolder.dll"),
  189. "SHGetFolderPathW");
  190. if(shGetFolderPath) {
  191. /* If we have shGetFolderPath use My Documents/My Squeak */
  192. WCHAR widepath[MAX_PATH];
  193. int sz;
  194. if(shGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, widepath) == S_OK) {
  195. WideCharToMultiByte(CP_UTF8,0,widepath,-1,untrustedUserDirectory,
  196. MAX_PATH,NULL,NULL);
  197. sz = strlen(untrustedUserDirectory);
  198. if(untrustedUserDirectory[sz-1] != '\\')
  199. strcat(untrustedUserDirectory, "\\");
  200. strcat(untrustedUserDirectory, "My Squeak");
  201. }
  202. }
  203. #else
  204. {
  205. WCHAR widepath[MAX_PATH];
  206. int sz;
  207. if(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, widepath) == S_OK) {
  208. WideCharToMultiByte(CP_UTF8,0,widepath,-1,untrustedUserDirectory, MAX_PATH,NULL,NULL);
  209. sz = strlen(untrustedUserDirectory);
  210. if(untrustedUserDirectory[sz-1] != '\\')
  211. strcat(untrustedUserDirectory, "\\");
  212. strcat(untrustedUserDirectory, "My Squeak");
  213. }
  214. }
  215. #endif
  216. /* Query Squeak.ini for network installations */
  217. GetPrivateProfileString(TEXT("Security"), TEXT("SecureDirectory"),
  218. secureUserDirectory, secureUserDirectory,
  219. MAX_PATH, squeakIniName);
  220. GetPrivateProfileString(TEXT("Security"), TEXT("UserDirectory"),
  221. untrustedUserDirectory, untrustedUserDirectory,
  222. MAX_PATH, squeakIniName);
  223. /* Attempt to read local user settings from registry */
  224. ok = RegOpenKey(HKEY_CURRENT_USER, HKEY_SQUEAK_ROOT, &hk);
  225. /* Read the secure directory from the subkey. */
  226. dwSize = MAX_PATH;
  227. ok = RegQueryValueEx(hk,"SecureDirectory",NULL, &dwType,
  228. (LPBYTE) tmp, &dwSize);
  229. if(ok == ERROR_SUCCESS) {
  230. if(tmp[dwSize-2] != '\\') {
  231. tmp[dwSize-1] = '\\';
  232. tmp[dwSize] = 0;
  233. }
  234. strcpy(secureUserDirectory, tmp);
  235. }
  236. /* Read the user directory from the subkey. */
  237. dwSize = MAX_PATH;
  238. ok = RegQueryValueEx(hk,"UserDirectory",NULL, &dwType,
  239. (LPBYTE) tmp, &dwSize);
  240. if(ok == ERROR_SUCCESS) {
  241. if(tmp[dwSize-2] != '\\') {
  242. tmp[dwSize-1] = '\\';
  243. tmp[dwSize] = 0;
  244. }
  245. strcpy(untrustedUserDirectory, tmp);
  246. }
  247. RegCloseKey(hk);
  248. /* Expand any environment variables in user directory. */
  249. dwSize = ExpandEnvironmentStrings(untrustedUserDirectory, tmp, MAX_PATH-1);
  250. if(dwSize > 0 && dwSize < MAX_PATH)
  251. strcpy(untrustedUserDirectory, tmp);
  252. return 1;
  253. }
  254. /***************************************************************************/
  255. /***************************************************************************/
  256. /***************************************************************************/
  257. /***************************************************************************/
  258. /* private entries for restoring rights */
  259. int _ioSetImageWrite(int enable) {
  260. if(enable == allowImageWrite) return 1;
  261. if(!allowImageWrite) {
  262. if(MessageBox(stWindow, TEXT("WARNING: Re-enabling the ability to write the image is a serious security hazard. Do you want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  263. return 0;
  264. if(MessageBox(stWindow, TEXT("WARNING: Untrusted code could WIPE OUT your entire hard disk, STEAL your credit card information and send your PERSONAL documents to the entire world. Do you really want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  265. return 0;
  266. if(MessageBox(stWindow, TEXT("WARNING: This is your last chance. If you proceed you will have to deal with the implications on your own. WE ARE REJECTING EVERY RESPONSIBILITY IF YOU CLICK ON YES. Do you want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  267. return 0;
  268. }
  269. allowImageWrite = enable;
  270. return 1;
  271. }
  272. int _ioSetFileAccess(int enable) {
  273. if(enable == allowFileAccess) return 1;
  274. if(!allowFileAccess) {
  275. if(MessageBox(stWindow, TEXT("WARNING: Re-enabling the ability to access arbitrary files is a serious security hazard. Do you want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  276. return 0;
  277. if(MessageBox(stWindow, TEXT("WARNING: Untrusted code could WIPE OUT your entire hard disk, STEAL your credit card information and send your PERSONAL documents to the entire world. Do you really want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  278. return 0;
  279. if(MessageBox(stWindow, TEXT("WARNING: This is your last chance. If you proceed you will have to deal with the implications on your own. WE ARE REJECTING EVERY RESPONSIBILITY IF YOU CLICK ON YES. Do you want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  280. return 0;
  281. }
  282. allowFileAccess = enable;
  283. return 1;
  284. }
  285. int _ioSetSocketAccess(int enable) {
  286. if(enable == allowSocketAccess) return 1;
  287. if(!allowSocketAccess) {
  288. if(MessageBox(stWindow, TEXT("WARNING: Re-enabling the ability to use sockets is a serious security hazard. Do you want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  289. return 0;
  290. if(MessageBox(stWindow, TEXT("WARNING: Untrusted code could WIPE OUT your entire hard disk, STEAL your credit card information and send your PERSONAL documents to the entire world. Do you really want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  291. return 0;
  292. if(MessageBox(stWindow, TEXT("WARNING: This is your last chance. If you proceed you will have to deal with the implications on your own. WE ARE REJECTING EVERY RESPONSIBILITY IF YOU CLICK ON YES. Do you want to continue?"), TEXT("Squeak Security Alert"), MB_YESNO | MB_ICONSTOP) != IDYES)
  293. return 0;
  294. }
  295. allowSocketAccess = enable;
  296. return 1;
  297. }