367 lines
11 KiB
C
367 lines
11 KiB
C
/*++ 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;
|
||
}
|
||
|
||
|
||
|