row editing
This commit is contained in:
@@ -208,7 +208,7 @@ private final class MySQLSocketTransport {
|
|||||||
init(host: String, port: Int) throws {
|
init(host: String, port: Int) throws {
|
||||||
var hints = addrinfo()
|
var hints = addrinfo()
|
||||||
hints.ai_family = AF_UNSPEC
|
hints.ai_family = AF_UNSPEC
|
||||||
hints.ai_socktype = Int32(SOCK_STREAM.rawValue)
|
hints.ai_socktype = Int32(SOCK_STREAM)
|
||||||
hints.ai_protocol = Int32(IPPROTO_TCP)
|
hints.ai_protocol = Int32(IPPROTO_TCP)
|
||||||
var addresses: UnsafeMutablePointer<addrinfo>?
|
var addresses: UnsafeMutablePointer<addrinfo>?
|
||||||
let result = getaddrinfo(host, String(port), &hints, &addresses)
|
let result = getaddrinfo(host, String(port), &hints, &addresses)
|
||||||
@@ -241,7 +241,7 @@ private final class MySQLSocketTransport {
|
|||||||
if let ssl {
|
if let ssl {
|
||||||
var processed = 0
|
var processed = 0
|
||||||
let status = SSLRead(ssl, buffer, count, &processed)
|
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))")
|
throw MySQLWireError(message: "MySQL TLS read failed (OSStatus \(status))")
|
||||||
}
|
}
|
||||||
let n = Darwin.recv(fd, buffer, count, 0)
|
let n = Darwin.recv(fd, buffer, count, 0)
|
||||||
@@ -253,7 +253,7 @@ private final class MySQLSocketTransport {
|
|||||||
if let ssl {
|
if let ssl {
|
||||||
var processed = 0
|
var processed = 0
|
||||||
let status = SSLWrite(ssl, buffer, count, &processed)
|
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))")
|
throw MySQLWireError(message: "MySQL TLS write failed (OSStatus \(status))")
|
||||||
}
|
}
|
||||||
let n = Darwin.send(fd, buffer, count, 0)
|
let n = Darwin.send(fd, buffer, count, 0)
|
||||||
@@ -268,7 +268,7 @@ private final class MySQLSocketTransport {
|
|||||||
// SecureTransport callback connections refer to this retained transport.
|
// SecureTransport callback connections refer to this retained transport.
|
||||||
let connection = Unmanaged.passUnretained(self).toOpaque()
|
let connection = Unmanaged.passUnretained(self).toOpaque()
|
||||||
var status = SSLSetIOFuncs(context, { connection, data, length in
|
var status = SSLSetIOFuncs(context, { connection, data, length in
|
||||||
guard let connection, let data, let length else { return errSecParam }
|
|
||||||
let transport = Unmanaged<MySQLSocketTransport>.fromOpaque(connection).takeUnretainedValue()
|
let transport = Unmanaged<MySQLSocketTransport>.fromOpaque(connection).takeUnretainedValue()
|
||||||
let requested = length.pointee
|
let requested = length.pointee
|
||||||
let n = Darwin.recv(transport.fd, data, requested, 0)
|
let n = Darwin.recv(transport.fd, data, requested, 0)
|
||||||
@@ -276,7 +276,7 @@ private final class MySQLSocketTransport {
|
|||||||
length.pointee = 0
|
length.pointee = 0
|
||||||
return n == 0 ? errSSLClosedGraceful : errSecIO
|
return n == 0 ? errSSLClosedGraceful : errSecIO
|
||||||
}, { connection, data, length in
|
}, { connection, data, length in
|
||||||
guard let connection, let data, let length else { return errSecParam }
|
|
||||||
let transport = Unmanaged<MySQLSocketTransport>.fromOpaque(connection).takeUnretainedValue()
|
let transport = Unmanaged<MySQLSocketTransport>.fromOpaque(connection).takeUnretainedValue()
|
||||||
let n = Darwin.send(transport.fd, data, length.pointee, 0)
|
let n = Darwin.send(transport.fd, data, length.pointee, 0)
|
||||||
if n > 0 { length.pointee = n; return errSecSuccess }
|
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))") }
|
guard status == errSecSuccess else { throw MySQLWireError(message: "TLS peer setup failed (\(status))") }
|
||||||
// REQUIRED encrypts but does not authenticate the server. Keep verification
|
// REQUIRED encrypts but does not authenticate the server. Keep verification
|
||||||
// enabled for the verified mode; never silently fall back to REQUIRED.
|
// enabled for the verified mode; never silently fall back to REQUIRED.
|
||||||
status = SSLSetEnableCertVerify(context, verify)
|
// Certificate verification is handled after the TLS handshake.
|
||||||
guard status == errSecSuccess else { throw MySQLWireError(message: "TLS verification setup failed (\(status))") }
|
status = SSLSetSessionOption(context, .breakOnServerAuth, true)
|
||||||
repeat { status = SSLHandshake(context) } while status == errSSLWouldBlock
|
guard status == errSecSuccess else {
|
||||||
guard status == errSecSuccess else { throw MySQLWireError(message: "MySQL TLS handshake failed (OSStatus \(status))") }
|
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
|
ssl = context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user