143 lines
5.9 KiB
Swift
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
|
|
|
|
|
|
}
|