Windows NT 4.0 source code leak
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.

432 lines
9.3 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Subject.c
  5. Abstract:
  6. This Module implements services related to subject security context.
  7. These services are part of the services provided by the Reference Monitor
  8. component.
  9. FOR PERFORMANCE SAKE, THIS MODULE IS AWARE OF INTERNAL TOKEN OBJECT
  10. FORMATS.
  11. Author:
  12. Jim Kelly (JimK) 2-Aug-1990
  13. Environment:
  14. Kernel Mode
  15. Revision History:
  16. --*/
  17. #include "sep.h"
  18. #include "seopaque.h"
  19. #include "tokenp.h"
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(PAGE,SeCaptureSubjectContext)
  22. #pragma alloc_text(PAGE,SeLockSubjectContext)
  23. #pragma alloc_text(PAGE,SeUnlockSubjectContext)
  24. #pragma alloc_text(PAGE,SeReleaseSubjectContext)
  25. #pragma alloc_text(PAGE,SepGetDefaultsSubjectContext)
  26. #pragma alloc_text(PAGE,SepValidOwnerSubjectContext)
  27. #endif
  28. VOID
  29. SeCaptureSubjectContext (
  30. OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
  31. )
  32. /*++
  33. Routine Description:
  34. This routine takes a snapshot of the calling thread's security
  35. context (locking tokens as necessary to do so). This function
  36. is intended to support the object manager and other components
  37. that utilize the reference monitor's access validation,
  38. privilege test, and audit generation services.
  39. A subject's security context should be captured before initiating
  40. access validation and should be released after audit messages
  41. are generated. This is necessary to provide a consistent security
  42. context to all those services.
  43. After calling access validation, privilege test, and audit generation
  44. services, the captured context should be released as soon as possible
  45. using the SeReleaseSubjectContext() service.
  46. Arguments:
  47. SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure
  48. to be filled in with a snapshot of the calling thread's security
  49. profile.
  50. Return Value:
  51. none.
  52. --*/
  53. {
  54. PEPROCESS CurrentProcess;
  55. //PVOID Objects[2];
  56. BOOLEAN IgnoreCopyOnOpen;
  57. BOOLEAN IgnoreEffectiveOnly;
  58. PAGED_CODE();
  59. CurrentProcess = PsGetCurrentProcess();
  60. SubjectContext->ProcessAuditId = PsProcessAuditId( CurrentProcess );
  61. //
  62. // Get pointers to primary and impersonation tokens
  63. //
  64. SubjectContext->ClientToken = PsReferenceImpersonationToken(
  65. PsGetCurrentThread(),
  66. &IgnoreCopyOnOpen,
  67. &IgnoreEffectiveOnly,
  68. &(SubjectContext->ImpersonationLevel)
  69. );
  70. SubjectContext->PrimaryToken = PsReferencePrimaryToken(CurrentProcess);
  71. return;
  72. }
  73. VOID
  74. SeLockSubjectContext(
  75. IN PSECURITY_SUBJECT_CONTEXT SubjectContext
  76. )
  77. /*++
  78. Routine Description:
  79. Acquires READ LOCKS on the primary and impersonation tokens
  80. in the passed SubjectContext.
  81. This call must be undone by a call to SeUnlockSubjectContext().
  82. No one outside of the SE component should need to acquire a
  83. write lock to a token. Therefore there is no public interface
  84. to do this.
  85. Arguments:
  86. SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure
  87. which points to a primary token and an optional impersonation token.
  88. Return Value:
  89. None
  90. --*/
  91. {
  92. PAGED_CODE();
  93. SepAcquireTokenReadLock((PTOKEN)(SubjectContext->PrimaryToken));
  94. if (ARGUMENT_PRESENT(SubjectContext->ClientToken)) {
  95. SepAcquireTokenReadLock((PTOKEN)(SubjectContext->ClientToken));
  96. }
  97. return;
  98. }
  99. VOID
  100. SeUnlockSubjectContext(
  101. IN PSECURITY_SUBJECT_CONTEXT SubjectContext
  102. )
  103. /*++
  104. Routine Description:
  105. Releases the read locks on the token(s) in the passed SubjectContext.
  106. Arguments:
  107. SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure
  108. which points to a primary token and an optional impersonation token.
  109. Return Value:
  110. None
  111. --*/
  112. {
  113. PAGED_CODE();
  114. SepReleaseTokenReadLock((PTOKEN)(SubjectContext->PrimaryToken));
  115. if (ARGUMENT_PRESENT(SubjectContext->ClientToken)) {
  116. SepReleaseTokenReadLock((PTOKEN)(SubjectContext->ClientToken));
  117. }
  118. }
  119. VOID
  120. SeReleaseSubjectContext (
  121. IN PSECURITY_SUBJECT_CONTEXT SubjectContext
  122. )
  123. /*++
  124. Routine Description:
  125. This routine releases a subject security context previously captured by
  126. SeCaptureSubjectContext().
  127. Arguments:
  128. SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure
  129. containing a subject's previously captured security context.
  130. Return Value:
  131. none.
  132. --*/
  133. {
  134. PAGED_CODE();
  135. PsDereferencePrimaryToken( SubjectContext->PrimaryToken );
  136. PsDereferenceImpersonationToken( SubjectContext->ClientToken );
  137. return;
  138. }
  139. VOID
  140. SepGetDefaultsSubjectContext(
  141. IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
  142. OUT PSID *Owner,
  143. OUT PSID *Group,
  144. OUT PSID *ServerOwner,
  145. OUT PSID *ServerGroup,
  146. OUT PACL *Dacl
  147. )
  148. /*++
  149. Routine Description:
  150. This routine retrieves pointers to the default owner, primary group,
  151. and, if present, discretionary ACL of the provided subject security
  152. context.
  153. Arguments:
  154. SubjectContext - Points to the subject security context whose default
  155. values are to be retrieved.
  156. Owner - Receives a pointer to the subject's default owner SID. This
  157. value will always be returned as a non-zero pointer. That is,
  158. a subject's security context must contain a owner SID.
  159. Group - Receives a pointer to the subject's default primary group SID.
  160. This value will always be returned as a non-zero pointer. That is,
  161. a subject's security context must contain a primary group.
  162. Dacl - Receives a pointer to the subject's default discretionary ACL,
  163. if one is define for the subject. Note that a subject security context
  164. does not have to include a default discretionary ACL. In this case,
  165. this value will be returned as NULL.
  166. Return Value:
  167. none.
  168. --*/
  169. {
  170. PTOKEN EffectiveToken;
  171. PTOKEN PrimaryToken;
  172. PAGED_CODE();
  173. if (ARGUMENT_PRESENT(SubjectContext->ClientToken)) {
  174. EffectiveToken = (PTOKEN)SubjectContext->ClientToken;
  175. } else {
  176. EffectiveToken = (PTOKEN)SubjectContext->PrimaryToken;
  177. }
  178. (*Owner) = EffectiveToken->UserAndGroups[EffectiveToken->DefaultOwnerIndex].Sid;
  179. (*Group) = EffectiveToken->PrimaryGroup;
  180. (*Dacl) = EffectiveToken->DefaultDacl;
  181. PrimaryToken = (PTOKEN)SubjectContext->PrimaryToken;
  182. *ServerOwner = PrimaryToken->UserAndGroups[PrimaryToken->DefaultOwnerIndex].Sid;
  183. *ServerGroup = PrimaryToken->PrimaryGroup;
  184. return;
  185. }
  186. BOOLEAN
  187. SepValidOwnerSubjectContext(
  188. IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
  189. IN PSID Owner,
  190. IN BOOLEAN ServerObject
  191. )
  192. /*++
  193. Routine Description:
  194. This routine checks to see whether the provided SID is one the subject
  195. is authorized to assign as the owner of objects. It will also check to
  196. see if the caller has SeRestorePrivilege, if so, the request is granted.
  197. Arguments:
  198. SubjectContext - Points to the subject's security context.
  199. Owner - Points to the SID to be checked.
  200. Return Value:
  201. none.
  202. --*/
  203. {
  204. ULONG Index;
  205. BOOLEAN Found;
  206. PTOKEN EffectiveToken;
  207. BOOLEAN Rc = FALSE;
  208. PAGED_CODE();
  209. //
  210. // It is invalid to assign a NULL owner, regardless of
  211. // whether you have SeRestorePrivilege or not.
  212. //
  213. if (Owner == NULL) {
  214. return( FALSE );
  215. }
  216. //
  217. // Allowable owners come from the primary if it's a server object.
  218. //
  219. if (!ServerObject && ARGUMENT_PRESENT(SubjectContext->ClientToken)) {
  220. EffectiveToken = (PTOKEN)SubjectContext->ClientToken;
  221. } else {
  222. EffectiveToken = (PTOKEN)SubjectContext->PrimaryToken;
  223. }
  224. SepAcquireTokenReadLock( EffectiveToken );
  225. //
  226. // Walk through the list of user and group IDs looking
  227. // for a match to the specified SID. If one is found,
  228. // make sure it may be assigned as an owner.
  229. //
  230. // This code is similar to that performed to set the default
  231. // owner of a token (NtSetInformationToken).
  232. //
  233. Index = 0;
  234. while (Index < EffectiveToken->UserAndGroupCount) {
  235. Found = RtlEqualSid(
  236. Owner,
  237. EffectiveToken->UserAndGroups[Index].Sid
  238. );
  239. if ( Found ) {
  240. //
  241. // We may return success if the Sid is one that may be assigned
  242. // as an owner, or if the caller has SeRestorePrivilege
  243. //
  244. if ( SepIdAssignableAsOwner(EffectiveToken,Index) ) {
  245. SepReleaseTokenReadLock( EffectiveToken );
  246. Rc = TRUE;
  247. goto exit;
  248. } else {
  249. //
  250. // Rc is already set to FALSE, just exit.
  251. //
  252. SepReleaseTokenReadLock( EffectiveToken );
  253. goto exit;
  254. } //endif assignable
  255. } //endif Found
  256. Index += 1;
  257. } //endwhile
  258. SepReleaseTokenReadLock( EffectiveToken );
  259. exit:
  260. //
  261. // If we are going to fail this call, check for Restore privilege,
  262. // and succeed if he has it.
  263. //
  264. //
  265. // We should really have gotten PreviousMode from the caller, but we
  266. // didn't, so hard wire it to be user-mode here.
  267. //
  268. if ( Rc == FALSE ) {
  269. Rc = SeSinglePrivilegeCheck( SeRestorePrivilege, UserMode );
  270. }
  271. return Rc;
  272. }