3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-12-22 18:52:41 +01:00

Merge pull request #958 from slingamn/issue950.2

four small fixes
This commit is contained in:
Shivaram Lingamneni 2020-04-23 12:43:13 -07:00 committed by GitHub
commit 9a6e3025c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 30 deletions

View File

@ -541,10 +541,16 @@ func (channel *Channel) ClientPrefixes(client *Client, isMultiPrefix bool) strin
func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool { func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool {
channel.stateMutex.RLock() channel.stateMutex.RLock()
founder := channel.registeredFounder
clientModes := channel.members[client] clientModes := channel.members[client]
targetModes := channel.members[target] targetModes := channel.members[target]
channel.stateMutex.RUnlock() channel.stateMutex.RUnlock()
if founder != "" && founder == client.Account() {
// #950: founder can kick or whatever without actually having the +q mode
return true
}
return channelUserModeHasPrivsOver(clientModes.HighestChannelUserMode(), targetModes.HighestChannelUserMode()) return channelUserModeHasPrivsOver(clientModes.HighestChannelUserMode(), targetModes.HighestChannelUserMode())
} }
@ -1064,6 +1070,25 @@ func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.I
message := fmt.Sprintf(client.t("%[1]s changed nick to %[2]s"), nick, item.Params[0]) message := fmt.Sprintf(client.t("%[1]s changed nick to %[2]s"), nick, item.Params[0])
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message) rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
} }
case history.Topic:
if eventPlayback {
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "TOPIC", chname, item.Message.Message)
} else {
message := fmt.Sprintf(client.t("%[1]s set the channel topic to: %[2]s"), nick, item.Message.Message)
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
}
case history.Mode:
params := make([]string, len(item.Message.Split)+1)
params[0] = chname
for i, pair := range item.Message.Split {
params[i+1] = pair.Message
}
if eventPlayback {
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "MODE", params...)
} else {
message := fmt.Sprintf(client.t("%[1]s set channel modes: %[2]s"), nick, strings.Join(params[1:], " "))
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
}
} }
} }
} }
@ -1113,22 +1138,30 @@ func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffe
} }
channel.stateMutex.Lock() channel.stateMutex.Lock()
chname := channel.name
channel.topic = topic channel.topic = topic
channel.topicSetBy = client.nickMaskString channel.topicSetBy = client.nickMaskString
channel.topicSetTime = time.Now().UTC() channel.topicSetTime = time.Now().UTC()
channel.stateMutex.Unlock() channel.stateMutex.Unlock()
prefix := client.NickMaskString() details := client.Details()
message := utils.MakeMessage(topic)
rb.AddFromClient(message.Time, message.Msgid, details.nickMask, details.accountName, nil, "TOPIC", chname, topic)
for _, member := range channel.Members() { for _, member := range channel.Members() {
for _, session := range member.Sessions() { for _, session := range member.Sessions() {
if session == rb.session { if session != rb.session {
rb.Add(nil, prefix, "TOPIC", channel.name, topic) session.sendFromClientInternal(false, message.Time, message.Msgid, details.nickMask, details.accountName, nil, "TOPIC", chname, topic)
} else {
session.Send(nil, prefix, "TOPIC", channel.name, topic)
} }
} }
} }
channel.AddHistoryItem(history.Item{
Type: history.Topic,
Nick: details.nickMask,
AccountName: details.accountName,
Message: message,
})
channel.MarkDirty(IncludeTopic) channel.MarkDirty(IncludeTopic)
} }

View File

@ -244,7 +244,7 @@ func csAmodeHandler(server *Server, client *Client, command string, params []str
if member.Account() == change.Arg { if member.Account() == change.Arg {
applied, change := channel.applyModeToMember(client, change, rb) applied, change := channel.applyModeToMember(client, change, rb)
if applied { if applied {
announceCmodeChanges(channel, modes.ModeChanges{change}, chanservMask, rb) announceCmodeChanges(channel, modes.ModeChanges{change}, chanservMask, "*", rb)
} }
} }
} }
@ -291,7 +291,7 @@ func csOpHandler(server *Server, client *Client, command string, params []string
}, },
rb) rb)
if applied { if applied {
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, rb) announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, "*", rb)
} }
csNotice(rb, fmt.Sprintf(client.t("Successfully op'd in channel %s"), channelName)) csNotice(rb, fmt.Sprintf(client.t("Successfully op'd in channel %s"), channelName))
@ -343,7 +343,7 @@ func csRegisterHandler(server *Server, client *Client, command string, params []
}, },
rb) rb)
if applied { if applied {
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, rb) announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, "*", rb)
} }
} }

View File

@ -205,9 +205,18 @@ func (clients *ClientManager) SetNick(client *Client, session *Session, newNick
// the client may just be changing case // the client may just be changing case
if currentClient != nil && currentClient != client && session != nil { if currentClient != nil && currentClient != client && session != nil {
// these conditions forbid reattaching to an existing session: // these conditions forbid reattaching to an existing session:
if registered || !bouncerAllowed || account == "" || account != currentClient.Account() || client.HasMode(modes.TLS) != currentClient.HasMode(modes.TLS) { if registered || !bouncerAllowed || account == "" || account != currentClient.Account() {
return "", errNicknameInUse return "", errNicknameInUse
} }
// check TLS modes
if client.HasMode(modes.TLS) != currentClient.HasMode(modes.TLS) {
if useAccountName {
// #955: this is fatal because they can't fix it by trying a different nick
return "", errInsecureReattach
} else {
return "", errNicknameInUse
}
}
reattachSuccessful, numSessions, lastSeen := currentClient.AddSession(session) reattachSuccessful, numSessions, lastSeen := currentClient.AddSession(session)
if !reattachSuccessful { if !reattachSuccessful {
return "", errNicknameInUse return "", errNicknameInUse

View File

@ -42,6 +42,7 @@ var (
errNickMissing = errors.New("nick missing") errNickMissing = errors.New("nick missing")
errNicknameInvalid = errors.New("invalid nickname") errNicknameInvalid = errors.New("invalid nickname")
errNicknameInUse = errors.New("nickname in use") errNicknameInUse = errors.New("nickname in use")
errInsecureReattach = errors.New("insecure reattach")
errNicknameReserved = errors.New("nickname is reserved") errNicknameReserved = errors.New("nickname is reserved")
errNickAccountMismatch = errors.New(`Your nickname must match your account name; try logging out and logging back in with SASL`) errNickAccountMismatch = errors.New(`Your nickname must match your account name; try logging out and logging back in with SASL`)
errNoExistingBan = errors.New("Ban does not exist") errNoExistingBan = errors.New("Ban does not exist")

View File

@ -1520,24 +1520,35 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
} }
// process mode changes, include list operations (an empty set of changes does a list) // process mode changes, include list operations (an empty set of changes does a list)
applied := channel.ApplyChannelModeChanges(client, msg.Command == "SAMODE", changes, rb) applied := channel.ApplyChannelModeChanges(client, msg.Command == "SAMODE", changes, rb)
announceCmodeChanges(channel, applied, client.NickMaskString(), rb) details := client.Details()
announceCmodeChanges(channel, applied, details.nickMask, details.accountName, rb)
return false return false
} }
func announceCmodeChanges(channel *Channel, applied modes.ModeChanges, source string, rb *ResponseBuffer) { func announceCmodeChanges(channel *Channel, applied modes.ModeChanges, source, accountName string, rb *ResponseBuffer) {
// send out changes // send out changes
if len(applied) > 0 { if len(applied) > 0 {
//TODO(dan): we should change the name of String and make it return a slice here message := utils.MakeMessage("")
args := append([]string{channel.name}, applied.Strings()...) changeStrings := applied.Strings()
rb.Add(nil, source, "MODE", args...) for _, changeString := range changeStrings {
message.Split = append(message.Split, utils.MessagePair{Message: changeString})
}
args := append([]string{channel.name}, changeStrings...)
rb.AddFromClient(message.Time, message.Msgid, source, accountName, nil, "MODE", args...)
for _, member := range channel.Members() { for _, member := range channel.Members() {
for _, session := range member.Sessions() { for _, session := range member.Sessions() {
if session != rb.session { if session != rb.session {
session.Send(nil, source, "MODE", args...) session.sendFromClientInternal(false, message.Time, message.Msgid, source, accountName, nil, "MODE", args...)
} }
} }
} }
channel.AddHistoryItem(history.Item{
Type: history.Mode,
Nick: source,
AccountName: accountName,
Message: message,
})
} }
} }
@ -2054,7 +2065,7 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
} }
// must pass at least one check, and all enabled checks // must pass at least one check, and all enabled checks
var checkPassed, checkFailed bool var checkPassed, checkFailed, passwordFailed bool
oper := server.GetOperator(msg.Params[0]) oper := server.GetOperator(msg.Params[0])
if oper != nil { if oper != nil {
if oper.Fingerprint != "" { if oper.Fingerprint != "" {
@ -2065,8 +2076,11 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
} }
} }
if !checkFailed && oper.Pass != nil { if !checkFailed && oper.Pass != nil {
if len(msg.Params) == 1 || bcrypt.CompareHashAndPassword(oper.Pass, []byte(msg.Params[1])) != nil { if len(msg.Params) == 1 {
checkFailed = true checkFailed = true
} else if bcrypt.CompareHashAndPassword(oper.Pass, []byte(msg.Params[1])) != nil {
checkFailed = true
passwordFailed = true
} else { } else {
checkPassed = true checkPassed = true
} }
@ -2075,11 +2089,18 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
if !checkPassed || checkFailed { if !checkPassed || checkFailed {
rb.Add(nil, server.name, ERR_PASSWDMISMATCH, client.Nick(), client.t("Password incorrect")) rb.Add(nil, server.name, ERR_PASSWDMISMATCH, client.Nick(), client.t("Password incorrect"))
client.Quit(client.t("Password incorrect"), rb.session) // #951: only disconnect them if we actually tried to check a password for them
return true if passwordFailed {
client.Quit(client.t("Password incorrect"), rb.session)
return true
} else {
return false
}
} }
applyOper(client, oper, rb) if oper != nil {
applyOper(client, oper, rb)
}
return false return false
} }

View File

@ -22,6 +22,7 @@ const (
Mode Mode
Tagmsg Tagmsg
Nick Nick
Topic
) )
const ( const (

View File

@ -25,12 +25,11 @@ var (
restrictedSkeletons = make(map[string]bool) restrictedSkeletons = make(map[string]bool)
) )
// returns whether the change succeeded or failed func performNickChange(server *Server, client *Client, target *Client, session *Session, nickname string, rb *ResponseBuffer) error {
func performNickChange(server *Server, client *Client, target *Client, session *Session, nickname string, rb *ResponseBuffer) bool {
currentNick := client.Nick() currentNick := client.Nick()
details := target.Details() details := target.Details()
if details.nick == nickname { if details.nick == nickname {
return true return nil
} }
hadNick := details.nick != "*" hadNick := details.nick != "*"
origNickMask := details.nickMask origNickMask := details.nickMask
@ -52,7 +51,7 @@ func performNickChange(server *Server, client *Client, target *Client, session *
rb.Add(nil, server.name, ERR_UNKNOWNERROR, currentNick, "NICK", fmt.Sprintf(client.t("Could not set or change nickname: %s"), err.Error())) rb.Add(nil, server.name, ERR_UNKNOWNERROR, currentNick, "NICK", fmt.Sprintf(client.t("Could not set or change nickname: %s"), err.Error()))
} }
if err != nil { if err != nil {
return false return err
} }
message := utils.MakeMessage("") message := utils.MakeMessage("")
@ -88,7 +87,7 @@ func performNickChange(server *Server, client *Client, target *Client, session *
client.server.monitorManager.AlertAbout(target, true) client.server.monitorManager.AlertAbout(target, true)
target.nickTimer.Touch(rb) target.nickTimer.Touch(rb)
} // else: these will be deferred to the end of registration (see #572) } // else: these will be deferred to the end of registration (see #572)
return true return nil
} }
func (server *Server) RandomlyRename(client *Client) { func (server *Server) RandomlyRename(client *Client) {
@ -124,7 +123,7 @@ func fixupNickEqualsAccount(client *Client, rb *ResponseBuffer, config *Config)
if !client.registered { if !client.registered {
return true return true
} }
if !performNickChange(client.server, client, client, rb.session, client.AccountName(), rb) { if performNickChange(client.server, client, client, rb.session, client.AccountName(), rb) != nil {
client.server.accounts.Logout(client) client.server.accounts.Logout(client)
nsNotice(rb, client.t("A client is already using that account; try logging out and logging back in with SASL")) nsNotice(rb, client.t("A client is already using that account; try logging out and logging back in with SASL"))
return false return false

View File

@ -343,11 +343,14 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
} }
rb := NewResponseBuffer(session) rb := NewResponseBuffer(session)
nickAssigned := performNickChange(server, c, c, session, c.preregNick, rb) nickError := performNickChange(server, c, c, session, c.preregNick, rb)
rb.Send(true) rb.Send(true)
if !nickAssigned { if nickError == errInsecureReattach {
c.Quit(c.t("You can't mix secure and insecure connections to this account"), nil)
return true
} else if nickError != nil {
c.preregNick = "" c.preregNick = ""
return return false
} }
if session.client != c { if session.client != c {
@ -355,7 +358,7 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
// we'll play the reg burst later, on the new goroutine associated with // we'll play the reg burst later, on the new goroutine associated with
// (thisSession, otherClient). This is to avoid having to transfer state // (thisSession, otherClient). This is to avoid having to transfer state
// like nickname, hostname, etc. to show the correct values in the reg burst. // like nickname, hostname, etc. to show the correct values in the reg burst.
return return false
} }
// check KLINEs // check KLINEs