Post

Replies

Boosts

Views

Activity

Reply to Charts: customising chartYAxis values
As a more general question, I'm trying to use the format: parameter of AxisValueLabel to format axis values of type Int. According to the documentation format: takes a FormatStyle so I would expect that something like this would work: AxisValueLabel(format: .number.sign(strategy: .always())) The code completion in Xcode offers this as an option, but any attempt to format a number like this throws a Ambiguous use of number error from the compiler. Am I missing something?
Jun ’22
Reply to Add pem certificate in URLSession to call Phillips Hue device API
I'm also a novice with TLS and struggling with this interface. Following Quinn's example code I ended up with this for the session delegate: import Foundation class NSURLSessionPinningDelegate: NSObject, URLSessionDelegate {     func urlSession(_ session: URLSession,                       didReceive challenge: URLAuthenticationChallenge,                       completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {         if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {             if let serverTrust = challenge.protectionSpace.serverTrust {                 Task {                     let result = await shouldAllowHTTPSConnection(trust: serverTrust)                     if result == true {                         completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: serverTrust))                     } else {                         completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)                     }                 }             }         }     }     func shouldAllowHTTPSConnection(chain: [SecCertificate]) async throws -> Bool {         let anchor = Bundle.module.certificateNamed("phillips-hue-cert")!         let policy = SecPolicyCreateBasicX509()         let trust = try secCall { SecTrustCreateWithCertificates(chain as NSArray, policy, $0) }         let err = SecTrustSetAnchorCertificates(trust, [anchor] as NSArray)         guard err == errSecSuccess else {             throw NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil)         }         var secresult: CFError? = nil         let status = SecTrustEvaluateWithError(trust, &secresult)         return status      }     func shouldAllowHTTPSConnection(trust: SecTrust) async -> Bool {         guard let chain = SecTrustCopyCertificateChain(trust) as? [SecCertificate] else { return false }         do {             return try await shouldAllowHTTPSConnection(chain: chain)         } catch {             return false         }     }     func secCall<Result>(_ body: (_ resultPtr: UnsafeMutablePointer<Result?>) -> OSStatus  ) throws -> Result {         var result: Result? = nil         let err = body(&result)         guard err == errSecSuccess else {             throw NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil)         }         return result!     } } extension Bundle {     func certificateNamed(_ name: String) -> SecCertificate? {         guard             let certURL = self.url(forResource: name, withExtension: "cer"),             let certData = try? Data(contentsOf: certURL),             let cert = SecCertificateCreateWithData(nil, certData as NSData)         else {             return nil         }         return cert     } } The delegate is called as expected and the result from shouldAllowHTTPSConnection is true!. My URLSession is set up as:         let session = URLSession(             configuration: URLSessionConfiguration.default,                                 delegate: NSURLSessionPinningDelegate(),                                 delegateQueue: OperationQueue.main) BUT a call to let (data, response) = try await session.data(for: request, delegate: nil) returns a 403 status. I'm at a loss how to debug that as it looks fine up to that point. Clearly I'm doing something wrong with the certificates (I suspect with the delegate callback) but I've no idea what...
Nov ’22
Reply to Trusted certificate is not trusted
Thanks, I had tried something like that, even just forcing shouldAllowHTTPSConnection(trust: response to true to see if that was the problem, but I still always get the same The certificate for this server is invalid. You might be connecting to a server that is pretending to be “192.168.86.200 ...” error. NSAllowsLocalNetworking property is not set as (a) I'm running macOS 14.5 so it should not be necessary, and (b) I can't work out how to set Info.plist values in a command line app that has no Bundle....
Jul ’24
Reply to Trusted certificate is not trusted
Sorry that's not working, something strange going on here... I created a new command line tool in Xcode using that exact same code just replacing https://self-signed.badssl.com with https:192.168.86.200:8444/smarthome/rooms I also checked that the challenge was NSURLAuthenticationMethodServerTrust Response is the same as I had before... will run task did not run task, error: NSURLErrorDomain / -1202 boringssl_context_handle_fatal_alert(2,072) [C1.1.1:2][0x157e07280] read alert, level: fatal, description: bad certificate boringssl_session_handshake_incomplete(210) [C1.1.1:2][0x157e07280] SSL library error boringssl_session_handshake_error_print(44) [C1.1.1:2][0x157e07280] Error: 5770378176:error:10000412:SSL routines:OPENSSL_internal:SSLV3_ALERT_BAD_CERTIFICATE:/AppleInternal/Library/BuildRoots/a8fc4767-fd9e-11ee-8f2e-b26cde007628/Library/Caches/com.apple.xbs/Sources/boringssl/ssl/tls_record.cc:592:SSL alert number 42 nw_protocol_boringssl_handshake_negotiate_proceed(779) [C1.1.1:2][0x157e07280] handshake failed at state 12,288: not completed Connection 1: received failure notification Connection 1: failed to connect 3:18,446,744,073,709,541,808, reason 18,446,744,073,709,551,615 Connection 1: encountered error(3:18,446,744,073,709,541,808) Task <857020EA-0B48-44DF-ABE3-E869745E0696>.<1> HTTP load failed, 0/0 bytes (error code: 18,446,744,073,709,550,414 [3:18,446,744,073,709,541,808]) Task <857020EA-0B48-44DF-ABE3-E869745E0696>.<1> finished with error [18,446,744,073,709,550,414] Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “192.168.86.200” which could put your confidential information at risk." UserInfo={NSErrorFailingURLStringKey=https://192.168.86.200:8444/smarthome/rooms, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <857020EA-0B48-44DF-ABE3-E869745E0696>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <857020EA-0B48-44DF-ABE3-E869745E0696>.<1>" ), NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “192.168.86.200” which could put your confidential information at risk., NSErrorFailingURLKey=https://192.168.86.200:8444/smarthome/rooms, NSUnderlyingError=0x60000010ccf0 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=1, _kCFNetworkCFStreamSSLErrorOriginalValue=-9808, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9808, _NSURLErrorNWPathKey=satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, dns, uses wifi}}, _kCFStreamErrorCodeKey=-9808} Program ended with exit code: 0 I'm running macOS 14.5 and Xcode 15 (15A240d). .. The only difference I can see is my hard-coded IP address, although I tried with the device name (https://shc403ac8.local:8444/smarthome/rooms) and that didn't work either ... do you have any other ideas? I could try the Xcode 16 beta but I'm not sure that's going the issue... Thanks
Jul ’24
Reply to Trusted certificate is not trusted
Doh!! I have found it.... I am also receiving a NSURLAuthenticationMethodClientCertificate challenge that was falling into the section for .performDefaultHandling and was causing the error as no certificate was exchanged from my side (although the error messages imply that the problem was the certificate from the accessory). I needed to create an identity from the certificate and key I used to set up the connection to the accessory, store it in my keychain and then return that as the client credential from the challenge... and it works Thanks for your help, this security and identity stuff is certainly a long learning curve...
Jul ’24