gitlab.com/apertussolutions/u-root@v7.0.0+incompatible/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  	"io/ioutil"
    11  	"log"
    12  	"os"
    13  	"os/exec"
    14  	"strings"
    15  	"syscall"
    16  	"unsafe"
    17  
    18  	"github.com/gliderlabs/ssh"
    19  	"github.com/kr/pty" // TODO: get rid of krpty
    20  	flag "github.com/spf13/pflag"
    21  )
    22  
    23  var (
    24  	hostKeyFile = flag.StringP("hostkeyfile", "h", "/etc/ssh_host_rsa_key", "file for host key")
    25  	pubKeyFile  = flag.StringP("pubkeyfile", "k", "key.pub", "file for public key")
    26  	port        = flag.StringP("port", "p", "2222", "default port")
    27  )
    28  
    29  func setWinsize(f *os.File, w, h int) {
    30  	syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ),
    31  		uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0})))
    32  }
    33  
    34  func handler(s ssh.Session) {
    35  	var a []string
    36  	if len(s.Command()) > 0 {
    37  		a = append([]string{"-c"}, strings.Join(s.Command(), " "))
    38  	}
    39  	cmd := exec.Command("/bin/sh", a...)
    40  	cmd.Env = append(cmd.Env, s.Environ()...)
    41  	ptyReq, winCh, isPty := s.Pty()
    42  	if isPty {
    43  		cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term))
    44  		f, err := pty.Start(cmd)
    45  		if err != nil {
    46  			log.Print(err)
    47  			return
    48  		}
    49  		go func() {
    50  			for win := range winCh {
    51  				setWinsize(f, win.Width, win.Height)
    52  			}
    53  		}()
    54  		go func() {
    55  			io.Copy(f, s) // stdin
    56  		}()
    57  		io.Copy(s, f) // stdout
    58  	} else {
    59  		cmd.Stdin, cmd.Stdout, cmd.Stderr = s, s, s
    60  		if err := cmd.Run(); err != nil {
    61  			log.Print(err)
    62  			return
    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 := ioutil.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  }