Source code of Windows XP (NT5)
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.

640 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: FILE.C
  7. //
  8. // Contents: Unit test for file propagation, issues
  9. //
  10. // History: 14-Sep-96 MacM Created
  11. //
  12. // Notes:
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <aclapi.h>
  22. #include <seopaque.h>
  23. #include <ntrtl.h>
  24. #define FLAG_ON(flags,bit) ((flags) & (bit))
  25. #define DEFAULT_ACCESS ACTRL_SVC_GET_INFO | ACTRL_SVC_SET_INFO | \
  26. ACTRL_SVC_STATUS | ACTRL_SVC_LIST | \
  27. ACTRL_SVC_START | ACTRL_SVC_STOP | \
  28. ACTRL_SVC_PAUSE | ACTRL_SVC_INTERROGATE
  29. #define HANDLE_CLOSE(h) if((h) != NULL) { CloseServiceHandle(h); (h) = NULL;}
  30. //
  31. // Flags for tests
  32. //
  33. #define STEST_READ 0x00000001
  34. #define STEST_CACHE 0x00000002
  35. DWORD
  36. AddAE (
  37. IN PWSTR pwszUser,
  38. IN ACCESS_RIGHTS AccessRights,
  39. IN INHERIT_FLAGS Inherit,
  40. IN ULONG fAccess,
  41. IN PACTRL_ACCESS pExistingAccess,
  42. OUT PACTRL_ACCESS *ppNewAccess
  43. )
  44. /*++
  45. Routine Description:
  46. Initialize an access entry
  47. Arguments:
  48. pwszUser - User to set
  49. AccessRights - Access rights to set
  50. Inherit - Any inheritance flags
  51. fAccess - Allowed or denied node?
  52. pExistingAccess - Access Entry to add to
  53. ppNewAccess - Where the new access is returned
  54. Return Value:
  55. ERROR_SUCCESS - Success
  56. --*/
  57. {
  58. DWORD dwErr = ERROR_SUCCESS;
  59. ACTRL_ACCESS_ENTRY AAE;
  60. BuildTrusteeWithNameW(&(AAE.Trustee),
  61. pwszUser);
  62. AAE.fAccessFlags = fAccess;
  63. AAE.Access = AccessRights;
  64. AAE.ProvSpecificAccess = 0;
  65. AAE.Inheritance = Inherit;
  66. AAE.lpInheritProperty = NULL;
  67. dwErr = SetEntriesInAccessListW(1,
  68. &AAE,
  69. GRANT_ACCESS,
  70. NULL,
  71. pExistingAccess,
  72. ppNewAccess);
  73. if(dwErr != ERROR_SUCCESS)
  74. {
  75. printf(" Failed to add new access entry: %lu\n", dwErr);
  76. }
  77. return(dwErr);
  78. }
  79. VOID
  80. Usage (
  81. IN PSTR pszExe
  82. )
  83. /*++
  84. Routine Description:
  85. Displays the usage
  86. Arguments:
  87. pszExe - Name of the exe
  88. Return Value:
  89. VOID
  90. --*/
  91. {
  92. printf("%s service user [/C] [/O] [/I] [/P] [/test] [/H]\n", pszExe);
  93. printf(" where services is the display name of the service\n");
  94. printf(" user is the name of a user to set access for\n");
  95. printf(" /test indicates which test to run:\n");
  96. printf(" /READ (Simple read/write)\n");
  97. printf(" /CACHE (Cache matching)\n");
  98. printf(" if test is not specified, all variations are run\n");
  99. printf(" /H indicates to use the handle version of the APIs\n");
  100. printf(" /C is Container Inherit\n");
  101. printf(" /O is Object Inherit\n");
  102. printf(" /I is InheritOnly\n");
  103. printf(" /P is Inherit No Propagate\n");
  104. return;
  105. }
  106. //
  107. // Conceptually, this is a companion function for GetSecurityForPath
  108. //
  109. #define SetSecurityForService(svc,usehandle,handle,access) \
  110. (usehandle == TRUE ? \
  111. SetSecurityInfoExW(handle, \
  112. SE_SERVICE, \
  113. DACL_SECURITY_INFORMATION, \
  114. NULL, \
  115. access, \
  116. NULL, \
  117. NULL, \
  118. NULL, \
  119. NULL) : \
  120. SetNamedSecurityInfoExW(svc, \
  121. SE_SERVICE, \
  122. DACL_SECURITY_INFORMATION, \
  123. NULL, \
  124. access, \
  125. NULL, \
  126. NULL, \
  127. NULL, \
  128. NULL))
  129. DWORD
  130. GetSecurityForService (
  131. IN PWSTR pwszService,
  132. IN BOOL fUseHandle,
  133. OUT HANDLE *phObj,
  134. OUT PACTRL_ACCESSW *ppAccess
  135. )
  136. /*++
  137. Routine Description:
  138. Reads the dacl off the specified service object
  139. Arguments:
  140. pwszService -- Service to read
  141. fUseHandle -- Use handle or path based API
  142. phObj -- Handle to object
  143. ppAccess -- Where the access is returned
  144. Return Value:
  145. ERROR_SUCCESS -- Success
  146. --*/
  147. {
  148. DWORD dwErr = ERROR_SUCCESS;
  149. SC_HANDLE hSC;
  150. if(fUseHandle == TRUE)
  151. {
  152. //
  153. // Open the object
  154. //
  155. if(*phObj == NULL)
  156. {
  157. hSC = OpenSCManager(NULL,
  158. NULL,
  159. GENERIC_READ);
  160. if(hSC == NULL)
  161. {
  162. dwErr = GetLastError();
  163. }
  164. else
  165. {
  166. //
  167. // Open the service
  168. //
  169. *phObj = OpenService(hSC,
  170. pwszService,
  171. READ_CONTROL | WRITE_DAC);
  172. if(*phObj == NULL)
  173. {
  174. dwErr = GetLastError();
  175. }
  176. }
  177. }
  178. if(dwErr == ERROR_SUCCESS)
  179. {
  180. dwErr = GetSecurityInfoExW(*phObj,
  181. SE_SERVICE,
  182. DACL_SECURITY_INFORMATION,
  183. NULL,
  184. NULL,
  185. ppAccess,
  186. NULL,
  187. NULL,
  188. NULL);
  189. if(dwErr != ERROR_SUCCESS)
  190. {
  191. HANDLE_CLOSE(*phObj);
  192. }
  193. }
  194. }
  195. else
  196. {
  197. dwErr = GetNamedSecurityInfoExW(pwszService,
  198. SE_SERVICE,
  199. DACL_SECURITY_INFORMATION,
  200. NULL,
  201. NULL,
  202. ppAccess,
  203. NULL,
  204. NULL,
  205. NULL);
  206. if(phObj != NULL)
  207. {
  208. *phObj = NULL;
  209. }
  210. }
  211. return(dwErr);
  212. }
  213. DWORD
  214. DoReadTest (
  215. IN PWSTR pwszService,
  216. IN PWSTR pwszUser,
  217. IN BOOL fDoHandle
  218. )
  219. /*++
  220. Routine Description:
  221. Does the simple read test
  222. Arguments:
  223. pwszService -- Service name
  224. pwszUser -- User to run with
  225. fDoHandle -- If true, use the handle based APIs
  226. Return Value:
  227. ERROR_SUCCESS -- Success
  228. --*/
  229. {
  230. DWORD dwErr = ERROR_SUCCESS;
  231. PACTRL_ACCESS pCurrent;
  232. PACTRL_ACCESS pNew;
  233. HANDLE hObj;
  234. printf("Simple read/write test\n");
  235. printf(" Processing service %ws\n", pwszService);
  236. hObj = NULL;
  237. dwErr = GetSecurityForService(pwszService,
  238. fDoHandle,
  239. &hObj,
  240. &pCurrent);
  241. if(dwErr != ERROR_SUCCESS)
  242. {
  243. printf(" Failed to read the DACL off %ws: %lu\n", pwszService, dwErr);
  244. }
  245. else
  246. {
  247. //
  248. // Ok, now add the entry for our user
  249. //
  250. dwErr = AddAE(pwszUser,
  251. DEFAULT_ACCESS,
  252. 0,
  253. ACTRL_ACCESS_ALLOWED,
  254. pCurrent,
  255. &pNew);
  256. if(dwErr == ERROR_SUCCESS)
  257. {
  258. //
  259. // Set it
  260. //
  261. dwErr = SetSecurityForService(pwszService, fDoHandle, hObj, pNew);
  262. if(dwErr != ERROR_SUCCESS)
  263. {
  264. printf(" Set failed: %lu\n", dwErr);
  265. }
  266. LocalFree(pNew);
  267. }
  268. //
  269. // If that worked, reread the new security, and see if it's correct
  270. //
  271. if(dwErr == ERROR_SUCCESS)
  272. {
  273. HANDLE_CLOSE(hObj);
  274. dwErr = GetSecurityForService(pwszService,
  275. fDoHandle,
  276. &hObj,
  277. &pNew);
  278. if(dwErr != ERROR_SUCCESS)
  279. {
  280. printf(" Failed to read the 2nd DACL off %ws: %lu\n", pwszService, dwErr);
  281. }
  282. else
  283. {
  284. //
  285. // We should only have one property, so cheat...
  286. //
  287. ULONG cExpected = 1 + pCurrent->pPropertyAccessList[0].
  288. pAccessEntryList->cEntries;
  289. ULONG cGot = pNew->pPropertyAccessList[0].
  290. pAccessEntryList->cEntries;
  291. if(cExpected != cGot)
  292. {
  293. printf(" Expected %lu entries, got %lu\n",
  294. cExpected, cGot);
  295. dwErr = ERROR_INVALID_FUNCTION;
  296. }
  297. LocalFree(pNew);
  298. }
  299. //
  300. // Restore the current security
  301. //
  302. SetNamedSecurityInfoExW(pwszService,
  303. SE_SERVICE,
  304. DACL_SECURITY_INFORMATION,
  305. NULL,
  306. pCurrent,
  307. NULL,
  308. NULL,
  309. NULL,
  310. NULL);
  311. }
  312. LocalFree(pCurrent);
  313. }
  314. HANDLE_CLOSE(hObj);
  315. return(dwErr);
  316. }
  317. DWORD
  318. DoCacheTest (
  319. IN PWSTR pwszService,
  320. IN PWSTR pwszUser,
  321. IN BOOL fDoHandle
  322. )
  323. /*++
  324. Routine Description:
  325. Does the marta cache matching test
  326. Arguments:
  327. pwszService -- Service name
  328. pwszUser -- User to run with
  329. fDoHandle -- If true, use the handle based APIs
  330. Return Value:
  331. ERROR_SUCCESS -- Success
  332. --*/
  333. {
  334. DWORD dwErr = ERROR_SUCCESS;
  335. PACTRL_ACCESS pCurrent;
  336. INT i;
  337. SE_OBJECT_TYPE SeList[] = {SE_FILE_OBJECT, SE_SERVICE, SE_PRINTER,
  338. SE_REGISTRY_KEY, SE_LMSHARE, SE_KERNEL_OBJECT,
  339. SE_WINDOW_OBJECT, SE_DS_OBJECT, SE_DS_OBJECT_ALL};
  340. PSTR pszSeList[] = {"SE_FILE_OBJECT", "SE_SERVICE", "SE_PRINTER",
  341. "SE_REGISTRY_KEY", "SE_LMSHARE", "SE_KERNEL_OBJECT",
  342. "SE_WINDOW_OBJECT", "SE_DS_OBJECT", "SE_DS_OBJECT_ALL"};
  343. ASSERT(sizeof(SeList) / sizeof(SE_OBJECT_TYPE) == sizeof(pszSeList) / sizeof(PSTR));
  344. printf("Marta cache matching test\n");
  345. printf(" Processing service %ws\n", pwszService);
  346. //
  347. // Prime the cache...
  348. //
  349. dwErr = GetNamedSecurityInfoExW(pwszService,
  350. SE_SERVICE,
  351. DACL_SECURITY_INFORMATION,
  352. NULL,
  353. NULL,
  354. &pCurrent,
  355. NULL,
  356. NULL,
  357. NULL);
  358. if(dwErr != ERROR_SUCCESS)
  359. {
  360. printf(" Failed to read the DACL off %ws: %lu\n", pwszService, dwErr);
  361. }
  362. else
  363. {
  364. LocalFree(pCurrent);
  365. //
  366. // Now, open it as an another object type...
  367. //
  368. for(i = 0; i < sizeof(pszSeList) / sizeof(PSTR); i++)
  369. {
  370. printf(" Processing %ws as a %s\n", pwszService, pszSeList[i]);
  371. if(GetNamedSecurityInfoExW(pwszService,
  372. SeList[i],
  373. DACL_SECURITY_INFORMATION,
  374. NULL,
  375. NULL,
  376. &pCurrent,
  377. NULL,
  378. NULL,
  379. NULL) == ERROR_SUCCESS)
  380. {
  381. LocalFree(pCurrent);
  382. }
  383. }
  384. //
  385. // In order to check this, we'll set the debugger on NTMARTA, turn on cache tracing,
  386. // and see how many hits we have. Tacky, no doubt, but we have little choice
  387. //
  388. }
  389. //
  390. // Now, create a file of the same name, and do the same code
  391. //
  392. if(dwErr == ERROR_SUCCESS)
  393. {
  394. HANDLE hFile;
  395. printf(" Processing file %ws\n", pwszService);
  396. hFile = CreateFile(pwszService, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  397. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  398. if(hFile == INVALID_HANDLE_VALUE)
  399. {
  400. dwErr = GetLastError();
  401. printf(" CreateEvent on %ws failed with %lu\n", pwszService, dwErr);
  402. }
  403. else
  404. {
  405. for(i = 0; i < sizeof(pszSeList) / sizeof(PSTR); i++)
  406. {
  407. printf(" Processing %ws as a %s\n", pwszService, pszSeList[i]);
  408. if(GetNamedSecurityInfoExW(pwszService,
  409. SeList[i],
  410. DACL_SECURITY_INFORMATION,
  411. NULL,
  412. NULL,
  413. &pCurrent,
  414. NULL,
  415. NULL,
  416. NULL) == ERROR_SUCCESS)
  417. {
  418. LocalFree(pCurrent);
  419. }
  420. }
  421. if(GetNamedSecurityInfoExW(pwszService,
  422. SE_FILE_OBJECT,
  423. DACL_SECURITY_INFORMATION,
  424. NULL,
  425. NULL,
  426. &pCurrent,
  427. NULL,
  428. NULL,
  429. NULL) == ERROR_SUCCESS)
  430. {
  431. LocalFree(pCurrent);
  432. }
  433. CloseHandle(hFile);
  434. DeleteFile(pwszService);
  435. }
  436. }
  437. return(dwErr);
  438. }
  439. __cdecl main (
  440. IN INT argc,
  441. IN CHAR *argv[])
  442. /*++
  443. Routine Description:
  444. The main
  445. Arguments:
  446. argc -- Count of arguments
  447. argv -- List of arguments
  448. Return Value:
  449. 0 -- Success
  450. non-0 -- Failure
  451. --*/
  452. {
  453. DWORD dwErr = ERROR_SUCCESS;
  454. WCHAR wszService[MAX_PATH + 1];
  455. WCHAR wszUser[MAX_PATH + 1];
  456. INHERIT_FLAGS Inherit = 0;
  457. ULONG Tests = 0;
  458. INT i;
  459. BOOL fHandle = FALSE;
  460. srand((ULONG)(GetTickCount() * GetCurrentThreadId()));
  461. if(argc < 3)
  462. {
  463. Usage(argv[0]);
  464. exit(1);
  465. }
  466. mbstowcs(wszService, argv[1], strlen(argv[1]) + 1);
  467. mbstowcs(wszUser, argv[2], strlen(argv[2]) + 1);
  468. //
  469. // process the command line
  470. //
  471. for(i = 3; i < argc; i++)
  472. {
  473. if(_stricmp(argv[i], "/h") == 0)
  474. {
  475. fHandle = TRUE;
  476. }
  477. else if(_stricmp(argv[i],"/C") == 0)
  478. {
  479. Inherit |= SUB_CONTAINERS_ONLY_INHERIT;
  480. }
  481. else if(_stricmp(argv[i],"/O") == 0)
  482. {
  483. Inherit |= SUB_OBJECTS_ONLY_INHERIT;
  484. }
  485. else if(_stricmp(argv[i],"/I") == 0)
  486. {
  487. Inherit |= INHERIT_ONLY;
  488. }
  489. else if(_stricmp(argv[i],"/P") == 0)
  490. {
  491. Inherit |= INHERIT_NO_PROPAGATE;
  492. }
  493. else if(_stricmp(argv[i],"/READ") == 0)
  494. {
  495. Tests |= STEST_READ;
  496. }
  497. else if(_stricmp(argv[i],"/CACHE") == 0)
  498. {
  499. Tests |= STEST_CACHE;
  500. }
  501. else
  502. {
  503. Usage(argv[0]);
  504. exit(1);
  505. break;
  506. }
  507. }
  508. if(Tests == 0)
  509. {
  510. Tests = STEST_READ;
  511. }
  512. //
  513. // Build the tree
  514. //
  515. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, STEST_READ))
  516. {
  517. dwErr = DoReadTest(wszService, wszUser, fHandle);
  518. }
  519. if(dwErr == ERROR_SUCCESS && FLAG_ON(Tests, STEST_CACHE))
  520. {
  521. dwErr = DoCacheTest(wszService, wszUser, fHandle);
  522. }
  523. printf("%s\n", dwErr == ERROR_SUCCESS ?
  524. "success" :
  525. "failed");
  526. return(dwErr);
  527. }