| 1 |
#!/usr/bin/env ruby |
| 2 |
|
| 3 |
require "yaml" |
| 4 |
if File.symlink?(__FILE__) |
| 5 |
$:.unshift File.dirname(File.readlink(__FILE__)) + "/../lib/gitorious/ssh" |
| 6 |
BASE_DIR = File.dirname(File.readlink(__FILE__)) + "/../" |
| 7 |
conf_file = File.join(BASE_DIR, "config/gitorious.yml") |
| 8 |
else |
| 9 |
$:.unshift File.dirname(__FILE__) + "/../lib/gitorious/ssh" |
| 10 |
BASE_DIR = File.dirname(__FILE__) + "/../" |
| 11 |
conf_file = File.join(BASE_DIR, "config/gitorious.yml") |
| 12 |
end |
| 13 |
|
| 14 |
#$DEBUG=true |
| 15 |
|
| 16 |
RAILS_ENV = ENV['RAILS_ENV'] ||= 'production' |
| 17 |
|
| 18 |
GitoriousConfig = YAML::load_file(conf_file)[RAILS_ENV] |
| 19 |
|
| 20 |
ENV["PATH"] = "/usr/local/bin/:/opt/local/bin:#{ENV["PATH"]}" |
| 21 |
|
| 22 |
require "logger" |
| 23 |
require "strainer" |
| 24 |
require "client" |
| 25 |
|
| 26 |
File.umask(0022) |
| 27 |
original_command = ENV["SSH_ORIGINAL_COMMAND"] |
| 28 |
user = ARGV[0] |
| 29 |
|
| 30 |
logger = Logger.new(File.join(BASE_DIR, "log", "gitorious_auth.log")) |
| 31 |
logger.formatter = Logger::Formatter.new |
| 32 |
logger.level = Logger::INFO |
| 33 |
logger.formatter.datetime_format = "%Y-%m-%d %H:%M:%S" |
| 34 |
logger.info("Connection from #{ENV['SSH_CLIENT'].inspect} (#{user || nil}): #{original_command || nil}") |
| 35 |
|
| 36 |
$stderr.puts "original_command: #{original_command.inspect}" if $DEBUG |
| 37 |
if original_command.nil? || original_command.strip.empty? |
| 38 |
logger.info("Need SSH_ORIGINAL_COMMAND") |
| 39 |
$stderr.puts "Need SSH_ORIGINAL_COMMAND" |
| 40 |
exit!(1) |
| 41 |
end |
| 42 |
|
| 43 |
$stderr.puts "user: #{user.inspect}" if $DEBUG |
| 44 |
if user.nil? || user.strip.empty? |
| 45 |
logger.info("Need user arg") |
| 46 |
$stderr.puts "Need user arg" |
| 47 |
exit!(1) |
| 48 |
end |
| 49 |
|
| 50 |
def gitorious_says(msg) |
| 51 |
$stderr.puts |
| 52 |
$stderr.puts "== Gitorious: " + ("=" * 59) |
| 53 |
$stderr.puts msg |
| 54 |
$stderr.puts "="*72 |
| 55 |
$stderr.puts |
| 56 |
end |
| 57 |
|
| 58 |
begin |
| 59 |
strainer = Gitorious::SSH::Strainer.new(original_command).parse! |
| 60 |
client = Gitorious::SSH::Client.new(strainer, user) |
| 61 |
|
| 62 |
args = client.to_git_shell_argument |
| 63 |
$stderr.puts "git-shell -c #{args.inspect}" if $DEBUG |
| 64 |
ENV['GITORIOUS_WRITABLE_BY_URL'] = client.writable_by_query_url |
| 65 |
ENV['GITORIOUS_USER'] = user |
| 66 |
ENV['GITORIOUS_BASE_DIR'] = BASE_DIR |
| 67 |
ENV['GITORIOUS_DENY_FORCE_PUSHES'] = client.force_pushing_denied? ? "true" : "false" |
| 68 |
|
| 69 |
logger.info("Accepted #{user.inspect} for #{args.inspect}") |
| 70 |
if client.pre_receive_hook_exists? |
| 71 |
exec("git-shell", "-c", args) |
| 72 |
else |
| 73 |
logger.fatal("The pre-receive hook is not executable") |
| 74 |
gitorious_says "Fatal error, please contact support" |
| 75 |
exit!(1) |
| 76 |
end |
| 77 |
|
| 78 |
unless $?.success? |
| 79 |
logger.fatal("Failed to execute git command") |
| 80 |
gitorious_says "Failed to execute git command" |
| 81 |
exit!(1) |
| 82 |
end |
| 83 |
rescue Gitorious::SSH::AccessDeniedError => e |
| 84 |
logger.info("Access denied or bad repository path for #{user.inspect}: #{original_command.inspect}") |
| 85 |
gitorious_says "Access denied or wrong repository path" |
| 86 |
exit!(1) |
| 87 |
rescue Gitorious::SSH::BadCommandError => e |
| 88 |
logger.info("Access denied or bad command for #{user.inspect}: #{original_command.inspect}") |
| 89 |
gitorious_says "Access denied or bad command" |
| 90 |
exit!(1) |
| 91 |
rescue Errno::ECONNREFUSED => e |
| 92 |
logger.fatal("Connection refused querying for paths/permissions") |
| 93 |
gitorious_says("Temporary error. Please try again shortly") |
| 94 |
exit!(1) |
| 95 |
rescue Object => e |
| 96 |
if $DEBUG |
| 97 |
$stderr.puts "#{e.class.name} #{e.message}" |
| 98 |
$stderr.puts e.backtrace.join(" \n") |
| 99 |
end |
| 100 |
logger.fatal("#{e.class.name} #{e.message}: #{e.backtrace.join("\n ")}") |
| 101 |
gitorious_says "fatal error" |
| 102 |
exit(1) |
| 103 |
end |