I'm trying to connect my users via SSL from my iOS XMPP chat client to Openfire server.
In my iOS client:
- (void)setupStream
{
...
// BOOL values for security settings
customCertEvaluation = NO;
allowSelfSignedCertificates = YES;
allowSSLHostNameMismatch = NO;
}
In my Openfire server's Security Settings > Client Connection Security, I've set:
Required - Clients can only connect to the server using secured connections.
Thus, the following delegate method will be called:
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
NSString *expectedCertName = [xmppStream.myJID domain];
if (customCertEvaluation)
[settings setObject:@(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
if (allowSelfSignedCertificates)
[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
if (allowSSLHostNameMismatch)
[settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName];
else
if (expectedCertName)
[settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
}
I attempted this solution from this thread: XMPPFramework TLS/SSL connection with Openfire
However, when I run my application and attempt to connect to the server, I'd receive this error:
Security option unavailable - kCFStreamSSLAllowsAnyRoot - You must use manual trust evaluation
I looked through the GCDAsyncSocket
class and realized kCFStreamSSLAllowsAnyRoot
is stated as deprecated. An NSAssert was implemented to deliberately throw the error.
Next, I decided to change my BOOL values as such:
- (void)setupStream
{
...
// BOOL values for security settings
// Manually evaluate trust
customCertEvaluation = YES;
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = NO;
}
This time, again, no connection could be made to the server but, no error was prompted.
I could connect to Openfire fine if I changed the Client Connection Security back to the original setting > Optional. But, I wouldn't be connected via SSL as indicated by a lock icon beside every user's status in Client Sessions.
My Android client (using Smack API for XMPP) connects to Openfire via SSL without issues. So I'm wondering if there's workaround I have to implement for my iOS client using XMPPFramework.
I would greatly appreciate any advices.
Complete the following steps to enable a secure sockets layer (SSL) for the Openfire chat server that runs with Smart IT. Obtain a valid, signed certificate from a trusted certificate authority (CA). The certificate can be in any format, such as .pem, .cer, or .crt. Import the certificate provided by the CA.
xmpp.socket.ssl.port -- the port to use for SSL (default is 5223 for XMPP) xmpp.socket.ssl.storeType -- the store type used ("JKS" is the Sun Java Keystore format used by the JDK keytool). If this property is not defined, Openfire will assume a value of "jks".
The Sun JDK (version 1.5.x) ships with all the security tools you need to configure SSL with Openfire. The most important is the keytool located in the JAVA_HOME/bin directory of the JDK. Sun JVMs persist keystores and truststores on the filesystem as encrypted files.
Obtain a valid, signed certificate from a trusted certificate authority (CA). The certificate can be in any format, such as .pem, .cer, or .crt. Import the certificate provided by the CA. Do these steps for all Openfire nodes, if installed in a cluster.
In the latest version of XMPP (after April 22), you can no longer use allowSelfSignedCertificates = YES
with the following:
if (allowSelfSignedCertificates)
[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];`
This is because kCFStreamSSLAllowsAnyRoot
& SSLSetAllowsAnyRoot
have been deprecated.
/*
* ==== The following UNAVAILABLE KEYS are: (with throw an exception)
* - kCFStreamSSLAllowsAnyRoot (UNAVAILABLE)
* You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust).
* Corresponding deprecated method: SSLSetAllowsAnyRoot
*/
See XMPPFramework/GCDAsyncSocket.h & Deprecated Secure Transport Functions.
Go to Openfire server > Security Settings > Client Connection Security
Check: Required - Clients can only connect to the server using secured connections.
Define variable in AppDelegate
BOOL customCertEvaluation;
Set variable in setupStream
- (void)setupStream
{
...
customCertEvaluation = YES;
}
Set security settings in willSecureWithSettings
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
/*
* Properly secure your connection by setting kCFStreamSSLPeerName
* to your server domain name
*/
[settings setObject:xmppStream.myJID.domain forKey:(NSString *)kCFStreamSSLPeerName];
/*
* Use manual trust evaluation
* as stated in the XMPPFramework/GCDAsyncSocket code documentation
*/
if (customCertEvaluation)
[settings setObject:@(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
}
Validate peer manually
/*
* This is only called if the stream is secured with settings that include:
* - GCDAsyncSocketManuallyEvaluateTrust == YES
* That is, if a delegate implements xmppStream:willSecureWithSettings:, and plugs in that key/value pair.
*/
- (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
/* Custom validation for your certificate on server should be performed */
completionHandler(YES); // After this line, SSL connection will be established
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With