github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/newsshd/newsshd.go (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "fmt" 9 "io" 10 "log" 11 "os" 12 "os/exec" 13 "strings" 14 "syscall" 15 "unsafe" 16 17 "github.com/gliderlabs/ssh" 18 "github.com/kr/pty" // TODO: get rid of krpty 19 flag "github.com/spf13/pflag" 20 ) 21 22 var ( 23 hostKeyFile = flag.StringP("hostkeyfile", "h", "/etc/ssh_host_rsa_key", "file for host key") 24 pubKeyFile = flag.StringP("pubkeyfile", "k", "key.pub", "file for public key") 25 port = flag.StringP("port", "p", "2222", "default port") 26 ) 27 28 func setWinsize(f *os.File, w, h int) { 29 syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), 30 uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0}))) 31 } 32 33 func handler(s ssh.Session) { 34 var a []string 35 if len(s.Command()) > 0 { 36 a = append([]string{"-c"}, strings.Join(s.Command(), " ")) 37 } 38 cmd := exec.Command("/bin/sh", a...) 39 cmd.Env = append(cmd.Env, s.Environ()...) 40 ptyReq, winCh, isPty := s.Pty() 41 if isPty { 42 cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term)) 43 f, err := pty.Start(cmd) 44 if err != nil { 45 log.Print(err) 46 return 47 } 48 go func() { 49 for win := range winCh { 50 setWinsize(f, win.Width, win.Height) 51 } 52 }() 53 go func() { 54 io.Copy(f, s) // stdin 55 }() 56 io.Copy(s, f) // stdout 57 } else { 58 cmd.Stdin, cmd.Stdout, cmd.Stderr = s, s, s 59 if err := cmd.Run(); err != nil { 60 log.Print(err) 61 return 62 } 63 } 64 } 65 66 func main() { 67 flag.Parse() 68 publicKeyOption := func(ctx ssh.Context, key ssh.PublicKey) bool { 69 // Glob the users's home directory for all the 70 // possible keys? 71 data, err := os.ReadFile(*pubKeyFile) 72 if err != nil { 73 fmt.Print(err) 74 return false 75 } 76 allowed, _, _, _, _ := ssh.ParseAuthorizedKey(data) 77 return ssh.KeysEqual(key, allowed) 78 } 79 80 server := ssh.Server{ 81 LocalPortForwardingCallback: ssh.LocalPortForwardingCallback(func(ctx ssh.Context, dhost string, dport uint32) bool { 82 log.Println("Accepted forward", dhost, dport) 83 return true 84 }), 85 Addr: ":" + *port, 86 PublicKeyHandler: publicKeyOption, 87 ReversePortForwardingCallback: ssh.ReversePortForwardingCallback(func(ctx ssh.Context, host string, port uint32) bool { 88 log.Println("attempt to bind", host, port, "granted") 89 return true 90 }), 91 Handler: handler, 92 } 93 94 server.SetOption(ssh.HostKeyFile(*hostKeyFile)) 95 log.Println("starting ssh server on port " + *port) 96 log.Fatal(server.ListenAndServe()) 97 }