9cc9a6a96a
- Renaming OneDriveProvider.SubAddress to Route - Refactors to improve codebeat score
222 lines
9.2 KiB
Swift
222 lines
9.2 KiB
Swift
//
|
|
// CIFSTypes.swift
|
|
// ExtDownloader
|
|
//
|
|
// Created by Amir Abbas Mousavian on 4/30/95.
|
|
// Copyright © 1395 Mousavian. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
// codebeat:disable[TOO_MANY_IVARS]
|
|
// SMB/CIFS Types
|
|
struct SMB1 {
|
|
struct Header { // 32 bytes
|
|
// header is always \u{ff}SMB
|
|
let protocolID: UInt32
|
|
static let protocolConst: UInt32 = 0x424d53ff
|
|
fileprivate var _command: UInt8
|
|
var command: Command {
|
|
get {
|
|
return Command(rawValue: _command) ?? .INVALID
|
|
}
|
|
set {
|
|
_command = newValue.rawValue
|
|
}
|
|
}
|
|
// error messages from the server to the client
|
|
fileprivate var _status: (UInt8, UInt8, UInt8, UInt8)
|
|
var error: (Class: UInt8, code: UInt16) {
|
|
get {
|
|
return (_status.0, UInt16(_status.2) + (UInt16(_status.3) << 8))
|
|
}
|
|
set {
|
|
_status = (newValue.Class, 0, UInt8(newValue.code & 0xff), UInt8(newValue.code >> 8))
|
|
}
|
|
}
|
|
var ntStatus: UInt32 {
|
|
get {
|
|
let statusLo = UInt32(_status.0) + UInt32(_status.1) << 8
|
|
let statusHi = UInt32(_status.2) + UInt32(_status.3) << 8
|
|
return statusHi << 16 + statusLo
|
|
}
|
|
set {
|
|
_status = (UInt8(newValue & 0xff), UInt8(newValue >> 8 & 0xff), UInt8(newValue >> 16 & 0xff), UInt8(newValue >> 24 & 0xff))
|
|
}
|
|
}
|
|
var flags: Flags
|
|
var flags2: Flags2
|
|
var pidHigh: UInt16
|
|
// encryption key used for validating messages over connectionless transports
|
|
fileprivate var _securityKey: (UInt16, UInt16)
|
|
var securityKey: UInt32 {
|
|
get {
|
|
return UInt32(_securityKey.1) << 16 + UInt32(_securityKey.0)
|
|
}
|
|
set {
|
|
_securityKey = (UInt16(newValue & 0xffff), UInt16(newValue >> 16))
|
|
}
|
|
}
|
|
/// Connection identifier
|
|
var securityCID: UInt16
|
|
/// Identifier of the sequence of a message over connectionless transports
|
|
var securitySequenceNumber: UInt16
|
|
fileprivate var ununsed: UInt16
|
|
var treeId: UInt16
|
|
var pidLow: UInt16
|
|
var userId: UInt16
|
|
var multiplexId: UInt16
|
|
var pid: UInt32 {
|
|
get {
|
|
return UInt32(pidLow) + UInt32(pidHigh) << 16
|
|
}
|
|
set {
|
|
pidLow = UInt16(newValue & 0xffff)
|
|
pidHigh = UInt16(newValue >> 16)
|
|
}
|
|
}
|
|
|
|
// codebeat:disable[ARITY]
|
|
init(command: Command, treeId: UInt16, pid: UInt32, userId: UInt16, multiplexId: UInt16, flags: Flags, flags2: Flags2 = [.LONG_NAMES, .ERR_STATUS, .UNICODE], ntStatus: UInt32 = 0, securityKey: UInt32 = 0, securityCID: UInt16 = 0, securitySequenceNumber: UInt16 = 0) {
|
|
self.protocolID = Header.protocolConst
|
|
self._command = command.rawValue
|
|
_status = (UInt8(ntStatus & 0xff), UInt8(ntStatus >> 8 & 0xff), UInt8(ntStatus >> 16 & 0xff), UInt8(ntStatus >> 24 & 0xff))
|
|
self.flags = flags
|
|
self.flags2 = flags2
|
|
self._securityKey = (UInt16(securityKey & 0xffff), UInt16(securityKey >> 16))
|
|
self.securityCID = securityCID
|
|
self.securitySequenceNumber = securitySequenceNumber
|
|
self.ununsed = 0
|
|
self.treeId = treeId
|
|
self.pidLow = UInt16(pid & 0xffff)
|
|
self.pidHigh = UInt16(pid >> 16)
|
|
self.userId = userId
|
|
self.multiplexId = multiplexId
|
|
}
|
|
// codebeat:enable[ARITY]
|
|
}
|
|
|
|
struct Flags: OptionSet {
|
|
let rawValue: UInt8
|
|
|
|
init(rawValue: UInt8) {
|
|
self.rawValue = rawValue
|
|
}
|
|
/** This bit is set (1) in the NEGOTIATE (0x72) Response if the server supports
|
|
* LOCK_AND_READ (0x13) and WRITE_AND_UNLOCK (0x14) commands. */
|
|
static let LOCK_AND_READ_OK = Flags(rawValue: 0x01)
|
|
static let BUF_AVAIL = Flags(rawValue: 0x02)
|
|
static let CASE_INSENSITIVE = Flags(rawValue: 0x08)
|
|
static let CANONICALIZED_PATHS = Flags(rawValue: 0x10)
|
|
static let OPLOCK = Flags(rawValue: 0x20)
|
|
static let OPBATCH = Flags(rawValue: 0x40)
|
|
/** When on, this message is being sent from the server in response to a client request. */
|
|
static let REPLY = Flags(rawValue: 0x80)
|
|
}
|
|
|
|
struct Flags2: OptionSet {
|
|
let rawValue: UInt16
|
|
|
|
init(rawValue: UInt16) {
|
|
self.rawValue = rawValue
|
|
}
|
|
/** Client: the message MAY contain long file names. */
|
|
static let LONG_NAMES = Flags2(rawValue: 0x0001)
|
|
/** Client: the client is aware of extended attributes (EAs). */
|
|
static let EAS = Flags2(rawValue: 0x0002)
|
|
/** Client: the client is requesting signing (if signing is not yet active) or the message
|
|
* being sent is signed. This bit is used on the SMB header of an SESSION_SETUP_ANDX */
|
|
static let SMB_SECURITY_SIGNATURE = Flags2(rawValue: 0x0004)
|
|
/// Reserved but not implemented.
|
|
static let IS_LONG_NAME = Flags2(rawValue: 0x0040)
|
|
/** client aware of Extended Security negotiation */
|
|
static let EXT_SEC = Flags2(rawValue: 0x0800)
|
|
/** any pathnames in this SMB SHOULD be resolved in the Distributed File System (DFS) */
|
|
static let DFS = Flags2(rawValue: 0x1000)
|
|
/**
|
|
* This flag is useful only on a read request. If the bit is set, then the client MAY read
|
|
* the file if the client does not have read permission but does have execute permission. */
|
|
static let PAGING_IO = Flags2(rawValue: 0x2000) // READ_IF_EXECUTE
|
|
/**
|
|
* Client: the server MUST return errors as 32-bit NTSTATUS codes in the response
|
|
* Server: the Status field in the header is formatted as an NTSTATUS cod */
|
|
static let ERR_STATUS = Flags2(rawValue: 0x4000)
|
|
/**
|
|
* Each field that contains a string in this SMB message MUST be encoded
|
|
* as an array of 16-bit Unicode characters */
|
|
static let UNICODE = Flags2(rawValue: 0x8000)
|
|
}
|
|
|
|
enum Command: UInt8 {
|
|
case CREATE_DIRECTORY = 0x00
|
|
case DELETE_DIRECTORY = 0x01
|
|
case OPEN = 0x02
|
|
case CREATE = 0x03
|
|
case CLOSE = 0x04
|
|
case FLUSH = 0x05
|
|
case DELETE = 0x06
|
|
case RENAME = 0x07
|
|
case QUERY_INFORMATION = 0x08
|
|
case SET_INFORMATION = 0x09
|
|
case READ = 0x0A
|
|
case WRITE = 0x0B
|
|
case LOCK_BYTE_RANGE = 0x0C
|
|
case UNLOCK_BYTE_RANGE = 0x0D
|
|
case CREATE_TEMPORARY = 0x0E
|
|
case CREATE_NEW = 0x0F
|
|
case CHECK_DIRECTORY = 0x10
|
|
case PROCESS_EXIT = 0x11
|
|
case SEEK = 0x12
|
|
case LOCK_AND_READ = 0x13
|
|
case WRITE_AND_UNLOCK = 0x14
|
|
case READ_RAW = 0x1A
|
|
case READ_MPX = 0x1B
|
|
case READ_MPX_SECONDARY = 0x1C
|
|
case WRITE_RAW = 0x1D
|
|
case WRITE_MPX = 0x1E
|
|
case WRITE_COMPLETE = 0x20
|
|
case SET_INFORMATION2 = 0x22
|
|
case QUERY_INFORMATION2 = 0x23
|
|
case LOCKING_ANDX = 0x24
|
|
case TRANSACTION = 0x25
|
|
case TRANSACTION_SECONDARY = 0x26
|
|
case IOCTL = 0x27
|
|
case IOCTL_SECONDARY = 0x28
|
|
case COPY = 0x29
|
|
case MOVE = 0x2A
|
|
case ECHO = 0x2B
|
|
case WRITE_AND_CLOSE = 0x2C
|
|
case OPEN_ANDX = 0x2D
|
|
case READ_ANDX = 0x2E
|
|
case WRITE_ANDX = 0x2F
|
|
case CLOSE_AND_TREE_DISC = 0x31
|
|
case TRANSACTION2 = 0x32
|
|
case TRANSACTION2_SECONDARY = 0x33
|
|
case FIND_CLOSE2 = 0x34
|
|
case FIND_NOTIFY_CLOSE = 0x35
|
|
case TREE_CONNECT = 0x70
|
|
case TREE_DISCONNECT = 0x71
|
|
case NEGOTIATE = 0x72
|
|
case SESSION_SETUP_ANDX = 0x73
|
|
case LOGOFF_ANDX = 0x74
|
|
case TREE_CONNECT_ANDX = 0x75
|
|
case QUERY_INFORMATION_DISK = 0x80
|
|
case SEARCH = 0x81
|
|
case FIND = 0x82
|
|
case FIND_UNIQUE = 0x83
|
|
case NT_TRANSACT = 0xA0
|
|
case NT_TRANSACT_SECONDARY = 0xA1
|
|
case NT_CREATE_ANDX = 0xA2
|
|
case NT_CANCEL = 0xA4
|
|
case OPEN_PRINT_FILE = 0xC0
|
|
case WRITE_PRINT_FILE = 0xC1
|
|
case CLOSE_PRINT_FILE = 0xC2
|
|
case GET_PRINT_QUEUE = 0xC3
|
|
case READ_BULK = 0xD8
|
|
case WRITE_BULK = 0xD9
|
|
case WRITE_BULK_DATA = 0xDA
|
|
case INVALID = 0xFE
|
|
}
|
|
}
|
|
// codebeat:enable[TOO_MANY_IVARS]
|