Haskell中的Gmail TLS hanshake失败(Gmail TLS hanshake failure in haskell)

编程入门 行业动态 更新时间:2024-10-24 22:23:24
Haskell中的Gmail TLS hanshake失败(Gmail TLS hanshake failure in haskell)

我正在尝试编写一个小脚本来通过gmail发送电子邮件。 我可以连接到Gmail,但是当我尝试遮住它时失败。 任何获得握手的指针都可以去?

这是代码:

import Network.Socket import Network import Network.TLS import Network.TLS.Extra import Crypto.Random import Data.CertificateStore -- to remove import System.Certificate.X509 --to use I think import System.IO import Text.Printf import Control.Monad (forever) import qualified Data.ByteString.Char8 as B main :: IO () main = emailGmail2 tListen :: Context -> IO () tListen ctx = forever $ recvData ctx >>= B.putStrLn cWrite :: Handle -> String -> IO () cWrite h s = do hPrintf h "%s\r\n" s printf "> %s\n" s cListen :: Handle -> IO () cListen h = forever $ hGetLine h >>= putStrLn emailGmail2 = do let host = "smtp.gmail.com" port = 587 params = defaultParamsClient g <- newGenIO :: IO SystemRandom h <- connectTo host (PortNumber (fromIntegral port)) hSetBuffering h LineBuffering cWrite h "EHLO" cWrite h "STARTTLS" --cListen h con <- contextNewOnHandle h params g handshake con tListen con

这是错误:

HandshakeFailed(Error_Packet_Parsing“Failed reading:invalid header type:50 \ nFrom:\ theader \ n \ n”)

I am trying to write a little script to send an email via gmail. I can connect to gmail but when I try to hanshake it fails. Any pointers to get the handshake a go?

Here is the code:

import Network.Socket import Network import Network.TLS import Network.TLS.Extra import Crypto.Random import Data.CertificateStore -- to remove import System.Certificate.X509 --to use I think import System.IO import Text.Printf import Control.Monad (forever) import qualified Data.ByteString.Char8 as B main :: IO () main = emailGmail2 tListen :: Context -> IO () tListen ctx = forever $ recvData ctx >>= B.putStrLn cWrite :: Handle -> String -> IO () cWrite h s = do hPrintf h "%s\r\n" s printf "> %s\n" s cListen :: Handle -> IO () cListen h = forever $ hGetLine h >>= putStrLn emailGmail2 = do let host = "smtp.gmail.com" port = 587 params = defaultParamsClient g <- newGenIO :: IO SystemRandom h <- connectTo host (PortNumber (fromIntegral port)) hSetBuffering h LineBuffering cWrite h "EHLO" cWrite h "STARTTLS" --cListen h con <- contextNewOnHandle h params g handshake con tListen con

And here's the error:

HandshakeFailed (Error_Packet_Parsing "Failed reading: invalid header type: 50\nFrom:\theader\n\n")

最满意答案

此错误部分与处理SMTP协议有关。 通过TLS RFC 2487查看Secure SMTP的RFC,有一个示例客户端 - 服务器对话。

S: <waits for connection on TCP port 25> C: <opens connection> S: 220 mail.imc.org SMTP service ready C: EHLO mail.ietf.org S: 250-mail.imc.org offers a warm hug of welcome S: 250 STARTTLS C: STARTTLS S: 220 Go ahead C: <starts TLS negotiation> C & S: <negotiate a TLS session> C & S: <check result of negotiation> C: <continues by sending an SMTP command> . . .

在您的代码中,您正在发送EHLO和STARTTLS,然后立即开始握手协商。 我相信发生的事情是服务器仍在发送上面的250和220代码中的一部分,TLS库试图将这些代码解释为导致问题的TLS消息。

事实上,如果我打开另一个终端并使用netcat监听端口587,并将程序更改为连接到本地主机,则我会收到同样的错误,如果我回复“250 STARTTLS”

改变它让程序为我工作:

import Network.Socket import Network import Network.TLS import Network.TLS.Extra import Crypto.Random import qualified Crypto.Random.AESCtr as RNG import System.IO import Text.Printf import Control.Monad (when) import Data.List (isPrefixOf) ciphers :: [Cipher] ciphers = [ cipher_AES128_SHA1 , cipher_AES256_SHA1 , cipher_RC4_128_MD5 , cipher_RC4_128_SHA1 ] main :: IO () main = emailGmail2 cWrite :: Handle -> String -> IO () cWrite h s = do hPrintf h "%s\r\n" s printf "> %s\n" s cWaitFor :: Handle -> String -> IO () cWaitFor h str = do ln <- hGetLine h putStrLn ln when (not $ str `isPrefixOf` ln) (cWaitFor h str) emailGmail2 = do let host = "smtp.gmail.com" port = 587 params = defaultParamsClient{pCiphers = ciphers} g <- RNG.makeSystem h <- connectTo host (PortNumber (fromIntegral port)) hSetBuffering h LineBuffering cWrite h "EHLO" cWaitFor h "250-STARTTLS" cWrite h "STARTTLS" cWaitFor h "220" con <- contextNewOnHandle h params g handshake con bye con

另请注意,我需要从Network.TLS.Extras添加一些密码,否则我会收到Illegal Parameter错误。 我找到了这个代码,并在Github 页面上添加了来自Vincent测试的日志记录。

另一个注意事项:如果遇到更多问题,我应该指出我使用命令行程序gnutls-cli和ssldump来用上面提到的密码来调试问题。

This error is partially to do with handling the SMTP protocol. Looking at the RFC for Secure SMTP over TLS RFC 2487 there is an example client-server dialogue.

S: <waits for connection on TCP port 25> C: <opens connection> S: 220 mail.imc.org SMTP service ready C: EHLO mail.ietf.org S: 250-mail.imc.org offers a warm hug of welcome S: 250 STARTTLS C: STARTTLS S: 220 Go ahead C: <starts TLS negotiation> C & S: <negotiate a TLS session> C & S: <check result of negotiation> C: <continues by sending an SMTP command> . . .

In your code you are sending EHLO and STARTTLS, and then immediately beginning the handshake negotiation. I believe what is happening is that the server is still sending some of the 250 and 220 codes above and the TLS library is trying to interpret these as TLS messages which is causing the problem.

Indeed if I open another terminal and listen to port 587 with netcat and change the program to connect to localhost I get the same error if I reply with "250 STARTTLS"

Changing this got the program to work for me:

import Network.Socket import Network import Network.TLS import Network.TLS.Extra import Crypto.Random import qualified Crypto.Random.AESCtr as RNG import System.IO import Text.Printf import Control.Monad (when) import Data.List (isPrefixOf) ciphers :: [Cipher] ciphers = [ cipher_AES128_SHA1 , cipher_AES256_SHA1 , cipher_RC4_128_MD5 , cipher_RC4_128_SHA1 ] main :: IO () main = emailGmail2 cWrite :: Handle -> String -> IO () cWrite h s = do hPrintf h "%s\r\n" s printf "> %s\n" s cWaitFor :: Handle -> String -> IO () cWaitFor h str = do ln <- hGetLine h putStrLn ln when (not $ str `isPrefixOf` ln) (cWaitFor h str) emailGmail2 = do let host = "smtp.gmail.com" port = 587 params = defaultParamsClient{pCiphers = ciphers} g <- RNG.makeSystem h <- connectTo host (PortNumber (fromIntegral port)) hSetBuffering h LineBuffering cWrite h "EHLO" cWaitFor h "250-STARTTLS" cWrite h "STARTTLS" cWaitFor h "220" con <- contextNewOnHandle h params g handshake con bye con

Also note that I needed to add some ciphers from Network.TLS.Extras as otherwise I got an Illegal Parameter error. I found the code for this and to add logging from Vincent's tests on the Github page.

Another note: In case you run into more issues I should point out that I used the command line programs gnutls-cli and ssldump to debug the issue with ciphers mentioned above.

更多推荐

本文发布于:2023-07-29 20:12:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1319423.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:TLS   Gmail   Haskell   haskell   failure

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!