@@ -203,10 +203,23 @@ var sysExec = syscall.Exec |
| 203 | // authorizedKeysLine builds the single line sshd consumes. The forced | 203 | // authorizedKeysLine builds the single line sshd consumes. The forced |
| 204 | // command runs `shithubd ssh-shell <user_id>`; the option set strips | 204 | // command runs `shithubd ssh-shell <user_id>`; the option set strips |
| 205 | // every interactive affordance. | 205 | // every interactive affordance. |
| | 206 | +// |
| | 207 | +// The command uses the BARE binary name (`shithubd`), not the absolute |
| | 208 | +// path of os.Args[0]. Reason: when the git user's login shell is |
| | 209 | +// /usr/bin/git-shell (kept as a defense-in-depth wall — git-shell |
| | 210 | +// only allows git's own commands plus entries in ~/git-shell-commands/), |
| | 211 | +// git-shell rejects any first token that contains a slash. With a |
| | 212 | +// bare token, git-shell looks for ~git/git-shell-commands/shithubd |
| | 213 | +// (must be a symlink to /usr/local/bin/shithubd installed by ansible) |
| | 214 | +// and execs it. |
| | 215 | +// |
| | 216 | +// PATH on the AKC's child process inherits sshd's env, which on |
| | 217 | +// Debian includes /usr/local/bin — so a fallback `shithubd` lookup |
| | 218 | +// would also find the binary even without git-shell-commands. The |
| | 219 | +// git-shell-commands symlink is the authoritative path. |
| 206 | func authorizedKeysLine(row usersdb.UserSshKey) string { | 220 | func authorizedKeysLine(row usersdb.UserSshKey) string { |
| 207 | - binary := os.Args[0] | 221 | + binary := filepath.Base(os.Args[0]) |
| 208 | - // Quote-escape only the binary path; user_id is a digit string so it | 222 | + // user_id is a digit string so it can never contain shell metacharacters. |
| 209 | - // can never contain shell metacharacters. | | |
| 210 | cmd := fmt.Sprintf(`%s ssh-shell %d`, binary, row.UserID) | 223 | cmd := fmt.Sprintf(`%s ssh-shell %d`, binary, row.UserID) |
| 211 | options := strings.Join([]string{ | 224 | options := strings.Join([]string{ |
| 212 | fmt.Sprintf(`command="%s"`, cmd), | 225 | fmt.Sprintf(`command="%s"`, cmd), |