[rt-devel] Tonight's incomplete proof-of-concept bad-idea code

Jesse Vincent jesse at bestpractical.com
Sun Dec 23 02:52:57 EST 2001


An RT IRC bot. the code's messy as hell. IRC's not at all secure.
I suspect that this bot's authentication is even more dodgy than most.
You don't want to run this code at all. But you ESPECIALLY don't want to run
it on a public IRC network.

It lets _anyone_ query open tickets in a queue or show a ticket or show an attachment.

It lets users who've issued a "login" command  open/stall/resolve tickets.

It's undocumented. 

You really don't want to run this code, but it might be fun to play with.

If anyone really wants to pick this up and run with it, they should get 
in touch with me.

	-j




#!/usr/bin/perl -w
#

use strict;
use POE;
use POE::Component::IRC;
use Text::Wrapper;
use strict;
use Carp;
use Getopt::Long;

use lib "/opt/rt-cpan/lib";
use lib "/opt/rt-cpan/etc";

use RT::Interface::CLI  qw(CleanEnv LoadConfig DBConnect 
                           GetCurrentUser GetMessageContent);

use RT::Queues;
use RT::Tickets;


#Clean out all the nasties from the environment
CleanEnv();

#Load etc/config.pm and drop privs
LoadConfig();

#Connect to the database and get RT::SystemUser and RT::Nobody loaded
DBConnect();

#Drop setgid permissions
RT::DropSetGIDPermissions();


my $CurrentUser = $RT::SystemUser;

package main;
my $nick = shift || 'ellie';
#
#  Create the IRC and Connection objects
#

sub _start {
  my ($kernel) = $_[KERNEL];

    print "About to connect to the irc server\n";
  $kernel->alias_set( 'smileyninja' );
  $kernel->post( 'dicebot', 'register', 'all');
  $kernel->post( 'dicebot', 'connect', { Debug    => 1,
                     Nick     => $nick,
                     Server   => $ARGV[0] || 'irc.example.com',
                     Port     => $ARGV[1] || 6667,
                     Username => 'ellie',
                     Ircname  => "obra's testbot",}
           );
}

sub irc_001 {
  my ($kernel) = $_[KERNEL];

  $kernel->post( 'dicebot', 'mode', $nick, '+i' );
}

sub irc_disconnected {
  my ($server) = $_[ARG0];
  print "Lost connection to server $server.\n";
}

sub irc_error {
  my $err = $_[ARG0];
  print "Server error occurred! $err\n";
}


sub irc_socketerr {
  my $err = $_[ARG0];
  print "Couldn't connect to server: $err\n";
}

sub _stop {
  my ($kernel) = $_[KERNEL];

  print "Control session stopped.\n";
  $kernel->post( 'dicebot', 'quit', 'Neenios on ice!' );
  $kernel->alias_remove( 'smileyninja' );
}
sub irc_msg {
    my ($kernel, $session, $who, $chan, $msg) = @_[KERNEL, HEAP, ARG0 .. ARG2];
    if ($who =~ /^(.*)!(.*)$/ ) {
        my $nick  = $1;
        my $mask = $2;
	print "Got $msg from $who\n";
        if ($msg =~ /^login (.*) (.*)$/) {
            my $username = $1;
            my $pass = $2;
    
            print "Pass is $pass\n";
            my $userobj = new RT::CurrentUser($username);
            print "Loading ".$userobj->Name ."\n";
            if ($userobj->IsPassword($pass)) {
               $session->{'users'}->{$mask}->{userobj} =  $userobj;
                msg($kernel, $nick, "Hi, ".$session->{'users'}->{$mask}->{userobj}->Name);
            }
            else {
                print $userobj->__Value('Password') ."\n". crypt($username, $userobj->__Value('Password')) ."\n";
                print "$username tried to log in with $pass-- as a password\n";
                msg($kernel, $nick, "Go away.");
                $session->{'users'}->{$mask} == undef;
            }
        }

    elsif ($msg =~ /^whoami$/) {
        if ($session->{'users'}->{$mask}->{userobj}) {
            msg($kernel, $nick, "You are ".$session->{'users'}->{$mask}->{userobj}->Name);
        } else{
            msg ($kernel, $nick, "You don't look familiar. you might want to login");
            }
    }

    elsif ($msg =~ /show ticket (\d*)$/) {
        show_ticket($kernel, $nick, $1)

    }
    elsif ($msg =~ /show attachment (.*?)$/) {
        show_attachment($kernel, $nick, $1);

    }

    elsif ($msg =~ /open tickets in (.*?)$/) {
        open_tickets_in($kernel, $nick, $1);
    }
    else {
        if ($session->{'users'}->{$mask}->{userobj}) {
            my $CurrentUser = $session->{'users'}->{$mask}->{userobj};
       
            my %statusmap = ( 'new'=> 'new', 'open' => 'open', 'stall' => 'stalled', 'resolve' => 'resolved', 'close' => 'resolved');

            if ($msg =~ /^(open|close|resolve|stall|new) (\d+)$/) {
                my $action = $1;
                my $id = $2;

                my $ticket = RT::Ticket->new($CurrentUser);
                $ticket->Load($id);
                unless ($ticket->id) {
                    msg($kernel, $nick, "Couldn't find ticket $id");
                }
                
                my ($val, $ret) = $ticket->SetStatus($statusmap{$action}) ; 
                msg($kernel, $nick, "#".$ticket->Id.": $ret". $statusmap{$action});
            }

        }

    }
    }     

    else {
       warn "Weird-ass who: $who";
    }
}



POE::Component::IRC->new( 'dicebot' ) or
  die "Can't instantiate new IRC component!\n";
POE::Session->new( 'main' => [qw(_start _stop irc_001 irc_disconnected
                                 irc_msg 
                                 irc_socketerr irc_error )] );
$poe_kernel->run();




exit 0;




# {{{ show_attach
sub show_attachment {
    my $kernel = shift;
    my $nick = shift;
    my $attach = shift;
	my $attachment = new RT::Attachment($CurrentUser);
	$attachment->Load($attach);
        if ($attachment->Id) {
	    foreach my $line( split(/\n/,$attachment->Content)) {
		msg($kernel,$nick, $line);
	    }	
	    
        } else {
            msg($kernel,$nick, "No such attachment");
        }

    }
# }}}

# {{{ show_ticket
sub show_ticket {
    my $kernel = shift;
    my $nick = shift;
    my $tid = shift;
    
	my $ticket = new RT::Ticket($CurrentUser);
	$ticket->Load($tid);
	if ($ticket->Id) {

	    msg($kernel,$nick, "Subject:   ",$ticket->Subject);
	    msg($kernel,$nick, "Status:    ",$ticket->Status , "  Priority:  ",$ticket->Priority);
	    msg($kernel,$nick, "Owner:     ", $ticket->OwnerObj->Name);
	    msg($kernel,$nick, "Requestors:", $ticket->RequestorsAsString);
	    msg($kernel,$nick, "Cc:        ", $ticket->CcAsString);
	    msg($kernel,$nick, "AdminCc:   ", $ticket->AdminCcAsString);
	    
	    msg($kernel,$nick, "----History----");
	    
	    my $trans = $ticket->Transactions;
	    while (my $t = $trans->Next) {
		msg($kernel,$nick, $t->CreatedObj->AsString, ' ', $t->Description);
		if ($t->Attachments->Count) {
		    my $a = $t->Attachments;
		    while ( my $attach = $a->Next) {
			if ($attach->ContentType =~ /multipart\//) { next }
			elsif ($attach->ContentType !~ /^text/i) {
			    msg($kernel,$nick, $attach->ContentType , ' file not shown.');
			    msg($kernel,$nick, $RT::WebURL,'/NoAuth/Attachment/',$t->id,'/',$attach->Id,'/',$attach->Filename);
			}
			else {
			    my $wrapper =  Text::Wrapper->new(columns => 60);
			    my @lines = split(/\n/, $wrapper->wrap($attach->Content));
			    for (my $i = 0; $i <8; $i++) {
				msg($kernel,$nick, shift @lines) if (@lines);
			    }	
			    if (@lines) {
				msg($kernel,$nick, ".... (see ".$RT::WebURL,'/NoAuth/Attachment/',$t->Id,'/',$attach->Id,'/',$attach->Filename);
			    }
			    
			}	
			
			
		    }	
		}	
		
	    }	
	    msg($kernel,$nick, "----End of history----");

	}
	else {
	    msg($kernel,$nick, "Ticket $1 could not be found");
	}	
    }
# }}}


# {{{ open tix
sub open_tickets_in {
	my $kernel = shift;
	my $nick = shift;
        my $queuename = shift;
	my $q = new RT::Queue($CurrentUser);
	$q->Load($queuename);
	
	if ($q->id) {
	    my $search = new RT::Tickets($CurrentUser);

	    $search->LimitStatus(VALUE => 'new', OPERATOR => '=', ENTRYAGGREGATOR => 'or');
	    $search->LimitStatus(VALUE => 'open', OPERATOR => '=', ENTRYAGGREGATOR => 'or');
	    $search->LimitQueue(VALUE => $q->id);
	    $search->GotoFirstItem();
	    msg($kernel,$nick,$search->Count, ' open tickets found for ',$q->Name);
	    $search->GotoFirstItem();
	    while (my $t = $search->Next) {
		msg($kernel,$nick,$t->id, " ", $t->Subject );
	    }
	}	
	else {
	    msg($kernel,$nick, "Queue $1 could not be found");
	}	
	
    }
# }}}

# {{{ send a msg convenience function
sub msg {
	my $kernel = shift;
        $kernel->post('dicebot' , 'privmsg', @_);
        }

# }}}

#



-- 
http://www.bestpractical.com/products/rt  -- Trouble Ticketing. Free.




More information about the Rt-devel mailing list