3

我有一个 POP3 登录测试脚本,用于IO::Socket::INET读取和写入 TCP:110 上打开的套接字。这是我习惯的:-

my $sock = IO::Socket::INET->new(
    PeerAddr    =>  "$h:$port",
    Proto       =>  "tcp",
) or die "$!\n";

但是,我还需要通过 SSL 保护的 POP3S (TCP:995) 测试相同的 POP3 对话。

我发现我可以在命令行上使用以下命令,这使我的状态与“telnet 主机名 110”类似,但已加密:-

openssl s_client -crlf -connect hostname:995

我希望找到一种方法,可以在 openssl 命令上设置某种读/写 FileHandle 或套接字,我可以读取它直到它为空,然后写入所需的 POP3 命令,然后读取响应,等等上...

我觉得因为我可以在屏幕上看到它,所以它足够近,可以抓取,但我不太了解 perl 的方法,无法“获取它”并继续前进!

不幸的是,这个脚本将在服务器上运行,无法安装更多的 perl 模块,这可能是一个明显的解决方案。

更新

感谢@ventatsu 的启发,我现在IPC::Open2这样使用:-

my ($sslread,$sslwrite);
my $ssl_fh = open2(
    $sslread,
    $sslwrite,
    "openssl s_client -crlf -connect mail.example.com:995"
) or die "$!\n";

while (<$sslread>) {
    print;
    if (/^\+OK.*$/) {
        ## Try to log in
        print $sslwrite "USER $u\r\n";
        print "USER $u\n";
        while (<$sslread>) {
            print;
            if (/^\+OK.*$/) {
                ## Keep going
                print $sslwrite "PASS $p\r\n";
                print "PASS $p\n";
                while (<$sslread>) {
                    print;
                }       
            }       
        }       
        print $sslwrite "QUIT"; 
        print "QUIT\n";
    }       
}       

waitpid( $ssl_fh, 0 );
my $child_exit_status = $? >> 8;

我的非 SSL 测试脚本是这样工作的:-

Testing pop3 on mail.example.com:110
+OK The Microsoft Exchange POP3 service is ready.
USER mailtest@example.com
+OK
PASS Abcd3fGh
+OK User successfully logged on.

当我在 CLI 上的交互式 SSL 会话中运行 POP3 命令时,凭据工作正常,如下所示:-

openssl s_client -crlf -connect mail.example.com:995
<snip out the SSL bumph />
+OK The Microsoft Exchange POP3 service is ready.
USER mailtest@example.com
+OK
PASS Abcd3fGh
+OK User successfully logged on.

但是我的 SSL 测试脚本几乎只能这样工作:-

Testing pop3s on mail.example.com:995
<snip out the SSL bumph />
+OK The Microsoft Exchange POP3 service is ready.
USER mailtest@example.com
+OK
PASS Abcd3fGh
-ERR Logon failure: unknown user name or bad password.

我究竟做错了什么?

4

1 回答 1

1

您可以使用IPC::Open2附加两个文件句柄,一个到输入,一个到程序的输出。它可能更接近您真正想要使用IO::Socket::SSL的功能,它的功能类似于IO::Socket::INET但已加密。

更新: 我最好的猜测是你的字符加倍\r。根据s_client -crlf将换行符转换为回车+换行符的手册页。当您打印到$sslwrite要发送的句柄时"\r\n"。我认为结果是服务器会在每个命令结束时收到“\r\r\n”。您可能希望-crlfopenssl程序中的命令中删除 。

于 2012-05-25T18:44:25.340 回答