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.

458 lines
11 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. roshare.c
  5. Abstract:
  6. This program is a quick-and-dirty app that allows a readonly ACL to
  7. be placed on a local server share. The ACL allows everyone Read
  8. access only.
  9. Author:
  10. Chuck Lenzmeier (chuckl) 20-Sep-1992
  11. Revision History:
  12. --*/
  13. #define UNICODE 1
  14. #define VERBOSE 0
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <lm.h>
  20. #include <stdio.h>
  21. //#include <string.h>
  22. #define MAX_NAMES 60
  23. BOOL
  24. FindSid(
  25. LPTSTR Name,
  26. PSID *Sid
  27. );
  28. VOID
  29. DumpSid(
  30. LPTSTR String,
  31. PISID Sid
  32. );
  33. BOOL
  34. ConstructAcl(
  35. PACL *acl,
  36. LPTSTR Names[],
  37. ULONG Index
  38. );
  39. __cdecl
  40. main (
  41. int argc,
  42. char *argv[]
  43. )
  44. {
  45. ANSI_STRING ansiShareName;
  46. UNICODE_STRING shareName;
  47. LPSHARE_INFO_502 shi502;
  48. SECURITY_DESCRIPTOR desc;
  49. DWORD aclBuffer[256/4];
  50. PACL acl = (PACL)aclBuffer;
  51. SID_IDENTIFIER_AUTHORITY worldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  52. PSID sid;
  53. ACCESS_MASK mask;
  54. int i;
  55. BOOL ok;
  56. NTSTATUS status;
  57. DWORD error;
  58. DWORD parmerr;
  59. LPTSTR Names[MAX_NAMES];
  60. BOOL ExplicitNames = FALSE;
  61. ULONG Index;
  62. //
  63. // Make sure at least one share name was specified.
  64. //
  65. if ( argc < 2 ) goto usage;
  66. //
  67. // Initialize the security descriptor and the ACL.
  68. //
  69. ok = InitializeSecurityDescriptor( &desc, SECURITY_DESCRIPTOR_REVISION );
  70. if ( !ok ) {
  71. error = GetLastError();
  72. printf( "InitializeSecurityDescriptor failed: %d\n", error );
  73. return error;
  74. }
  75. ok = InitializeAcl( acl, 256, ACL_REVISION );
  76. if ( !ok ) {
  77. error = GetLastError();
  78. printf( "InitializeAcl failed: %d\n", error );
  79. return error;
  80. }
  81. //
  82. // Check to see if there are any usernames specified for
  83. // the ACL.
  84. //
  85. if ( _stricmp( argv[1], "-u") == 0 ) {
  86. #if VERBOSE
  87. printf("Processing names\n");
  88. #endif
  89. ExplicitNames = TRUE;
  90. i=2; // skip the argument
  91. Index = 0;
  92. while ( (_stricmp(argv[i], "-s") != 0) && (Index < MAX_NAMES)) {
  93. Names[Index++] = (LPTSTR)argv[i++];
  94. }
  95. if ( Index > 0 ) {
  96. ok = ConstructAcl( &acl, Names, Index );
  97. if ( !ok ) {
  98. fprintf(stderr, "Unable to create ACL, quitting\n");
  99. return( ERROR_INVALID_PARAMETER );
  100. }
  101. } else {
  102. goto usage;
  103. }
  104. } else {
  105. #if VERBOSE
  106. printf("No names\n");
  107. #endif
  108. //
  109. // Get the SID for World (aka Everyone).
  110. //
  111. ok = AllocateAndInitializeSid(
  112. &worldSidAuthority,
  113. 1,
  114. SECURITY_WORLD_RID,
  115. 0, 0, 0, 0, 0, 0, 0,
  116. &sid
  117. );
  118. if ( !ok ) {
  119. error = GetLastError();
  120. printf( "AllocateAndInitializeSid failed: %d\n", error );
  121. return error;
  122. }
  123. //
  124. // Add an ACE that allows World read access.
  125. //
  126. mask = GENERIC_READ | GENERIC_EXECUTE;
  127. ok = AddAccessAllowedAce( acl, ACL_REVISION, mask, sid );
  128. if ( !ok ) {
  129. error = GetLastError();
  130. printf( "AddAccessAllowedAce failed: %d\n", error );
  131. return error;
  132. }
  133. }
  134. //
  135. // Associate the ACL with the security descriptor.
  136. //
  137. ok = SetSecurityDescriptorDacl( &desc, TRUE, acl, FALSE );
  138. if ( !ok ) {
  139. error = GetLastError();
  140. printf( "SetSecurityDescriptorDacl failed: %d\n", error );
  141. return error;
  142. }
  143. //
  144. // For each share in the argument list, add the ACL to the share.
  145. // Note that this will override a preexisting ACL.
  146. //
  147. for ( i = (ExplicitNames ? i+1 : 1) ; i < argc; i++ ) {
  148. //
  149. // Convert the share name to Unicode.
  150. //
  151. RtlInitAnsiString( &ansiShareName, argv[i] );
  152. status = RtlAnsiStringToUnicodeString(
  153. &shareName,
  154. &ansiShareName,
  155. TRUE
  156. );
  157. if ( !NT_SUCCESS(status) ) {
  158. printf( "Error converting string %s to Unicode: %x\n",
  159. argv[i], status );
  160. continue;
  161. }
  162. //
  163. // Get the current share information. If the share doesn't
  164. // exist, continue with the next one in the list.
  165. //
  166. error = NetShareGetInfo(
  167. NULL,
  168. shareName.Buffer,
  169. 502,
  170. (LPBYTE *)&shi502 );
  171. if ( error == NERR_NetNameNotFound ) {
  172. printf( "Share %s doesn't exist\n", argv[i] );
  173. continue;
  174. }
  175. if ( error == ERROR_ACCESS_DENIED ) {
  176. printf( "Access denied. Log in as an admin or power user\n" );
  177. break;
  178. }
  179. if ( error != NO_ERROR ) {
  180. printf( "Unable to get info for share %s: %d\n",
  181. argv[i], error );
  182. continue;
  183. }
  184. //
  185. // Change the security descriptor for the share and set the new
  186. // information.
  187. //
  188. shi502->shi502_security_descriptor = &desc;
  189. error = NetShareSetInfo(
  190. NULL,
  191. shareName.Buffer,
  192. 502,
  193. (LPBYTE)shi502,
  194. &parmerr
  195. );
  196. if ( error == NERR_NetNameNotFound ) {
  197. printf( "Share %s doesn't exist\n", argv[i] );
  198. continue;
  199. }
  200. if ( error == ERROR_ACCESS_DENIED ) {
  201. printf( "Access denied. Log in as an admin or power user\n" );
  202. break;
  203. }
  204. if ( error != NO_ERROR ) {
  205. printf( "Unable to set info for share %s: %d, %d\n",
  206. argv[i], error, parmerr );
  207. continue;
  208. }
  209. printf( "Readonly ACL added to share %s\n", argv[i] );
  210. } // for ( i = 1; i < argc; i++ )
  211. return NO_ERROR;
  212. usage:
  213. printf( "Usage: %s [-u domain\\name1 [domain\\name2]... -s ] share [share]...\n", argv[0] );
  214. return ERROR_INVALID_PARAMETER;
  215. }
  216. BOOL
  217. FindSid(
  218. LPTSTR Name,
  219. PSID *Sid
  220. )
  221. {
  222. DWORD SidLength = 0;
  223. TCHAR DomainName[256];
  224. DWORD DomainNameLength = 256;
  225. SID_NAME_USE Use;
  226. BOOL Result;
  227. UNICODE_STRING UName;
  228. ANSI_STRING AName;
  229. NTSTATUS status;
  230. printf("\nName: %s\n",Name);
  231. //
  232. // Convert name to unicode
  233. //
  234. RtlInitAnsiString( &AName, (PCSZ)Name );
  235. status = RtlAnsiStringToUnicodeString(
  236. &UName,
  237. &AName,
  238. TRUE
  239. );
  240. if ( !NT_SUCCESS(status) ) {
  241. printf( "Error converting string %s to Unicode: %x\n",
  242. Name, status );
  243. return( FALSE );
  244. }
  245. Result = LookupAccountName(
  246. NULL,
  247. UName.Buffer,
  248. (PSID)NULL,
  249. &SidLength,
  250. DomainName,
  251. &DomainNameLength,
  252. &Use
  253. );
  254. if ( !Result && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) ) {
  255. *Sid = LocalAlloc( 0, SidLength );
  256. Result = LookupAccountName(
  257. NULL,
  258. UName.Buffer,
  259. *Sid,
  260. &SidLength,
  261. DomainName,
  262. &DomainNameLength,
  263. &Use
  264. );
  265. if ( !Result) {
  266. printf("2nd Lookup %s failed, error = %d\n",Name,GetLastError());
  267. } else {
  268. #if VERBOSE
  269. DumpSid( "2nd Lookup worked\n", (PISID)(*Sid) );
  270. #endif
  271. }
  272. } else {
  273. printf("1st Lookup %s failed, error = %d\n",Name,GetLastError());
  274. }
  275. return( Result );
  276. }
  277. #if VERBOSE
  278. VOID
  279. DumpSid(
  280. LPTSTR String,
  281. PISID Sid
  282. )
  283. {
  284. char tab[80];
  285. int i;
  286. PULONG psa;
  287. printf(String);
  288. memset(tab, ' ', strlen(String));
  289. tab[strlen(String)] = 0;
  290. printf( "Revision : %d\n"
  291. "%s"
  292. "SubAuthorityCount : %d\n"
  293. "%s"
  294. "IdentifierAuthority : %d-%d-%d-%d-%d-%d\n",
  295. Sid->Revision,
  296. tab,
  297. Sid->SubAuthorityCount,
  298. tab,
  299. ((PUCHAR)&Sid->IdentifierAuthority)[0],
  300. ((PUCHAR)&Sid->IdentifierAuthority)[1],
  301. ((PUCHAR)&Sid->IdentifierAuthority)[2],
  302. ((PUCHAR)&Sid->IdentifierAuthority)[3],
  303. ((PUCHAR)&Sid->IdentifierAuthority)[4],
  304. ((PUCHAR)&Sid->IdentifierAuthority)[5]
  305. );
  306. psa = (PULONG)&Sid->SubAuthority;
  307. for (i=0; i<(int)Sid->SubAuthorityCount; ++i) {
  308. printf(
  309. "%s"
  310. "SubAuthority : %d\n",
  311. tab,
  312. *psa++
  313. );
  314. }
  315. }
  316. #endif
  317. BOOL
  318. ConstructAcl(
  319. PACL *acl,
  320. LPTSTR Names[],
  321. ULONG Index
  322. )
  323. {
  324. ULONG i;
  325. PSID Sids[MAX_NAMES];
  326. ULONG TotalSidLength = 0;
  327. ULONG TotalAclLength = 0;
  328. BOOL Result;
  329. DWORD error;
  330. for ( i=0; i<Index ; i++) {
  331. Result = FindSid( Names[i], &Sids[i] );
  332. if ( !Result ) {
  333. fprintf(stderr, "Unable to map name %s, quitting\n", Names[i]);
  334. return( FALSE );
  335. } else {
  336. TotalSidLength += GetLengthSid( Sids[i] );
  337. }
  338. }
  339. //
  340. // This is a slight overestimate
  341. //
  342. TotalAclLength = TotalSidLength +
  343. sizeof( ACL ) +
  344. Index * sizeof( ACCESS_ALLOWED_ACE );
  345. *acl = LocalAlloc( 0, TotalAclLength );
  346. if ( *acl == NULL ) {
  347. fprintf(stderr, "Out of memory\n");
  348. return( FALSE );
  349. }
  350. Result = InitializeAcl( *acl, TotalAclLength, ACL_REVISION );
  351. //
  352. // This should not fail
  353. //
  354. if ( !Result ) {
  355. error = GetLastError();
  356. fprintf( stderr, "InitializeAcl failed: %d\n", error );
  357. return FALSE;
  358. }
  359. for ( i=0; i<Index ; i++) {
  360. Result = AddAccessAllowedAce( *acl,
  361. ACL_REVISION,
  362. GENERIC_READ | GENERIC_EXECUTE,
  363. Sids[i]
  364. );
  365. if ( !Result ) {
  366. error = GetLastError();
  367. fprintf( stderr, "AddAccessAllowedAce failed: %d\n", error );
  368. return FALSE;
  369. }
  370. }
  371. return( TRUE );
  372. }