objective-c - 通过套接字与 ESMTP 协商 TLS

标签 objective-c cocoa sockets smtp ssl

我有一个简单的 SMTP 客户端,我正在尝试向其添加 TLS 支持。我不确定客户端发出“STARTTLS”命令后会发生什么。大多数来源(包括 RFC 本身)将其描述为 TLS session 的协商,但这并不是特别清楚。

如何做这件事?我的客户端是用 Objective C 编写的,并使用 Cocoa 的流对象(套接字的包装器)。 Cocoa 流可以使用 NSStream 的 setProperty 函数将 TLS 指定为套接字安全级别系统。

然而,这似乎必须在连接打开之前完成。如果是这种情况,那么客户端是否希望在从服务器(响应 STARTTLS)收到代码 220 后断开连接,然后在指定 TLS 时重新连接?

或者更确切地说,这只是 NSStream 的限制吗?普通套接字是否在未关闭的情况下重新协商 TLS 或 SSL?

此外,一旦发出 STARTTLS 并完成后续协商,客户端是否需要任何其他编码/解码?

如果这些是简单的问题,我们深表歉意。我很难找到合适的例子。

干杯!

最佳答案

我刚刚发现 NSStream 允许您通过设置 kCFStreamSSLLevel 属性并重新打开流,将已经激活的非 TLS 连接升级到 TLS。我刚刚在与 smtp.gmail.com:25 的 SMTP 连接上对此进行了测试,令人惊讶的是它有效!我正在描述 NSStream/SMTP 序列以防有人感兴趣:

NSHost* host = [NSHost hostWithName:address];
[NSStream getStreamsToHost:host port:port inputStream:&is outputStream:&os];
[is setDelegate:self];
[os setDelegate:self];
[is scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[os scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[is open];
[os open];

SMTP 对话,直到我们发送 STARTTLS 并且服务器说 OK:

-> 220 mx.google.com ESMTP gb6sm4472052wbb.0
<- EHLO example.address.com
-> 250-mx.google.com at your service, [84.227.165.204]
-> 250-SIZE 35882577
-> 250-8BITMIME
-> 250-STARTTLS
-> 250 ENHANCEDSTATUSCODES
<- STARTTLS
-> 220 2.0.0 Ready to start TLS

此时我们执行以下命令将套接字升级到 SSL:

NSMutableDictionary* settings = [NSMutableDictionary dictionary];
[settings setObject:NSStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel];
[settings setObject:address forKey:(NSString*)kCFStreamSSLPeerName];
[is setProperty:settings forKey:(NSString*)kCFStreamPropertySSLSettings];
[os setProperty:settings forKey:(NSString*)kCFStreamPropertySSLSettings];
[is open];
[os open];

我们现在可以像以前一样使用 is 和 os 了。现在可用的 AUTH 选项证明服务器认为连接是安全的。

<- EHLO example.address.com
-> 250-mx.google.com at your service, [84.227.165.204]
-> 250-SIZE 35882577
-> 250-8BITMIME
-> 250-AUTH LOGIN PLAIN XOAUTH
-> 250 ENHANCEDSTATUSCODES
<- AUTH PLAIN hIdDeNbAsE64dAtA
-> 235 2.7.0 Accepted
<- MAIL FROM: <example.address@gmail.com>
-> 250 2.1.0 OK gb6sm4472052wbb.0
<- RCPT TO: <another.address@gmail.com>
-> 250 2.1.5 OK gb6sm4472052wbb.0
<- DATA
<- From: =?UTF-8?B?QWxlc3NhbmRybyBWb2x6?= <example.address@gmail.com>
<- To: =?UTF-8?B?QWxl?= <another.address@gmail.com>
<- Subject: =?UTF-8?B?VGVzdA==?=
<- Mime-Version: 1.0;
<- Content-Type: text/html; charset="UTF-8";
<- Content-Transfer-Encoding: 7bit;
<- 
<- Ciao!
<- .
-> 354  Go ahead gb6sm4472052wbb.0
-> 250 2.0.0 OK 1307994916 gb6sm4472052wbb.0
<- QUIT
-> 221 2.0.0 closing connection gb6sm4472052wbb.0

我希望这对某人有用... 干杯,

关于objective-c - 通过套接字与 ESMTP 协商 TLS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3262557/

相关文章:

ios - iOS 如何存储用户数据

ios - UIWebView 在文本字段焦点后滚动

cocoa - 两个给定 NSDate 之间的 NSDate

objective-c - 在运行时发现类的哪些实例变量被声明为 __weak

objective-c - 验证 if 语句语法

python - 我无法理解 python 中的轮询/选择

linux - UDP 套接字上的接收通知

ios - 在整个应用程序中将默认字体更改为自定义字体

objective-c - 破译崩溃报告

关闭 BSD 套接字中的套接字