BOOLEAN AFSIsInGroup(PSID Sid) { SECURITY_SUBJECT_CONTEXT subjectContext; PTOKEN_GROUPS groups; PACCESS_TOKEN token; BOOLEAN retVal = FALSE; SeCaptureSubjectContext( &subjectContext ); SeLockSubjectContext( &subjectContext ); token = SeQuerySubjectContextToken( &subjectContext ); if (NT_SUCCESS(SeQueryInformationToken(token, TokenGroups, (PVOID*) &groups))) { ULONG i; for (i = 0; !retVal && i < groups->GroupCount; i++) { retVal = RtlEqualSid(Sid, groups->Groups[i].Sid); } ExFreePool( groups ); } SeUnlockSubjectContext( &subjectContext ); SeReleaseSubjectContext( &subjectContext ); return retVal; }
BOOLEAN AFSIsUser( IN PSID Sid) { SECURITY_SUBJECT_CONTEXT subjectContext; PTOKEN_USER user; PACCESS_TOKEN token; BOOLEAN retVal = FALSE; SeCaptureSubjectContext( &subjectContext); SeLockSubjectContext( &subjectContext); token = SeQuerySubjectContextToken( &subjectContext); if (NT_SUCCESS (SeQueryInformationToken( token, TokenUser, (PVOID*) &user))) { retVal = RtlEqualSid( user->User.Sid, Sid); ExFreePool( user ); } SeUnlockSubjectContext( &subjectContext); SeReleaseSubjectContext( &subjectContext); return retVal; }
void TestsSeQueryInformationToken(PACCESS_TOKEN Token) { NTSTATUS Status; PVOID Buffer = NULL; PSID sid; PTOKEN_OWNER Towner; PTOKEN_DEFAULT_DACL TDefDacl; PTOKEN_GROUPS TGroups; ULONG GroupCount; PACL acl; PTOKEN_STATISTICS TStats; PTOKEN_TYPE TType; PTOKEN_USER TUser; BOOLEAN Flag; ULONG i; //----------------------------------------------------------------// // Testing SeQueryInformationToken with various args // //----------------------------------------------------------------// ok(Token != NULL, "Token is not captured. Testing SQIT interrupted\n\n"); if (Token == NULL) return; Status = SeQueryInformationToken(Token, TokenOwner, &Buffer); ok((Status == STATUS_SUCCESS), "SQIT with TokenOwner arg fails with status 0x%X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenOwner arg. But Buffer = NULL\n"); if (Buffer) { Towner = (TOKEN_OWNER *)Buffer; sid = Towner->Owner; ok((RtlValidSid(sid) == TRUE), "TokenOwner's SID is not a valid SID\n"); ExFreePool(Buffer); } } //----------------------------------------------------------------// Buffer = NULL; Status = SeQueryInformationToken(Token, TokenDefaultDacl, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenDefaultDacl fails with status 0x%X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenDefaultDacl arg. But Buffer = NULL\n"); if (Buffer) { TDefDacl = (PTOKEN_DEFAULT_DACL)Buffer; acl = TDefDacl->DefaultDacl; ok(((acl->AclRevision == ACL_REVISION || acl->AclRevision == ACL_REVISION_DS) == TRUE), "DACL is invalid\n"); ExFreePool(Buffer); } } //----------------------------------------------------------------// Buffer = NULL; Status = SeQueryInformationToken(Token, TokenGroups, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenGroups fails with status 0x%X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenGroups arg. But Buffer = NULL\n"); if (Buffer) { TGroups = (PTOKEN_GROUPS)Buffer; GroupCount = TGroups->GroupCount; Flag = TRUE; for (i = 0; i < GroupCount; i++) { sid = TGroups->Groups[i].Sid; if (!RtlValidSid(sid)) { Flag = FALSE; break; } } ok((Flag == TRUE), "TokenGroup's SIDs are not valid\n"); ExFreePool(Buffer); } } //----------------------------------------------------------------// // Call SQIT with TokenImpersonationLevel argument // // What's up? Why SQIT fails with right arg? Buffer = NULL; Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenImpersonationLevel fails with status 0x%X\n", Status); Buffer = NULL; Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); ok(Status == STATUS_SUCCESS, "and again: SQIT with TokenImpersonationLevel fails with status 0x%X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenImpersonationLevel arg. But Buffer = NULL\n"); } else { ok(Buffer == NULL, "Wrong. SQIT call is't success. But Buffer != NULL\n"); } //----------------------------------------------------------------// Buffer = NULL; Status = SeQueryInformationToken(Token, TokenStatistics, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenStatistics fails with status 0x%X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenStatistics arg. But Buffer = NULL\n"); if (Buffer) { TStats = (PTOKEN_STATISTICS)Buffer; // just put 0 into 1st arg or use trace to print TokenStatistics f ok(1, "print statistics:\n\tTokenID = %u_%d\n\tSecurityImperLevel = %d\n\tPrivCount = %d\n\tGroupCount = %d\n\n", TStats->TokenId.LowPart, TStats->TokenId.HighPart, TStats->ImpersonationLevel, TStats->PrivilegeCount, TStats->GroupCount ); ExFreePool(TStats); } } else { ok(Buffer == NULL, "Wrong. SQIT call is't success. But Buffer != NULL\n"); } //----------------------------------------------------------------// Buffer = NULL; Status = SeQueryInformationToken(Token, TokenType, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenType fails with status 0x%X\n", Status); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenType arg. But Buffer = NULL\n"); if (Buffer) { TType = (PTOKEN_TYPE)Buffer; ok((*TType == TokenPrimary || *TType == TokenImpersonation), "TokenType in not a primary nor impersonation. FAILED\n"); ExFreePool(TType); } } //----------------------------------------------------------------// Buffer = NULL; Status = SeQueryInformationToken(Token, TokenUser, &Buffer); ok(Status == STATUS_SUCCESS, "SQIT with TokenUser fails\n"); if (Status == STATUS_SUCCESS) { ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenUser arg. But Buffer = NULL\n"); if (Buffer) { TUser = (PTOKEN_USER)Buffer; ok(RtlValidSid(TUser->User.Sid), "TokenUser has an invalid Sid\n"); ExFreePool(TUser); } } //----------------------------------------------------------------// Buffer = NULL; Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); ok(Status != STATUS_SUCCESS, "SQIT must fail with wrong TOKEN_INFORMATION_CLASS arg\n"); }
FLT_POSTOP_CALLBACK_STATUS claimsmanPostOperation( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags ) /*++ Routine Description: This routine is the post-operation completion routine for this miniFilter. This is non-pageable because it may be called at DPC level. Arguments: Data - Pointer to the filter callbackData that is passed to us. FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. CompletionContext - The completion context set in the pre-operation routine. Flags - Denotes whether the completion is successful or is being drained. Return Value: The return value is the status of the operation. --*/ { UNREFERENCED_PARAMETER(Data); UNREFERENCED_PARAMETER(CompletionContext); UNREFERENCED_PARAMETER(Flags); NTSTATUS status; PFLT_FILE_NAME_INFORMATION nameInfo = NULL; PUNICODE_STRING fileName = NULL; PTOKEN_USER pTokenUser = NULL; UNICODE_STRING sidString; LARGE_INTEGER Timeout; Timeout.QuadPart = (LONGLONG)1 * 10 * 1000 * 1000; // If there is no client registered, bail out immediately! // If the event is from kernel, bail out immediately! // If the event check for existence of file, bail out immediately! if ( (ClaimsmanData.ClientPort == NULL) || (Data->RequestorMode == KernelMode) || (Data->IoStatus.Information == FILE_DOES_NOT_EXIST) || (Data->IoStatus.Information == FILE_EXISTS) ) { return FLT_POSTOP_FINISHED_PROCESSING; } // We got a log record, if there is a file object, get its name. if (FltObjects->FileObject != NULL) { status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo); } else { // Can't get a name when there's no file object status = STATUS_UNSUCCESSFUL; } if (NT_SUCCESS(status)) { FltParseFileNameInformation(nameInfo); fileName = &nameInfo->Name; // Produces way too much logging //PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, // ("claimsman!claimsmanPostOperation: fileName=%wZ\n", fileName)); } else { // No point continuing because we obviously did not get a filename anyways return FLT_POSTOP_FINISHED_PROCESSING; } //The only IRP you can trust for user information is IRP_MJ_CREATE. Things //like write can be in arbitrary thread context, and even if the call works //you can get the wrong SID. status = SeQueryInformationToken(SeQuerySubjectContextToken(&(Data->Iopb->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext)), TokenUser, &pTokenUser); if (STATUS_SUCCESS == status && RtlValidSid(pTokenUser->User.Sid)) { // Interesting extension? if (ClaimsmanCheckExtension(&nameInfo->Extension)) { CLAIMSMAN_MESSAGE msg; status = RtlConvertSidToUnicodeString(&sidString, pTokenUser->User.Sid, TRUE); if (NT_SUCCESS(status)) { PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPostOperation: SID=%wZ\n", &sidString)); } else { // No point continuing because we obviously did not get a valid SID FltReleaseFileNameInformation(nameInfo); ExFreePool(pTokenUser); return FLT_POSTOP_FINISHED_PROCESSING; } if (ClaimsmanCheckUserIgnore(&sidString)) { // Ignored user! Bail out! FltReleaseFileNameInformation(nameInfo); ExFreePool(pTokenUser); RtlFreeUnicodeString(&sidString); return FLT_POSTOP_FINISHED_PROCESSING; } LONGLONG size; LONGLONG modified; getSizeModified(FltObjects->Instance, fileName, &size, &modified); InitializeMessage(&msg, &sidString, fileName, FltObjects->FileObject->ReadAccess, FltObjects->FileObject->WriteAccess, FltObjects->FileObject->DeleteAccess, size, modified, Data->IoStatus.Status); // Ready, send the message! // But only if there's a client connected if (ClaimsmanData.ClientPort != NULL) { FltSendMessage(ClaimsmanData.Filter, &ClaimsmanData.ClientPort, &msg, sizeof(msg), NULL, 0, &Timeout ); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPostOperation: sent message=%d\n", status)); } else { PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPostOperation: no client connected!")); } RtlFreeUnicodeString(&sidString); } } FltReleaseFileNameInformation(nameInfo); if (pTokenUser != NULL) { ExFreePool(pTokenUser); } return FLT_POSTOP_FINISHED_PROCESSING; }