test: token.c Source File

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

# token.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     token.c
    00008
    00009 Abstract:
    00010
    00011    This module implements the initialization, open, duplicate and other
    00012    services of the executive token object.
    00013
    00014 Author:
    00015
    00016     Jim Kelly (JimK) 5-April-1990
    00017
    00018 Environment:
    00019
    00020     Kernel mode only.
    00021
    00022 Revision History:
    00023
    00024     v15: robertre
    00025          updated ACL_REVISION
    00026
    00027 --*/
    00028
    00029
    00030 #include "sep.h"
    00031 #include "sertlp.h"
    00032 #include <zwapi.h>
    00033 #include "tokenp.h"
    00034
    00035 #ifdef ALLOC_PRAGMA
    00036 #pragma alloc_text(INIT,SepTokenInitialization)
    00037 #pragma alloc_text(INIT,SeMakeSystemToken)
    00038 #pragma alloc_text(INIT,SeMakeAnonymousToken)
    00039 #pragma alloc_text(PAGE,SeTokenType)
    00040 #pragma alloc_text(PAGE,SeTokenIsAdmin)
    00041 #pragma alloc_text(PAGE,SepCreateToken)
    00042 #pragma alloc_text(PAGE,SeTokenImpersonationLevel)
    00043 #pragma alloc_text(PAGE,SeAssignPrimaryToken)
    00044 #pragma alloc_text(PAGE,SeDeassignPrimaryToken)
    00045 #pragma alloc_text(PAGE,SeExchangePrimaryToken)
    00046 #pragma alloc_text(PAGE,SeGetTokenControlInformation)
    00047 #pragma alloc_text(PAGE,SeSubProcessToken)
    00048 #pragma alloc_text(PAGE,NtCreateToken)
    00049 #pragma alloc_text(PAGE,SepTokenDeleteMethod)
    00050 #pragma alloc_text(PAGE,SepIdAssignableAsOwner)
    00051 #pragma alloc_text(PAGE,SeIsChildToken)
    00052 #pragma alloc_text(PAGE,SeIsChildTokenByPointer)
    00053 #pragma alloc_text(PAGE,NtImpersonateAnonymousToken)
    00054 #endif
    00055
    00056
    00058 //                                                                    //
    00059 //           Global Variables                                         //
    00060 //                                                                    //
    00062
    00063 //
    00064 // Generic mapping of access types
    00065 //
    00066
    00067 GENERIC_MAPPING SepTokenMapping = { TOKEN_READ,
    00068                                     TOKEN_WRITE,
    00069                                     TOKEN_EXECUTE,
    00070                                     TOKEN_ALL_ACCESS
    00071                                   };
    00072
    00073 //
    00074 // Address of token object type descriptor.
    00075 //
    00076
    00077 POBJECT_TYPE SepTokenObjectType;
    00078
    00079
    00080 //
    00081 // Used to track whether or not a system token has been created or not.
    00082 //
    00083
    00084 #if DBG
    00085 BOOLEAN SystemTokenCreated = FALSE;
    00086 #endif //DBG
    00087
    00088
    00089 //
    00090 // Token lock
    00091 //
    00092
    00093 ERESOURCE    SepTokenLock;
    00094
    00095
    00096
    00097
    00098 //
    00099 // Used to control the active token diagnostic support provided
    00100 //
    00101
    00102 #ifdef    TOKEN_DIAGNOSTICS_ENABLED
    00103 ULONG TokenGlobalFlag = 0;
    00104 #endif // TOKEN_DIAGNOSTICS_ENABLED
    00105
    00106
    00107
    00109 //                                                                    //
    00110 //           Token Object Routines & Methods                          //
    00111 //                                                                    //
    00113
    00114
    00115
    00116
    00117 TOKEN_TYPE
    00118 SeTokenType(
    00119     IN PACCESS_TOKEN Token
    00120     )
    00121
    00122 /*++
    00123
    00124 Routine Description:
    00125
    00126     This function returns the type of an instance of a token (TokenPrimary,
    00127     or TokenImpersonation).
    00128
    00129
    00130 Arguments:
    00131
    00132     Token - Points to the token whose type is to be returned.
    00133
    00134 Return Value:
    00135
    00136     The token's type.
    00137
    00138 --*/
    00139
    00140 {
    00141     PAGED_CODE();
    00142
    00143     return (((PTOKEN)Token)->TokenType);
    00144 }
    00145
    00146
    00147
    00148 NTKERNELAPI
    00149 BOOLEAN
    00150 SeTokenIsAdmin(
    00151     IN PACCESS_TOKEN Token
    00152     )
    00153
    00154 /*++
    00155
    00156 Routine Description:
    00157
    00158     Returns if the token is a member of the local admin group.
    00159
    00160 Arguments:
    00161
    00162     Token - Points to the token.
    00163
    00164 Return Value:
    00165
    00166     TRUE - Token contains the local admin group
    00167     FALSE - no admin.
    00168
    00169 --*/
    00170
    00171 {
    00172     PAGED_CODE();
    00173
    00174     return ((((PTOKEN)Token)->TokenFlags & TOKEN_HAS_ADMIN_GROUP) != 0 );
    00175 }
    00176
    00177
    00178
    00179 NTKERNELAPI
    00180 BOOLEAN
    00181 SeTokenIsRestricted(
    00182     IN PACCESS_TOKEN Token
    00183     )
    00184
    00185 /*++
    00186
    00187 Routine Description:
    00188
    00189     Returns if the token is a restricted token.
    00190
    00191 Arguments:
    00192
    00193     Token - Points to the token.
    00194
    00195 Return Value:
    00196
    00197     TRUE - Token contains restricted sids
    00198     FALSE - no admin.
    00199
    00200 --*/
    00201
    00202 {
    00203     PAGED_CODE();
    00204
    00205     return ((((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0 );
    00206 }
    00207
    00208
    00209
    00210 SECURITY_IMPERSONATION_LEVEL
    00211 SeTokenImpersonationLevel(
    00212     IN PACCESS_TOKEN Token
    00213     )
    00214
    00215 /*++
    00216
    00217 Routine Description:
    00218
    00219     This function returns the impersonation level of a token.  The token
    00220     is assumed to be a TokenImpersonation type token.
    00221
    00222
    00223 Arguments:
    00224
    00225     Token - Points to the token whose impersonation level is to be returned.
    00226
    00227 Return Value:
    00228
    00229     The token's impersonation level.
    00230
    00231 --*/
    00232
    00233 {
    00234     PAGED_CODE();
    00235
    00236     return ((PTOKEN)Token)->ImpersonationLevel;
    00237 }
    00238
    00239
    00240 VOID
    00241 SeAssignPrimaryToken(
    00242     IN PEPROCESS Process,
    00243     IN PACCESS_TOKEN Token
    00244     )
    00245
    00246
    00247 /*++
    00248
    00249 Routine Description:
    00250
    00251     This function establishes a primary token for a process.
    00252
    00253 Arguments:
    00254
    00255     Token - Points to the new primary token.
    00256
    00257 Return Value:
    00258
    00259     None.
    00260
    00261 --*/
    00262
    00263 {
    00264
    00265     NTSTATUS
    00266         Status;
    00267
    00268     PTOKEN
    00269         NewToken = (PTOKEN)Token;
    00270
    00271     PAGED_CODE();
    00272
    00273     ASSERT(NewToken->TokenType == TokenPrimary);
    00274     ASSERT( !NewToken->TokenInUse );
    00275
    00276
    00277     //
    00278     // Dereference the old token if there is one.
    00279     //
    00280     // Processes typically already have a token that must be
    00281     // dereferenced.  There are two cases where this may not
    00282     // be the situation.  First, during phase 0 system initialization,
    00283     // the initial system process starts out without a token.  Second,
    00284     // if an error occurs during process creation, we may be cleaning
    00285     // up a process that hasn't yet had a primary token assigned.
    00286     //
    00287
    00288     if (Process->Token != NULL) {
    00289         SeDeassignPrimaryToken( Process );
    00290     }
    00291
    00292
    00293     Process->Token=Token;
    00294     NewToken->TokenInUse = TRUE;
    00295     ObReferenceObject(NewToken);
    00296     return;
    00297 }
    00298
    00299
    00300
    00301 VOID
    00302 SeDeassignPrimaryToken(
    00303     IN PEPROCESS Process
    00304     )
    00305
    00306
    00307 /*++
    00308
    00309 Routine Description:
    00310
    00311     This function causes a process reference to a token to be
    00312     dropped.
    00313
    00314 Arguments:
    00315
    00316     Process - Points to the process whose primary token is no longer needed.
    00317         This is probably only the case at process deletion or when
    00318         a primary token is being replaced.
    00319
    00320 Return Value:
    00321
    00322     None.
    00323
    00324 --*/
    00325
    00326 {
    00327
    00328     PTOKEN
    00329         OldToken = (PTOKEN)(Process->Token);
    00330
    00331     PAGED_CODE();
    00332
    00333     ASSERT(OldToken->TokenType == TokenPrimary);
    00334     ASSERT(OldToken->TokenInUse);
    00335
    00336     OldToken->TokenInUse = FALSE;
    00337     ObDereferenceObject( OldToken );
    00338
    00339
    00340     return;
    00341 }
    00342
    00343
    00344
    00345 NTSTATUS
    00346 SeExchangePrimaryToken(
    00347     IN PEPROCESS Process,
    00348     IN PACCESS_TOKEN NewAccessToken,
    00349     OUT PACCESS_TOKEN *OldAccessToken
    00350     )
    00351
    00352
    00353 /*++
    00354
    00355 Routine Description:
    00356
    00357     This function is used to perform the portions of changing a primary
    00358     token that reference the internals of token structures.
    00359
    00360     The new token is checked to make sure it is not already in use.
    00361
    00362     The
    00363
    00364
    00365     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    00366     !!!!!!!!       WARNING     WARNING     WARNING        !!!!!!!!
    00367     !!!!!!!!                                              !!!!!!!!
    00368     !!!!!!!!  THIS ROUTINE MUST BE CALLED WITH THE GOBAL  !!!!!!!!
    00369     !!!!!!!!  PROCESS SECURITY FIELDS LOCK HELD           !!!!!!!!
    00370     !!!!!!!!                                              !!!!!!!!
    00371     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    00372
    00373 Arguments:
    00374
    00375     Process - Points to the process whose primary token is being exchanged.
    00376
    00377     NewAccessToken - Points to the process's new primary token.
    00378
    00379     OldAccessToken - Receives a pointer to the process's current token.
    00380         The caller is responsible for dereferencing this token when
    00381         it is no longer needed.  This can't be done while the process
    00382         security locks are held.
    00383
    00384
    00385 Return Value:
    00386
    00387     STATUS_SUCCESS - Everything has been updated.
    00388
    00389     STATUS_TOKEN_ALREADY_IN_USE - A primary token can only be used by a
    00390         single process.  That is, each process must have its own primary
    00391         token.  The token passed to  be assigned as the primary token is
    00392         already in use as a primary token.
    00393
    00394     STATUS_BAD_TOKEN_TYPE - The new token is not a primary token.
    00395
    00396
    00397 --*/
    00398
    00399 {
    00400     NTSTATUS
    00401         Status;
    00402
    00403     PTOKEN
    00404         OldToken = (PTOKEN)(Process->Token);
    00405
    00406     PTOKEN
    00407         NewToken = (PTOKEN)NewAccessToken;
    00408
    00409     PAGED_CODE();
    00410
    00411
    00412     //
    00413     // We need to access the security fields of both tokens.
    00414     // Access to these fields is guarded by the global Process Security
    00415     // fields lock.
    00416     //
    00417
    00418     ASSERT(OldToken->TokenType == TokenPrimary);
    00419     ASSERT(OldToken->TokenInUse);
    00420
    00421
    00422     //
    00423     // Make sure the new token is a primary token...
    00424     //
    00425
    00426     if ( NewToken->TokenType != TokenPrimary ) {
    00427         return(STATUS_BAD_TOKEN_TYPE);
    00428     }
    00429
    00430     //
    00431     // and that it is not already in use...
    00432     //
    00433
    00434     if (NewToken->TokenInUse) {
    00435         return(STATUS_TOKEN_ALREADY_IN_USE);
    00436     }
    00437
    00438     //
    00439     // Ensure SessionId consistent for hydra
    00440     //
    00441
    00442     NewToken->SessionId = OldToken->SessionId ;
    00443
    00444
    00445
    00446     //
    00447     // Switch the tokens
    00448     //
    00449
    00450     Process->Token=NewAccessToken;
    00451     NewToken->TokenInUse = TRUE;
    00452     ObReferenceObject(NewToken);
    00453
    00454     //
    00455     // Mark the token as "NOT USED"
    00456     //
    00457
    00458     OldToken->TokenInUse = FALSE;
    00459
    00460     //
    00461     // Return the pointer to the old token.  The caller
    00462     // is responsible for dereferencing it if they don't need it.
    00463     //
    00464
    00465     (*OldAccessToken) = OldToken;
    00466
    00467     return (STATUS_SUCCESS);
    00468 }
    00469
    00470
    00471
    00472
    00473
    00474 VOID
    00475 SeGetTokenControlInformation (
    00476     IN PACCESS_TOKEN Token,
    00477     OUT PTOKEN_CONTROL TokenControl
    00478     )
    00479
    00480 /*++
    00481
    00482 Routine Description:
    00483
    00484     This routine is provided for communication session layers, or
    00485     any other executive component that needs to keep track of
    00486     whether a caller's security context has changed between calls.
    00487     Communication session layers will need to check this, for some
    00488     security quality of service modes, to determine whether or not
    00489     a server's security context needs to be updated to reflect
    00490     changes in the client's security context.
    00491
    00492     This routine will also be useful to communications subsystems
    00493     that need to retrieve client' authentication information from
    00494     the local security authority in order to perform a remote
    00495     authentication.
    00496
    00497
    00498 Parameters:
    00499
    00500     Token - Points to the token whose information is to be retrieved.
    00501
    00502     TokenControl - Points to the buffer to receive the token control
    00503         information.
    00504
    00505 Return Value:
    00506
    00507     None.
    00508
    00509 --*/
    00510
    00511 {
    00512     PAGED_CODE();
    00513
    00514     //
    00515     //  acquire exclusive access to the token
    00516     //
    00517
    00518     SepAcquireTokenReadLock( (PTOKEN)Token );
    00519
    00520     //
    00521     //  Grab the data  and  run
    00522     //
    00523
    00524     TokenControl->TokenId = ((TOKEN *)Token)->TokenId;
    00525     TokenControl->AuthenticationId = ((TOKEN *)Token)->AuthenticationId;
    00526     TokenControl->ModifiedId = ((TOKEN *)Token)->ModifiedId;
    00527     TokenControl->TokenSource = ((TOKEN *)Token)->TokenSource;
    00528
    00529     SepReleaseTokenReadLock( (PTOKEN)Token );
    00530
    00531     return;
    00532
    00533 }
    00534
    00535 PACCESS_TOKEN
    00536 SeMakeSystemToken ()
    00537
    00538 /*++
    00539
    00540 Routine Description:
    00541
    00542     This routine is provided for use by executive components
    00543     DURING SYSTEM INITIALIZATION ONLY.  It creates a token for
    00544     use by system components.
    00545
    00546     A system token has the following characteristics:
    00547
    00548          - It has LOCAL_SYSTEM as its user ID
    00549
    00550          - It has the following groups with the corresponding
    00551            attributes:
    00552
    00553                ADMINS_ALIAS      EnabledByDefault |
    00554                                  Enabled          |
    00555                                  Owner
    00556
    00557                WORLD             EnabledByDefault |
    00558                                  Enabled          |
    00559                                  Mandatory
    00560
    00561                ADMINISTRATORS (alias)  Owner   (disabled)
    00562
    00563                AUTHENTICATED_USER
    00564                                 EnabledByDefault  |
    00565                                 Enabled           |
    00566                                 Mandatory
    00567
    00568
    00569          - It has LOCAL_SYSTEM as its primary group.
    00570
    00571          - It has the privileges shown in comments below.
    00572
    00573
    00574          - It has protection that provides TOKEN_ALL_ACCESS to
    00575            the LOCAL_SYSTEM ID.
    00576
    00577
    00578          - It has a default ACL that grants GENERIC_ALL access
    00579            to LOCAL_SYSTEM and GENERIC_EXECUTE to WORLD.
    00580
    00581
    00582 Parameters:
    00583
    00584     None.
    00585
    00586 Return Value:
    00587
    00588     Pointer to a system token.
    00589
    00590 --*/
    00591
    00592 {
    00593     NTSTATUS Status;
    00594
    00595     PVOID Token;
    00596
    00597     SID_AND_ATTRIBUTES UserId;
    00598     TOKEN_PRIMARY_GROUP PrimaryGroup;
    00599     PSID_AND_ATTRIBUTES GroupIds;
    00600     ULONG GroupIdsLength;
    00601     LUID_AND_ATTRIBUTES Privileges[30];
    00602     PACL TokenAcl;
    00603     PSID Owner;
    00604     ULONG NormalGroupAttributes;
    00605     ULONG OwnerGroupAttributes;
    00606     ULONG Length;
    00607     OBJECT_ATTRIBUTES TokenObjectAttributes;
    00608     PSECURITY_DESCRIPTOR TokenSecurityDescriptor;
    00609     ULONG BufferLength;
    00610     PVOID Buffer;
    00611
    00612     ULONG_PTR GroupIdsBuffer[128 * sizeof(ULONG) / sizeof(ULONG_PTR)];
    00613
    00614     TIME_FIELDS TimeFields;
    00615     LARGE_INTEGER NoExpiration;
    00616
    00617     PAGED_CODE();
    00618
    00619
    00620     //
    00621     // Make sure only one system token gets created.
    00622     //
    00623
    00624 #if DBG
    00625     ASSERT( !SystemTokenCreated );
    00626     SystemTokenCreated = TRUE;
    00627 #endif //DBG
    00628
    00629
    00630     //
    00631     // Set up expiration times
    00632     //
    00633
    00634     TimeFields.Year = 3000;
    00635     TimeFields.Month = 1;
    00636     TimeFields.Day = 1;
    00637     TimeFields.Hour = 1;
    00638     TimeFields.Minute = 1;
    00639     TimeFields.Second = 1;
    00640     TimeFields.Milliseconds = 1;
    00641     TimeFields.Weekday = 1;
    00642
    00643     RtlTimeFieldsToTime( &TimeFields, &NoExpiration );
    00644
    00645
    00646 //    //
    00647 //    //  The amount of memory used in the following is gross overkill, but
    00648 //    //  it is freed up immediately after creating the token.
    00649 //    //
    00650 //
    00651 //    GroupIds = (PSID_AND_ATTRIBUTES)ExAllocatePool( NonPagedPool, 512 );
    00652
    00653     GroupIds = (PSID_AND_ATTRIBUTES)GroupIdsBuffer;
    00654
    00655
    00656     //
    00657     // Set up the attributes to be assigned to groups
    00658     //
    00659
    00660     NormalGroupAttributes =    (SE_GROUP_MANDATORY          |
    00661                                 SE_GROUP_ENABLED_BY_DEFAULT |
    00662                                 SE_GROUP_ENABLED
    00663                                 );
    00664
    00665     OwnerGroupAttributes  =    (SE_GROUP_ENABLED_BY_DEFAULT |
    00666                                 SE_GROUP_ENABLED            |
    00667                                 SE_GROUP_OWNER
    00668                                 );
    00669
    00670     //
    00671     // Set up the user ID
    00672     //
    00673
    00674     UserId.Sid = SeLocalSystemSid;
    00675     UserId.Attributes = 0;
    00676
    00677     //
    00678     // Set up the groups
    00679     //
    00680
    00681
    00682     GroupIds->Sid  = SeAliasAdminsSid;
    00683     (GroupIds+1)->Sid  = SeWorldSid;
    00684     (GroupIds+2)->Sid  = SeAuthenticatedUsersSid;
    00685
    00686     GroupIds->Attributes  = OwnerGroupAttributes;
    00687     (GroupIds+1)->Attributes  = NormalGroupAttributes;
    00688     (GroupIds+2)->Attributes  = NormalGroupAttributes;
    00689
    00690     GroupIdsLength = (ULONG)LongAlignSize(SeLengthSid(GroupIds->Sid)) +
    00691                      (ULONG)LongAlignSize(SeLengthSid((GroupIds+1)->Sid)) +
    00692                      (ULONG)LongAlignSize(SeLengthSid((GroupIds+2)->Sid)) +
    00693                      sizeof(SID_AND_ATTRIBUTES);
    00694
    00695     ASSERT( GroupIdsLength <= 128 * sizeof(ULONG) );
    00696
    00697
    00698     //
    00699     // Privileges
    00700     //
    00701
    00702     //
    00703     // The privileges in the system token are as follows:
    00704     //
    00705     //    Privilege Name                           Attributes
    00706     //    --------------                           ----------
    00707     //
    00708     // SeTcbPrivilege                        enabled/enabled by default
    00709     // SeCreateTokenPrivilege                DISabled/NOT enabled by default
    00710     // SeTakeOwnershipPrivilege              DISabled/NOT enabled by default
    00711     // SeCreatePagefilePrivilege             enabled/enabled by default
    00712     // SeLockMemoryPrivilege                 enabled/enabled by default
    00713     // SeAssignPrimaryTokenPrivilege         DISabled/NOT enabled by default
    00714     // SeIncreaseQuotaPrivilege              DISabled/NOT enabled by default
    00715     // SeIncreaseBasePriorityPrivilege       enabled/enabled by default
    00716     // SeCreatePermanentPrivilege            enabled/enabled by default
    00717     // SeDebugPrivilege                      enabled/enabled by default
    00718     // SeAuditPrivilege                      enabled/enabled by default
    00719     // SeSecurityPrivilege                   DISabled/NOT enabled by default
    00720     // SeSystemEnvironmentPrivilege          DISabled/NOT enabled by default
    00721     // SeChangeNotifyPrivilege               enabled/enabled by default
    00722     // SeBackupPrivilege                     DISabled/NOT enabled by default
    00723     // SeRestorePrivilege                    DISabled/NOT enabled by default
    00724     // SeShutdownPrivilege                   DISabled/NOT enabled by default
    00725     // SeLoadDriverPrivilege                 DISabled/NOT enabled by default
    00726     // SeProfileSingleProcessPrivilege       enabled/enabled by default
    00727     // SeSystemtimePrivilege                 DISabled/NOT enabled by default
    00728     // SeUndockPrivilege                     DISabled/NOT enabled by default
    00729     //
    00730     // The following privileges are not present, and should never be present in
    00731     // the local system token:
    00732     //
    00733     // SeRemoteShutdownPrivilege             no one can come in as local system
    00734     // SeSyncAgentPrivilege                  only users specified by the admin can
    00735     //                                       be sync agents
    00736     // SeEnableDelegationPrivilege           only users specified by the admin can
    00737     //                                       enable delegation on accounts.
    00738     //
    00739
    00740     Privileges[0].Luid = SeTcbPrivilege;
    00741     Privileges[0].Attributes =
    00742         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00743          SE_PRIVILEGE_ENABLED);               // Enabled
    00744
    00745     Privileges[1].Luid = SeCreateTokenPrivilege;
    00746     Privileges[1].Attributes = 0;     // Only the LSA should enable this.
    00747
    00748     Privileges[2].Luid = SeTakeOwnershipPrivilege;
    00749     Privileges[2].Attributes = 0;
    00750
    00751     Privileges[3].Luid = SeCreatePagefilePrivilege;
    00752     Privileges[3].Attributes =
    00753         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00754          SE_PRIVILEGE_ENABLED);               // Enabled
    00755
    00756     Privileges[4].Luid = SeLockMemoryPrivilege;
    00757     Privileges[4].Attributes =
    00758         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00759          SE_PRIVILEGE_ENABLED);               // Enabled
    00760
    00761     Privileges[5].Luid = SeAssignPrimaryTokenPrivilege;
    00762     Privileges[5].Attributes = 0;    // disabled, not enabled by default
    00763
    00764     Privileges[6].Luid = SeIncreaseQuotaPrivilege;
    00765     Privileges[6].Attributes = 0;    // disabled, not enabled by default
    00766
    00767     Privileges[7].Luid = SeIncreaseBasePriorityPrivilege;
    00768     Privileges[7].Attributes =
    00769         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00770          SE_PRIVILEGE_ENABLED);               // Enabled
    00771
    00772     Privileges[8].Luid = SeCreatePermanentPrivilege;
    00773     Privileges[8].Attributes =
    00774         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00775          SE_PRIVILEGE_ENABLED);               // Enabled
    00776
    00777     Privileges[9].Luid = SeDebugPrivilege;
    00778     Privileges[9].Attributes =
    00779         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |   // Enabled by default
    00780          SE_PRIVILEGE_ENABLED);               // Enabled
    00781
    00782     Privileges[10].Luid = SeAuditPrivilege;
    00783     Privileges[10].Attributes =
    00784         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00785          SE_PRIVILEGE_ENABLED);               // Enabled
    00786
    00787     Privileges[11].Luid = SeSecurityPrivilege;
    00788     Privileges[11].Attributes = 0;    // disabled, not enabled by default
    00789
    00790     Privileges[12].Luid = SeSystemEnvironmentPrivilege;
    00791     Privileges[12].Attributes = 0;    // disabled, not enabled by default
    00792
    00793     Privileges[13].Luid = SeChangeNotifyPrivilege;
    00794     Privileges[13].Attributes =
    00795         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00796          SE_PRIVILEGE_ENABLED);               // Enabled
    00797
    00798
    00799     Privileges[14].Luid = SeBackupPrivilege;
    00800     Privileges[14].Attributes = 0;    // disabled, not enabled by default
    00801
    00802     Privileges[15].Luid = SeRestorePrivilege;
    00803     Privileges[15].Attributes = 0;    // disabled, not enabled by default
    00804
    00805     Privileges[16].Luid = SeShutdownPrivilege;
    00806     Privileges[16].Attributes = 0;    // disabled, not enabled by default
    00807
    00808     Privileges[17].Luid = SeLoadDriverPrivilege;
    00809     Privileges[17].Attributes = 0;    // disabled, not enabled by default
    00810
    00811     Privileges[18].Luid = SeProfileSingleProcessPrivilege;
    00812     Privileges[18].Attributes =
    00813         (SE_PRIVILEGE_ENABLED_BY_DEFAULT |    // Enabled by default
    00814          SE_PRIVILEGE_ENABLED);               // Enabled
    00815
    00816     Privileges[19].Luid = SeSystemtimePrivilege;
    00817     Privileges[19].Attributes = 0;    // disabled, not enabled by default
    00818
    00819     Privileges[20].Luid = SeUndockPrivilege ;
    00820     Privileges[20].Attributes = 0 ;   // disabled, not enabled by default
    00821
    00822     //BEFORE ADDING ANOTHER PRIVILEGE ^^ HERE ^^ CHECK THE ARRAY BOUND
    00823     //ALSO INCREMENT THE PRIVILEGE COUNT IN THE SepCreateToken() call
    00824
    00825
    00826     //
    00827     // Establish the primary group and default owner
    00828     //
    00829
    00830     PrimaryGroup.PrimaryGroup = SeLocalSystemSid;  // Primary group
    00831     Owner = SeAliasAdminsSid;                      // Default owner
    00832
    00833
    00834
    00835
    00836
    00837     //
    00838     // Set up an ACL to protect token as well ...
    00839     // give system full reign of terror.  This includes user-mode components
    00840     // running as part of the system.
    00841     //
    00842
    00843     Length = (ULONG)sizeof(ACL) +
    00844              ((ULONG)sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG)) +
    00845              SeLengthSid( SeLocalSystemSid ) ;
    00846
    00847     TokenAcl = (PACL)ExAllocatePoolWithTag(PagedPool, Length, 'cAeS');
    00848
    00849     if ( TokenAcl == NULL ) {
    00850
    00851         return NULL ;
    00852     }
    00853
    00854     Status = RtlCreateAcl( TokenAcl, Length, ACL_REVISION2);
    00855     ASSERT( NT_SUCCESS(Status) );
    00856
    00857     Status = RtlAddAccessAllowedAce (
    00858                  TokenAcl,
    00859                  ACL_REVISION2,
    00860                  TOKEN_ALL_ACCESS,
    00861                  SeLocalSystemSid
    00862                  );
    00863     ASSERT( NT_SUCCESS(Status) );
    00864
    00865     TokenSecurityDescriptor =
    00866     (PSECURITY_DESCRIPTOR)ExAllocatePoolWithTag(
    00867                               PagedPool,
    00868                               sizeof(SECURITY_DESCRIPTOR),
    00869                               'dSeS'
    00870                               );
    00871
    00872     if ( TokenSecurityDescriptor == NULL ) {
    00873
    00874         ExFreePool( TokenAcl );
    00875
    00876         return NULL ;
    00877     }
    00878
    00879     Status = RtlCreateSecurityDescriptor(
    00880                  TokenSecurityDescriptor,
    00881                  SECURITY_DESCRIPTOR_REVISION
    00882                  );
    00883     ASSERT( NT_SUCCESS(Status) );
    00884
    00885     Status = RtlSetDaclSecurityDescriptor (
    00886                  TokenSecurityDescriptor,
    00887                  TRUE,
    00888                  TokenAcl,
    00889                  FALSE
    00890                  );
    00891     ASSERT( NT_SUCCESS(Status) );
    00892
    00893
    00894     Status = RtlSetOwnerSecurityDescriptor (
    00895                  TokenSecurityDescriptor,
    00896                  SeAliasAdminsSid,
    00897                  FALSE // Owner defaulted
    00898                  );
    00899     ASSERT( NT_SUCCESS(Status) );
    00900
    00901     Status = RtlSetGroupSecurityDescriptor (
    00902                  TokenSecurityDescriptor,
    00903                  SeAliasAdminsSid,
    00904                  FALSE // Group defaulted
    00905                  );
    00906     ASSERT( NT_SUCCESS(Status) );
    00907
    00908
    00909     //
    00910     // Create the system token
    00911     //
    00912
    00913 #ifdef TOKEN_DEBUG
    00914
    00915 //
    00916 // Debug
    00917     DbgPrint("\n Creating system token...\n");
    00918 // Debug
    00919 //
    00921 #endif //TOKEN_DEBUG
    00922
    00923     InitializeObjectAttributes(
    00924         &TokenObjectAttributes,
    00925         NULL,
    00926         0,
    00927         NULL,
    00928         TokenSecurityDescriptor
    00929         );
    00930
    00931
    00932
    00933     ASSERT(SeSystemDefaultDacl != NULL);
    00934     Status = SepCreateToken(
    00935                  (PHANDLE)&Token,
    00936                  KernelMode,
    00937                  0,               // No handle created for system token
    00938                  &TokenObjectAttributes,
    00939                  TokenPrimary,
    00940                  (SECURITY_IMPERSONATION_LEVEL)0,
    00941                  &SeSystemAuthenticationId,
    00942                  &NoExpiration,
    00943                  &UserId,
    00944                  3,                         // GroupCount
    00945                  GroupIds,
    00946                  GroupIdsLength,
    00947                  21,                        // privileges
    00948                  Privileges,
    00949                  sizeof(Privileges),
    00950                  Owner,
    00951                  PrimaryGroup.PrimaryGroup,
    00952                  SeSystemDefaultDacl,
    00953                  &SeSystemTokenSource,
    00954                  TRUE,                        // System token
    00955                  NULL,
    00956                  NULL
    00957                  );
    00958
    00959      ASSERT(NT_SUCCESS(Status));
    00960
    00961     //
    00962     // Assign the security descriptor here, since we don't do it
    00963     // in SepCreateToken for the System Token.
    00964     //
    00965
    00966     BufferLength = Length +
    00967                    sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
    00968                    2 * SeLengthSid(SeAliasAdminsSid);
    00969
    00970     Buffer =  (PSECURITY_DESCRIPTOR)ExAllocatePoolWithTag( PagedPool,
    00971                                                            BufferLength,
    00972                                                            'dSeS'
    00973                                                            );
    00974
    00975     if ( Buffer ) {
    00976
    00977         Status =  RtlAbsoluteToSelfRelativeSD( TokenSecurityDescriptor,
    00978                                                Buffer,
    00979                                                &BufferLength
    00980                                                );
    00981         ASSERT(NT_SUCCESS(Status));
    00982
    00983         Status =  ObAssignObjectSecurityDescriptor( Token,
    00984                                                     Buffer,
    00985                                                     PagedPool
    00986                                                     );
    00987         ASSERT(NT_SUCCESS(Status));
    00988
    00989     } else {
    00990
    00991         ObDereferenceObject( Token );
    00992
    00993         Token = NULL ;
    00994
    00995     }
    00996
    00997     //
    00998     // We can free the old one now.
    00999     //
    01000
    01001     ExFreePool( TokenAcl );
    01002     ExFreePool( TokenSecurityDescriptor );
    01003
    01004     return  (PACCESS_TOKEN)Token;
    01005
    01006 }
    01007
    01008
    01009 PACCESS_TOKEN
    01010 SeMakeAnonymousLogonToken (
    01011     VOID
    01012     )
    01013
    01014 /*++
    01015
    01016 Routine Description:
    01017
    01018     This routine is provided for use by executive components
    01019     DURING SYSTEM INITIALIZATION ONLY.  It creates a token for
    01020     use by system components.
    01021
    01022     A system token has the following characteristics:
    01023
    01024          - It has ANONYMOUS_LOGON as its user ID
    01025
    01026          - It has the following groups with the corresponding
    01027            attributes:
    01028
    01029
    01030                WORLD             EnabledByDefault |
    01031                                  Enabled          |
    01032                                  Mandatory
    01033
    01034
    01035          - It has WORLD as its primary group.
    01036
    01037          - It has no privileges/
    01038
    01039
    01040          - It has protection that provides TOKEN_ALL_ACCESS to
    01041            the WORLD ID.
    01042
    01043
    01044          - It has a default ACL that grants GENERIC_ALL access
    01045            to WORLD.
    01046
    01047
    01048 Parameters:
    01049
    01050     None.
    01051
    01052 Return Value:
    01053
    01054     Pointer to a system token.
    01055
    01056 --*/
    01057
    01058 {
    01059     NTSTATUS Status;
    01060
    01061     PVOID Token;
    01062
    01063     SID_AND_ATTRIBUTES UserId;
    01064     PSID_AND_ATTRIBUTES GroupIds;
    01065     TOKEN_PRIMARY_GROUP PrimaryGroup;
    01066     ULONG GroupIdsLength;
    01067     PACL TokenAcl;
    01068     PSID Owner;
    01069     ULONG NormalGroupAttributes;
    01070     ULONG Length;
    01071     OBJECT_ATTRIBUTES TokenObjectAttributes;
    01072     PSECURITY_DESCRIPTOR TokenSecurityDescriptor;
    01073     ULONG BufferLength;
    01074     PVOID Buffer;
    01075
    01076     ULONG_PTR GroupIdsBuffer[128 * sizeof(ULONG) / sizeof(ULONG_PTR)];
    01077
    01078     TIME_FIELDS TimeFields;
    01079     LARGE_INTEGER NoExpiration;
    01080
    01081     PAGED_CODE();
    01082
    01083
    01084
    01085     //
    01086     // Set up expiration times
    01087     //
    01088
    01089     TimeFields.Year = 3000;
    01090     TimeFields.Month = 1;
    01091     TimeFields.Day = 1;
    01092     TimeFields.Hour = 1;
    01093     TimeFields.Minute = 1;
    01094     TimeFields.Second = 1;
    01095     TimeFields.Milliseconds = 1;
    01096     TimeFields.Weekday = 1;
    01097
    01098     RtlTimeFieldsToTime( &TimeFields, &NoExpiration );
    01099
    01100
    01101
    01102     GroupIds = (PSID_AND_ATTRIBUTES)GroupIdsBuffer;
    01103
    01104
    01105     //
    01106     // Set up the attributes to be assigned to groups
    01107     //
    01108
    01109     NormalGroupAttributes =    (SE_GROUP_MANDATORY          |
    01110                                 SE_GROUP_ENABLED_BY_DEFAULT |
    01111                                 SE_GROUP_ENABLED
    01112                                 );
    01113
    01114
    01115     //
    01116     // Set up the user ID
    01117     //
    01118
    01119     UserId.Sid = SeAnonymousLogonSid;
    01120     UserId.Attributes = 0;
    01121
    01122     //
    01123     // Set up the groups
    01124     //
    01125
    01126
    01127     GroupIds->Sid  = SeWorldSid;
    01128     GroupIds->Attributes = NormalGroupAttributes;
    01129
    01130
    01131     GroupIdsLength = (ULONG)LongAlignSize(SeLengthSid(GroupIds->Sid)) +
    01132                                                     sizeof(SID_AND_ATTRIBUTES);
    01133
    01134     ASSERT( GroupIdsLength <= 128 * sizeof(ULONG) );
    01135
    01136
    01137     //
    01138     // Privileges
    01139     //
    01140
    01141
    01142     //
    01143     // Establish the primary group and default owner
    01144     //
    01145
    01146     PrimaryGroup.PrimaryGroup = SeAnonymousLogonSid;  // Primary group
    01147
    01148
    01149
    01150
    01151
    01152     //
    01153     // Set up an ACL to protect token as well ...
    01154     // give system full reign of terror.  This includes user-mode components
    01155     // running as part of the system.
    01156     //
    01157
    01158     Length = (ULONG)sizeof(ACL) +
    01159              (ULONG)sizeof(ACCESS_ALLOWED_ACE) +
    01160              SeLengthSid( SeWorldSid ) +
    01161              8; // The 8 is just for good measure
    01162     ASSERT( Length < 200 );
    01163
    01164     TokenAcl = (PACL)ExAllocatePoolWithTag(PagedPool, 200, 'cAeS');
    01165
    01166     if ( !TokenAcl ) {
    01167
    01168         return NULL ;
    01169     }
    01170
    01171     Status = RtlCreateAcl( TokenAcl, Length, ACL_REVISION2);
    01172     ASSERT( NT_SUCCESS(Status) );
    01173
    01174     Status = RtlAddAccessAllowedAce (
    01175                  TokenAcl,
    01176                  ACL_REVISION2,
    01177                  TOKEN_ALL_ACCESS,
    01178                  SeWorldSid
    01179                  );
    01180     ASSERT( NT_SUCCESS(Status) );
    01181
    01182     TokenSecurityDescriptor =
    01183     (PSECURITY_DESCRIPTOR)ExAllocatePoolWithTag(
    01184                               PagedPool,
    01185                               SECURITY_DESCRIPTOR_MIN_LENGTH,
    01186                               'dSeS'
    01187                               );
    01188
    01189     if ( !TokenSecurityDescriptor ) {
    01190
    01191         ExFreePool( TokenAcl );
    01192
    01193         return NULL ;
    01194     }
    01195
    01196
    01197     Status = RtlCreateSecurityDescriptor(
    01198                  TokenSecurityDescriptor,
    01199                  SECURITY_DESCRIPTOR_REVISION
    01200                  );
    01201     ASSERT( NT_SUCCESS(Status) );
    01202
    01203     Status = RtlSetDaclSecurityDescriptor (
    01204                  TokenSecurityDescriptor,
    01205                  TRUE,
    01206                  TokenAcl,
    01207                  FALSE
    01208                  );
    01209     ASSERT( NT_SUCCESS(Status) );
    01210
    01211
    01212     Status = RtlSetOwnerSecurityDescriptor (
    01213                  TokenSecurityDescriptor,
    01214                  SeWorldSid,
    01215                  FALSE // Owner defaulted
    01216                  );
    01217     ASSERT( NT_SUCCESS(Status) );
    01218
    01219     Status = RtlSetGroupSecurityDescriptor (
    01220                  TokenSecurityDescriptor,
    01221                  SeWorldSid,
    01222                  FALSE // Group defaulted
    01223                  );
    01224     ASSERT( NT_SUCCESS(Status) );
    01225
    01226
    01227     //
    01228     // Create the system token
    01229     //
    01230
    01231 #ifdef TOKEN_DEBUG
    01232
    01233 //
    01234 // Debug
    01235     DbgPrint("\n Creating system token...\n");
    01236 // Debug
    01237 //
    01239 #endif //TOKEN_DEBUG
    01240
    01241     InitializeObjectAttributes(
    01242         &TokenObjectAttributes,
    01243         NULL,
    01244         0,
    01245         NULL,
    01246         TokenSecurityDescriptor
    01247         );
    01248
    01249
    01250
    01251     Status = SepCreateToken(
    01252                  (PHANDLE)&Token,
    01253                  KernelMode,
    01254                  0,               // No handle created for system token
    01255                  &TokenObjectAttributes,
    01256                  TokenPrimary,
    01257                  (SECURITY_IMPERSONATION_LEVEL)0,
    01258                  &SeAnonymousAuthenticationId,
    01259                  &NoExpiration,
    01260                  &UserId,
    01261                  1,                         // GroupCount
    01262                  GroupIds,
    01263                  GroupIdsLength,
    01264                  0,                         // no privileges
    01265                  NULL,                      // no Privileges,
    01266                  0,                         // no privileges
    01267                  NULL,
    01268                  PrimaryGroup.PrimaryGroup,
    01269                  TokenAcl,
    01270                  &SeSystemTokenSource,
    01271                  TRUE,                        // System token
    01272                  NULL,
    01273                  NULL
    01274                  );
    01275
    01276      ASSERT(NT_SUCCESS(Status));
    01277
    01278     //
    01279     // Assign the security descriptor here, since we don't do it
    01280     // in SepCreateToken for the System Token.
    01281     //
    01282
    01283     BufferLength = Length +
    01284                    sizeof(SECURITY_DESCRIPTOR) +
    01285                    2 * SeLengthSid(SeAliasAdminsSid);
    01286
    01287     Buffer =  (PSECURITY_DESCRIPTOR)ExAllocatePoolWithTag( PagedPool,
    01288                                                            BufferLength,
    01289                                                            'dSeS'
    01290                                                            );
    01291
    01292     if ( Buffer ) {
    01293
    01294         Status =  RtlAbsoluteToSelfRelativeSD( TokenSecurityDescriptor,
    01295                                                Buffer,
    01296                                                &BufferLength
    01297                                                );
    01298         ASSERT(NT_SUCCESS(Status));
    01299
    01300         Status =  ObAssignObjectSecurityDescriptor( Token,
    01301                                                     Buffer,
    01302                                                     PagedPool
    01303                                                     );
    01304         ASSERT(NT_SUCCESS(Status));
    01305
    01306     } else {
    01307
    01308         ObDereferenceObject( Token );
    01309
    01310         Token = NULL ;
    01311     }
    01312
    01313
    01314     //
    01315     // We can free the old one now.
    01316     //
    01317
    01318     ExFreePool( TokenAcl );
    01319     ExFreePool( TokenSecurityDescriptor );
    01320
    01321     return  (PACCESS_TOKEN)Token;
    01322
    01323 }
    01324
    01325
    01326 NTSTATUS
    01327 SeSubProcessToken (
    01328     IN PEPROCESS ParentProcess,
    01329     OUT PACCESS_TOKEN *ChildToken
    01330     )
    01331
    01332 /*++
    01333
    01334 Routine Description:
    01335
    01336     This routine makes a token for a sub-process that is a duplicate
    01337     of the parent process's token.
    01338
    01339
    01340
    01341 Parameters:
    01342
    01343     ParentProcess - Pointer to the parent process object.  This is used
    01344         to locate the parent process's primary token, and for logging
    01345         purposes.
    01346
    01347     ChildToken - Receives a pointer to the child process's token.
    01348
    01349 Return Value:
    01350
    01351     STATUS_SUCCESS - Indicates the sub-process's token has been created
    01352         successfully.
    01353
    01354     Other status values may be returned from memory allocation or object
    01355     creation services used and typically indicate insufficient resources
    01356     or quota on the requestor's part.
    01357
    01358
    01359
    01360 --*/
    01361
    01362 {
    01363
    01364     //
    01365     //  NOTE:  THIS ROUTINE CAN BE MADE MUCH MORE EFFICIENT.
    01366     //         IT IS DONE IN A BRUTE FORCE FASHION FOR THE LARGE_INTEGER
    01367     //         BEING TO GET THINGS UP AND RUNNING.
    01368     //
    01369     //         THE PERFORMANCE OF THIS ROUTINE DIRECTLY IMPACTS
    01370     //         THE PERFORMANCE OF SUB-PROCESS CREATION.
    01371     //
    01372
    01373
    01374     KPROCESSOR_MODE PreviousMode;
    01375     PTOKEN ParentToken;
    01376     PTOKEN NewToken;
    01377     HANDLE NewTokenHandle;
    01378     OBJECT_ATTRIBUTES PrimaryTokenAttributes;
    01379
    01380     PTOKEN InsertedToken;
    01381
    01382     NTSTATUS Status;
    01383     NTSTATUS IgnoreStatus;
    01384
    01385     PAGED_CODE();
    01386
    01387     PreviousMode = KeGetPreviousMode();
    01388
    01389     InitializeObjectAttributes(
    01390         &PrimaryTokenAttributes,
    01391         NULL,
    01392         0,
    01393         NULL,
    01394         NULL
    01395         );
    01396
    01397 #ifdef TOKEN_DEBUG
    01398     DbgPrint("\nCreating sub-process token...\n");
    01399     DbgPrint("Parent token address = 0x%lx\n", ParentProcess->Token);
    01400 #endif //TOKEN_DEBUG
    01401
    01402     ParentToken = (PTOKEN)PsReferencePrimaryToken( ParentProcess );
    01403
    01404     Status = SepDuplicateToken(
    01405                 ParentToken,                         // ExistingToken
    01406                 &PrimaryTokenAttributes,             // ObjectAttributes
    01407                 FALSE,                               // EffectiveOnly
    01408                 TokenPrimary,                        // TokenType
    01409                 (SECURITY_IMPERSONATION_LEVEL)0,     // ImpersonationLevel
    01410                 KernelMode,                          // RequestorMode
    01411                 &NewToken                            // NewToken
    01412                 );
    01413
    01414     PsDereferencePrimaryToken( (PACCESS_TOKEN)ParentToken );
    01415
    01416     if (NT_SUCCESS(Status)) {
    01417
    01418         //
    01419         // Insert the new token object, up its ref count, and then
    01420         // delete the new handle.
    01421         //
    01422
    01423         Status = ObInsertObject(
    01424                      NewToken,
    01425                      NULL,
    01426                      0,
    01427                      1,             // ObjectPointerBias
    01428                      (PVOID *)&InsertedToken,
    01429                      &NewTokenHandle
    01430                      );
    01431
    01432         if (NT_SUCCESS(Status)) {
    01433
    01434             *ChildToken = InsertedToken;
    01435             InsertedToken->TokenInUse = TRUE;
    01436             IgnoreStatus = ZwClose( NewTokenHandle );
    01437
    01438             //
    01439             // At this point, either the token has a reference
    01440             // outstanding (and no handles), or the reference
    01441             // failed.  If the reference failed, the status will
    01442             // be returned indicating why.
    01443             //
    01444
    01445         } else {
    01446
    01447             //
    01448             // ObInsertObject dereferences the passed object if it
    01449             // fails, so we don't have to do any cleanup on NewToken
    01450             // here.
    01451             //
    01452         }
    01453     }
    01454
    01455     return Status;
    01456 }
    01457
    01458
    01459 BOOLEAN
    01460 SepTokenInitialization ( VOID )
    01461
    01462 /*++
    01463
    01464 Routine Description:
    01465
    01466     This function creates the token object type descriptor at system
    01467     initialization and stores the address of the object type descriptor
    01468     in global storage.  It also created token related global variables.
    01469
    01470     Furthermore, some number of pseudo tokens are created during system
    01471     initialization.  These tokens are tracked down and replaced with
    01472     real tokens.
    01473
    01474 Arguments:
    01475
    01476     None.
    01477
    01478 Return Value:
    01479
    01480     A value of TRUE is returned if the object type descriptor is
    01481     successfully initialized. Otherwise a value of FALSE is returned.
    01482
    01483 --*/
    01484
    01485 {
    01486
    01487     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
    01488     NTSTATUS Status;
    01489     UNICODE_STRING TypeName;
    01490
    01491     PAGED_CODE();
    01492
    01493     //
    01494     // Initialize string descriptor.
    01495     //
    01496
    01497     RtlInitUnicodeString(&TypeName, L"Token");
    01498
    01499
    01500     //
    01501     // Create the global token lock
    01502     //
    01503
    01504     ExInitializeResource(&SepTokenLock);
    01505
    01506
    01507 #if 0
    01508 BUG, BUG   Need to get system default ACL to protect token object
    01509 #endif
    01510
    01511     //
    01512     // Create object type descriptor.
    01513     //
    01514
    01515     RtlZeroMemory(&ObjectTypeInitializer,sizeof(ObjectTypeInitializer));
    01516     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
    01517     ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
    01518     ObjectTypeInitializer.GenericMapping = SepTokenMapping;
    01519     ObjectTypeInitializer.SecurityRequired = TRUE;
    01520     ObjectTypeInitializer.UseDefaultObject = TRUE;
    01521     ObjectTypeInitializer.PoolType = PagedPool;
    01522     ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
    01523     ObjectTypeInitializer.DeleteProcedure = SepTokenDeleteMethod;
    01524
    01525     Status = ObCreateObjectType(&TypeName,
    01526                                 &ObjectTypeInitializer,
    01527                                 (PSECURITY_DESCRIPTOR)NULL,   // BUG, BUG assign real protection
    01528                                 &SepTokenObjectType
    01529                                 );
    01530
    01531
    01532 #if 0
    01533 BUG, BUG   Now track down all pseudo tokens used during system initialization
    01534 BUG, BUG   and replace them with real ones.
    01535 #endif
    01536
    01537     //
    01538     // If the object type descriptor was successfully created, then
    01539     // return a value of TRUE. Otherwise return a value of FALSE.
    01540     //
    01541
    01542     return (BOOLEAN)NT_SUCCESS(Status);
    01543 }
    01544
    01546 //                                                                      //
    01547 //          Temporary, for Debug only                                   //
    01548 //                                                                      //
    01550 #ifdef TOKEN_DEBUG
    01551 VOID
    01552 SepDumpToken(
    01553     IN PTOKEN T
    01554     )
    01555
    01556 {
    01557     ULONG Index;
    01558
    01559     //
    01560     // Dump a token
    01561     //
    01562
    01563     DbgPrint("\n");
    01564
    01565     DbgPrint("                        address: 0x%lx \n", ((ULONG)T) );
    01566
    01567     DbgPrint("                        TokenId: (0x%lx, 0x%lx) \n",
    01568                                      T->TokenId.HighPart, T->TokenId.LowPart );
    01569
    01570     if ( (T->AuthenticationId.Data[0] == SeSystemAuthenticationId.Data[0]) &&
    01571          (T->AuthenticationId.Data[1] == SeSystemAuthenticationId.Data[1]) &&
    01572          (T->AuthenticationId.Data[2] == SeSystemAuthenticationId.Data[2]) &&
    01573          (T->AuthenticationId.Data[3] == SeSystemAuthenticationId.Data[3]) ) {
    01574
    01575         DbgPrint("               AuthenticationId: SeSystemAuthenticationId \n");
    01576
    01577     } else {
    01578
    01579         DbgPrint("               AuthenticationId: (0x%lx, 0x%lx, 0x%lx, 0x%lx) \n",
    01580                                          T->AuthenticationId.Data[0],
    01581                                          T->AuthenticationId.Data[1],
    01582                                          T->AuthenticationId.Data[2],
    01583                                          T->AuthenticationId.Data[3] );
    01584     }
    01585
    01586     DbgPrint("                 ExpirationTime: 0x%lx, 0x%lx \n",
    01587                                      T->ExpirationTime.HighPart,
    01588                                      T->ExpirationTime.LowPart );
    01589
    01590     if (T->TokenType == TokenPrimary) {
    01591         DbgPrint("                      TokenType: Primary \n");
    01592     } else {
    01593         if (T->TokenType == TokenImpersonation) {
    01594             DbgPrint("                      TokenType: Impersonation \n");
    01595         } else {
    01596             DbgPrint("                      TokenType: (Unknown type, value = 0x%lx) \n",
    01597                                              ((ULONG)T-TokenType) );
    01598         }
    01599     }
    01600
    01601     DbgPrint("             ImpersonationLevel: 0x%lx \n",
    01602                                      ((ULONG)T->ImpersonationLevel) );
    01603
    01604     DbgPrint("                    TokenSource: (not yet provided) \n");
    01605     DbgPrint("                 DynamicCharged: 0x%lx \n", T->DynamicCharged);
    01606     DbgPrint("              UserAndGroupCount: 0x%lx \n", T->UserAndGroupCount);
    01607     DbgPrint("                 PrivilegeCount: 0x%lx \n", T->PrivilegeCount);
    01608     DbgPrint("                 VariableLength: 0x%lx \n", T->VariableLength);
    01609
    01610
    01611     DbgPrint("                  ModifiedId: (0x%lx, 0x%lx) \n",
    01612                                      T->ModifiedId.HighPart,
    01613                                      T->ModifiedId.LowPart );
    01614     DbgPrint("               DynamicAvailable: 0x%lx \n", T->DynamicAvailable);
    01615     DbgPrint("              DefaultOwnerIndex: 0x%lx \n", T->DefaultOwnerIndex);
    01616
    01617
    01618     DbgPrint("         Address of DynamicPart: 0x%lx \n",
    01619                                      (* (PULONG)((PVOID)(&(T->DynamicPart)))) );
    01620     DbgPrint("        Address of Default DACL: 0x%lx \n",
    01621                                      (* (PULONG)((PVOID)(&(T->DefaultDacl)))) );
    01622
    01623     DbgPrint("       Address Of Variable Part: 0x%lx \n",
    01624                                      &(T->VariablePart) );
    01625
    01626     DbgPrint("\n");
    01627     DbgPrint("                   PrimaryGroup:\n");
    01628     DbgPrint("                                         Address: 0x%lx \n",
    01629                                      (* (PULONG)((PVOID)(&(T->PrimaryGroup)))) );
    01630     DbgPrint("                                          Length: 0x%lx \n",
    01631                                      SeLengthSid((T->PrimaryGroup)) );
    01632     DbgPrint("\n");
    01633     DbgPrint("                  UserAndGroups: 0x%lx \n",
    01634                                      (* (PULONG)((PVOID)(&(T->UserAndGroups)))) );
    01635     DbgPrint("                               User ID - \n");
    01636     DbgPrint("                                Address: 0x%lx \n",
    01637                                      (* (PULONG)((PVOID)(&(T->UserAndGroups[0].Sid)))) );
    01638     DbgPrint("                             Attributes: 0x%lx \n",
    01639                                      (T->UserAndGroups[0].Attributes) );
    01640     DbgPrint("                                 Length: 0x%lx \n",
    01641                                      SeLengthSid((T->UserAndGroups[0].Sid)) );
    01642     Index = 1;
    01643     while (Index < T->UserAndGroupCount) {
    01644         DbgPrint("                           Group 0x%lx - \n", Index );
    01645         DbgPrint("                                Address: 0x%lx \n",
    01646                                          (* (PULONG)((PVOID)(&(T->UserAndGroups[Index].Sid)))) );
    01647         DbgPrint("                             Attributes: 0x%lx \n",
    01648                                          (T->UserAndGroups[Index].Attributes) );
    01649         DbgPrint("                                 Length: 0x%lx \n",
    01650                                          SeLengthSid((T->UserAndGroups[Index].Sid)) );
    01651         Index += 1;
    01652     }
    01653
    01654     Index = 0;
    01655     while (Index < T->RestrictedSidCount) {
    01656         DbgPrint("                           Sid 0x%lx - \n", Index );
    01657         DbgPrint("                                Address: 0x%lx \n",
    01658                                          (* (PULONG)((PVOID)(&(T->RestrictedSids[Index].Sid)))) );
    01659         DbgPrint("                             Attributes: 0x%lx \n",
    01660                                          (T->RestrictedSids[Index].Attributes) );
    01661         DbgPrint("                                 Length: 0x%lx \n",
    01662                                          SeLengthSid((T->RestrictedSids[Index].Sid)) );
    01663         Index += 1;
    01664     }
    01665
    01666
    01667     DbgPrint("\n");
    01668     DbgPrint("                     Privileges: 0x%lx\n",
    01669                                      (* (PULONG)((PVOID)(&(T->Privileges)))) );
    01670     Index = 0;
    01671     while (Index < T->PrivilegeCount) {
    01672         DbgPrint("                       Privilege 0x%lx - \n", Index );
    01673         DbgPrint("                                Address: 0x%lx \n",
    01674                                          (&(T->Privileges[Index])) );
    01675         DbgPrint("                                   LUID: (0x%lx, 0x%lx) \n",
    01676                                          T->Privileges[Index].Luid.HighPart,
    01677                                          T->Privileges[Index].Luid.LowPart );
    01678         DbgPrint("                             Attributes: 0x%lx \n",
    01679                                          T->Privileges[Index].Attributes );
    01680
    01681         Index += 1;
    01682     }
    01683
    01684     return;
    01685
    01686 }
    01687 #endif //TOKEN_DEBUG
    01688
    01689 NTSTATUS
    01690 NtCreateToken(
    01691     OUT PHANDLE TokenHandle,
    01692     IN ACCESS_MASK DesiredAccess,
    01693     IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    01694     IN TOKEN_TYPE TokenType,
    01695     IN PLUID AuthenticationId,
    01696     IN PLARGE_INTEGER ExpirationTime,
    01697     IN PTOKEN_USER User,
    01698     IN PTOKEN_GROUPS Groups,
    01699     IN PTOKEN_PRIVILEGES Privileges,
    01700     IN PTOKEN_OWNER Owner OPTIONAL,
    01701     IN PTOKEN_PRIMARY_GROUP PrimaryGroup,
    01702     IN PTOKEN_DEFAULT_DACL DefaultDacl OPTIONAL,
    01703     IN PTOKEN_SOURCE TokenSource
    01704     )
    01705
    01706 /*++
    01707
    01708 Routine Description:
    01709
    01710     Create a token object and return a handle opened for access to
    01711     that token.  This API requires SeCreateTokenPrivilege privilege.
    01712
    01713 Arguments:
    01714
    01715     TokenHandle - Receives the handle of the newly created token.
    01716
    01717     DesiredAccess - Is an access mask indicating which access types
    01718         the handle is to provide to the new object.
    01719
    01720     ObjectAttributes - Points to the standard object attributes data
    01721         structure.  Refer to the NT Object Management
    01722         Specification for a description of this data structure.
    01723
    01724         If the token type is TokenImpersonation, then this parameter
    01725         must specify the impersonation level of the token.
    01726
    01727     TokenType - Type of token to be created.  Privilege is required
    01728         to create any type of token.
    01729
    01730     AuthenticationId - Points to a LUID (or LUID) providing a unique
    01731         identifier associated with the authentication.  This is used
    01732         within security only, for audit purposes.
    01733
    01734     ExpirationTime - Time at which the token becomes invalid.  If this
    01735         value is specified as zero, then the token has no expiration
    01736         time.
    01737
    01738     User - Is the user SID to place in the token.
    01739
    01740     Groups - Are the group SIDs to place in the token.
    01741
    01742     Privileges - Are the privileges to place in the token.
    01743
    01744     Owner - (Optionally) identifies an identifier that is to be used
    01745         as the default owner for the token.  If not provided, the
    01746         user ID is made the default owner.
    01747
    01748     PrimaryGroup - Identifies which of the group IDs is to be the
    01749         primary group of the token.
    01750
    01751     DefaultDacl - (optionally) establishes an ACL to be used as the
    01752         default discretionary access protection for the token.
    01753
    01754     TokenSource - Identifies the token source name string and
    01755         identifier to be assigned to the token.
    01756
    01757 Return Value:
    01758
    01759     STATUS_SUCCESS - Indicates the operation was successful.
    01760
    01761     STATUS_INVALID_OWNER - Indicates the ID provided to be assigned
    01762         as the default owner of the token does not have an attribute
    01763         indicating it may be assigned as an owner.
    01764
    01765     STATUS_INVALID_PRIMARY_GROUP - Indicates the group ID provided
    01766         via the PrimaryGroup parameter was not among those assigned
    01767         to the token in the Groups parameter.
    01768
    01769     STATUS_BAD_IMPERSONATION_LEVEL - Indicates no impersonation level
    01770         was provided when attempting to create a token of type
    01771         TokenImpersonation.
    01772
    01773 --*/
    01774
    01775 {
    01776
    01777     KPROCESSOR_MODE PreviousMode;
    01778     NTSTATUS Status;
    01779     ULONG Ignore;
    01780
    01781
    01782     HANDLE LocalHandle;
    01783
    01784     BOOLEAN SecurityQosPresent = FALSE;
    01785     SECURITY_ADVANCED_QUALITY_OF_SERVICE CapturedSecurityQos;
    01786
    01787     LUID CapturedAuthenticationId;
    01788     LARGE_INTEGER CapturedExpirationTime;
    01789
    01790     PSID_AND_ATTRIBUTES CapturedUser = NULL;
    01791     ULONG CapturedUserLength;
    01792
    01793     ULONG CapturedGroupCount;
    01794     PSID_AND_ATTRIBUTES CapturedGroups = NULL;
    01795     ULONG CapturedGroupsLength;
    01796
    01797     ULONG CapturedPrivilegeCount;
    01798     PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
    01799     ULONG CapturedPrivilegesLength;
    01800
    01801     PSID CapturedOwner = NULL;
    01802
    01803     PSID CapturedPrimaryGroup = NULL;
    01804
    01805     PACL CapturedDefaultDacl = NULL;
    01806
    01807     TOKEN_SOURCE CapturedTokenSource;
    01808
    01809     PVOID CapturedAddress;
    01810
    01811     PAGED_CODE();
    01812
    01813     PreviousMode = KeGetPreviousMode();
    01814
    01815     if (PreviousMode != KernelMode) {
    01816
    01817         //
    01818         // Probe everything necessary for input to the capture subroutines.
    01819         //
    01820
    01821         try {
    01822
    01823             ProbeForWriteHandle(TokenHandle);
    01824
    01825
    01826             ProbeForRead( ExpirationTime, sizeof(LARGE_INTEGER), sizeof(ULONG) );
    01827             ProbeForRead( Groups, sizeof(TOKEN_GROUPS), sizeof(ULONG) );
    01828             ProbeForRead( Privileges, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG) );
    01829             ProbeForRead( TokenSource, sizeof(TOKEN_SOURCE), sizeof(ULONG) );
    01830
    01831
    01832             if ( ARGUMENT_PRESENT(Owner) ) {
    01833                 ProbeForRead( Owner, sizeof(TOKEN_OWNER), sizeof(ULONG) );
    01834             }
    01835
    01836
    01837             ProbeForRead(
    01838                 PrimaryGroup,
    01839                 sizeof(TOKEN_PRIMARY_GROUP),
    01840                 sizeof(ULONG)
    01841                 );
    01842
    01843
    01844             if ( ARGUMENT_PRESENT(DefaultDacl) ) {
    01845                 ProbeForRead(
    01846                     DefaultDacl,
    01847                     sizeof(TOKEN_DEFAULT_DACL),
    01848                     sizeof(ULONG)
    01849                     );
    01850              }
    01851
    01852             ProbeForRead(
    01853                 AuthenticationId,
    01854                 sizeof(LUID),
    01855                 sizeof(ULONG)
    01856                 );
    01857
    01858         } except(EXCEPTION_EXECUTE_HANDLER) {
    01859             return GetExceptionCode();
    01860         }  // end_try
    01861
    01862     } //end_if
    01863
    01864     //
    01865     //  Capture the security quality of service.
    01866     //  This capture routine necessarily does some probing of its own.
    01867     //
    01868
    01869     Status = SeCaptureSecurityQos(
    01870                  ObjectAttributes,
    01871                  PreviousMode,
    01872                  &SecurityQosPresent,
    01873                  &CapturedSecurityQos
    01874                  );
    01875
    01876     if (!NT_SUCCESS(Status)) {
    01877         return Status;
    01878     }
    01879
    01880     if (TokenType == TokenImpersonation) {
    01881
    01882         if (!SecurityQosPresent) {
    01883             return STATUS_BAD_IMPERSONATION_LEVEL;
    01884         } // endif
    01885
    01886     } // endif
    01887
    01888
    01889     //
    01890     //  Capture the rest of the arguments.
    01891     //  These arguments have already been probed.
    01892     //
    01893
    01894     try {
    01895
    01896         Status = STATUS_SUCCESS;
    01897
    01898         //
    01899         //  Capture and validate AuthenticationID
    01900         //
    01901
    01902         RtlCopyLuid( &CapturedAuthenticationId, AuthenticationId );
    01903
    01904         //
    01905         //  Capture ExpirationTime
    01906         //
    01907
    01908         CapturedExpirationTime = (*ExpirationTime);
    01909
    01910         //
    01911         //  Capture User
    01912         //
    01913
    01914         if (NT_SUCCESS(Status)) {
    01915             Status = SeCaptureSidAndAttributesArray(
    01916                          &(User->User),
    01917                          1,
    01918                          PreviousMode,
    01919                          NULL, 0,
    01920                          PagedPool,
    01921                          TRUE,
    01922                          &CapturedUser,
    01923                          &CapturedUserLength
    01924                          );
    01925         }
    01926
    01927
    01928         //
    01929         //  Capture Groups
    01930         //
    01931
    01932         if (NT_SUCCESS(Status)) {
    01933             CapturedGroupCount = Groups->GroupCount;
    01934             Status = SeCaptureSidAndAttributesArray(
    01935                          (Groups->Groups),
    01936                          CapturedGroupCount,
    01937                          PreviousMode,
    01938                          NULL, 0,
    01939                          PagedPool,
    01940                          TRUE,
    01941                          &CapturedGroups,
    01942                          &CapturedGroupsLength
    01943                          );
    01944         }
    01945
    01946
    01947         //
    01948         //  Capture Privileges
    01949         //
    01950
    01951         if (NT_SUCCESS(Status)) {
    01952             CapturedPrivilegeCount = Privileges->PrivilegeCount;
    01953             Status = SeCaptureLuidAndAttributesArray(
    01954                          (Privileges->Privileges),
    01955                          CapturedPrivilegeCount,
    01956                          PreviousMode,
    01957                          NULL, 0,
    01958                          PagedPool,
    01959                          TRUE,
    01960                          &CapturedPrivileges,
    01961                          &CapturedPrivilegesLength
    01962                          );
    01963         }
    01964
    01965
    01966         //
    01967         //  Capture Owner
    01968         //
    01969
    01970         if ( ARGUMENT_PRESENT(Owner) && NT_SUCCESS(Status)) {
    01971             CapturedAddress = Owner->Owner;
    01972             Status = SeCaptureSid(
    01973                          (PSID)CapturedAddress,
    01974                          PreviousMode,
    01975                          NULL, 0,
    01976                          PagedPool,
    01977                          TRUE,
    01978                          &CapturedOwner
    01979                          );
    01980         }
    01981
    01982
    01983         //
    01984         //  Capture PrimaryGroup
    01985         //
    01986         if (NT_SUCCESS(Status)) {
    01987             CapturedAddress = PrimaryGroup->PrimaryGroup;
    01988             Status = SeCaptureSid(
    01989                          (PSID)CapturedAddress,
    01990                          PreviousMode,
    01991                          NULL, 0,
    01992                          PagedPool,
    01993                          TRUE,
    01994                          &CapturedPrimaryGroup
    01995                          );
    01996         }
    01997
    01998
    01999         //
    02000         //  Capture DefaultDacl
    02001         //
    02002
    02003         if ( ARGUMENT_PRESENT(DefaultDacl) && NT_SUCCESS(Status) ) {
    02004             CapturedAddress = DefaultDacl->DefaultDacl;
    02005             if (CapturedAddress != NULL) {
    02006                 Status = SeCaptureAcl(
    02007                              (PACL)CapturedAddress,
    02008                              PreviousMode,
    02009                              NULL, 0,
    02010                              NonPagedPool,
    02011                              TRUE,
    02012                              &CapturedDefaultDacl,
    02013                              &Ignore
    02014                              );
    02015             }
    02016         }
    02017
    02018         //
    02019         //  Capture TokenSource
    02020         //
    02021
    02022         CapturedTokenSource = (*TokenSource);
    02023
    02024
    02025     } except(EXCEPTION_EXECUTE_HANDLER) {
    02026
    02027         if (CapturedUser != NULL) {
    02028             SeReleaseSidAndAttributesArray(
    02029                 CapturedUser,
    02030                 PreviousMode,
    02031                 TRUE
    02032                 );
    02033         }
    02034
    02035         if (CapturedGroups != NULL) {
    02036             SeReleaseSidAndAttributesArray(
    02037                 CapturedGroups,
    02038                 PreviousMode,
    02039                 TRUE
    02040                 );
    02041         }
    02042
    02043         if (CapturedPrivileges != NULL) {
    02044             SeReleaseLuidAndAttributesArray(
    02045                 CapturedPrivileges,
    02046                 PreviousMode,
    02047                 TRUE
    02048                 );
    02049         }
    02050
    02051         if (CapturedOwner != NULL) {
    02052             SeReleaseSid( CapturedOwner, PreviousMode, TRUE);
    02053         }
    02054
    02055         if (CapturedPrimaryGroup != NULL) {
    02056             SeReleaseSid( CapturedPrimaryGroup, PreviousMode, TRUE);
    02057         }
    02058
    02059         if (CapturedDefaultDacl != NULL) {
    02060             SeReleaseAcl( CapturedDefaultDacl, PreviousMode, TRUE);
    02061         }
    02062
    02063         if (SecurityQosPresent == TRUE) {
    02064             SeFreeCapturedSecurityQos( &CapturedSecurityQos );
    02065         }
    02066
    02067         return GetExceptionCode();
    02068
    02069     }  // end_try{}
    02070
    02071     //
    02072     //  Create the token
    02073     //
    02074
    02075     if (NT_SUCCESS(Status)) {
    02076         Status = SepCreateToken(
    02077                                 &LocalHandle,
    02078                                 PreviousMode,
    02079                                 DesiredAccess,
    02080                                 ObjectAttributes,
    02081                                 TokenType,
    02082                                 CapturedSecurityQos.ImpersonationLevel,
    02083                                 &CapturedAuthenticationId,
    02084                                 &CapturedExpirationTime,
    02085                                 CapturedUser,
    02086                                 CapturedGroupCount,
    02087                                 CapturedGroups,
    02088                                 CapturedGroupsLength,
    02089                                 CapturedPrivilegeCount,
    02090                                 CapturedPrivileges,
    02091                                 CapturedPrivilegesLength,
    02092                                 CapturedOwner,
    02093                                 CapturedPrimaryGroup,
    02094                                 CapturedDefaultDacl,
    02095                                 &CapturedTokenSource,
    02096                                 FALSE,                       // Not a system token
    02097                                 SecurityQosPresent ? CapturedSecurityQos.ProxyData : NULL,
    02098                                 SecurityQosPresent ? CapturedSecurityQos.AuditData : NULL
    02099                                 );
    02100     }
    02101
    02102     //
    02103     //  Clean up the temporary capture buffers
    02104     //
    02105
    02106     if (CapturedUser != NULL) {
    02107         SeReleaseSidAndAttributesArray( CapturedUser, PreviousMode, TRUE);
    02108     }
    02109     if (CapturedGroups != NULL) {
    02110         SeReleaseSidAndAttributesArray( CapturedGroups, PreviousMode, TRUE);
    02111     }
    02112
    02113     if (CapturedPrivileges != NULL) {
    02114         SeReleaseLuidAndAttributesArray( CapturedPrivileges, PreviousMode, TRUE);
    02115     }
    02116
    02117     if (CapturedOwner != NULL) {
    02118         SeReleaseSid( CapturedOwner, PreviousMode, TRUE);
    02119     }
    02120
    02121     if (CapturedPrimaryGroup != NULL) {
    02122         SeReleaseSid( CapturedPrimaryGroup, PreviousMode, TRUE);
    02123     }
    02124
    02125     if (CapturedDefaultDacl != NULL) {
    02126         SeReleaseAcl( CapturedDefaultDacl, PreviousMode, TRUE);
    02127     }
    02128
    02129     if (SecurityQosPresent == TRUE) {
    02130         SeFreeCapturedSecurityQos( &CapturedSecurityQos );
    02131     }
    02132
    02133     //
    02134     //  Return the handle to this new token
    02135     //
    02136
    02137     if (NT_SUCCESS(Status)) {
    02138         try { *TokenHandle = LocalHandle; }
    02139             except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); }
    02140     }
    02141
    02142     return Status;
    02143
    02144 }
    02145
    02146
    02147
    02149 //                                                                    //
    02150 //           Token Private Routines                                   //
    02151 //                                                                    //
    02153
    02154
    02155 VOID
    02156 SepTokenDeleteMethod (
    02157     IN PVOID Token
    02158     )
    02159
    02160 /*++
    02161
    02162 Routine Description:
    02163
    02164     This function is the token object type-specific delete method.
    02165     It is needed to ensure that all memory allocated for the token
    02166     gets deallocated.
    02167
    02168 Arguments:
    02169
    02170     Token - Points to the token object being deleted.
    02171
    02172 Return Value:
    02173
    02174     None.
    02175
    02176 --*/
    02177
    02178 {
    02179     PAGED_CODE();
    02180
    02181     //
    02182     // De-reference the logon session referenced by this token object
    02183     //
    02184
    02185     SepDeReferenceLogonSession( &(((TOKEN *)Token)->AuthenticationId) );
    02186
    02187
    02188     //
    02189     // If the token has an associated Dynamic part, deallocate it.
    02190     //
    02191
    02192     if (ARGUMENT_PRESENT( ((TOKEN *)Token)->DynamicPart)) {
    02193         ExFreePool( ((TOKEN *)Token)->DynamicPart );
    02194     }
    02195
    02196     //
    02197     // Free the Proxy and Global audit structures if present.
    02198     //
    02199
    02200     if (ARGUMENT_PRESENT(((TOKEN *) Token)->ProxyData)) {
    02201         SepFreeProxyData( ((TOKEN *)Token)->ProxyData );
    02202     }
    02203
    02204     if (ARGUMENT_PRESENT(((TOKEN *)Token)->AuditData )) {
    02205         ExFreePool( (((TOKEN *)Token)->AuditData) );
    02206     }
    02207
    02208
    02209     return;
    02210 }
    02211
    02212 NTSTATUS
    02213 SepCreateToken(
    02214     OUT PHANDLE TokenHandle,
    02215     IN KPROCESSOR_MODE RequestorMode,
    02216     IN ACCESS_MASK DesiredAccess,
    02217     IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    02218     IN TOKEN_TYPE TokenType,
    02219     IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel OPTIONAL,
    02220     IN PLUID AuthenticationId,
    02221     IN PLARGE_INTEGER ExpirationTime,
    02222     IN PSID_AND_ATTRIBUTES User,
    02223     IN ULONG GroupCount,
    02224     IN PSID_AND_ATTRIBUTES Groups,
    02225     IN ULONG GroupsLength,
    02226     IN ULONG PrivilegeCount,
    02227     IN PLUID_AND_ATTRIBUTES Privileges,
    02228     IN ULONG PrivilegesLength,
    02229     IN PSID Owner OPTIONAL,
    02230     IN PSID PrimaryGroup,
    02231     IN PACL DefaultDacl OPTIONAL,
    02232     IN PTOKEN_SOURCE TokenSource,
    02233     IN BOOLEAN SystemToken,
    02234     IN PSECURITY_TOKEN_PROXY_DATA ProxyData OPTIONAL,
    02235     IN PSECURITY_TOKEN_AUDIT_DATA AuditData OPTIONAL
    02236     )
    02237
    02238 /*++
    02239
    02240 Routine Description:
    02241
    02242     Create a token object and return a handle opened for access to
    02243     that token.  This API implements the bulk of the work needed
    02244     for NtCreateToken.
    02245
    02246     All parameters except DesiredAccess and ObjectAttributes are assumed
    02247     to have been probed and captured.
    02248
    02249     The output parameter (TokenHandle) is expected to be returned to a
    02250     safe address, rather than to a user mode address that may cause an
    02251     exception.
    02252
    02253     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    02254     NOTE: This routine is also used to create the initial system token.
    02255           In that case, the SystemToken parameter is TRUE and no handle
    02256           is established to the token.  Instead, a pointer to the token
    02257           is returned via the TokenHandle parameter.
    02258     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    02259
    02260
    02261 Arguments:
    02262
    02263     TokenHandle - Receives the handle of the newly created token.  If the
    02264         SystemToken parameter is specified is true, then this parameter
    02265         receives a pointer to the token instead of a handle to the token.
    02266
    02267     RequestorMode - The mode of the caller on whose behalf the token
    02268         is being created.
    02269
    02270     DesiredAccess - Is an access mask indicating which access types
    02271         the handle is to provide to the new object.
    02272
    02273     ObjectAttributes - Points to the standard object attributes data
    02274         structure.  Refer to the NT Object Management
    02275         Specification for a description of this data structure.
    02276
    02277     TokenType - Type of token to be created.  Privilege is required
    02278         to create any type of token.
    02279
    02280     ImpersonationLevel - If the token type is TokenImpersonation, then
    02281         this parameter is used to specify the impersonation level of
    02282         the token.
    02283
    02284     AuthenticationId - Points to a LUID (or LUID) providing a unique
    02285         identifier associated with the authentication.  This is used
    02286         within security only, for audit purposes.
    02287
    02288     ExpirationTime - Time at which the token becomes invalid.  If this
    02289         value is specified as zero, then the token has no expiration
    02290         time.
    02291
    02292     User - Is the user SID to place in the token.
    02293
    02294     GroupCount - Indicates the number of groups in the 'Groups' parameter.
    02295         This value may be zero, in which case the 'Groups' parameter is
    02296         ignored.
    02297
    02298     Groups - Are the group SIDs, and their corresponding attributes,
    02299         to place in the token.
    02300
    02301     GroupsLength - Indicates the length, in bytes, of the array of groups
    02302         to place in the token.
    02303
    02304     PrivilegeCount - Indicates the number of privileges in the 'Privileges'
    02305         parameter.  This value may be zero, in which case the 'Privileges'
    02306         parameter is ignored.
    02307
    02308     Privileges - Are the privilege LUIDs, and their corresponding attributes,
    02309         to place in the token.
    02310
    02311     PrivilegesLength - Indicates the length, in bytes, of the array of
    02312         privileges to place in the token.
    02313
    02314     Owner - (Optionally) identifies an identifier that is to be used
    02315         as the default owner for the token.  If not provided, the
    02316         user ID is made the default owner.
    02317
    02318     PrimaryGroup - Identifies which of the group IDs is to be the
    02319         primary group of the token.
    02320
    02321     DefaultDacl - (optionally) establishes an ACL to be used as the
    02322         default discretionary access protection for the token.
    02323
    02324     TokenSource - Identifies the token source name string and
    02325         identifier to be assigned to the token.
    02326
    02327 Return Value:
    02328
    02329     STATUS_SUCCESS - Indicates the operation was successful.
    02330
    02331     STATUS_INVALID_OWNER - Indicates the ID provided to be assigned
    02332         as the default owner of the token does not have an attribute
    02333         indicating it may be assigned as an owner.
    02334
    02335     STATUS_INVALID_PRIMARY_GROUP - Indicates the group ID provided
    02336         via the PrimaryGroup parameter was not among those assigned
    02337         to the token in the Groups parameter.
    02338
    02339     STATUS_INVALID_PARAMETER - Indicates that a required parameter,
    02340         such as User or PrimaryGroup, was not provided with a legitimate
    02341         value.
    02342
    02343 --*/
    02344
    02345 {
    02346
    02347     PTOKEN Token;
    02348     NTSTATUS Status;
    02349
    02350     ULONG PagedPoolSize;
    02351
    02352     ULONG PrimaryGroupLength;
    02353
    02354     ULONG TokenBodyLength;
    02355     ULONG VariableLength;
    02356
    02357     ULONG DefaultOwnerIndex;
    02358     PUCHAR Where ;
    02359     ULONG ComputedPrivLength ;
    02360
    02361     //ULONG_PTR NextFree;
    02362     PSID NextSidFree;
    02363
    02364     ULONG DynamicLength = TOKEN_DEFAULT_DYNAMIC_CHARGE;
    02365     ULONG DynamicLengthUsed;
    02366
    02367     ULONG SubAuthorityCount;
    02368     ULONG GroupIndex;
    02369     ULONG PrivilegeIndex;
    02370     BOOLEAN OwnerFound;
    02371
    02372     UCHAR TokenFlags = 0;
    02373
    02374     ACCESS_STATE AccessState;
    02375     AUX_ACCESS_DATA AuxData;
    02376     LUID NewModifiedId;
    02377
    02378     PAGED_CODE();
    02379
    02380     ASSERT( sizeof(SECURITY_IMPERSONATION_LEVEL) <= sizeof(ULONG) );
    02381
    02382     //
    02383     // Make sure the Enabled and Enabled-by-default bits are set on every
    02384     // mandatory group.
    02385     //
    02386     // Also, check to see if the local administrators alias is present.
    02387     // if so, turn on the flag so that we can do restrictions later
    02388     //
    02389
    02390     for (GroupIndex=0; GroupIndex < GroupCount; GroupIndex++) {
    02391         if (Groups[GroupIndex].Attributes & SE_GROUP_MANDATORY) {
    02392             Groups[GroupIndex].Attributes |= (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT);
    02393         }
    02394         if ( RtlEqualSid( SeAliasAdminsSid, Groups[GroupIndex].Sid ) )
    02395         {
    02396             TokenFlags |= TOKEN_HAS_ADMIN_GROUP ;
    02397         }
    02398     }
    02399
    02400     //
    02401     // Check to see if the token being created is going to be granted
    02402     // SeChangeNotifyPrivilege.  If so, set a flag in the TokenFlags field
    02403     // so we can find this out quickly.
    02404     //
    02405
    02406     for (PrivilegeIndex = 0; PrivilegeIndex < PrivilegeCount; PrivilegeIndex++) {
    02407
    02408         if (((RtlEqualLuid(&Privileges[PrivilegeIndex].Luid,&SeChangeNotifyPrivilege))
    02409                 &&
    02410             (Privileges[PrivilegeIndex].Attributes & SE_PRIVILEGE_ENABLED))) {
    02411
    02412             TokenFlags |= TOKEN_HAS_TRAVERSE_PRIVILEGE;
    02413             break;
    02414         }
    02415     }
    02416
    02417
    02418     //
    02419     // Get a ModifiedId to use
    02420     //
    02421
    02422     ExAllocateLocallyUniqueId( &NewModifiedId );
    02423
    02424     //
    02425     // Validate the owner ID, if provided and establish the default
    02426     // owner index.
    02427     //
    02428
    02429     if (!ARGUMENT_PRESENT(Owner)) {
    02430
    02431         DefaultOwnerIndex = 0;
    02432
    02433     } else {
    02434
    02435
    02436         if ( RtlEqualSid( Owner, User->Sid )  ) {
    02437
    02438             DefaultOwnerIndex = 0;
    02439
    02440         } else {
    02441
    02442             GroupIndex = 0;
    02443             OwnerFound = FALSE;
    02444
    02445             while ((GroupIndex < GroupCount) && (!OwnerFound)) {
    02446
    02447                 if ( RtlEqualSid( Owner, (Groups[GroupIndex].Sid) )  ) {
    02448
    02449                     //
    02450                     // Found a match - make sure it is assignable as owner.
    02451                     //
    02452
    02453                     if ( SepArrayGroupAttributes( Groups, GroupIndex ) &
    02454                          SE_GROUP_OWNER ) {
    02455
    02456                         DefaultOwnerIndex = GroupIndex + 1;
    02457                         OwnerFound = TRUE;
    02458
    02459                     } else {
    02460
    02461                         return STATUS_INVALID_OWNER;
    02462
    02463                     } // endif Owner attribute set
    02464
    02465                 } // endif owner = group
    02466
    02467                 GroupIndex += 1;
    02468
    02469             }  // endwhile
    02470
    02471             if (!OwnerFound) {
    02472
    02473                 return STATUS_INVALID_OWNER;
    02474
    02475             } // endif !OwnerFound
    02476         } // endif owner = user
    02477     } // endif owner specified
    02478
    02479
    02480
    02481     //
    02482     // Increment the reference count for this logon session
    02483     // (fail if there is no corresponding logon session.)
    02484     //
    02485
    02486     Status = SepReferenceLogonSession( AuthenticationId );
    02487     if ( !NT_SUCCESS(Status) ) {
    02488         return Status;
    02489     }
    02490
    02491
    02492
    02493
    02494     //
    02495     //  Calculate the length needed for the variable portion of the token
    02496     //  This includes the User ID, Group IDs, and Privileges
    02497     //
    02498     //
    02499     // Align the privilege chunk by pointer alignment so that the SIDs will
    02500     // be correctly aligned.  Align the Groups Length so that the SID_AND_ATTR
    02501     // array (which is
    02502     //
    02503
    02504     ComputedPrivLength = PrivilegeCount * sizeof( LUID_AND_ATTRIBUTES ) ;
    02505
    02506     ComputedPrivLength = ALIGN_UP( ComputedPrivLength, PVOID );
    02507
    02508     GroupsLength = ALIGN_UP( GroupsLength, PVOID );
    02509
    02510
    02511     VariableLength  = GroupsLength + ComputedPrivLength +
    02512                        ALIGN_UP( (GroupCount * sizeof( SID_AND_ATTRIBUTES )), PVOID ) ;
    02513
    02514     SubAuthorityCount = ((SID *)(User->Sid))->SubAuthorityCount;
    02515     VariableLength += sizeof(SID_AND_ATTRIBUTES) +
    02516                       (ULONG)LongAlignSize(RtlLengthRequiredSid( SubAuthorityCount ));
    02517
    02518
    02519
    02520     //
    02521     //  Calculate the length needed for the dynamic portion of the token
    02522     //  This includes the default Dacl and the primary group.
    02523     //
    02524
    02525     SubAuthorityCount = ((SID *)PrimaryGroup)->SubAuthorityCount;
    02526     DynamicLengthUsed = (ULONG)LongAlignSize(RtlLengthRequiredSid( SubAuthorityCount ));
    02527
    02528     if (ARGUMENT_PRESENT(DefaultDacl)) {
    02529         DynamicLengthUsed += (ULONG)LongAlignSize(DefaultDacl->AclSize);
    02530     }
    02531
    02532     if (DynamicLengthUsed > DynamicLength) {
    02533         DynamicLength = DynamicLengthUsed;
    02534     }
    02535
    02536     //
    02537     // Now create the token body
    02538     //
    02539
    02540     TokenBodyLength = sizeof(TOKEN) + VariableLength;
    02541     PagedPoolSize = TokenBodyLength + DynamicLength;
    02542
    02543
    02544     Status = ObCreateObject(
    02545                  RequestorMode,      // ProbeMode
    02546                  SepTokenObjectType, // ObjectType
    02547                  ObjectAttributes,   // ObjectAttributes
    02548                  UserMode,           // OwnershipMode
    02549                  NULL,               // ParseContext
    02550                  TokenBodyLength,    // ObjectBodySize
    02551                  PagedPoolSize,      // PagedPoolCharge
    02552                  0,                  // NonPagedPoolCharge
    02553                  (PVOID *)&Token     // Return pointer to object
    02554                  );
    02555
    02556     if (!NT_SUCCESS(Status)) {
    02557         SepDeReferenceLogonSession( AuthenticationId );
    02558         return Status;
    02559     }
    02560
    02561     //
    02562     // After this point, we rely on token deletion to clean up the referenced
    02563     // logon session if the creation fails.
    02564     //
    02565
    02566
    02567     //
    02568     // Main Body initialization
    02569     //
    02570
    02571
    02572     ExAllocateLocallyUniqueId( &(Token->TokenId) );
    02573     Token->ParentTokenId = RtlConvertLongToLuid(0);
    02574     Token->AuthenticationId = (*AuthenticationId);
    02575     Token->TokenInUse = FALSE;
    02576     Token->ModifiedId = NewModifiedId;
    02577     Token->ExpirationTime = (*ExpirationTime);
    02578     Token->TokenType = TokenType;
    02579     Token->ImpersonationLevel = ImpersonationLevel;
    02580     Token->TokenSource = (*TokenSource);
    02581
    02582     Token->TokenFlags = TokenFlags;
    02583     Token->SessionId = 0;
    02584
    02585     Token->DynamicCharged  = DynamicLength;
    02586     Token->DynamicAvailable = DynamicLength - DynamicLengthUsed;
    02587
    02588     Token->DefaultOwnerIndex = DefaultOwnerIndex;
    02589     Token->DefaultDacl = NULL;
    02590
    02591     Token->VariableLength = VariableLength;
    02592
    02593     // Ensure SepTokenDeleteMethod knows the buffers aren't allocated yet.
    02594     Token->ProxyData = NULL;
    02595     Token->AuditData = NULL;
    02596     Token->DynamicPart = NULL;
    02597
    02598     if (ARGUMENT_PRESENT( ProxyData )) {
    02599
    02600         Status = SepCopyProxyData(
    02601                     &Token->ProxyData,
    02602                     ProxyData
    02603                     );
    02604
    02605         if (!NT_SUCCESS(Status)) {
    02606             ObDereferenceObject( Token );
    02607             return( STATUS_NO_MEMORY );
    02608         }
    02609
    02610     } else {
    02611
    02612         Token->ProxyData = NULL;
    02613     }
    02614
    02615     if (ARGUMENT_PRESENT( AuditData )) {
    02616
    02617         Token->AuditData = ExAllocatePool( PagedPool, sizeof( SECURITY_TOKEN_AUDIT_DATA ));
    02618
    02619         if (Token->AuditData == NULL) {
    02620             ObDereferenceObject( Token );
    02621             return( STATUS_NO_MEMORY );
    02622         }
    02623
    02624         *(Token->AuditData) = *AuditData;
    02625
    02626     } else {
    02627
    02628         Token->AuditData = NULL;
    02629     }
    02630
    02631
    02632     //
    02633     //  Variable part initialization
    02634     //  Data is in the following order:
    02635     //
    02636     //               Privileges array
    02637     //               User (SID_AND_ATTRIBUTES)
    02638     //               Groups (SID_AND_ATTRIBUTES)
    02639     //               Restricted Sids (SID_AND_ATTRIBUTES)
    02640     //               SIDs
    02641     //
    02642
    02643     Where = (PUCHAR) & Token->VariablePart ;
    02644
    02645     Token->Privileges = (PLUID_AND_ATTRIBUTES) Where ;
    02646     Token->PrivilegeCount = PrivilegeCount ;
    02647
    02648     RtlCopyMemory(
    02649         Where,
    02650         Privileges,
    02651         PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES) );
    02652
    02653     ASSERT( ComputedPrivLength >= PrivilegeCount * sizeof( LUID_AND_ATTRIBUTES ) );
    02654
    02655     Where += ComputedPrivLength ;
    02656     VariableLength -= ComputedPrivLength ;
    02657
    02658     ASSERT( (((ULONG_PTR) Where ) & (sizeof(PVOID) - 1)) == 0 );
    02659
    02660     //
    02661     // Now, copy the sid and attributes arrays.
    02662     //
    02663
    02664     NextSidFree = (PSID) (Where + (sizeof( SID_AND_ATTRIBUTES ) *
    02665                                    (GroupCount + 1) ) );
    02666
    02667     Token->UserAndGroups = (PSID_AND_ATTRIBUTES) Where ;
    02668     Token->UserAndGroupCount = GroupCount + 1 ;
    02669
    02670
    02671     ASSERT(VariableLength >= ((GroupCount + 1) * (ULONG)sizeof(SID_AND_ATTRIBUTES)));
    02672
    02673     VariableLength -= ((GroupCount + 1) * (ULONG)sizeof(SID_AND_ATTRIBUTES));
    02674     Status = RtlCopySidAndAttributesArray(
    02675                  1,
    02676                  User,
    02677                  VariableLength,
    02678                  (PSID_AND_ATTRIBUTES)Where,
    02679                  NextSidFree,
    02680                  &NextSidFree,
    02681                  &VariableLength
    02682                  );
    02683
    02684     Where += sizeof( SID_AND_ATTRIBUTES );
    02685
    02686     ASSERT( (((ULONG_PTR) Where ) & (sizeof(PVOID) - 1)) == 0 );
    02687
    02688     Status = RtlCopySidAndAttributesArray(
    02689                  GroupCount,
    02690                  Groups,
    02691                  VariableLength,
    02692                  (PSID_AND_ATTRIBUTES)Where,
    02693                  NextSidFree,
    02694                  &NextSidFree,
    02695                  &VariableLength
    02696                  );
    02697
    02698
    02699     ASSERT(NT_SUCCESS(Status));
    02700
    02701
    02702     Token->RestrictedSids = NULL;
    02703     Token->RestrictedSidCount = 0;
    02704
    02705
    02706     //
    02707     //  Dynamic part initialization
    02708     //  Data is in the following order:
    02709     //
    02710     //                  PrimaryGroup (SID)
    02711     //                  Default Discreationary Acl (ACL)
    02712     //
    02713
    02714     Token->DynamicPart = (PULONG)ExAllocatePoolWithTag( PagedPool, DynamicLength, 'dTeS' );
    02715
    02716     //
    02717     // The attempt to allocate the DynamicPart of the token may have
    02718     // failed.  Dereference the created object and exit with an error.
    02719     //
    02720
    02721     if (Token->DynamicPart == NULL) {
    02722         ObDereferenceObject( Token );
    02723         return( STATUS_NO_MEMORY );
    02724     }
    02725
    02726
    02727     Where = (PUCHAR) Token->DynamicPart;
    02728
    02729     Token->PrimaryGroup = (PSID) Where;
    02730     PrimaryGroupLength = RtlLengthRequiredSid( ((SID *)PrimaryGroup)->SubAuthorityCount );
    02731     RtlCopySid( PrimaryGroupLength, (PSID)Where, PrimaryGroup );
    02732     Where += (ULONG)LongAlignSize(PrimaryGroupLength);
    02733
    02734     if (ARGUMENT_PRESENT(DefaultDacl)) {
    02735         Token->DefaultDacl = (PACL)Where;
    02736
    02737         RtlCopyMemory( (PVOID)Where,
    02738                       (PVOID)DefaultDacl,
    02739                       DefaultDacl->AclSize
    02740                       );
    02741     }
    02742
    02743 #ifdef TOKEN_DEBUG
    02744
    02745 //
    02746 // Debug
    02747     SepDumpToken( Token );
    02748 // Debug
    02749 //
    02751 #endif //TOKEN_DEBUG
    02752
    02753
    02754     //
    02755     //  Insert the token unless it is a system token.
    02756     //
    02757
    02758     if (!SystemToken) {
    02759
    02760         Status = SeCreateAccessState(
    02761                      &AccessState,
    02762                      &AuxData,
    02763                      DesiredAccess,
    02764                      &SepTokenObjectType->TypeInfo.GenericMapping
    02765                      );
    02766
    02767         if ( NT_SUCCESS(Status) ) {
    02768             BOOLEAN PrivilegeHeld;
    02769
    02770             PrivilegeHeld = SeSinglePrivilegeCheck(
    02771                             SeCreateTokenPrivilege,
    02772                             KeGetPreviousMode()
    02773                             );
    02774
    02775             if (PrivilegeHeld) {
    02776
    02777                 Status = ObInsertObject( Token,
    02778                                          &AccessState,
    02779                                          0,
    02780                                          0,
    02781                                          (PVOID *)NULL,
    02782                                          TokenHandle
    02783                                          );
    02784
    02785             } else {
    02786
    02787                 Status = STATUS_PRIVILEGE_NOT_HELD;
    02788                 ObDereferenceObject( Token );
    02789             }
    02790
    02791             SeDeleteAccessState( &AccessState );
    02792
    02793         } else {
    02794
    02795             ObDereferenceObject( Token );
    02796         }
    02797     } else {
    02798
    02799         ASSERT( NT_SUCCESS( Status ) );
    02800         ObDeleteCapturedInsertInfo(Token);
    02801         //
    02802         // Return pointer instead of handle.
    02803         //
    02804
    02805         (*TokenHandle) = (HANDLE)Token;
    02806     }
    02807
    02808     return Status;
    02809
    02810 }
    02811
    02812 BOOLEAN
    02813 SepIdAssignableAsOwner(
    02814     IN PTOKEN Token,
    02815     IN ULONG Index
    02816     )
    02817
    02818 /*++
    02819
    02820
    02821 Routine Description:
    02822
    02823     This routine returns a boolean value indicating whether the user
    02824     or group ID in the specified token with the specified index is
    02825     assignable as the owner of an object.
    02826
    02827     If the index is 0, which is always the USER ID, then the ID is
    02828     assignable as owner.  Otherwise, the ID is that of a group, and
    02829     it must have the "Owner" attribute set to be assignable.
    02830
    02831
    02832
    02833 Arguments:
    02834
    02835     Token - Pointer to a locked Token to use.
    02836
    02837     Index - Index into the Token's UserAndGroupsArray.  This value
    02838         is assumed to be valid.
    02839
    02840 Return Value:
    02841
    02842     TRUE  - Indicates the index corresponds to an ID that may be assigned
    02843             as the owner of objects.
    02844
    02845     FALSE - Indicates the index does not correspond to an ID that may be
    02846             assigned as the owner of objects.
    02847
    02848 --*/
    02849 {
    02850     PAGED_CODE();
    02851
    02852     if (Index == 0) {
    02853
    02854         return TRUE;
    02855
    02856     } else {
    02857
    02858         return (BOOLEAN)
    02859                    ( (SepTokenGroupAttributes(Token,Index) & SE_GROUP_OWNER)
    02860                      != 0
    02861                    );
    02862     }
    02863 }
    02864
    02865
    02866 NTSTATUS
    02867 SeIsChildToken(
    02868     IN HANDLE Token,
    02869     OUT PBOOLEAN IsChild
    02870     )
    02871 /*++
    02872
    02873 Routine Description:
    02874
    02875     This routine returns TRUE if the supplied token is a child of the caller's
    02876     process token. This is done by comparing the ParentTokenId field of the
    02877     supplied token to the TokenId field of the token from the current subject
    02878     context.
    02879
    02880 Arguments:
    02881
    02882     Token - Token to check for childhood
    02883
    02884     IsChild - Contains results of comparison.
    02885
    02886         TRUE - The supplied token is a child of the caller's token
    02887         FALSE- The supplied token is not a child of the caller's token
    02888
    02889 Returns:
    02890
    02891     Status codes from any NT services called.
    02892
    02893 --*/
    02894 {
    02895     PTOKEN CallerToken;
    02896     PTOKEN SuppliedToken;
    02897     LUID CallerTokenId;
    02898     LUID SuppliedParentTokenId;
    02899     NTSTATUS Status = STATUS_SUCCESS;
    02900
    02901     *IsChild = FALSE;
    02902
    02903     //
    02904     // Capture the caller's token and get the token id
    02905     //
    02906
    02907     CallerToken = (PTOKEN) PsReferencePrimaryToken(PsGetCurrentProcess());
    02908
    02909
    02910     SepAcquireTokenReadLock( CallerToken );
    02911
    02912     CallerTokenId = CallerToken->TokenId;
    02913
    02914     SepReleaseTokenReadLock( CallerToken );
    02915
    02916     PsDereferencePrimaryToken(CallerToken);
    02917
    02918     //
    02919     // Reference the supplied token and get the parent token id.
    02920     //
    02921
    02922     Status = ObReferenceObjectByHandle(
    02923                 Token,                   // Handle
    02924                 0,                       // DesiredAccess
    02925                 SepTokenObjectType,      // ObjectType
    02926                 KeGetPreviousMode(),     // AccessMode
    02927                 (PVOID *)&SuppliedToken, // Object
    02928                 NULL                     // GrantedAccess
    02929                 );
    02930
    02931     if (NT_SUCCESS(Status))
    02932     {
    02933         SepAcquireTokenReadLock( SuppliedToken );
    02934
    02935         SuppliedParentTokenId = SuppliedToken->ParentTokenId;
    02936
    02937         SepReleaseTokenReadLock( SuppliedToken );
    02938
    02939         ObDereferenceObject(SuppliedToken);
    02940
    02941         //
    02942         // Check to see if the supplied token's parent ID is the ID
    02943         // of the caller.
    02944         //
    02945
    02946         if (RtlEqualLuid(
    02947                 &SuppliedParentTokenId,
    02948                 &CallerTokenId
    02949                 )) {
    02950
    02951             *IsChild = TRUE;
    02952         }
    02953
    02954     }
    02955     return(Status);
    02956 }
    02957
    02958
    02959 NTSTATUS
    02960 SeIsChildTokenByPointer(
    02961     IN PACCESS_TOKEN Token,
    02962     OUT PBOOLEAN IsChild
    02963     )
    02964 /*++
    02965
    02966 Routine Description:
    02967
    02968     This routine returns TRUE if the supplied token is a child of the caller's
    02969     token. This is done by comparing the ParentTokenId field of the supplied
    02970     token to the TokenId field of the token from the current subject context.
    02971
    02972 Arguments:
    02973
    02974     Token - Token to check for childhood
    02975
    02976     IsChild - Contains results of comparison.
    02977
    02978         TRUE - The supplied token is a child of the caller's token
    02979         FALSE- The supplied token is not a child of the caller's token
    02980
    02981 Returns:
    02982
    02983     Status codes from any NT services called.
    02984
    02985 --*/
    02986 {
    02987     SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
    02988     PTOKEN CallerToken;
    02989     PTOKEN SuppliedToken;
    02990     LUID CallerTokenId;
    02991     LUID SuppliedParentTokenId;
    02992     NTSTATUS Status = STATUS_SUCCESS;
    02993
    02994     *IsChild = FALSE;
    02995
    02996     //
    02997     // Capture the caller's token and get the token id
    02998     //
    02999
    03000     CallerToken = (PTOKEN) PsReferencePrimaryToken(PsGetCurrentProcess());
    03001
    03002
    03003     SepAcquireTokenReadLock( CallerToken );
    03004
    03005     CallerTokenId = CallerToken->TokenId;
    03006
    03007     SepReleaseTokenReadLock( CallerToken );
    03008
    03009     PsDereferencePrimaryToken(CallerToken);
    03010
    03011     SuppliedToken = (PTOKEN) Token ;
    03012
    03013     SepAcquireTokenReadLock( SuppliedToken );
    03014
    03015     SuppliedParentTokenId = SuppliedToken->ParentTokenId;
    03016
    03017     SepReleaseTokenReadLock( SuppliedToken );
    03018
    03019     //
    03020     // Check to see if the supplied token's parent ID is the ID
    03021     // of the caller.
    03022     //
    03023
    03024     if (RtlEqualLuid(
    03025             &SuppliedParentTokenId,
    03026             &CallerTokenId
    03027             )) {
    03028
    03029         *IsChild = TRUE;
    03030     }
    03031
    03032
    03033
    03034     return(Status);
    03035 }
    03036
    03037 NTSTATUS
    03038 NtImpersonateAnonymousToken(
    03039     IN HANDLE ThreadHandle
    03040     )
    03041
    03042 /*++
    03043
    03044 Routine Description:
    03045
    03046     Impersonates the system's anonymous logon token on this thread.
    03047
    03048 Arguments:
    03049
    03050     ThreadHandle - Handle to the thread to do the impersonation.
    03051
    03052 Return Value:
    03053
    03054     STATUS_SUCCESS - Indicates the operation was successful.
    03055
    03056     STATUS_INVALID_HANDLE - the thread handle is invalid.
    03057
    03058     STATUS_ACCESS_DENIED - The thread handle is not open for impersonation
    03059         access.
    03060 --*/
    03061 {
    03062     PETHREAD CallerThread = NULL;
    03063     NTSTATUS Status = STATUS_SUCCESS;
    03064
    03065     //
    03066     // Reference the caller's thread to make sure we can impersonate
    03067     //
    03068
    03069     Status = ObReferenceObjectByHandle(
    03070                  ThreadHandle,
    03071                  THREAD_IMPERSONATE,
    03072                  PsThreadType,
    03073                  KeGetPreviousMode(),
    03074                  (PVOID *)&CallerThread,
    03075                  NULL
    03076                  );
    03077     if (!NT_SUCCESS(Status)) {
    03078         goto Cleanup;
    03079     }
    03080
    03081     //
    03082     // Reference the impersonation token to make sure we are allowed to
    03083     // impersonate it.
    03084     //
    03085
    03086     Status = ObReferenceObjectByPointer(
    03087                 SeAnonymousLogonToken,
    03088                 TOKEN_IMPERSONATE,
    03089                 SepTokenObjectType,
    03090                 KeGetPreviousMode()
    03091                 );
    03092     if (!NT_SUCCESS(Status))
    03093     {
    03094         goto Cleanup;
    03095     }
    03096
    03097     ObDereferenceObject(SeAnonymousLogonToken);
    03098
    03099     //
    03100     // Do the impersonation. We want copy on open so the caller can't
    03101     // actually modify this system's copy of this token.
    03102     //
    03103
    03104     Status = PsImpersonateClient(
    03105                 CallerThread,
    03106                 SeAnonymousLogonToken,
    03107                 TRUE,                   // copy on open
    03108                 FALSE,                  // no effective only
    03109                 SecurityImpersonation
    03110                 );
    03111 Cleanup:
    03112
    03113     if (CallerThread != NULL) {
    03114         ObDereferenceObject(CallerThread);
    03115     }
    03116     return(Status);
    03117 }