2012-10-02 21 views
8

Estoy portando una aplicación de PHP/cURL a Perl y LWP :: UserAgent. Necesito hacer una solicitud POST a un servidor web y proporcionar un certificado de cliente y un archivo de clave. El código PHP que estoy tratando de reproducir es la siguiente:Uso de LWP con SSL y certificados de cliente

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"); 

Y aquí está mi código Perl:

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"; } 
); 

el código PHP se conecta correctamente al servidor pero el código Perl falla con:

Error de error de lectura de SSL: 14094410: rutinas SSL: SSL3_READ_BYTES: falla de protocolo de alerta de sslv3

No me puedo dar cuenta de lo que me estoy perdiendo.

+0

¿Es el 'private.key' (PHP) y' private.pem' (Perl) un error o parte del porting? – amon

+2

Pasar varios argumentos a [ssl_opts] (https://metacpan.org/module/LWP::UserAgent#ATTRIBUTES) no está documentado. Para estar seguro, llame a ssl_opts varias veces o páselos al constructor. Creo que funciona, pero es más seguro. También podría [informarlo como una función error/faltante] (https://rt.cpan.org/Public/Bug/Report.html?Queue=libwww-perl). – Schwern

+0

Eso fue solo un error cuando oculté mi código. Debería ser private.key para ambos. Gracias por notarlo pero ese no es el problema. ¡Aún necesitas ayuda! :) – kent

Respuesta

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

La respuesta de emazep anterior resolvió mi problema. Estoy usando el código Perl de muestra de UPS para conectarme a su servicio Rate a través de XML. Según mis pruebas, esto funcionará cada vez que se llame a LWP :: UserAgent sin argumentos que pueda controlar directamente, lo que lo hace útil si está utilizando algún otro módulo que haga llamadas a LWP por usted. Sólo tiene que utilizar Net :: SSL (además de cualesquiera paquetes ya han utilizado LWP) y establecer algunas variables de entorno:

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

eso es todo! Ni siquiera debería necesitar especificar la ruta al certificado raíz de su servidor con $ ENV {PERL_LWP_SSL_CA_FILE}.

1

De hecho, esto es un poco complicado. Dependiendo de su configuración, LWP :: UserAgent puede usar uno de (al menos) dos módulos SSL para manejar la conexión SSL.

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

El primero de ellos debe ser el valor por defecto para las nuevas versiones de LWP :: agente de usuario. Puede probar cuál de éstas se instalan mediante la ejecución del comando estándar en un terminal para cada módulo:

perl -e 'use <module>;' 

IO :: Socket :: SSL requiere la configuración de SSL con las ssl_opts como en su ejemplo.

Net :: SSL requiere la configuración de SSL en variables de entorno como en goddogsrunnings answer.

Personalmente caigo en la segunda categoría y tuve una buena inspiración de Crypt::SSLeay page. Particularmente la sección llamada "APOYO AL CERTIFICADO DEL CLIENTE".

Cuestiones relacionadas