Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

subject.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 Subject.c 00008 00009 Abstract: 00010 00011 This Module implements services related to subject security context. 00012 These services are part of the services provided by the Reference Monitor 00013 component. 00014 00015 FOR PERFORMANCE SAKE, THIS MODULE IS AWARE OF INTERNAL TOKEN OBJECT 00016 FORMATS. 00017 00018 Author: 00019 00020 Jim Kelly (JimK) 2-Aug-1990 00021 00022 Environment: 00023 00024 Kernel Mode 00025 00026 Revision History: 00027 00028 --*/ 00029 00030 #include "sep.h" 00031 #include "seopaque.h" 00032 #include "tokenp.h" 00033 00034 00035 #ifdef ALLOC_PRAGMA 00036 #pragma alloc_text(PAGE,SeCaptureSubjectContext) 00037 #pragma alloc_text(PAGE,SeLockSubjectContext) 00038 #pragma alloc_text(PAGE,SeUnlockSubjectContext) 00039 #pragma alloc_text(PAGE,SeReleaseSubjectContext) 00040 #pragma alloc_text(PAGE,SepGetDefaultsSubjectContext) 00041 #pragma alloc_text(PAGE,SepValidOwnerSubjectContext) 00042 #endif 00043 00044 00045 VOID 00046 SeCaptureSubjectContext ( 00047 OUT PSECURITY_SUBJECT_CONTEXT SubjectContext 00048 ) 00049 00050 /*++ 00051 00052 Routine Description: 00053 00054 This routine takes a snapshot of the calling thread's security 00055 context (locking tokens as necessary to do so). This function 00056 is intended to support the object manager and other components 00057 that utilize the reference monitor's access validation, 00058 privilege test, and audit generation services. 00059 00060 A subject's security context should be captured before initiating 00061 access validation and should be released after audit messages 00062 are generated. This is necessary to provide a consistent security 00063 context to all those services. 00064 00065 After calling access validation, privilege test, and audit generation 00066 services, the captured context should be released as soon as possible 00067 using the SeReleaseSubjectContext() service. 00068 00069 Arguments: 00070 00071 SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure 00072 to be filled in with a snapshot of the calling thread's security 00073 profile. 00074 00075 Return Value: 00076 00077 none. 00078 00079 --*/ 00080 00081 { 00082 00083 PEPROCESS CurrentProcess; 00084 00085 //PVOID Objects[2]; 00086 00087 BOOLEAN IgnoreCopyOnOpen; 00088 BOOLEAN IgnoreEffectiveOnly; 00089 00090 PAGED_CODE(); 00091 00092 CurrentProcess = PsGetCurrentProcess(); 00093 SubjectContext->ProcessAuditId = PsProcessAuditId( CurrentProcess ); 00094 00095 // 00096 // Get pointers to primary and impersonation tokens 00097 // 00098 00099 SubjectContext->ClientToken = PsReferenceImpersonationToken( 00100 PsGetCurrentThread(), 00101 &IgnoreCopyOnOpen, 00102 &IgnoreEffectiveOnly, 00103 &(SubjectContext->ImpersonationLevel) 00104 ); 00105 00106 SubjectContext->PrimaryToken = PsReferencePrimaryToken(CurrentProcess); 00107 00108 return; 00109 00110 } 00111 00112 00113 00114 VOID 00115 SeLockSubjectContext( 00116 IN PSECURITY_SUBJECT_CONTEXT SubjectContext 00117 ) 00118 00119 /*++ 00120 00121 Routine Description: 00122 00123 Acquires READ LOCKS on the primary and impersonation tokens 00124 in the passed SubjectContext. 00125 00126 This call must be undone by a call to SeUnlockSubjectContext(). 00127 00128 No one outside of the SE component should need to acquire a 00129 write lock to a token. Therefore there is no public interface 00130 to do this. 00131 00132 Arguments: 00133 00134 SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure 00135 which points to a primary token and an optional impersonation token. 00136 00137 Return Value: 00138 00139 None 00140 00141 --*/ 00142 00143 { 00144 PAGED_CODE(); 00145 00146 SepAcquireTokenReadLock((PTOKEN)(SubjectContext->PrimaryToken)); 00147 00148 if (ARGUMENT_PRESENT(SubjectContext->ClientToken)) { 00149 00150 SepAcquireTokenReadLock((PTOKEN)(SubjectContext->ClientToken)); 00151 } 00152 00153 return; 00154 } 00155 00156 00157 00158 VOID 00159 SeUnlockSubjectContext( 00160 IN PSECURITY_SUBJECT_CONTEXT SubjectContext 00161 ) 00162 00163 /*++ 00164 00165 Routine Description: 00166 00167 Releases the read locks on the token(s) in the passed SubjectContext. 00168 00169 Arguments: 00170 00171 SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure 00172 which points to a primary token and an optional impersonation token. 00173 00174 Return Value: 00175 00176 None 00177 00178 --*/ 00179 00180 { 00181 PAGED_CODE(); 00182 00183 SepReleaseTokenReadLock((PTOKEN)(SubjectContext->PrimaryToken)); 00184 00185 if (ARGUMENT_PRESENT(SubjectContext->ClientToken)) { 00186 00187 SepReleaseTokenReadLock((PTOKEN)(SubjectContext->ClientToken)); 00188 } 00189 00190 00191 } 00192 00193 00194 00195 VOID 00196 SeReleaseSubjectContext ( 00197 IN PSECURITY_SUBJECT_CONTEXT SubjectContext 00198 ) 00199 00200 /*++ 00201 00202 00203 Routine Description: 00204 00205 This routine releases a subject security context previously captured by 00206 SeCaptureSubjectContext(). 00207 00208 Arguments: 00209 00210 SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure 00211 containing a subject's previously captured security context. 00212 00213 Return Value: 00214 00215 none. 00216 00217 --*/ 00218 00219 { 00220 PAGED_CODE(); 00221 00222 PsDereferencePrimaryToken( SubjectContext->PrimaryToken ); 00223 SubjectContext->PrimaryToken = NULL; 00224 00225 00226 PsDereferenceImpersonationToken( SubjectContext->ClientToken ); 00227 SubjectContext->ClientToken = NULL; 00228 00229 return; 00230 00231 } 00232 00233 VOID 00234 SepGetDefaultsSubjectContext( 00235 IN PSECURITY_SUBJECT_CONTEXT SubjectContext, 00236 OUT PSID *Owner, 00237 OUT PSID *Group, 00238 OUT PSID *ServerOwner, 00239 OUT PSID *ServerGroup, 00240 OUT PACL *Dacl 00241 ) 00242 /*++ 00243 00244 Routine Description: 00245 00246 This routine retrieves pointers to the default owner, primary group, 00247 and, if present, discretionary ACL of the provided subject security 00248 context. 00249 00250 Arguments: 00251 00252 SubjectContext - Points to the subject security context whose default 00253 values are to be retrieved. 00254 00255 Owner - Receives a pointer to the subject's default owner SID. This 00256 value will always be returned as a non-zero pointer. That is, 00257 a subject's security context must contain a owner SID. 00258 00259 Group - Receives a pointer to the subject's default primary group SID. 00260 This value will always be returned as a non-zero pointer. That is, 00261 a subject's security context must contain a primary group. 00262 00263 Dacl - Receives a pointer to the subject's default discretionary ACL, 00264 if one is define for the subject. Note that a subject security context 00265 does not have to include a default discretionary ACL. In this case, 00266 this value will be returned as NULL. 00267 00268 00269 00270 00271 Return Value: 00272 00273 none. 00274 00275 --*/ 00276 00277 { 00278 PTOKEN EffectiveToken; 00279 PTOKEN PrimaryToken; 00280 00281 PAGED_CODE(); 00282 00283 if (ARGUMENT_PRESENT(SubjectContext->ClientToken)) { 00284 EffectiveToken = (PTOKEN)SubjectContext->ClientToken; 00285 } else { 00286 EffectiveToken = (PTOKEN)SubjectContext->PrimaryToken; 00287 } 00288 00289 (*Owner) = EffectiveToken->UserAndGroups[EffectiveToken->DefaultOwnerIndex].Sid; 00290 00291 (*Group) = EffectiveToken->PrimaryGroup; 00292 00293 (*Dacl) = EffectiveToken->DefaultDacl; 00294 00295 PrimaryToken = (PTOKEN)SubjectContext->PrimaryToken; 00296 00297 *ServerOwner = PrimaryToken->UserAndGroups[PrimaryToken->DefaultOwnerIndex].Sid; 00298 00299 *ServerGroup = PrimaryToken->PrimaryGroup; 00300 00301 return; 00302 } 00303 00304 00305 BOOLEAN 00306 SepIdAssignableAsGroup( 00307 IN PACCESS_TOKEN AToken, 00308 IN PSID Group 00309 ) 00310 /*++ 00311 00312 Routine Description: 00313 00314 This routine checks to see whether the provided SID is one that 00315 may be assigned to be the default primary group in a token. 00316 00317 The current criteria is that the passed SID be a group in the 00318 token, with no other restrictions. 00319 00320 Arguments: 00321 00322 Token - Points to the token to be examined. 00323 00324 Group - Points to the SID to be checked. 00325 00326 Return Value: 00327 00328 TRUE - SID passed by be assigned as the default primary group in a token. 00329 00330 FALSE - Passed SID may not be so assigned. 00331 00332 --*/ 00333 00334 { 00335 ULONG Index; 00336 BOOLEAN Found = FALSE; 00337 PTOKEN Token; 00338 00339 PAGED_CODE(); 00340 00341 Token = (PTOKEN)AToken; 00342 00343 // 00344 // Let's make it invalid to assign a NULL primary group, 00345 // but we may need to revisit this. 00346 // 00347 00348 if (Group == NULL) { 00349 return( FALSE ); 00350 } 00351 00352 SepAcquireTokenReadLock( Token ); 00353 00354 // 00355 // Walk through the list of user and group IDs looking 00356 // for a match to the specified SID. 00357 // 00358 00359 Index = 0; 00360 while (Index < Token->UserAndGroupCount) { 00361 00362 Found = RtlEqualSid( 00363 Group, 00364 Token->UserAndGroups[Index].Sid 00365 ); 00366 00367 if ( Found ) { 00368 break; 00369 } 00370 00371 Index += 1; 00372 } 00373 00374 SepReleaseTokenReadLock( Token ); 00375 00376 return Found; 00377 } 00378 00379 00380 BOOLEAN 00381 SepValidOwnerSubjectContext( 00382 IN PSECURITY_SUBJECT_CONTEXT SubjectContext, 00383 IN PSID Owner, 00384 IN BOOLEAN ServerObject 00385 ) 00386 /*++ 00387 00388 Routine Description: 00389 00390 This routine checks to see whether the provided SID is one the subject 00391 is authorized to assign as the owner of objects. It will also check to 00392 see if the caller has SeRestorePrivilege, if so, the request is granted. 00393 00394 Arguments: 00395 00396 SubjectContext - Points to the subject's security context. 00397 00398 Owner - Points to the SID to be checked. 00399 00400 00401 00402 Return Value: 00403 00404 none. 00405 00406 --*/ 00407 00408 { 00409 00410 ULONG Index; 00411 BOOLEAN Found; 00412 PTOKEN EffectiveToken; 00413 BOOLEAN Rc = FALSE; 00414 00415 PAGED_CODE(); 00416 00417 // 00418 // It is invalid to assign a NULL owner, regardless of 00419 // whether you have SeRestorePrivilege or not. 00420 // 00421 00422 if (Owner == NULL) { 00423 return( FALSE ); 00424 } 00425 00426 // 00427 // Allowable owners come from the primary if it's a server object. 00428 // 00429 00430 if (!ServerObject && ARGUMENT_PRESENT(SubjectContext->ClientToken)) { 00431 EffectiveToken = (PTOKEN)SubjectContext->ClientToken; 00432 } else { 00433 EffectiveToken = (PTOKEN)SubjectContext->PrimaryToken; 00434 } 00435 00436 00437 // 00438 // If we're impersonating, make sure we're at TokenImpersonation 00439 // or above. This prevents someone from setting the owner of an 00440 // object when impersonating at less Identify or Anonymous. 00441 // 00442 00443 if (EffectiveToken->TokenType == TokenImpersonation) { 00444 00445 if (EffectiveToken->ImpersonationLevel < SecurityImpersonation) { 00446 00447 return( FALSE ); 00448 00449 } 00450 } 00451 00452 SepAcquireTokenReadLock( EffectiveToken ); 00453 00454 // 00455 // Walk through the list of user and group IDs looking 00456 // for a match to the specified SID. If one is found, 00457 // make sure it may be assigned as an owner. 00458 // 00459 // This code is similar to that performed to set the default 00460 // owner of a token (NtSetInformationToken). 00461 // 00462 00463 Index = 0; 00464 while (Index < EffectiveToken->UserAndGroupCount) { 00465 00466 00467 Found = RtlEqualSid( 00468 Owner, 00469 EffectiveToken->UserAndGroups[Index].Sid 00470 ); 00471 00472 if ( Found ) { 00473 00474 // 00475 // We may return success if the Sid is one that may be assigned 00476 // as an owner, or if the caller has SeRestorePrivilege 00477 // 00478 00479 if ( SepIdAssignableAsOwner(EffectiveToken,Index) ) { 00480 00481 SepReleaseTokenReadLock( EffectiveToken ); 00482 Rc = TRUE; 00483 goto exit; 00484 00485 } else { 00486 00487 // 00488 // Rc is already set to FALSE, just exit. 00489 // 00490 00491 SepReleaseTokenReadLock( EffectiveToken ); 00492 goto exit; 00493 00494 } //endif assignable 00495 00496 00497 } //endif Found 00498 00499 00500 Index += 1; 00501 00502 } //endwhile 00503 00504 00505 SepReleaseTokenReadLock( EffectiveToken ); 00506 00507 exit: 00508 00509 // 00510 // If we are going to fail this call, check for Restore privilege, 00511 // and succeed if he has it. 00512 // 00513 00514 // 00515 // We should really have gotten PreviousMode from the caller, but we 00516 // didn't, so hard wire it to be user-mode here. 00517 // 00518 00519 if ( Rc == FALSE ) { 00520 Rc = SeSinglePrivilegeCheck( SeRestorePrivilege, UserMode ); 00521 } 00522 00523 return Rc; 00524 } 00525 00526 00527 00528 NTSTATUS 00529 SeQueryAuthenticationIdSubjectContext( 00530 IN PSECURITY_SUBJECT_CONTEXT SubjectContext, 00531 OUT PLUID AuthenticationId 00532 ) 00533 /*++ 00534 00535 Routine Description: 00536 00537 This routine returns the authentication ID for the effective token 00538 in a subject context 00539 00540 Parameters: 00541 00542 SubjectContext - The subject context to get the ID from 00543 00544 AuthenticationId - Receives the authentication ID from the token 00545 00546 Return Value: 00547 00548 Errors from SeQueryAuthenticationidToken. 00549 00550 --*/ 00551 { 00552 NTSTATUS Status; 00553 00554 SeLockSubjectContext( SubjectContext ); 00555 00556 00557 Status = SeQueryAuthenticationIdToken( 00558 EffectiveToken(SubjectContext), 00559 AuthenticationId 00560 ); 00561 00562 SeUnlockSubjectContext( SubjectContext ); 00563 00564 return( Status ); 00565 00566 00567 }

Generated on Sat May 15 19:41:54 2004 for test by doxygen 1.3.7