-
Notifications
You must be signed in to change notification settings - Fork 0
/
birdrs.go
99 lines (86 loc) · 2.39 KB
/
birdrs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package main
import (
"flag"
"fmt"
"github.com/creack/pty"
"github.com/gliderlabs/ssh"
"io"
"io/ioutil"
"log"
"os/exec"
"syscall"
"unsafe"
)
var release = "dev" // set by build process
var (
hostKeyFile = flag.String("k", "~/.ssh/id_ed25519", "SSH host key file")
listenPort = flag.String("b", ":22", "SSH daemon bind address:port")
bannerPath = flag.String("m", "", "path to text file for connection banner")
verbose = flag.Bool("v", false, "enable verbose debugging output")
birdPath = flag.String("p", "birdc", "path to birdc binary")
)
func main() {
flag.Usage = func() {
fmt.Printf("Usage for birdrs (%s) https://github.com/natesales/birdrs:\n", release)
flag.PrintDefaults()
}
flag.Parse()
if *verbose {
log.Println("verbose logging enabled")
}
var banner []byte
if *bannerPath != "" { // If bannerPath is set
_banner, err := ioutil.ReadFile(*bannerPath)
if err != nil {
log.Fatalf("reading banner file %s: %v", *bannerPath, err)
}
banner = _banner // TODO: Fix scope here
}
log.Printf("starting birdrs %s\n", release)
log.Printf("using bird path: %s\n", *birdPath)
ssh.Handle(func(s ssh.Session) {
log.Printf("new connection from %s\n", s.RemoteAddr())
if *bannerPath != "" { // If bannerPath is set
s.Write(banner)
}
cmd := exec.Command(*birdPath, "-r") // -r flag for restricted mode
ptyReq, winCh, isPty := s.Pty()
if isPty {
cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term))
f, err := pty.Start(cmd)
if err != nil {
panic(err)
}
go func() {
for win := range winCh {
syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(win.Height), uint16(win.Width), 0, 0})))
}
}()
go func() { // goroutine to handle
_, err = io.Copy(f, s) // stdin
if err != nil {
if *verbose {
log.Printf("command f->s copy error: %v\n", err)
}
}
}()
_, err = io.Copy(s, f) // stdout
if err != nil {
if *verbose {
log.Printf("command s->f copy error: %v\n", err)
}
}
err = cmd.Wait()
if err != nil {
if *verbose {
log.Printf("command wait error: %v\n", err)
}
}
} else {
io.WriteString(s, "No PTY requested.\n")
s.Exit(1)
}
})
log.Printf("starting birdrs ssh server on port %s\n", *listenPort)
log.Fatal(ssh.ListenAndServe(*listenPort, nil, ssh.HostKeyFile(*hostKeyFile)))
}