是否可以为system()调用创建读/写FileHandle?

时间:2012-05-25 18:14:29

标签: perl 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 hostname 110”类似,但加密: -

openssl s_client -crlf -connect hostname:995

我希望找到一种方法,我可以在openssl命令上设置某种读/写FileHandle或socket,我可以读取它为空,然后写入所需的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.

我做错了什么?

1 个答案:

答案 0 :(得分:1)

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

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