Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

merge paulv-sudo

  • Loading branch information...
commit 533241dd927c25f65524b94406420f12512d064c 2 parents 226e569 + 8438539
@paulv paulv authored
Showing with 159 additions and 1 deletion.
  1. +3 −0  Gemfile
  2. +18 −1 Gemfile.lock
  3. +73 −0 plugins/sudo.rb
  4. +65 −0 spec/sudo_spec.rb
View
3  Gemfile
@@ -5,3 +5,6 @@ gem 'cinch'
gem 'time-lord'
gem 'weather-underground'
gem 'twitter'
+gem 'rspec'
+gem 'rspec-given'
+gem 'file-tail'
View
19 Gemfile.lock
@@ -5,23 +5,37 @@ GEM
i18n (~> 0.6)
multi_json (~> 1.0)
cinch (2.0.2)
+ diff-lcs (1.1.3)
faraday (0.8.0)
multipart-post (~> 1.1)
+ file-tail (1.0.8)
+ tins (~> 0.3)
happymapper (0.4.0)
libxml-ruby (~> 2.0)
i18n (0.6.0)
libxml-ruby (2.3.2)
mime-types (1.18)
- multi_json (1.3.2)
+ multi_json (1.3.4)
multipart-post (1.1.5)
nokogiri (1.5.2)
rest-client (1.6.7)
mime-types (>= 1.16)
+ rspec (2.9.0)
+ rspec-core (~> 2.9.0)
+ rspec-expectations (~> 2.9.0)
+ rspec-mocks (~> 2.9.0)
+ rspec-core (2.9.0)
+ rspec-expectations (2.9.1)
+ diff-lcs (~> 1.1.3)
+ rspec-given (1.4.2)
+ rspec (> 1.2.8)
+ rspec-mocks (2.9.0)
ruby-bitly (0.1.5)
rest-client (~> 1.6.1)
simple_oauth (0.1.7)
temperature (1.2)
time-lord (0.2.5)
+ tins (0.4.2)
twitter (2.2.5)
activesupport (>= 2.3.9, < 4)
faraday (~> 0.8)
@@ -37,7 +51,10 @@ PLATFORMS
DEPENDENCIES
cinch
+ file-tail
nokogiri
+ rspec
+ rspec-given
ruby-bitly
time-lord
twitter
View
73 plugins/sudo.rb
@@ -0,0 +1,73 @@
+class Sudo
+ include Cinch::Plugin
+ require 'file-tail'
+
+ # this is the event that gets called when you join a channel
+ listen_to 353
+
+ def initialize(*args)
+ super
+ @date_re = Regexp.new(/^(\w{3}\s+\d+\s+\d{2}:\d{2}:\d{2})\s+/)
+ @user_re = Regexp.new(/^sudo:\s+(\w+)\s+: /)
+ @sudo_re = Regexp.new(/^\w{3}\s+\d+\s+\d{2}:\d{2}:\d{2}\s+\w+\s+sudo:\s+(\w+)\s+:/)
+ @results_struct = Struct.new(:date, :user, :tty, :pwd, :executed_as, :command, :success)
+ end
+
+ def listen(arg)
+ # FIX: don't hard-code the channel name here
+ target = Cinch::Target.new("#bottest", bot)
+
+ File::Tail::Logfile.tail("/var/log/auth.log") do |line|
+ if looks_like_sudo? line
+ target.msg format_results(process_line(line.chomp))
+ end
+ end
+ end
+
+ def format_results(results)
+ if results.success == true
+ "#{results.date}: #{results.user} ran (#{results.command}) as #{results.executed_as} in (#{results.pwd})"
+ else
+ "#{results.date}: #{results.user} tried to run (#{results.command}) as #{results.executed_as} in (#{results.pwd}), but failed (incorrect password?)"
+ end
+ end
+
+ def looks_like_sudo?(line)
+ if line.match(@sudo_re)
+ true
+ else
+ false
+ end
+ end
+
+ def process_line(line)
+ results = @results_struct.new
+ results.date = line.match(@date_re)[1] || "(unknown timestamp)"
+ line.gsub!(@date_re, "")
+
+ # remove hostname
+ line.gsub!(/^\w+\s/, "")
+
+ # extract user
+ results.user = line.match(@user_re)[1]
+ line.gsub!(@user_re, '')
+
+ sudo_fields = line.split(/\s+;\s+/).map {|chunk| chunk.split(/=/)[1]}
+
+ if sudo_fields.length == 4
+ results.tty = sudo_fields[0]
+ results.pwd = sudo_fields[1]
+ results.executed_as = sudo_fields[2]
+ results.command = sudo_fields[3]
+ results.success = true
+ else
+ results.success = false
+ results.tty = sudo_fields[1]
+ results.pwd = sudo_fields[2]
+ results.executed_as = sudo_fields[3]
+ results.command = sudo_fields[4]
+ end
+
+ results
+ end
+end
View
65 spec/sudo_spec.rb
@@ -0,0 +1,65 @@
+require 'cinch'
+require 'rspec/given'
+require_relative '../plugins/sudo'
+
+describe Sudo do
+ def bot_with_fatal_logger
+ bot = Cinch::Bot.new
+ bot.loggers.level = :fatal
+ bot
+ end
+
+ context "looks like sudo: test 1" do
+ Given(:sudo) { Sudo.new(bot_with_fatal_logger) }
+ When(:looks_like) { sudo.looks_like_sudo?("Apr 23 13:15:03 panacea sudo: fsfzones : TTY=unknown ; PWD=/home/fsfzones ; USER=root ; COMMAND=/usr/sbin/invoke-rc.d bind9 reload") }
+ Then { looks_like.should == true }
+ end
+
+ context "looks like sudo: test 2" do
+ Given(:sudo) { Sudo.new(bot_with_fatal_logger) }
+ When(:looks_like) { sudo.looks_like_sudo?("Apr 18 02:04:11 panacea sudo: pam_unix(sudo:auth): conversation failed") }
+ Then { looks_like.should == false }
+ end
+
+ context "looks like sudo: test 3" do
+ Given(:sudo) { Sudo.new(bot_with_fatal_logger) }
+ When(:looks_like) { sudo.looks_like_sudo?("Apr 30 17:59:12 panacea sshd[14284]: Failed password for sudo from 222.87.204.13 port 40829 ssh2") }
+ Then { looks_like.should == false }
+ end
+
+ context "test 1" do
+ Given(:sudo) { Sudo.new(bot_with_fatal_logger) }
+ When(:sudo_results) { sudo.process_line("Apr 23 13:15:03 panacea sudo: fsfzones : TTY=unknown ; PWD=/home/fsfzones ; USER=root ; COMMAND=/usr/sbin/invoke-rc.d bind9 reload") }
+ Then { sudo_results.date.should == "Apr 23 13:15:03" }
+ Then { sudo_results.user.should == "fsfzones" }
+ Then { sudo_results.tty.should == "unknown" }
+ Then { sudo_results.pwd.should == "/home/fsfzones" }
+ Then { sudo_results.executed_as.should == "root" }
+ Then { sudo_results.command.should == "/usr/sbin/invoke-rc.d bind9 reload" }
+ Then { sudo_results.success.should == true }
+ end
+
+ context "test 2" do
+ Given(:sudo) { Sudo.new(bot_with_fatal_logger) }
+ When(:sudo_results) { sudo.process_line("Apr 18 02:23:32 panacea sudo: jrbl : TTY=pts/38 ; PWD=/home/jrbl/.spamassassin ; USER=root ; COMMAND=/bin/chgrp spamd bayes_toks") }
+ Then { sudo_results.date.should == "Apr 18 02:23:32" }
+ Then { sudo_results.user.should == "jrbl" }
+ Then { sudo_results.tty.should == "pts/38" }
+ Then { sudo_results.pwd.should == "/home/jrbl/.spamassassin" }
+ Then { sudo_results.executed_as.should == "root" }
+ Then { sudo_results.command.should == "/bin/chgrp spamd bayes_toks" }
+ Then { sudo_results.success.should == true }
+ end
+
+ context "test 3" do
+ Given(:sudo) { Sudo.new(bot_with_fatal_logger) }
+ When(:sudo_results) { sudo.process_line("Apr 24 03:12:39 panacea sudo: paulv : 3 incorrect password attempts ; TTY=pts/6 ; PWD=/home/paulv ; USER=root ; COMMAND=/bin/ls -l /tmp") }
+ Then { sudo_results.date.should == "Apr 24 03:12:39" }
+ Then { sudo_results.user.should == "paulv" }
+ Then { sudo_results.tty.should == "pts/6" }
+ Then { sudo_results.pwd.should == "/home/paulv" }
+ Then { sudo_results.executed_as.should == "root" }
+ Then { sudo_results.command.should == "/bin/ls -l /tmp" }
+ Then { sudo_results.success.should == false }
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.