commit bba43f4598e698f3f9cbf6500a163a05e7859c9f Author: Moritz Bitsch Date: Wed Oct 6 19:31:52 2021 +0200 initial import diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..fa98426 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module codeberg.org/madmo/rdebug + +go 1.16 + +require golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a06bcfd --- /dev/null +++ b/go.sum @@ -0,0 +1,9 @@ +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/rdebug.go b/rdebug.go new file mode 100644 index 0000000..c9bd223 --- /dev/null +++ b/rdebug.go @@ -0,0 +1,125 @@ +// Helper script for remote gdb +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "os" + "path" + "strconv" + "strings" + + "golang.org/x/crypto/ssh" +) + +var ( + optUser = flag.String("user", "default", "username for ssh user") + optPassword = flag.String("pass", "", "password") + optGdbPort = flag.Uint("port", 10001, "remote gdb port to use") +) + +func main() { + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] hostname program args\n", os.Args[0]) + flag.PrintDefaults() + } + + flag.Parse() + + if flag.NArg() < 2 { + flag.Usage() + os.Exit(2) + } + + connection, err := createConnection(flag.Arg(0), *optUser, *optPassword) + if err != nil { + fmt.Fprintf(os.Stderr, "Can't connect to host: %s", err.Error()) + os.Exit(1) + } + defer connection.Close() + + err = deployFile(connection, flag.Arg(1), path.Base(flag.Arg(1)), "0755") + if err != nil { + fmt.Fprintf(os.Stderr, "Can't deploy file: %s", err.Error()) + os.Exit(1) + } + + session, err := startGDB(connection, "./"+path.Base(flag.Arg(1))) + if err != nil { + fmt.Fprintf(os.Stderr, "Can't start gdb: %s", err.Error()) + os.Exit(1) + } + defer session.Close() +} + +func startGDB(client *ssh.Client, remoteCommand string) (*ssh.Session, error) { + session, err := client.NewSession() + if err != nil { + return nil, err + } + + output, err := session.StderrPipe() + if err != nil { + return nil, err + } + + err = session.Start("exec nohup gdbserver --once :" + strconv.Itoa(int(*optGdbPort)) + " " + remoteCommand) + if err != nil { + return nil, err + } + + reader := bufio.NewReader(output) + + for line, err := reader.ReadString('\n'); err == nil; line, err = reader.ReadString('\n') { + if strings.HasPrefix(line, "Listening on port") { + println(line) + break + } + } + + return session, nil +} + +func deployFile(client *ssh.Client, localPath, remotePath string, permissions string) error { + reader, err := os.Open(localPath) + if err != nil { + return err + } + defer reader.Close() + + st, err := reader.Stat() + if err != nil { + return err + } + + session, err := client.NewSession() + if err != nil { + return err + } + defer session.Close() + + writer, _ := session.StdinPipe() + + go func() { + fmt.Fprintf(writer, "C%s %d %s\n", permissions, st.Size(), path.Base(remotePath)) + io.Copy(writer, reader) + writer.Write([]byte{0x00}) + writer.Close() + }() + + return session.Run("/usr/bin/scp -t " + path.Dir(remotePath)) +} + +func createConnection(host string, username string, password string) (*ssh.Client, error) { + config := &ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ + ssh.Password(password), + }, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + + return ssh.Dial("tcp", host, config) +}