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.

328 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. secobj.c
  5. Abstract:
  6. This module provides support routines to simplify the creation of
  7. security descriptors for user-mode objects.
  8. Author:
  9. Cliff Van Dyke (CliffV) 09-Feb-1994
  10. Environment:
  11. Contains NT specific code.
  12. Revision History:
  13. Cliff Van Dyke (CliffV) 09-Feb-1994
  14. Split off from secobj.c so NtLmSsp can reference secobj.c
  15. without loading the rpc libaries.
  16. --*/
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h> // DWORD.
  21. #include <lmcons.h> // NET_API_STATUS.
  22. #include <netlib.h>
  23. #include <lmerr.h>
  24. #include <netdebug.h>
  25. #include <debuglib.h>
  26. #include <rpc.h>
  27. #include <rpcutil.h>
  28. #include <secobj.h>
  29. NET_API_STATUS
  30. NetpAccessCheckAndAudit(
  31. IN LPTSTR SubsystemName,
  32. IN LPTSTR ObjectTypeName,
  33. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  34. IN ACCESS_MASK DesiredAccess,
  35. IN PGENERIC_MAPPING GenericMapping
  36. )
  37. /*++
  38. Routine Description:
  39. This function impersonates the caller so that it can perform access
  40. validation using NtAccessCheckAndAuditAlarm; and reverts back to
  41. itself before returning.
  42. Arguments:
  43. SubsystemName - Supplies a name string identifying the subsystem
  44. calling this routine.
  45. ObjectTypeName - Supplies the name of the type of the object being
  46. accessed.
  47. SecurityDescriptor - A pointer to the Security Descriptor against which
  48. acccess is to be checked.
  49. DesiredAccess - Supplies desired acccess mask. This mask must have been
  50. previously mapped to contain no generic accesses.
  51. GenericMapping - Supplies a pointer to the generic mapping associated
  52. with this object type.
  53. Return Value:
  54. NET_API_STATUS - NERR_Success or reason for failure.
  55. --*/
  56. {
  57. NTSTATUS NtStatus;
  58. RPC_STATUS RpcStatus;
  59. BOOLEAN fWasEnabled;
  60. UNICODE_STRING Subsystem;
  61. UNICODE_STRING ObjectType;
  62. UNICODE_STRING ObjectName;
  63. #ifndef UNICODE
  64. OEM_STRING AnsiString;
  65. #endif
  66. ACCESS_MASK GrantedAccess;
  67. BOOLEAN GenerateOnClose;
  68. NTSTATUS AccessStatus;
  69. #ifdef UNICODE
  70. RtlInitUnicodeString(&Subsystem, SubsystemName);
  71. RtlInitUnicodeString(&ObjectType, ObjectTypeName);
  72. #else
  73. NetpInitOemString( &AnsiString, SubsystemName );
  74. NtStatus = RtlOemStringToUnicodeString(
  75. &Subsystem,
  76. &AnsiString,
  77. TRUE
  78. );
  79. if ( !NT_SUCCESS( NtStatus )) {
  80. NetpKdPrint(("[Netlib] Error calling RtlOemStringToUnicodeString %08lx\n",
  81. NtStatus));
  82. return NetpNtStatusToApiStatus( NtStatus );
  83. }
  84. NetpInitOemString( &AnsiString, ObjectTypeName );
  85. NtStatus = RtlOemStringToUnicodeString(&ObjectType,
  86. &AnsiString,
  87. TRUE);
  88. if ( !NT_SUCCESS( NtStatus )) {
  89. NetpKdPrint(("[Netlib] Error calling RtlOemStringToUnicodeString %08lx\n",
  90. NtStatus));
  91. RtlFreeUnicodeString( &Subsystem );
  92. return NetpNtStatusToApiStatus( NtStatus );
  93. }
  94. #endif
  95. //
  96. // Make sure SE_AUDIT_PRIVILEGE is enabled for this process (rather
  97. // than the thread) since the audit privilege is checked in the process
  98. // token (and not the thread token). Leave it enabled since there's
  99. // no harm in doing so once it's been enabled (since the process needs
  100. // to have the privilege in the first place).
  101. //
  102. RtlAdjustPrivilege(SE_AUDIT_PRIVILEGE,
  103. TRUE,
  104. FALSE,
  105. &fWasEnabled);
  106. RtlInitUnicodeString(&ObjectName, NULL); // No object name
  107. if ((RpcStatus = RpcImpersonateClient(NULL)) != RPC_S_OK) {
  108. NetpKdPrint(("[Netlib] Failed to impersonate client %08lx\n",
  109. RpcStatus));
  110. return NetpRpcStatusToApiStatus(RpcStatus);
  111. }
  112. NtStatus = NtAccessCheckAndAuditAlarm(
  113. &Subsystem,
  114. NULL, // No handle for object
  115. &ObjectType,
  116. &ObjectName,
  117. SecurityDescriptor,
  118. DesiredAccess,
  119. GenericMapping,
  120. FALSE,
  121. &GrantedAccess,
  122. &AccessStatus,
  123. &GenerateOnClose
  124. );
  125. #ifndef UNICODE
  126. RtlFreeUnicodeString( &Subsystem );
  127. RtlFreeUnicodeString( &ObjectType );
  128. #endif
  129. if ((RpcStatus = RpcRevertToSelf()) != RPC_S_OK) {
  130. NetpKdPrint(("[Netlib] Fail to revert to self %08lx\n", RpcStatus));
  131. NetpAssert(FALSE);
  132. }
  133. if (! NT_SUCCESS(NtStatus)) {
  134. NetpKdPrint(("[Netlib] Error calling NtAccessCheckAndAuditAlarm %08lx\n",
  135. NtStatus));
  136. return ERROR_ACCESS_DENIED;
  137. }
  138. if (AccessStatus != STATUS_SUCCESS) {
  139. IF_DEBUG(SECURITY) {
  140. NetpKdPrint(("[Netlib] Access status is %08lx\n", AccessStatus));
  141. }
  142. return ERROR_ACCESS_DENIED;
  143. }
  144. return NERR_Success;
  145. }
  146. NET_API_STATUS
  147. NetpAccessCheck(
  148. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  149. IN ACCESS_MASK DesiredAccess,
  150. IN PGENERIC_MAPPING GenericMapping
  151. )
  152. /*++
  153. Routine Description:
  154. This function impersonates the caller so that it can perform access
  155. validation using NtAccessCheck; and reverts back to
  156. itself before returning.
  157. This routine differs from NetpAccessCheckAndAudit in that it doesn't require
  158. the caller to have SE_AUDIT_PRIVILEGE nor does it generate audits.
  159. That is typically fine since the passed in security descriptor typically doesn't
  160. have a SACL requesting an audit.
  161. Arguments:
  162. SecurityDescriptor - A pointer to the Security Descriptor against which
  163. acccess is to be checked.
  164. DesiredAccess - Supplies desired acccess mask. This mask must have been
  165. previously mapped to contain no generic accesses.
  166. GenericMapping - Supplies a pointer to the generic mapping associated
  167. with this object type.
  168. Return Value:
  169. NET_API_STATUS - NERR_Success or reason for failure.
  170. --*/
  171. {
  172. NET_API_STATUS NetStatus;
  173. NET_API_STATUS TempStatus;
  174. HANDLE ClientToken = NULL;
  175. DWORD GrantedAccess;
  176. BOOL AccessStatus;
  177. BYTE PrivilegeSet[500]; // Large buffer
  178. DWORD PrivilegeSetSize;
  179. //
  180. // Impersonate the client.
  181. //
  182. NetStatus = RpcImpersonateClient(NULL);
  183. if ( NetStatus != RPC_S_OK ) {
  184. NetpKdPrint(("[Netlib] Failed to impersonate client %08lx\n",
  185. NetStatus));
  186. return NetpRpcStatusToApiStatus(NetStatus);
  187. }
  188. //
  189. // Open the impersonated token.
  190. //
  191. if ( !OpenThreadToken( GetCurrentThread(),
  192. TOKEN_QUERY,
  193. TRUE, // Use NtLmSvc security context to open token
  194. &ClientToken )) {
  195. NetStatus = GetLastError();
  196. NetpKdPrint(("[Netlib] Error calling GetCurrentThread %ld\n",
  197. NetStatus));
  198. goto Cleanup;
  199. }
  200. //
  201. // Check if the client has the required access.
  202. //
  203. PrivilegeSetSize = sizeof(PrivilegeSet);
  204. if ( !AccessCheck( SecurityDescriptor,
  205. ClientToken,
  206. DesiredAccess,
  207. GenericMapping,
  208. (PPRIVILEGE_SET) PrivilegeSet,
  209. &PrivilegeSetSize,
  210. &GrantedAccess,
  211. &AccessStatus ) ) {
  212. NetStatus = GetLastError();
  213. NetpKdPrint(("[Netlib] Error calling AccessCheck %ld\n",
  214. NetStatus));
  215. goto Cleanup;
  216. }
  217. if ( !AccessStatus ) {
  218. NetStatus = GetLastError();
  219. IF_DEBUG(SECURITY) {
  220. NetpKdPrint(("[Netlib] Access status is %ld\n", NetStatus ));
  221. }
  222. goto Cleanup;
  223. }
  224. //
  225. // Success
  226. //
  227. NetStatus = NERR_Success;
  228. //
  229. // Free locally used resources
  230. //
  231. Cleanup:
  232. TempStatus = RpcRevertToSelf();
  233. if ( TempStatus != RPC_S_OK ) {
  234. NetpKdPrint(("[Netlib] Fail to revert to self %08lx\n", TempStatus));
  235. NetpAssert(FALSE);
  236. }
  237. if ( ClientToken != NULL ) {
  238. CloseHandle( ClientToken );
  239. }
  240. return NetStatus;
  241. }