shell bypass 403
use strict; use warnings;
package IO::All::Socket;
use IO::All -base;
use IO::Socket;
const type => 'socket';
field _listen => undef;
option 'fork';
const domain_default => 'localhost';
chain domain => undef;
chain port => undef;
proxy_open 'recv';
proxy_open 'send';
sub socket {
my $self = shift;
bless $self, __PACKAGE__;
$self->name(shift) if @_;
return $self->_init;
}
sub socket_handle {
my $self = shift;
bless $self, __PACKAGE__;
$self->_handle(shift) if @_;
return $self->_init;
}
sub accept {
my $self = shift;
use POSIX ":sys_wait_h";
sub REAPER {
while (waitpid(-1, WNOHANG) > 0) {}
$SIG{CHLD} = \&REAPER;
}
local $SIG{CHLD};
$self->_listen(1);
$self->_assert_open;
my $server = $self->io_handle;
my $socket;
while (1) {
$socket = $server->accept;
last unless $self->_fork;
next unless defined $socket;
$SIG{CHLD} = \&REAPER;
my $pid = CORE::fork;
$self->throw("Unable to fork for IO::All::accept")
unless defined $pid;
last unless $pid;
close $socket;
undef $socket;
}
close $server if $self->_fork;
my $io = ref($self)->new->socket_handle($socket);
$io->io_handle($socket);
$io->is_open(1);
return $io;
}
sub shutdown {
my $self = shift;
my $how = @_ ? shift : 2;
my $handle = $self->io_handle;
$handle->shutdown(2)
if defined $handle;
}
sub _assert_open {
my $self = shift;
return if $self->is_open;
$self->mode(shift) unless $self->mode;
$self->open;
}
sub open {
my $self = shift;
return if $self->is_open;
$self->is_open(1);
$self->get_socket_domain_port;
my @args = $self->_listen
? (
LocalAddr => $self->domain,
LocalPort => $self->port,
Proto => 'tcp',
Listen => 1,
Reuse => 1,
)
: (
PeerAddr => $self->domain,
PeerPort => $self->port,
Proto => 'tcp',
);
my $socket = IO::Socket::INET->new(@args)
or $self->throw("Can't open socket");
$self->io_handle($socket);
$self->_set_binmode;
}
sub get_socket_domain_port {
my $self = shift;
my ($domain, $port);
($domain, $port) = split /:/, $self->name
if defined $self->name;
$self->domain($domain) unless defined $self->domain;
$self->domain($self->domain_default) unless $self->domain;
$self->port($port) unless defined $self->port;
return $self;
}
sub _overload_table {
my $self = shift;
(
$self->SUPER::_overload_table(@_),
'&{} socket' => '_overload_socket_as_code',
)
}
sub _overload_socket_as_code {
my $self = shift;
sub {
my $coderef = shift;
while ($self->is_open) {
$_ = $self->getline;
&$coderef($self);
}
}
}
sub _overload_any_from_any {
my $self = shift;
$self->SUPER::_overload_any_from_any(@_);
$self->close;
}
sub _overload_any_to_any {
my $self = shift;
$self->SUPER::_overload_any_to_any(@_);
$self->close;
}
1;