Skip to content

Commit 6ddfde7

Browse files
committed
fix: Remove smbdir crash workaround
fix: Security issues in docker file chore: Minor refactors
1 parent a74f9a3 commit 6ddfde7

11 files changed

+326
-148
lines changed

AMSMB2/AMSMB2.swift

+8-3
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,11 @@ public class SMB2Manager: NSObject, NSSecureCoding, Codable, NSCopying, CustomRe
13721372
/// - path: Path of file or folder to be monitored for changes.
13731373
/// - filter: Change types that will be monitored.
13741374
/// - completionHandler: closure will be run after a change in montored file/folder.
1375-
func monitorItem(atPath path: String, for filter: SMB2FileChangeType, completionHandler: SimpleCompletionHandler) {
1375+
func monitorItem(
1376+
atPath path: String,
1377+
for filter: SMB2FileChangeType,
1378+
completionHandler: @Sendable @escaping (_ result: Result<[SMB2FileChangeInfo], any Error>) -> Void
1379+
) {
13761380
with(completionHandler: completionHandler) { client in
13771381
var flags = O_RDONLY | O_SYNC
13781382
switch try client.stat(path).resourceType {
@@ -1384,7 +1388,7 @@ public class SMB2Manager: NSObject, NSSecureCoding, Codable, NSCopying, CustomRe
13841388
break
13851389
}
13861390
let file = try SMB2FileHandle(path: path, flags: flags, on: client)
1387-
try file.changeNotify(for: filter)
1391+
return try file.changeNotify(for: filter)
13881392
}
13891393
}
13901394

@@ -1393,7 +1397,8 @@ public class SMB2Manager: NSObject, NSSecureCoding, Codable, NSCopying, CustomRe
13931397
/// - Parameters:
13941398
/// - path: Path of file or folder to be monitored for changes.
13951399
/// - filter: Change types that will be monitored.
1396-
func monitorItem(atPath path: String, for filter: SMB2FileChangeType) async throws {
1400+
@discardableResult
1401+
func monitorItem(atPath path: String, for filter: SMB2FileChangeType) async throws -> [SMB2FileChangeInfo] {
13971402
try await withCheckedThrowingContinuation { continuation in
13981403
monitorItem(atPath: path, for: filter, completionHandler: asyncHandler(continuation))
13991404
}

AMSMB2/Context.swift

+49-37
Original file line numberDiff line numberDiff line change
@@ -315,45 +315,18 @@ extension SMB2Client {
315315
smb2_rmdir_async(context, path.canonical, SMB2Client.generic_handler, cbPtr)
316316
}
317317
}
318-
319-
func unlink(_ path: String) throws {
320-
try async_await { context, cbPtr -> Int32 in
321-
smb2_unlink_async(context, path.canonical, SMB2Client.generic_handler, cbPtr)
322-
}
323-
}
324-
325-
private func unlinkSymlink(_ path: String) throws {
326-
let file = try SMB2FileHandle(path: path, flags: O_RDWR | O_SYMLINK, on: self)
327-
var inputBuffer = [UInt8](repeating: 0, count: 8)
328-
inputBuffer[0] = 0x01 // DeletePending set to true
329-
try withExtendedLifetime(file) { file in
330-
try inputBuffer.withUnsafeMutableBytes { buf in
331-
var req = smb2_set_info_request(
332-
info_type: UInt8(SMB2_0_INFO_FILE),
333-
file_info_class: UInt8(SMB2_FILE_DISPOSITION_INFORMATION),
334-
buffer_length: UInt32(buf.count),
335-
buffer_offset: 0,
336-
additional_information: 0,
337-
file_id: file.fileId.uuid,
338-
input_data: buf.baseAddress
339-
)
340-
341-
try async_await_pdu(dataHandler: EmptyReply.init) {
342-
context, cbPtr -> UnsafeMutablePointer<smb2_pdu>? in
343-
smb2_cmd_set_info_async(context, &req, SMB2Client.generic_handler, cbPtr)
344-
}
345-
}
346-
}
347-
}
348318

349319
func unlink(_ path: String, type: smb2_stat_64.ResourceType = .file) throws {
350320
switch type {
351321
case .directory:
352322
throw POSIXError(.EINVAL, description: "Use rmdir() to delete a directory.")
353323
case .file:
354-
try unlink(path)
324+
try async_await { context, cbPtr -> Int32 in
325+
smb2_unlink_async(context, path.canonical, SMB2Client.generic_handler, cbPtr)
326+
}
355327
case .link:
356-
try unlinkSymlink(path)
328+
let file = try SMB2FileHandle(path: path, flags: O_RDWR | O_SYMLINK, on: self)
329+
try file.setInfo(smb2_file_disposition_info(delete_pending: 1), infoClass: .disposition)
357330
default:
358331
preconditionFailure("Not supported file type.")
359332
}
@@ -503,9 +476,16 @@ extension SMB2Client {
503476
}
504477

505478
extension SMB2Client {
506-
struct NegotiateSigning: OptionSet {
479+
struct NegotiateSigning: OptionSet, Sendable, CustomStringConvertible {
507480
var rawValue: UInt16
508-
481+
482+
var description: String {
483+
var result: [String] = []
484+
if contains(.enabled) { result.append("Enabled") }
485+
if contains(.required) { result.append("Required") }
486+
return result.joined(separator: ", ")
487+
}
488+
509489
static let enabled = NegotiateSigning(rawValue: SMB2_NEGOTIATE_SIGNING_ENABLED)
510490
static let required = NegotiateSigning(rawValue: SMB2_NEGOTIATE_SIGNING_REQUIRED)
511491
}
@@ -514,7 +494,7 @@ extension SMB2Client {
514494
typealias Security = smb2_sec
515495
}
516496

517-
extension SMB2.smb2_negotiate_version: Swift.Hashable {
497+
extension SMB2.smb2_negotiate_version: Swift.Hashable, Swift.CustomStringConvertible {
518498
static let any = SMB2_VERSION_ANY
519499
static let v2 = SMB2_VERSION_ANY2
520500
static let v3 = SMB2_VERSION_ANY3
@@ -523,6 +503,20 @@ extension SMB2.smb2_negotiate_version: Swift.Hashable {
523503
static let v3_00 = SMB2_VERSION_0300
524504
static let v3_02 = SMB2_VERSION_0302
525505
static let v3_11 = SMB2_VERSION_0311
506+
507+
public var description: String {
508+
switch self {
509+
case .any: return "Any"
510+
case .v2: return "2.0"
511+
case .v3: return "3.0"
512+
case .v2_02: return "2.02"
513+
case .v2_10: return "2.10"
514+
case .v3_00: return "3.00"
515+
case .v3_02: return "3.02"
516+
case .v3_11: return "3.11"
517+
default: return "Unknown"
518+
}
519+
}
526520

527521
static func ==(lhs: smb2_negotiate_version, rhs: smb2_negotiate_version) -> Bool {
528522
lhs.rawValue == rhs.rawValue
@@ -533,10 +527,19 @@ extension SMB2.smb2_negotiate_version: Swift.Hashable {
533527
}
534528
}
535529

536-
extension SMB2.smb2_sec: Swift.Hashable {
530+
extension SMB2.smb2_sec: Swift.Hashable, Swift.CustomStringConvertible {
537531
static let undefined = SMB2_SEC_UNDEFINED
538532
static let ntlmSsp = SMB2_SEC_NTLMSSP
539533
static let kerberos5 = SMB2_SEC_KRB5
534+
535+
public var description: String {
536+
switch self {
537+
case .undefined: return "Undefined"
538+
case .ntlmSsp: return "NTLM SSP"
539+
case .kerberos5: return "Kerberos5"
540+
default: return "Unknown"
541+
}
542+
}
540543

541544
static func ==(lhs: smb2_sec, rhs: smb2_sec) -> Bool {
542545
lhs.rawValue == rhs.rawValue
@@ -573,12 +576,21 @@ struct ShareProperties: RawRepresentable {
573576
}
574577

575578
struct NTStatus: LocalizedError, Hashable, Sendable {
576-
enum Severity: UInt32, Hashable, Sendable {
579+
enum Severity: UInt32, Hashable, Sendable, CustomStringConvertible {
577580
case success
578581
case info
579582
case warning
580583
case error
581584

585+
var description: String {
586+
switch self {
587+
case .success: return "Success"
588+
case .info: return "Info"
589+
case .warning: return "Warning"
590+
case .error: return "Error"
591+
}
592+
}
593+
582594
init(status: NTStatus) {
583595
self = switch status.rawValue & SMB2_STATUS_SEVERITY_MASK {
584596
case UInt32(bitPattern: SMB2_STATUS_SEVERITY_SUCCESS):

AMSMB2/Directory.swift

+8-36
Original file line numberDiff line numberDiff line change
@@ -10,60 +10,34 @@
1010
import Foundation
1111
import SMB2
1212

13-
typealias smb2dir = OpaquePointer
13+
typealias smb2dirPointer = UnsafeMutablePointer<smb2dir>?
1414

1515
/// - Note: This class is NOT thread-safe.
1616
final class SMB2Directory: Collection {
1717
private let path: String
1818
private let client: SMB2Client
19-
private var handle: smb2dir
19+
private var handle: smb2dirPointer
2020

2121
init(_ path: String, on client: SMB2Client) throws {
2222
self.path = path
23-
self.handle = try Self.openHandle(path, on: client)
23+
let (_, handle) = try client.async_await(dataHandler: OpaquePointer.init) { context, cbPtr -> Int32 in
24+
smb2_opendir_async(context, path, SMB2Client.generic_handler, cbPtr)
25+
}
26+
2427
self.client = client
28+
self.handle = .init(handle)
2529
}
2630

2731
deinit {
28-
let handle = self.handle
29-
guard unsafeBitCast(handle, to: UInt.self) & 0xffff_f000 > 0 else {
30-
return
31-
}
3232
try? client.withThreadSafeContext { context in
3333
smb2_closedir(context, handle)
3434
}
3535
}
3636

37-
static func openHandle(_ path: String, on client: SMB2Client) throws -> smb2dir {
38-
// Due to a unexpected free in closedir, async version is not usable.
39-
let handle = try client.withThreadSafeContext { context in
40-
smb2_opendir(context, path)
41-
}
42-
guard let handle else {
43-
throw POSIXError(client.ntError.posixErrorCode, description: client.error)
44-
}
45-
46-
return handle
47-
}
48-
49-
func safeHandle() -> smb2dir? {
50-
var handle = handle
51-
while unsafeBitCast(handle, to: UInt.self) & 0xffff_f000 == 0 {
52-
do {
53-
handle = try Self.openHandle(path, on: client)
54-
self.handle = handle
55-
} catch {
56-
return nil
57-
}
58-
}
59-
return handle
60-
}
61-
6237
func makeIterator() -> AnyIterator<smb2dirent> {
6338
let context = client.context
64-
let handle = safeHandle()
6539
smb2_rewinddir(context, handle)
66-
return AnyIterator {
40+
return AnyIterator { [handle] in
6741
smb2_readdir(context, handle)?.pointee
6842
}
6943
}
@@ -78,7 +52,6 @@ final class SMB2Directory: Collection {
7852

7953
var count: Int {
8054
let context = client.context
81-
let handle = safeHandle()
8255
let currentPos = smb2_telldir(context, handle)
8356
defer {
8457
smb2_seekdir(context, handle, currentPos)
@@ -94,7 +67,6 @@ final class SMB2Directory: Collection {
9467

9568
subscript(_: Int) -> smb2dirent {
9669
let context = client.context
97-
let handle = safeHandle()
9870
let currentPos = smb2_telldir(context, handle)
9971
smb2_seekdir(context, handle, 0)
10072
defer {

0 commit comments

Comments
 (0)