From 3f9f572434b51792d36cf510b9a9c7cbce80e6bd Mon Sep 17 00:00:00 2001 From: Mark Gregory Date: Wed, 21 Oct 2026 10:21:27 +0100 Subject: [PATCH] row editing --- DBSyn/MySQLProtocol.swift | 51 ++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/DBSyn/MySQLProtocol.swift b/DBSyn/MySQLProtocol.swift index b46d12f..2bf5e5d 100644 --- a/DBSyn/MySQLProtocol.swift +++ b/DBSyn/MySQLProtocol.swift @@ -208,7 +208,7 @@ private final class MySQLSocketTransport { init(host: String, port: Int) throws { var hints = addrinfo() hints.ai_family = AF_UNSPEC - hints.ai_socktype = Int32(SOCK_STREAM.rawValue) + hints.ai_socktype = Int32(SOCK_STREAM) hints.ai_protocol = Int32(IPPROTO_TCP) var addresses: UnsafeMutablePointer? let result = getaddrinfo(host, String(port), &hints, &addresses) @@ -241,7 +241,7 @@ private final class MySQLSocketTransport { if let ssl { var processed = 0 let status = SSLRead(ssl, buffer, count, &processed) - if status == errSSLSuccess || (status == errSSLWouldBlock && processed > 0) { return processed } + if status == errSecSuccess || (status == errSSLWouldBlock && processed > 0) { return processed } throw MySQLWireError(message: "MySQL TLS read failed (OSStatus \(status))") } let n = Darwin.recv(fd, buffer, count, 0) @@ -253,7 +253,7 @@ private final class MySQLSocketTransport { if let ssl { var processed = 0 let status = SSLWrite(ssl, buffer, count, &processed) - if status == errSSLSuccess || (status == errSSLWouldBlock && processed > 0) { return processed } + if status == errSecSuccess || (status == errSSLWouldBlock && processed > 0) { return processed } throw MySQLWireError(message: "MySQL TLS write failed (OSStatus \(status))") } let n = Darwin.send(fd, buffer, count, 0) @@ -268,7 +268,7 @@ private final class MySQLSocketTransport { // SecureTransport callback connections refer to this retained transport. let connection = Unmanaged.passUnretained(self).toOpaque() var status = SSLSetIOFuncs(context, { connection, data, length in - guard let connection, let data, let length else { return errSecParam } + let transport = Unmanaged.fromOpaque(connection).takeUnretainedValue() let requested = length.pointee let n = Darwin.recv(transport.fd, data, requested, 0) @@ -276,7 +276,7 @@ private final class MySQLSocketTransport { length.pointee = 0 return n == 0 ? errSSLClosedGraceful : errSecIO }, { connection, data, length in - guard let connection, let data, let length else { return errSecParam } + let transport = Unmanaged.fromOpaque(connection).takeUnretainedValue() let n = Darwin.send(transport.fd, data, length.pointee, 0) if n > 0 { length.pointee = n; return errSecSuccess } @@ -290,10 +290,43 @@ private final class MySQLSocketTransport { guard status == errSecSuccess else { throw MySQLWireError(message: "TLS peer setup failed (\(status))") } // REQUIRED encrypts but does not authenticate the server. Keep verification // enabled for the verified mode; never silently fall back to REQUIRED. - status = SSLSetEnableCertVerify(context, verify) - guard status == errSecSuccess else { throw MySQLWireError(message: "TLS verification setup failed (\(status))") } - repeat { status = SSLHandshake(context) } while status == errSSLWouldBlock - guard status == errSecSuccess else { throw MySQLWireError(message: "MySQL TLS handshake failed (OSStatus \(status))") } + // Certificate verification is handled after the TLS handshake. + status = SSLSetSessionOption(context, .breakOnServerAuth, true) + guard status == errSecSuccess else { + throw MySQLWireError(message: "TLS authentication setup failed (\(status))") + } + + repeat { + status = SSLHandshake(context) + } while status == errSSLWouldBlock + + if status == OSStatus(-9841) { + if verify { + var trust: SecTrust? + let trustStatus = SSLCopyPeerTrust(context, &trust) + + guard trustStatus == errSecSuccess, let trust else { + throw MySQLWireError(message: "Unable to obtain MySQL server trust") + } + + var trustError: CFError? + + guard SecTrustEvaluateWithError(trust, &trustError) else { + throw MySQLWireError( + message: "MySQL server verification failed: \(trustError?.localizedDescription ?? "untrusted server")" + ) + } + } + + repeat { + status = SSLHandshake(context) + } while status == errSSLWouldBlock + } + + guard status == errSecSuccess else { + throw MySQLWireError(message: "MySQL TLS handshake failed (OSStatus \(status))") + } + ssl = context } }