Files

143 lines
5.9 KiB
Swift

//
// SMB2Types.swift
// FileProvider
//
// Created by Amir Abbas Mousavian.
// Copyright © 2016 Mousavian. Distributed under MIT license.
//
import Foundation
protocol FileProviderSMBHeader {
var protocolID: UInt32 { get }
static var protocolConst: UInt32 { get }
}
// SMB2 Types
struct SMB2 {
struct Header: FileProviderSMBHeader { // 64 bytes
// header is always \u{fe}SMB
let protocolID: UInt32
static let protocolConst: UInt32 = 0x424d53fe
let size: UInt16
let creditCharge: UInt16
// error messages from the server to the client
let status: NTStatus
enum StatusSeverity: UInt8 {
case success = 0, information, warning, error
}
var statusDetails: (severity: StatusSeverity, customer: Bool, facility: UInt16, code: UInt16) {
let severity = StatusSeverity(rawValue: UInt8(status.rawValue >> 30))!
return (severity, status.rawValue & 0x20000000 != 0,
UInt16((status.rawValue & 0x0FFF0000) >> 16),
UInt16(status.rawValue & 0x0000FFFF))
}
let command: Command
let creditRequestResponse: UInt16
let flags: Flags
var nextCommand: UInt32
let messageId: UInt64
fileprivate let reserved: UInt32
let treeId: UInt32
var asyncId: UInt64 {
get {
return UInt64(reserved) + (UInt64(treeId) << 32)
}
}
let sessionId: UInt64
let signature: (UInt64, UInt64)
// codebeat:disable[ARITY]
init(command: Command, status: NTStatus = .SUCCESS, creditCharge: UInt16 = 0, creditRequestResponse: UInt16, flags: Flags = [], nextCommand: UInt32 = 0, messageId: UInt64, treeId: UInt32, sessionId: UInt64, signature: (UInt64, UInt64) = (0, 0)) {
self.protocolID = type(of: self).protocolConst
self.size = 64
self.status = status
self.command = command
self.creditCharge = creditCharge
self.creditRequestResponse = creditRequestResponse
self.flags = flags
self.nextCommand = nextCommand
self.messageId = messageId
self.reserved = 0
self.treeId = treeId
self.sessionId = sessionId
self.signature = signature
}
init(asyncCommand: Command, status: NTStatus = .SUCCESS, creditCharge: UInt16 = 0, creditRequestResponse: UInt16, flags: Flags = [.ASYNC_COMMAND], nextCommand: UInt32 = 0, messageId: UInt64, asyncId: UInt64, sessionId: UInt64, signature: (UInt64, UInt64) = (0, 0)) {
self.protocolID = type(of: self).protocolConst
self.size = 64
self.status = status
self.command = asyncCommand
self.creditCharge = creditCharge
self.creditRequestResponse = creditRequestResponse
self.flags = flags.union([Flags.ASYNC_COMMAND])
self.nextCommand = nextCommand
self.messageId = messageId
self.reserved = UInt32(asyncId & 0xffffffff)
self.treeId = UInt32(asyncId >> 32)
self.sessionId = sessionId
self.signature = signature
}
// codebeat:enable[ARITY]
}
struct Flags: OptionSet {
var rawValue: UInt32
init(rawValue: UInt32) {
self.rawValue = rawValue
}
var priorityMask: UInt8 {
get {
return UInt8((rawValue & Flags.PRIORITY_MASK.rawValue) >> 4)
}
set {
rawValue = (rawValue & 0xffffff8f) | (UInt32(newValue & 0x7) << 4)
}
}
static let SERVER_TO_REDIR = Flags(rawValue: 0x00000001)
static let ASYNC_COMMAND = Flags(rawValue: 0x00000002)
static let RELATED_OPERATIONS = Flags(rawValue: 0x00000004)
static let SIGNED = Flags(rawValue: 0x00000008)
fileprivate static let PRIORITY_MASK = Flags(rawValue: 0x00000070)
static let DFS_OPERATIONS = Flags(rawValue: 0x10000000)
static let REPLAY_OPERATION = Flags(rawValue: 0x20000000)
}
struct Command: Option {
init(rawValue: UInt16) {
self.rawValue = rawValue
}
let rawValue: UInt16
public static let NEGOTIATE = Command(rawValue: 0x0000)
public static let SESSION_SETUP = Command(rawValue: 0x0001)
public static let LOGOFF = Command(rawValue: 0x0002)
public static let TREE_CONNECT = Command(rawValue: 0x0003)
public static let TREE_DISCONNECT = Command(rawValue: 0x0004)
public static let CREATE = Command(rawValue: 0x0005)
public static let CLOSE = Command(rawValue: 0x0006)
public static let FLUSH = Command(rawValue: 0x0007)
public static let READ = Command(rawValue: 0x0008)
public static let WRITE = Command(rawValue: 0x0009)
public static let LOCK = Command(rawValue: 0x000A)
public static let IOCTL = Command(rawValue: 0x000B)
public static let CANCEL = Command(rawValue: 0x000C)
public static let ECHO = Command(rawValue: 0x000D)
public static let QUERY_DIRECTORY = Command(rawValue: 0x000E)
public static let CHANGE_NOTIFY = Command(rawValue: 0x000F)
public static let QUERY_INFO = Command(rawValue: 0x0010)
public static let SET_INFO = Command(rawValue: 0x0011)
public static let OPLOCK_BREAK = Command(rawValue: 0x0012)
public static let INVALID = Command(rawValue: 0xFFFF)
}
// MARK: SMB2 Oplock Break
}