[NEW] Support self-signed certificates for SSL (WebSocket & REST) #708
Description
Activity
@ispcolohost Hey, thanks for opening this issue. That's really an issue we have on the app today. We certainly have a way to handle this, but I think you'll need to add the certificate into the bundle and generate the app binary yourself. I'll let this issue opened so we can investigate.
👍
- changed the title
[-]iOS client certificate-based access?[/-][+][INVESTIGATE] iOS client certificate-based access?[/+]on Sep 24, 2017 @rafaelks
Hi, we also have the same needs, based on the company's self-issued certificate. But now we have now solved this problem. You can push the code up, and share with the community, where the design to the two libraries "Rocket.Chat" and "Starscream". In addition, we also found some versions of the Bug:-
If the server URL is filled with the path of the service will be a problem. Such as "https://192.168.1.100/chat", because in the code "API / Requests" package such as
/ api / v1 / info
These paths are fixed, if the server URL is with the address you need to modify the path to
/ chat / api / v1 / info -
The hyperlink in the chat content resolves the bug. In "RCMarkdownParser.swift":
let linkTextRange = NSRange (location: linkEnd.location + 1, length: match.range.length - linkEnd.location - 2)
change into
let linkTextRange = NSRange (location: linkEnd.location + 1, length: match.range.length - linkUrlRange.length - 3)
-
@rafaelks
Dependency library has also been modified.
"SscContextIn" and "sslContextOut" in "WebSocket.swift" in the "Starscream" library need to be submitted to the client certificate:let path: String = "\(NSHomeDirectory())/Documents/" + prePath! let PKCS12Data = NSData(contentsOfFile: path)! let key: NSString = kSecImportExportPassphrase as NSString let options: NSDictionary = [key: "123456"] //Client certificate password var items: CFArray? securityError = SecPKCS12Import(PKCS12Data, options, &items) if securityError == errSecSuccess { let certItems: CFArray = items as CFArray! let certItemsArray: Array = certItems as Array let dict: AnyObject? = certItemsArray.first if let certEntry: Dictionary = dict as? Dictionary<String, AnyObject> { // grab the identity let identityPointer: AnyObject? = certEntry["identity"] var secIdentityRef: SecIdentity = identityPointer as! SecIdentity! // set identity let secIdentityRefRawPointer = Unmanaged.passUnretained(secIdentityRef).toOpaque() let secIdentityRefPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 1) secIdentityRefPointer.initialize(to: secIdentityRefRawPointer) var certRefs: CFArray = CFArrayCreate(kCFAllocatorDefault, secIdentityRefPointer, 1, nil) SSLSetCertificate(sslContextIn, certRefs) SSLSetCertificate(sslContextOut, certRefs) } }Hi @xingchen966.
- Can you open a separate issue for this problem?
- I think we fixed the markdown crash in the latest version.
Thanks for the feedback.
Starscream now supports SSL pinning, so this issue could be closed: https://github.com/daltoniam/Starscream#ssl-pinning.
hi rafaelks
SSL pinning is used to verify server certificate, If server need a client certificate, we still need xingchen966's patch. so ,could you open the issue again?- changed the title
[-][INVESTIGATE] iOS client certificate-based access?[/-][+][NEW] Support self-signed certificates for SSL (WebSocket & REST)[/+]on Jan 24, 2018 @rafaelks We updated the app on our end to work fully with Client Side SSL. This involves sharing the Client Certificate from the mail app to the RocketChat app. The Client Side SSL is agnostic and should work with any Rocket Chat server that has client certificates. Should we upload to the app store ourselves? or do you want the code to update on the store officially?
@achen954 can you submit a pull request with the code? We'll review it and integrate with the main project if possible. Thanks!
@cardoso One of our other team members will do so shortly. Thanks for your patience.
You said you got the client-cert authentification working for the website version.
Could you post the (probably Nginx) config file? I‘ve troubles to achieve exactly this for iOS.
@dersimn I did it in apache but you can probably adapt my config to nginx. It is really simple. You take the CA certificate from whatever is managing your client certs, keep that in sync on the web server, and point at it with:
SSLCACertificateFile /etc/httpd/conf.d/rocketchat-ca.crt
You'll also want to require cert auth: SSLVerifyClient require
and then finally you'll have to also keep the revocation list in sync:
SSLCARevocationCheck leaf
SSLCARevocationFile /etc/httpd/conf.d/rocketchat-crl.pemAfter that, we have the mod proxy directives (you'll have to have loaded mod proxy):
RewriteEngine On RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteRule /(.*) wss://192.0.2.1/$1 [P,L] RewriteCond %{HTTP:Upgrade} !=websocket [NC] RewriteRule /(.*) https://192.0.2.1/$1 [P,L] SSLProxyEngine on ProxyPassReverse / https://my_rocket_server/Guys, please refer to this guide for setting up your own root certificate and distributing it on the devices of the users.
https://rocket.chat/docs/developer-guides/mobile-apps/supporting-ssl/
Hi all, we have a reverse proxy in front of our RocketChat for employees to access from the outside securely. It requires a client SSL certificate. This was a non-issue on regular computers; just requires some generating of CSRs and we sign them internally, push back the resulting cert.
On the iOS side, we've run into an issue where only Safari seems to be able to connect to our certificate-based proxy server, so the RocketChat app doesn't work externally. The steps that have been taken were to generate a key and cert on the server side since iOS doesn't have that functionality. Turn the resulting cert and key into a PKCS#12 (.p12) format file. Get the file over to the iOS device, click it, tell it to install. Once that is done, the certificate is visible under Settings -> General -> Profile. If you fire up Safari iOS and hit our RocketChat external URL, it prompts to use the cert, then RocketChat works great. RocketChat+ App does not prompt and just says can't connect.
I don't know the internal workings of the app and how it makes its requests, but wanted to bring this up in case there's any chance of modifying it in a way that would either front-end Safari in some hidden way, or perhaps make use of additional iOS functions that would allow it to gain access to the 'Profile' certificates. Or perhaps Apple has locked that away and such a setup would be impossible.