static NTSTATUS SrvShareBootstrapDiskRoot( IN OUT PLWIO_SRV_SHARE_ENTRY_LIST pShareList ) { NTSTATUS ntStatus = STATUS_SUCCESS; wchar16_t wszFileRootName[] = {'C','$',0}; PSTR pszDefaultSharePath = NULL; PWSTR pwszFileSystemRoot = NULL; PSRV_SHARE_INFO pShareInfo = NULL; ntStatus = SrvShareFindByName( pShareList, &wszFileRootName[0], &pShareInfo); if (ntStatus == STATUS_NOT_FOUND) { wchar16_t wszDesc[] = {'D','e','f','a','u','l','t',' ','S','h','a','r','e',0}; wchar16_t wszServiceType[] = LWIO_SRV_SHARE_STRING_ID_DISK_W; ntStatus = SrvGetDefaultSharePath(&pszDefaultSharePath); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvMbsToWc16s(pszDefaultSharePath, &pwszFileSystemRoot); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvCreateDefaultSharePath(pwszFileSystemRoot); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareAdd( pShareList, &wszFileRootName[0], pwszFileSystemRoot, &wszDesc[0], NULL, 0, &wszServiceType[0], 0); } BAIL_ON_NT_STATUS(ntStatus); cleanup: SRV_SAFE_FREE_MEMORY(pszDefaultSharePath); SRV_SAFE_FREE_MEMORY(pwszFileSystemRoot); return ntStatus; error: LWIO_LOG_ERROR("Failed to bootstrap default shares. [error code: %d]", ntStatus); goto cleanup; }
NTSTATUS SrvSocketAddressToStringW( const struct sockaddr* pSocketAddress, PWSTR* ppwszAddress ) { NTSTATUS ntStatus = STATUS_SUCCESS; CHAR szBuffer[SRV_SOCKET_ADDRESS_STRING_MAX_SIZE]; PWSTR pwszAddress = NULL; if (!pSocketAddress) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvSocketAddressToString( pSocketAddress, &szBuffer[0], sizeof(szBuffer)); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvMbsToWc16s(szBuffer, &pwszAddress); BAIL_ON_NT_STATUS(ntStatus); *ppwszAddress = pwszAddress; cleanup: return ntStatus; error: *ppwszAddress = NULL; 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; }
NTSTATUS SrvGetShareName( IN PCSTR pszHostname, IN PCSTR pszDomain, IN PWSTR pwszPath, OUT PWSTR* ppwszSharename ) { NTSTATUS ntStatus = 0; PWSTR pwszSharename = NULL; PSTR pszPath = NULL; PSTR pszShareName = NULL; PSTR pszCursor = NULL; ntStatus = SrvWc16sToMbs(pwszPath, &pszPath); BAIL_ON_NT_STATUS(ntStatus); pszCursor = pszPath; /* Skip a leading pair of backslashes */ if ((strlen(pszCursor) > 2) && (*pszCursor == '\\') && (*(pszCursor+1) == '\\')) { pszCursor += 2; } pszShareName = strchr(pszCursor, '\\'); if (pszShareName == NULL) { pszShareName = pszCursor; } else { pszShareName++; } if (*pszShareName == '\0') { ntStatus = STATUS_BAD_NETWORK_PATH; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvMbsToWc16s(pszShareName, &pwszSharename); BAIL_ON_NT_STATUS(ntStatus); *ppwszSharename = pwszSharename; cleanup: if (pszPath) { SrvFreeMemory(pszPath); } return ntStatus; error: *ppwszSharename = NULL; goto cleanup; }
NTSTATUS SrvBuildNegotiateResponse_SMB_V1_NTLM_0_12( IN PLWIO_SRV_CONNECTION pConnection, IN PSMB_PACKET pSmbRequest, IN SMB_PROTOCOL_DIALECT Dialect, IN USHORT idxDialect, OUT PSMB_PACKET* ppSmbResponse ) { NTSTATUS ntStatus = 0; NEGOTIATE_RESPONSE_HEADER* pResponseHeader = NULL; time_t curTime = 0L; LONG64 llUTCTime = 0LL; uint16_t byteCount = 0; uint8_t* pDataCursor = NULL; PSRV_PROPERTIES pServerProperties = &pConnection->serverProperties; PSMB_PACKET pSmbResponse = NULL; PWSTR pwszHostname = NULL; ntStatus = SMBPacketAllocate( pConnection->hPacketAllocator, &pSmbResponse); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SMBPacketBufferAllocate( pConnection->hPacketAllocator, (64 * 1024) + 4096, &pSmbResponse->pRawBuffer, &pSmbResponse->bufferLen); BAIL_ON_NT_STATUS(ntStatus); if ((pSmbRequest->pSMBHeader->flags2 & FLAG2_EXT_SEC) == 0) { pServerProperties->Capabilities &= ~CAP_EXTENDED_SECURITY; } ntStatus = SMBPacketMarshallHeader( pSmbResponse->pRawBuffer, pSmbResponse->bufferLen, COM_NEGOTIATE, 0, TRUE, pSmbRequest->pSMBHeader->tid, SMB_V1_GET_PROCESS_ID(pSmbRequest->pSMBHeader), 0, pSmbRequest->pSMBHeader->mid, FALSE, pSmbResponse); BAIL_ON_NT_STATUS(ntStatus); if ((pServerProperties->Capabilities & CAP_EXTENDED_SECURITY) == 0) { pSmbResponse->pSMBHeader->flags2 &= ~FLAG2_EXT_SEC; } pSmbResponse->pSMBHeader->wordCount = 17; pResponseHeader = (NEGOTIATE_RESPONSE_HEADER*)pSmbResponse->pParams; pSmbResponse->pData = pSmbResponse->pParams + sizeof(NEGOTIATE_RESPONSE_HEADER); pSmbResponse->bufferUsed += sizeof(NEGOTIATE_RESPONSE_HEADER); pResponseHeader->dialectIndex = idxDialect; pResponseHeader->securityMode = 0; if (pServerProperties->preferredSecurityMode == SMB_SECURITY_MODE_USER) { pResponseHeader->securityMode |= 0x1; // User level security } if (pServerProperties->bEncryptPasswords) { pResponseHeader->securityMode |= 0x2; } if (pServerProperties->bEnableSecuritySignatures) { pResponseHeader->securityMode |= 0x4; } if (pServerProperties->bRequireSecuritySignatures) { pResponseHeader->securityMode |= 0x8; } pResponseHeader->maxMpxCount = pServerProperties->MaxMpxCount; pResponseHeader->maxNumberVcs = pServerProperties->MaxNumberVCs; pResponseHeader->maxBufferSize = pServerProperties->MaxBufferSize; pResponseHeader->maxRawSize = pServerProperties->MaxRawSize; pResponseHeader->sessionKey = 0; pResponseHeader->capabilities = pServerProperties->Capabilities; curTime = time(NULL); ntStatus = WireSMBUTimeToTimeZone(curTime, &pResponseHeader->serverTimeZone); BAIL_ON_NT_STATUS(ntStatus); ntStatus = WireSMBUTimetoNTTime(curTime, FALSE, &llUTCTime); BAIL_ON_NT_STATUS(ntStatus); pResponseHeader->systemTimeLow = llUTCTime & 0xFFFFFFFFLL; pResponseHeader->systemTimeHigh = (llUTCTime & 0xFFFFFFFF00000000LL) >> 32; pDataCursor = pSmbResponse->pData; if (pResponseHeader->capabilities & CAP_EXTENDED_SECURITY) { PBYTE pNegHintsBlob = NULL; /* Do not free */ ULONG ulNegHintsLength = 0; pResponseHeader->encryptionKeyLength = 0; memcpy(pDataCursor, pServerProperties->GUID, sizeof(pServerProperties->GUID)); pDataCursor += sizeof(pServerProperties->GUID); byteCount += sizeof(pServerProperties->GUID); ntStatus = SrvGssNegHints(&pNegHintsBlob, &ulNegHintsLength); /* Microsoft clients ignore the security blob on the neg prot response so don't fail here if we can't get a negHintsBlob */ if (ntStatus == STATUS_SUCCESS) { memcpy(pDataCursor, pNegHintsBlob, ulNegHintsLength); pDataCursor += ulNegHintsLength; byteCount += ulNegHintsLength; } } else { WCHAR wszWorkgroup[] = SRV_NATIVE_DOMAIN_W; CHAR szHostname[HOST_NAME_MAX]; PWSTR pwszDomain = pConnection->clientProperties.pwszNativeDomain; if (!pwszDomain) { pwszDomain = &wszWorkgroup[0]; } if (gethostname(szHostname, HOST_NAME_MAX) == -1) { ntStatus = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(ntStatus); } pResponseHeader->encryptionKeyLength = sizeof(pConnection->ServerChallenge); // Generate challenge and remember it in connection if (!RAND_bytes( pConnection->ServerChallenge, sizeof(pConnection->ServerChallenge))) { ntStatus = STATUS_INTERNAL_ERROR; BAIL_ON_NT_STATUS(ntStatus); } RtlCopyMemory(pDataCursor, &pConnection->ServerChallenge, sizeof(pConnection->ServerChallenge)); pDataCursor += sizeof(pConnection->ServerChallenge); byteCount += sizeof(pConnection->ServerChallenge); // Add domain name { size_t sDomainLen = (wc16slen(pwszDomain)+1) * sizeof(wchar16_t); RtlCopyMemory(pDataCursor, pwszDomain, sDomainLen); pDataCursor += sDomainLen; byteCount += sDomainLen; } // Add hostname { size_t sHostnameLen = 0; ntStatus = SrvMbsToWc16s(szHostname, &pwszHostname); BAIL_ON_NT_STATUS(ntStatus); sHostnameLen = (wc16slen(pwszHostname)+1) * sizeof(wchar16_t); RtlCopyMemory(pDataCursor, pwszHostname, sHostnameLen); pDataCursor += sHostnameLen; byteCount += sHostnameLen; } } pResponseHeader->byteCount = byteCount; pSmbResponse->bufferUsed += byteCount; ntStatus = SMBPacketMarshallFooter(pSmbResponse); BAIL_ON_NT_STATUS(ntStatus); *ppSmbResponse = pSmbResponse; cleanup: SRV_SAFE_FREE_MEMORY(pwszHostname); return ntStatus; error: *ppSmbResponse = NULL; if (pSmbResponse) { SMBPacketRelease(pConnection->hPacketAllocator, pSmbResponse); } goto cleanup; }