#!/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 $cookie_name = getOption("cookie_name=") $force_ssl = getOption("force_ssl=") if $force_ssl=="true" $http="https" else $http="http" end def auth(username,domain,password) #[TEST ONLY] Allow everybody #return true #[TEST] Admin password #if username == "admin" and password == "pass" # return true #end accessByPasswordUrl = $http + "://" + getWebDomainUrlFromDomain(domain) + "/users/sign_in" begin response = RestClient.post accessByPasswordUrl, :user => { :email => username , :password => password } return response.code == 201 rescue => e if e.class.name == "RestClient::Found" && e.http_code == 302 && e.http_body =~ /home/ return true end $logger.error "#{Process.pid}: Exception in auth(username, password)" $logger.error "#{Process.pid}: #{e.class.name}: #{e.message}" return false end end def authByCookie(username, domain, cookie) begin accessByCookieUrl = $http + "://" + getWebDomainUrlFromDomain(domain) + "/api/me" 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 def getWebDomainUrlFromDomain(domain) web_domain = getOption(domain + "="); if (web_domain != "Undefined") return web_domain else return domain end 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 userJid #{data[0]}@#{data[1]} and cookie #{cookie}" authByCookie(data[0], data[1], cookie) else $logger.info "#{Process.pid}: With userJid #{data[0]}@#{data[1]} and password ******" #$logger.info "#{Process.pid}: With userJid #{data[0]}@#{data[1]} and password #{data[2]}" auth(data[0], data[1], data[2]) end when "isuser" $logger.info "#{Process.pid}: Isuser with userJid: #{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