#!/usr/bin/env ruby require 'logger' require 'rest_client' require 'rexml/document' include REXML $stdout.sync = true $stdin.sync = true path = "/var/log/ejabberd/auth.log" file = File.open(path, File::WRONLY | File::APPEND | File::CREAT) file.sync = true $logger = Logger.new(file) $logger.level = Logger::DEBUG $logger.info "#{Process.pid}: Starting ejabberd authentication service" def getOption(option) File.open('/etc/ejabberd/ssconfig.cfg', 'r') do |f1| while line = f1.gets line = line.gsub(/\n/,'') if line.match(/^#/) #Comments elsif line.match(/^#{option}/) return line.gsub(/#{option}/,'') end end end return "Undefined" end $accessByPasswordUrl = "http://" + getOption("web_domain=") + "/users/sign_in" $accessByCookieUrl = "http://" + getOption("web_domain=") + "/api/me" $cookie_name = getOption("cookie_name=") def auth(username, password) #[TEST ONLY] Allow everybody #return true #[TEST] Admin password #if username == "admin" and password == "pass" # return true #end begin response = RestClient.post $accessByPasswordUrl, :user => { :email => username , :password => password } if response.code == 201 return true else return false end rescue => e unless e.class.name == "RestClient::Unauthorized" and e.message == "401 Unauthorized" $logger.error "#{Process.pid}: Exception in auth(username, password)" $logger.error "#{Process.pid}: #{e.class.name}: #{e.message}" end return false end end def authByCookie(username, cookie) begin response = RestClient.get $accessByCookieUrl, :cookies => {:"#{$cookie_name}" => cookie} doc = REXML::Document.new(response.body) slug = "" doc.elements.each('user/slug') do |ele| slug = ele.text end if username != "" and username == slug return true else return false end rescue => e unless e.class.name == "RestClient::Unauthorized" and e.message == "401 Unauthorized" $logger.error "#{Process.pid}: Exception in authByCookie(username, cookie)" $logger.error "#{Process.pid}: #{e.class.name}: #{e.message}" end return false end end def validateParameters(username,domain,password) if !username or !password or !domain return false end if (username.gsub(/\s+/, "")=="") or (password.gsub(/\s+/, "")=="") or (domain.gsub(/\s+/, "")=="") return false end return true end loop do begin $stdin.eof? # wait for input start = Time.now msg = $stdin.read(2) length = msg.unpack('n').first msg = $stdin.read(length) cmd, *data = msg.split(":") $logger.info "#{Process.pid}: Incoming Request: '#{cmd}'" success = case cmd when "auth" $logger.info "#{Process.pid}: Authenticating #{data[0]}@#{data[1]}" #Parameters basic validation: validateParameters(username,domain,password) if !validateParameters(data[0],data[1],data[2]) $logger.info "#{Process.pid}: Invalid parameters" return false end #Select authorization condition for LOGIN #Authentication methods: user/password or user/cookie password = data[2] if password.split(">>")[0]=="AuthenticationByCookie" cookie = password.split(">>")[1] $logger.info "#{Process.pid}: With username #{data[0]} and cookie #{cookie}" authByCookie(data[0], cookie) else $logger.info "#{Process.pid}: With username #{data[0]} and password ******" #$logger.info "#{Process.pid}: With username #{data[0]} and password #{data[2]}" auth(data[0], data[2]) end when "isuser" $logger.info "#{Process.pid}: Isuser #{data[0]}@#{data[1]}" #Authorization condition for ISUSER (Add buddys) true else false end bool = success ? 1 : 0 $stdout.write [2, bool].pack("nn") $logger.info "#{Process.pid}: Response: #{success ? "success" : "failure"}" rescue => e $logger.error "#{Process.pid}: #{e.class.name}: #{e.message}" $logger.error "#{Process.pid}: " + e.backtrace.join("\n\t") $logger.error "#{Process.pid}: Finish process" break end end