gitreef

A GIT over SSH server implemented using fish.
Log | Files | Refs | README | LICENSE

git-run (1853B)


      1 #!/usr/bin/env fish
      2 
      3 # load common environment
      4 source (status dirname)/env
      5 
      6 set gitCommand
      7 set repoDir
      8 set currentUser (whoami)
      9 
     10 ###
     11 ###
     12 ### functions
     13 ###
     14 ###
     15 
     16 function log --on-event log
     17 	echo "$(date -Is): $argv[1..2] user=$currentUser $argv[3..] ip=$SSH_CONNECTION" >> $_LOG
     18 end
     19 
     20 function parseCommand
     21 	set -l matcher (string match -r -g $_GIT_VALIDATION_REGEX -- "$argv")
     22 
     23 	# check given git command
     24 	# basic form is <git-command> '<path-to-repo>'
     25 	if test (count $matcher) -ne 2
     26 		emit log DENY bad_format "argv=$argv"
     27 		return 1
     28 	end
     29 
     30 	# extract variables
     31 	set gitCommand $matcher[1]
     32 
     33 	# adjust repo path to /srv/repos
     34 	set repoDir /(string join -n '/' srv repos (string split '/' $matcher[2]))
     35 end
     36 
     37 function verifyRepoJail
     38 	set -l realPath (realpath $repoDir)
     39 	if not string match -r -q -- "/srv/repos/.*" "$realPath"
     40 		emit log DENY jail_escape "realPath=$realPath"
     41 		return 2
     42 	end
     43 end
     44 
     45 function verifyPermissions
     46 	set -l permission
     47 	switch "$gitCommand"
     48 		case "git-upload-pack"
     49 			# allow clone/fetch/pull
     50 			set permission [rw]
     51 		case "git-upload-archive"
     52 			# allow remote archive
     53 			set permission [rw]
     54 		case "git-receive-pack"
     55 			# only allow for write users
     56 			set permission [w]
     57 		case '*'
     58 			# this should not happend because we sanitize above the git command
     59 			emit log DENY unkown_git_command "gitCommand=$gitCommand"
     60 			return 3
     61 	end
     62 
     63 	# check for permissions
     64 	if not grep -q -E "^$repoDir:$currentUser:$permission\$" < $_REPO_PERMISSIONS_FILE
     65 		emit log DENY no_permissions
     66 		return 4
     67 	end
     68 end
     69 
     70 ###
     71 ###
     72 ### main
     73 ###
     74 ###
     75 
     76 # redirect stdout/stderr to file, no information to potential attacker
     77 begin
     78 	parseCommand $argv; or exit $status
     79 
     80 	verifyRepoJail; or exit $status
     81 	
     82 	verifyPermissions; or exit $status
     83 
     84 	emit log ALLOW ok "argv=$argv"
     85 end &>>$_LOG
     86 
     87 exec /usr/bin/sudo -n -u git /usr/bin/git-shell -c "$gitCommand '$repoDir'"