Allow AUTHENTICATE before NICK
Now that dc.nick is not blank during registration, sasl replies from the server are correct and cap handling can be a bit simplified.
This commit is contained in:
parent
98af48d254
commit
dcc1eff130
@ -178,7 +178,8 @@ func updateNetworkAttrs(record *Network, attrs irc.Tags, subcommand string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ' ' and ':' break the IRC message wire format, '@' and '!' break prefixes,
|
// ' ' and ':' break the IRC message wire format, '@' and '!' break prefixes,
|
||||||
// '*' and '?' break masks, '$' breaks server masks in PRIVMSG/NOTICE
|
// '*' and '?' break masks, '$' breaks server masks in PRIVMSG/NOTICE,
|
||||||
|
// "*" is the reserved nickname for registration
|
||||||
const illegalNickChars = " :@!*?$"
|
const illegalNickChars = " :@!*?$"
|
||||||
|
|
||||||
// permanentDownstreamCaps is the list of always-supported downstream
|
// permanentDownstreamCaps is the list of always-supported downstream
|
||||||
@ -280,6 +281,8 @@ func newDownstreamConn(srv *Server, ic ircConn, id uint64) *downstreamConn {
|
|||||||
dc := &downstreamConn{
|
dc := &downstreamConn{
|
||||||
conn: *newConn(srv, ic, &options),
|
conn: *newConn(srv, ic, &options),
|
||||||
id: id,
|
id: id,
|
||||||
|
nick: "*",
|
||||||
|
nickCM: "*",
|
||||||
supportedCaps: make(map[string]string),
|
supportedCaps: make(map[string]string),
|
||||||
caps: make(map[string]bool),
|
caps: make(map[string]bool),
|
||||||
monitored: newCasemapMap(0),
|
monitored: newCasemapMap(0),
|
||||||
@ -684,27 +687,24 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
|||||||
case "AUTHENTICATE":
|
case "AUTHENTICATE":
|
||||||
if !dc.caps["sasl"] {
|
if !dc.caps["sasl"] {
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{"*", "AUTHENTICATE requires the \"sasl\" capability to be enabled"},
|
Params: []string{"*", "AUTHENTICATE requires the \"sasl\" capability to be enabled"},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
if len(msg.Params) == 0 {
|
if len(msg.Params) == 0 {
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{"*", "Missing AUTHENTICATE argument"},
|
Params: []string{"*", "Missing AUTHENTICATE argument"},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
if dc.nick == "" {
|
|
||||||
return ircError{&irc.Message{
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
|
||||||
Params: []string{"*", "Expected NICK command before AUTHENTICATE"},
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
var resp []byte
|
var resp []byte
|
||||||
if msg.Params[0] == "*" {
|
if msg.Params[0] == "*" {
|
||||||
dc.saslServer = nil
|
dc.saslServer = nil
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.ERR_SASLABORTED,
|
Command: irc.ERR_SASLABORTED,
|
||||||
Params: []string{"*", "SASL authentication aborted"},
|
Params: []string{"*", "SASL authentication aborted"},
|
||||||
}}
|
}}
|
||||||
@ -720,6 +720,7 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
|||||||
}))
|
}))
|
||||||
default:
|
default:
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{"*", fmt.Sprintf("Unsupported SASL mechanism %q", mech)},
|
Params: []string{"*", fmt.Sprintf("Unsupported SASL mechanism %q", mech)},
|
||||||
}}
|
}}
|
||||||
@ -733,6 +734,7 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
dc.saslServer = nil
|
dc.saslServer = nil
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{"*", "Invalid base64-encoded response"},
|
Params: []string{"*", "Invalid base64-encoded response"},
|
||||||
}}
|
}}
|
||||||
@ -744,6 +746,7 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
|||||||
dc.saslServer = nil
|
dc.saslServer = nil
|
||||||
if ircErr, ok := err.(ircError); ok && ircErr.Message.Command == irc.ERR_PASSWDMISMATCH {
|
if ircErr, ok := err.(ircError); ok && ircErr.Message.Command == irc.ERR_PASSWDMISMATCH {
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{"*", ircErr.Message.Params[1]},
|
Params: []string{"*", ircErr.Message.Params[1]},
|
||||||
}}
|
}}
|
||||||
@ -823,7 +826,7 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
|||||||
dc.logger.Printf("unhandled message: %v", msg)
|
dc.logger.Printf("unhandled message: %v", msg)
|
||||||
return newUnknownCommandError(msg.Command)
|
return newUnknownCommandError(msg.Command)
|
||||||
}
|
}
|
||||||
if dc.rawUsername != "" && dc.nick != "" && !dc.negotiatingCaps {
|
if dc.rawUsername != "" && dc.nick != "*" && !dc.negotiatingCaps {
|
||||||
return dc.register(ctx)
|
return dc.register(ctx)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -832,11 +835,6 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
|||||||
func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
|
func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
|
||||||
cmd = strings.ToUpper(cmd)
|
cmd = strings.ToUpper(cmd)
|
||||||
|
|
||||||
replyTo := dc.nick
|
|
||||||
if !dc.registered {
|
|
||||||
replyTo = "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case "LS":
|
case "LS":
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
@ -867,7 +865,7 @@ func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
|
|||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
Prefix: dc.srv.prefix(),
|
||||||
Command: "CAP",
|
Command: "CAP",
|
||||||
Params: []string{replyTo, "LS", strings.Join(caps, " ")},
|
Params: []string{dc.nick, "LS", strings.Join(caps, " ")},
|
||||||
})
|
})
|
||||||
|
|
||||||
if dc.capVersion >= 302 {
|
if dc.capVersion >= 302 {
|
||||||
@ -890,13 +888,13 @@ func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
|
|||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
Prefix: dc.srv.prefix(),
|
||||||
Command: "CAP",
|
Command: "CAP",
|
||||||
Params: []string{replyTo, "LIST", strings.Join(caps, " ")},
|
Params: []string{dc.nick, "LIST", strings.Join(caps, " ")},
|
||||||
})
|
})
|
||||||
case "REQ":
|
case "REQ":
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
Command: err_invalidcapcmd,
|
Command: err_invalidcapcmd,
|
||||||
Params: []string{replyTo, cmd, "Missing argument in CAP REQ command"},
|
Params: []string{dc.nick, cmd, "Missing argument in CAP REQ command"},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -936,7 +934,7 @@ func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
|
|||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
Prefix: dc.srv.prefix(),
|
||||||
Command: "CAP",
|
Command: "CAP",
|
||||||
Params: []string{replyTo, reply, args[0]},
|
Params: []string{dc.nick, reply, args[0]},
|
||||||
})
|
})
|
||||||
|
|
||||||
if !dc.registered {
|
if !dc.registered {
|
||||||
@ -947,7 +945,7 @@ func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
|
|||||||
default:
|
default:
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
Command: err_invalidcapcmd,
|
Command: err_invalidcapcmd,
|
||||||
Params: []string{replyTo, cmd, "Unknown CAP command"},
|
Params: []string{dc.nick, cmd, "Unknown CAP command"},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -962,11 +960,6 @@ func (dc *downstreamConn) setSupportedCap(name, value string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
replyTo := dc.nick
|
|
||||||
if !dc.registered {
|
|
||||||
replyTo = "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
cap := name
|
cap := name
|
||||||
if value != "" && dc.capVersion >= 302 {
|
if value != "" && dc.capVersion >= 302 {
|
||||||
cap = name + "=" + value
|
cap = name + "=" + value
|
||||||
@ -975,7 +968,7 @@ func (dc *downstreamConn) setSupportedCap(name, value string) {
|
|||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
Prefix: dc.srv.prefix(),
|
||||||
Command: "CAP",
|
Command: "CAP",
|
||||||
Params: []string{replyTo, "NEW", cap},
|
Params: []string{dc.nick, "NEW", cap},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -988,15 +981,10 @@ func (dc *downstreamConn) unsetSupportedCap(name string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
replyTo := dc.nick
|
|
||||||
if !dc.registered {
|
|
||||||
replyTo = "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
Prefix: dc.srv.prefix(),
|
||||||
Command: "CAP",
|
Command: "CAP",
|
||||||
Params: []string{replyTo, "DEL", name},
|
Params: []string{dc.nick, "DEL", name},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user