diff --git a/irc/chanserv.go b/irc/chanserv.go index bcd8b3f9..e3ab0d31 100644 --- a/irc/chanserv.go +++ b/irc/chanserv.go @@ -502,10 +502,13 @@ func csTransferHandler(service *ircService, server *Server, client *Client, comm chname = regInfo.Name account := client.Account() isFounder := account != "" && account == regInfo.Founder - hasPrivs := client.HasRoleCapabs("chanreg") - if !(isFounder || hasPrivs) { - service.Notice(rb, client.t("Insufficient privileges")) - return + var oper *Oper + if !isFounder { + oper = client.Oper() + if !oper.HasRoleCapab("chanreg") { + service.Notice(rb, client.t("Insufficient privileges")) + return + } } target := params[1] targetAccount, err := server.accounts.LoadAccount(params[1]) @@ -522,7 +525,12 @@ func csTransferHandler(service *ircService, server *Server, client *Client, comm return } } - status, err := channel.Transfer(client, target, hasPrivs) + if !isFounder { + message := fmt.Sprintf("Operator %s ran CS TRANSFER on %s to account %s", oper.Name, chname, target) + server.snomasks.Send(sno.LocalOpers, message) + server.logger.Info("opers", message) + } + status, err := channel.Transfer(client, target, oper != nil) if err == nil { switch status { case channelTransferComplete: diff --git a/irc/config.go b/irc/config.go index e2423981..159977e5 100644 --- a/irc/config.go +++ b/irc/config.go @@ -733,6 +733,10 @@ type Oper struct { Modes []modes.ModeChange } +func (oper *Oper) HasRoleCapab(capab string) bool { + return oper != nil && oper.Class.Capabilities.Has(capab) +} + // Operators returns a map of operator configs from the given OperClass and config. func (conf *Config) Operators(oc map[string]*OperClass) (map[string]*Oper, error) { operators := make(map[string]*Oper) diff --git a/irc/handlers.go b/irc/handlers.go index 015a68f8..794ee580 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -826,7 +826,7 @@ func formatBanForListing(client *Client, key string, info IPBanInfo) string { func dlineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { // check oper permissions oper := client.Oper() - if oper == nil || !oper.Class.Capabilities.Has("ban") { + if !oper.HasRoleCapab("ban") { rb.Add(nil, server.name, ERR_NOPRIVS, client.nick, msg.Command, client.t("Insufficient oper privs")) return false } @@ -1273,6 +1273,10 @@ func sajoinHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re } } + message := fmt.Sprintf("Operator %s ran SAJOIN %s", client.Oper().Name, strings.Join(msg.Params, " ")) + server.snomasks.Send(sno.LocalOpers, message) + server.logger.Info("opers", message) + channels := strings.Split(channelString, ",") for _, chname := range channels { err, _ := server.channels.Join(target, chname, "", true, rb) @@ -1364,7 +1368,7 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res details := client.Details() // check oper permissions oper := client.Oper() - if oper == nil || !oper.Class.Capabilities.Has("ban") { + if !oper.HasRoleCapab("ban") { rb.Add(nil, server.name, ERR_NOPRIVS, details.nick, msg.Command, client.t("Insufficient oper privs")) return false } @@ -1737,6 +1741,12 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res return false } + if msg.Command == "SAMODE" { + message := fmt.Sprintf("Operator %s ran SAMODE %s", client.Oper().Name, strings.Join(msg.Params, " ")) + server.snomasks.Send(sno.LocalOpers, message) + server.logger.Info("opers", message) + } + // applied mode changes applied := make(modes.ModeChanges, 0) @@ -2307,6 +2317,7 @@ func applyOper(client *Client, oper *Oper, rb *ResponseBuffer) { copy(modeChanges[1:], oper.Modes) applied := ApplyUserModeChanges(client, modeChanges, true, oper) + client.server.logger.Info("opers", details.nick, "opered up as", oper.Name) client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), newDetails.nickMask, oper.Name)) rb.Broadcast(nil, client.server.name, RPL_YOUREOPER, details.nick, client.t("You are now an IRC operator")) @@ -2814,7 +2825,7 @@ func topicHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res func unDLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { // check oper permissions oper := client.Oper() - if oper == nil || !oper.Class.Capabilities.Has("ban") { + if !oper.HasRoleCapab("ban") { rb.Add(nil, server.name, ERR_NOPRIVS, client.nick, msg.Command, client.t("Insufficient oper privs")) return false } @@ -2853,7 +2864,7 @@ func unKLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R details := client.Details() // check oper permissions oper := client.Oper() - if oper == nil || !oper.Class.Capabilities.Has("ban") { + if !oper.HasRoleCapab("ban") { rb.Add(nil, server.name, ERR_NOPRIVS, details.nick, msg.Command, client.t("Insufficient oper privs")) return false } diff --git a/irc/nickserv.go b/irc/nickserv.go index c311a8ba..0a39f32c 100644 --- a/irc/nickserv.go +++ b/irc/nickserv.go @@ -995,17 +995,21 @@ func nsPasswdHandler(service *ircService, server *Server, client *Client, comman var newPassword string var errorMessage string - hasPrivs := client.HasRoleCapabs("accreg") + var oper *Oper switch len(params) { case 2: - if !hasPrivs { + oper = client.Oper() + if !oper.HasRoleCapab("accreg") { errorMessage = `Insufficient privileges` } else { target, newPassword = params[0], params[1] if newPassword == "*" { newPassword = "" } + message := fmt.Sprintf("Operator %s ran NS PASSWD for account %s", oper.Name, target) + server.snomasks.Send(sno.LocalOpers, message) + server.logger.Info("opers", message) } case 3: target = client.Account() @@ -1041,7 +1045,7 @@ func nsPasswdHandler(service *ircService, server *Server, client *Client, comman return } - err := server.accounts.setPassword(target, newPassword, hasPrivs) + err := server.accounts.setPassword(target, newPassword, oper != nil) switch err { case nil: service.Notice(rb, client.t("Password changed")) @@ -1144,7 +1148,7 @@ func nsClientsLogoutHandler(service *ircService, server *Server, client *Client, // User must have "kill" privileges to logout other user sessions. if target != client { oper := client.Oper() - if oper == nil || !oper.Class.Capabilities.Has("kill") { + if oper.HasRoleCapab("kill") { service.Notice(rb, client.t("Insufficient oper privs")) return }