|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
smbce.h
Abstract:
This module defines all functions, along with implementations for inline functions related to accessing the SMB connection engine
Revision History:
Balan Sethu Raman [SethuR] 6-March-1995
--*/
#ifndef _SMBCE_H_
#define _SMBCE_H_
#define SECURITY_KERNEL
#define SECURITY_NTLM
#include "security.h"
#include "secint.h"
#include "md5.h"
//
// Flag to enable/disable double buffering on exchanges with security signatures.
//
#define SMBCE_NO_DOUBLE_BUFFERING 0x80000000
//
// The SMB protocol has a number of dialects. These reflect the extensions made
// to the core protocol over a period of time to cater to increasingly sophisticated
// file systems. The connection engine must be capable of dealing with different
// dialects implemented by server. The underlying Transport mechanism is used to
// uniquely identify the file server and the SMB protocol furnishes the remaining
// identification information to uniquely map an SMB onto a particular file opened by
// a particular client. The three important pieces of information are the SMB_TREE_ID,
// SMB_FILE_ID and SMB_USER_ID. These identify the particular connection made by a
// client machine, the particular file opened on that connection, and the user on
// behalf of whom the file has been opened. Note that there could be multiple
// connections from a client machine to a server machine. Therefore the unique id. is
// really connection based rather than machine based. The SMB connection engine
// data structures are built around these concepts.
//
// The known SMB dialects are as follows.
//
typedef enum _SMB_DIALECT_ { PCNET1_DIALECT, //XENIXCORE_DIALECT,
//MSNET103_DIALECT,
LANMAN10_DIALECT, WFW10_DIALECT, LANMAN12_DIALECT, LANMAN21_DIALECT, NTLANMAN_DIALECT } SMB_DIALECT, *PSMB_DIALECT;
#define NET_ROOT_FILESYSTEM_UNKOWN ((UCHAR)0)
#define NET_ROOT_FILESYSTEM_FAT ((UCHAR)1)
#define NET_ROOT_FILESYSTEM_NTFS ((UCHAR)2)
typedef UCHAR NET_ROOT_FILESYSTEM, *PNET_ROOT_FILESYSTEM;
//
// The SMBCE_NET_ROOT encapsulates the information pertaining to a share on a server.
//
//we restrict to the first 7 characters (HPFS386)
#define SMB_MAXIMUM_SUPPORTED_VOLUME_LABEL 7
#define MaximumNumberOfVNetRootContextsForScavenging 10
typedef struct _SMBCE_NET_ROOT_ { BOOLEAN DfsAware;
NET_ROOT_TYPE NetRootType; NET_ROOT_FILESYSTEM NetRootFileSystem;
SMB_USER_ID UserId;
ULONG MaximumReadBufferSize; ULONG MaximumWriteBufferSize;
LIST_ENTRY ClusterSizeSerializationQueue;
ULONG FileSystemAttributes;
LONG MaximumComponentNameLength;
USHORT CompressionFormatAndEngine; UCHAR CompressionUnitShift; UCHAR ChunkShift; UCHAR ClusterShift;
ULONG ChunkSize;
//CSC Stuff
CSC_ROOT_INFO sCscRootInfo;
ULONG CachedNumberOfSrvOpens;
BOOLEAN CscEnabled; //this, if we are to automatically build shadows
BOOLEAN CscShadowable; //this, if we are allowed to build shadows
USHORT CscFlags; // CSC flags as returned by the server
BOOLEAN UpdateCscShareRights; // indication to update share rights on the CSC database
BOOLEAN Disconnected;
LIST_ENTRY DirNotifyList; // head of a list of notify Irps.
PNOTIFY_SYNC pNotifySync; // used to synchronize the dir notify list.
LIST_ENTRY NotifyeeFobxList; // list of fobx's given to the fsrtl structure
FAST_MUTEX NotifyeeFobxListMutex;
union { struct { USHORT FileSystemNameLength; WCHAR FileSystemName[SMB_MAXIMUM_SUPPORTED_VOLUME_LABEL]; }; struct { USHORT Pad2; UCHAR FileSystemNameALength; UCHAR FileSystemNameA[SMB_MAXIMUM_SUPPORTED_VOLUME_LABEL]; UCHAR Pad; //this field is used for a null in a dbgprint; don't move it
}; };
//ULONG ClusterSize;
} SMBCE_NET_ROOT, *PSMBCE_NET_ROOT;
//
// There are two levels of security in the SMB protocol. User level security and Share level
// security. Corresponding to each user in the user level security mode there is a session.
//
// Typically the password, user name and domain name strings associated with the session entry
// revert to the default values, i.e., they are zero. In the event that they are not zero the
// SessionString represents a concatenated version of the password,user name and domain name in
// that order. This representation in a concatenated way yields us a savings of atleast 3
// USHORT's over other representations.
//
typedef enum _SECURITY_MODE_ { SECURITY_MODE_SHARE_LEVEL = 0, SECURITY_MODE_USER_LEVEL = 1 } SECURITY_MODE, *PSECURITY_MODE;
#define SMBCE_SHARE_LEVEL_SERVER_USERID 0xffffffff
typedef enum _SESSION_TYPE_ { UNINITIALIZED_SESSION, LANMAN_SESSION, EXTENDED_NT_SESSION } SESSION_TYPE, *PSESSION_TYPE;
typedef enum _SMB_SESSION_KEY_STATE { SmbSessionKeyUnavailible = 0, SmbSessionKeyAuthenticating, SmbSessionKeyAvailible } SMB_SESSION_KEY_STATE;
#define SMBCE_SESSION_FLAGS_LANMAN_SESSION_KEY_USED (0x002)
#define SMBCE_SESSION_FLAGS_NULL_CREDENTIALS (0x004)
#define SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION (0x008)
#define SMBCE_SESSION_FLAGS_GUEST_SESSION (0x010)
#define SMBCE_SESSION_FLAGS_LOGGED_OFF (0x020)
#define SMBCE_SESSION_FLAGS_MARKED_FOR_DELETION (0x040)
#define SMBCE_SESSION_FLAGS_SECSIG_ENABLED (0x080)
#define SMBCE_SESSION_FLAGS_SESSION_KEY_HASHED (0x100)
typedef struct _SMBCE_SESSION_ { SESSION_TYPE Type; SMB_USER_ID UserId;
// Flags associated with the session.
ULONG Flags;
LUID LogonId; PUNICODE_STRING pUserName; PUNICODE_STRING pPassword; PUNICODE_STRING pUserDomainName;
SMB_SESSION_KEY_STATE SessionKeyState; UCHAR UserSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH]; UCHAR UserNewSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH]; UCHAR LanmanSessionKey[MSV1_0_LANMAN_SESSION_KEY_LENGTH];
// The credential and context handles.
CtxtHandle SecurityContextHandle; CredHandle CredentialHandle; ULONG SessionId; ULONG SessionKeyLength;
ULONG NumberOfActiveVNetRoot; ULONG TargetInfoLength; PUSHORT TargetInfoMarshalled; } SMBCE_SESSION, *PSMBCE_SESSION;
extern VOID UninitializeSecurityContextsForSession(PSMBCE_SESSION pSession);
extern VOID DeleteSecurityContextForSession(PSMBCE_SESSION pSession);
//
// SMBCE_*_SERVER -- This data structure encapsulates all the information related to a server.
// Since there are multiple dialects of the SMB protocol, the capabilities as well as the
// actions that need to be taken at the client machine are very different.
//
// Owing to the number of dialects of the SMB protocol we have two design possibilities.
// Either we define an all encompassing data structure and have a code path that
// uses the dialect and the capabilities of the connection to determine the action
// required, or we use a subclassing mechanism associated with a dispatch vector.
// The advantage of the second mechanism is that it can be developed incrementally and
// it is very easily extensible. The disadvantage of this mechanism is that it can
// lead to a very large footprint, if sufficient care is not exercised during
// factorization and we could have lots and lots of procedure calls which has an
// adverse effect on the code generated.
//
// We will adopt the second approach ( Thereby implicitly defining the metrics by
// which the code should be evaluated !! ).
//
// The types of SMBCE_SERVER's can be classified in the following hierarchy
//
// SMBCE_SERVER
//
// SMBCE_USER_LEVEL_SERVER
//
// SMBCE_NT_SERVER
//
// SMBCE_SHARE_LEVEL_SERVER
//
// The dispatch vector which defines the set of methods supported by all the connections
// (virtual functions in C++ terminology) are as follows
//
#define RAW_READ_CAPABILITY 0x0001
#define RAW_WRITE_CAPABILITY 0x0002
#define LWIO_CAPABILITY 0x0004
#define COMPRESSED_DATA_CAPABILITY 0x0008
#define ECHO_PROBE_IDLE 0x1
#define ECHO_PROBE_AWAITING_RESPONSE 0x2
#define CRYPT_TEXT_LEN MSV1_0_CHALLENGE_LENGTH
typedef struct _NTLANMAN_SERVER_ { ULONG NtCapabilities; GUID ServerGuid; ULONG SecurityBlobLength; PVOID pSecurityBlob; } NTLANMAN_SERVER, *PNTLANMAN_SERVER;
typedef struct _SMBCE_SERVER_ { // the server version count
ULONG Version;
// the dispatch vector
struct _SMBCE_SERVER_DISPATCH_VECTOR_ *pDispatch;
// the SMB dialect
SMB_DIALECT Dialect;
// More Server Capabilities
ULONG DialectFlags;
// the session key
ULONG SessionKey;
// the server Ip address
ULONG IpAddress;
// Security mode supported on the server
SECURITY_MODE SecurityMode;
// Time zone bias for conversion.
LARGE_INTEGER TimeZoneBias;
// Echo Expiry Time
LARGE_INTEGER EchoExpiryTime;
LONG SmbsReceivedSinceLastStrobe;
//CSC stuff
LONG CscState;
LONG EchoProbeState; LONG NumberOfEchoProbesSent;
// Maximum negotiated buffer size.
ULONG MaximumBufferSize;
// maximum buffer size for read/write operations
ULONG MaximumDiskFileReadBufferSize; ULONG MaximumNonDiskFileReadBufferSize; ULONG MaximumDiskFileWriteBufferSize; ULONG MaximumNonDiskFileWriteBufferSize;
// This is used to detect the number of server opens. If it is larger than 0,
// we shouldn't tear down the current transport in case the user provides the transport.
LONG NumberOfSrvOpens;
LONG NumberOfVNetRootContextsForScavenging;
LONG MidCounter;
// Maximum number of multiplexed requests
USHORT MaximumRequests;
// Maximum number of VC's
USHORT MaximumVCs;
// Server Capabilities
USHORT Capabilities;
// encrypt passwords
BOOLEAN EncryptPasswords;
BOOLEAN SecuritySignaturesEnabled;
BOOLEAN SecuritySignaturesRequired;
// distinguishes a loopback connections
BOOLEAN IsLoopBack;
// TRUE if the same server is being referred to by multiple names
BOOLEAN AliasedServers;
BOOLEAN IsRemoteBootServer;
// There are certain servers that return DF_NT_SMBS in the negotiate
// but do not support change notifies. This allows us to suppress
// change notify requests to those servers.
BOOLEAN ChangeNotifyNotSupported;
// avoid multiple event logs posted for security context failures
BOOLEAN EventLogPosted;
// The sessions on this server should use the extended timeout interval
BOOLEAN ExtendedSessTimeout;
USHORT EncryptionKeyLength; UCHAR EncryptionKey[CRYPT_TEXT_LEN];
// Dialect specific information
union { NTLANMAN_SERVER NtServer; };
MD5_CTX SmbSecuritySignatureIntermediateContext; ULONG SmbSecuritySignatureIndex;
BOOLEAN IsFakeDfsServerForOfflineUse; BOOLEAN IsPinnedOffline;
} SMBCE_SERVER, *PSMBCE_SERVER;
typedef NTSTATUS (*PBUILD_SESSION_SETUP_SMB)( IN OUT struct _SMB_EXCHANGE *pExchange, IN OUT PGENERIC_ANDX pSmb, IN OUT PULONG pBufferSize );
typedef NTSTATUS (*PBUILD_TREE_CONNECT_SMB)( IN OUT struct _SMB_EXCHANGE *pExchange, IN OUT PGENERIC_ANDX pSmb, IN OUT PULONG pBufferSize );
typedef struct _SMBCE_SERVER_DISPATCH_VECTOR_ { PBUILD_SESSION_SETUP_SMB BuildSessionSetup; PBUILD_TREE_CONNECT_SMB BuildTreeConnect; } SMBCE_SERVER_DISPATCH_VECTOR, *PSMBCE_SERVER_DISPATCH_VECTOR;
#define SMBCE_SERVER_DIALECT_DISPATCH(pServer,Routine,Arguments) \
(*((pServer)->pDispatch->Routine))##Arguments
// The SMBCE engine process all requests in an asychronous fashion. Therefore for synchronous
// requests an additional mechanism is required for synchronization. The following data structure
// provides an easy way for implementing this synchronization.
//
// NOTE: For asynchronous resumption contexts the resumption routine can be invoked
// at DPC level.
#define SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS (0x1)
typedef struct SMBCE_RESUMPTION_CONTEXT { ULONG Flags; NTSTATUS Status; // the status
PVOID pContext; // a void pointer for clients to add additional context information
union { PRX_WORKERTHREAD_ROUTINE pRoutine; // asynchronous contexts
KEVENT Event; // the event for synchronization
}; BOOLEAN SecuritySignatureReturned; } SMBCE_RESUMPTION_CONTEXT, *PSMBCE_RESUMPTION_CONTEXT;
#define SmbCeIsResumptionContextAsynchronous(pResumptionContext) \
((pResumptionContext)->Flags & SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS)
INLINE VOID SmbCeInitializeResumptionContext( PSMBCE_RESUMPTION_CONTEXT pResumptionContext) { KeInitializeEvent(&(pResumptionContext)->Event,NotificationEvent,FALSE); pResumptionContext->Status = STATUS_SUCCESS; pResumptionContext->Flags = 0; pResumptionContext->pContext = NULL; }
INLINE VOID SmbCeInitializeAsynchronousResumptionContext( PSMBCE_RESUMPTION_CONTEXT pResumptionContext, PRX_WORKERTHREAD_ROUTINE pResumptionRoutine, PVOID pResumptionRoutineParam) { pResumptionContext->Status = STATUS_SUCCESS; pResumptionContext->Flags = SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS; pResumptionContext->pContext = pResumptionRoutineParam; pResumptionContext->pRoutine = pResumptionRoutine; }
INLINE VOID SmbCeSuspend( PSMBCE_RESUMPTION_CONTEXT pResumptionContext) { ASSERT(!(pResumptionContext->Flags & SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS)); KeWaitForSingleObject( &pResumptionContext->Event, Executive, KernelMode, FALSE, NULL); }
INLINE VOID SmbCeResume( PSMBCE_RESUMPTION_CONTEXT pResumptionContext) { if (!(pResumptionContext->Flags & SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS)) { KeSetEvent(&(pResumptionContext)->Event,0,FALSE); } else { if (RxShouldPostCompletion()) { RxDispatchToWorkerThread( MRxSmbDeviceObject, CriticalWorkQueue, pResumptionContext->pRoutine, pResumptionContext->pContext); } else { (pResumptionContext->pRoutine)(pResumptionContext->pContext); } } }
//
// The SMBCE_REQUEST struct encapsulates the continuation context associated. Typically
// the act of sending a SMB along an exchange results in a SMBCE_REQUEST structure being
// created with sufficient context information to resume the exchange upon reciept of
// response from the serve. The SMBCE_REQUEST conatins ebough information to identify
// the SMB for which the response is being obtained followed by enough context information
// to resume the exchange.
//
typedef enum _SMBCE_OPERATION_ { SMBCE_TRANCEIVE, SMBCE_RECEIVE, SMBCE_SEND, SMBCE_ASYNCHRONOUS_SEND, SMBCE_ACQUIRE_MID } SMBCE_OPERATION, *PSMBCE_OPERATION;
typedef enum _SMBCE_REQUEST_TYPE_ { ORDINARY_REQUEST, COPY_DATA_REQUEST, RECONNECT_REQUEST, ACQUIRE_MID_REQUEST, HOLD_REQUEST } SMBCE_REQUEST_TYPE, *PSMBCE_REQUEST_TYPE;
typedef struct _SMBCE_GENERIC_REQUEST_ { SMBCE_REQUEST_TYPE Type;
// the exchange instance that originated this SMB
struct _SMB_EXCHANGE * pExchange; } SMBCE_GENERIC_REQUEST, *PSMBCE_GENERIC_REQUEST;
//
// The release routine prototype definition.
//
typedef NTSTATUS (*PSMBCE_RELEASE_ROUTINE) ( struct _SMB_EXCHANGE * pExchange, PRX_CONTEXT pRxContext );
//
// Request to hold an exchange in suspension until someone releases it.
//
typedef struct _SMBCE_HOLD_REQUEST_ { SMBCE_GENERIC_REQUEST; PSMBCE_RELEASE_ROUTINE ReleaseRoutine;
} SMBCE_HOLD_REQUEST, *PSMBCE_HOLD_REQUEST;
typedef struct _SMBCE_REQUEST_ { SMBCE_GENERIC_REQUEST;
// the type of request
SMBCE_OPERATION Operation;
// the virtual circuit along which this request was sent.
PRXCE_VC pVc;
// MPX Id of outgoing request.
SMB_MPX_ID Mid;
// the pedigree of the request
SMB_TREE_ID TreeId; // The Tree Id.
SMB_FILE_ID FileId; // The file id.
SMB_USER_ID UserId; // User Id. for cancel.
SMB_PROCESS_ID ProcessId; // Process Id. for cancel.
PMDL pSendBuffer; ULONG BytesSent; } SMBCE_REQUEST, *PSMBCE_REQUEST;
typedef struct _SMBCE_COPY_DATA_REQUEST_ { SMBCE_GENERIC_REQUEST;
// the virtual circuit along which this request was sent.
PRXCE_VC pVc;
// the buffer into whihc data is being copied.
PVOID pBuffer;
// the actual number of bytes copied
ULONG BytesCopied; } SMBCE_COPY_DATA_REQUEST, *PSMBCE_COPY_DATA_REQUEST;
typedef struct _SMBCE_RECONNECT_REQUEST_ { SMBCE_GENERIC_REQUEST; } SMBCE_RECONNECT_REQUEST, *PSMBCE_RECONNECT_REQUEST;
typedef struct _SMBCE_MID_REQUEST_ { SMBCE_GENERIC_REQUEST; PSMBCE_RESUMPTION_CONTEXT pResumptionContext; } SMBCE_MID_REQUEST, *PSMBCE_MID_REQUEST;
//
// extern function declarations
//
extern NTSTATUS BuildSessionSetupSmb( struct _SMB_EXCHANGE *pExchange, PGENERIC_ANDX pAndXSmb, PULONG pAndXSmbBufferSize);
extern NTSTATUS CoreBuildTreeConnectSmb( struct _SMB_EXCHANGE *pExchange, PGENERIC_ANDX pAndXSmb, PULONG pAndXSmbBufferSize);
extern NTSTATUS LmBuildTreeConnectSmb( struct _SMB_EXCHANGE *pExchange, PGENERIC_ANDX pAndXSmb, PULONG pAndXSmbBufferSize);
extern NTSTATUS NtBuildTreeConnectSmb( struct _SMB_EXCHANGE *pExchange, PGENERIC_ANDX pAndXSmb, PULONG pAndXSmbBufferSize);
extern NTSTATUS BuildNegotiateSmb( PVOID *pSmbBufferPointer, PULONG pSmbBufferLength, BOOLEAN RemoteBootSession);
extern NTSTATUS ParseNegotiateResponse( IN OUT struct _SMB_ADMIN_EXCHANGE_ *pExchange, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG pBytesTaken, IN PSMB_HEADER pSmbHeader, OUT PMDL *pDataBufferPointer, OUT PULONG pDataSize);
extern NTSTATUS SmbCeHoldExchangeForSessionRecovery( struct _SMB_EXCHANGE *pExchange, PSMBCE_RELEASE_ROUTINE pRoutine );
extern struct _MINIRDR_DISPATCH MRxSmbDispatch;
#endif // _SMBCE_H_
|