mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-23 03:02:48 +01:00
commit
9a6e3025c2
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ const (
|
|||||||
Mode
|
Mode
|
||||||
Tagmsg
|
Tagmsg
|
||||||
Nick
|
Nick
|
||||||
|
Topic
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user