Example #1
0
func main() {
	syscall.Umask(0022) // set umask for pushes

	clientId := common.Getenv("SSH_CLIENT", "local")
	logfilePath := common.Getenv("LOGFILE", "/var/log/gitorious/gitorious-shell.log")
	internalApiUrl := common.Getenv("GITORIOUS_INTERNAL_API_URL", "http://localhost:3000/api/internal")

	logger := getLogger(logfilePath, clientId)
	internalApi := &api.GitoriousInternalApi{internalApiUrl}

	logger.Printf("client connected")

	if len(os.Args) < 2 {
		say("Error occured, please contact support")
		logger.Printf("username argument missing, check .authorized_keys file")
		os.Exit(1)
	}

	username := os.Args[1]
	logger.Printf("user authenticated as %v", username)

	sshCommand := strings.Trim(os.Getenv("SSH_ORIGINAL_COMMAND"), " \n")

	if sshCommand == "" { // deny regular ssh login attempts
		say("Hey %v! Sorry, Gitorious doesn't provide shell access. Bye!", username)
		logger.Printf("SSH_ORIGINAL_COMMAND missing, aborting...")
		os.Exit(1)
	}

	logger.Printf("processing command: %v", sshCommand)

	command, repoPath, err := parseGitShellCommand(sshCommand)
	if err != nil {
		say("Invalid command")
		logger.Printf("%v, aborting...", err)
		os.Exit(1)
	}

	repoConfig, err := internalApi.GetRepoConfig(repoPath, username)
	if err != nil {
		if httpErr, ok := err.(*api.HttpError); ok {
			if httpErr.StatusCode == 403 {
				say("Access denied")
				logger.Printf("%v, aborting...", err)
				os.Exit(1)
			} else if httpErr.StatusCode == 404 {
				say("Invalid repository path")
				logger.Printf("%v, aborting...", err)
				os.Exit(1)
			}
		}

		say("Error occured, please contact support")
		logger.Printf("%v, aborting...", err)
		os.Exit(1)
	}

	logger.Printf("full repo path: %v", repoConfig.FullPath)

	if !common.PreReceiveHookExists(repoConfig.FullPath) {
		say("Error occurred, please contact support")
		logger.Printf("pre-receive hook for %v is missing or is not executable, aborting...", repoConfig.FullPath)
		os.Exit(1)
	}

	gitShellCommand := formatGitShellCommand(command, repoConfig.FullPath)
	env := createSshEnv(username, repoConfig)

	logger.Printf(`invoking git-shell with command "%v"`, gitShellCommand)

	if stderr, err := execGitShell(gitShellCommand, env, os.Stdin, os.Stdout); err != nil {
		say("Error occurred, please contact support")
		logger.Printf("error occured in git-shell: %v", err)
		logger.Printf("stderr: %v", stderr)
		os.Exit(1)
	}

	logger.Printf("done")
}
Example #2
0
func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	logger := &common.SessionLogger{h.logger, req.RemoteAddr}

	logger.Printf("client connected")

	var username string

	if usernameOrEmail, password, ok := BasicAuth(req); ok {
		user, err := h.internalApi.AuthenticateUser(usernameOrEmail, password)
		if err != nil {
			say(w, http.StatusInternalServerError, "Error occured, please contact support")
			logger.Printf("%v, disconnecting...", err)
			return
		}

		if user != nil {
			username = user.Username
			logger.Printf("user authenticated as %v", username)
		} else {
			requestBasicAuth(w, "Invalid username or password")
			logger.Printf("invalid credentials, requesting basic auth, disconnecting...")
			return
		}
	}

	logger.Printf("processing request: %v", req.URL.String())

	repoPath, slug, err := parsePath(req.URL.Path)
	if err != nil {
		say(w, http.StatusBadRequest, "Invalid command")
		logger.Printf("%v, disconnecting...", err)
		return
	}

	if (req.URL.Query().Get("service") == "git-receive-pack" || slug == "/git-receive-pack") && username == "" {
		requestBasicAuth(w, "Anonymous pushing not allowed")
		logger.Printf("denying anonymous push, requesting basic auth, disconnecting...")
		return
	}

	repoConfig, err := h.internalApi.GetRepoConfig(repoPath, username)
	if err != nil {
		if httpErr, ok := err.(*api.HttpError); ok {
			if httpErr.StatusCode == 403 {
				requestBasicAuth(w, "Access denied")
				logger.Printf("%v, requesting basic auth, disconnecting...", err)
				return
			} else if httpErr.StatusCode == 404 {
				say(w, http.StatusNotFound, "Invalid repository path")
				logger.Printf("%v, disconnecting...", err)
				return
			}
		}

		say(w, http.StatusInternalServerError, "Error occured, please contact support")
		logger.Printf("%v, disconnecting...", err)
		return
	}

	logger.Printf("full repo path: %v", repoConfig.FullPath)

	if !common.PreReceiveHookExists(repoConfig.FullPath) {
		say(w, http.StatusInternalServerError, "Error occurred, please contact support")
		logger.Printf("pre-receive hook for %v is missing or is not executable, aborting...", repoConfig.FullPath)
		return
	}

	translatedPath := repoConfig.FullPath + slug
	env := createHttpEnv(username, repoConfig, translatedPath)

	logger.Printf(`invoking git-http-backend with translated path "%v"`, translatedPath)

	execGitHttpBackend(env, w, req)

	logger.Printf("done")
}