Add support for downstream multi-line AUTHENTICATE commands

Useful for long passwords.
This commit is contained in:
Simon Ser 2021-12-09 23:21:08 +01:00
parent e397cc2a1f
commit e7f9d2332b

View File

@ -1,6 +1,7 @@
package soju package soju
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/base64" "encoding/base64"
@ -275,6 +276,7 @@ var passthroughIsupport = map[string]bool{
type downstreamSASL struct { type downstreamSASL struct {
server sasl.Server server sasl.Server
plainUsername, plainPassword string plainUsername, plainPassword string
pendingResp bytes.Buffer
} }
type downstreamConn struct { type downstreamConn struct {
@ -966,16 +968,35 @@ func (dc *downstreamConn) handleAuthenticateCommand(msg *irc.Message) (result *d
dc.sasl = &downstreamSASL{server: server} dc.sasl = &downstreamSASL{server: server}
} else { } else {
// TODO: multi-line messages chunk := msg.Params[0]
if msg.Params[0] == "+" { if chunk == "+" {
resp = nil chunk = ""
} else if resp, err = base64.StdEncoding.DecodeString(msg.Params[0]); err != nil { }
if dc.sasl.pendingResp.Len()+len(chunk) > 10*1024 {
return nil, ircError{&irc.Message{
Prefix: dc.srv.prefix(),
Command: irc.ERR_SASLFAIL,
Params: []string{dc.nick, "Response too long"},
}}
}
dc.sasl.pendingResp.WriteString(chunk)
if len(chunk) == 400 {
return nil, nil // Multi-line response, wait for the next command
}
resp, err = base64.StdEncoding.DecodeString(dc.sasl.pendingResp.String())
if err != nil {
return nil, ircError{&irc.Message{ return nil, ircError{&irc.Message{
Prefix: dc.srv.prefix(), Prefix: dc.srv.prefix(),
Command: irc.ERR_SASLFAIL, Command: irc.ERR_SASLFAIL,
Params: []string{dc.nick, "Invalid base64-encoded response"}, Params: []string{dc.nick, "Invalid base64-encoded response"},
}} }}
} }
dc.sasl.pendingResp.Reset()
} }
challenge, done, err := dc.sasl.server.Next(resp) challenge, done, err := dc.sasl.server.Next(resp)