Perl and secure server questions

I’m proficient at C++ programming. I can look usually at code in other languages and figure out what it’s doing. I don’t know much Perl, but now I’m forced to use it to help some friends implement their merchant account. I spent a good deal of time last night researching a problem that I have with this implementation. I found similar questions asked in many places, but never really answered. It’s beginning to make me think that what I (and others) want to do is not easy if at all possible, even though I think it should be.

The problem seems like a very simple thing on the surface. Here is an example. A user hits an “order” button on a HTML page. This form POSTs to a Perl script that adds in some login information, a verification key, and an invoice number. This Perl script then needs to POST this data to an off site page belonging to the gateway provider.

So the flow looks like this:

HTML order page (friend’s site) --> Perl script (friend’s site) --> gateway (off site)

I know how to do a simple redirection from the Perl script, but the only way I could include form data would be to use the GET style with the form data appended to the URL. There is some sensitive information that I really don’t want appearing on a browser’s address bar. Besides, the gateway provider specifies POSTed data.

So, my first question is:

1) How do I POST form data from a Perl script to an off site web page?

The typical answer that I see on other boards is, “look up lwpcook.” I did that. Here is the closest thing that I could find in the lwpcook man page:

use LWP::UserAgent;
$ua = LWP::UserAgent->new;

my $req = HTTP::Request->new(POST => ‘http://www.perl.com/cgi-bin/BugGlimpse’);
$req->content_type(‘application/x-www-form-urlencoded’);
$req->content(‘match=www&errors=0’);

my $res = $ua->request($req);
print $res->as_string;

The problem is this leaves the client’s browser at my web site. I need to have the client’s browser actually go to the payment gateway site.

My second question deals with secure servers. The data sent between a secure server and a browser is encrypted, right? Correct me if I’m wrong, but I think it should be secure from the prying eyes of a packet sniffer.

2) Looking at the above example, if the HTML order page and the Perl script are both on a secure server and the gateway server is secure, will the data sent from the Perl script to the gateway server also be encrypted?

To send a browser redirect, use the header() method from the CGI class like so:



use CGI;
my $q = CGI->new;
print $q->header(-location => 'http://www.place.to.redirect.com/');


The CGI class also makes it extremely easy (and secure) to get the form values from your HTML. CGI docs. Also, whenever writing web applications, you should use taint mode to protect against nefarious data.

Right.

Yep.

No, because the above example uses an ‘http’ URL, as opposed to ‘https’. The LWP classes determine which protocol to use based on the URL method (the thing before the ://.) Just like your web browser. In order for your script to make a secure post to the credit card people, you must have an ‘https’ URL to post to. Using it may require the installation of the Crypt::SSLeay Perl module if you don’t already have it.

Thanks for the reply, friedo! The taint mode link was very interesting. :slight_smile:

Bah! I must not have written that as clearly as I hoped. That sample code was from the lwpcook manpage, not my code. If I was using my code, the target URL for the post would be a secure server prefixed by https. So, if my script is running on a secure server and my target is also secure, the POST from my script is secure?
Also,

Unless I’m missing something though, this just sends the browser to the URL without doing a POST like I mentioned above. Let me try one more time.

  1. The client’s browser starts on a order page. Let’s say it’s https://www.mycheesyproduct.com/order.html. This page has a form with an order button. There is some form data, but it’s all hidden. When the order button is clicked this form data is POSTed to a Perl script also at the same secure site. In other words, the form’s method=post and the action=myscript.pl

  2. This Perl script (https://www.mycheesyproduct.com/cgi-bin/myscript.pl) uses the passed data along with some sensitive data stored on the server to build a transaction key. It also reads in some other information from the server that it needs to pass to the gateway (like a gateway user id).

  3. This Perl script then needs to POST this data to the secure gateway (https://www.mymerchantaccountprovider.com/gateway.cgi) mimicking a HTML form post. The client’s browser end up at the gateway address.

It’s step 3 that I can’t find an answer to. The best I can come up with is doing a HTTP::Request and then printing the result, but it that case the client is actually still at the local site.

It’s entirely possible that I’m just being thick about something. I fully admit that I have that potential and that my Perl knowledge is lacking. I just hope that the experts will be gentle with me. Thanks again! :slight_smile:

Perl’s LWP will let you post data to an HTTPS URL. See the example on the link below. Note that they specify the POST method when they set up the new request object and the “content” of the request contains name-value pairs of data to be posted:
http://www.perldoc.com/perl5.6/lib/LWP.html#An-Example
I haven’t tested this and none of the LWP code I’ve written uses posted data, so I can’t guarantee the example will work as shown. If it doesn’t, let me know and I’ll test it because this is the kind of code I should have laying around and don’t at the moment.

That example is similar to the one from the lwpcook manpage that I put in the OP. It does POST to a URL. However, the browser is never sent to the new page. Instead the results of the POST are stored and printed out with control remaining at the original site. I want to actually pass control to the new site.

Hmmm… Am I making the difference clear?

Very. Sorry I didn’t read carefully enough. You might check out this page:
http://ppewww.ph.gla.ac.uk/~flavell/www/post-redirect.html
It seems to discuss what you need, using the Location header to specify a redirect for the client to execute and why it doesn’t work with POST data. It might not answer your question, but it might explain why there is no good solution for what you want.

There is a solution, but it’s not a particularly good one.

Once you receive the initial form submission from the client, you can output a second form, consisting solely of hidden input fields, whose action points to the credit card gateway. Fill this form with all the data you need to send to the gateway, and use some Javascript to tell the browser to submit the form immediately upon loading. This saves you from having to use LWP in your Perl script, but it exposes the “sensitive” data because you will be putting it in the second-level form.

If you don’t want to do that, then you can use LWP to do your form posting as originally intended, and you will need to prepare your own page to send back to the client. (Or simply send back the HTML you got as a result of the post.)

Simply sending the return from the LWP call to the user (so your script basically works as a proxy) can cause problems if the data from the LWP call includes links or image tags with relative URLs. That’s simple to fix with a little substitution in Perl, but it’s something you have to account for.

The only way I can think of to do it without passing the sensative data to the user’s browser would be to use cookies. The gateway server would not send its output to the site that sent the POST, i.e., your server. Instead it would cache the information, accessable via some key. If that key is not implicit in the data you sent, it would then need to pass it back to your site. In any case, when you send the redirection reply to the user’s browser, you would also send a cookie with that key as the data, with the domain set to be the site you’re redirecting the browser to. The remote site would then access its cached data based upon that cookie.

Thanks for the links plus the time and effort! This site always seems to come through with answers for me.

In this case it really isn’t the answer that I wanted to hear, but it was what I was beginning to expect. The merchant account provider is still pretty annoying though. They tell you that you shouldn’t put certain information in hidden form fields. They refer you to code samples that do exactly that. When I sent them an email questioning this, they again said not to put certain information in hidden fields and once again referred me to the same code samples. :smack:

I think I’m going to try using the lwpcook method and see if I can fix the links in the returned page. Thanks again for the help. :slight_smile:

I don’t want to throw another wrench in your plan, but here’s something I ran into. I was doing essentially the same thing with a merchant account. We were using a form with hidden inputs and I tried to convert it to use a server-side HTTP call to the merchant server and then correct the relative links displayed to the user. In this case, I was using XMLHTTP in ASP rather than LWP in Perl, but that’s an irrelevant detail.

The problem was that the merchant process included a form the user had to submit containing credit card info, and the processing page for that form verified the HTTP_REFERER to make sure the form had been submitted from their server. When I set my server up to proxy their content, the submit failed this check. Not all merchant systems may do this, but I couldn’t really complain about it since it’s a sensible security measure on their part.

Thanks for the extra information. I was kind of wondering if something like that would be a problem with the lwpcook method. I’ll probably find out tonight.