NTSTATUS SrvShareDbBeginEnum( HANDLE hRepository, ULONG ulLimit, PHANDLE phResume ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_SHARE_DB_ENUM_CONTEXT pEnumContext = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_SHARE_DB_ENUM_CONTEXT), (PVOID*)&pEnumContext); BAIL_ON_NT_STATUS(ntStatus); pEnumContext->ulOffset = 0; pEnumContext->ulLimit = ulLimit; *phResume = (HANDLE)pEnumContext; cleanup: return ntStatus; error: *phResume = NULL; SRV_SAFE_FREE_MEMORY(pEnumContext); goto cleanup; }
NTSTATUS SrvMatchPathPrefix( PWSTR pwszPath, ULONG ulPathLength, PWSTR pwszPrefix ) { NTSTATUS ntStatus = STATUS_NO_MATCH; ULONG ulPrefixLength = wc16slen(pwszPrefix); PWSTR pwszTmp = NULL; if (ulPathLength >= ulPrefixLength) { ntStatus = SrvAllocateMemory( (ulPrefixLength + 1) * sizeof(wchar16_t), (PVOID*)&pwszTmp); BAIL_ON_NT_STATUS(ntStatus); memcpy( (PBYTE)pwszTmp, (PBYTE)pwszPath, ulPrefixLength * sizeof(wchar16_t)); if (!SMBWc16sCaseCmp(pwszTmp, pwszPrefix)) { ntStatus = STATUS_SUCCESS; } } error: SRV_SAFE_FREE_MEMORY(pwszTmp); return ntStatus; }
NTSTATUS SrvSessionCreate( USHORT uid, PLWIO_SRV_SESSION* ppSession ) { NTSTATUS ntStatus = 0; PLWIO_SRV_SESSION pSession = NULL; LWIO_LOG_DEBUG("Creating session [uid:%u]", uid); ntStatus = SrvAllocateMemory( sizeof(LWIO_SRV_SESSION), (PVOID*)&pSession); BAIL_ON_NT_STATUS(ntStatus); pSession->refcount = 1; pthread_rwlock_init(&pSession->mutex, NULL); pSession->pMutex = &pSession->mutex; pSession->uid = uid; ntStatus = WireGetCurrentNTTime(&pSession->llBirthTime); BAIL_ON_NT_STATUS(ntStatus); pSession->llLastActivityTime = pSession->llBirthTime; LWIO_LOG_DEBUG("Associating session [object:0x%x][uid:%u]", pSession, uid); ntStatus = LwRtlRBTreeCreate( &SrvSessionTreeCompare, NULL, &SrvSessionTreeRelease, &pSession->pTreeCollection); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvFinderCreateRepository( &pSession->hFinderRepository); BAIL_ON_NT_STATUS(ntStatus); SRV_ELEMENTS_INCREMENT_SESSIONS; *ppSession = pSession; cleanup: return ntStatus; error: *ppSession = NULL; if (pSession) { SrvSessionRelease(pSession); } goto cleanup; }
static NTSTATUS SrvBuildRenameState( PSMB_RENAME_REQUEST_HEADER pRequestHeader, PWSTR pwszOldName, PWSTR pwszNewName, PSRV_RENAME_STATE_SMB_V1* ppRenameState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_RENAME_STATE_SMB_V1 pRenameState = NULL; if (!pwszOldName || !*pwszOldName || !pwszNewName || !*pwszNewName) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvAllocateMemory( sizeof(SRV_RENAME_STATE_SMB_V1), (PVOID*)&pRenameState); BAIL_ON_NT_STATUS(ntStatus); pRenameState->refCount = 1; pthread_mutex_init(&pRenameState->mutex, NULL); pRenameState->pMutex = &pRenameState->mutex; pRenameState->stage = SRV_RENAME_STAGE_SMB_V1_INITIAL; pRenameState->pRequestHeader = pRequestHeader; pRenameState->pwszOldName = pwszOldName; pRenameState->pwszNewName = pwszNewName; *ppRenameState = pRenameState; cleanup: return ntStatus; error: *ppRenameState = NULL; if (pRenameState) { SrvFreeRenameState(pRenameState); } goto cleanup; }
static NTSTATUS SrvBuildGetInfoState_SMB_V2( PSMB2_GET_INFO_REQUEST_HEADER pRequestHeader, PLWIO_SRV_FILE_2 pFile, PBYTE pInputBuffer, ULONG ulInputBufferLength, PSRV_GET_INFO_STATE_SMB_V2* ppGetInfoState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_GET_INFO_STATE_SMB_V2 pGetInfoState = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_GET_INFO_STATE_SMB_V2), (PVOID*)&pGetInfoState); BAIL_ON_NT_STATUS(ntStatus); pGetInfoState->refCount = 1; pthread_mutex_init(&pGetInfoState->mutex, NULL); pGetInfoState->pMutex = &pGetInfoState->mutex; pGetInfoState->stage = SRV_GET_INFO_STAGE_SMB_V2_INITIAL; pGetInfoState->pRequestHeader = pRequestHeader; pGetInfoState->pFile = SrvFile2Acquire(pFile); pGetInfoState->pInputBuffer = pInputBuffer; pGetInfoState->ulInputBufferLength = ulInputBufferLength; *ppGetInfoState = pGetInfoState; cleanup: return ntStatus; error: *ppGetInfoState = NULL; if (pGetInfoState) { SrvFreeGetInfoState_SMB_V2(pGetInfoState); } goto cleanup; }
static NTSTATUS SrvBuildDeleteState( PSMB_DELETE_REQUEST_HEADER pRequestHeader, PWSTR pwszSearchPattern, BOOLEAN bUseLongFilenames, PSRV_DELETE_STATE_SMB_V1* ppDeleteState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_DELETE_STATE_SMB_V1 pDeleteState = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_DELETE_STATE_SMB_V1), (PVOID*)&pDeleteState); BAIL_ON_NT_STATUS(ntStatus); pDeleteState->refCount = 1; pthread_mutex_init(&pDeleteState->mutex, NULL); pDeleteState->pMutex = &pDeleteState->mutex; pDeleteState->stage = SRV_DELETE_STAGE_SMB_V1_INITIAL; pDeleteState->pRequestHeader = pRequestHeader; pDeleteState->pwszSearchPattern = pwszSearchPattern; pDeleteState->bUseLongFilenames = bUseLongFilenames; pDeleteState->usSearchAttributes = pRequestHeader->usSearchAttributes; *ppDeleteState = pDeleteState; cleanup: return ntStatus; error: *ppDeleteState = NULL; if (pDeleteState) { SrvFreeDeleteState(pDeleteState); } goto cleanup; }
NTSTATUS SrvSocketStringToAddressA( PCSTR pszAddress, struct sockaddr** ppSocketAddress, SOCKLEN_TYPE* pAddressLength ) { NTSTATUS ntStatus = STATUS_SUCCESS; struct addrinfo* pAddrInfo = NULL; struct sockaddr* pSocketAddress = NULL; ntStatus = SrvSocketGetAddrInfoA(pszAddress, &pAddrInfo); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvAllocateMemory( pAddrInfo->ai_addrlen, OUT_PPVOID(&pSocketAddress)); BAIL_ON_NT_STATUS(ntStatus); memcpy(pSocketAddress, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen); *ppSocketAddress = pSocketAddress; *pAddressLength = pAddrInfo->ai_addrlen; cleanup: if (pAddrInfo) { freeaddrinfo(pAddrInfo); } return ntStatus; error: if (pSocketAddress) { SrvFreeMemory(pSocketAddress); } *ppSocketAddress = NULL; *pAddressLength = 0; goto cleanup; }
static NTSTATUS SrvBuildFlushState_SMB_V2( PSMB2_FID pFid, PLWIO_SRV_FILE_2 pFile, PSRV_FLUSH_STATE_SMB_V2* ppFlushState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_FLUSH_STATE_SMB_V2 pFlushState = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_FLUSH_STATE_SMB_V2), (PVOID*)&pFlushState); BAIL_ON_NT_STATUS(ntStatus); pFlushState->refCount = 1; pthread_mutex_init(&pFlushState->mutex, NULL); pFlushState->pMutex = &pFlushState->mutex; pFlushState->stage = SRV_FLUSH_STAGE_SMB_V2_INITIAL; pFlushState->pFid = pFid; pFlushState->pFile = SrvFile2Acquire(pFile); *ppFlushState = pFlushState; cleanup: return ntStatus; error: *ppFlushState = NULL; if (pFlushState) { SrvFreeFlushState_SMB_V2(pFlushState); } goto cleanup; }
static NTSTATUS SrvBuildCheckdirState( PSMB_CHECK_DIRECTORY_REQUEST_HEADER pRequestHeader, PWSTR pwszPathFragment, PSRV_CHECKDIR_STATE_SMB_V1* ppCheckdirState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_CHECKDIR_STATE_SMB_V1 pCheckdirState = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_CHECKDIR_STATE_SMB_V1), (PVOID*)&pCheckdirState); BAIL_ON_NT_STATUS(ntStatus); pCheckdirState->refCount = 1; pthread_mutex_init(&pCheckdirState->mutex, NULL); pCheckdirState->pMutex = &pCheckdirState->mutex; pCheckdirState->stage = SRV_CHECKDIR_STAGE_SMB_V1_INITIAL; pCheckdirState->pwszPathFragment = pwszPathFragment; pCheckdirState->pRequestHeader = pRequestHeader; *ppCheckdirState = pCheckdirState; cleanup: return ntStatus; error: *ppCheckdirState = NULL; if (pCheckdirState) { SrvFreeCheckdirState(pCheckdirState); } goto cleanup; }
NTSTATUS SrvFinderCreateRepository( OUT PHANDLE phFinderRepository ) { NTSTATUS ntStatus = 0; PSRV_FINDER_REPOSITORY pFinderRepository = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_FINDER_REPOSITORY), (PVOID*)&pFinderRepository); BAIL_ON_NT_STATUS(ntStatus); pFinderRepository->refCount = 1; pthread_mutex_init(&pFinderRepository->mutex, NULL); pFinderRepository->pMutex = &pFinderRepository->mutex; ntStatus = LwRtlRBTreeCreate( &SrvFinderCompareSearchSpaces, NULL, &SrvFinderFreeData, &pFinderRepository->pSearchSpaceCollection); BAIL_ON_NT_STATUS(ntStatus); *phFinderRepository = pFinderRepository; cleanup: return ntStatus; error: *phFinderRepository = NULL; if (pFinderRepository) { SrvFinderFreeRepository(pFinderRepository); } goto cleanup; }
NTSTATUS SrvAsyncStateCreate( ULONG64 ullAsyncId, USHORT usCommand, HANDLE hAsyncState, PFN_LWIO_SRV_CANCEL_ASYNC_STATE pfnCancelAsyncState, PFN_LWIO_SRV_FREE_ASYNC_STATE pfnFreeAsyncState, PLWIO_ASYNC_STATE* ppAsyncState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PLWIO_ASYNC_STATE pAsyncState = NULL; ntStatus = SrvAllocateMemory( sizeof(LWIO_ASYNC_STATE), (PVOID*)&pAsyncState); BAIL_ON_NT_STATUS(ntStatus); pAsyncState->refcount = 1; pthread_rwlock_init(&pAsyncState->mutex, NULL); pAsyncState->pMutex = &pAsyncState->mutex; pAsyncState->ullAsyncId = ullAsyncId; pAsyncState->usCommand = usCommand; pAsyncState->hAsyncState = hAsyncState; pAsyncState->pfnFreeAsyncState = pfnFreeAsyncState; pAsyncState->pfnCancelAsyncState = pfnCancelAsyncState; *ppAsyncState = pAsyncState; cleanup: return ntStatus; error: *ppAsyncState = NULL; goto cleanup; }
static NTSTATUS SrvBuildNotifyRequestState_SMB_V2( PSMB2_NOTIFY_CHANGE_HEADER pRequestHeader, PSRV_NOTIFY_REQUEST_STATE_SMB_V2* ppNotifyRequestState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_NOTIFY_REQUEST_STATE_SMB_V2 pNotifyRequestState = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_NOTIFY_REQUEST_STATE_SMB_V2), (PVOID*)&pNotifyRequestState); BAIL_ON_NT_STATUS(ntStatus); pNotifyRequestState->refCount = 1; pthread_mutex_init(&pNotifyRequestState->mutex, NULL); pNotifyRequestState->pMutex = &pNotifyRequestState->mutex; pNotifyRequestState->stage = SRV_NOTIFY_STAGE_SMB_V2_INITIAL; pNotifyRequestState->pRequestHeader = pRequestHeader; *ppNotifyRequestState = pNotifyRequestState; cleanup: return ntStatus; error: *ppNotifyRequestState = NULL; if (pNotifyRequestState) { SrvFreeNotifyRequestState_SMB_V2(pNotifyRequestState); } goto cleanup; }
NTSTATUS SrvBuildEmptyExecContext( OUT PSRV_EXEC_CONTEXT* ppContext ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pContext = NULL; ntStatus = SrvAllocateMemory(sizeof(SRV_EXEC_CONTEXT), (PVOID*)&pContext); BAIL_ON_NT_STATUS(ntStatus); pthread_mutex_init(&pContext->execMutex, NULL); pContext->pExecMutex = &pContext->execMutex; ntStatus = SrvLogContextCreate(&pContext->pLogContext); BAIL_ON_NT_STATUS(ntStatus); pContext->refCount = 1; pContext->bInternal = TRUE; *ppContext = pContext; cleanup: return ntStatus; error: *ppContext = NULL; if (pContext) { SrvReleaseExecContext(pContext); } goto cleanup; }
static NTSTATUS SrvShareRegWriteToShareInfo( IN REG_DATA_TYPE regDataType, IN PWSTR pwszShareName, IN PBYTE pData, IN ULONG ulDataLen, IN REG_DATA_TYPE regSecDataType, IN PBYTE pSecData, IN ULONG ulSecDataLen, OUT PSRV_SHARE_INFO* ppShareInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_SHARE_INFO pShareInfo = NULL; PWSTR* ppwszValues = NULL; PSTR pszFlags = NULL; ntStatus = SrvAllocateMemory(sizeof(*pShareInfo), (PVOID*)&pShareInfo); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->refcount = 1; pthread_rwlock_init(&pShareInfo->mutex, NULL); pShareInfo->pMutex = &pShareInfo->mutex; ntStatus = SrvAllocateStringW(pwszShareName, &pShareInfo->pwszName); BAIL_ON_NT_STATUS(ntStatus); if (pData) { ULONG iValue = 0; wchar16_t wszCommentPrefix[] = REG_KEY_COMMENT_PREFIX_W; ULONG ulCommentPrefixLen = (sizeof(wszCommentPrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszPathPrefix[] = REG_KEY_PATH_PREFIX_W; ULONG ulPathPrefixLen = (sizeof(wszPathPrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszServicePrefix[] = REG_KEY_SERVICE_PREFIX_W; ULONG ulServicePrefixLen = (sizeof(wszServicePrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszFlagsPrefix[] = REG_KEY_FLAGS_PREFIX_W; ULONG ulFlagsPrefixLen = (sizeof(wszFlagsPrefix)/sizeof(wchar16_t)) - 1; ntStatus = NtRegByteArrayToMultiStrs(pData, ulDataLen, &ppwszValues); BAIL_ON_NT_STATUS(ntStatus); for (; ppwszValues[iValue]; iValue++) { PWSTR pwszValue = &ppwszValues[iValue][0]; if (!wc16sncmp(&wszPathPrefix[0], pwszValue, ulPathPrefixLen)) { SRV_SAFE_FREE_MEMORY(pShareInfo->pwszPath); ntStatus = SrvAllocateStringW( &pwszValue[ulPathPrefixLen], &pShareInfo->pwszPath); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszCommentPrefix[0], pwszValue, ulCommentPrefixLen)) { SRV_SAFE_FREE_MEMORY(pShareInfo->pwszComment); ntStatus = SrvAllocateStringW( &pwszValue[ulCommentPrefixLen], &pShareInfo->pwszComment); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszServicePrefix[0], pwszValue, ulServicePrefixLen)) { ntStatus = SrvShareMapServiceStringToIdW( &pwszValue[ulServicePrefixLen], &pShareInfo->service); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszFlagsPrefix[0], pwszValue, ulFlagsPrefixLen)) { ntStatus = RtlCStringAllocateFromWC16String( &pszFlags, &pwszValue[ulFlagsPrefixLen]); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->ulFlags = strtol(pszFlags, NULL, 16); } else { ntStatus = STATUS_INVALID_PARAMETER_3; BAIL_ON_NT_STATUS(ntStatus); } } } if (!pShareInfo->pwszComment) { wchar16_t wszComment[] = {0}; ntStatus = SrvAllocateStringW( &wszComment[0], &pShareInfo->pwszComment); BAIL_ON_NT_STATUS(ntStatus); } if (ulSecDataLen) { ntStatus = SrvShareSetSecurity( pShareInfo, (PSECURITY_DESCRIPTOR_RELATIVE)pSecData, ulSecDataLen); BAIL_ON_NT_STATUS(ntStatus); } else { ntStatus = SrvShareSetDefaultSecurity(pShareInfo); BAIL_ON_NT_STATUS(ntStatus); } *ppShareInfo = pShareInfo; cleanup: if (ppwszValues) { RegFreeMultiStrsW(ppwszValues); } RTL_FREE(&pszFlags); return ntStatus; error: if (pShareInfo) { SrvShareReleaseInfo(pShareInfo); } goto cleanup; }
NTSTATUS SrvShareRegEnum( HANDLE hRepository, HANDLE hResume, PSRV_SHARE_INFO** pppShareInfoList, PULONG pulNumSharesFound ) { NTSTATUS ntStatus = 0; ULONG ulIndex = 0; ULONG ulBatchIndex = 0; HKEY hRootKey = NULL; HKEY hKey = NULL; HKEY hSecKey = NULL; PWSTR pwszValueName = NULL; PBYTE pData = NULL; REG_DATA_TYPE dataType = REG_UNKNOWN; wchar16_t wszHKTM[] = HKEY_THIS_MACHINE_W; wchar16_t wszSharesKey[] = REG_KEY_PATH_SRV_SHARES_W; wchar16_t wszShareSecKey[] = REG_KEY_PATH_SRV_SHARES_SECURITY_W; PSRV_SHARE_INFO* ppShareInfoList = NULL; REG_DATA_TYPE dataSecType = REG_UNKNOWN; ULONG ulNumSharesFound = 0; BYTE pSecData[MAX_VALUE_LENGTH] = {0}; PSRV_SHARE_REG_ENUM_CONTEXT pResume = (PSRV_SHARE_REG_ENUM_CONTEXT)hResume; if (!pResume) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NtRegOpenKeyExW( hRepository, NULL, &wszHKTM[0], 0, KEY_READ, &hRootKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszSharesKey[0], 0, KEY_READ, &hKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszShareSecKey[0], 0, KEY_READ, &hSecKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvAllocateMemory( pResume->ulBatchLimit * sizeof(*ppShareInfoList), (PVOID) &ppShareInfoList); BAIL_ON_NT_STATUS(ntStatus); ulBatchIndex = pResume->ulBatchIndex; for (ulIndex = 0; ulIndex < pResume->ulBatchLimit; ulIndex++) { ULONG ulMaxValueNameLen = 0; ULONG ulMaxValueLen = 0; ULONG ulMaxSecValueLen = 0; ulMaxValueNameLen = (pResume->ulMaxValueNameLen + 1) * sizeof(*pwszValueName); ulMaxValueLen = pResume->ulMaxValueLen; ulMaxSecValueLen = MAX_VALUE_LENGTH; if (ulMaxValueNameLen) { SRV_SAFE_FREE_MEMORY_AND_RESET(pwszValueName); ntStatus = SrvAllocateMemory( ulMaxValueNameLen, (PVOID*) &pwszValueName); BAIL_ON_NT_STATUS(ntStatus); } if (ulMaxValueLen) { SRV_SAFE_FREE_MEMORY_AND_RESET(pData); ntStatus = SrvAllocateMemory(ulMaxValueLen, (PVOID*) &pData); BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NtRegEnumValueW( hRepository, hKey, ulBatchIndex++, pwszValueName, &ulMaxValueNameLen, NULL, &dataType, pData, &ulMaxValueLen); if (ntStatus == STATUS_NO_MORE_MATCHES || ntStatus == STATUS_NO_MORE_ENTRIES) { ntStatus = STATUS_SUCCESS; break; } BAIL_ON_NT_STATUS(ntStatus); if (REG_MULTI_SZ != dataType) { continue; } ntStatus = NtRegGetValueW( hRepository, hSecKey, NULL, pwszValueName, RRF_RT_REG_BINARY, &dataSecType, pSecData, &ulMaxSecValueLen); if (STATUS_OBJECT_NAME_NOT_FOUND == ntStatus) { ntStatus = 0; ulMaxSecValueLen = 0; } BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareRegWriteToShareInfo( dataType, pwszValueName, pData, ulMaxValueLen, dataSecType, pSecData, ulMaxSecValueLen, &ppShareInfoList[ulNumSharesFound++]); BAIL_ON_NT_STATUS(ntStatus); } pResume->ulBatchIndex = ulBatchIndex; *pppShareInfoList = ppShareInfoList; *pulNumSharesFound = ulNumSharesFound; cleanup: if (hRootKey) { NtRegCloseKey(hRepository, hRootKey); } if (hKey) { NtRegCloseKey(hRepository, hKey); } if (hSecKey) { NtRegCloseKey(hRepository, hSecKey); } SRV_SAFE_FREE_MEMORY(pwszValueName); SRV_SAFE_FREE_MEMORY(pData); return ntStatus; error: *pppShareInfoList = NULL; *pulNumSharesFound = 0; if (ppShareInfoList) { SrvShareFreeInfoList(ppShareInfoList, ulNumSharesFound); } goto cleanup; }
NTSTATUS SrvShareRegBeginEnum( HANDLE hRepository, ULONG ulBatchLimit, PHANDLE phResume ) { NTSTATUS ntStatus = 0; HKEY hRootKey = NULL; HKEY hKey = NULL; wchar16_t wszHKTM[] = HKEY_THIS_MACHINE_W; wchar16_t wszSharesKey[] = REG_KEY_PATH_SRV_SHARES_W; PSRV_SHARE_REG_ENUM_CONTEXT pEnumContext = NULL; if (!ulBatchLimit || (ulBatchLimit == UINT32_MAX)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvAllocateMemory( sizeof(SRV_SHARE_REG_ENUM_CONTEXT), (PVOID*)&pEnumContext); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, NULL, &wszHKTM[0], 0, KEY_READ, &hRootKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszSharesKey[0], 0, KEY_READ, &hKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegQueryInfoKeyW( hRepository, hKey, NULL, NULL, NULL, NULL, NULL, NULL, &pEnumContext->ulValuesAvailable, &pEnumContext->ulMaxValueNameLen, &pEnumContext->ulMaxValueLen, NULL, NULL); BAIL_ON_NT_STATUS(ntStatus); pEnumContext->ulBatchLimit = ulBatchLimit; *phResume = (HANDLE)pEnumContext; cleanup: if (hRootKey) { NtRegCloseKey(hRepository, hRootKey); } if (hKey) { NtRegCloseKey(hRepository, hKey); } return ntStatus; error: *phResume = NULL; SRV_SAFE_FREE_MEMORY(pEnumContext); goto cleanup; }
NTSTATUS SrvShareRegAdd( IN HANDLE hRepository, IN PWSTR pwszShareName, IN PWSTR pwszPath, IN PWSTR pwszComment, IN PBYTE pSecDesc, IN ULONG ulSecDescLen, IN PWSTR pwszService, IN ULONG ulFlags ) { NTSTATUS ntStatus = 0; HKEY hRootKey = NULL; HKEY hKey = NULL; HKEY hSecKey = NULL; PWSTR* ppwszValues = NULL; PBYTE pOutData = NULL; SSIZE_T cOutDataLen = 0; PWSTR pwszFlags = NULL; ULONG ulCount = 0; wchar16_t wszHKTM[] = HKEY_THIS_MACHINE_W; wchar16_t wszSharesKey[] = REG_KEY_PATH_SRV_SHARES_W; wchar16_t wszShareSecKey[] = REG_KEY_PATH_SRV_SHARES_SECURITY_W; wchar16_t wszPathPrefix[] = REG_KEY_PATH_PREFIX_W; wchar16_t wszFlagsPrefix[] = REG_KEY_FLAGS_PREFIX_W; ULONG ulPathPrefixLen = (sizeof(wszPathPrefix)/sizeof(wchar16_t)) - 1; ULONG ulFlagsPrefixLen = (sizeof(wszFlagsPrefix)/sizeof(wchar16_t)) - 1; if (IsNullOrEmptyString(pwszShareName)) { ntStatus = STATUS_INVALID_PARAMETER_2; BAIL_ON_NT_STATUS(ntStatus); } if (IsNullOrEmptyString(pwszPath)) { ntStatus = STATUS_INVALID_PARAMETER_3; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NtRegOpenKeyExW( hRepository, NULL, &wszHKTM[0], 0, KEY_ALL_ACCESS, &hRootKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszSharesKey[0], 0, KEY_ALL_ACCESS, &hKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvAllocateMemory(sizeof(PWSTR) * 5, (PVOID*)&ppwszValues); BAIL_ON_NT_STATUS(ntStatus); // Path ntStatus = SrvAllocateMemory( sizeof(wszPathPrefix) + wc16slen(pwszPath) * sizeof(wchar16_t), (PVOID*)&ppwszValues[ulCount]); BAIL_ON_NT_STATUS(ntStatus); memcpy( (PBYTE)&ppwszValues[ulCount][0], (PBYTE)&wszPathPrefix[0], sizeof(wszPathPrefix) - sizeof(wchar16_t)); memcpy( (PBYTE)&ppwszValues[ulCount][ulPathPrefixLen], (PBYTE)pwszPath, wc16slen(pwszPath) * sizeof(wchar16_t)); if (!IsNullOrEmptyString(pwszComment)) { wchar16_t wszCommentPrefix[] = REG_KEY_COMMENT_PREFIX_W; ULONG ulCommentPrefixLen = (sizeof(wszCommentPrefix)/sizeof(wchar16_t)) - 1; ntStatus = SrvAllocateMemory( sizeof(wszCommentPrefix) + wc16slen(pwszComment) * sizeof(wchar16_t), (PVOID*)&ppwszValues[++ulCount]); BAIL_ON_NT_STATUS(ntStatus); memcpy( (PBYTE)&ppwszValues[ulCount][0], (PBYTE)&wszCommentPrefix[0], sizeof(wszCommentPrefix) - sizeof(wchar16_t)); memcpy( (PBYTE)&ppwszValues[ulCount][ulCommentPrefixLen], (PBYTE)pwszComment, wc16slen(pwszComment) * sizeof(wchar16_t)); } if (!IsNullOrEmptyString(pwszService)) { wchar16_t wszServicePrefix[] = REG_KEY_SERVICE_PREFIX_W; ULONG ulServicePrefixLen = (sizeof(wszServicePrefix)/sizeof(wchar16_t)) - 1; ntStatus = SrvAllocateMemory( sizeof(wszServicePrefix) + wc16slen(pwszService) * sizeof(wchar16_t), (PVOID*)&ppwszValues[++ulCount]); BAIL_ON_NT_STATUS(ntStatus); memcpy( (PBYTE)&ppwszValues[ulCount][0], (PBYTE)&wszServicePrefix[0], sizeof(wszServicePrefix) - sizeof(wchar16_t)); memcpy( (PBYTE)&ppwszValues[ulCount][ulServicePrefixLen], (PBYTE)pwszService, wc16slen(pwszService) * sizeof(wchar16_t)); } // Flags ntStatus = LwRtlWC16StringAllocatePrintfW(&pwszFlags, L"0x%08x", ulFlags); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvAllocateMemory( sizeof(wszFlagsPrefix) + wc16slen(pwszFlags) * sizeof(wchar16_t), OUT_PPVOID(&ppwszValues[++ulCount])); BAIL_ON_NT_STATUS(ntStatus); memcpy((PBYTE)&ppwszValues[ulCount][0], (PBYTE)&wszFlagsPrefix[0], sizeof(wszFlagsPrefix) - sizeof(wchar16_t)); memcpy((PBYTE)&ppwszValues[ulCount][ulFlagsPrefixLen], (PBYTE)pwszFlags, wc16slen(pwszFlags) * sizeof(wchar16_t)); ntStatus = NtRegMultiStrsToByteArrayW(ppwszValues, &pOutData, &cOutDataLen); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegSetValueExW( hRepository, hKey, pwszShareName, 0, REG_MULTI_SZ, pOutData, cOutDataLen); BAIL_ON_NT_STATUS(ntStatus); if ((pSecDesc && !ulSecDescLen) || (!pSecDesc && ulSecDescLen)) { ntStatus = STATUS_INVALID_PARAMETER_5; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszShareSecKey[0], 0, KEY_ALL_ACCESS, &hSecKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegSetValueExW( hRepository, hSecKey, pwszShareName, 0, REG_BINARY, pSecDesc, ulSecDescLen); BAIL_ON_NT_STATUS(ntStatus); cleanup: if (hRootKey) { NtRegCloseKey(hRepository, hRootKey); } if (hKey) { NtRegCloseKey(hRepository, hKey); } if (hSecKey) { NtRegCloseKey(hRepository, hSecKey); } if (ppwszValues) { SrvShareFreeStringArray(ppwszValues, 4); } if (pOutData) { RegFreeMemory(pOutData); } RTL_FREE(&pwszFlags); return ntStatus; error: goto cleanup; }
static NTSTATUS SrvBuildOpenState( PSRV_EXEC_CONTEXT pExecContext, POPEN_REQUEST_HEADER pRequestHeader, PWSTR pwszFilename, PSRV_OPEN_STATE_SMB_V1* ppOpenState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PLWIO_SRV_CONNECTION pConnection = pExecContext->pConnection; PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext; PSRV_EXEC_CONTEXT_SMB_V1 pCtxSmb1 = pCtxProtocol->pSmb1Context; PSRV_OPEN_STATE_SMB_V1 pOpenState = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_OPEN_STATE_SMB_V1), (PVOID*)&pOpenState); BAIL_ON_NT_STATUS(ntStatus); pOpenState->refCount = 1; pthread_mutex_init(&pOpenState->mutex, NULL); pOpenState->pMutex = &pOpenState->mutex; pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_INITIAL; // TODO: Handle root fids ntStatus = SrvAllocateMemory( sizeof(IO_FILE_NAME), (PVOID*)&pOpenState->pFilename); BAIL_ON_NT_STATUS(ntStatus); pOpenState->pTree = SrvTreeAcquire(pCtxSmb1->pTree); ntStatus = SrvBuildTreeRelativePath( pCtxSmb1->pTree, pwszFilename, pOpenState->pFilename); BAIL_ON_NT_STATUS(ntStatus); pOpenState->pwszFilename = pwszFilename; ntStatus = IoRtlEcpListAllocate(&pOpenState->pEcpList); BAIL_ON_NT_STATUS(ntStatus); ntStatus = IoRtlEcpListInsert(pOpenState->pEcpList, SRV_ECP_TYPE_NET_OPEN_INFO, &pOpenState->networkOpenInfo, sizeof(pOpenState->networkOpenInfo), NULL); BAIL_ON_NT_STATUS(ntStatus); /* For named pipes, we need to pipe some extra data into the npfs driver: * - Session key * - Client principal name * - Client address */ if (SrvTreeIsNamedPipe(pCtxSmb1->pTree)) { ntStatus = SrvConnectionGetNamedPipeSessionKey( pConnection, pOpenState->pEcpList); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvConnectionGetNamedPipeClientAddress( pConnection, pOpenState->pEcpList); BAIL_ON_NT_STATUS(ntStatus); ntStatus = IoRtlEcpListInsert(pOpenState->pEcpList, SRV_ECP_TYPE_PIPE_INFO, &pOpenState->filePipeInfo, sizeof(pOpenState->filePipeInfo), NULL); BAIL_ON_NT_STATUS(ntStatus); ntStatus = IoRtlEcpListInsert(pOpenState->pEcpList, SRV_ECP_TYPE_PIPE_LOCAL_INFO, &pOpenState->filePipeLocalInfo, sizeof(pOpenState->filePipeLocalInfo), NULL); BAIL_ON_NT_STATUS(ntStatus); } pOpenState->usCreateOptions = FILE_NON_DIRECTORY_FILE; pOpenState->usShareAccess = (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); switch (pRequestHeader->usDesiredAccess & 0x70) { case 0x00: /* compatibility mode */ ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); break; case 0x10: /* deny read/write/execute (exclusive) */ pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_READ; pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_WRITE; break; case 0x20: /* deny write */ pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_WRITE; break; case 0x30: /* deny read/execute */ pOpenState->usShareAccess &= (USHORT)~FILE_SHARE_READ; break; case 0x40: /* deny none */ break; } /* desired access mask */ switch (pRequestHeader->usDesiredAccess & 0x7) { case 0x00: pOpenState->ulDesiredAccessMask = GENERIC_READ; break; case 0x01: pOpenState->ulDesiredAccessMask = GENERIC_WRITE; break; case 0x02: pOpenState->ulDesiredAccessMask = GENERIC_READ | GENERIC_WRITE; break; case 0x03: pOpenState->ulDesiredAccessMask = (GENERIC_READ | GENERIC_EXECUTE); break; default: ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); break; } /* action to take if the file exists */ switch (pRequestHeader->usOpenFunction) { case 0x0000: /* Weird EXECUTE -> OPEN_IF semantics */ if ((pOpenState->ulDesiredAccessMask & GENERIC_EXECUTE) == 0) { ntStatus = STATUS_INVALID_DISPOSITION; BAIL_ON_NT_STATUS(ntStatus); } pOpenState->ulCreateDisposition = FILE_OPEN_IF; break; case 0x0001: /* Open file */ pOpenState->ulCreateDisposition = FILE_OPEN; break; case 0x0002: /* truncate file */ pOpenState->ulCreateDisposition = FILE_OVERWRITE; break; case 0x0010: /* create new file */ pOpenState->ulCreateDisposition = FILE_CREATE; break; case 0x0011: /* open or create file */ pOpenState->ulCreateDisposition = FILE_OPEN_IF; break; case 0x0012: /* create or truncate */ pOpenState->ulCreateDisposition = FILE_OVERWRITE_IF; break; default: ntStatus = STATUS_INVALID_DISPOSITION; BAIL_ON_NT_STATUS(ntStatus); break; } pOpenState->pRequestHeader = pRequestHeader; *ppOpenState = pOpenState; cleanup: return ntStatus; error: *ppOpenState = NULL; if (pOpenState) { SrvFreeOpenState(pOpenState); } goto cleanup; }
NTSTATUS SrvTree2Create( PLWIO_SRV_SESSION_2 pSession, ULONG ulTid, PSRV_SHARE_INFO pShareInfo, PLWIO_SRV_TREE_2* ppTree ) { NTSTATUS ntStatus = 0; PLWIO_SRV_TREE_2 pTree = NULL; LWIO_LOG_DEBUG("Creating Tree [tid: %u]", ulTid); ntStatus = SrvAllocateMemory(sizeof(LWIO_SRV_TREE_2), (PVOID*)&pTree); BAIL_ON_NT_STATUS(ntStatus); pTree->refcount = 1; pthread_rwlock_init(&pTree->mutex, NULL); pTree->pMutex = &pTree->mutex; pTree->pSession = pSession;; SrvSession2Acquire(pSession); pTree->ulTid = ulTid; pTree->ullUid = pSession->ullUid; pTree->resource.resourceType = SRV_RESOURCE_TYPE_TREE; pTree->resource.pAttributes = &pTree->resourceAttrs; pTree->resource.pAttributes->protocolVersion = SMB_PROTOCOL_VERSION_2; pTree->resource.pAttributes->treeId.ulTid = pTree->ulTid; pTree->resource.pAttributes->sessionId.ullUid = pTree->ullUid; pTree->resource.pAttributes->ulConnectionResourceId = pSession->ulConnectionResourceId; LWIO_LOG_DEBUG("Associating Tree [object:0x%x][tid:%u]", pTree, ulTid); pTree->pShareInfo = pShareInfo; SrvShareAcquireInfo(pShareInfo); pTree->ullNextAvailableFid = 0xFFFFFFFF00000001LL; ntStatus = LwRtlRBTreeCreate( &SrvTree2FileCompare, NULL, &SrvTree2FileRelease, &pTree->pFileCollection); BAIL_ON_NT_STATUS(ntStatus); SRV_ELEMENTS_INCREMENT_TREE_CONNECTS; *ppTree = pTree; cleanup: return ntStatus; error: *ppTree = NULL; if (pTree) { SrvTree2Release(pTree); } goto cleanup; }
static NTSTATUS SrvShareDbWriteToShareInfo( IN sqlite3_stmt* pSqlStatement, OUT PSRV_SHARE_INFO** pppShareInfoList, IN OUT PULONG pulNumSharesFound ) { NTSTATUS ntStatus = 0; PSRV_SHARE_INFO* ppShareInfoList = NULL; PSRV_SHARE_INFO pShareInfo = NULL; PWSTR pwszStringVal = NULL; ULONG ulIntVal = 0; ULONG ulNumSharesAllocated = 0; ULONG ulNumSharesAvailable = 0; ULONG iShare = 0; while ((ntStatus = sqlite3_step(pSqlStatement)) == SQLITE_ROW) { ULONG iCol = 0; if (!ulNumSharesAvailable) { PSRV_SHARE_INFO* ppShareInfoListNew = NULL; ULONG ulNumSharesNew = 5; ULONG ulNumSharesAllocatedNew = ulNumSharesAllocated + ulNumSharesNew; ntStatus = SrvAllocateMemory( sizeof(PSRV_SHARE_INFO) * ulNumSharesAllocatedNew, (PVOID*)&ppShareInfoListNew); BAIL_ON_NT_STATUS(ntStatus); if (ppShareInfoList) { memcpy((PBYTE)ppShareInfoListNew, (PBYTE)ppShareInfoList, sizeof(PSRV_SHARE_INFO) * ulNumSharesAllocated); SrvFreeMemory(ppShareInfoList); } ppShareInfoList = ppShareInfoListNew; ulNumSharesAllocated = ulNumSharesAllocatedNew; ulNumSharesAvailable = ulNumSharesNew; } ntStatus = SrvAllocateMemory( sizeof(SRV_SHARE_INFO), (PVOID*)&pShareInfo); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->refcount = 1; pthread_rwlock_init(&pShareInfo->mutex, NULL); pShareInfo->pMutex = &pShareInfo->mutex; for (; iCol < 5; iCol++) { const unsigned char* pszStringVal = NULL; ULONG ulNumBytes = sqlite3_column_bytes(pSqlStatement, iCol); switch(iCol) { case 0: /* ShareName */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pShareInfo->pwszName); BAIL_ON_NT_STATUS(ntStatus); } break; case 1: /* PathName */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pShareInfo->pwszPath); BAIL_ON_NT_STATUS(ntStatus); } break; case 2: /* Comment */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pShareInfo->pwszComment); } else { /* Deal with empty comments */ ntStatus = SrvMbsToWc16s( "", &pShareInfo->pwszComment); } BAIL_ON_NT_STATUS(ntStatus); break; case 3: /* Security Descriptor */ if (ulNumBytes) { PCVOID pBlob = sqlite3_column_blob(pSqlStatement, iCol); ntStatus = SrvAllocateMemory( ulNumBytes, (PVOID*)&pShareInfo->pSecDesc); BAIL_ON_NT_STATUS(ntStatus); memcpy(pShareInfo->pSecDesc, pBlob, ulNumBytes); pShareInfo->ulSecDescLen = ulNumBytes; } break; case 4: /* service */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); } ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pwszStringVal); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareMapServiceStringToId( pwszStringVal, &pShareInfo->service); BAIL_ON_NT_STATUS(ntStatus); break; case 5: /* flags */ if (ulNumBytes) { ulIntVal = sqlite3_column_int(pSqlStatement, iCol); } pShareInfo->ulFlags = ulIntVal; break; } } *(ppShareInfoList + iShare++) = pShareInfo; pShareInfo = NULL; ulNumSharesAvailable--; } if (ntStatus == SQLITE_DONE) { ntStatus = STATUS_SUCCESS; } BAIL_ON_LWIO_SRV_SQLITE_ERROR_STMT(ntStatus, pSqlStatement); *pppShareInfoList = ppShareInfoList; *pulNumSharesFound = iShare; cleanup: SRV_SAFE_FREE_MEMORY(pwszStringVal); if (pShareInfo) { SrvShareReleaseInfo(pShareInfo); } return ntStatus; error: *pppShareInfoList = NULL; *pulNumSharesFound = 0; if (ppShareInfoList) { SrvShareFreeInfoList(ppShareInfoList, iShare); } goto cleanup; }
static NTSTATUS SrvUnmarshalSetEaListInformation( PSRV_EXEC_CONTEXT pExecContext ) { NTSTATUS ntStatus = 0; PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext; PSRV_EXEC_CONTEXT_SMB_V1 pCtxSmb1 = pCtxProtocol->pSmb1Context; PSRV_TRANS2_STATE_SMB_V1 pTrans2State = NULL; ULONG ulBytesAvailable = 0; ULONG ulOffset = 0; PBYTE pDataCursor = NULL; PTRANS2_FILE_EA_LIST_INFORMATION pFileEaListInfo = NULL; PFILE_FULL_EA_INFORMATION pFileFullEaInformation = NULL; pTrans2State = (PSRV_TRANS2_STATE_SMB_V1)pCtxSmb1->hState; pDataCursor = pTrans2State->pData; ulOffset = pTrans2State->pRequestHeader->dataOffset; ulBytesAvailable = pTrans2State->pRequestHeader->dataCount; if (ulBytesAvailable < sizeof(TRANS2_FILE_EA_LIST_INFORMATION)) { ntStatus = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(ntStatus); } pFileEaListInfo = (PTRANS2_FILE_EA_LIST_INFORMATION)pDataCursor; pDataCursor += sizeof(TRANS2_FILE_EA_LIST_INFORMATION); ulBytesAvailable -= sizeof(TRANS2_FILE_EA_LIST_INFORMATION); ulOffset += sizeof(TRANS2_FILE_EA_LIST_INFORMATION); if (pFileEaListInfo->ulEaListSize <= 0) { ntStatus = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(ntStatus); } /* Assume for now that we are only allocating one FILE_FULL_EA_INFORMATION record which is all that has been observed from WinXP --jerry */ pTrans2State->usBytesAllocated = pFileEaListInfo->ulEaListSize + sizeof(ULONG); ntStatus = SrvAllocateMemory( pTrans2State->usBytesAllocated, (PVOID*)&pTrans2State->pData2); BAIL_ON_NT_STATUS(ntStatus); pFileFullEaInformation = (PFILE_FULL_EA_INFORMATION)pTrans2State->pData2; pFileFullEaInformation->NextEntryOffset = 0; memcpy((PBYTE)&pFileFullEaInformation->Flags, (PBYTE)&pFileEaListInfo->pEaList[0], pFileEaListInfo->ulEaListSize); cleanup: return ntStatus; error: goto cleanup; }
static NTSTATUS SrvUnmarshalRenameInformation( PSRV_EXEC_CONTEXT pExecContext ) { NTSTATUS ntStatus = 0; PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext; PSRV_EXEC_CONTEXT_SMB_V1 pCtxSmb1 = pCtxProtocol->pSmb1Context; PSRV_TRANS2_STATE_SMB_V1 pTrans2State = NULL; ULONG ulBytesAvailable = 0; ULONG ulOffset = 0; PWSTR pwszFilename = NULL; PBYTE pDataCursor = NULL; BOOLEAN bTreeInLock = FALSE; PSMB_FILE_RENAME_INFO_HEADER pFileRenameInfo = NULL; pTrans2State = (PSRV_TRANS2_STATE_SMB_V1)pCtxSmb1->hState; pDataCursor = pTrans2State->pData; ulOffset = pTrans2State->pRequestHeader->dataOffset; ulBytesAvailable = pTrans2State->pRequestHeader->dataCount; if (ulBytesAvailable < sizeof(SMB_FILE_RENAME_INFO_HEADER)) { ntStatus = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(ntStatus); } pFileRenameInfo = (PSMB_FILE_RENAME_INFO_HEADER)pDataCursor; pDataCursor += sizeof(SMB_FILE_RENAME_INFO_HEADER); ulBytesAvailable -= sizeof(SMB_FILE_RENAME_INFO_HEADER); ulOffset += sizeof(SMB_FILE_RENAME_INFO_HEADER); if (ulOffset % 2) { if (ulBytesAvailable < 1) { ntStatus = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(ntStatus); } pDataCursor++; ulOffset++; ulBytesAvailable--; } if (!pFileRenameInfo->ulFileNameLength || (ulBytesAvailable < pFileRenameInfo->ulFileNameLength)) { ntStatus = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(ntStatus); } if (pFileRenameInfo->ulRootDir) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } pwszFilename = (PWSTR)pDataCursor; pTrans2State->usBytesAllocated = sizeof(FILE_RENAME_INFORMATION) + pFileRenameInfo->ulFileNameLength; ntStatus = SrvAllocateMemory( pTrans2State->usBytesAllocated, (PVOID*)&pTrans2State->pData2); BAIL_ON_NT_STATUS(ntStatus); ((PFILE_RENAME_INFORMATION)pTrans2State->pData2)->ReplaceIfExists = pFileRenameInfo->ucReplaceIfExists ? TRUE : FALSE; ((PFILE_RENAME_INFORMATION)pTrans2State->pData2)->FileNameLength = pFileRenameInfo->ulFileNameLength; memcpy((PBYTE)((PFILE_RENAME_INFORMATION)pTrans2State->pData2)->FileName, (PBYTE)pwszFilename, pFileRenameInfo->ulFileNameLength); cleanup: LWIO_UNLOCK_RWMUTEX(bTreeInLock, &pCtxSmb1->pTree->mutex); return ntStatus; error: goto cleanup; }
static PVOID SrvTimerMain( IN PVOID pData ) { NTSTATUS status = 0; PSRV_TIMER_CONTEXT pContext = (PSRV_TIMER_CONTEXT)pData; PSRV_TIMER_REQUEST pTimerRequest = NULL; LONG64 llCurTime = 0LL; BOOLEAN bInLock = FALSE; LWIO_LOG_DEBUG("Srv timer starting"); LWIO_LOCK_MUTEX(bInLock, &pContext->mutex); while (!SrvTimerMustStop_inlock(pContext)) { int errCode = 0; BOOLEAN bRetryWait = FALSE; // If we have a current timer request, check if it is time to service it if (pTimerRequest) { status = WireGetCurrentNTTime(&llCurTime); BAIL_ON_NT_STATUS(status); if (llCurTime >= pTimerRequest->llExpiry && !pTimerRequest->bCanceled) { SrvTimerDetachRequest_inlock(pContext, pTimerRequest); LWIO_UNLOCK_MUTEX(bInLock, &pContext->mutex); if (pTimerRequest->pfnTimerExpiredCB) { // Timer has not been canceled pTimerRequest->pfnTimerExpiredCB( pTimerRequest, pTimerRequest->pUserData); } LWIO_LOCK_MUTEX(bInLock, &pContext->mutex); } SrvTimerRelease(pTimerRequest); pTimerRequest = NULL; } // Get the next timer request in queue status = SrvTimerGetNextRequest_inlock(pContext, &pTimerRequest); if (status == STATUS_NOT_FOUND) { // If the queue is empty wait for a day or until a request arrives struct timespec tsLong = { .tv_sec = time(NULL) + 86400, .tv_nsec = 0 }; status = STATUS_SUCCESS; do { bRetryWait = FALSE; errCode = pthread_cond_timedwait( &pContext->event, &pContext->mutex, &tsLong); if (errCode == ETIMEDOUT) { if (time(NULL) < tsLong.tv_sec) { bRetryWait = TRUE; continue; } break; } status = LwErrnoToNtStatus(errCode); BAIL_ON_NT_STATUS(status); } while (bRetryWait && !SrvTimerMustStop_inlock(pContext)); continue; } BAIL_ON_NT_STATUS(status); // At this point, we have a timer request - wait for its specified time do { struct timespec ts = {.tv_sec = 0, .tv_nsec = 0}; bRetryWait = FALSE; status = WireNTTimeToTimeSpec(pTimerRequest->llExpiry, &ts); BAIL_ON_NT_STATUS(status); errCode = pthread_cond_timedwait( &pContext->event, &pContext->mutex, &ts); if (errCode == ETIMEDOUT) { status = WireGetCurrentNTTime(&llCurTime); BAIL_ON_NT_STATUS(status); if (llCurTime < pTimerRequest->llExpiry) { bRetryWait = TRUE; continue; } break; } status = LwErrnoToNtStatus(errCode); BAIL_ON_NT_STATUS(status); } while (bRetryWait && !SrvTimerMustStop_inlock(pContext)); } cleanup: LWIO_UNLOCK_MUTEX(bInLock, &pContext->mutex); if (pTimerRequest) { SrvTimerRelease(pTimerRequest); } LWIO_LOG_DEBUG("Srv timer stopping"); return NULL; error: LWIO_LOG_ERROR("Srv timer stopping due to error [%d]", status); goto cleanup; } static NTSTATUS SrvTimerGetNextRequest_inlock( IN PSRV_TIMER_CONTEXT pContext, OUT PSRV_TIMER_REQUEST* ppTimerRequest ) { NTSTATUS status = STATUS_SUCCESS; PSRV_TIMER_REQUEST pTimerRequest = NULL; if (!pContext->pRequests) { status = STATUS_NOT_FOUND; BAIL_ON_NT_STATUS(status); } pTimerRequest = pContext->pRequests; InterlockedIncrement(&pTimerRequest->refCount); *ppTimerRequest = pTimerRequest; cleanup: return status; error: *ppTimerRequest = NULL; goto cleanup; } static NTSTATUS SrvTimerDetachRequest_inlock( IN OUT PSRV_TIMER_CONTEXT pContext, IN OUT PSRV_TIMER_REQUEST pTimerRequest ) { if (pTimerRequest->pPrev) { pTimerRequest->pPrev->pNext = pTimerRequest->pNext; if (pTimerRequest->pNext) { pTimerRequest->pNext->pPrev = pTimerRequest->pPrev; } } else { pContext->pRequests = pTimerRequest->pNext; if (pTimerRequest->pNext) { pTimerRequest->pNext->pPrev = NULL; } } pTimerRequest->pPrev = NULL; pTimerRequest->pNext = NULL; // Removed from timer queue InterlockedDecrement(&pTimerRequest->refCount); return STATUS_SUCCESS; } NTSTATUS SrvTimerPostRequestSpecific( IN PSRV_TIMER pTimer, IN LONG64 llExpiry, IN PVOID pUserData, IN PFN_SRV_TIMER_CALLBACK pfnTimerExpiredCB, OUT PSRV_TIMER_REQUEST* ppTimerRequest ) { NTSTATUS status = STATUS_SUCCESS; PSRV_TIMER_REQUEST pTimerRequest = NULL; PSRV_TIMER_REQUEST pTimerIter = NULL; PSRV_TIMER_REQUEST pPrev = NULL; BOOLEAN bInLock = FALSE; if (!llExpiry) { status = STATUS_INVALID_PARAMETER_1; BAIL_ON_NT_STATUS(status); } if (!pfnTimerExpiredCB) { status = STATUS_INVALID_PARAMETER_3; BAIL_ON_NT_STATUS(status); } status = SrvAllocateMemory( sizeof(SRV_TIMER_REQUEST), (PVOID*)&pTimerRequest); BAIL_ON_NT_STATUS(status); pTimerRequest->refCount = 1; pTimerRequest->llExpiry = llExpiry; pTimerRequest->pUserData = pUserData; pTimerRequest->pfnTimerExpiredCB = pfnTimerExpiredCB; pTimerRequest->bCanceled = FALSE; LWIO_LOCK_MUTEX(bInLock, &pTimer->context.mutex); for (pTimerIter = pTimer->context.pRequests; pTimerIter && (pTimerIter->llExpiry <= llExpiry); pPrev = pTimerIter, pTimerIter = pTimerIter->pNext); if (!pPrev) { pTimerRequest->pNext = pTimer->context.pRequests; if (pTimer->context.pRequests) { pTimer->context.pRequests->pPrev = pTimerRequest; } pTimer->context.pRequests = pTimerRequest; } else { pTimerRequest->pNext = pPrev->pNext; pTimerRequest->pPrev = pPrev; pPrev->pNext = pTimerRequest; if (pTimerRequest->pNext) { pTimerRequest->pNext->pPrev = pTimerRequest; } } // +1 for timer queue InterlockedIncrement(&pTimerRequest->refCount); LWIO_UNLOCK_MUTEX(bInLock, &pTimer->context.mutex); pthread_cond_signal(&pTimer->context.event); // +1 for caller InterlockedIncrement(&pTimerRequest->refCount); *ppTimerRequest = pTimerRequest; cleanup: LWIO_UNLOCK_MUTEX(bInLock, &pTimer->context.mutex); if (pTimerRequest) { SrvTimerRelease(pTimerRequest); } return status; error: *ppTimerRequest = NULL; goto cleanup; }
NTSTATUS SrvShareDbAcquireContext( PSRV_SHARE_DB_CONTEXT* ppDbContext ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PSRV_SHARE_DB_GLOBALS pGlobals = &gShareRepository_lwshare; PSRV_SHARE_DB_CONTEXT pDbContext = NULL; LWIO_LOCK_MUTEX(bInLock, &pGlobals->mutex); if (pGlobals->ulNumDbContexts) { pDbContext = pGlobals->pDbContextList; pGlobals->pDbContextList = pGlobals->pDbContextList->pNext; pDbContext->pNext = NULL; pGlobals->ulNumDbContexts--; LWIO_UNLOCK_MUTEX(bInLock, &pGlobals->mutex); } else { PCSTR pszShareDbPath = LWIO_SRV_SHARE_DB; ntStatus = SrvAllocateMemory( sizeof(SRV_SHARE_DB_CONTEXT), (PVOID*)&pDbContext); BAIL_ON_NT_STATUS(ntStatus); ntStatus = sqlite3_open( pszShareDbPath, &pDbContext->pDbHandle); if (ntStatus) { LWIO_LOG_ERROR("Sqlite3 Error (code: %d): %s", ntStatus, "Failed to open database handle"""); ntStatus = STATUS_INTERNAL_DB_ERROR; } BAIL_ON_NT_STATUS(ntStatus); } *ppDbContext = pDbContext; cleanup: LWIO_UNLOCK_MUTEX(bInLock, &pGlobals->mutex); return ntStatus; error: *ppDbContext = NULL; if (pDbContext) { SrvShareDbFreeContext(pDbContext); } goto cleanup; }
static NTSTATUS SrvMarshalNotifyResponse_SMB_V2( PBYTE pNotifyResponse, ULONG ulNotifyResponseLength, PBYTE* ppBuffer, PULONG pulBufferLength ) { NTSTATUS ntStatus = STATUS_SUCCESS; PBYTE pBuffer = NULL; ULONG ulBufferLength = 0; ULONG ulOffset = 0; ULONG ulNumRecords = 0; ULONG iRecord = 0; ULONG ulBytesAvailable = ulNotifyResponseLength; PBYTE pDataCursor = NULL; PFILE_NOTIFY_INFORMATION pNotifyCursor = NULL; PFILE_NOTIFY_INFORMATION pPrevHeader = NULL; PFILE_NOTIFY_INFORMATION pCurHeader = NULL; pNotifyCursor = (PFILE_NOTIFY_INFORMATION)pNotifyResponse; while (pNotifyCursor && (ulBufferLength < ulBytesAvailable)) { ulBufferLength += offsetof(FILE_NOTIFY_INFORMATION, FileName); if (!pNotifyCursor->FileNameLength) { ulBufferLength += sizeof(wchar16_t); } else { ulBufferLength += pNotifyCursor->FileNameLength; } ulNumRecords++; if (pNotifyCursor->NextEntryOffset) { if (ulBufferLength % 4) { USHORT usAlignment = (4 - (ulBufferLength % 4)); ulBufferLength += usAlignment; } pNotifyCursor = (PFILE_NOTIFY_INFORMATION)(((PBYTE)pNotifyCursor) + pNotifyCursor->NextEntryOffset); } else { pNotifyCursor = NULL; } } if (ulBufferLength) { ntStatus = SrvAllocateMemory(ulBufferLength, (PVOID*)&pBuffer); BAIL_ON_NT_STATUS(ntStatus); } pNotifyCursor = (PFILE_NOTIFY_INFORMATION)pNotifyResponse; pDataCursor = pBuffer; for (; iRecord < ulNumRecords; iRecord++) { pPrevHeader = pCurHeader; pCurHeader = (PFILE_NOTIFY_INFORMATION)pDataCursor; /* Update next entry offset for previous entry. */ if (pPrevHeader != NULL) { pPrevHeader->NextEntryOffset = ulOffset; } ulOffset = 0; pCurHeader->NextEntryOffset = 0; pCurHeader->Action = pNotifyCursor->Action; pCurHeader->FileNameLength = pNotifyCursor->FileNameLength; pDataCursor += offsetof(FILE_NOTIFY_INFORMATION, FileName); ulOffset += offsetof(FILE_NOTIFY_INFORMATION, FileName); if (pNotifyCursor->FileNameLength) { memcpy( pDataCursor, (PBYTE)pNotifyCursor->FileName, pNotifyCursor->FileNameLength); pDataCursor += pNotifyCursor->FileNameLength; ulOffset += pNotifyCursor->FileNameLength; } else { pDataCursor += sizeof(wchar16_t); ulOffset += sizeof(wchar16_t); } if (pNotifyCursor->NextEntryOffset != 0) { if (ulOffset % 4) { USHORT usAlign = 4 - (ulOffset % 4); pDataCursor += usAlign; ulOffset += usAlign; } } pNotifyCursor = (PFILE_NOTIFY_INFORMATION)(((PBYTE)pNotifyCursor) + pNotifyCursor->NextEntryOffset); } *ppBuffer = pBuffer; *pulBufferLength = ulBufferLength; cleanup: return ntStatus; error: *ppBuffer = NULL; *pulBufferLength = 0; if (pBuffer) { SrvFreeMemory(pBuffer); } goto cleanup; }
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; }
static NTSTATUS SrvInitialize( IO_DEVICE_HANDLE hDevice ) { NTSTATUS ntStatus = 0; INT iWorker = 0; memset(&gSMBSrvGlobals, 0, sizeof(gSMBSrvGlobals)); pthread_mutex_init(&gSMBSrvGlobals.mutex, NULL); gSMBSrvGlobals.pMutex = &gSMBSrvGlobals.mutex; ntStatus = SrvInitConfig(&gSMBSrvGlobals.config); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvReadConfig(&gSMBSrvGlobals.config); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SMBPacketCreateAllocator( gSMBSrvGlobals.config.ulMaxNumPackets, &gSMBSrvGlobals.hPacketAllocator); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvProdConsInitContents( &gSMBSrvGlobals.workQueue, gSMBSrvGlobals.config.ulMaxNumWorkItemsInQueue, &SrvReleaseExecContextHandle); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareInit(); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareInitList(&gSMBSrvGlobals.shareList); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareBootstrapNamedPipeRoot(&gSMBSrvGlobals.shareList); BAIL_ON_NT_STATUS(ntStatus); if (gSMBSrvGlobals.config.bBootstrapDefaultSharePath) { ntStatus = SrvShareBootstrapDiskRoot(&gSMBSrvGlobals.shareList); BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvElementsInit(); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvStatisticsInitialize(); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvProtocolInit( &gSMBSrvGlobals.workQueue, gSMBSrvGlobals.hPacketAllocator, &gSMBSrvGlobals.shareList); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvAllocateMemory( gSMBSrvGlobals.config.ulNumWorkers * sizeof(LWIO_SRV_WORKER), (PVOID*)&gSMBSrvGlobals.pWorkerArray); BAIL_ON_NT_STATUS(ntStatus); gSMBSrvGlobals.ulNumWorkers = gSMBSrvGlobals.config.ulNumWorkers; for (; iWorker < gSMBSrvGlobals.config.ulNumWorkers; iWorker++) { PLWIO_SRV_WORKER pWorker = &gSMBSrvGlobals.pWorkerArray[iWorker]; pWorker->workerId = iWorker + 1; ntStatus = SrvWorkerInit(pWorker); BAIL_ON_NT_STATUS(ntStatus); } gSMBSrvGlobals.hDevice = hDevice; error: return ntStatus; }
NTSTATUS SrvShareSetSecurity( IN PSRV_SHARE_INFO pShareInfo, IN PSECURITY_DESCRIPTOR_RELATIVE pIncRelSecDesc, IN ULONG ulIncRelSecDescLen ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pIncAbsSecDesc = NULL; PSECURITY_DESCRIPTOR_ABSOLUTE pFinalAbsSecDesc = NULL; PSECURITY_DESCRIPTOR_RELATIVE pFinalRelSecDesc = NULL; ULONG ulFinalRelSecDescLen = 0; SECURITY_INFORMATION secInfo = 0; PSID pOwner = NULL; PSID pGroup = NULL; PACL pDacl = NULL; PACL pSacl = NULL; BOOLEAN bDefaulted = FALSE; BOOLEAN bPresent = FALSE; GENERIC_MAPPING GenericMap = { .GenericRead = FILE_GENERIC_READ, .GenericWrite = FILE_GENERIC_WRITE, .GenericExecute = FILE_GENERIC_EXECUTE, .GenericAll = FILE_ALL_ACCESS }; /* Sanity checks */ if ((pIncRelSecDesc == NULL) || (ulIncRelSecDescLen == 0)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } if (pShareInfo->ulSecDescLen == 0) { ntStatus = SrvShareSetDefaultSecurity(pShareInfo); BAIL_ON_NT_STATUS(ntStatus); } /* Make the Absolute version of thr incoming SD and get the SecurityInformation */ ntStatus = SrvShareCreateAbsoluteSecDescFromRel( &pIncAbsSecDesc, pIncRelSecDesc) ; BAIL_ON_NT_STATUS(ntStatus); /* Don't bail on these. We'll be checking the pointer */ ntStatus = RtlGetOwnerSecurityDescriptor( pIncAbsSecDesc, &pOwner, &bDefaulted); secInfo |= pOwner ? OWNER_SECURITY_INFORMATION : 0; ntStatus = RtlGetGroupSecurityDescriptor( pIncAbsSecDesc, &pGroup, &bDefaulted); secInfo |= pGroup ? GROUP_SECURITY_INFORMATION : 0; ntStatus = RtlGetDaclSecurityDescriptor( pIncAbsSecDesc, &bPresent, &pDacl, &bDefaulted); secInfo |= pDacl ? DACL_SECURITY_INFORMATION : 0; ntStatus = RtlGetSaclSecurityDescriptor( pIncAbsSecDesc, &bPresent, &pSacl, &bDefaulted); secInfo |= pSacl ? SACL_SECURITY_INFORMATION : 0; /* Assume the new length is not longer than the combined length of both the current and incoming relative SecDesc buffers */ ulFinalRelSecDescLen = ulIncRelSecDescLen + pShareInfo->ulSecDescLen; ntStatus = SrvAllocateMemory( ulFinalRelSecDescLen, (PVOID*)&pFinalRelSecDesc); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetSecurityDescriptorInfo( secInfo, pIncRelSecDesc, pShareInfo->pSecDesc, pFinalRelSecDesc, &ulFinalRelSecDescLen, &GenericMap); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareCreateAbsoluteSecDescFromRel( &pFinalAbsSecDesc, pFinalRelSecDesc) ; BAIL_ON_NT_STATUS(ntStatus); /* Free the old SecDesc and save the new one */ SrvShareFreeSecurity(pShareInfo); pShareInfo->pSecDesc = pFinalRelSecDesc; pShareInfo->ulSecDescLen = ulFinalRelSecDescLen; pShareInfo->pAbsSecDesc = pFinalAbsSecDesc; ntStatus = STATUS_SUCCESS; cleanup: if (pIncAbsSecDesc) { SrvShareFreeAbsoluteSecurityDescriptor(&pIncAbsSecDesc); } return ntStatus; error: if (pFinalRelSecDesc) { SrvFreeMemory(pFinalRelSecDesc); } if (pFinalAbsSecDesc) { SrvShareFreeAbsoluteSecurityDescriptor(&pFinalAbsSecDesc); } 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; }
NTSTATUS SrvTreeCreate( USHORT tid, PSRV_SHARE_INFO pShareInfo, PLWIO_SRV_TREE* ppTree ) { NTSTATUS ntStatus = 0; PLWIO_SRV_TREE pTree = NULL; LWIO_LOG_DEBUG("Creating Tree [tid: %u]", tid); ntStatus = SrvAllocateMemory(sizeof(LWIO_SRV_TREE), (PVOID*)&pTree); BAIL_ON_NT_STATUS(ntStatus); pTree->refcount = 1; pthread_rwlock_init(&pTree->mutex, NULL); pTree->pMutex = &pTree->mutex; pTree->tid = tid; LWIO_LOG_DEBUG("Associating Tree [object:0x%x][tid:%u]", pTree, tid); pTree->pShareInfo = SrvShareAcquireInfo(pShareInfo); ntStatus = LwRtlRBTreeCreate( &SrvTreeFileCompare, NULL, &SrvTreeFileRelease, &pTree->pFileCollection); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LwRtlRBTreeCreate( &SrvTreeAsyncStateCompare, NULL, &SrvTreeAsyncStateRelease, &pTree->pAsyncStateCollection); BAIL_ON_NT_STATUS(ntStatus); SRV_ELEMENTS_INCREMENT_TREE_CONNECTS; *ppTree = pTree; cleanup: return ntStatus; error: *ppTree = NULL; if (pTree) { SrvTreeRelease(pTree); } goto cleanup; }