⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srvcall.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 3 页
字号:

                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 + -