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.

554 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. radmin.c (remote admin)
  5. Abstract:
  6. This file exercises the various NetAdminTools API.
  7. Author:
  8. Dan Lafferty (danl) 19-Sept-1991
  9. Environment:
  10. User Mode -Win32
  11. Revision History:
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h> // needed for windows.h when I have nt.h
  16. #include <windows.h>
  17. #include <stdlib.h> // atoi
  18. #include <stdio.h> // printf
  19. #include <tstr.h> // STRICMP
  20. #include <ntseapi.h> // SECURITY_DESCRIPTOR_CONTROL
  21. #include <srvsvc.h>
  22. #include <filesec.h> // NetpGetFileSecurity, NetpSetFileSecurity
  23. //
  24. // DataStructures
  25. //
  26. typedef struct _TEST_SID {
  27. UCHAR Revision;
  28. UCHAR SubAuthorityCount;
  29. UCHAR IdentifierAuthority[6];
  30. ULONG SubAuthority[10];
  31. } TEST_SID, *PTEST_SID, *LPTEST_SID;
  32. typedef struct _TEST_ACL {
  33. UCHAR AclRevision;
  34. UCHAR Sbz1;
  35. USHORT AclSize;
  36. UCHAR Dummy1[];
  37. } TEST_ACL, *PTEST_ACL;
  38. typedef struct _TEST_SECURITY_DESCRIPTOR {
  39. UCHAR Revision;
  40. UCHAR Sbz1;
  41. SECURITY_DESCRIPTOR_CONTROL Control;
  42. PTEST_SID Owner;
  43. PTEST_SID Group;
  44. PTEST_ACL Sacl;
  45. PTEST_ACL Dacl;
  46. } TEST_SECURITY_DESCRIPTOR, *PTEST_SECURITY_DESCRIPTOR;
  47. //
  48. // GLOBALS
  49. //
  50. TEST_SID OwnerSid = {
  51. 1, 5,
  52. 1,2,3,4,5,6,
  53. 0x999, 0x888, 0x777, 0x666, 0x12345678};
  54. TEST_SID GroupSid = {
  55. 1, 5,
  56. 1,2,3,4,5,6,
  57. 0x999, 0x888, 0x777, 0x666, 0x12345678};
  58. TEST_ACL SaclAcl = { 1, 2, 4+1, 3};
  59. TEST_ACL DaclAcl = { 1, 2, 4+5, 4, 4, 4, 4, 4, };
  60. TEST_SECURITY_DESCRIPTOR TestSd = {
  61. 1, 2, 0x3333,
  62. &OwnerSid,
  63. &GroupSid,
  64. &SaclAcl,
  65. NULL };
  66. //
  67. // Function Prototypes
  68. //
  69. NET_API_STATUS
  70. TestGetFileSec(
  71. LPTSTR ServerName,
  72. LPTSTR FileName
  73. );
  74. NET_API_STATUS
  75. TestSetFileSec(
  76. LPTSTR ServerName,
  77. LPTSTR FileName
  78. );
  79. VOID
  80. Usage(VOID);
  81. VOID
  82. DisplaySecurityDescriptor(
  83. PTEST_SECURITY_DESCRIPTOR pSecDesc
  84. );
  85. BOOL
  86. MakeArgsUnicode (
  87. DWORD argc,
  88. PCHAR argv[]
  89. );
  90. BOOL
  91. ConvertToUnicode(
  92. OUT LPWSTR *UnicodeOut,
  93. IN LPSTR AnsiIn
  94. );
  95. VOID __cdecl
  96. main (
  97. DWORD argc,
  98. PUCHAR argv[]
  99. )
  100. /*++
  101. Routine Description:
  102. Allows manual testing of the AdminTools API.
  103. radmin GetNameFromSid - calls NetpGetNameFromSid
  104. radmin SetFileSec - calls NetpSetFileSecurity
  105. etc...
  106. Arguments:
  107. Return Value:
  108. --*/
  109. {
  110. DWORD status;
  111. LPTSTR FileName;
  112. LPTSTR *FixArgv;
  113. LPTSTR pServerName;
  114. DWORD argIndex;
  115. //
  116. // Make the arguments unicode if necessary.
  117. //
  118. #ifdef UNICODE
  119. if (!MakeArgsUnicode(argc, argv)) {
  120. return;
  121. }
  122. #endif
  123. FixArgv = (LPTSTR *)argv;
  124. argIndex = 1;
  125. pServerName = NULL;
  126. if (STRNCMP (FixArgv[1], TEXT("\\\\"), 2) == 0) {
  127. pServerName = FixArgv[1];
  128. argIndex = 2;
  129. }
  130. if (argc < 2) {
  131. printf("ERROR: \n");
  132. Usage();
  133. return;
  134. }
  135. if (STRICMP (FixArgv[argIndex], TEXT("GetFileSec")) == 0) {
  136. if (argc > argIndex ) {
  137. FileName = FixArgv[argIndex+1];
  138. }
  139. else {
  140. FileName = NULL;
  141. }
  142. status = TestGetFileSec(pServerName,FileName);
  143. }
  144. else if (STRICMP (FixArgv[argIndex], TEXT("SetFileSec")) == 0) {
  145. if (argc > argIndex ) {
  146. FileName = FixArgv[argIndex+1];
  147. }
  148. else {
  149. FileName = NULL;
  150. }
  151. status = TestSetFileSec(pServerName,FileName);
  152. }
  153. else {
  154. printf("[sc] Unrecognized Command\n");
  155. Usage();
  156. }
  157. return;
  158. }
  159. NET_API_STATUS
  160. TestGetFileSec(
  161. LPTSTR ServerName,
  162. LPTSTR FileName
  163. )
  164. {
  165. NET_API_STATUS status;
  166. SECURITY_INFORMATION secInfo;
  167. PTEST_SECURITY_DESCRIPTOR pSecurityDescriptor;
  168. LPBYTE pDest;
  169. DWORD Length;
  170. if (FileName == NULL ) {
  171. FileName = TEXT("Dan.txt");
  172. }
  173. // secInfo = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  174. // DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION);
  175. secInfo = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  176. DACL_SECURITY_INFORMATION );
  177. status = NetpGetFileSecurity(
  178. FileName, // FileName,
  179. secInfo, // pRequestedInformation,
  180. (PSECURITY_DESCRIPTOR *)&pSecurityDescriptor, // pSecurityDescriptor,
  181. &Length); // pnLength
  182. if (status != NO_ERROR) {
  183. printf("NetpGetFileSecurity Failed %d,0x%x\n",status,status);
  184. }
  185. else{
  186. pDest = (LPBYTE) pSecurityDescriptor;
  187. if (!IsValidSecurityDescriptor(pSecurityDescriptor)) {
  188. printf("FAILURE: SECURITY DESCRIPTOR IS INVALID\n");
  189. }
  190. else {
  191. printf("SUCCESS: SECURITY DESCRIPTOR IS VALID\n");
  192. }
  193. //
  194. // Make the self-releative SD absolute for display.
  195. //
  196. pSecurityDescriptor->Owner = (PTEST_SID)(pDest + (DWORD)pSecurityDescriptor->Owner);
  197. pSecurityDescriptor->Group = (PTEST_SID)(pDest + (DWORD)pSecurityDescriptor->Group);
  198. pSecurityDescriptor->Sacl = (PTEST_ACL)(pDest + (DWORD)pSecurityDescriptor->Sacl);
  199. pSecurityDescriptor->Dacl = (PTEST_ACL)(pDest + (DWORD)pSecurityDescriptor->Dacl);
  200. pSecurityDescriptor->Control &= (~SE_SELF_RELATIVE);
  201. if (pSecurityDescriptor->Sacl == (PTEST_ACL)pDest) {
  202. pSecurityDescriptor->Sacl = NULL;
  203. }
  204. if (pSecurityDescriptor->Dacl == (PTEST_ACL)pDest) {
  205. pSecurityDescriptor->Dacl = NULL;
  206. }
  207. printf("Size of Security Descriptor = %ld \n",Length);
  208. DisplaySecurityDescriptor(pSecurityDescriptor);
  209. }
  210. return (NO_ERROR);
  211. }
  212. NET_API_STATUS
  213. TestSetFileSec(
  214. LPTSTR ServerName,
  215. LPTSTR FileName
  216. )
  217. {
  218. NET_API_STATUS status;
  219. SECURITY_INFORMATION secInfo;
  220. if (FileName == NULL ) {
  221. FileName = TEXT("Dan.txt");
  222. }
  223. secInfo = 0x55555555;
  224. status = NetpSetFileSecurity(
  225. FileName, // FileName,
  226. secInfo, // pRequestedInformation,
  227. (PSECURITY_DESCRIPTOR)&TestSd); // pSecurityDescriptor,
  228. if (status != NO_ERROR) {
  229. printf("NetpSetFileSecurity Failed %d,0x%x\n",status,status);
  230. }
  231. return (NO_ERROR);
  232. }
  233. VOID
  234. Usage(VOID)
  235. {
  236. printf("USAGE:\n");
  237. printf("radmin <server> <function>\n");
  238. printf("Functions: GetFileSec, SetFileSec...\n\n");
  239. printf("SYNTAX EXAMPLES \n");
  240. printf("radmin \\\\DANL2 GetFileSec - calls NetpGetFileSecurity on \\DANL2\n");
  241. printf("radmin \\\\DANL2 SetFileSec - calls NetpSetFileSecurity on \\DANL2\n");
  242. }
  243. // ***************************************************************************
  244. VOID
  245. DisplaySecurityDescriptor(
  246. PTEST_SECURITY_DESCRIPTOR pSecDesc
  247. )
  248. {
  249. DWORD i;
  250. DWORD numAces;
  251. if (!IsValidSecurityDescriptor(pSecDesc)) {
  252. printf("FAILURE: SECURITY DESCRIPTOR IS INVALID\n");
  253. }
  254. printf("[ADT]:Security Descriptor Received\n");
  255. printf("\tSECURITY_DESCRIPTOR HEADER:\n");
  256. printf("\tRevision: %d\n", pSecDesc->Revision);
  257. printf("\tSbz1: 0x%x\n", pSecDesc->Sbz1);
  258. printf("\tControl: 0x%x\n", pSecDesc->Control);
  259. //-------------------
  260. // OWNER SID
  261. //-------------------
  262. printf("\n\tOWNER_SID\n");
  263. printf("\t\tRevision: %u\n",pSecDesc->Owner->Revision);
  264. printf("\t\tSubAuthorityCount: %u\n",pSecDesc->Owner->SubAuthorityCount);
  265. printf("\t\tIdentifierAuthority: ");
  266. for(i=0; i<6; i++) {
  267. printf("%u ",pSecDesc->Owner->IdentifierAuthority[i]);
  268. }
  269. printf("\n");
  270. printf("\t\tSubAuthority: ");
  271. for(i=0; i<pSecDesc->Group->SubAuthorityCount; i++) {
  272. printf("0x%x ",pSecDesc->Owner->SubAuthority[i]);
  273. }
  274. printf("\n");
  275. //-------------------
  276. // GROUP SID
  277. //-------------------
  278. printf("\n\tGROUP_SID\n");
  279. printf("\t\tRevision: %u\n",pSecDesc->Group->Revision);
  280. printf("\t\tSubAuthorityCount: %u\n",pSecDesc->Group->SubAuthorityCount);
  281. printf("\t\tIdentifierAuthority: ");
  282. for(i=0; i<6; i++) {
  283. printf("%u ",pSecDesc->Group->IdentifierAuthority[i]);
  284. }
  285. printf("\n");
  286. printf("\t\tSubAuthority: ");
  287. for(i=0; i<pSecDesc->Group->SubAuthorityCount; i++) {
  288. printf("0x%x ",pSecDesc->Group->SubAuthority[i]);
  289. }
  290. printf("\n");
  291. if (pSecDesc->Sacl != NULL) {
  292. printf("\n\tSYSTEM_ACL\n");
  293. printf("\t\tRevision: %d\n",pSecDesc->Sacl->AclRevision);
  294. printf("\t\tSbz1: %d\n",pSecDesc->Sacl->Sbz1);
  295. printf("\t\tAclSize: %d\n",pSecDesc->Sacl->AclSize);
  296. printf("\t\tACE: %u\n",(unsigned short)pSecDesc->Sacl->Dummy1[0]);
  297. }
  298. else {
  299. printf("\n\tSYSTEM_ACL = NULL\n");
  300. }
  301. if (pSecDesc->Dacl != NULL) {
  302. printf("\n\tDISCRETIONARY_ACL\n");
  303. printf("\t\tRevision: %d\n",pSecDesc->Dacl->AclRevision);
  304. printf("\t\tSbz1: %d\n",pSecDesc->Dacl->Sbz1);
  305. printf("\t\tAclSize: %d\n",pSecDesc->Dacl->AclSize);
  306. numAces = pSecDesc->Dacl->AclSize - 4;
  307. for (i=0; i<numAces; i++) {
  308. //
  309. // NOTE: I couldn't get this to print out the right value in DOS16.
  310. // So I gave up. It puts the 04 into the AL register and then
  311. // clears the AH register, then pushes AX (both parts). But when
  312. // it prints, it only prints 0.
  313. //
  314. printf("\t\tACE%u: %u\n",i,(unsigned short)pSecDesc->Dacl->Dummy1[i]);
  315. }
  316. }
  317. else {
  318. printf("\n\tDISCRETIONARY_ACL = NULL\n");
  319. }
  320. }
  321. BOOL
  322. MakeArgsUnicode (
  323. DWORD argc,
  324. PCHAR argv[]
  325. )
  326. /*++
  327. Routine Description:
  328. Arguments:
  329. Return Value:
  330. Note:
  331. --*/
  332. {
  333. DWORD i;
  334. //
  335. // ScConvertToUnicode allocates storage for each string.
  336. // We will rely on process termination to free the memory.
  337. //
  338. for(i=0; i<argc; i++) {
  339. if(!ConvertToUnicode( (LPWSTR *)&(argv[i]), argv[i])) {
  340. printf("Couldn't convert argv[%d] to unicode\n",i);
  341. return(FALSE);
  342. }
  343. }
  344. return(TRUE);
  345. }
  346. BOOL
  347. ConvertToUnicode(
  348. OUT LPWSTR *UnicodeOut,
  349. IN LPSTR AnsiIn
  350. )
  351. /*++
  352. Routine Description:
  353. This function translates an AnsiString into a Unicode string.
  354. A new string buffer is created by this function. If the call to
  355. this function is successful, the caller must take responsibility for
  356. the unicode string buffer that was allocated by this function.
  357. The allocated buffer should be free'd with a call to LocalFree.
  358. NOTE: This function allocates memory for the Unicode String.
  359. Arguments:
  360. AnsiIn - This is a pointer to an ansi string that is to be converted.
  361. UnicodeOut - This is a pointer to a location where the pointer to the
  362. unicode string is to be placed.
  363. Return Value:
  364. TRUE - The conversion was successful.
  365. FALSE - The conversion was unsuccessful. In this case a buffer for
  366. the unicode string was not allocated.
  367. --*/
  368. {
  369. NTSTATUS ntStatus;
  370. DWORD bufSize;
  371. UNICODE_STRING unicodeString;
  372. ANSI_STRING ansiString;
  373. //
  374. // Allocate a buffer for the unicode string.
  375. //
  376. bufSize = (strlen(AnsiIn)+1) * sizeof(WCHAR);
  377. *UnicodeOut = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (UINT)bufSize);
  378. if (*UnicodeOut == NULL) {
  379. printf("ScConvertToUnicode:LocalAlloc Failure %ld\n",GetLastError());
  380. return(FALSE);
  381. }
  382. //
  383. // Initialize the string structures
  384. //
  385. RtlInitAnsiString( &ansiString, AnsiIn);
  386. unicodeString.Buffer = *UnicodeOut;
  387. unicodeString.MaximumLength = (USHORT)bufSize;
  388. unicodeString.Length = 0;
  389. //
  390. // Call the conversion function.
  391. //
  392. ntStatus = RtlAnsiStringToUnicodeString (
  393. &unicodeString, // Destination
  394. &ansiString, // Source
  395. (BOOLEAN)FALSE); // Allocate the destination
  396. if (!NT_SUCCESS(ntStatus)) {
  397. printf("ScConvertToUnicode:RtlAnsiStringToUnicodeString Failure %lx\n",
  398. ntStatus);
  399. return(FALSE);
  400. }
  401. //
  402. // Fill in the pointer location with the unicode string buffer pointer.
  403. //
  404. *UnicodeOut = unicodeString.Buffer;
  405. return(TRUE);
  406. }