// makeGitPassHelper writes a GIT_ASKPASS helper that supplies password over stdout. // You should remove the passHelper (and tempDir if any) after using it. func makeGitPassHelper(pass string) (passHelper string, tempDir string, err error) { tmpFile, dir, err := internal.ScriptFile("go-vcs-gitcmd-ask") if err != nil { return tmpFile, dir, err } passPath := filepath.Join(dir, "password") err = internal.WriteFileWithPermissions(passPath, []byte(pass), 0600) if err != nil { return tmpFile, dir, err } var script string // We assume passPath can be escaped with a simple wrapping of single // quotes. The path is not user controlled so this assumption should // not be violated. if runtime.GOOS == "windows" { script = "@echo off\ntype " + passPath + "\n" } else { script = "#!/bin/sh\ncat '" + passPath + "'\n" } err = internal.WriteFileWithPermissions(tmpFile, []byte(script), 0500) return tmpFile, dir, err }
// Makes system-dependent SSH wrapper func gitSSHWrapper(keyFile string, otherOpt string) (sshWrapperFile string, tempDir string, err error) { // TODO(sqs): encrypt and store the key in the env so that // attackers can't decrypt if they have disk access after our // process dies var script string if runtime.GOOS == "windows" { script = ` @echo off ssh -o ControlMaster=no -o ControlPath=none ` + otherOpt + ` -i ` + filepath.ToSlash(keyFile) + ` "%@" ` } else { script = ` #!/bin/sh exec /usr/bin/ssh -o ControlMaster=no -o ControlPath=none ` + otherOpt + ` -i ` + filepath.ToSlash(keyFile) + ` "$@" ` } sshWrapperName, tempDir, err := internal.ScriptFile("go-vcs-gitcmd") if err != nil { return sshWrapperName, tempDir, err } err = internal.WriteFileWithPermissions(sshWrapperName, []byte(script), 0500) return sshWrapperName, tempDir, err }
// Makes long file with abbbb... content. Returns file name, file's content, and error if any func createLongFile() (file string, line []byte, err error) { longline := make([]byte, bufio.MaxScanTokenSize+1) for i := 0; i < len(longline); i++ { if i == 0 { longline[i] = 'a' } else { longline[i] = 'b' } } tmp, err := ioutil.TempFile("", "test") if err != nil { return "", longline, err } err = internal.WriteFileWithPermissions(tmp.Name(), longline, 0666) return tmp.Name(), longline, err }
// makeGitPassHelper writes a GIT_ASKPASS helper that supplies password over stdout. // You should remove the passHelper (and tempDir if any) after using it. func makeGitPassHelper(pass string) (passHelper string, tempDir string, err error) { tmpFile, dir, err := internal.ScriptFile("go-vcs-gitcmd-ask") if err != nil { return tmpFile, dir, err } var script string if runtime.GOOS == "windows" { script = "@echo off\necho " + pass + "\n" } else { script = "#!/bin/sh\necho '" + pass + "'\n" } err = internal.WriteFileWithPermissions(tmpFile, []byte(script), 0500) return tmpFile, dir, err }
// makeGitSSHWrapper writes a GIT_SSH wrapper that runs ssh with the // private key. You should remove the sshWrapper, sshWrapperDir and // the keyFile after using them. func makeGitSSHWrapper(privKey []byte) (sshWrapper, sshWrapperDir, keyFile string, err error) { var otherOpt string if InsecureSkipCheckVerifySSH { otherOpt = "-o StrictHostKeyChecking=no" } kf, err := ioutil.TempFile("", "go-vcs-gitcmd-key") if err != nil { return "", "", "", err } keyFile = kf.Name() err = internal.WriteFileWithPermissions(keyFile, privKey, 0600) if err != nil { return "", "", keyFile, err } tmpFile, tmpFileDir, err := gitSSHWrapper(keyFile, otherOpt) return tmpFile, tmpFileDir, keyFile, err }
func TestServer(t *testing.T) { var shellScript string if runtime.GOOS == "windows" { shellScript = `@echo off set flag=%1 set flag=%flag:"=% set args=%2 set args=%args:"=% echo %flag% %args% ` } else { shellScript = `#!/bin/sh echo $* exit ` } shell, dir, err := internal.ScriptFile("govcs-ssh-shell") if err != nil { t.Fatal(err) } defer os.Remove(shell) if dir != "" { defer os.RemoveAll(dir) } err = internal.WriteFileWithPermissions(shell, []byte(shellScript), 0700) if err != nil { t.Fatal(err) } s, err := NewServer(shell, os.TempDir(), PrivateKey(SamplePrivKey)) if err != nil { t.Fatal(err) } if err := s.Start(); err != nil { t.Fatal(err) } // Client cauth, err := clientAuth(SamplePrivKey) if err != nil { t.Fatal(err) } cconf := ssh.ClientConfig{User: "******"} cconf.Auth = append(cconf.Auth, cauth) sshc, err := ssh.Dial(s.l.Addr().Network(), s.l.Addr().String(), &cconf) if err != nil { t.Fatal(err) } defer sshc.Close() session, err := sshc.NewSession() if err != nil { t.Fatal(err) } defer session.Close() out, err := session.CombinedOutput("git-upload-pack 'foo'") if err != nil { t.Fatal(err) } if got, want := strings.TrimSpace(string(out)), "-c git-upload-pack 'foo'"; got != want { t.Errorf("got ssh session output %q, want %q", got, want) } }