Hello again.
I have a couple of questions about how you are testing this, because what you state and how you claim your code is running don't necessarily make sense.
First, is your password field inside your HTML file named "pass" or "password"? You attempt to get both of them at two different points toward the top of your code shown; you get the "password" param in the 'collect data from form' section, and then you get the "pass" param in the 'Cookie junk' section. You should choose one, stick with it, and only get it from the CGI once. Unless, of course, you have both. In which case I'm really confused.
Second, when you say "And if the HTML form is submitted emtpy, it prints "test" instead of erroring out and doesn't print the login form.", have you already run this at least once, and therefore you have the "filemanager" cookie set on your browser? If that is the case, then when you test for the existence of $tasty, your code calls &processing; and then quits. The "password checking" and "cookie setting" parts of your code appear to never get run once the "filemanager" cookie is set the first time.
Now, I have a couple of tips that I spotted right off the bat.
- You're not taint checking. Use the -T flag on the shebang line.
- Don't store your users database file inside the directory structure of your webserver. Put it somewhere that can be seen from your script, but where it can never possibly be served up by the web server. You never know how it might get served up.
- See Ovid's CGI Course Lesson Three and search for "Security by Obscurity" to learn why you shouldn't have the use CGI::Carp qw(fatalsToBrowser); line in your script...
- In your "Password checking" section, you have a closing </form> tag, but no opening <form> tag. Also, your closing form tag should be after the </table> tag, just as the opening <form> tag should be before the opening <table> tag.
- Also in the "Password checking" section, you again retrieve the username and password. The same with the split line that gets the specific user information. I don't see why this would be necessary, as the variables you're using are already defined.
- It's a bad idea to give different messages for "user not found" vs. "bad password." You're giving the user too much information. Doing so means that the user can keep banging on your script gathering which usernames are valid, thereby significantly reducing further work in trying to break in (I'm assuming a determined cracker here) via any form of concerted password attack. Provide one and only one error message for both cases.
Also, I provided you mostly-fully-working code yesterday, and pretty much noted the pieces that were shown to be called but missing from my post. bmann also provided a link to Ovid's CGI course. I highly recommend that as well. I learned a bunch of stuff on how to handle things in CGI from that course.
I hope that the above helps, or at least provides more ideas for you to work with. If you have questions about my node from yesterday, feel free to go back and reply to it with your questions (same goes for this node.) I'll be happy to answer.
| [reply] |
Thanks for the input, I tried to clear up the code as much as I could (see below) but nothing changed.
If you submit a blank form, it prints test. If you type in the wrong details, it prints the CGI login form with junk printed to screen that reads "Set-Cookie: filemanager=d; path=/ Expires: Fri, 15 Oct 2004 20:13:35 GMT Date: Fri, 15 Oct 2004 20:13:35 GMT Content-Type: text/html; charset=ISO-8859-1 test"
If you want to test the script, www.spydersubmission.com (upper left corner). After clearing the cookies and restarting IE, it always prints "test" when the form is blank. So in reality, no part of this form is working but I know it's ALMOST functional again.
I have read Ovid's CGI tutorials and I know CGI::Carp can be a bad thing, but now it's just used to help me with debugging. When the script is live, that'll be removed.
I didn't use your other script because it was too different from this current login template I've been using for a while now and a template like this would would be easier, for me, to implement in other scripts easily.
Can you see what else might be causing the problem with 1) not setting a cookie if login is right, 2) not erroring out when the form is blank, 3) what that junk is that prints when the password is wrong?
On a side note on the security about my error messages. Someone told me that before but I don't think it makes any difference if they know a certain username exists or not. For Hotmail, you could pick virtually anything you can think of for a screen name and know it works and attempt to break it even if they don't tell you "error: the username doesn't exist". Not saying security isn't an issue or important.
Thanks.
#!/usr/bin/perl -t
use warnings;
use strict;
use CGI qw/:standard/;
use CGI::Carp qw(fatalsToBrowser);
#######
# collect data from form
#######
my $username = param("username");
my $password = param("password");
#########
# Cookie junk
#########
my $cookiename = "filemanager";
my $tasty = cookie($cookiename);
use DB_File;
my %users;
my $users = "users.db"; # location of database
tie %users, "DB_File", "$users", O_CREAT|O_RDWR, 0644 or die "Cannot o
+pen file 'default.db': $!\n";
my ($savedpassword, $name, $email, $website, $start) = split(/::/, $us
+ers{$username});
######################################################################
+#########################################
# COOKIE CHECKING
######################################################################
+#########################################
# First check if we saved a cookie last time
if($tasty)
{
print header(-expires=>'now'),
start_html("You are logged in!");
&processing;
print end_html;
exit;
}
######################################################################
+##################################
# Password checking
######################################################################
+##################################
unless ($password eq $savedpassword)
{
print header(-expires=>'now'), start_html("You need to Login");
print <<"FORM";
<table border="2" width="181" bgcolor="#AAAAAA">
<form action="" method="post">
<tr>
<td bgcolor="#CC0000" valign="bottom"><font color="#FFFFFF" fac
+e="Arial, Helvetica, sans-serif">Client Login </font></td>
</tr>
<tr>
<td valign="top">
<table width="181" border="0" align="center">
<form action="/cgi-bin/member/login.cgi" method="post">
<tr>
<td width="59">username</td>
<td width="122" valign="top"><input name="username" type="t
+ext" size="15"></td>
</tr>
<tr>
<td>password</td>
<td valign="top"><input name="password" type="password" siz
+e="15"></td>
</tr>
<tr>
<td> </td>
<td valign="top"><div align="right">
<input type="submit" name="Submit" value="Log In">
</div></td>
</tr>
</form>
</table>
FORM
if (param())
{
if (exists $users{$username})
{
if ($password ne $savedpassword)
{
print "<b>Wrong password!</b>";
exit;
}
} }
else
{
print "username does not exist";
exit;
}
}
######################################################################
+##################################
# Cookie setting
######################################################################
+##################################
my $cookie = cookie(
-NAME=> $cookiename,
-VALUE=> $password,
);
print header(-COOKIE => $cookie, -expires=>'now');
print start_html("Going through here");
&processing;
sub processing
{
print "test";
} ########### END PROCESSING SUB HERE
exit;
"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"
sulfericacid
| [reply] [d/l] |
All right, this time I'm not going to just hand you an answer - I'm going to try to make you work for it ;) You've asked a lot of questions about cookies and form handling at pm, and seem to be asking some of the same here again. Here are some clues that will hopefully point you in the right direction...
#1: What happens when you set a cookie with an empty value? Hint - it doesn't get stored, and if there is already a cookie with that name...
#2: What happens when you compare two undefined values?
perl -wle 'print "true!" if undef eq undef';
# hmm, undef eq undef is true!
#3: What happens when you print HTTP headers more than once to the browser?
I think two out of three of these questions are answered at Ovid's CGI course mentioned above (I can't reach it from here right now). Also try perldoc CGI, then have a look at CGI Programming with Perl (one of many good O'Reilly books). Good luck! | [reply] [d/l] |
A quick look at CGI shows them using -NAME,-VALUE, and -COOKIE all in all lower case. I'm not sure if CGI is doing some magic that makes it not care about case, but I would recommend using the same as they use in the documentation to keep things simple.
For logins I general check for success and do the right thing then. Instead of checking for failure and doing the login. Its definitly personal preference but it can help weed out some bugs where variables aren't what you expect. Aslo CGI::Carp might be of some use for you. It will let you send warnings to the browser so that you can use them for debuging. This can be usefull when you don't have access to the error_log.
| [reply] |