/** * SMB2/3 Protocol Type Definitions * Based on MS-SMB2 specification */ import type { SMB2_COMMANDS, SMB2_STATUS, SMB2_FLAGS, SMB2_DIALECTS, FILE_ATTRIBUTES, ACCESS_MASK, SHARE_ACCESS, CREATE_DISPOSITION, CREATE_OPTIONS, OPLOCK_LEVEL, FILE_INFORMATION_CLASS, SECURITY_INFORMATION, SHARE_TYPE, SHARE_FLAGS, SHARE_CAPABILITIES, } from './constants.js'; // Basic SMB2 Types export type SMB2Guid = string; // 128-bit GUID as hex string export type SMB2FileId = { readonly persistent: bigint; readonly volatile: bigint; }; // SMB2 Header Structure export interface SMB2Header { readonly protocolId: number; // Should be SMB2_PROTOCOL_ID readonly structureSize: number; // Should be 64 readonly creditCharge: number; readonly status: SMB2_STATUS; readonly command: SMB2_COMMANDS; readonly creditRequestResponse: number; readonly flags: SMB2_FLAGS; readonly nextCommand: number; readonly messageId: bigint; readonly reserved: number; readonly treeId: number; readonly sessionId: bigint; readonly signature: Buffer; // 16 bytes } // SMB2 Transform Header (for encryption) export interface SMB2TransformHeader { readonly protocolId: number; // SMB2_TRANSFORM_PROTOCOL_ID readonly signature: Buffer; // 16 bytes readonly nonce: Buffer; // 16 bytes readonly originalMessageSize: number; readonly reserved: number; readonly flags: number; readonly sessionId: bigint; } // Base SMB2 Message export interface SMB2Message { readonly header: SMB2Header; readonly data: Buffer; } // SMB2 Error Response export interface SMB2ErrorResponse { readonly structureSize: number; readonly reserved: number; readonly byteCount: number; readonly errorData: Buffer; } // SMB2 Negotiate Request export interface SMB2NegotiateRequest { readonly structureSize: number; readonly dialectCount: number; readonly securityMode: number; readonly reserved: number; readonly capabilities: number; readonly clientGuid: SMB2Guid; readonly clientStartTime: bigint; readonly dialects: SMB2_DIALECTS[]; readonly negotiateContexts?: SMB2NegotiateContext[]; } // SMB2 Negotiate Response export interface SMB2NegotiateResponse { readonly structureSize: number; readonly securityMode: number; readonly dialectRevision: SMB2_DIALECTS; readonly negotiateContextCount: number; readonly serverGuid: SMB2Guid; readonly capabilities: number; readonly maxTransactSize: number; readonly maxReadSize: number; readonly maxWriteSize: number; readonly systemTime: bigint; readonly serverStartTime: bigint; readonly securityBufferOffset: number; readonly securityBufferLength: number; readonly negotiateContextOffset: number; readonly securityBuffer: Buffer; readonly negotiateContexts: SMB2NegotiateContext[]; } // SMB2 Negotiate Context export interface SMB2NegotiateContext { readonly contextType: number; readonly dataLength: number; readonly reserved: number; readonly data: Buffer; } // SMB2 Session Setup Request export interface SMB2SessionSetupRequest { readonly structureSize: number; readonly flags: number; readonly securityMode: number; readonly capabilities: number; readonly channel: number; readonly securityBufferOffset: number; readonly securityBufferLength: number; readonly previousSessionId: bigint; readonly securityBuffer: Buffer; } // SMB2 Session Setup Response export interface SMB2SessionSetupResponse { readonly structureSize: number; readonly sessionFlags: number; readonly securityBufferOffset: number; readonly securityBufferLength: number; readonly securityBuffer: Buffer; } // SMB2 Tree Connect Request export interface SMB2TreeConnectRequest { readonly structureSize: number; readonly flags: number; readonly pathOffset: number; readonly pathLength: number; readonly path: string; } // SMB2 Tree Connect Response export interface SMB2TreeConnectResponse { readonly structureSize: number; readonly shareType: SHARE_TYPE; readonly reserved: number; readonly shareFlags: SHARE_FLAGS; readonly capabilities: SHARE_CAPABILITIES; readonly maximalAccess: ACCESS_MASK; } // SMB2 Create Request export interface SMB2CreateRequest { readonly structureSize: number; readonly securityFlags: number; readonly requestedOplockLevel: OPLOCK_LEVEL; readonly impersonationLevel: number; readonly smbCreateFlags: bigint; readonly reserved: bigint; readonly desiredAccess: ACCESS_MASK; readonly fileAttributes: FILE_ATTRIBUTES; readonly shareAccess: SHARE_ACCESS; readonly createDisposition: CREATE_DISPOSITION; readonly createOptions: CREATE_OPTIONS; readonly nameOffset: number; readonly nameLength: number; readonly createContextsOffset: number; readonly createContextsLength: number; readonly name: string; readonly createContexts: SMB2CreateContext[]; } // SMB2 Create Response export interface SMB2CreateResponse { readonly structureSize: number; readonly oplockLevel: OPLOCK_LEVEL; readonly flags: number; readonly createAction: number; readonly creationTime: bigint; readonly lastAccessTime: bigint; readonly lastWriteTime: bigint; readonly changeTime: bigint; readonly allocationSize: bigint; readonly endOfFile: bigint; readonly fileAttributes: FILE_ATTRIBUTES; readonly reserved2: number; readonly fileId: SMB2FileId; readonly createContextsOffset: number; readonly createContextsLength: number; readonly createContexts: SMB2CreateContext[]; } // SMB2 Create Context export interface SMB2CreateContext { readonly next: number; readonly nameOffset: number; readonly nameLength: number; readonly reserved: number; readonly dataOffset: number; readonly dataLength: number; readonly name: string; readonly data: Buffer; } // SMB2 Close Request export interface SMB2CloseRequest { readonly structureSize: number; readonly flags: number; readonly reserved: number; readonly fileId: SMB2FileId; } // SMB2 Close Response export interface SMB2CloseResponse { readonly structureSize: number; readonly flags: number; readonly reserved: number; readonly creationTime: bigint; readonly lastAccessTime: bigint; readonly lastWriteTime: bigint; readonly changeTime: bigint; readonly allocationSize: bigint; readonly endOfFile: bigint; readonly fileAttributes: FILE_ATTRIBUTES; } // SMB2 Read Request export interface SMB2ReadRequest { readonly structureSize: number; readonly padding: number; readonly flags: number; readonly length: number; readonly offset: bigint; readonly fileId: SMB2FileId; readonly minimumCount: number; readonly channel: number; readonly remainingBytes: number; readonly readChannelInfoOffset: number; readonly readChannelInfoLength: number; readonly readChannelInfo: Buffer; } // SMB2 Read Response export interface SMB2ReadResponse { readonly structureSize: number; readonly dataOffset: number; readonly dataLength: number; readonly dataRemaining: number; readonly reserved: number; readonly data: Buffer; } // SMB2 Write Request export interface SMB2WriteRequest { readonly structureSize: number; readonly dataOffset: number; readonly length: number; readonly offset: bigint; readonly fileId: SMB2FileId; readonly channel: number; readonly remainingBytes: number; readonly writeChannelInfoOffset: number; readonly writeChannelInfoLength: number; readonly flags: number; readonly writeChannelInfo: Buffer; readonly data: Buffer; } // SMB2 Write Response export interface SMB2WriteResponse { readonly structureSize: number; readonly reserved: number; readonly count: number; readonly remaining: number; readonly writeChannelInfoOffset: number; readonly writeChannelInfoLength: number; readonly writeChannelInfo: Buffer; } // SMB2 Query Directory Request export interface SMB2QueryDirectoryRequest { readonly structureSize: number; readonly fileInformationClass: FILE_INFORMATION_CLASS; readonly flags: number; readonly fileIndex: number; readonly fileId: SMB2FileId; readonly fileNameOffset: number; readonly fileNameLength: number; readonly outputBufferLength: number; readonly fileName: string; } // SMB2 Query Directory Response export interface SMB2QueryDirectoryResponse { readonly structureSize: number; readonly outputBufferOffset: number; readonly outputBufferLength: number; readonly outputBuffer: Buffer; } // SMB2 Query Info Request export interface SMB2QueryInfoRequest { readonly structureSize: number; readonly infoType: number; readonly fileInfoClass: number; readonly outputBufferLength: number; readonly inputBufferOffset: number; readonly reserved: number; readonly inputBufferLength: number; readonly additionalInformation: SECURITY_INFORMATION; readonly flags: number; readonly fileId: SMB2FileId; readonly inputBuffer: Buffer; } // SMB2 Query Info Response export interface SMB2QueryInfoResponse { readonly structureSize: number; readonly outputBufferOffset: number; readonly outputBufferLength: number; readonly outputBuffer: Buffer; } // SMB2 Set Info Request export interface SMB2SetInfoRequest { readonly structureSize: number; readonly infoType: number; readonly fileInfoClass: number; readonly bufferLength: number; readonly bufferOffset: number; readonly reserved: number; readonly additionalInformation: SECURITY_INFORMATION; readonly fileId: SMB2FileId; readonly buffer: Buffer; } // SMB2 Set Info Response export interface SMB2SetInfoResponse { readonly structureSize: number; } // File Information Structures export interface FileBasicInformation { readonly creationTime: bigint; readonly lastAccessTime: bigint; readonly lastWriteTime: bigint; readonly changeTime: bigint; readonly fileAttributes: FILE_ATTRIBUTES; readonly reserved: number; } export interface FileStandardInformation { readonly allocationSize: bigint; readonly endOfFile: bigint; readonly numberOfLinks: number; readonly deletePending: boolean; readonly directory: boolean; readonly reserved: number; } export interface FileDirectoryInformation { readonly nextEntryOffset: number; readonly fileIndex: number; readonly creationTime: bigint; readonly lastAccessTime: bigint; readonly lastWriteTime: bigint; readonly changeTime: bigint; readonly endOfFile: bigint; readonly allocationSize: bigint; readonly fileAttributes: FILE_ATTRIBUTES; readonly fileNameLength: number; readonly fileName: string; } // Session and Connection Types export interface SMB2Session { readonly sessionId: bigint; readonly userId: string; readonly isGuest: boolean; readonly isAnonymous: boolean; readonly creationTime: Date; readonly lastActivityTime: Date; readonly signingRequired: boolean; readonly encryptionRequired: boolean; readonly preauthIntegrityHashValue: Buffer; readonly sessionKey: Buffer; readonly signKey: Buffer; readonly applicationKey?: Buffer; readonly encryptionKey?: Buffer; readonly decryptionKey?: Buffer; } export interface SMB2TreeConnect { readonly treeConnectId: number; readonly sessionId: bigint; readonly shareName: string; readonly shareType: SHARE_TYPE; readonly shareFlags: SHARE_FLAGS; readonly maximalAccess: ACCESS_MASK; readonly encryptData: boolean; readonly creationTime: Date; readonly lastActivityTime: Date; } export interface SMB2OpenFile { readonly fileId: SMB2FileId; readonly treeConnectId: number; readonly sessionId: bigint; readonly fileName: string; readonly desiredAccess: ACCESS_MASK; readonly shareAccess: SHARE_ACCESS; readonly createOptions: CREATE_OPTIONS; readonly fileAttributes: FILE_ATTRIBUTES; readonly oplockLevel: OPLOCK_LEVEL; readonly creationTime: Date; readonly lastAccessTime: Date; readonly isDurable: boolean; readonly isResilient: boolean; } // Connection and Transport Types export interface SMB2Connection { readonly connectionId: string; readonly clientAddress: string; readonly serverAddress: string; readonly dialect: SMB2_DIALECTS; readonly supportsMultiCredit: boolean; readonly maxTransactSize: number; readonly maxReadSize: number; readonly maxWriteSize: number; readonly requireMessageSigning: boolean; readonly clientGuid: SMB2Guid; readonly clientName?: string; readonly creationTime: Date; readonly lastActivityTime: Date; readonly sessions: Map; readonly treeConnects: Map; readonly openFiles: Map; // key is fileId string } // Server Configuration Types export interface SMB2ServerConfig { readonly serverGuid: SMB2Guid; readonly serverName: string; readonly domainName?: string; readonly workgroupName?: string; readonly supportedDialects: SMB2_DIALECTS[]; readonly requireMessageSigning: boolean; readonly enableEncryption: boolean; readonly maxConnections: number; readonly maxSessionsPerConnection: number; readonly sessionTimeout: number; readonly maxTransactSize: number; readonly maxReadSize: number; readonly maxWriteSize: number; readonly shares: SMB2ShareConfig[]; readonly users?: SMB2UserConfig[]; } export interface SMB2ShareConfig { readonly name: string; readonly path: string; readonly shareType: SHARE_TYPE; readonly shareFlags: SHARE_FLAGS; readonly capabilities: SHARE_CAPABILITIES; readonly maximalAccess: ACCESS_MASK; readonly encryptData: boolean; readonly cachingPolicy: number; readonly description?: string; readonly accessControl?: SMB2ShareAccessControl[]; } export interface SMB2UserConfig { readonly username: string; readonly passwordHash: string; readonly isGuest: boolean; readonly isAdmin: boolean; readonly allowedShares: string[]; } export interface SMB2ShareAccessControl { readonly principal: string; // username or group readonly accessMask: ACCESS_MASK; readonly allowDeny: 'allow' | 'deny'; } // Event Types export type SMB2EventType = | 'connection:established' | 'connection:closed' | 'session:established' | 'session:closed' | 'tree:connected' | 'tree:disconnected' | 'file:opened' | 'file:closed' | 'file:read' | 'file:written' | 'error' | 'warning'; export interface SMB2Event { readonly type: SMB2EventType; readonly timestamp: Date; readonly connectionId?: string; readonly sessionId?: bigint; readonly treeId?: number; readonly fileId?: SMB2FileId; readonly data: T; } // Utility Types export type SMB2MessageHandler = ( request: TRequest, connection: SMB2Connection, session?: SMB2Session, treeConnect?: SMB2TreeConnect, ) => Promise; export type SMB2CommandHandler = SMB2MessageHandler; export type SMB2EventHandler = (event: SMB2Event) => void | Promise; // Parser and Serializer Types export interface SMB2Parser { parse(buffer: Buffer, offset?: number): { result: T; bytesRead: number }; } export interface SMB2Serializer { serialize(value: T): Buffer; getSize(value: T): number; } // Credit Management export interface SMB2CreditManager { readonly available: number; readonly granted: number; readonly consumed: number; request(amount: number): boolean; grant(amount: number): void; consume(amount: number): void; release(amount: number): void; } // Async Context Types export interface SMB2AsyncContext { readonly asyncId: bigint; readonly originalCommand: SMB2_COMMANDS; readonly originalMessageId: bigint; readonly connectionId: string; readonly sessionId: bigint; readonly treeId: number; readonly creationTime: Date; readonly callback: (response: Buffer) => void; readonly timeout: NodeJS.Timeout; } // Compound Request Types export interface SMB2CompoundRequest { readonly messages: SMB2Message[]; readonly isRelated: boolean; } export interface SMB2CompoundResponse { readonly messages: SMB2Message[]; } // Type Guards export type SMB2RequestType = T extends SMB2_COMMANDS.NEGOTIATE ? SMB2NegotiateRequest : T extends SMB2_COMMANDS.SESSION_SETUP ? SMB2SessionSetupRequest : T extends SMB2_COMMANDS.TREE_CONNECT ? SMB2TreeConnectRequest : T extends SMB2_COMMANDS.CREATE ? SMB2CreateRequest : T extends SMB2_COMMANDS.CLOSE ? SMB2CloseRequest : T extends SMB2_COMMANDS.READ ? SMB2ReadRequest : T extends SMB2_COMMANDS.WRITE ? SMB2WriteRequest : T extends SMB2_COMMANDS.QUERY_DIRECTORY ? SMB2QueryDirectoryRequest : T extends SMB2_COMMANDS.QUERY_INFO ? SMB2QueryInfoRequest : T extends SMB2_COMMANDS.SET_INFO ? SMB2SetInfoRequest : Buffer; export type SMB2ResponseType = T extends SMB2_COMMANDS.NEGOTIATE ? SMB2NegotiateResponse : T extends SMB2_COMMANDS.SESSION_SETUP ? SMB2SessionSetupResponse : T extends SMB2_COMMANDS.TREE_CONNECT ? SMB2TreeConnectResponse : T extends SMB2_COMMANDS.CREATE ? SMB2CreateResponse : T extends SMB2_COMMANDS.CLOSE ? SMB2CloseResponse : T extends SMB2_COMMANDS.READ ? SMB2ReadResponse : T extends SMB2_COMMANDS.WRITE ? SMB2WriteResponse : T extends SMB2_COMMANDS.QUERY_DIRECTORY ? SMB2QueryDirectoryResponse : T extends SMB2_COMMANDS.QUERY_INFO ? SMB2QueryInfoResponse : T extends SMB2_COMMANDS.SET_INFO ? SMB2SetInfoResponse : Buffer;