mirror of
https://github.com/shazow/ssh-chat.git
synced 2025-04-24 04:20:58 +03:00
Merge branch 'master' into whitelist-command
This commit is contained in:
commit
89ee27d930
2
Makefile
2
Makefile
@ -43,4 +43,4 @@ release:
|
||||
deploy: build/ssh-chat-linux_amd64.tgz
|
||||
ssh -p 2022 ssh.chat tar xvz < build/ssh-chat-linux_amd64.tgz
|
||||
@echo " --- Ready to deploy ---"
|
||||
@echo "Run: ssh -p 2022 ssh.chat sudo systemctl restart ssh-chat"
|
||||
@echo "Run: ssh -t -p 2022 ssh.chat sudo systemctl restart ssh-chat"
|
||||
|
@ -18,7 +18,9 @@ $ ssh ssh.chat
|
||||
|
||||
Please abide by our [project's Code of Conduct](https://github.com/shazow/ssh-chat/blob/master/CODE_OF_CONDUCT.md) while participating in chat.
|
||||
|
||||
The server's RSA key fingerprint is `MD5:e5:d5:d1:75:90:38:42:f6:c7:03:d7:d0:56:7d:6a:db` or `SHA256:HQDLlZsXL3t0lV5CHM0OXeZ5O6PcfHuzkS8cRbbTLBI`. If you see something different, you might be [MITM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack)'d.
|
||||
The host's public key is `ssh.chat ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPrQofxXqoz2y9A7NFkkENt6iW8/mvpfes3RY/41Oyt` and the fingerprint is `SHA256:yoqMXkCysMTBsvhu2yRoMUl+EmZKlvkN+ZKmL3115xU` (as of 2021-10-13).
|
||||
|
||||
If you see something different, you might be [MITM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack)'d.
|
||||
|
||||
(Apologies if the server is down, try again shortly.)
|
||||
|
||||
|
@ -469,12 +469,13 @@ func InitCommands(c *Commands) {
|
||||
msg.From().SetAway(awayMsg)
|
||||
if awayMsg != "" {
|
||||
room.Send(message.NewEmoteMsg("has gone away: "+awayMsg, msg.From()))
|
||||
} else if !isAway {
|
||||
room.Send(message.NewSystemMsg("Not away. Append a reason message to set away.", msg.From()))
|
||||
} else {
|
||||
room.Send(message.NewEmoteMsg("is back.", msg.From()))
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
if isAway {
|
||||
room.Send(message.NewEmoteMsg("is back.", msg.From()))
|
||||
return nil
|
||||
}
|
||||
return errors.New("not away. Append a reason message to set away")
|
||||
},
|
||||
})
|
||||
|
||||
@ -486,8 +487,9 @@ func InitCommands(c *Commands) {
|
||||
if isAway {
|
||||
msg.From().SetAway("")
|
||||
room.Send(message.NewEmoteMsg("is back.", msg.From()))
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return errors.New("must be away to be back")
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -25,10 +25,17 @@ func TestAwayCommands(t *testing.T) {
|
||||
// expected output
|
||||
IsUserAway bool
|
||||
AwayMessage string
|
||||
|
||||
// expected state change
|
||||
ExpectsError func(awayBefore bool) bool
|
||||
}
|
||||
awayStep := step{"/away snorkling", true, "snorkling"}
|
||||
notAwayStep := step{"/away", false, ""}
|
||||
backStep := step{"/back", false, ""}
|
||||
neverError := func(_ bool) bool { return false }
|
||||
// if the user was away before, then the error is expected
|
||||
errorIfAwayBefore := func(awayBefore bool) bool { return awayBefore }
|
||||
|
||||
awayStep := step{"/away snorkling", true, "snorkling", neverError}
|
||||
notAwayStep := step{"/away", false, "", errorIfAwayBefore}
|
||||
backStep := step{"/back", false, "", errorIfAwayBefore}
|
||||
|
||||
steps := []step{awayStep, notAwayStep, backStep}
|
||||
cases := [][]int{
|
||||
@ -42,7 +49,12 @@ func TestAwayCommands(t *testing.T) {
|
||||
for _, s := range []step{steps[c[0]], steps[c[1]], steps[c[2]]} {
|
||||
msg, _ := message.NewPublicMsg(s.Msg, u).ParseCommand()
|
||||
|
||||
cmds.Run(room, *msg)
|
||||
awayBeforeCommand, _, _ := u.GetAway()
|
||||
|
||||
err := cmds.Run(room, *msg)
|
||||
if err != nil && s.ExpectsError(awayBeforeCommand) {
|
||||
t.Fatalf("unexpected error running the command: %+v", err)
|
||||
}
|
||||
|
||||
isAway, _, awayMsg := u.GetAway()
|
||||
if isAway != s.IsUserAway {
|
||||
|
@ -26,16 +26,16 @@ var Version string = "dev"
|
||||
|
||||
// Options contains the flag options
|
||||
type Options struct {
|
||||
Admin string `long:"admin" description:"File of public keys who are admins."`
|
||||
Bind string `long:"bind" description:"Host and port to listen on." default:"0.0.0.0:2022"`
|
||||
Identity string `short:"i" long:"identity" description:"Private key to identify server with." default:"~/.ssh/id_rsa"`
|
||||
Log string `long:"log" description:"Write chat log to this file."`
|
||||
Motd string `long:"motd" description:"Optional Message of the Day file."`
|
||||
Pprof int `long:"pprof" description:"Enable pprof http server for profiling."`
|
||||
Verbose []bool `short:"v" long:"verbose" description:"Show verbose logging."`
|
||||
Version bool `long:"version" description:"Print version and exit."`
|
||||
Whitelist string `long:"whitelist" description:"Optional file of public keys who are allowed to connect."`
|
||||
Passphrase string `long:"unsafe-passphrase" description:"Require an interactive passphrase to connect. Whitelist feature is more secure."`
|
||||
Admin string `long:"admin" description:"File of public keys who are admins."`
|
||||
Bind string `long:"bind" description:"Host and port to listen on." default:"0.0.0.0:2022"`
|
||||
Identity []string `short:"i" long:"identity" description:"Private key to identify server with." default:"~/.ssh/id_rsa"`
|
||||
Log string `long:"log" description:"Write chat log to this file."`
|
||||
Motd string `long:"motd" description:"Optional Message of the Day file."`
|
||||
Pprof int `long:"pprof" description:"Enable pprof http server for profiling."`
|
||||
Verbose []bool `short:"v" long:"verbose" description:"Show verbose logging."`
|
||||
Version bool `long:"version" description:"Print version and exit."`
|
||||
Whitelist string `long:"whitelist" description:"Optional file of public keys who are allowed to connect."`
|
||||
Passphrase string `long:"unsafe-passphrase" description:"Require an interactive passphrase to connect. Whitelist feature is more secure."`
|
||||
}
|
||||
|
||||
const extraHelp = `There are hidden options and easter eggs in ssh-chat. The source code is a good
|
||||
@ -100,25 +100,28 @@ func main() {
|
||||
message.SetLogger(os.Stderr)
|
||||
}
|
||||
|
||||
privateKeyPath := options.Identity
|
||||
if strings.HasPrefix(privateKeyPath, "~/") {
|
||||
user, err := user.Current()
|
||||
if err == nil {
|
||||
privateKeyPath = strings.Replace(privateKeyPath, "~", user.HomeDir, 1)
|
||||
}
|
||||
}
|
||||
|
||||
signer, err := ReadPrivateKey(privateKeyPath)
|
||||
if err != nil {
|
||||
fail(3, "Failed to read identity private key: %v\n", err)
|
||||
}
|
||||
|
||||
auth := sshchat.NewAuth()
|
||||
config := sshd.MakeAuth(auth)
|
||||
config.AddHostKey(signer)
|
||||
config.ServerVersion = "SSH-2.0-Go ssh-chat"
|
||||
// FIXME: Should we be using config.NoClientAuth = true by default?
|
||||
|
||||
for _, privateKeyPath := range options.Identity {
|
||||
if strings.HasPrefix(privateKeyPath, "~/") {
|
||||
user, err := user.Current()
|
||||
if err == nil {
|
||||
privateKeyPath = strings.Replace(privateKeyPath, "~", user.HomeDir, 1)
|
||||
}
|
||||
}
|
||||
|
||||
signer, err := ReadPrivateKey(privateKeyPath)
|
||||
if err != nil {
|
||||
fail(3, "Failed to read identity private key: %v\n", err)
|
||||
}
|
||||
|
||||
config.AddHostKey(signer)
|
||||
fmt.Printf("Added server identity: %s\n", sshd.Fingerprint(signer.PublicKey()))
|
||||
}
|
||||
|
||||
s, err := sshd.ListenSSH(options.Bind, config)
|
||||
if err != nil {
|
||||
fail(4, "Failed to listen on socket: %v\n", err)
|
||||
|
6
go.mod
6
go.mod
@ -4,11 +4,11 @@ require (
|
||||
github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58
|
||||
github.com/jessevdk/go-flags v1.5.0
|
||||
github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6
|
||||
golang.org/x/text v0.3.5
|
||||
golang.org/x/text v0.3.6
|
||||
)
|
||||
|
||||
go 1.13
|
||||
|
17
go.sum
17
go.sum
@ -4,19 +4,20 @@ github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LF
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 h1:zwQ1HBo5FYwn1ksMd19qBCKO8JAWE9wmHivEpkw/DvE=
|
||||
github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8=
|
||||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 h1:EC6+IGYTjPpRfv9a2b/6Puw0W+hLtAhkV1tPsXhutqs=
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -264,6 +264,10 @@ func (t *Terminal) moveCursorToPos(pos int) {
|
||||
return
|
||||
}
|
||||
|
||||
if pos > len(t.line) {
|
||||
pos = len(t.line)
|
||||
}
|
||||
|
||||
x := visualLength(t.prompt) + visualLength(t.line[:pos])
|
||||
y := x / t.termWidth
|
||||
x = x % t.termWidth
|
||||
|
Loading…
x
Reference in New Issue
Block a user