Jacinta Alice Richardson wrote: > Dear Gisle Aas author of libwww-perl > Joshua Chamas author of Crypt::SSLeay > Graham Barr author of perl-ldap and > Marko Asplund author of IO::Socket::SSL > > First of all, I'd like to say thanks for writing a great set of packages > and releasing them to CPAN for the good of all. > > I'm writing to you today due to a problem I have had when trying to use > these packages in combination, specificially I was trying to use > LWP::UserAgent for HTTP SSL connections as well as Net::LDAPS for LDAP SSL > connections in the same application. To the best of my knowledge these > both rely on IO::Socket::SSL. >
Please post messages such as this in the future to [EMAIL PROTECTED] which is the LWP support mailing list. Posting such questions directly to authors is less good for all of us usually. You just happened to catch me at a good time, but this is not normally the case! :) The problem here I believe is IO::Socket::SSL not working with LWP to connect to your web site, where Crypt::SSLeay does. With perl 5.8, & recent IO::Socket::SSL & LWP, openssl 0.9.6d, I was not able to connect to https://www.nodeworks.com, but when using Crypt::SSLeay instead of IO::Socket::SSL, I was. Net::LDAPS loads IO::Socket::SSL on the back end it seems, so if you use the former, LWP will try to use IO::Socket::SSL for its https connections. To work around this problem for the moment, you might undef $IO::Socket::SSL::VERSION $IO::Socket::SSL::VERSION = undef; AFTER you load Net::LDAPS or IO::Socket::SSL ( might as well "use IO::Socket::SSL" explicity ). This work around however would break as soon as LWP detects IO::Socket::SSL a different way. A better long term fix is for LWP & IO::Socket::SSL to work on your platform. It did not on mine. Getting IO::Socket::SSL to work is not something I will try, but you are more than welcome to dive into the code & send a patch to the author if you find the problem. Regards, Josh ________________________________________________________________ Josh Chamas, Founder phone:714-625-4051 Chamas Enterprises Inc. http://www.chamas.com NodeWorks Link Checking http://www.nodeworks.com > My problem was the following: > > My current job at work is to alter a very successful student service site > to play nicely with a portal we've just bought. > > Currently we require the students to submit their PIN with every change to > their details and hope that that can be avoided with the portal. The first > time that the student comes in from the portal they'll hit a basic auth > page and submit their username and password. From then on the portal will > submit their details to my site and no further PIN or password will be > needed. > > Unfortunately their username will not be their student number, so I need > to make an LDAP query to our LDAP server to get their student number based > on their username. This is easy, I'm using perl-ldap version 0.26. (I did > try perldap but had too much trouble getting it to install on our alpha > machine). > > The machine that our (Forte) database (with all the student's course > details etc) is on is different from where we host the student service. > Access for information and updates for changes are made by web requests > over SSL. This is easy, I'm using the libwww-perl libraries version 5.65. > > My problem is that I can very easily get the student's student number from > LDAP or I can very easily access Forte, but for some reason I can't do > both. > > Originally my code looked like this (heavily simplified): > > ### Forte.pm > package Forte; > use LWP::UserAgent; > > $ENV{HTTPS_VERSION} = '3'; > $ENV{HTTPS_CERT_FILE} = "some.crt"; > $ENV{HTTPS_KEY_FILE} = "some.key"; > > sub callforte > { > ... > my $ua = new LWP::UserAgent; > my $req = new HTTP::Request("POST", "$url"); > ... > my $res = $ua->request($req); > ... > } > > #------------------------------------------ > ### LDAP.pm > package LDAP; > use Net::LDAPS; > > sub LDAP_connect > { > .... > my $conn = new Net::LDAPS($LDAPhost, > port=>$LDAPport, > clientcert=>$cert, > clientkey=>$key); > .... > } > > sub get_student_number > { > LDAP_connect(); > ... > my $entry = $conn->search(filter=>"(uid=$username)", > base=>$base, > attrs=>[qw/studentnumber/]); > if($entry->code()) > { > html_error("Search for student ID for [$username] " . > "failed:". $entry->code() . "\n"); > return 0; > } > > ... > return $entry->{attrs}{studentnumber}[0]; > } > > #------------------------------------------ > #### application > use Forte; > use LDAP; > > # test for connection to db: > $return = Forte::callforte($url, $input); > > ... > > if($using_portal) > { > # get student number > $student_number = LDAP::get_student_number($username); > } > > > I found that if I commented out "use LDAP;" and set "$using_portal" to > false, everything worked as it should, the "$ua->request($req);" takes > some time and returns with code 200 (and any data I want). If I leave > "$using_portal" false, but uncomment "use LDAP;" then when I attempt to > connect to the Forte database the "$ua->request($req);" line returns > immediately with error code 500. The same happened just with commenting > out "use Net::LDAPS;" > > The dependencies (that I know about) and the versions I have installed are > as follows: > > * libwww-perl > o Crypt::SSLeay (version 0.41) > o IO::Socket::SSL (version 0.81) > * perl-ldap > o Convert::ASN1 (version 0.15) > o IO::Socket::SSL (version 0.81) > o Ne::SSLeay (version 1.18) > o URI (version 1.19) > o URI::ldap > o Digest::MD5 (version 2.20) > o XML::Parser (version 2.31) > o MIME::Base64 (version 2.12) > o Authen::SASL (version 2.02) > > "perl -v" yields: This is perl, v5.6.1 built for alpha-dec_osf > > Using "Net::LDAP" and TLS would be a great idea, but TLS isn't supported > in our current LDAP server (iplanet 4.1 I believe). It is supported in > 5.1 but the migration of our data is not trivial. > > I later simplified the code to: > > > #!/servers/web/bin/perl -w > use strict; > > use IO::Socket::SSL; > use LWP::UserAgent; > use Data::Dumper; > > ### LWP Stuff > $ENV{HTTPS_VERSION} = '3'; > # CLIENT CERT SUPPORT > > ### These ENV variables are required by LWP, there > ### exists no other method of telling LWP which > ### certificates should be used. > my $certdbpath = "/some/cert/path/conf/"; > $ENV{HTTPS_CERT_FILE} = "$certdbpath/client.crt"; > $ENV{HTTPS_KEY_FILE} = "$certdbpath/client.key"; > > callforte(); > > exit; > > ############################################## > > sub callforte > { > print "This is libwww-perl-$LWP::VERSION\n"; > print STDERR "This is libwww-perl-$LWP::VERSION\n"; > > # Check we have permission to read the certificates. > open CERT, $ENV{HTTPS_CERT_FILE} or die "not cert :("; > open KEY, $ENV{HTTPS_KEY_FILE} or die "not key :("; > > my $ua = new LWP::UserAgent; > my $req = new HTTP::Request('POST', > 'https://machine.edu.au:123443/cgi-bin/fortecgi?'. > 'pagename=CheckForte'); > > # This is an HTML form > $req->content_type('application/x-www-form-urlencoded'); > > $req->content("dummy_input=1"); > > my $res = $ua->request($req); > > print STDERR $res->code."\n"; > print STDERR $res->content(), "\n"; > print Dumper($res); > return ""; > } > > with the same problem. > > When I attempt my LWP connection, the HTTP::Response _msg is "Can't > connect to machine.edu.au:123443 ()". However no message is recorded in > the server error logs and no access attempt is recorded in the server > access logs. > > Doing a watch of netstat -tn on the forte machine records tcp connections > when the script is run without IO::Socket::SSL but none when that code is > included. Since these connections stick around for a few minutes I suspect > that it isn't just because the script connects and then disconnects super > fast. > > A separate test, changing the host I'm trying to connect to, yeilds > similar results. Attempting to connect to https://www.unimelb.edu.au fails > in exactly the same manner, but connecting to http://www.unimelb.edu.au > responds with a "405: Method Not Allowed" which is good, because the page > doesn't accept POSTs. > > I think the ultimate problem is summed up in these two lines of the > IO::Socket::SSL documentation: > > Currently, the IO::Socket::INET interface as > implemented by this package is not quite complete. > There can be only one SSL context at a given time. > > And this piece of code: > > # > # $Id: https10.pm,v 1.1 2001/10/26 17:27:19 gisle Exp $ > > use strict; > > package LWP::Protocol::https10; > > # Figure out which SSL implementation to use > use vars qw($SSL_CLASS); > if ($IO::Socket::SSL::VERSION) { > $SSL_CLASS = "IO::Socket::SSL"; # it was already loaded > } else { > eval { require Net::SSL; }; # from Crypt-SSLeay > if ($@) { > require IO::Socket::SSL; > $SSL_CLASS = "IO::Socket::SSL"; > } else { > $SSL_CLASS = "Net::SSL"; > } > } > > > However a bigger problem is that this failure is completely silent. One > single use statement in my code makes my previously working LWP requests > silently fail, even when I don't do anything with the module I've loaded! > > I've written this to all of you because I hope this way a solution might > be found that allows all of these modules to work together in harmony. > > Thanks. > Jacinta > > > >
