ARCv2
view release on metacpan or search on metacpan
lib/Arc/Connection/Client.pm view on Meta::CPAN
@{$this->{_expectedcmds}} = qw(SASL ERR);
return $this->_StepAuthentication(1);
}
## another SASL step.
## Response of a SASL command from the server.
## Protocol command: SASL <base64 encoded SASL outout>\r\n
##in> $first_step
##out> true when succesful, otherwise false
##eg> return $this->_StepAuthentication(1);
sub _StepAuthentication
{
my $this = shift;
my $first = shift;
my $sasl = $this->{_sasl};
my $ret = 0;
my $str;
if ($first) {
$str = $sasl->client_start();
} else {
$str = $sasl->client_step(decode_base64($this->{_cmdparameter}));
}
$str = "" unless defined $str;
if ($sasl->need_step || $sasl->code == 0) {
if ($sasl->code == 0) {
$this->_Sasl($str) if $str ne "";
$this->{_authenticated} = 1;
@{$this->{_expectedcmds}} = qw(ERR);
$this->{sasl_mechanism} = $this->{_saslmech};
$this->Log(LOG_AUTH,"SASL: Negotiation complete. User is authenticated.");
$ret = 1;
} else {
$ret = $this->_Sasl($str);
}
} else {
$this->Quit();
$ret = $this->_SetError("SASL: Negotiation failed. User is not authenticated. SASL error: (",$sasl->code,") ",$sasl->error);
}
return $ret
}
## send an ARCv2 command request
## Protocol command: CMD <cmd> <cmdparameter>\r\n
##in> ... (cmd and parameter)
##out> true when succesful, otherwise false
##eg> $this->_Cmd ("whoami");
sub _Cmd
{
my $this = shift;
my $str = join " ",@_;
$str =~ s/[\r\n]//g;
return $this->_SetError("Empty command won't be sent.") unless length $str;
@{$this->{_expectedcmds}} = qw(ERR CMDPASV DONE);
return $this->_SendCommand("CMD",$str);
}
# The _R subs are processing a server response, call resp. subs and set the expectedcmds array approp.
## parses the AUTH <list of SASL mech>\r\n, sent by the server
sub _RAUTH
{
my $this = shift;
@{$this->{server_sasl_mechanisms}} = split(',',$this->{_cmdparameter});
return $this->_Authenticate();
}
## parses the AUTHTYPE <SASL mech>\r\n, sent by the server.
## Which SASL mech the server will use.
sub _RAUTHTYPE
{
my $this = shift;
$this->{_saslmech} = $this->{_cmdparameter};
return $this->_StartAuthentication();
}
## parses the SASL <base64 encoded SASL string>\r\n, sent by the server.
## Sasl response from the server
sub _RSASL
{
my $this = shift;
return $this->_SetError("SASL Negotiation failed.") unless ($this->_StepAuthentication(0));
return 1;
}
## parses the ERR <msg>\r\n, sent by the server.
## Server command, which reports an server-side error
sub _RERR
{
my $this = shift;
$this->_SetError("Server ERROR:",$this->{_cmdparameter});
return 1;
}
## parses the CMDERR <msg>\r\n, sent by the server.
## Command specific error, which reports an error during the command
sub _RCMDERR
{
my $this = shift;
$this->_SetError("Command ERROR:",$this->{_cmdparameter});
return 1;
}
## parses CMDPASV <host:port>\r\n, sent by the server.
## Establish the encrypted command connection.
sub _RCMDPASV
{
my $this = shift;
$this->Log(LOG_SIDE,"Try to connect to:",$this->{_cmdparameter});
@{$this->{_expectedcmds}} = qw(ERR DONE CMDERR);
return if defined $this->{_cmdclientsock};
my ($host,$port) = split(/:/,$this->{_cmdparameter});
return unless defined $host || defined $port;
$this->{_cmdclientsock} = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Type => SOCK_STREAM,
) || return $this->_SetError("Passive Connection failed.");
return 1;
}
## parses DONE\r\n, sent by the server.
## This is received when a command is done.
sub _RDONE
{
my $this = shift;
@{$this->{_exceptedcmds}} = qw(ERR CMD);
return 1;
}
## start an ARCv2 session.
## This function which will change the status of the connection into a
## authenticated status. Users have to call this function
## to be able to run ARCv2 commands afterwards.
##out> true if authentication was successful, otherwise false.
##eg> if ($arc->StartSession()) { .. }
sub StartSession
{
my $this = shift;
return $this->_SetError("There is already a command running.") if $this->IsConnected();
return $this->_SetError("Connection to host ",$this->{server},":",$this->{port}," failed") unless $this->_Connect();
$this->_InitARC2();
while (!$this->{_error} && ($this->{_authenticated} == 0) && (my $cmd = $this->_RecvCommand())) {
last unless $this->_ProcessLine($cmd);
}
return !$this->{_error} && $this->{_authenticated};
}
## ends the connection.
## Tells the server that we want to end the conversation. (Userlevel)
## Protocol command: QUIT\r\n
##out> always true
##eg> $arc->Quit();
sub Quit
{
my $this = shift;
$this->_SendCommand("QUIT");
$this->{_connection}->close();
$this->{_connected} = 0;
$this->{_expectedcmds} = qw();
return 1;
}
## process a command.
## This function runs a command with STDIN and STDOUT as clients
## in- and output control.
##in> ... (command and its parameters)
##out> true if successful, false if not. (IsError is set appropriatly)
##eg> $arc->ProcessCommand("whoami");
sub ProcessCommand
{
my $this = shift;
return unless $this->CommandStart(@_);
STDOUT->autoflush(1);
$this->_ReadWriteBinary(*STDIN,*STDOUT);
return $this->CommandEnd();
}
## start an ARCv2 command
## This function starts the given ARCv2 Command and enables the Command* functions.
##in> ... (command and its parameters)
##out> true if successful, false if not. (IsError is set appropriatly)
##eg> if ($arc->CommandStart()) { ... }
sub CommandStart
{
my $this = shift;
return $this->_SetError("You are not authenticated.") unless $this->{_authenticated};
return $this->_SetError("Already running a command.") if defined $this->{_cmdclientsock};
return unless @_;
return unless $this->_Cmd(@_);
while (!$this->{_error} && (not defined $this->{_cmdclientsock}) && (my $cmd = $this->_RecvCommand()) ) {
$this->_ProcessLine($cmd);
last if $cmd eq "DONE";
}
return 1 if defined $this->{_cmdclientsock};
return;
}
## write something to the command.
## Write something to the standard input of the command started by C<CommandStart>.
##in> ... (data)
##out> true if successful, false if not. (IsError is set appropriatly)
##eg> last unless $this->CommandWrite();
sub CommandWrite
{
my $this = shift;
return $this->_SetError("There is no command running.") unless defined $this->{_cmdclientsock};
return unless @_;
my $str = join("",@_);
$str = $this->{_sasl}->encode($str);
return $this->{_cmdclientsock}->syswrite($str);
}
## close the write part of the netsock.
## This function closes the write-part of the command connection.
##out> true if successful, false if not. (IsError is set appropriatly)
##eg> last unless $arc->CommandEOF();
sub CommandEOF
( run in 0.791 second using v1.01-cache-2.11-cpan-39bf76dae61 )