i have a script running on a web server (Apache) that accepts data
from STDIN and saves it:
#!/perl
use IO::Handle '_IONBF';
use constant BUFSIZE => 1024 * 2;
my $io = new IO::Handle;
if ( $io->fdopen(fileno(STDIN),"r") )
{
while($io->read($buf, BUFSIZE))
{
# ... save $buf ...
}
$io->close;
}
__END__;
I decided to check out if a user can upload to this script or else my
web server would screw up. So I put this on top of my script:
if ($ENV{"HTTP_USER_PASS"} ne 'mypassword')
{
close STDIN;
exit;
}
then I sent a couple of MBs of data thru http without the USER_PASS
header, i was struck by my finding out the script sort of died but I was
still sending raw data to the script...I though close STDIN would drop
the connection, too bad it didn't...how can I sort this out?
thanks
> if ($ENV{"HTTP_USER_PASS"} ne 'mypassword')
> {
> close STDIN;
> exit;
> }
Your script not only closes stdin, it also exits.
> then I sent a couple of MBs of data thru http without the USER_PASS
> header, i was struck by my finding out the script sort of died but I was
> still sending raw data to the script...
You can't send it to the script, since the script is already dead. You
might still be sending it to the web server. That makes it a web server
specific question and you should ask in an Apache group.
hp
> You can't send it to the script, since the script is already dead. You
> might still be sending it to the web server. That makes it a web server
> specific question and you should ask in an Apache group.
well, the thing is i tried to send the data to the following:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $q = new CGI();
$CGI::DISABLE_UPLOADS = 1;
print "content-type: text/plain\n\n";
__END__;
it just keeps on accetping the data...so i tried ps -ux on the web server
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
claudio 531 0.0 0.0 0 0 ? Z 19:13 0:00 [receiver.cgi]
<defunct>
what is <defunct>?? i tried to kill it, yet i didnt get...thats so
strange!
The <defunct> (and the STAT Z: Z is for 'zombie') mean that the process
has exitted, but its parent hasn't waited for it yet. Since the process
is already dead, you can't kill it again :). Presumably the httpd child
is receiving all the uploaded data and just throwing it away, and once
it's finished it'll perform the wait(2).
Ben
--
All persons, living or dead, are entirely coincidental.
b...@morrow.me.uk Kurt Vonnegut
> Presumably the httpd child
> is receiving all the uploaded data and just throwing it away, and once
> it's finished it'll perform the wait(2).
hopefully. Do you think that may affect/screw up my web server? I mean
the httpd child throwing the data away...
> You can't send it to the script, since the script is already dead.
ok, so back to my question...is ok to close STDIN and exit in order to
stop my script if a user fails to auth?
thanks
No, it may waste resources though.
If you need to authenticate uploaders you might find it better to use
the web-server's authentication and authorisation mechanisms (e.g. see
Apache's .htaccess). That ought to prevent the situation you describe.
--
RGB
But if authentication fails, you could return a "401 Unauthorized"
before you even begin reading:
if ( $ENV{"HTTP_USER_PASS"} ne ... ) {
print $q->header(
-status="401 Unauthorized"), ...,
"Wrong password....";
} else {
if ( $io->fdopen(fileno(STDIN),"r") )
{
... # read
}
}
exit;
--
Charles DeRykus
Of course, this won't alleviate the data push,
but at least you'll be failing gracefully with
the appropriate status.
--
Charles DeRykus
Or you can simply write
if ( $ENV{"HTTP_USER_PASS"} ne ... ) {
print "Status: 401 Unauthorized\n\n");
exit;
}
--
Petr Vileta, Czech republic
(My server rejects all messages from Yahoo and Hotmail.
Send me your mail from another non-spammer site please.)
Please reply to <petr AT practisoft DOT cz>
> Of course, this won't alleviate the data push,
> but at least you'll be failing gracefully with
> the appropriate status.
that's what I'm worring about...
Reviewing CGI docs, I think the problem may
be that you'll need to set $CGI::POST_MAX and
check cgi_error before you start reading, eg
use CGI;
my $q = new CGI();
$CGI::MAX_POST = ...;
my $q = CGI->new;
if ( my $error = $q->cgi_error ) {
print $q->start_html, $error,...
exit;
}
Hopefully only a partial transfer has occurred before CGI.pm
sees the content length and throws an error. Here're the
relevant lines from CGI.pm:
if (($POST_MAX > 0)
&& ($content_length > $POST_MAX)) {
#discard the post, unread
$self->cgi_error(
"413 Request entity too large");
...
}
--
Charles DeRykus