2025-04-27 07:49:33 -04:00

367 lines
11 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++ BUILD Version: 0009 // Increment this if a change has global effects
Copyright (c) 1987-1993 Microsoft Corporation
Module Name:
3connect.c
Abstract:
This module implements the tree connect SMB related routines. It also implements the
three flavours of this routine ( user level and share level non NT server tree connect
SMB construction and the tree connect SMB construction for SMB servers)
--*/
#include "precomp.h"
#pragma hdrstop
#include "ntlsapi.h"
//
// The order of these names should match the order in which the enumerated type
// NET_ROOT_TYPE is defined. This facilitates easy access of share type names
//
PCHAR s_NetRootTypeName[] = {
SHARE_TYPE_NAME_DISK,
SHARE_TYPE_NAME_PIPE,
SHARE_TYPE_NAME_COMM,
SHARE_TYPE_NAME_PRINT,
SHARE_TYPE_NAME_WILD
};
extern NTSTATUS
BuildTreeConnectSecurityInformation(
PSMB_EXCHANGE pExchange,
PBYTE pBuffer,
PBYTE pPasswordLength,
PULONG pSmbBufferSize);
NTSTATUS
BuildCanonicalNetRootInformation(
PUNICODE_STRING pServerName,
PUNICODE_STRING pNetRootName,
NET_ROOT_TYPE NetRootType,
BOOLEAN fUnicode,
BOOLEAN fPostPendServiceString,
PBYTE *pBufferPointer,
PULONG pBufferSize)
/*++
Routine Description:
This routine builds the desired net root information for a tree connect SMB
Arguments:
pServerName - the server name
pNetRootName - the net root name
NetRootType - the net root type ( print,pipe,disk etc.,)
fUnicode - TRUE if it is to be built in UNICODE
pBufferPointer - the SMB buffer
pBufferSize - the size on input. modified to the remaining size on output
Return Value:
RXSTATUS - The return status for the operation
Notes:
This routine relies upon the names being in certain formats to ensure that a
valid UNC name can be formulated.
1) The RDBSS netroot names start with a \ and also include the server name as
part of the net root name. This is mandated by the prefix table search requirements
in RDBSS.
--*/
{
NTSTATUS Status;
if (fUnicode)
{
// Align the buffer and adjust the size accordingly.
PBYTE pBuffer = *pBufferPointer;
RxDbgTrace( 0, (DEBUG_TRACE_CREATE),
("BuildCanonicalNetRootInformation -- tcstring as unicode %wZ\n", pNetRootName));
pBuffer = ALIGN_SMB_WSTR(pBuffer);
*pBufferSize -= (pBuffer - *pBufferPointer);
*pBufferPointer = pBuffer;
*((PWCHAR)*pBufferPointer) = L'\\';
*pBufferPointer = *pBufferPointer + sizeof(WCHAR);
*pBufferSize -= sizeof(WCHAR);
Status = SmbPutUnicodeStringAndUpcase(pBufferPointer,pNetRootName,pBufferSize);
}
else
{
RxDbgTrace( 0, (DEBUG_TRACE_CREATE), ("BuildCanonicalNetRootInformation -- tcstring as ascii\n"));
*((PCHAR)*pBufferPointer) = '\\';
*pBufferPointer += sizeof(CHAR);
*pBufferSize -= sizeof(CHAR);
Status = SmbPutUnicodeStringAsOemStringAndUpcase(pBufferPointer,pNetRootName,pBufferSize);
}
if (NT_SUCCESS(Status) && fPostPendServiceString)
{
// Put the desired service name in ASCII ( always )
ULONG Length = strlen(s_NetRootTypeName[NetRootType]) + 1;
if (*pBufferSize >= Length) {
RtlCopyMemory(*pBufferPointer,s_NetRootTypeName[NetRootType],Length);
*pBufferSize -= Length;
} else {
Status = STATUS_BUFFER_OVERFLOW;
}
}
return Status;
}
NTSTATUS
CoreBuildTreeConnectSmb(
PSMB_EXCHANGE pExchange,
PGENERIC_ANDX pAndXSmb,
PULONG pAndXSmbBufferSize)
/*++
Routine Description:
This routine builds the tree connect SMB for a pre NT server
Arguments:
pExchange - the exchange instance
pAndXSmb - the tree connect to be filled in...it's not really a andX
pAndXSmbBufferSize - the SMB buffer size on input modified to remaining size on
output.
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
USHORT PasswordLength;
PMRX_NET_ROOT NetRoot;
UNICODE_STRING ServerName;
UNICODE_STRING NetRootName;
PSMBCE_SERVER pServer;
PREQ_TREE_CONNECT pTreeConnect = (PREQ_TREE_CONNECT)pAndXSmb;
ULONG OriginalBufferSize = *pAndXSmbBufferSize;
BOOLEAN AppendServiceString;
PBYTE pBuffer;
PCHAR ServiceName; // = s_NetRootTypeName[NET_ROOT_WILD];
ULONG Length; // = strlen(ServiceName) + 1;
NetRoot = pExchange->SmbCeContext.pVNetRoot->pNetRoot;
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS),
("CoreBuildTreeConnectSmb buffer,remptr %08lx %08lx, nrt=%08lx\n",pAndXSmb,pAndXSmbBufferSize,NetRoot->Type));
pServer = &pExchange->SmbCeContext.pServerEntry->Server;
SmbCeGetServerName(NetRoot->pSrvCall,&ServerName);
SmbCeGetNetRootName(NetRoot,&NetRootName);
ServiceName = s_NetRootTypeName[NetRoot->Type];
Length = strlen(ServiceName) + 1;
pTreeConnect->WordCount = 0;
AppendServiceString = FALSE;
pBuffer = (PBYTE)pTreeConnect + FIELD_OFFSET(REQ_TREE_CONNECT,Buffer);
*pBuffer = 0x04;
pBuffer++;
*pAndXSmbBufferSize -= (FIELD_OFFSET(REQ_TREE_CONNECT,Buffer)+1);
// put in the netname
Status = BuildCanonicalNetRootInformation(
&ServerName,
&NetRootName,
pExchange->SmbCeContext.pVNetRoot->pNetRoot->Type,
(BOOLEAN)(pServer->Dialect >= NTLANMAN_DIALECT),
AppendServiceString,
&pBuffer,
pAndXSmbBufferSize);
if (!NT_SUCCESS(Status))
return Status;
// put in the password
pBuffer = (PBYTE)pTreeConnect + OriginalBufferSize - *pAndXSmbBufferSize;
*pBuffer = 0x04;
pBuffer++;
*pAndXSmbBufferSize -= 1;
if (pServer->SecurityMode == SECURITY_MODE_SHARE_LEVEL)
{
// The password information needs to be sent as part of the tree connect
// SMB for share level servers.
Status = BuildTreeConnectSecurityInformation(
pExchange,
pBuffer,
(PBYTE)&PasswordLength,
pAndXSmbBufferSize);
}
// string in the service string based on the netroot type
pBuffer = (PBYTE)pTreeConnect + OriginalBufferSize - *pAndXSmbBufferSize;
*pBuffer = 0x04;
pBuffer++;
*pAndXSmbBufferSize -= 1;
if (*pAndXSmbBufferSize >= Length) {
RtlCopyMemory(pBuffer,ServiceName,Length);
*pAndXSmbBufferSize -= Length;
} else {
Status = STATUS_BUFFER_OVERFLOW;
}
SmbPutUshort(&pTreeConnect->ByteCount,
(USHORT)(OriginalBufferSize
- *pAndXSmbBufferSize
- FIELD_OFFSET(REQ_TREE_CONNECT,Buffer)
)
);
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("CoreBuildTreeConnectSmb end buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
return Status;
}
NTSTATUS
LmBuildTreeConnectSmb(
PSMB_EXCHANGE pExchange,
PGENERIC_ANDX pAndXSmb,
PULONG pAndXSmbBufferSize)
/*++
Routine Description:
This routine builds the tree connect SMB for a pre NT server
Arguments:
pExchange - the exchange instance
pAndXSmb - the tree connect to be filled in...it's not really a andX
pAndXSmbBufferSize - the SMB buffer size on input modified to remaining size on
output.
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
USHORT PasswordLength;
PMRX_NET_ROOT NetRoot;
UNICODE_STRING ServerName;
UNICODE_STRING NetRootName;
PSMBCE_SERVER pServer;
PREQ_TREE_CONNECT_ANDX pTreeConnectAndX = (PREQ_TREE_CONNECT_ANDX)pAndXSmb;
ULONG OriginalBufferSize = *pAndXSmbBufferSize;
BOOLEAN AppendServiceString;
PBYTE pBuffer;
PCHAR ServiceName;
ULONG Length;
NetRoot = pExchange->SmbCeContext.pVNetRoot->pNetRoot;
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS),
("LmBuildTreeConnectSmb buffer,remptr %08lx %08lx, nrt=%08lx\n",pAndXSmb,pAndXSmbBufferSize,NetRoot->Type));
pServer = &pExchange->SmbCeContext.pServerEntry->Server;
SmbCeGetServerName(NetRoot->pSrvCall,&ServerName);
SmbCeGetNetRootName(NetRoot,&NetRootName);
ServiceName = s_NetRootTypeName[NetRoot->Type];
Length = strlen(ServiceName) + 1;
AppendServiceString = TRUE;
pTreeConnectAndX->WordCount = 4;
SmbPutUshort(&pTreeConnectAndX->AndXReserved,0);
SmbPutUshort(&pTreeConnectAndX->Flags,0);
pBuffer = (PBYTE)pTreeConnectAndX + FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer);
*pAndXSmbBufferSize -= (FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer)+1);
if (pServer->SecurityMode == SECURITY_MODE_SHARE_LEVEL) {
// The password information needs to be sent as part of the tree connect
// SMB for share level servers.
Status = BuildTreeConnectSecurityInformation(
pExchange,
pBuffer,
(PBYTE)&PasswordLength,
pAndXSmbBufferSize);
if (Status == STATUS_SUCCESS) {
pBuffer += PasswordLength;
SmbPutUshort(&pTreeConnectAndX->PasswordLength,PasswordLength);
}
} else {
pBuffer = (PBYTE)pTreeConnectAndX + FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer);
*pAndXSmbBufferSize -= FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer);
// No password is required for user level security servers as part of tree
// connect
SmbPutUshort(&pTreeConnectAndX->PasswordLength,0x1);
*((PCHAR)pBuffer) = '\0';
pBuffer += sizeof(CHAR);
*pAndXSmbBufferSize -= sizeof(CHAR);
Status = STATUS_SUCCESS;
}
if (Status == STATUS_SUCCESS) {
Status = BuildCanonicalNetRootInformation(
&ServerName,
&NetRootName,
pExchange->SmbCeContext.pVNetRoot->pNetRoot->Type,
(BOOLEAN)(pServer->Dialect >= NTLANMAN_DIALECT),
AppendServiceString,
&pBuffer,
pAndXSmbBufferSize);
if (Status == STATUS_SUCCESS) {
SmbPutUshort(&pTreeConnectAndX->ByteCount,
(USHORT)(OriginalBufferSize
- *pAndXSmbBufferSize
- FIELD_OFFSET(REQ_TREE_CONNECT_ANDX,Buffer)
)
);
}
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("LmBuildTreeConnectSmb end buffer,rem %08lx %08lx\n",pBuffer,*pAndXSmbBufferSize));
}
return Status;
}