是否可以为 system() 调用创建读/写文件句柄



我有一个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 $urn";
        print "USER $un";
        while (<$sslread>) {
            print;
            if (/^+OK.*$/) {
                ## Keep going
                print $sslwrite "PASS $prn";
                print "PASS $pn";
                while (<$sslread>) {
                    print;
                }       
            }       
        }       
        print $sslwrite "QUIT"; 
        print "QUITn";
    }       
}       
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.

我做错了什么?

可以使用

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

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

最新更新