]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/commitdiff
Merge pull request #20 from 4poc/ssl-verify
authorOblomov <giuseppe.bilotta@gmail.com>
Thu, 14 Nov 2013 14:23:27 +0000 (06:23 -0800)
committerOblomov <giuseppe.bilotta@gmail.com>
Thu, 14 Nov 2013 14:23:27 +0000 (06:23 -0800)
Implements SSL verification against a configured CA

lib/rbot/ircbot.rb
lib/rbot/ircsocket.rb

index d75d6b54591dfb07ac647ffb90d611e2ccfb8fe3..108d0b1d04ac85a7d7a8f8f64742168d8b99550a 100644 (file)
@@ -66,6 +66,10 @@ def rawlog(level, message=nil, who_pos=1)
     qmsg.push [level, l.chomp, who]
     who = ' ' * who.size
   }
+  # Also output (fatal) errors to STDERR:
+  if level == Logger::Severity::ERROR or level == Logger::Severity::FATAL
+    $stderr.puts str
+  end
   $log_queue.push qmsg
 end
 
@@ -278,6 +282,18 @@ class Bot
     Config.register Config::BooleanValue.new('server.ssl',
       :default => false, :requires_restart => true, :wizard => true,
       :desc => "Use SSL to connect to this server?")
+    Config.register Config::BooleanValue.new('server.ssl_verify',
+      :default => false, :requires_restart => true,
+      :desc => "Verify the SSL connection?",
+      :wizard => true)
+    Config.register Config::StringValue.new('server.ssl_ca_file',
+      :default => default_ssl_ca_file, :requires_restart => true,
+      :desc => "The CA file used to verify the SSL connection.",
+      :wizard => true)
+    Config.register Config::StringValue.new('server.ssl_ca_path',
+      :default => '', :requires_restart => true,
+      :desc => "Alternativly a directory that includes CA PEM files used to verify the SSL connection.",
+      :wizard => true)
     Config.register Config::StringValue.new('server.password',
       :default => false, :requires_restart => true,
       :desc => "Password for connecting to this server (if required)",
@@ -608,7 +624,12 @@ class Bot
         debug "server.list is now #{@config['server.list'].inspect}"
     end
 
-    @socket = Irc::Socket.new(@config['server.list'], @config['server.bindhost'], :ssl => @config['server.ssl'], :penalty_pct =>@config['send.penalty_pct'])
+    @socket = Irc::Socket.new(@config['server.list'], @config['server.bindhost'], 
+                              :ssl => @config['server.ssl'],
+                              :ssl_verify => @config['server.ssl_verify'],
+                              :ssl_ca_file => @config['server.ssl_ca_file'],
+                              :ssl_ca_path => @config['server.ssl_ca_path'],
+                              :penalty_pct => @config['send.penalty_pct'])
     @client = Client.new
 
     @plugins.scan
@@ -804,6 +825,17 @@ class Bot
     trap_signals
   end
 
+  # Determine (if possible) a valid path to a CA certificate bundle. 
+  def default_ssl_ca_file
+    [ '/etc/ssl/certs/ca-certificates.crt', # Ubuntu/Debian
+      '/etc/ssl/certs/ca-bundle.crt', # Amazon Linux
+      '/etc/ssl/ca-bundle.pem', # OpenSUSE
+      '/etc/pki/tls/certs/ca-bundle.crt' # Fedora/RHEL
+    ].find do |file|
+      File.readable? file
+    end
+  end
+
   def repopulate_botclass_directory
     template_dir = File.join Config::datadir, 'templates'
     if FileTest.directory? @botclass
index 029d1ca54026353518eab0b402e8a72a3b2670a7..e5131c2b6b3edbeb3f542f358a698e90bbd027bd 100644 (file)
@@ -285,6 +285,9 @@ module Irc
       @lines_sent = 0
       @lines_received = 0
       @ssl = opts[:ssl]
+      @ssl_verify = opts[:ssl_verify]
+      @ssl_ca_file = opts[:ssl_ca_file]
+      @ssl_ca_path = opts[:ssl_ca_path]
       @penalty_pct = opts[:penalty_pct] || 100
     end
 
@@ -331,7 +334,13 @@ module Irc
       if(@ssl)
         require 'openssl'
         ssl_context = OpenSSL::SSL::SSLContext.new()
-        ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
+        if @ssl_verify
+          ssl_context.ca_file = @ssl_ca_file if @ssl_ca_file and not @ssl_ca_file.empty?
+          ssl_context.ca_path = @ssl_ca_path if @ssl_ca_path and not @ssl_ca_path.empty?
+          ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER 
+        else
+          ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
+        end
         sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
         sock.sync_close = true
         sock.connect