Skip to content
This repository was archived by the owner on Jun 7, 2020. It is now read-only.

[NEW] Support self-signed certificates for SSL (WebSocket & REST) #708

Description

@ispcolohost
  • Your Rocket.Chat app version: 1.4.0 (96)
  • Your Rocket.Chat server version: 0.58.2
  • Device (or Simulator) you're running with: iPad Mini 4 on 11.0

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.

Activity

  1. rafaelks commented on Sep 24, 2017

    @rafaelks
    Contributor

    @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.

    👍

  2. changed the title [-]iOS client certificate-based access?[/-] [+][INVESTIGATE] iOS client certificate-based access?[/+] on Sep 24, 2017
  3. xingchen966 commented on Nov 1, 2017

    @xingchen966

    @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:

    1. 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

    2. 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)

  4. xingchen966 commented on Nov 1, 2017

    @xingchen966

    @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)
          }
    }
    
  5. cardoso commented on Nov 1, 2017

    @cardoso
    Member

    Hi @xingchen966.

    1. Can you open a separate issue for this problem?
    2. I think we fixed the markdown crash in the latest version.

    Thanks for the feedback.

  6. added a commit that references this issue on Nov 1, 2017
  7. rafaelks commented on Nov 9, 2017

    @rafaelks
    Contributor

    Starscream now supports SSL pinning, so this issue could be closed: https://github.com/daltoniam/Starscream#ssl-pinning.

  8. ntvis commented on Nov 22, 2017

    @ntvis

    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?

  9. changed the title [-][INVESTIGATE] iOS client certificate-based access?[/-] [+][NEW] Support self-signed certificates for SSL (WebSocket & REST)[/+] on Jan 24, 2018
  10. atc07 commented on Jan 26, 2018

    @atc07

    @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?

  11. cardoso commented on Jan 26, 2018

    @cardoso
    Member

    @achen954 can you submit a pull request with the code? We'll review it and integrate with the main project if possible. Thanks!

  12. atc07 commented on Feb 23, 2018

    @atc07

    @cardoso One of our other team members will do so shortly. Thanks for your patience.

  13. atc07 commented on Mar 8, 2018

    @atc07

    @cardoso @rafaelks We submitted through #1387. Let me know if you have any questions.

  14. dersimn commented on Apr 30, 2018

    @dersimn

    @ispcolohost

    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.

  15. ispcolohost commented on Apr 30, 2018

    @ispcolohost
    Author

    @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.pem

    After 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/
    
  16. Sameesunkaria commented on Aug 31, 2018

    @Sameesunkaria
    Contributor

    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/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions