@@ -2,13 +2,15 @@ package main
2
2
3
3
import (
4
4
"bufio"
5
+ "errors"
5
6
"fmt"
6
7
"io/ioutil"
7
8
"net/http"
8
9
"os"
9
10
"os/signal"
10
11
"os/user"
11
12
"strings"
13
+ "time"
12
14
13
15
"github.com/alexcesaro/log"
14
16
"github.com/alexcesaro/log/golog"
@@ -19,8 +21,9 @@ import (
19
21
"github.com/shazow/ssh-chat/chat"
20
22
"github.com/shazow/ssh-chat/chat/message"
21
23
"github.com/shazow/ssh-chat/sshd"
24
+
25
+ _ "net/http/pprof"
22
26
)
23
- import _ "net/http/pprof"
24
27
25
28
// Version of the binary, assigned during build.
26
29
var Version string = "dev"
@@ -36,8 +39,22 @@ type Options struct {
36
39
Motd string `long:"motd" description:"Optional Message of the Day file."`
37
40
Log string `long:"log" description:"Write chat log to this file."`
38
41
Pprof int `long:"pprof" description:"Enable pprof http server for profiling."`
42
+
43
+ // Hidden flags, because they're discouraged from being used casually.
44
+ Passphrase string `long:"unsafe-passphrase" description:"Require an interactive passphrase to connect. Whitelist feature is more secure." hidden:"true"`
39
45
}
40
46
47
+ const extraHelp = `There are hidden options and easter eggs in ssh-chat. The source code is a good
48
+ place to start looking. Some useful links:
49
+
50
+ * Project Repository:
51
+ https://github.com/shazow/ssh-chat
52
+ * Project Wiki FAQ:
53
+ https://github.com/shazow/ssh-chat/wiki/FAQ
54
+ * Command Flags Declaration:
55
+ https://github.com/shazow/ssh-chat/blob/master/cmd/ssh-chat/cmd.go#L29
56
+ `
57
+
41
58
var logLevels = []log.Level {
42
59
log .Warning ,
43
60
log .Info ,
@@ -57,6 +74,9 @@ func main() {
57
74
if p == nil {
58
75
fmt .Print (err )
59
76
}
77
+ if flagErr , ok := err .(* flags.Error ); ok && flagErr .Type == flags .ErrHelp {
78
+ fmt .Print (extraHelp )
79
+ }
60
80
return
61
81
}
62
82
@@ -78,7 +98,8 @@ func main() {
78
98
}
79
99
80
100
logLevel := logLevels [numVerbose ]
81
- sshchat .SetLogger (golog .New (os .Stderr , logLevel ))
101
+ logger := golog .New (os .Stderr , logLevel )
102
+ sshchat .SetLogger (logger )
82
103
83
104
if logLevel == log .Debug {
84
105
// Enable logging from submodules
@@ -109,6 +130,45 @@ func main() {
109
130
config := sshd .MakeAuth (auth )
110
131
config .AddHostKey (signer )
111
132
config .ServerVersion = "SSH-2.0-Go ssh-chat"
133
+ // FIXME: Should we be using config.NoClientAuth = true by default?
134
+
135
+ if options .Passphrase != "" {
136
+ if options .Whitelist != "" {
137
+ logger .Warning ("Passphrase is disabled while whitelist is enabled." )
138
+ }
139
+ if config .KeyboardInteractiveCallback != nil {
140
+ fail (1 , "Passphrase authentication conflicts with existing KeyboardInteractive setup." ) // This should not happen
141
+ }
142
+
143
+ // We use KeyboardInteractiveCallback instead of PasswordCallback to
144
+ // avoid preventing the client from including a pubkey in the user
145
+ // identification.
146
+ config .KeyboardInteractiveCallback = func (conn ssh.ConnMetadata , challenge ssh.KeyboardInteractiveChallenge ) (* ssh.Permissions , error ) {
147
+ answers , err := challenge ("" , "" , []string {"Passphrase required to connect: " }, []bool {true })
148
+ if err != nil {
149
+ return nil , err
150
+ }
151
+ if len (answers ) == 1 && answers [0 ] == options .Passphrase {
152
+ // Success
153
+ return nil , nil
154
+ }
155
+ // It's not gonna do much but may as well throttle brute force attempts a little
156
+ time .Sleep (2 * time .Second )
157
+
158
+ return nil , errors .New ("incorrect passphrase" )
159
+ }
160
+
161
+ // We also need to override the PublicKeyCallback to prevent rando pubkeys from bypassing
162
+ cb := config .PublicKeyCallback
163
+ config .PublicKeyCallback = func (conn ssh.ConnMetadata , key ssh.PublicKey ) (* ssh.Permissions , error ) {
164
+ perms , err := cb (conn , key )
165
+ if err == nil {
166
+ err = errors .New ("passphrase authentication required" )
167
+ }
168
+ return perms , err
169
+ }
170
+
171
+ }
112
172
113
173
s , err := sshd .ListenSSH (options .Bind , config )
114
174
if err != nil {
0 commit comments