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.

400 lines
9.4 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. secure.c
  5. Abstract:
  6. Security related routines
  7. Author:
  8. Colin Brace (ColinBr)
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <setpch.h>
  14. #include <dssetp.h>
  15. #include "secure.h"
  16. //
  17. // Data global to this module only
  18. //
  19. SECURITY_DESCRIPTOR DsRolepPromoteSD;
  20. SECURITY_DESCRIPTOR DsRolepDemoteSD;
  21. //
  22. // DsRole related access masks
  23. //
  24. #define DSROLE_ROLE_CHANGE_ACCESS 0x00000001
  25. #define DSROLE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | \
  26. DSROLE_ROLE_CHANGE_ACCESS )
  27. GENERIC_MAPPING DsRolepInfoMapping =
  28. {
  29. STANDARD_RIGHTS_READ, // Generic read
  30. STANDARD_RIGHTS_WRITE, // Generic write
  31. STANDARD_RIGHTS_EXECUTE, // Generic execute
  32. DSROLE_ALL_ACCESS // Generic all
  33. };
  34. //
  35. // Function definitions
  36. //
  37. BOOLEAN
  38. DsRolepCreateInterfaceSDs(
  39. VOID
  40. )
  41. /*++
  42. Routine Description:
  43. This routine creates the in memory access control lists that
  44. are used to perform security checks on callers of the DsRoler
  45. API's.
  46. The model is as follows:
  47. Promote: the caller must have the builtin admin SID
  48. Demote: the caller must have the builtin admin SID
  49. Arguments:
  50. None.
  51. Returns:
  52. TRUE if successful; FALSE otherwise
  53. --*/
  54. {
  55. NTSTATUS Status;
  56. BOOLEAN fSuccess = TRUE;
  57. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  58. ULONG AclLength = 0;
  59. PSID BuiltinAdminsSid = NULL;
  60. PSID *AllowedSids [] =
  61. {
  62. &BuiltinAdminsSid
  63. };
  64. ULONG cAllowedSids = sizeof(AllowedSids) / sizeof(AllowedSids[0]);
  65. ULONG i;
  66. PACL DsRolepPromoteAcl = NULL;
  67. PACL DsRolepDemoteAcl = NULL;
  68. //
  69. // Build the builtin administrators sid
  70. //
  71. Status = RtlAllocateAndInitializeSid(
  72. &NtAuthority,
  73. 2,
  74. SECURITY_BUILTIN_DOMAIN_RID,
  75. DOMAIN_ALIAS_RID_ADMINS,
  76. 0, 0, 0, 0, 0, 0,
  77. &BuiltinAdminsSid
  78. );
  79. if ( !NT_SUCCESS( Status ) ) {
  80. fSuccess = FALSE;
  81. goto Cleanup;
  82. }
  83. //
  84. // Calculate how much space we'll need for the ACL
  85. //
  86. AclLength = sizeof( ACL );
  87. for ( i = 0; i < cAllowedSids; i++ ) {
  88. AclLength += (sizeof( ACCESS_ALLOWED_ACE )
  89. - sizeof(DWORD)
  90. + GetLengthSid((*AllowedSids[i])) );
  91. }
  92. DsRolepPromoteAcl = LocalAlloc( 0, AclLength );
  93. if ( !DsRolepPromoteAcl ) {
  94. fSuccess = FALSE;
  95. goto Cleanup;
  96. }
  97. if ( !InitializeAcl( DsRolepPromoteAcl, AclLength, ACL_REVISION ) ) {
  98. fSuccess = FALSE;
  99. goto Cleanup;
  100. }
  101. for ( i = 0; i < cAllowedSids; i++ ) {
  102. if ( !AddAccessAllowedAce( DsRolepPromoteAcl,
  103. ACL_REVISION,
  104. DSROLE_ALL_ACCESS,
  105. *(AllowedSids[i]) ) ) {
  106. fSuccess = FALSE;
  107. goto Cleanup;
  108. }
  109. }
  110. //
  111. // Now make the security descriptor
  112. //
  113. if ( !InitializeSecurityDescriptor( &DsRolepPromoteSD,
  114. SECURITY_DESCRIPTOR_REVISION ) ) {
  115. fSuccess = FALSE;
  116. goto Cleanup;
  117. }
  118. if ( !SetSecurityDescriptorOwner( &DsRolepPromoteSD,
  119. BuiltinAdminsSid,
  120. FALSE ) ) { // not defaulted
  121. fSuccess = FALSE;
  122. goto Cleanup;
  123. }
  124. if ( !SetSecurityDescriptorGroup( &DsRolepPromoteSD,
  125. BuiltinAdminsSid,
  126. FALSE ) ) { // not defaulted
  127. fSuccess = FALSE;
  128. goto Cleanup;
  129. }
  130. if ( !SetSecurityDescriptorDacl( &DsRolepPromoteSD,
  131. TRUE, // DACL is present
  132. DsRolepPromoteAcl,
  133. FALSE ) ) { // not defaulted
  134. fSuccess = FALSE;
  135. goto Cleanup;
  136. }
  137. //
  138. // Make the demote access check the same
  139. //
  140. DsRolepDemoteAcl = LocalAlloc( 0, AclLength );
  141. if ( !DsRolepDemoteAcl ) {
  142. fSuccess = FALSE;
  143. goto Cleanup;
  144. }
  145. RtlCopyMemory( DsRolepDemoteAcl, DsRolepPromoteAcl, AclLength );
  146. //
  147. // Now make the security descriptor
  148. //
  149. if ( !InitializeSecurityDescriptor( &DsRolepDemoteSD,
  150. SECURITY_DESCRIPTOR_REVISION ) ) {
  151. fSuccess = FALSE;
  152. goto Cleanup;
  153. }
  154. if ( !SetSecurityDescriptorOwner( &DsRolepDemoteSD,
  155. BuiltinAdminsSid,
  156. FALSE ) ) { // not defaulted
  157. fSuccess = FALSE;
  158. goto Cleanup;
  159. }
  160. if ( !SetSecurityDescriptorGroup( &DsRolepDemoteSD,
  161. BuiltinAdminsSid,
  162. FALSE ) ) { // not defaulted
  163. fSuccess = FALSE;
  164. goto Cleanup;
  165. }
  166. if ( !SetSecurityDescriptorDacl( &DsRolepDemoteSD,
  167. TRUE, // DACL is present
  168. DsRolepDemoteAcl,
  169. FALSE ) ) { // not defaulted
  170. fSuccess = FALSE;
  171. goto Cleanup;
  172. }
  173. Cleanup:
  174. if ( !fSuccess ) {
  175. for ( i = 0; i < cAllowedSids; i++ ) {
  176. if ( *(AllowedSids[i]) ) {
  177. RtlFreeHeap( RtlProcessHeap(), 0, *(AllowedSids[i]) );
  178. }
  179. }
  180. if ( DsRolepPromoteAcl ) {
  181. LocalFree( DsRolepPromoteAcl );
  182. }
  183. if ( DsRolepDemoteAcl ) {
  184. LocalFree( DsRolepDemoteAcl );
  185. }
  186. }
  187. return fSuccess;
  188. }
  189. DWORD
  190. DsRolepCheckClientAccess(
  191. PSECURITY_DESCRIPTOR pSD,
  192. DWORD DesiredAccess
  193. )
  194. /*++
  195. Routine Description:
  196. This routine grabs a copy of the client's token and then performs
  197. an access to make the client has the privlege found in pSD
  198. Arguments:
  199. pSD : a valid security descriptor
  200. DesiredAccess: the access mask the client is asking for
  201. Returns:
  202. ERROR_SUCCESS, ERROR_ACCESS_DENIED, or system error
  203. --*/
  204. {
  205. DWORD WinError = ERROR_SUCCESS;
  206. BOOL fStatus, fAccessAllowed = FALSE;
  207. HANDLE ClientToken = 0;
  208. DWORD AccessGranted = 0;
  209. BYTE Buffer[500];
  210. PRIVILEGE_SET *PrivilegeSet = (PRIVILEGE_SET*)Buffer;
  211. DWORD PrivilegeSetSize = sizeof(Buffer);
  212. WinError = DsRolepGetImpersonationToken( &ClientToken );
  213. if ( ERROR_SUCCESS == WinError ) {
  214. fStatus = AccessCheck( pSD,
  215. ClientToken,
  216. DesiredAccess,
  217. &DsRolepInfoMapping,
  218. PrivilegeSet,
  219. &PrivilegeSetSize,
  220. &AccessGranted,
  221. &fAccessAllowed );
  222. if ( !fStatus ) {
  223. WinError = GetLastError();
  224. } else {
  225. if ( !fAccessAllowed ) {
  226. WinError = ERROR_ACCESS_DENIED;
  227. }
  228. }
  229. }
  230. if ( ClientToken ) {
  231. NtClose( ClientToken );
  232. }
  233. return WinError;
  234. }
  235. DWORD
  236. DsRolepCheckPromoteAccess(
  237. VOID
  238. )
  239. {
  240. return DsRolepCheckClientAccess( &DsRolepPromoteSD,
  241. DSROLE_ROLE_CHANGE_ACCESS );
  242. }
  243. DWORD
  244. DsRolepCheckDemoteAccess(
  245. VOID
  246. )
  247. {
  248. return DsRolepCheckClientAccess( &DsRolepDemoteSD,
  249. DSROLE_ROLE_CHANGE_ACCESS );
  250. }
  251. DWORD
  252. DsRolepGetImpersonationToken(
  253. OUT HANDLE *ImpersonationToken
  254. )
  255. /*++
  256. Routine Description:
  257. This function will impersonate the invoker of this call and then duplicate their token
  258. Arguments:
  259. ImpersonationToken - Where the duplicated token is returned
  260. Returns:
  261. ERROR_SUCCESS - Success
  262. --*/
  263. {
  264. DWORD Win32Err = ERROR_SUCCESS;
  265. NTSTATUS Status;
  266. OBJECT_ATTRIBUTES ObjAttrs;
  267. SECURITY_QUALITY_OF_SERVICE SecurityQofS;
  268. HANDLE ClientToken;
  269. //
  270. // Impersonate the caller
  271. //
  272. Win32Err = RpcImpersonateClient( 0 );
  273. if ( Win32Err == ERROR_SUCCESS ) {
  274. Status = NtOpenThreadToken( NtCurrentThread(),
  275. TOKEN_QUERY | TOKEN_DUPLICATE,
  276. TRUE,
  277. &ClientToken );
  278. RpcRevertToSelf( );
  279. if ( NT_SUCCESS( Status ) ) {
  280. //
  281. // Duplicate the token
  282. //
  283. InitializeObjectAttributes( &ObjAttrs, NULL, 0L, NULL, NULL );
  284. SecurityQofS.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  285. SecurityQofS.ImpersonationLevel = SecurityImpersonation;
  286. SecurityQofS.ContextTrackingMode = FALSE; // Snapshot client context
  287. SecurityQofS.EffectiveOnly = FALSE;
  288. ObjAttrs.SecurityQualityOfService = &SecurityQofS;
  289. Status = NtDuplicateToken( ClientToken,
  290. TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_DUPLICATE,
  291. &ObjAttrs,
  292. FALSE,
  293. TokenImpersonation,
  294. ImpersonationToken );
  295. NtClose( ClientToken );
  296. }
  297. if ( !NT_SUCCESS( Status ) ) {
  298. Win32Err = RtlNtStatusToDosError( Status );
  299. }
  300. }
  301. return( Win32Err );
  302. }