forked from shazow/ssh-chat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcmd.go
129 lines (110 loc) · 3.08 KB
/
cmd.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package main
import (
"bufio"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/signal"
"os/user"
"strings"
"github.com/alexcesaro/log"
"github.com/alexcesaro/log/golog"
"github.com/jessevdk/go-flags"
)
import _ "net/http/pprof"
// Options contains the flag options
type Options struct {
Verbose []bool `short:"v" long:"verbose" description:"Show verbose logging."`
Identity string `short:"i" long:"identity" description:"Private key to identify server with." default:"~/.ssh/id_rsa"`
Bind string `long:"bind" description:"Host and port to listen on." default:"0.0.0.0:22"`
Admin []string `long:"admin" description:"Fingerprint of pubkey to mark as admin."`
Whitelist string `long:"whitelist" description:"Optional file of pubkey fingerprints who are allowed to connect."`
Motd string `long:"motd" description:"Optional Message of the Day file."`
Pprof int `long:"pprof" description:"Enable pprof http server for profiling."`
}
var logLevels = []log.Level{
log.Warning,
log.Info,
log.Debug,
}
func main() {
options := Options{}
parser := flags.NewParser(&options, flags.Default)
p, err := parser.Parse()
if err != nil {
if p == nil {
fmt.Print(err)
}
return
}
if options.Pprof != 0 {
go func() {
fmt.Println(http.ListenAndServe(fmt.Sprintf("localhost:%d", options.Pprof), nil))
}()
}
// Initialize seed for random colors
RandomColorInit()
// Figure out the log level
numVerbose := len(options.Verbose)
if numVerbose > len(logLevels) {
numVerbose = len(logLevels)
}
logLevel := logLevels[numVerbose]
logger = golog.New(os.Stderr, logLevel)
privateKeyPath := options.Identity
if strings.HasPrefix(privateKeyPath, "~") {
user, err := user.Current()
if err == nil {
privateKeyPath = strings.Replace(privateKeyPath, "~", user.HomeDir, 1)
}
}
privateKey, err := ioutil.ReadFile(privateKeyPath)
if err != nil {
logger.Errorf("Failed to load identity: %v", err)
return
}
server, err := NewServer(privateKey)
if err != nil {
logger.Errorf("Failed to create server: %v", err)
return
}
for _, fingerprint := range options.Admin {
server.Op(fingerprint)
}
if options.Whitelist != "" {
file, err := os.Open(options.Whitelist)
if err != nil {
logger.Errorf("Could not open whitelist file")
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
server.Whitelist(scanner.Text())
}
}
if options.Motd != "" {
motd, err := ioutil.ReadFile(options.Motd)
if err != nil {
logger.Errorf("Failed to load MOTD file: %v", err)
return
}
motdString := string(motd[:])
/* hack to normalize line endings into \r\n */
motdString = strings.Replace(motdString, "\r\n", "\n", -1)
motdString = strings.Replace(motdString, "\n", "\r\n", -1)
server.SetMotd(motdString)
}
// Construct interrupt handler
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
err = server.Start(options.Bind)
if err != nil {
logger.Errorf("Failed to start server: %v", err)
return
}
<-sig // Wait for ^C signal
logger.Warningf("Interrupt signal detected, shutting down.")
server.Stop()
}