📄 srvcall.c
字号:
pReqEcho->WordCount = 1;
RtlMoveMemory( pReqEcho->Buffer, s_EchoData, sizeof( s_EchoData ) );
SmbPutUshort(&pReqEcho->EchoCount, SMB_ECHO_COUNT);
SmbPutUshort(&pReqEcho->ByteCount, (USHORT) sizeof( s_EchoData ) );
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return Status;
}
VOID
MRxSmbTearDownEchoProbeService(
PMRXSMB_ECHO_PROBE_SERVICE_CONTEXT pEchoProbeContext)
/*++
Routine Description:
This routine tears down the echo processing context
--*/
{
PAGED_CODE();
if (pEchoProbeContext->pEchoSmb != NULL) {
RxFreePool(pEchoProbeContext->pEchoSmb);
pEchoProbeContext->pEchoSmb = NULL;
}
}
NTSTATUS
BuildNegotiateSmb(
PVOID *pSmbBufferPointer,
PULONG pSmbBufferLength)
/*++
Routine Description:
This routine builds the negotiate SMB
Arguments:
pSmbBufferPointer - a placeholder for the smb buffer
pNegotiateSmbLength - the smb buffer size
Return Value:
STATUS_SUCCESS - implies that pServer is a valid instnace .
Other Status codes correspond to error situations.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG DialectIndex;
PSMB_HEADER pSmbHeader = NULL;
PREQ_NEGOTIATE pReqNegotiate = NULL;
PAGED_CODE();
if (s_pNegotiateSmb == NULL) {
s_NegotiateSmbLength = sizeof(SMB_HEADER) +
FIELD_OFFSET(REQ_NEGOTIATE,Buffer) +
sizeof(s_DialectNames);
s_pNegotiateSmb = (PBYTE)RxAllocatePoolWithTag(
PagedPool,
s_NegotiateSmbLength + TRANSPORT_HEADER_SIZE,
MRXSMB_ADMIN_POOLTAG);
if (s_pNegotiateSmb != NULL) {
s_pNegotiateSmb += TRANSPORT_HEADER_SIZE;
pSmbHeader = (PSMB_HEADER)s_pNegotiateSmb;
pReqNegotiate = (PREQ_NEGOTIATE)(s_pNegotiateSmb + sizeof(SMB_HEADER));
// Fill in the header
RtlZeroMemory( pSmbHeader, sizeof( SMB_HEADER ) );
*(PULONG)(&pSmbHeader->Protocol) = (ULONG)SMB_HEADER_PROTOCOL;
// By default, paths in SMBs are marked as case insensitive and
// canonicalized.
pSmbHeader->Flags =
SMB_FLAGS_CASE_INSENSITIVE | SMB_FLAGS_CANONICALIZED_PATHS;
// Put our flags2 field. The Ox10 is a temporary flag for SLM
// corruption detection
SmbPutAlignedUshort(
&pSmbHeader->Flags2,
(SMB_FLAGS2_KNOWS_LONG_NAMES
| SMB_FLAGS2_KNOWS_EAS
| SMB_FLAGS2_IS_LONG_NAME
| SMB_FLAGS2_NT_STATUS
| SMB_FLAGS2_UNICODE
));
// Fill in the process id.
SmbPutUshort( &pSmbHeader->Pid, MRXSMB_PROCESS_ID );
// Lastly, fill in the smb command code.
pSmbHeader->Command = (UCHAR) SMB_COM_NEGOTIATE;
pReqNegotiate->WordCount = 0;
RtlMoveMemory(
pReqNegotiate->Buffer,
s_DialectNames,
sizeof( s_DialectNames ) );
SmbPutUshort(
&pReqNegotiate->ByteCount,
(USHORT) sizeof( s_DialectNames ) );
// Initialize the maximum time zone bias used in negotiate response parsing.
s_MaxTimeZoneBias.QuadPart = Int32x32To64(24*60*60,1000*10000);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (NT_SUCCESS(Status)) {
*pSmbBufferLength = s_NegotiateSmbLength;
*pSmbBufferPointer = s_pNegotiateSmb;
}
return Status;
}
ULONG MRxSmbSrvWriteBufSize = 0xffff; //use the negotiated size
NTSTATUS
ParseNegotiateResponse(
IN OUT PSMB_ADMIN_EXCHANGE pSmbAdminExchange,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT PULONG pBytesTaken,
IN PSMB_HEADER pSmbHeader,
OUT PMDL *pDataBufferPointer,
OUT PULONG pDataSize)
/*++
Routine Description:
This routine parses the response from the server
Arguments:
pServer - the server instance
pDomainName - the domain name string to be extracted from the response
pSmbHeader - the response SMB
BytesAvailable - length of the response
pBytesTaken - response consumed
Return Value:
STATUS_SUCCESS - the server call construction has been finalized.
Other Status codes correspond to error situations.
Notes:
The SMB servers can speak a variety of dialects of the SMB protocol. The initial
negotiate response can come in one of three possible flavours. Either we get the
NT negotiate response SMB from a NT server or the extended response from DOS and
OS/2 servers or the CORE response from other servers.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PSMBCE_SERVER pServer;
PUNICODE_STRING pDomainName;
USHORT DialectIndex;
PRESP_NEGOTIATE pNegotiateResponse;
ULONG NegotiateSmbLength;
ASSERT( pSmbHeader != NULL );
pServerEntry = SmbCeGetExchangeServerEntry(pSmbAdminExchange);
pServer = &pServerEntry->Server;
pDomainName = &pSmbAdminExchange->Negotiate.DomainName;
pNegotiateResponse = (PRESP_NEGOTIATE) (pSmbHeader + 1);
NegotiateSmbLength = sizeof(SMB_HEADER);
*pBytesTaken = NegotiateSmbLength;
// Assume that the indicated response is sufficient.
// The TDI imposed minimum of 128 bytes subsumes the negotiate response.
*pDataBufferPointer = NULL;
*pDataSize = 0;
DialectIndex = SmbGetUshort( &pNegotiateResponse->DialectIndex );
if (DialectIndex == (USHORT) -1) {
// means server cannot accept any requests from
*pBytesTaken = BytesAvailable;
pServerEntry->ServerStatus = STATUS_REQUEST_NOT_ACCEPTED;
return Status;
}
if (pNegotiateResponse->WordCount < 1 || DialectIndex > s_NumberOfDialects) {
*pBytesTaken = BytesAvailable;
pServerEntry->ServerStatus = STATUS_INVALID_NETWORK_RESPONSE;
return Status;
}
// set the domain name length to zero ( default initialization )
pDomainName->Length = 0;
// Fix up the dialect type and the corresponding dispatch vector.
pServer->Dialect = (SMB_DIALECT)DialectIndex;
pServer->DialectFlags = MRxSmbDialectFlags[DialectIndex];
pServer->pDispatch = &s_SmbServerDispatchVectors[s_SmbDialects[DialectIndex].DispatchVectorIndex];
// Parse the response based upon the type of negotiate response expected.
switch (s_SmbDialects[DialectIndex].NegotiateType) {
case SMB_NT_NEGOTIATE:
{
ULONG NegotiateResponseLength;
LARGE_INTEGER ZeroTime;
LARGE_INTEGER LocalTimeBias;
LARGE_INTEGER ServerTimeBias;
PRESP_NT_NEGOTIATE pNtNegotiateResponse = (PRESP_NT_NEGOTIATE) pNegotiateResponse;
ASSERT(BytesAvailable > sizeof(RESP_NT_NEGOTIATE));
if (pNtNegotiateResponse->WordCount != 17) {
*pBytesTaken = BytesAvailable;
Status = STATUS_INVALID_NETWORK_RESPONSE;
} else {
// parse and map the capabilities.
ULONG NtCapabilities;
NegotiateResponseLength = FIELD_OFFSET(RESP_NT_NEGOTIATE,Buffer) +
SmbGetUshort(&pNtNegotiateResponse->ByteCount);
NegotiateSmbLength += NegotiateResponseLength;
//Start with a clean slate
pServer->Capabilities = 0;
// Initialize server based constants
pServer->MaximumRequests = SmbGetUshort( &pNtNegotiateResponse->MaxMpxCount );
pServer->MaximumVCs = SmbGetUshort( &pNtNegotiateResponse->MaxNumberVcs );
pServer->MaximumBufferSize = SmbGetUlong( &pNtNegotiateResponse->MaxBufferSize );
NtCapabilities = pServer->NtServer.NtCapabilities = SmbGetUlong(&pNtNegotiateResponse->Capabilities);
if (NtCapabilities & CAP_RAW_MODE) {
pServer->Capabilities |= (RAW_READ_CAPABILITY | RAW_WRITE_CAPABILITY);
}
if (NtCapabilities & CAP_DFS) {
pServer->Capabilities |= CAP_DFS;
}
//copy other nt capabilities into the dialog flags
if (NtCapabilities & CAP_UNICODE) {
pServer->DialectFlags |= DF_UNICODE;
}
if (NtCapabilities & CAP_LARGE_FILES) {
pServer->DialectFlags |= DF_LARGE_FILES;
}
if (NtCapabilities & CAP_NT_SMBS) {
pServer->DialectFlags |= DF_NT_SMBS | DF_NT_FIND;
}
if (NtCapabilities & CAP_NT_FIND) {
pServer->DialectFlags |= DF_NT_FIND;
}
if (NtCapabilities & CAP_RPC_REMOTE_APIS) {
pServer->DialectFlags |= DF_RPC_REMOTE;
}
if (NtCapabilities & CAP_NT_STATUS) {
pServer->DialectFlags |= DF_NT_STATUS;
}
if (NtCapabilities & CAP_LEVEL_II_OPLOCKS) {
pServer->DialectFlags |= DF_OPLOCK_LVL2;
}
if (NtCapabilities & CAP_LOCK_AND_READ) {
pServer->DialectFlags |= DF_LOCKREAD;
}
if (NtCapabilities & CAP_INFOLEVEL_PASSTHRU) {
pServer->DialectFlags |= DF_NT_INFO_PASSTHROUGH;
}
// For non disk files the LARGE_READX capability is not useful.
pServer->MaximumNonDiskFileReadBufferSize =
pServer->MaximumBufferSize -
QuadAlign(
sizeof(SMB_HEADER) +
FIELD_OFFSET(
REQ_NT_READ_ANDX,
Buffer[0]));
if (NtCapabilities & CAP_LARGE_READX) {
if (NtCapabilities & CAP_LARGE_WRITEX) {
pServer->MaximumDiskFileReadBufferSize = 60*1024;
} else {
// The maximum size for reads to servers which support
// large read and x is constrained by the USHORT to record
// lengths in the SMB. Thus the maximum length that can be used
// is (65536 - 1) . This length should accomodate the header as
// well as the rest of the SMB. Actually, tho, we cut back to 60K.
pServer->MaximumDiskFileReadBufferSize = 60*1024;
}
} else {
pServer->MaximumDiskFileReadBufferSize = pServer->MaximumNonDiskFileReadBufferSize;
}
// Specifying a zero local time will give you the time zone bias
ZeroTime.HighPart = ZeroTime.LowPart = 0;
ExLocalTimeToSystemTime( &ZeroTime, &LocalTimeBias );
ServerTimeBias = RtlEnlargedIntegerMultiply(
(LONG)SmbGetUshort(
&pNtNegotiateResponse->ServerTimeZone),
ONE_MINUTE_IN_TIME );
pServer->TimeZoneBias.QuadPart = ServerTimeBias.QuadPart -
LocalTimeBias.QuadPart;
if (!FlagOn(pServer->DialectFlags,DF_NT_SMBS)) {
//sigh...........
pServer->DialectFlags &= ~(DF_MIXEDCASEPW);
pServer->DialectFlags |= DF_W95;
}
Status = GetNTSecurityParameters(
pSmbAdminExchange,
pServer,
pDomainName,
pNtNegotiateResponse,
BytesIndicated,
BytesAvailable,
pBytesTaken,
pDataBufferPointer,
pDataSize);
pServer->MaximumNonDiskFileWriteBufferSize =
min(
MRxSmbSrvWriteBufSize,
pServer->MaximumBufferSize -
QuadAlign(
sizeof(SMB_HEADER) +
FIELD_OFFSET(
REQ_NT_WRITE_ANDX,
Buffer[0])));
if (NtCapabilities & CAP_LARGE_WRITEX) {
pServer->DialectFlags |= DF_LARGE_WRITEX;
pServer->MaximumDiskFileWriteBufferSize = 0x10000;
} else {
pServer->MaximumDiskFileWriteBufferSize =
pServer->MaximumNonDiskFileWriteBufferSize;
}
}
}
break;
case SMB_EXTENDED_NEGOTIATE :
{
// An SMB_EXTENDED_NEGOTIATE response is never partially indicated. The response
// length is ithin the TDI minimum for indication.
USHORT RawMode;
// DOS or OS2 server
if (pNegotiateResponse->WordCount != 13 &&
pNegotiateResponse->WordCount != 10 &&
pNegotiateResponse->WordCount != 8) {
Status = STATUS_INVALID_NETWORK_RESPONSE;
} else {
NegotiateSmbLength += FIELD_OFFSET(RESP_NEGOTIATE,Buffer) +
SmbGetUshort(&pNegotiateResponse->ByteCount);
ASSERT(
(BytesIndicated >= NegotiateSmbLength) &&
(BytesIndicated == BytesAvailable));
RawMode = SmbGetUshort( &pNegotiateResponse->RawMode );
pServer->Capabilities |= ((RawMode & 0x1) != 0
? RAW_READ_CAPABILITY : 0);
pServer->Capabilities |= ((RawMode & 0x2) != 0
? RAW_WRITE_CAPABILITY : 0);
if (pSmbHeader->Flags & SMB_FLAGS_LOCK_AND_READ_OK) {
pServer->DialectFlags |= DF_LOCKREAD;
}
pServer->EncryptPasswords = FALSE;
pServer->MaximumVCs = 1;
pServer->MaximumBufferSize = SmbGetUshort( &pNegotiateResponse->MaxBufferSize );
pServer->MaximumDiskFileReadBufferSize =
pServer->MaximumBufferSize -
QuadAlign(
sizeof(SMB_HEADER) +
FIELD_OFFSET(
RESP_READ_ANDX,
Buffer[0]));
pServer->MaximumNonDiskFileReadBufferSize = pServer->MaximumDiskFileReadBufferSize;
pServer->MaximumDiskFileWriteBufferSize = pServer->MaximumDiskFileReadBufferSize;
pServer->MaximumNonDiskFileWriteBufferSize = pServer->MaximumDiskFileReadBufferSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -