解决 xmpp ios 终端不能正常建立 TLS 连接的问题

先看一下正常流程:

TLS 的使用

概览

XMPP包含的一个保证流安全的方法来防止篡改和偷听.这个传输层安全协议[TLS]的频道加密方法, 模拟了类似的其他"STARTTLS"(见 RFC 2595 [USINGTLS])的扩展,如 IMAP [IMAP], POP3 [POP3], and ACAP [ACAP]."STARTTLS"的扩展名字空间是'urn:ietf:params:xml:ns:xmpp-tls'.
一个给定域的管理员可以(MAY)要求客户端和服务器通信以及服务器之间通信时使用TLS,或者两者都要求。客户端应该(SHOULD)在尝试完成 SASL (第六章)握手之前使用 TLS,服务器应该(SHOULD)在两个域之间使用 TLS 以保证服务器间通信的安全。
以下是使用规则:
  1. 一个遵守本协议的初始化实体必须(MUST)在初始化流的头信息中包含一个'version'属性并把值设为“1.0”。
  2. 如果TLS握手发生在两个服务器之间,除非服务器声称的DNS主机名已经被解析(见第十四章第四节 Server-to-Server Communications),通信不能(MUST NOT)继续进行。
  3. 当一个遵守本协议的接收实体接收了一个初始化流(它的头信息中包含一个'version'属性并且值设为“1.0”),在发送应答流的的头信息(其中包含版本标记)之后,它必须发送(MUST)<starttls/>元素(名字空间为 'urn:ietf:params:xml:ns:xmpp-tls')以及其他它支持的流特性 。
  4. 如果初始化实体选择使用TLS,TLS握手必须在SASL握手之前完成;这个顺序用于帮助保护SASL握手时发送的认证信息的安全,同时可以在必要的时候在TLS握手之前为SASL外部机制提供证书。
  5. TLS握手期间,一个实体不能(MUST NOT)在流的根元素中发送任何空格符号作为元素的分隔符(在下面的TLS示例中的任何空格符都仅仅是为了便于阅读);这个禁令用来帮助确保安全层字节精度。
  6. 接收实体必须(MUST)在发送<proceed/> 元素的关闭符号">" 之后立刻开始TLS协商。初始化实体必须(MUST)在从接收实体接收到<proceed/> 元素的关闭符号">" 之后立刻开始TLS协商。
  7. 初始化实体必须(MUST)验证接收实体出示的证书;关于证书验证流程参见Certificate Validation ( 第十四章第二节)。
  8. 证书必须(MUST)检查初始化实体(比如一个用户)提供的主机名;而不是通过DNS系统解析出来的主机名;例如,如果用户指定一个主机名"example.com"而一个DNS SRV [SRV]查询返回"im.example.com",证书必须(MUST)检查"example.com".如果任何种类的XMPP实体(例如客户端或服务器)的JID出现在一个证书里,它必须(MUST)表现为一个别名实体里面的UTF8字符串,存在于subjectAltName之中。如何使用 [ASN.1] 对象标识符 "id-on-xmppAddr" 定义在本文的第五章第一节第一小节。
  9. 如果 TLS 握手成功了,接收实体必须(MUST) 丢弃TLS 生效之前从初始化实体得到的任何不可靠的信息.
  10. 如果 TLS 握手成功了,初始化实体必须(MUST) 丢弃TLS 生效之前从接收实体得到的任何不可靠的信息.
  11. 如果 TLS 握手成功了,接收实体不能(MUST NOT)在流重新开始的时候通过提供其他的流特性来向初始化实体提供 STARTTLS 扩展.
  12. 如果 TLS 握手成功了,初始化实体必须(MUST)继续进行SASL握手。
  13. 如果 TLS 握手失败了,接收实体必须(MUST)终止XML流和相应的TCP连接。
  14. 关于必须(MUST)支持的机制,参照 Mandatory-to-Implement Technologies (第十四章第七节) 。



xmppframework 开启TLS:

搜索 handleStreamFeatures , 查看里面的代码,它是根据服务器提供的 features 来决定是否启动TLS的。如果服务器没有设置 require TLS ,而你又想要有,则可以直接修改IF判断。


错误处理

如果TLS建立之初连接就被断开了,网络错误提示为: Error Domain=NSOSStatusErrorDomain Code=-9807 "The operation couldn’t be completed. (OSStatus error -9807.)"

那么在 willSecureWithSettings 的函数里面,设置 settings 的属性:

// Allow self-signed certificates
[settings setObject:[NSNumber numberWithBool:YES]
 forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];


参考:

网络的错误编码对应的意义。 SecureTransport.h   在  /System/Library/Frameworks/ Security.framework   :
enum {
  errSSLProtocol                  = -9800,  /* SSL protocol error */
  errSSLNegotiation               = -9801,  /* Cipher Suite negotiation failure */
  errSSLFatalAlert                = -9802,  /* Fatal alert */
  errSSLWouldBlock                = -9803,  /* I/O would block (not fatal) */
  errSSLSessionNotFound           = -9804,  /* attempt to restore an unknown session */
  errSSLClosedGraceful            = -9805,  /* connection closed gracefully */
  errSSLClosedAbort               = -9806,  /* connection closed via error */
  errSSLXCertChainInvalid         = -9807,  /* Invalid certificate chain */
  errSSLBadCert                   = -9808,  /* bad certificate format */
  errSSLCrypto                    = -9809,  /* underlying cryptographic error */
  errSSLInternal                  = -9810,  /* Internal error */
  errSSLModuleAttach              = -9811,  /* module attach failure */
  errSSLUnknownRootCert           = -9812,  /* valid cert chain, untrusted root */
  errSSLNoRootCert                = -9813,  /* cert chain not verified by root */
  errSSLCertExpired               = -9814,  /* chain had an expired cert */
  errSSLCertNotYetValid           = -9815,  /* chain had a cert not yet valid */
  errSSLClosedNoNotify            = -9816,  /* server closed session with no notification */
  errSSLBufferOverflow            = -9817,  /* insufficient buffer provided */
  errSSLBadCipherSuite            = -9818,  /* bad SSLCipherSuite */
  /* fatal errors detected by peer */
  errSSLPeerUnexpectedMsg         = -9819,  /* unexpected message received */
  errSSLPeerBadRecordMac          = -9820,  /* bad MAC */
  errSSLPeerDecryptionFail        = -9821,  /* decryption failed */
  errSSLPeerRecordOverflow        = -9822,  /* record overflow */
  errSSLPeerDecompressFail        = -9823,  /* decompression failure */
  errSSLPeerHandshakeFail         = -9824,  /* handshake failure */
  errSSLPeerBadCert               = -9825,  /* misc. bad certificate */
  errSSLPeerUnsupportedCert       = -9826,  /* bad unsupported cert format */
  errSSLPeerCertRevoked           = -9827,  /* certificate revoked */
  errSSLPeerCertExpired           = -9828,  /* certificate expired */
  errSSLPeerCertUnknown           = -9829,  /* unknown certificate */
  errSSLIllegalParam              = -9830,  /* illegal parameter */
  errSSLPeerUnknownCA             = -9831,  /* unknown Cert Authority */
  errSSLPeerAccessDenied          = -9832,  /* access denied */
  errSSLPeerDecodeError           = -9833,  /* decoding error */
  errSSLPeerDecryptError          = -9834,  /* decryption error */
  errSSLPeerExportRestriction     = -9835,  /* export restriction */
  errSSLPeerProtocolVersion       = -9836,  /* bad protocol version */
   errSSLPeerInsufficientSecurity  = -9837,  /* insufficient security */
  errSSLPeerInternalError         = -9838,  /* internal error */
  errSSLPeerUserCancelled         = -9839,  /* user canceled */
  errSSLPeerNoRenegotiation       = -9840,  /* no renegotiation allowed */

  /* more errors detected by us */
  errSSLHostNameMismatch          = -9843,  /* peer host name mismatch */
  errSSLConnectionRefused         = -9844,  /* peer dropped connection before responding */
  errSSLDecryptionFail            = -9845,  /* decryption failure */
  errSSLBadRecordMac              = -9846,  /* bad MAC */
  errSSLRecordOverflow            = -9847,  /* Record Overflow */
  errSSLBadConfiguration          = -9848,  /* configuration error */
  errSSLLast                      = -9849   /* end of range, to be deleted */
};



// Allow expired certificates
[settings setObject:[NSNumber numberWithBool:YES]
 forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];

// Allow self-signed certificates
[settings setObject:[NSNumber numberWithBool:YES]
 forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];

// In fact, don't even validate the certificate chain
[settings setObject:[NSNumber numberWithBool:NO]
 forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];

参考自  https://groups.google.com/forum/#!topic/xmppframework/K2iIPX1f3lM


你可能感兴趣的:(解决 xmpp ios 终端不能正常建立 TLS 连接的问题)