Advertisement
Guest User

Untitled

a guest
May 18th, 2017
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.65 KB | None | 0 0
  1. #!/usr/bin/perl
  2. #
  3. package P5EvalBot;
  4.  
  5. use base 'Bot::BasicBot';
  6. use POE;
  7. use POE::Component::SSLify;
  8. use BSD::Resource;
  9. use Data::Dumper;
  10. use Carp::Heavy; #chroot
  11. use POSIX;
  12. use Symbol qw/delete_package/;
  13. use Cwd qw/getcwd/;
  14. use strict;
  15. $|++;
  16.  
  17. my $pass="";
  18.  
  19. open my $log, ">>/home/epoch/eb/jail/eb.log" or die $!;
  20. my %fork_output;
  21.  
  22. sub new
  23. {
  24. my $class = shift;
  25. my( $nick, $channels, $server, $ignore ) = @_;
  26. my $self = $class->SUPER::new(
  27. usessl => 1,
  28. nick => $nick,
  29. channels => $channels,
  30. server => $server,
  31. port => 6697,
  32. username => $nick,
  33. name => $nick,
  34. ignore_list => $ignore,
  35. );
  36.  
  37. setrlimit( RLIMIT_CPU, RLIM_INFINITY, RLIM_INFINITY); #load auto/BSD/Resource/setrlimit.al
  38. POSIX::close(6000); #load POSIX::close.al, unavailable when chrooted
  39. POSIX::setgid(0); #load setgid.al
  40. print "I am: $$\n";
  41. print getcwd,"\n";
  42.  
  43. $self->load_plugins;
  44. return $self;
  45. }
  46.  
  47. sub load_plugins
  48. {
  49. my $self = shift;
  50.  
  51. my @plugins;
  52.  
  53. chdir "plugins" or return;
  54.  
  55. for( glob( "*.pm" ) )
  56. {
  57. my $ret = do $_;
  58. if( ref $ret eq 'HASH' or ref $ret eq 'ARRAY' ) #Array reference of plugins..
  59. {
  60. for my $ret ( ref $ret eq 'ARRAY' ? @$ret : $ret )
  61. {
  62. push @plugins, { file => $_, %{ $ret } };
  63. if( $ret->{ destroy_handler } )
  64. {
  65. push @{ $self->{ death_handlers } }, $ret->{ destroy_handler };
  66. }
  67. }
  68.  
  69. print "Added $_, $plugins[-1], $@\n";
  70. }
  71. else
  72. {
  73. warn "ZOMG ERROR: got an invalid result from $_, $!, $@";
  74. }
  75. }
  76.  
  77. chdir ".." or die $!;
  78.  
  79. $self->{ plugins } = \@plugins;
  80. }
  81.  
  82. sub call_plugin
  83. {
  84. my $self = shift;
  85. my $said = shift;
  86. my $plugin_name = shift;
  87. if( $plugin_name !~ /\.pm$/ ) { $plugin_name .= ".pm" }
  88.  
  89. for( @{ $self->{ plugins } } )
  90. {
  91. if( $_->{ file } eq $plugin_name )
  92. {
  93. $_->{ code }->( $self, $said, @_ );
  94. last; #Only one name can match.. I hope
  95. }
  96. }
  97. }
  98.  
  99. sub unload_plugin
  100. {
  101. my $self = shift;
  102. my $plugin = shift;
  103.  
  104. warn "Attempting to unload $plugin";
  105. my $index;
  106. for( 0 .. $#{ $self->{ plugins } } )
  107. {
  108. if( $self->{ plugins }->[ $_ ]->{ file } eq $plugin )
  109. {
  110. $index = $_;
  111. warn "Found plugin $plugin at $_";
  112. last;
  113. }
  114. }
  115.  
  116. if( defined $index )
  117. {
  118. splice @{ $self->{ plugins } }, $index, 1;
  119. warn "Dropped plugin";
  120. return 1;
  121. }
  122.  
  123. else
  124. {
  125. return;
  126. }
  127. }
  128.  
  129. sub DESTROY
  130. {
  131. my $self = shift;
  132.  
  133. for( @{ $self->{ death_handlers } } )
  134. {
  135. $_->( $self );
  136. }
  137. }
  138.  
  139. sub connected
  140. {
  141. my( $self ) = shift;
  142.  
  143. warn "Connected to: ", $self->server,"\n";
  144.  
  145. if( $self->server eq 'irc.fake.net' )
  146. {
  147. warn "IDENTIFYING with SECRET PASSWORD";
  148. $self->say( who => 'nickserv', channel => 'msg', body => "identify " );
  149. }
  150. }
  151.  
  152. sub said
  153. {
  154. my $self = shift;
  155. my $said = shift;
  156.  
  157. my $a_superuser = ( ( $said->{ raw_nick } =~ 'epoch' ) );
  158.  
  159. if( $self->ignored( $said ) and not $a_superuser )
  160. {
  161. warn "Skipping ignored user: $said->{who} on $said->{channel}";
  162. return;
  163. }
  164.  
  165. my @matched;
  166. for( @{ $self->{ plugins } } )
  167. {
  168. if( my @matches = $said->{ body } =~ $_->{ syntax } )
  169. {
  170. push @matched, $_;
  171. #ok, yeah, this is silly.
  172. if( $_->{ superuser } and not $a_superuser )
  173. {
  174. warn "Error, $said->{who} is not a super user for $_->{file}\n";
  175. next;
  176. }
  177.  
  178. if( $_->{ addressed } and not $said->{ address } )
  179. {
  180. next;
  181. }
  182.  
  183. warn "Triggering: $_->{file}";
  184.  
  185. local $@;
  186. eval { $_->{ code }->( $self, $said, @matches ); };
  187.  
  188. if( $@ )
  189. {
  190. warn "Error with $_->{file}, $@";
  191. }
  192. }
  193. }
  194.  
  195. if( $said->{ address } and not @matched )
  196. {
  197. $self->reply( $said, "fail" );
  198. }
  199. }
  200. sub forkit
  201. {
  202. my $self = shift;
  203. my %args = @_;
  204.  
  205. $poe_kernel->state( $args{handler}, $self );
  206.  
  207. my $run;
  208.  
  209. if( ref $args{run} eq 'CODE' )
  210. {
  211. my @args = @{ $args{arguments} }; #Closure problems?
  212. my $ref = $args{run};
  213.  
  214. print "args: '@args'\n";
  215. $run = sub{ $ref->( @args ) };
  216. }
  217.  
  218. else
  219. {
  220. $run = $args{run};
  221. }
  222.  
  223. my $wheel = POE::Wheel::Run->new(
  224. Program => $run,
  225. StdoutFilter => POE::Filter::Stream->new,
  226. StderrFilter => POE::Filter::Stream->new,
  227. StdoutEvent => $args{handler},
  228. StderrEvent => $args{handler},
  229. CloseEvent => "fork_close"
  230. );
  231.  
  232. $poe_kernel->sig( CHLD => 'fork_close' );
  233.  
  234. $self->{ wheels }->{ $wheel->ID } = {
  235. wheel => $wheel,
  236. start => time,
  237. args => {
  238. channel => $args{channel},
  239. who => $args{who},
  240. address => $args{address},
  241. }
  242. };
  243.  
  244. if( $self->{ __fork_ret } )
  245. {
  246. $self->{ wheels }->{ $wheel->ID }->{ ret_sub } = $self->{ __fork_ret };
  247. $self->{ __fork_ret } = 0;
  248. }
  249.  
  250. $self->schedule_tick(10);
  251.  
  252. return $wheel;
  253. }
  254.  
  255. sub tick
  256. {
  257. my $self = shift;
  258.  
  259. for( keys %{ $self->{ wheels } } )
  260. {
  261. my $wheel_dat = $self->{ wheels }->{ $_ };
  262.  
  263. if( time - $wheel_dat->{ start } > 9 )
  264. {
  265. print "Killing: wheel $_\n";
  266. $wheel_dat->{ wheel }->kill(9);
  267.  
  268. $wheel_dat->{args}->{body} = "Killing $_ Due To Run Time.";
  269. $self->say( $wheel_dat->{args} );
  270.  
  271. delete $self->{ wheels }->{ $_ };
  272. delete $fork_output{ $_ };
  273. }
  274. }
  275.  
  276. if( not keys %{ $self->{ wheels } } )
  277. {
  278. return 0;
  279. }
  280.  
  281. else
  282. {
  283. return 10; #time till next tick
  284. }
  285. }
  286.  
  287. sub fork_close_state
  288. {
  289. my( $self, $wheel_id ) = @_[ 0, ARG0 ];
  290. print $log "Called: $self, $wheel_id\n";
  291. my $ref = delete $self->{wheels}->{$wheel_id};
  292.  
  293. my $output = delete $fork_output{$wheel_id};
  294. $output =~ s/\r?\n/ /g;
  295. $output =~ s/[^\x20-\x7f]/ /g;
  296. print $log "output: $output";
  297.  
  298. $ref->{args}->{body} = substr( $output, 0, 200 );
  299.  
  300. if( $ref->{ ret_sub } )
  301. {
  302. $ref->{ ret_sub }->( $ref->{args}->{body} );
  303. }
  304. else
  305. {
  306. $self->say( $ref->{args} );
  307. }
  308. }
  309.  
  310. sub fork_error_state
  311. {
  312. print "Zomg! Fatal error:\n";
  313. }
  314.  
  315. sub safe_execute
  316. {
  317. my( $self, $code ) = @_;
  318.  
  319. chdir("/home/epoch/eb/jail") or die $!;
  320. chroot("/home/epoch/eb/jail") or die $!;
  321.  
  322. $<=$>=65534;
  323. POSIX::setgid(65534);
  324.  
  325. setrlimit(RLIMIT_CPU, 10,10);
  326. setrlimit(RLIMIT_DATA, 5*1024,5*1024 );
  327. setrlimit(RLIMIT_STACK, 5*1024, 5*1024 );
  328. setrlimit(RLIMIT_NPROC, 1,1);
  329. setrlimit(RLIMIT_NOFILE, 0,0);
  330. setrlimit(RLIMIT_OFILE, 0,0);
  331. setrlimit(RLIMIT_OPEN_MAX,0,0);
  332. setrlimit(RLIMIT_LOCKS, 0,0);
  333. setrlimit(RLIMIT_AS,5*1024,5*1024);
  334. setrlimit(RLIMIT_VMEM,5*1024,5*1024);
  335. setrlimit(RLIMIT_MEMLOCK,100,100);
  336. #setrlimit(RLIMIT_MSGQUEUE,100,100);
  337.  
  338. die "Failed to drop root: $<" unless $<;
  339. close STDIN;
  340.  
  341. local $@;
  342.  
  343. for( qw/Socket IO::Socket::INET/ )
  344. {
  345. delete_package( $_ );
  346. }
  347.  
  348. local @INC;
  349.  
  350. $code->();
  351. }
  352.  
  353. my %line_counter;
  354.  
  355. sub fork_handler
  356. {
  357. my( $self, $body, $wheel_id ) = @_[0, ARG0, ARG1];
  358.  
  359. print "Got '$body' from $wheel_id\n";
  360.  
  361. $fork_output{ $wheel_id } .= "$body";
  362.  
  363. #$self->say(channel=>"#buubot", body => "Received line from $wheel_id" );
  364. }
  365.  
  366. sub hush
  367. {
  368. my( $self, $channel ) = @_;
  369.  
  370. $self->{ __EB_HUSH }->{ $channel } = 1;
  371. }
  372.  
  373. sub unhush
  374. {
  375. my( $self, $channel ) = @_;
  376.  
  377. delete $self->{ __EB_HUSH}->{ $channel };
  378. }
  379.  
  380. sub ignore
  381. {
  382. if( @_ == 3 )
  383. {
  384. my( $self, $channel, $nick ) = @_;
  385. $self->{ _ignore_list }->{ $channel }->{ $nick } = 1;
  386. }
  387.  
  388. elsif( @_ == 2)
  389. {
  390. my( $self, $said ) = @_;
  391. $self->{ _ignore_list }->{ $said->{ channel } }->{ $said->{ who } } = 1;
  392. }
  393.  
  394. else
  395. {
  396. warn "sub ignored called with odd number of arguments, ",scalar(@_)," @_";
  397. }
  398.  
  399. warn "ignored @_";
  400. warn Dumper( $_[0]->{_ignore_list} );
  401. }
  402.  
  403. sub ignored
  404. {
  405. if( @_ == 3 )
  406. {
  407. my( $self, $channel, $nick ) = @_;
  408.  
  409. warn "Returning: $self->{ _ignore_list }->{ $channel }->{ $nick };";
  410.  
  411. return $self->{ _ignore_list }->{ $channel }->{ $nick };
  412. }
  413. elsif( @_ == 2 )
  414. {
  415. my( $self, $said ) = @_;
  416. warn "Returning: $self->{ _ignore_list }->{ $said->{ channel } }->{ $said->{ who } }";
  417. return $self->{ _ignore_list }->{ $said->{ channel } }->{ $said->{ who } };
  418. }
  419.  
  420. else
  421. {
  422. warn "sub ignored called with odd number of arguments, ",scalar(@_)," @_";
  423. }
  424. }
  425.  
  426. sub unignore
  427. {
  428. if( @_ == 3 )
  429. {
  430. my( $self, $channel, $nick ) = @_;
  431. delete $self->{ _ignore_list }->{ $channel }->{ $nick };
  432. }
  433.  
  434. elsif( @_ == 2 )
  435. {
  436. my( $self, $said ) = @_;
  437. delete $self->{ _ignore_list }->{ $said->{ channel } }->{ $self->{ who } };
  438. }
  439.  
  440. else
  441. {
  442. warn "sub ignored called with odd number of arguments, ",scalar(@_)," @_";
  443. }
  444. }
  445.  
  446. sub say
  447. {
  448. my $self = shift;
  449. my $args;
  450. if (ref($_[0]))
  451. {
  452. $args = shift;
  453. }
  454.  
  455. else
  456. {
  457. my %args = @_;
  458. $args = \%args;
  459. }
  460.  
  461. if( not exists $self->{ __EB_HUSH }->{ $args->{channel} } )
  462. {
  463. $self->SUPER::say( $args );
  464. }
  465. }
  466.  
  467. package main;
  468. my $first = P5EvalBot->new("perldoc",[qw/#ninjas/],"the.fake.us");
  469. #my $second = P5EvalBot->new("perldoc",[qw/#darkscience/],"irc.darkscience.ws");
  470. $first->run;
  471. #$second->run;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement