Skip to content

Instantly share code, notes, and snippets.

@Papierkorb
Created January 1, 2016 17:10
Show Gist options
  • Save Papierkorb/7466c24b6fa58fe20af7 to your computer and use it in GitHub Desktop.
Save Papierkorb/7466c24b6fa58fe20af7 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# Ejabberd authentication back-end script in Ruby.
# Works with Ruby 2.2.
# Dependency: RestClient gem
root = File.realpath("#{File.dirname __FILE__}/..")
URL = 'http://URL_TO_YOUR/service'
LOG_FILE = "#{root}/log/ejabberd_auth_tool.log"
RUN_AS = 'nobody'
#
ENV['BUNDLE_GEMFILE'] = "#{root}/Gemfile"
require 'bundler/setup'
require 'rest_client'
require 'logger'
require 'json'
$stdout.sync = true
$log = Logger.new LOG_FILE
$log.info "ejabberd_auth_tool started!"
def log_error(error)
$log.error "Exception: #{error.class.name}: #{error.message}"
$log.error error.backtrace.join("\n")
end
def http_request(path, data)
response = RestClient.post "#{URL}/#{path}", data
yield response if response.code == 200
false
rescue RestClient::Exception => err
log_error err
false
end
def authenticate(username, password)
$log.info "Trying to authenticate #{username.inspect}:#{password.inspect} against #{URL}"
return false unless username =~ /\A_([0-9]+)\z/
user_id = Integer $1 rescue nil
http_request '/authentication/path', credential: password, username: username do |response|
return response.success?
end
end
def isuser(username)
$log.info "Checking if #{username.inspect} is a YOUR_SERVICE user"
http_request '/CHECK_IF_USER_EXISTS', name: username do |response|
return true if USER_EXISTS
end
end
def run_command(cmd, data)
case cmd
when 'auth' then authenticate(data[0], data[2])
when 'isuser' then isuser(data[0])
when 'tryregister' then false
else
false
end
rescue StandardError => err
log_error err
false
end
def process
raise Interrupt if $stdin.eof?
msg = $stdin.read(2)
return if msg.nil?
length = msg.unpack('n').first
msg = $stdin.read(length)
cmd, *data = msg.split(":")
$log.info "Incoming Request: #{cmd.inspect} with #{data.size} arguments"
success = run_command cmd, data
bool = success ? 1 : 0
$stdout.write [2, bool].pack("nn")
$log.info "Response: #{success ? "success" : "failure"}"
rescue => err
log_error err
sleep 1
rescue SystemExit, Interrupt, IOError
$log.info "Received interrupt - Exiting now!"
raise
end
# Drop permissions
current = Process::Sys.geteuid
if current == 0
$log.info "Changing UID to #{RUN_AS}."
Process::Sys.setuid Etc.getpwnam(RUN_AS).uid
else
$log.warn "Can NOT change UID to #{RUN_AS} as current UID is #{current} !"
end
current = nil
# Main loop
at_exit{ $log.info "Bye." }
loop{ process }
#
$log.info "ejabber_auth_tool exiting!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment