📄 srvcall.c
字号:
pServer->MaximumRequests = SmbGetUshort(
&pNegotiateResponse->MaxMpxCount );
pServer->MaximumVCs = SmbGetUshort(
&pNegotiateResponse->MaxNumberVcs );
if (pNegotiateResponse->WordCount == 13) {
//CODE.IMPROVEMENT use the DF_bit for this
switch (pServer->Dialect) {
case LANMAN10_DIALECT:
case WFW10_DIALECT:
case LANMAN12_DIALECT:
case LANMAN21_DIALECT:
GetLanmanTimeBias( pServer,pNegotiateResponse );
break;
}
Status = GetLanmanSecurityParameters( pServer,pNegotiateResponse );
}
}
*pBytesTaken = BytesAvailable;
}
break;
case SMB_CORE_NEGOTIATE :
default :
{
// An SMB_CORE_NEGOTIATE response is never partially indicated. The response
// length is ithin the TDI minimum for indication.
pServer->SecurityMode = SECURITY_MODE_SHARE_LEVEL;
pServer->EncryptPasswords = FALSE;
pServer->MaximumBufferSize = 0;
pServer->MaximumRequests = 1;
pServer->MaximumVCs = 1;
pServer->SessionKey = 0;
if (pSmbHeader->Flags & SMB_FLAGS_OPLOCK) {
pServer->DialectFlags |= DF_OPLOCK;
}
*pBytesTaken = BytesAvailable;
ASSERT(BytesIndicated == BytesAvailable);
}
}
if (pServer->MaximumRequests == 0) {
//
// If this is a Lanman 1.0 or better server, this is a invalid negotiate
// response. For others it would have been set to 1.
//
Status = STATUS_INVALID_NETWORK_RESPONSE;
}
if ((Status == STATUS_SUCCESS) ||
(Status == STATUS_MORE_PROCESSING_REQUIRED)) {
// Note that this code relies on the minimum incication size covering
// the negotiate response header.
// Check to make sure that the time zone bias isn't more than +-24
// hours.
//
if ((pServer->TimeZoneBias.QuadPart > s_MaxTimeZoneBias.QuadPart) ||
(-pServer->TimeZoneBias.QuadPart > s_MaxTimeZoneBias.QuadPart)) {
// Set the bias to 0 - assume local time zone.
pServer->TimeZoneBias.LowPart = pServer->TimeZoneBias.HighPart = 0;
}
// Do not allow negotiated buffersize to exceed the size of a USHORT.
// Remove 4096 bytes to avoid overrun and make it easier to handle
// than 0xffff
pServer->MaximumBufferSize =
(pServer->MaximumBufferSize < 0x00010000) ? pServer->MaximumBufferSize :
0x00010000 - 4096;
} else {
pServerEntry->ServerStatus = Status;
*pBytesTaken = BytesAvailable;
}
if ((pServer->DialectFlags & DF_NTNEGOTIATE)!=0) {
InterlockedIncrement(&MRxSmbStatistics.LanmanNtConnects);
} else if ((pServer->DialectFlags & DF_LANMAN21)!=0) {
InterlockedIncrement(&MRxSmbStatistics.Lanman21Connects);
} else if ((pServer->DialectFlags & DF_LANMAN20)!=0) {
InterlockedIncrement(&MRxSmbStatistics.Lanman20Connects);
} else {
InterlockedIncrement(&MRxSmbStatistics.CoreConnects);
}
if ((pServer->Dialect == NTLANMAN_DIALECT) &&
!pServer->EncryptPasswords) {
// Encrypted password is required on NTLANMAN
pServer->Dialect = LANMAN21_DIALECT;
}
return Status;
}
NTSTATUS
GetNTSecurityParameters(
PSMB_ADMIN_EXCHANGE pSmbAdminExchange,
PSMBCE_SERVER pServer,
PUNICODE_STRING pDomainName,
PRESP_NT_NEGOTIATE pNtNegotiateResponse,
ULONG BytesIndicated,
ULONG BytesAvailable,
PULONG pBytesTaken,
PMDL *pDataBufferPointer,
PULONG pDataSize)
/*++
Routine Description:
This routine extracts the security parameters from an NT server
Arguments:
pServer - the server
pDomainName - the domain name
pNtNegotiateResponse - the response
NegotiateResponseLength - size of the negotiate response
Return Value:
STATUS_SUCCESS - implies that pServer is a valid instnace .
Other Status codes correspond to error situations.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
USHORT ByteCount;
PUSHORT pByteCountInSmb =
((PUSHORT)((PUCHAR) pNtNegotiateResponse + 1)) +
pNtNegotiateResponse->WordCount;
PUCHAR pBuffer = (PUCHAR)(pByteCountInSmb + 1);
*pBytesTaken += FIELD_OFFSET(RESP_NT_NEGOTIATE,Buffer);
ByteCount = SmbGetUshort(pByteCountInSmb);
pServer->SecurityMode = (((pNtNegotiateResponse->SecurityMode & NEGOTIATE_USER_SECURITY) != 0)
? SECURITY_MODE_USER_LEVEL
: SECURITY_MODE_SHARE_LEVEL);
pServer->EncryptPasswords = ((pNtNegotiateResponse->SecurityMode & NEGOTIATE_ENCRYPT_PASSWORDS) != 0);
pServer->EncryptionKeyLength = 0;
*pBytesTaken = BytesAvailable;
pServer->SessionKey = SmbGetUlong( &pNtNegotiateResponse->SessionKey );
if (pServer->EncryptPasswords) {
pServer->EncryptionKeyLength = pNtNegotiateResponse->EncryptionKeyLength;
if (pServer->EncryptionKeyLength != 0) {
ASSERT( CRYPT_TXT_LEN == MSV1_0_CHALLENGE_LENGTH );
if (pServer->EncryptionKeyLength != CRYPT_TXT_LEN) {
Status = STATUS_INVALID_NETWORK_RESPONSE;
} else {
RtlCopyMemory(
pServer->EncryptionKey,
pBuffer,
pServer->EncryptionKeyLength );
if (ByteCount - pServer->EncryptionKeyLength > 0) {
ASSERT((pDomainName->Buffer != NULL) &&
(pDomainName->MaximumLength >= (ByteCount - pServer->EncryptionKeyLength)));
pBuffer = pBuffer + pServer->EncryptionKeyLength;
pDomainName->Length = ByteCount - pServer->EncryptionKeyLength;
if (pDomainName->Length & 1) {
// The remainder of the length is odd. This implies that the server did
// some alignment.
pBuffer++;
pDomainName->Length -= 1;
}
RtlCopyMemory(
pDomainName->Buffer,
pBuffer,
pDomainName->Length);
}
}
}
}
return Status;
}
NTSTATUS
GetLanmanSecurityParameters(
PSMBCE_SERVER pServer,
PRESP_NEGOTIATE pNegotiateResponse)
/*++
Routine Description:
This routine extracts the security parameters from a LANMAN server
Arguments:
pServer - the server
pNtNegotiateResponse - the response
Return Value:
STATUS_SUCCESS - implies that pServer is a valid instnace .
Other Status codes correspond to error situations.
--*/
{
USHORT i;
USHORT SecurityMode;
pServer->SessionKey = SmbGetUlong( &pNegotiateResponse->SessionKey );
SecurityMode = SmbGetUshort( &pNegotiateResponse->SecurityMode );
pServer->SecurityMode = (((SecurityMode & 1) != 0)
? SECURITY_MODE_USER_LEVEL
: SECURITY_MODE_SHARE_LEVEL);
pServer->EncryptPasswords = ((SecurityMode & 2) != 0);
if (pServer->EncryptPasswords) {
if (pServer->Dialect == LANMAN21_DIALECT) {
pServer->EncryptionKeyLength = SmbGetUshort(&pNegotiateResponse->EncryptionKeyLength);
} else {
pServer->EncryptionKeyLength = SmbGetUshort(&pNegotiateResponse->ByteCount);
}
if (pServer->EncryptionKeyLength != 0) {
if (pServer->EncryptionKeyLength > CRYPT_TXT_LEN) {
return( STATUS_INVALID_NETWORK_RESPONSE );
}
for (i = 0; i < pServer->EncryptionKeyLength; i++) {
pServer->EncryptionKey[i] = pNegotiateResponse->Buffer[i];
}
}
}
return( STATUS_SUCCESS );
}
LARGE_INTEGER
ConvertSmbTimeToTime (
IN SMB_TIME Time,
IN SMB_DATE Date
)
/*++
Routine Description:
This routine converts an SMB time to an NT time structure.
Arguments:
IN SMB_TIME Time - Supplies the time of day to convert
IN SMB_DATE Date - Supplies the day of the year to convert
IN PSERVERLISTENTRY Server - if supplied, supplies the server for tz bias.
Return Value:
LARGE_INTEGER - Time structure describing input time.
--*/
{
TIME_FIELDS TimeFields;
LARGE_INTEGER OutputTime;
//
// This routine cannot be paged because it is called from both the
// RdrFileDiscardableSection and the RdrVCDiscardableSection.
//
if (SmbIsTimeZero(&Date) && SmbIsTimeZero(&Time)) {
OutputTime.LowPart = OutputTime.HighPart = 0;
} else {
TimeFields.Year = Date.Struct.Year + (USHORT )1980;
TimeFields.Month = Date.Struct.Month;
TimeFields.Day = Date.Struct.Day;
TimeFields.Hour = Time.Struct.Hours;
TimeFields.Minute = Time.Struct.Minutes;
TimeFields.Second = Time.Struct.TwoSeconds*(USHORT )2;
TimeFields.Milliseconds = 0;
//
// Make sure that the times specified in the SMB are reasonable
// before converting them.
//
if (TimeFields.Year < 1601) {
TimeFields.Year = 1601;
}
if (TimeFields.Month > 12) {
TimeFields.Month = 12;
}
if (TimeFields.Hour >= 24) {
TimeFields.Hour = 23;
}
if (TimeFields.Minute >= 60) {
TimeFields.Minute = 59;
}
if (TimeFields.Second >= 60) {
TimeFields.Second = 59;
}
if (!RtlTimeFieldsToTime(&TimeFields, &OutputTime)) {
OutputTime.HighPart = 0;
OutputTime.LowPart = 0;
return OutputTime;
}
ExLocalTimeToSystemTime(&OutputTime, &OutputTime);
}
return OutputTime;
}
VOID
GetLanmanTimeBias(
PSMBCE_SERVER pServer,
PRESP_NEGOTIATE pNegotiateResponse)
/*++
Routine Description:
This routine extracts the time bias from a Lanman server
Arguments:
pServer - the server
pNtNegotiateResponse - the response
Return Value:
STATUS_SUCCESS - implies that pServer is a valid instnace .
Other Status codes correspond to error situations.
--*/
{
// If this is a LM 1.0 or 2.0 server (ie a non NT server), we
// remember the timezone and bias our time based on this value.
//
// The redirector assumes that all times from these servers are
// local time for the server, and converts them to local time
// using this bias. It then tells the user the local time for
// the file on the server.
LARGE_INTEGER Workspace, ServerTime, CurrentTime;
BOOLEAN Negated = FALSE;
SMB_TIME SmbServerTime;
SMB_DATE SmbServerDate;
SmbMoveTime(&SmbServerTime, &pNegotiateResponse->ServerTime);
SmbMoveDate(&SmbServerDate, &pNegotiateResponse->ServerDate);
ServerTime = ConvertSmbTimeToTime(SmbServerTime, SmbServerDate);
KeQuerySystemTime(&CurrentTime);
Workspace.QuadPart = CurrentTime.QuadPart - ServerTime.QuadPart;
if ( Workspace.HighPart < 0) {
// avoid using -ve large integers to routines that accept only unsigned
Workspace.QuadPart = -Workspace.QuadPart;
Negated = TRUE;
}
//
// Workspace has the exact difference in 100ns intervals
// between the server and redirector times. To remove the minor
// difference between the time settings on the two machines we
// round the Bias to the nearest 30 minutes.
//
// Calculate ((exact bias+15minutes)/30minutes)* 30minutes
// then convert back to the bias time.
//
Workspace.QuadPart += ((LONGLONG) ONE_MINUTE_IN_TIME) * 15;
// Workspace is now exact bias + 15 minutes in 100ns units
Workspace.QuadPart /= ((LONGLONG) ONE_MINUTE_IN_TIME) * 30;
pServer->TimeZoneBias.QuadPart = Workspace.QuadPart * ((LONGLONG) ONE_MINUTE_IN_TIME) * 30;
if ( Negated == TRUE ) {
pServer->TimeZoneBias.QuadPart = -pServer->TimeZoneBias.QuadPart;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -