static NTSTATUS NtpAllocAsyncContext( OUT PVOID* ppContext, size_t Size ) { NTSTATUS status = STATUS_SUCCESS; PIO_CLIENT_ASYNC_CONTEXT pContext = NULL; static const LWMsgParams init = LWMSG_PARAMS_INITIALIZER; status = RTL_ALLOCATE(&pContext, IO_CLIENT_ASYNC_CONTEXT, Size); BAIL_ON_NT_STATUS(status); pContext->in = init; pContext->out = init; *ppContext = (PVOID) pContext; error: if (status) { *ppContext = NULL; } return status; }
NTSTATUS PvfsListInit( PPVFS_LIST *ppNewList, DWORD dwMaxSize, PPVFS_LIST_FREE_DATA_FN pfnFreeData ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_LIST pList = NULL; BAIL_ON_INVALID_PTR(ppNewList, ntError); ntError = RTL_ALLOCATE(&pList, PVFS_LIST, sizeof(PVFS_LIST)); BAIL_ON_NT_STATUS(ntError); pList->MaxSize = dwMaxSize; pList->CurrentSize = 0; pList->pfnFreeData = pfnFreeData; LwListInit(&pList->DataList); *ppNewList = pList; pList = NULL; ntError = STATUS_SUCCESS; cleanup: RTL_FREE(&pList); return ntError; error: goto cleanup; }
NTSTATUS RtlDuplicateSid( OUT PSID* NewSid, IN PSID OriginalSid ) { NTSTATUS status = STATUS_SUCCESS; ULONG length = RtlLengthSid(OriginalSid); PSID resultSid = NULL; status = RTL_ALLOCATE(&resultSid, SID, length); GOTO_CLEANUP_ON_STATUS(status); RtlCopyMemory(resultSid, OriginalSid, length); cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&resultSid); } *NewSid = resultSid; return status; }
NTSTATUS LwRtlWC16StringDuplicate( OUT PWSTR* ppszNewString, IN PCWSTR pszOriginalString ) { NTSTATUS status = 0; int EE ATTRIBUTE_UNUSED = 0; size_t size = 0; PWSTR pszNewString = NULL; if (!pszOriginalString) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP_ON_STATUS_EE(status, EE); } size = (LwRtlWC16StringNumChars(pszOriginalString) + 1) * sizeof(pszOriginalString[0]); status = RTL_ALLOCATE(&pszNewString, wchar16_t, size); GOTO_CLEANUP_ON_STATUS_EE(status, EE); memcpy(pszNewString, pszOriginalString, size); cleanup: if (status) { RTL_FREE(&pszNewString); } *ppszNewString = pszNewString; return status; }
DWORD UmnSrvInitConfig( PUMN_SRV_API_CONFIG *ppConfig ) { PUMN_SRV_API_CONFIG pConfig = NULL; DWORD dwError = 0; dwError = RTL_ALLOCATE( &pConfig, UMN_SRV_API_CONFIG, sizeof(*pConfig)); BAIL_ON_UMN_ERROR(dwError); pConfig->CheckInterval = 60 * 30; pConfig->SkipNoLogin = FALSE; *ppConfig = pConfig; cleanup: return dwError; error: *ppConfig = NULL; UmnSrvFreeConfig(pConfig); goto cleanup; }
static NTSTATUS ItpCreateDriverState( OUT PIT_DRIVER_STATE* ppState ) { NTSTATUS status = STATUS_SUCCESS; int EE = 0; PIT_DRIVER_STATE pState = NULL; status = RTL_ALLOCATE(&pState, IT_DRIVER_STATE, sizeof(*pState)); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = ItCreateWorkQueue(&pState->pWorkQueue); GOTO_CLEANUP_ON_STATUS_EE(status, EE); cleanup: if (status) { ItpDestroyDriverState(&pState); } *ppState = pState; LOG_LEAVE_IF_STATUS_EE(status, EE); return status; }
LW_NTSTATUS LwIoAllocateMemory( size_t Size, LW_PVOID * ppMemory ) { return RTL_ALLOCATE(ppMemory, VOID, Size); }
NTSTATUS PvfsAllocateMemory( OUT PVOID *ppBuffer, IN DWORD dwSize ) { /* No op */ if (dwSize == 0) { *ppBuffer = NULL; return STATUS_SUCCESS; } /* Real work */ return RTL_ALLOCATE(ppBuffer, VOID, dwSize); }
NTSTATUS RdrAllocatePacketBuffer( PSMB_PACKET pPacket, ULONG ulSize ) { NTSTATUS status = STATUS_SUCCESS; status = RTL_ALLOCATE(&pPacket->pRawBuffer, BYTE, ulSize); BAIL_ON_NT_STATUS(status); pPacket->bufferLen = ulSize; error: return status; }
NTSTATUS LwRtlAnsiStringDuplicate( OUT PANSI_STRING pNewString, IN PANSI_STRING pOriginalString ) { NTSTATUS status = 0; int EE ATTRIBUTE_UNUSED = 0; ANSI_STRING newString = { 0 }; if (!pOriginalString || !pNewString) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP_ON_STATUS_EE(status, EE); } if (pOriginalString->Buffer && pOriginalString->Length > 0) { // Add a NULL anyhow. newString.Length = pOriginalString->Length; newString.MaximumLength = pOriginalString->Length + sizeof(pOriginalString->Buffer[0]); status = RTL_ALLOCATE(&newString.Buffer, CHAR, newString.MaximumLength); GOTO_CLEANUP_ON_STATUS_EE(status, EE); memcpy(newString.Buffer, pOriginalString->Buffer, pOriginalString->Length); newString.Buffer[newString.Length/sizeof(newString.Buffer[0])] = 0; } cleanup: if (status) { RtlAnsiStringFree(&newString); } if (pNewString) { *pNewString = newString; } return status; }
NTSTATUS PvfsFileDirname( PSTR *ppszDirname, PCSTR pszPath ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PSTR pszCursor = NULL; PSTR pszNewString = NULL; /* Case #1: No '/' so just return '.' */ if (((pszCursor = strrchr(pszPath, '/')) == NULL)) { ntError = RtlCStringDuplicate(ppszDirname, "."); goto cleanup; } /* Case #2: only one '/' (at beginning of path) */ if (pszCursor == pszPath) { ntError = RtlCStringDuplicate(ppszDirname, "/"); goto cleanup; } /* Case #3: Real dirname and file name components */ ntError = RTL_ALLOCATE(&pszNewString, CHAR, PVFS_PTR_DIFF(pszPath,pszCursor) + 1); BAIL_ON_NT_STATUS(ntError); RtlCopyMemory(pszNewString, pszPath, PVFS_PTR_DIFF(pszPath,pszCursor)); *ppszDirname = pszNewString; ntError = STATUS_SUCCESS; cleanup: return ntError; error: goto cleanup; }
DWORD RegAllocateMemory( size_t Size, LW_PVOID * ppMemory ) { DWORD dwError = 0; if (Size) { dwError = RegNtStatusToWin32Error( RTL_ALLOCATE(ppMemory, VOID, Size) ); } else { dwError = RegNtStatusToWin32Error(LW_STATUS_INSUFFICIENT_RESOURCES); } return dwError; }
static NTSTATUS NpfsCommonProcessCreateEcp( PNPFS_IRP_CONTEXT pIrpContext, PIRP pIrp, PNPFS_CCB pCCB ) { NTSTATUS ntStatus = STATUS_SUCCESS; PNPFS_PIPE pPipe = pCCB->pPipe; PBYTE pSessionKey = NULL; ULONG ulSessionKeyLength = 0; PBYTE pAddr = NULL; ULONG ulEcpSize = 0; PFILE_NETWORK_OPEN_INFORMATION pNetworkOpenInfo = NULL; PFILE_PIPE_INFORMATION pPipeInfo = NULL; PFILE_PIPE_LOCAL_INFORMATION pPipeLocalInfo = NULL; ntStatus = IoRtlEcpListFind( pIrp->Args.Create.EcpList, IO_ECP_TYPE_SESSION_KEY, OUT_PPVOID(&pSessionKey), &ulSessionKeyLength); if (ntStatus != STATUS_NOT_FOUND) { BAIL_ON_NT_STATUS(ntStatus); ntStatus = RTL_ALLOCATE(&pPipe->pSessionKey, BYTE, ulSessionKeyLength); BAIL_ON_NT_STATUS(ntStatus); memcpy(pPipe->pSessionKey, pSessionKey, ulSessionKeyLength); pPipe->ulSessionKeyLength = ulSessionKeyLength; } ntStatus = IoRtlEcpListFind( pIrp->Args.Create.EcpList, IO_ECP_TYPE_PEER_ADDRESS, OUT_PPVOID(&pAddr), &ulEcpSize); if (ntStatus != STATUS_NOT_FOUND) { BAIL_ON_NT_STATUS(ntStatus); if (ulEcpSize > sizeof(pPipe->ClientAddress)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } pPipe->usClientAddressLen = (USHORT) ulEcpSize; memcpy(pPipe->ClientAddress, pAddr, ulEcpSize); } ntStatus = IoRtlEcpListFind( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_NET_OPEN_INFO, OUT_PPVOID(&pNetworkOpenInfo), &ulEcpSize); if (ntStatus == STATUS_SUCCESS) { if (ulEcpSize != sizeof(FILE_NETWORK_OPEN_INFORMATION)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NpfsQueryCcbFileNetworkOpenInfo(pCCB, pNetworkOpenInfo); BAIL_ON_NT_STATUS(ntStatus); ntStatus = IoRtlEcpListAcknowledge( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_NET_OPEN_INFO); BAIL_ON_NT_STATUS(ntStatus); } else { ntStatus = STATUS_SUCCESS; } ntStatus = IoRtlEcpListFind( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_PIPE_INFO, OUT_PPVOID(&pPipeInfo), &ulEcpSize); if (ntStatus == STATUS_SUCCESS) { if (ulEcpSize != sizeof(FILE_PIPE_INFORMATION)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NpfsQueryCcbFilePipeInfo(pCCB, pPipeInfo); BAIL_ON_NT_STATUS(ntStatus); ntStatus = IoRtlEcpListAcknowledge( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_PIPE_INFO); BAIL_ON_NT_STATUS(ntStatus); } else { ntStatus = STATUS_SUCCESS; } ntStatus = IoRtlEcpListFind( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_PIPE_LOCAL_INFO, OUT_PPVOID(&pPipeLocalInfo), &ulEcpSize); if (ntStatus == STATUS_SUCCESS) { if (ulEcpSize != sizeof(FILE_PIPE_LOCAL_INFORMATION)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NpfsQueryCcbFilePipeLocalInfo(pCCB, pPipeLocalInfo); BAIL_ON_NT_STATUS(ntStatus); ntStatus = IoRtlEcpListAcknowledge( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_PIPE_LOCAL_INFO); BAIL_ON_NT_STATUS(ntStatus); } else { ntStatus = STATUS_SUCCESS; } cleanup: return ntStatus; error: goto cleanup; }
NTSTATUS RtlAllocateCStringFromSid( OUT PSTR* StringSid, IN PSID Sid ) { NTSTATUS status = STATUS_SUCCESS; PSTR result = NULL; size_t size = 0; int count = 0; ULONG i = 0; if (!StringSid || !RtlValidSid(Sid)) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } size = RTLP_STRING_SID_MAX_CHARS(Sid->SubAuthorityCount); status = RTL_ALLOCATE(&result, CHAR, size); GOTO_CLEANUP_ON_STATUS(status); if (Sid->IdentifierAuthority.Value[0] || Sid->IdentifierAuthority.Value[1]) { count += snprintf(result + count, size - count, "S-%u-0x%.2X%.2X%.2X%.2X%.2X%.2X", Sid->Revision, Sid->IdentifierAuthority.Value[0], Sid->IdentifierAuthority.Value[1], Sid->IdentifierAuthority.Value[2], Sid->IdentifierAuthority.Value[3], Sid->IdentifierAuthority.Value[4], Sid->IdentifierAuthority.Value[5]); } else { ULONG value = 0; value |= (ULONG) Sid->IdentifierAuthority.Value[5]; value |= (ULONG) Sid->IdentifierAuthority.Value[4] << 8; value |= (ULONG) Sid->IdentifierAuthority.Value[3] << 16; value |= (ULONG) Sid->IdentifierAuthority.Value[2] << 24; count += snprintf(result + count, size - count, "S-%u-%u", Sid->Revision, value); } for (i = 0; i < Sid->SubAuthorityCount; i++) { count += snprintf(result + count, size - count, "-%u", Sid->SubAuthority[i]); } status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&result); } if (StringSid) { *StringSid = result; } return status; }
NTSTATUS RtlCreateAccessToken( OUT PACCESS_TOKEN* AccessToken, IN PTOKEN_USER User, IN PTOKEN_GROUPS Groups, IN PTOKEN_PRIVILEGES Privileges, IN PTOKEN_OWNER Owner, IN PTOKEN_PRIMARY_GROUP PrimaryGroup, IN PTOKEN_DEFAULT_DACL DefaultDacl, IN OPTIONAL PTOKEN_UNIX Unix ) { NTSTATUS status = STATUS_SUCCESS; int unixError = 0; ULONG requiredSize = 0; PACCESS_TOKEN token = NULL; ULONG i = 0; ULONG size = 0; PVOID location = NULL; if (!User || !User->User.Sid || !Groups || !Owner || !PrimaryGroup || !DefaultDacl) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if (!RtlValidSid(User->User.Sid) || (Owner->Owner && !RtlValidSid(Owner->Owner)) || (PrimaryGroup->PrimaryGroup && !RtlValidSid(PrimaryGroup->PrimaryGroup))) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } // No user attributes currently exist. if (User->User.Attributes != 0) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } for (i = 0; i < Groups->GroupCount; i++) { // TODO-Perhaps validate Group attributes if (!Groups->Groups[i].Sid) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if (!RtlValidSid(Groups->Groups[i].Sid)) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } } if (DefaultDacl->DefaultDacl && !RtlValidAcl(DefaultDacl->DefaultDacl, NULL)) { status = STATUS_INVALID_ACL; GOTO_CLEANUP(); } // Compute size required requiredSize = sizeof(*token); size = RtlLengthSid(User->User.Sid); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); if (Owner->Owner) { size = RtlLengthSid(Owner->Owner); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); } if (PrimaryGroup->PrimaryGroup) { size = RtlLengthSid(PrimaryGroup->PrimaryGroup); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); } if (DefaultDacl->DefaultDacl) { status = RtlSafeAddULONG(&requiredSize, requiredSize, DefaultDacl->DefaultDacl->AclSize); GOTO_CLEANUP_ON_STATUS(status); } status = RtlSafeMultiplyULONG(&size, sizeof(Groups->Groups[0]), Groups->GroupCount); GOTO_CLEANUP_ON_STATUS(status); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); for (i = 0; i < Groups->GroupCount; i++) { size = RtlLengthSid(Groups->Groups[i].Sid); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); } status = RtlSafeMultiplyULONG(&size, sizeof(Privileges->Privileges[0]), Privileges->PrivilegeCount); GOTO_CLEANUP_ON_STATUS(status); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); status = RTL_ALLOCATE(&token, ACCESS_TOKEN, requiredSize); GOTO_CLEANUP_ON_STATUS(status); location = LW_PTR_ADD(token, sizeof(*token)); // Initialize token->ReferenceCount = 1; token->Flags = 0; unixError = pthread_rwlock_init(&token->RwLock, NULL); if (unixError) { LW_RTL_LOG_ERROR("Failed to init rwlock in access token " "(error = %d).", unixError); status = LwErrnoToNtStatus(unixError); GOTO_CLEANUP(); } token->pRwLock = &token->RwLock; token->User.Attributes = User->User.Attributes; token->User.Sid = (PSID) location; location = RtlpAppendData(location, User->User.Sid, RtlLengthSid(User->User.Sid)); token->GroupCount = Groups->GroupCount; token->Groups = (PSID_AND_ATTRIBUTES) location; location = LwRtlOffsetToPointer(location, sizeof(Groups->Groups[0]) * Groups->GroupCount); for (i = 0; i < Groups->GroupCount; i++) { token->Groups[i].Attributes = Groups->Groups[i].Attributes; token->Groups[i].Sid = (PSID) location; location = RtlpAppendData(location, Groups->Groups[i].Sid, RtlLengthSid(Groups->Groups[i].Sid)); } token->PrivilegeCount = Privileges->PrivilegeCount; token->Privileges = (PLUID_AND_ATTRIBUTES) location; location = LwRtlOffsetToPointer( location, sizeof(Privileges->Privileges[0]) * Privileges->PrivilegeCount); memcpy(token->Privileges, Privileges->Privileges, sizeof(token->Privileges[0]) * token->PrivilegeCount); if (Owner->Owner) { token->Owner = (PSID) location; location = RtlpAppendData(location, Owner->Owner, RtlLengthSid(Owner->Owner)); } if (PrimaryGroup->PrimaryGroup) { token->PrimaryGroup = (PSID) location; location = RtlpAppendData(location, PrimaryGroup->PrimaryGroup, RtlLengthSid(PrimaryGroup->PrimaryGroup)); } if (DefaultDacl->DefaultDacl) { token->DefaultDacl = (PACL) location; location = RtlpAppendData(location, DefaultDacl->DefaultDacl, DefaultDacl->DefaultDacl->AclSize); } if (Unix) { SetFlag(token->Flags, ACCESS_TOKEN_FLAG_UNIX_PRESENT); token->Uid = Unix->Uid; token->Gid = Unix->Gid; token->Umask = Unix->Umask; } if (location != LW_PTR_ADD(token, requiredSize)) { status = STATUS_ASSERTION_FAILURE; GOTO_CLEANUP(); } status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RtlReleaseAccessToken(&token); } *AccessToken = token; return status; }
NTSTATUS LwNtCreateFile( OUT PIO_FILE_HANDLE FileHandle, IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PIO_FILE_NAME FileName, IN OPTIONAL PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, IN OPTIONAL PVOID SecurityQualityOfService, // TBD IN ACCESS_MASK DesiredAccess, IN OPTIONAL LONG64 AllocationSize, IN FILE_ATTRIBUTES FileAttributes, IN FILE_SHARE_FLAGS ShareAccess, IN FILE_CREATE_DISPOSITION CreateDisposition, IN FILE_CREATE_OPTIONS CreateOptions, IN OPTIONAL PVOID EaBuffer, // PFILE_FULL_EA_INFORMATION IN ULONG EaLength, IN OPTIONAL PIO_ECP_LIST EcpList, IN OPTIONAL LW_PIO_CREDS pCreds ) { NTSTATUS status = 0; int EE = 0; PIO_CREDS pActiveCreds = NULL; PCREATEFILE_CONTEXT pCreateContext = NULL; if (!pCreds) { status = LwIoGetActiveCreds(FileName->FileName, &pActiveCreds); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pCreds = pActiveCreds; } status = NtpAllocAsyncContext(OUT_PPVOID(&pCreateContext), sizeof(*pCreateContext)); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pCreateContext->IoStatusBlock = IoStatusBlock; pCreateContext->FileHandle = FileHandle; status = LwIoResolveCreds(pCreds, &pCreateContext->Request.pSecurityToken); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pCreateContext->Request.FileName = *FileName; pCreateContext->Request.DesiredAccess = DesiredAccess; pCreateContext->Request.AllocationSize = AllocationSize; pCreateContext->Request.FileAttributes = FileAttributes; pCreateContext->Request.ShareAccess = ShareAccess; pCreateContext->Request.CreateDisposition = CreateDisposition; pCreateContext->Request.CreateOptions = CreateOptions; pCreateContext->Request.EaBuffer = EaBuffer; pCreateContext->Request.EaLength = EaLength; if (SecurityDescriptor) { pCreateContext->Request.SecurityDescriptor = SecurityDescriptor; pCreateContext->Request.SecDescLength = RtlLengthSecurityDescriptorRelative(SecurityDescriptor); } pCreateContext->Request.EcpCount = IoRtlEcpListGetCount(EcpList); if (pCreateContext->Request.EcpCount) { PCSTR pszType = NULL; ULONG ecpIndex = 0; status = RTL_ALLOCATE( &pCreateContext->Request.EcpList, NT_IPC_HELPER_ECP, sizeof(*pCreateContext->Request.EcpList) * pCreateContext->Request.EcpCount); GOTO_CLEANUP_ON_STATUS_EE(status, EE); while (ecpIndex < pCreateContext->Request.EcpCount) { status = IoRtlEcpListGetNext( EcpList, pszType, &pCreateContext->Request.EcpList[ecpIndex].pszType, &pCreateContext->Request.EcpList[ecpIndex].pData, &pCreateContext->Request.EcpList[ecpIndex].Size); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pszType = pCreateContext->Request.EcpList[ecpIndex].pszType; ecpIndex++; } assert(ecpIndex == pCreateContext->Request.EcpCount); status = STATUS_SUCCESS; } status = NtpCtxCallAsync( &pCreateContext->Base, NT_IPC_MESSAGE_TYPE_CREATE_FILE, &pCreateContext->Request, NT_IPC_MESSAGE_TYPE_CREATE_FILE_RESULT, AsyncControlBlock, LwNtCreateFileComplete); GOTO_CLEANUP_ON_STATUS_EE(status, EE); cleanup: if (pActiveCreds) { LwIoDeleteCreds(pActiveCreds); } if (status != STATUS_PENDING) { if (pCreateContext) { LwNtCreateFileComplete(&pCreateContext->Base, status); status = IoStatusBlock->Status; NtpFreeClientAsyncContext(&pCreateContext->Base); } else { IoStatusBlock->Status = status; } } LOG_LEAVE_IF_STATUS_EE(status, EE); return status; }
LW_NTSTATUS LwIoSetRdrDomainHints( LW_PWSTR* ppwszDomains, ULONG ulCount ) { NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK ioStatus = {0}; WCHAR wszRdrPath[] = {'\\', 'r', 'd', 'r', '\0'}; UNICODE_STRING rdrPath = LW_RTL_CONSTANT_STRING(wszRdrPath); IO_FILE_NAME fileName = {0}; IO_FILE_HANDLE hFile = NULL; PWSTR pwszBuffer = NULL; ULONG ulLength = 0; ULONG ulIndex = 0; ULONG ulOffset = 0; ULONG ulStrLen = 0; for (ulIndex = 0; ulIndex < ulCount; ulIndex++) { ulLength += (LwRtlWC16StringNumChars(ppwszDomains[ulIndex]) + 1) * sizeof(WCHAR); } status = RTL_ALLOCATE(&pwszBuffer, WCHAR, ulLength); BAIL_ON_NT_STATUS(status); for (ulIndex = 0; ulIndex < ulCount; ulIndex++) { ulStrLen = (LwRtlWC16StringNumChars(ppwszDomains[ulIndex]) + 1) * sizeof(WCHAR); memcpy((PBYTE) pwszBuffer + ulOffset, ppwszDomains[ulIndex], ulStrLen); ulOffset += ulStrLen; } fileName.Name = rdrPath; status = LwNtCreateFile( &hFile, NULL, &ioStatus, &fileName, NULL, NULL, FILE_GENERIC_WRITE, 0, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0, NULL, NULL); BAIL_ON_NT_STATUS(status); status = LwNtDeviceIoControlFile( hFile, NULL, &ioStatus, RDR_DEVCTL_SET_DOMAIN_HINTS, pwszBuffer, ulLength, NULL, 0); BAIL_ON_NT_STATUS(status); cleanup: RTL_FREE(&pwszBuffer); if (hFile) { LwNtCloseFile(hFile); } return status; error: goto cleanup; }
static NTSTATUS PvfsResolvePath( PSTR *ppszResolvedPath, PCSTR pszLookupPath ) { NTSTATUS ntError = STATUS_SUCCESS; PSTR pszCursor = NULL; PSTR pszComponent = NULL; PSTR pszPath = NULL; PVFS_STAT Stat = {0}; PSTR pszResolvedPath = NULL; PSTR pszResWorkingPath = NULL; PSTR pszWorkingPath = NULL; DWORD Length = PATH_MAX; DIR *pDir = NULL; struct dirent *pDirEntry = NULL; if (*pszLookupPath != '/') { ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } ntError = RTL_ALLOCATE(&pszResolvedPath, CHAR, Length); BAIL_ON_NT_STATUS(ntError); ntError = RTL_ALLOCATE(&pszWorkingPath, CHAR, PATH_MAX); BAIL_ON_NT_STATUS(ntError); ntError = RtlCStringDuplicate(&pszPath, pszLookupPath); BAIL_ON_NT_STATUS(ntError); pszComponent = pszPath + 1; while (pszComponent && (Length > 0)) { pDir = NULL; if ((pszCursor = strchr(pszComponent, '/')) != NULL) { *pszCursor = '\0'; } snprintf(pszWorkingPath, PATH_MAX-1, "%s/%s", pszResolvedPath, pszComponent); /* Try cache first */ ntError = PvfsPathCacheLookup(&pszResWorkingPath, pszWorkingPath); if(ntError == STATUS_SUCCESS) { strncpy(pszResolvedPath, pszResWorkingPath, PATH_MAX-1); Length = PATH_MAX - RtlCStringNumChars(pszResolvedPath); RtlCStringFree(&pszResWorkingPath); } /* Maybe an exact match on disk? */ else if (PvfsSysStat(pszWorkingPath, &Stat) == STATUS_SUCCESS) { strncpy(pszResolvedPath, pszWorkingPath, PATH_MAX-1); Length = PATH_MAX - RtlCStringNumChars(pszResolvedPath); RtlCStringFree(&pszResWorkingPath); ntError = PvfsPathCacheAdd(pszResolvedPath); BAIL_ON_NT_STATUS(ntError); } /* Do the work ourselves */ else { /* Enumerate directory entries and look for a match */ ntError = PvfsSysOpenDir(pszResolvedPath, &pDir); if (ntError == STATUS_NOT_A_DIRECTORY) { ntError = STATUS_OBJECT_PATH_NOT_FOUND; } BAIL_ON_NT_STATUS(ntError); for(ntError = PvfsSysReadDir(pDir, &pDirEntry); pDirEntry; ntError = PvfsSysReadDir(pDir, &pDirEntry)) { /* First check the error return */ BAIL_ON_NT_STATUS(ntError); if (RtlCStringIsEqual(pszComponent, pDirEntry->d_name, FALSE)) { break; } } /* Did we find a match? */ if (!pDirEntry) { /* Return code depends on whether the last component was not found or if an intermediate component was invalid */ if (pszCursor == NULL) { ntError = STATUS_OBJECT_NAME_NOT_FOUND; } else { ntError = STATUS_OBJECT_PATH_NOT_FOUND; } BAIL_ON_NT_STATUS(ntError); } strncat(pszResolvedPath, "/", Length-1); Length -= 1; strncat(pszResolvedPath, pDirEntry->d_name, Length-1); Length -= RtlCStringNumChars(pDirEntry->d_name); ntError = PvfsSysCloseDir(pDir); pDir = NULL; BAIL_ON_NT_STATUS(ntError); ntError = PvfsPathCacheAdd(pszResolvedPath); BAIL_ON_NT_STATUS(ntError); } /* Cleanup for next loop */ if (pszCursor) { *pszCursor = '/'; } if ((pszComponent = strchr(pszComponent, '/')) != NULL) { pszComponent++; } } /* Did we finish? */ if ((Length <= 0) && (pszComponent != NULL)) { ntError = STATUS_NAME_TOO_LONG; BAIL_ON_NT_STATUS(ntError); } *ppszResolvedPath = pszResolvedPath; pszResolvedPath = NULL; ntError = STATUS_SUCCESS; cleanup: RtlCStringFree(&pszPath); RtlCStringFree(&pszWorkingPath); RtlCStringFree(&pszResWorkingPath); RtlCStringFree(&pszResolvedPath); if (pDir) { PvfsSysCloseDir(pDir); } return ntError; error: goto cleanup; }
NTSTATUS LwNtCreateNamedPipeFile( OUT PIO_FILE_HANDLE FileHandle, IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PIO_FILE_NAME FileName, IN OPTIONAL PVOID SecurityDescriptor, // TBD IN OPTIONAL PVOID SecurityQualityOfService, // TBD IN ACCESS_MASK DesiredAccess, IN FILE_SHARE_FLAGS ShareAccess, IN FILE_CREATE_DISPOSITION CreateDisposition, IN FILE_CREATE_OPTIONS CreateOptions, IN FILE_PIPE_TYPE_MASK NamedPipeType, IN FILE_PIPE_READ_MODE_MASK ReadMode, IN FILE_PIPE_COMPLETION_MODE_MASK CompletionMode, IN ULONG MaximumInstances, IN ULONG InboundQuota, IN ULONG OutboundQuota, IN OPTIONAL PLONG64 DefaultTimeout ) { NTSTATUS status = 0; int EE = 0; PIO_ECP_LIST ecpList = NULL; PIO_ECP_NAMED_PIPE pPipeParams = NULL; PCREATEPIPE_CONTEXT pContext = NULL; status = RTL_ALLOCATE(&pPipeParams, IO_ECP_NAMED_PIPE, sizeof(*pPipeParams)); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = IoRtlEcpListAllocate(&ecpList); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pPipeParams->NamedPipeType = NamedPipeType; pPipeParams->ReadMode = ReadMode; pPipeParams->CompletionMode = CompletionMode; pPipeParams->MaximumInstances = MaximumInstances; pPipeParams->InboundQuota = InboundQuota; pPipeParams->OutboundQuota = OutboundQuota; if (DefaultTimeout) { pPipeParams->DefaultTimeout = *DefaultTimeout; pPipeParams->HaveDefaultTimeout = TRUE; } status = IoRtlEcpListInsert(ecpList, IO_ECP_TYPE_NAMED_PIPE, pPipeParams, sizeof(*pPipeParams), LwRtlMemoryFree); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pPipeParams = NULL; if (AsyncControlBlock) { status = RTL_ALLOCATE(&pContext, CREATEPIPE_CONTEXT, sizeof(*pContext)); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pContext->pEcpList = ecpList; pContext->pChain = AsyncControlBlock; pContext->AsyncControl.Callback = LwNtCreateNamedPipeComplete; pContext->AsyncControl.CallbackContext = pContext; AsyncControlBlock = &pContext->AsyncControl; } status = NtCreateFile( FileHandle, AsyncControlBlock, IoStatusBlock, FileName, SecurityDescriptor, SecurityQualityOfService, DesiredAccess, 0, 0, ShareAccess, CreateDisposition, CreateOptions, NULL, 0, ecpList, NULL); if (pContext) { pContext->pChain->AsyncCancelContext = pContext->AsyncControl.AsyncCancelContext; } cleanup: if (status != STATUS_PENDING) { if (pContext) { IoRtlEcpListFree(&pContext->pEcpList); RTL_FREE(&pContext); } else { IoRtlEcpListFree(&ecpList); } IoStatusBlock->Status = status; RTL_FREE(&pPipeParams); } LOG_LEAVE_IF_STATUS_EE(status, EE); return status; }
NTSTATUS LwIoFuseRename( const char* pszOldPath, const char* pszNewPath ) { NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK ioStatus = {0}; IO_FILE_HANDLE handle = NULL; PIO_FUSE_CONTEXT pFuseContext = NULL; IO_FILE_NAME filename = {0}; PFILE_RENAME_INFORMATION pRenameInfo = NULL; PWSTR pwszNewPath = NULL; size_t newPathLength = 0; pFuseContext = LwIoFuseGetContext(); status = LwIoFuseGetDriverRelativePath( pFuseContext, pszNewPath, &pwszNewPath); BAIL_ON_NT_STATUS(status); newPathLength = LwRtlWC16StringNumChars(pwszNewPath); status = RTL_ALLOCATE( &pRenameInfo, FILE_RENAME_INFORMATION, sizeof(*pRenameInfo) + (newPathLength + 1) * sizeof(WCHAR)); BAIL_ON_NT_STATUS(status); pRenameInfo->ReplaceIfExists = TRUE; pRenameInfo->RootDirectory = NULL; pRenameInfo->FileNameLength = newPathLength * sizeof(WCHAR); memcpy(pRenameInfo->FileName, pwszNewPath, newPathLength * sizeof(WCHAR)); status = LwIoFuseGetNtFilename( pFuseContext, pszOldPath, &filename); BAIL_ON_NT_STATUS(status); status = LwNtCreateFile( &handle, /* File handle */ NULL, /* Async control block */ &ioStatus, /* IO status block */ &filename, /* Filename */ NULL, /* Security descriptor */ NULL, /* Security QOS */ DELETE, /* Desired access mask */ 0, /* Allocation size */ 0, /* File attributes */ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* Share access */ FILE_OPEN, /* Create disposition */ 0, /* Create options */ NULL, /* EA buffer */ 0, /* EA length */ NULL, /* ECP list */ NULL); BAIL_ON_NT_STATUS(status); status = LwNtSetInformationFile( handle, /* File handle */ NULL, /* Async control block */ &ioStatus, /* IO status block */ pRenameInfo, /* File information */ sizeof(*pRenameInfo) + (newPathLength + 1) * sizeof(WCHAR), /* File information size */ FileRenameInformation); /* Information class */ BAIL_ON_NT_STATUS(status); cleanup: if (handle) { LwNtCloseFile(handle); } RTL_UNICODE_STRING_FREE(&filename.Name); RTL_FREE(&pwszNewPath); RTL_FREE(&pRenameInfo); return status; error: goto cleanup; }
LW_NTSTATUS LwIoGetPeerAccessToken( IO_FILE_HANDLE File, PACCESS_TOKEN* ppToken ) { NTSTATUS Status = STATUS_SUCCESS; IO_STATUS_BLOCK IoStatus; ULONG ulLength = ACCESS_TOKEN_LENGTH; PBYTE pBuffer = NULL; PBYTE pNewBuffer = NULL; Status = RTL_ALLOCATE(&pBuffer, BYTE, ulLength); BAIL_ON_NT_STATUS(Status); do { Status = LwNtFsControlFile( File, NULL, &IoStatus, IO_FSCTL_SMB_GET_PEER_ACCESS_TOKEN, NULL, 0, pBuffer, ulLength); if (Status == STATUS_BUFFER_TOO_SMALL) { ulLength *= 2; pNewBuffer = LwRtlMemoryRealloc(pBuffer, ulLength); if (!pNewBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; BAIL_ON_NT_STATUS(Status); } pBuffer = pNewBuffer; } } while (Status == STATUS_BUFFER_TOO_SMALL); BAIL_ON_NT_STATUS(Status); if (IoStatus.BytesTransferred > 0) { Status = RtlSelfRelativeAccessTokenToAccessToken( (PACCESS_TOKEN_SELF_RELATIVE) pBuffer, IoStatus.BytesTransferred, ppToken); BAIL_ON_NT_STATUS(Status); } else { *ppToken = NULL; } cleanup: RTL_FREE(&pBuffer); return Status; error: *ppToken = NULL; goto cleanup; }
NTSTATUS SrvShareSetDefaultSecurity( PSRV_SHARE_INFO pShareInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_RELATIVE pRelSecDesc = NULL; ULONG ulRelSecDescLen = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsSecDesc = NULL; DWORD dwAceCount = 0; PSID pOwnerSid = NULL; PSID pGroupSid = NULL; PACL pDacl = NULL; DWORD dwSizeDacl = 0; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } administratorsSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } powerUsersSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } everyoneSid; ULONG ulAdministratorsSidSize = sizeof(administratorsSid.buffer); ULONG ulPowerUsersSidSize = sizeof(powerUsersSid.buffer); ULONG ulEveryoneSidSize = sizeof(everyoneSid.buffer); ACCESS_MASK worldAccessMask = 0; /* Clear out any existing SecDesc's. This is not a normal use case, but be paranoid */ if (pShareInfo->ulSecDescLen) { SrvShareFreeSecurity(pShareInfo); } /* Build the new Absolute Security Descriptor */ ntStatus = RTL_ALLOCATE( &pAbsSecDesc, VOID, SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateSecurityDescriptorAbsolute( pAbsSecDesc, SECURITY_DESCRIPTOR_REVISION); BAIL_ON_NT_STATUS(ntStatus); /* Create some SIDs */ ntStatus = RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, (PSID)administratorsSid.buffer, &ulAdministratorsSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinBuiltinPowerUsersSid, NULL, (PSID)powerUsersSid.buffer, &ulPowerUsersSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinWorldSid, NULL, (PSID)everyoneSid.buffer, &ulEveryoneSidSize); BAIL_ON_NT_STATUS(ntStatus); /* Owner: Administrators */ ntStatus = RtlDuplicateSid(&pOwnerSid, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetOwnerSecurityDescriptor( pAbsSecDesc, pOwnerSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Group: Power Users */ ntStatus = RtlDuplicateSid(&pGroupSid, &powerUsersSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetGroupSecurityDescriptor( pAbsSecDesc, pGroupSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* DACL: Administrators - (Full Control) Everyone - (Read) for disk shares, (Read/Write) to IPC shares */ dwAceCount = 2; dwSizeDacl = ACL_HEADER_SIZE + dwAceCount * sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&administratorsSid.sid) + RtlLengthSid(&everyoneSid.sid) - dwAceCount * sizeof(ULONG); ntStatus= RTL_ALLOCATE(&pDacl, VOID, dwSizeDacl); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateAcl(pDacl, dwSizeDacl, ACL_REVISION); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, 0, FILE_ALL_ACCESS, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); worldAccessMask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE; if (pShareInfo->service == SHARE_SERVICE_NAMED_PIPE) { worldAccessMask |= FILE_GENERIC_WRITE; } ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, 0, worldAccessMask, &everyoneSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetDaclSecurityDescriptor( pAbsSecDesc, TRUE, pDacl, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Create the SelfRelative SD and assign them to the Share */ ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, NULL, &ulRelSecDescLen); if (ntStatus == STATUS_BUFFER_TOO_SMALL) { ntStatus = SrvAllocateMemory(ulRelSecDescLen, (PVOID*)&pRelSecDesc); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, pRelSecDesc, &ulRelSecDescLen); } BAIL_ON_NT_STATUS(ntStatus); pShareInfo->pSecDesc = pRelSecDesc; pShareInfo->ulSecDescLen = ulRelSecDescLen; pShareInfo->pAbsSecDesc = pAbsSecDesc; ntStatus = STATUS_SUCCESS; cleanup: return ntStatus; error: RTL_FREE(&pAbsSecDesc); RTL_FREE(&pOwnerSid); RTL_FREE(&pGroupSid); RTL_FREE(&pDacl); if (pRelSecDesc) { SrvFreeMemory(pRelSecDesc); } goto cleanup; }
static NTSTATUS SrvShareCreateAbsoluteSecDescFromRel( OUT PSECURITY_DESCRIPTOR_ABSOLUTE *ppAbsSecDesc, IN PSECURITY_DESCRIPTOR_RELATIVE pRelSecDesc ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsSecDesc = NULL; ULONG ulAbsSecDescLen = 0; PACL pDacl = NULL; ULONG ulDaclLen = 0; PACL pSacl = NULL; ULONG ulSaclLen = 0; PSID pOwner = NULL; ULONG ulOwnerLen = 0; PSID pGroup = NULL; ULONG ulGroupLen = 0; /* Get sizes for the Absolute SD */ ntStatus = RtlSelfRelativeToAbsoluteSD( pRelSecDesc, pAbsSecDesc, &ulAbsSecDescLen, pDacl, &ulDaclLen, pSacl, &ulSaclLen, pOwner, &ulOwnerLen, pGroup, &ulGroupLen); if (ntStatus == STATUS_BUFFER_TOO_SMALL) { ntStatus = STATUS_SUCCESS; } BAIL_ON_NT_STATUS(ntStatus); /* Allocate -- Always use RTL routines for Absolute SDs */ if (ulOwnerLen) { ntStatus = RTL_ALLOCATE(&pOwner, SID, ulOwnerLen); BAIL_ON_NT_STATUS(ntStatus); } if (ulGroupLen) { ntStatus = RTL_ALLOCATE(&pGroup, SID, ulGroupLen); BAIL_ON_NT_STATUS(ntStatus); } if (ulDaclLen) { ntStatus = RTL_ALLOCATE(&pDacl, VOID, ulDaclLen); BAIL_ON_NT_STATUS(ntStatus); } if (ulSaclLen) { ntStatus = RTL_ALLOCATE(&pSacl, VOID, ulSaclLen); BAIL_ON_NT_STATUS(ntStatus); } ntStatus = RTL_ALLOCATE(&pAbsSecDesc, VOID, ulAbsSecDescLen); BAIL_ON_NT_STATUS(ntStatus); /* Translate the SD */ ntStatus = RtlSelfRelativeToAbsoluteSD( pRelSecDesc, pAbsSecDesc, &ulAbsSecDescLen, pDacl, &ulDaclLen, pSacl, &ulSaclLen, pOwner, &ulOwnerLen, pGroup, &ulGroupLen); BAIL_ON_NT_STATUS(ntStatus); *ppAbsSecDesc = pAbsSecDesc; cleanup: return ntStatus; error: LW_RTL_FREE(&pAbsSecDesc); LW_RTL_FREE(&pOwner); LW_RTL_FREE(&pGroup); LW_RTL_FREE(&pSacl); LW_RTL_FREE(&pDacl); goto cleanup; }
NTSTATUS RtlSelfRelativeAccessTokenToAccessToken( IN PACCESS_TOKEN_SELF_RELATIVE pRelative, IN ULONG ulRelativeSize, OUT PACCESS_TOKEN* ppToken ) { NTSTATUS status = STATUS_SUCCESS; ULONG ulOffset = 0; PBYTE pBuffer = (PBYTE) pRelative; PSID pSid = NULL; PSID_AND_ATTRIBUTES_SELF_RELATIVE pGroups = NULL; ULONG ulSize = 0; ULONG ulRealSize = 0; ULONG i = 0; TOKEN_USER User = {{0}}; TOKEN_OWNER Owner = {0}; TOKEN_PRIMARY_GROUP PrimaryGroup = {0}; TOKEN_UNIX Unix = {0}; PTOKEN_GROUPS pTokenGroups = NULL; PTOKEN_PRIVILEGES pTokenPrivileges = NULL; TOKEN_DEFAULT_DACL DefaultDacl = {0}; status = CheckOffset(0, sizeof(*pRelative), ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); if (pRelative->Flags & ACCESS_TOKEN_FLAG_UNIX_PRESENT) { Unix.Uid = pRelative->Uid; Unix.Gid = pRelative->Gid; Unix.Umask = pRelative->Umask; } User.User.Attributes = pRelative->User.Attributes; ulOffset = pRelative->User.SidOffset; pSid = (PSID) (pBuffer + ulOffset); status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); User.User.Sid = pSid; ulOffset = pRelative->GroupsOffset; if (ulOffset) { status = LwRtlSafeMultiplyULONG( &ulSize, sizeof(SID_AND_ATTRIBUTES_SELF_RELATIVE), pRelative->GroupCount); GOTO_CLEANUP_ON_STATUS(status); status = LwRtlSafeMultiplyULONG( &ulRealSize, sizeof(SID_AND_ATTRIBUTES), pRelative->GroupCount); GOTO_CLEANUP_ON_STATUS(status); status = LwRtlSafeAddULONG( &ulRealSize, ulRealSize, sizeof(TOKEN_GROUPS)); GOTO_CLEANUP_ON_STATUS(status); status = CheckOffset(ulOffset, ulSize, ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); pGroups = (PSID_AND_ATTRIBUTES_SELF_RELATIVE) (pBuffer + ulOffset); status = RTL_ALLOCATE(&pTokenGroups, TOKEN_GROUPS, ulRealSize); GOTO_CLEANUP_ON_STATUS(status); pTokenGroups->GroupCount = pRelative->GroupCount; for (i = 0; i < pRelative->GroupCount; i++) { pTokenGroups->Groups[i].Attributes = pGroups[i].Attributes; ulOffset = pGroups[i].SidOffset; pSid = (PSID) (pBuffer + ulOffset); status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); pTokenGroups->Groups[i].Sid = pSid; } } ulOffset = pRelative->PrivilegesOffset; if (ulOffset) { status = LwRtlSafeMultiplyULONG( &ulSize, sizeof(LUID_AND_ATTRIBUTES), pRelative->PrivilegeCount); GOTO_CLEANUP_ON_STATUS(status); status = LwRtlSafeMultiplyULONG( &ulRealSize, sizeof(LUID_AND_ATTRIBUTES), pRelative->PrivilegeCount); GOTO_CLEANUP_ON_STATUS(status); status = LwRtlSafeAddULONG( &ulRealSize, ulRealSize, sizeof(TOKEN_PRIVILEGES)); GOTO_CLEANUP_ON_STATUS(status); status = CheckOffset(ulOffset, ulSize, ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); status = RTL_ALLOCATE(&pTokenPrivileges, TOKEN_PRIVILEGES, ulRealSize); GOTO_CLEANUP_ON_STATUS(status); pTokenPrivileges->PrivilegeCount = pRelative->PrivilegeCount; memcpy(pTokenPrivileges->Privileges, pBuffer + ulOffset, sizeof(LUID_AND_ATTRIBUTES) * pTokenPrivileges->PrivilegeCount); } ulOffset = pRelative->OwnerOffset; if (ulOffset) { pSid = (PSID) (pBuffer + ulOffset); status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); Owner.Owner = pSid; } ulOffset = pRelative->PrimaryGroupOffset; if (ulOffset) { pSid = (PSID) (pBuffer + ulOffset); status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); PrimaryGroup.PrimaryGroup = pSid; } status = RtlCreateAccessToken( ppToken, &User, pTokenGroups, pTokenPrivileges, &Owner, &PrimaryGroup, &DefaultDacl, pRelative->Flags & ACCESS_TOKEN_FLAG_UNIX_PRESENT ? &Unix : NULL); GOTO_CLEANUP_ON_STATUS(status); cleanup: RTL_FREE(&pTokenGroups); if (!NT_SUCCESS(status)) { *ppToken = NULL; } return status; }
NTSTATUS LwIoFuseTranslateSecurityDescriptor( PSECURITY_DESCRIPTOR_RELATIVE pSecurityDescriptor, struct stat* pStatbuf ) { NTSTATUS status = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsolute = NULL; PACL pDacl = NULL; PACL pSacl = NULL; PSID pOwnerSid = NULL; PSID pGroupSid = NULL; ULONG ulOwnerSidSize = 0; ULONG ulGroupSidSize = 0; ULONG ulDaclSize = 0; ULONG ulSaclSize = 0; ULONG ulAbsSize = 0; /* Get required sizes */ RtlSelfRelativeToAbsoluteSD( pSecurityDescriptor, pAbsolute, &ulAbsSize, pDacl, &ulDaclSize, pSacl, &ulSaclSize, pOwnerSid, &ulOwnerSidSize, pGroupSid, &ulGroupSidSize); /* Allocate space */ status = RTL_ALLOCATE(&pAbsolute, struct _SECURITY_DESCRIPTOR_ABSOLUTE, ulAbsSize); BAIL_ON_NT_STATUS(status); if (ulDaclSize) { status = RTL_ALLOCATE(&pDacl, struct _ACL, ulDaclSize); BAIL_ON_NT_STATUS(status); } if (ulSaclSize) { status = RTL_ALLOCATE(&pSacl, struct _ACL, ulSaclSize); BAIL_ON_NT_STATUS(status); } if (ulOwnerSidSize) { status = RTL_ALLOCATE(&pOwnerSid, SID, ulOwnerSidSize); BAIL_ON_NT_STATUS(status); } if (ulGroupSidSize) { status = RTL_ALLOCATE(&pGroupSid, SID, ulGroupSidSize); BAIL_ON_NT_STATUS(status); } /* Unpack descriptor */ status = RtlSelfRelativeToAbsoluteSD( pSecurityDescriptor, pAbsolute, &ulAbsSize, pDacl, &ulDaclSize, pSacl, &ulSaclSize, pOwnerSid, &ulOwnerSidSize, pGroupSid, &ulGroupSidSize); BAIL_ON_NT_STATUS(status); status = LwIoFuseTranslateAbsoluteSecurityDescriptor( pAbsolute, pOwnerSid, pGroupSid, pStatbuf); BAIL_ON_NT_STATUS(status); error: RTL_FREE(&pAbsolute); RTL_FREE(&pDacl); RTL_FREE(&pSacl); RTL_FREE(&pOwnerSid); RTL_FREE(&pGroupSid); return status; }
static NTSTATUS SrvBuildDefaultShareSID( PSECURITY_DESCRIPTOR_RELATIVE* ppSecDesc ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_RELATIVE pRelSecDesc = NULL; ULONG ulRelSecDescLen = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsSecDesc = NULL; DWORD dwAceCount = 0; PSID pOwnerSid = NULL; PSID pGroupSid = NULL; PACL pDacl = NULL; DWORD dwSizeDacl = 0; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } localSystemSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } administratorsSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } builtinUsersSid; ULONG ulLocalSystemSidSize = sizeof(localSystemSid.buffer); ULONG ulAdministratorsSidSize = sizeof(administratorsSid.buffer); ULONG ulBuiltinUsersSidSize = sizeof(builtinUsersSid.buffer); ACCESS_MASK builtinUsersAccessMask = 0; ULONG ulAceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; /* Build the new Absolute Security Descriptor */ ntStatus = RTL_ALLOCATE( &pAbsSecDesc, VOID, SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateSecurityDescriptorAbsolute( pAbsSecDesc, SECURITY_DESCRIPTOR_REVISION); BAIL_ON_NT_STATUS(ntStatus); /* Create some SIDs */ ntStatus = RtlCreateWellKnownSid( WinLocalSystemSid, NULL, (PSID)localSystemSid.buffer, &ulLocalSystemSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, (PSID)administratorsSid.buffer, &ulAdministratorsSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinBuiltinUsersSid, NULL, (PSID)builtinUsersSid.buffer, &ulBuiltinUsersSidSize); BAIL_ON_NT_STATUS(ntStatus); /* Owner: Local System */ ntStatus = RtlDuplicateSid(&pOwnerSid, &localSystemSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetOwnerSecurityDescriptor( pAbsSecDesc, pOwnerSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Group: Administrators */ ntStatus = RtlDuplicateSid(&pGroupSid, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetGroupSecurityDescriptor( pAbsSecDesc, pGroupSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* DACL: Administrators - (Full Control) LocalSystem - (Full Control) Builtin Users - (Read && Execute && List Directory Contents) */ dwAceCount = 3; dwSizeDacl = ACL_HEADER_SIZE + dwAceCount * sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&localSystemSid.sid) + RtlLengthSid(&administratorsSid.sid) + RtlLengthSid(&builtinUsersSid.sid) - dwAceCount * sizeof(ULONG); ntStatus= RTL_ALLOCATE(&pDacl, VOID, dwSizeDacl); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateAcl(pDacl, dwSizeDacl, ACL_REVISION); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, ulAceFlags, FILE_ALL_ACCESS, &localSystemSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, ulAceFlags, FILE_ALL_ACCESS, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); builtinUsersAccessMask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE; ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, ulAceFlags, builtinUsersAccessMask, &builtinUsersSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetDaclSecurityDescriptor( pAbsSecDesc, TRUE, pDacl, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Create the SelfRelative SD */ ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, NULL, &ulRelSecDescLen); if (ntStatus == STATUS_BUFFER_TOO_SMALL) { ntStatus = SrvAllocateMemory(ulRelSecDescLen, (PVOID*)&pRelSecDesc); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, pRelSecDesc, &ulRelSecDescLen); } BAIL_ON_NT_STATUS(ntStatus); *ppSecDesc = pRelSecDesc; cleanup: RTL_FREE(&pAbsSecDesc); RTL_FREE(&pOwnerSid); RTL_FREE(&pGroupSid); RTL_FREE(&pDacl); return ntStatus; error: *ppSecDesc = NULL; if (pRelSecDesc) { SrvFreeMemory(pRelSecDesc); } goto cleanup; }
LW_NTSTATUS LwIoSetPathCreds( IN LW_PUNICODE_STRING PathPrefix, IN OPTIONAL LW_PIO_CREDS pCreds ) { LW_NTSTATUS Status = STATUS_SUCCESS; PIO_PATH_CREDS pPathCreds = NULL; PIO_CREDS pCredCopy = NULL; BOOL bInLock = FALSE; LWIO_LOCK_MUTEX(bInLock, &gLock); Status = LwIoFindPathCreds(PathPrefix, TRUE, &pPathCreds); BAIL_ON_NT_STATUS(Status); if (pPathCreds) { Status = LwIoCopyCreds(pCreds, &pCredCopy); BAIL_ON_NT_STATUS(Status); if (pPathCreds->pCreds) { LwIoDeleteCreds(pPathCreds->pCreds); } pPathCreds->pCreds = pCredCopy; pCredCopy = NULL; pPathCreds = NULL; } else if (pCreds) { Status = RTL_ALLOCATE(&pPathCreds, IO_PATH_CREDS, sizeof(IO_PATH_CREDS)); BAIL_ON_NT_STATUS(Status); LwListInit(&pPathCreds->link); Status = LwIoNormalizePath(PathPrefix, &pPathCreds->PathPrefix); BAIL_ON_NT_STATUS(Status); Status = LwIoCopyCreds(pCreds, &pPathCreds->pCreds); BAIL_ON_NT_STATUS(Status); LwListInsertBefore(&gPathCreds, &pPathCreds->link); pPathCreds = NULL; } cleanup: LWIO_UNLOCK_MUTEX(bInLock, &gLock); if (pCredCopy) { LwIoDeleteCreds(pCredCopy); } if (pPathCreds) { LwIoDeletePathCreds(pPathCreds); } return Status; error: goto cleanup; }
LW_NTSTATUS LwIoRdrGetPhysicalPath( IO_FILE_HANDLE File, LW_PWSTR* ppResolved ) { NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK ioStatus; ULONG length = RESOLVED_PATH_LENGTH; PBYTE pBuffer = NULL; PBYTE pNewBuffer = NULL; PWSTR pResolved = NULL; status = RTL_ALLOCATE(&pBuffer, BYTE, length); GOTO_CLEANUP_ON_STATUS(status); do { status = LwNtDeviceIoControlFile( File, NULL, &ioStatus, RDR_DEVCTL_GET_PHYSICAL_PATH, NULL, 0, pBuffer, length); if (status == STATUS_BUFFER_TOO_SMALL) { length *= 2; pNewBuffer = LwRtlMemoryRealloc(pBuffer, length); if (!pNewBuffer) { status = STATUS_INSUFFICIENT_RESOURCES; GOTO_CLEANUP_ON_STATUS(status); } pBuffer = pNewBuffer; } } while (status == STATUS_BUFFER_TOO_SMALL); GOTO_CLEANUP_ON_STATUS(status); if (ioStatus.BytesTransferred > 0) { status = LW_RTL_ALLOCATE( &pResolved, WCHAR, ioStatus.BytesTransferred + sizeof(WCHAR)); GOTO_CLEANUP_ON_STATUS(status); #ifdef WORDS_BIGENDIAN swab(pBuffer, pResolved, ioStatus.BytesTransferred); #else memcpy(pResolved, pBuffer, ioStatus.BytesTransferred); #endif } cleanup: *ppResolved = pResolved; RTL_FREE(&pBuffer); return status; }