2012-10-02 10 views
8

Ich portiere eine Anwendung von PHP/CURL zu Perl und LWP :: UserAgent. Ich muss eine POST-Anfrage an einen Webserver stellen und ein Client-Zertifikat und eine Schlüsseldatei bereitstellen. Der PHP-Code, den ich versuche zu replizieren diese:Verwendung von LWP mit SSL und Client-Zertifikaten

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_SSLCERT, "/path/to/certificate.pem"); 
curl_setopt($ch, CURLOPT_SSLKEY, "/path/to/private.key"); 
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, "secretpassword"); 

Und hier ist mein Perl-Code:

my $ua = LWP::UserAgent->new(); 
$ua->ssl_opts(
    SSL_verify_mode => 0, 
    SSL_cert_file => '/path/to/certificate.pem', 
    SSL_key_file => "/path/to/private.key", 
    SSL_passwd_cb => sub { return "secretpassword"; } 
); 

Der PHP-Code erfolgreich eine Verbindung mit dem Server, aber der Perl-Code nicht mit:

SSL Lesefehler Fehler: 14094410: SSL Routinen: SSL3_READ_BYTES: sslv3 Alarm Handshake Fehler

Ich kann nicht herausfinden, was ich vermisse.

+0

Sind die 'private.key' (PHP) und' private.pem' (Perl) ein Tippfehler oder ein Teil der Portierung? – amon

+2

Das Übergeben mehrerer Argumente an [ssl_opts] (https://metacpan.org/module/LWP::UserAgent#ATTRIBUTES) ist nicht dokumentiert. Um sicherzugehen, rufen Sie ssl_opts mehrmals auf oder übergeben Sie sie an den Konstruktor. Ich denke, es funktioniert, aber besser sicher. Sie könnten es auch als Fehler/fehlende Funktion melden (https://rt.cpan.org/Public/Bug/Report.html?Queue=libwww-perl). – Schwern

+0

Das war nur ein Tippfehler, als ich meinen Code verdunkelte. Es sollte private.key für beide sein. Danke fürs merken, aber das ist nicht das Problem. Brauchst du noch immer Hilfe! :) – kent

Antwort

2
sub send_command(){ 
     my $command = shift; 
     my $parser = XML::LibXML->new('1.0','utf-8'); 

     print color ("on_yellow"), "SEND: ", $command, color ("reset"), "\n"; 

     # Create a request 
     my $req = HTTP::Request->new(GET => $Gateway.$command); 

     # Pass request to the user agent and get a response back 
     my $res; 
     eval { 
       my $ua; 
       local $SIG{'__DIE__'}; 
       $ua = LWP::UserAgent->new(); # или 
       $ua->ssl_opts(#$key => $value 
        SSL_version   => 'SSLv3', 
        SSL_ca_file   => '/ca.pem', 
        #SSL_passwd_cb  => sub { return "xxxxx\n"; }, 
        SSL_cert_file  => '/test_test_cert.pem', 
        SSL_key_file  => '/test_privkey_nopassword.pem', 
       ); # ssl_opts => { verify_hostname => 0 } 
       $ua->agent("xxxxxx xxxx_tester.pl/0.1 "); 
       $res = $ua->request($req); 

     }; 
     warn [email protected] if [email protected]; 
     # Check the outcome of the response 
     if ($res->is_success) { 
       open xxxLOG, ">> $dir/XXXX_tester.log"; 
       my $without_lf = $res->content; 
       $without_lf =~ s/(\r|\n)//gm; 
       print PAYLOG $without_lf,"\n"; 
       close PAYLOG; 
     } 
     else { 
       return $res->status_line; 
     }  
     print color ("on_blue"), "RESPONSE: ", color ("reset"), respcode_color($res->content), color ("reset"),"\n\n"; 
     return $res->content; 
} 
3

Die Antwort von oben emazep löste mein Problem. Ich verwende den Perl-Beispielcode von UPS, um über XML eine Verbindung mit dem Tarifservice herzustellen. Aus meinen Tests funktioniert das immer dann, wenn LWP :: UserAgent ohne Argumente aufgerufen wird, die Sie direkt steuern können. Dies ist praktisch, wenn Sie ein anderes Modul verwenden, das Anrufe an LWP für Sie durchführt. Verwenden Sie einfach Net :: SSL (zusätzlich zu was auch immer Pakete LWP bereits verwendet) und stellen ein paar Umgebungsvariablen:

... 
use Net::SSL; 
$ENV{HTTPS_VERSION} = 3; 
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; 
my $browser = LWP::UserAgent->new(); 
... 

Das ist es! Sie sollten den Pfad zum Stammzertifikat Ihres Servers nicht einmal mit $ ENV {PERL_LWP_SSL_CA_FILE} angeben müssen.

1

In der Tat ist dies ein unordentliches Bit. Abhängig von Ihrer Konfiguration kann LWP :: UserAgent eines von (mindestens) zwei SSL-Modulen für die SSL-Verbindung verwenden.

  • IO :: Socket :: SSL
  • Net :: SSL

Die erste der Standard für neuere Versionen von LWP :: Useragent sein sollte. Sie können, welche dieser Test für jedes Modul, indem Sie den Standard-Befehl in einem Terminal installiert sind:

perl -e 'use <module>;' 

IO :: Socket :: SSL erfordert die SSL-Konfiguration mit den ssl_opts wie in Ihrem Beispiel.

Net :: SSL erfordert die SSL-Konfiguration in Umgebungsvariablen wie in goddogsrunnings Antwort.

Persönlich falle ich in die zweite Kategorie und hatte eine gute Inspiration von der Crypt::SSLeay page. Insbesondere der Abschnitt namens "CLIENT CERTIFICATE SUPPORT".

Verwandte Themen