forked from yuki-kimoto/gitprep
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gitprep-shell
executable file
·111 lines (86 loc) · 2.72 KB
/
gitprep-shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use FindBin;
use lib "$FindBin::Bin/../lib";
use lib "$FindBin::Bin/../extlib/lib/perl5";
use Gitprep;
my $debug = 0;
# Project name pattern
my $project_re = qr/[a-zA-Z0-9_\-\.]+$/;
# User
my $session_user = shift;
die "User not specifed" unless defined $session_user;
# Application
my $app = Gitprep->new;
# Git
my $git = $app->git;
# DBI
my $dbi = $app->dbi;
# SSH connection
my $ssh_connection = $ENV{SSH_CONNECTION};
warn "ssh_connection: $ssh_connection" if $debug;
die "who the *heck* are you?\n" unless defined $ssh_connection;
# SSH original command
my $ssh_original_command = $ENV{SSH_ORIGINAL_COMMAND} || '';
warn "ssh_original_command: $ssh_original_command" if $debug;
# IP address
my $ip = $ssh_connection || '(no-IP)';
warn "ip: $ip" if $debug;
$ip =~ s/ .*//;
# Check new line of SSH original command
my $ssh_original_command_tmp = $ssh_original_command;
$ssh_original_command_tmp =~ s/[\n\r]+/<<newline>>/g;
die "I don't like newlines in the command: $ssh_original_command\n"
if $ssh_original_command ne $ssh_original_command_tmp;
# Project
my ($verb, $user, $project) = parse_ssh_original_command($ssh_original_command);
sanity($project);
# Can access
my $can_access;
if ($session_user eq $user) {
$can_access = 1;
}
else {
my $row = $app->dbi->model('collaboration')->select(
id => [$user, $project, $session_user]
)->one;
$can_access = $row ? 1 : 0;
}
die qq|User "$session_user" can't access repository "$user/$project.git"\n|
unless $can_access;
# Command
my $rep_home = $git->rep_home;
my $repository = "'$rep_home/$user/$project.git'";
my @git_shell_cmd = ("git", "shell", "-c", "$verb $repository");
warn "@git_shell_cmd" if $debug;
unless ($debug) {
system(@git_shell_cmd) == 0
or die "Can't execute command: @git_shell_cmd\n" ;
}
sub parse_ssh_original_command {
my $ssh_original_command = shift;
$ssh_original_command ||= '';
my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
if ($ssh_original_command =~ m(^($git_commands) '.*/([a-zA-Z1-9_]+)/([^\/]+?)\.git'$)) {
my ($verb, $user, $project) = ($1, $2, $3);
warn "User:$user, Project:$project" if $debug;
die "invalid repo name: '$project'\n" if $project !~ $project_re;
return ($verb, $user, $project);
}
else {
die "Invalid command: $ssh_original_command\n";
}
}
sub sanity {
my $project = shift;
die "'$project' contains bad characters\n" if $project !~ $project_re;
die "'$project' ends with a '/'\n" if $project =~ m(/$);
die "'$project' contains '..'\n" if $project =~ m(\.\.);
}
=head1 NAME
gitprep-shell - AuthorizedKeysCommand for sshd
=head1 USAGE
./gitprep-shell kimoto
This command return user public_key