mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-22 20:09:41 +01:00
Merge pull request #1315 from slingamn/issue1194_stealthoper
hidden operators, tweaks to default operator config
This commit is contained in:
commit
f5374c014b
@ -597,13 +597,20 @@ opers:
|
|||||||
class: "server-admin"
|
class: "server-admin"
|
||||||
|
|
||||||
# custom whois line
|
# custom whois line
|
||||||
whois-line: is a cool dude
|
whois-line: is a server admin
|
||||||
|
|
||||||
# custom hostname
|
# custom hostname
|
||||||
vhost: "n"
|
vhost: "staff"
|
||||||
|
|
||||||
# modes are the modes to auto-set upon opering-up
|
# normally, operator status is visible to unprivileged users in WHO and WHOIS
|
||||||
modes: +is acjknoqtuxv
|
# responses. this can be disabled with 'hidden'. ('hidden' also causes the
|
||||||
|
# 'vhost' line above to be ignored.)
|
||||||
|
hidden: false
|
||||||
|
|
||||||
|
# modes are modes to auto-set upon opering-up. uncomment this to automatically
|
||||||
|
# enable snomasks ("server notification masks" that alert you to server events;
|
||||||
|
# see `/quote help snomasks` while opered-up for more information):
|
||||||
|
#modes: +is acjknoqtuxv
|
||||||
|
|
||||||
# operators can be authenticated either by password (with the /OPER command),
|
# operators can be authenticated either by password (with the /OPER command),
|
||||||
# or by certificate fingerprint, or both. if a password hash is set, then a
|
# or by certificate fingerprint, or both. if a password hash is set, then a
|
||||||
|
15
default.yaml
15
default.yaml
@ -625,13 +625,20 @@ opers:
|
|||||||
class: "server-admin"
|
class: "server-admin"
|
||||||
|
|
||||||
# custom whois line
|
# custom whois line
|
||||||
whois-line: is a cool dude
|
whois-line: is a server admin
|
||||||
|
|
||||||
# custom hostname
|
# custom hostname
|
||||||
vhost: "n"
|
vhost: "staff"
|
||||||
|
|
||||||
# modes are the modes to auto-set upon opering-up
|
# normally, operator status is visible to unprivileged users in WHO and WHOIS
|
||||||
modes: +is acjknoqtuxv
|
# responses. this can be disabled with 'hidden'. ('hidden' also causes the
|
||||||
|
# 'vhost' line above to be ignored.)
|
||||||
|
hidden: false
|
||||||
|
|
||||||
|
# modes are modes to auto-set upon opering-up. uncomment this to automatically
|
||||||
|
# enable snomasks ("server notification masks" that alert you to server events;
|
||||||
|
# see `/quote help snomasks` while opered-up for more information):
|
||||||
|
#modes: +is acjknoqtuxv
|
||||||
|
|
||||||
# operators can be authenticated either by password (with the /OPER command),
|
# operators can be authenticated either by password (with the /OPER command),
|
||||||
# or by certificate fingerprint, or both. if a password hash is set, then a
|
# or by certificate fingerprint, or both. if a password hash is set, then a
|
||||||
|
@ -1207,7 +1207,7 @@ func (client *Client) getVHostNoMutex() string {
|
|||||||
// hostserv vhost OR operclass vhost OR nothing (i.e., normal rdns hostmask)
|
// hostserv vhost OR operclass vhost OR nothing (i.e., normal rdns hostmask)
|
||||||
if client.vhost != "" {
|
if client.vhost != "" {
|
||||||
return client.vhost
|
return client.vhost
|
||||||
} else if client.oper != nil {
|
} else if client.oper != nil && !client.oper.Hidden {
|
||||||
return client.oper.Vhost
|
return client.oper.Vhost
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
|
@ -419,6 +419,7 @@ type OperConfig struct {
|
|||||||
Fingerprint *string // legacy name for certfp, #1050
|
Fingerprint *string // legacy name for certfp, #1050
|
||||||
Certfp string
|
Certfp string
|
||||||
Auto bool
|
Auto bool
|
||||||
|
Hidden bool
|
||||||
Modes string
|
Modes string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,9 +724,15 @@ type Oper struct {
|
|||||||
Pass []byte
|
Pass []byte
|
||||||
Certfp string
|
Certfp string
|
||||||
Auto bool
|
Auto bool
|
||||||
|
Hidden bool
|
||||||
Modes []modes.ModeChange
|
Modes []modes.ModeChange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns whether this is a publicly visible operator, for WHO/WHOIS purposes
|
||||||
|
func (oper *Oper) Visible(hasPrivs bool) bool {
|
||||||
|
return oper != nil && (hasPrivs || !oper.Hidden)
|
||||||
|
}
|
||||||
|
|
||||||
// Operators returns a map of operator configs from the given OperClass and config.
|
// 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) {
|
func (conf *Config) Operators(oc map[string]*OperClass) (map[string]*Oper, error) {
|
||||||
operators := make(map[string]*Oper)
|
operators := make(map[string]*Oper)
|
||||||
@ -756,6 +763,7 @@ func (conf *Config) Operators(oc map[string]*OperClass) (map[string]*Oper, error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
oper.Auto = opConf.Auto
|
oper.Auto = opConf.Auto
|
||||||
|
oper.Hidden = opConf.Hidden
|
||||||
|
|
||||||
if oper.Pass == nil && oper.Certfp == "" {
|
if oper.Pass == nil && oper.Certfp == "" {
|
||||||
return nil, fmt.Errorf("Oper %s has neither a password nor a fingerprint", name)
|
return nil, fmt.Errorf("Oper %s has neither a password nor a fingerprint", name)
|
||||||
|
@ -3018,7 +3018,7 @@ func (fields whoxFields) Has(field rune) bool {
|
|||||||
// <channel> <user> <host> <server> <nick> <H|G>[*][~|&|@|%|+][B] :<hopcount> <real name>
|
// <channel> <user> <host> <server> <nick> <H|G>[*][~|&|@|%|+][B] :<hopcount> <real name>
|
||||||
// whox format:
|
// whox format:
|
||||||
// <type> <channel> <user> <ip> <host> <server> <nick> <H|G>[*][~|&|@|%|+][B] <hops> <idle> <account> <rank> :<real name>
|
// <type> <channel> <user> <ip> <host> <server> <nick> <H|G>[*][~|&|@|%|+][B] <hops> <idle> <account> <rank> :<real name>
|
||||||
func (client *Client) rplWhoReply(channel *Channel, target *Client, rb *ResponseBuffer, isWhox bool, fields whoxFields, whoType string) {
|
func (client *Client) rplWhoReply(channel *Channel, target *Client, rb *ResponseBuffer, hasPrivs, isWhox bool, fields whoxFields, whoType string) {
|
||||||
params := []string{client.Nick()}
|
params := []string{client.Nick()}
|
||||||
|
|
||||||
details := target.Details()
|
details := target.Details()
|
||||||
@ -3038,7 +3038,7 @@ func (client *Client) rplWhoReply(channel *Channel, target *Client, rb *Response
|
|||||||
}
|
}
|
||||||
if fields.Has('i') {
|
if fields.Has('i') {
|
||||||
fIP := "255.255.255.255"
|
fIP := "255.255.255.255"
|
||||||
if client.HasMode(modes.Operator) || client == target {
|
if hasPrivs || client == target {
|
||||||
// you can only see a target's IP if they're you or you're an oper
|
// you can only see a target's IP if they're you or you're an oper
|
||||||
fIP = target.IPString()
|
fIP = target.IPString()
|
||||||
}
|
}
|
||||||
@ -3061,7 +3061,7 @@ func (client *Client) rplWhoReply(channel *Channel, target *Client, rb *Response
|
|||||||
flags.WriteRune('H') // Here
|
flags.WriteRune('H') // Here
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.HasMode(modes.Operator) {
|
if target.HasMode(modes.Operator) && target.Oper().Visible(hasPrivs) {
|
||||||
flags.WriteRune('*')
|
flags.WriteRune('*')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3169,7 +3169,7 @@ func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
|||||||
}
|
}
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
if !member.HasMode(modes.Invisible) || isJoined || isOper {
|
if !member.HasMode(modes.Invisible) || isJoined || isOper {
|
||||||
client.rplWhoReply(channel, member, rb, isWhox, fields, whoType)
|
client.rplWhoReply(channel, member, rb, isOper, isWhox, fields, whoType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3200,7 +3200,7 @@ func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
|||||||
|
|
||||||
for mclient := range server.clients.FindAll(mask) {
|
for mclient := range server.clients.FindAll(mask) {
|
||||||
if isOper || !mclient.HasMode(modes.Invisible) || isFriend(mclient) {
|
if isOper || !mclient.HasMode(modes.Invisible) || isFriend(mclient) {
|
||||||
client.rplWhoReply(nil, mclient, rb, isWhox, fields, whoType)
|
client.rplWhoReply(nil, mclient, rb, isOper, isWhox, fields, whoType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3238,7 +3238,8 @@ func whoisHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.HasMode(modes.Operator) {
|
hasPrivs := client.HasMode(modes.Operator) // TODO(#1176) figure out the right capab for this
|
||||||
|
if hasPrivs {
|
||||||
for _, mask := range strings.Split(masksString, ",") {
|
for _, mask := range strings.Split(masksString, ",") {
|
||||||
matches := server.clients.FindAll(mask)
|
matches := server.clients.FindAll(mask)
|
||||||
if len(matches) == 0 && !handleService(mask) {
|
if len(matches) == 0 && !handleService(mask) {
|
||||||
@ -3246,7 +3247,7 @@ func whoisHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for mclient := range matches {
|
for mclient := range matches {
|
||||||
client.getWhoisOf(mclient, rb)
|
client.getWhoisOf(mclient, hasPrivs, rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -3254,7 +3255,7 @@ func whoisHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
|||||||
nick := strings.Split(masksString, ",")[0]
|
nick := strings.Split(masksString, ",")[0]
|
||||||
mclient := server.clients.Get(nick)
|
mclient := server.clients.Get(nick)
|
||||||
if mclient != nil {
|
if mclient != nil {
|
||||||
client.getWhoisOf(mclient, rb)
|
client.getWhoisOf(mclient, hasPrivs, rb)
|
||||||
} else if !handleService(nick) {
|
} else if !handleService(nick) {
|
||||||
rb.Add(nil, client.server.name, ERR_NOSUCHNICK, client.Nick(), utils.SafeErrorParam(masksString), client.t("No such nick"))
|
rb.Add(nil, client.server.name, ERR_NOSUCHNICK, client.Nick(), utils.SafeErrorParam(masksString), client.t("No such nick"))
|
||||||
}
|
}
|
||||||
|
@ -429,7 +429,7 @@ func (client *Client) WhoisChannelsNames(target *Client, multiPrefix bool) []str
|
|||||||
return chstrs
|
return chstrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
|
func (client *Client) getWhoisOf(target *Client, hasPrivs bool, rb *ResponseBuffer) {
|
||||||
cnick := client.Nick()
|
cnick := client.Nick()
|
||||||
targetInfo := target.Details()
|
targetInfo := target.Details()
|
||||||
rb.Add(nil, client.server.name, RPL_WHOISUSER, cnick, targetInfo.nick, targetInfo.username, targetInfo.hostname, "*", targetInfo.realname)
|
rb.Add(nil, client.server.name, RPL_WHOISUSER, cnick, targetInfo.nick, targetInfo.username, targetInfo.hostname, "*", targetInfo.realname)
|
||||||
@ -440,10 +440,10 @@ func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
|
|||||||
rb.Add(nil, client.server.name, RPL_WHOISCHANNELS, cnick, tnick, strings.Join(whoischannels, " "))
|
rb.Add(nil, client.server.name, RPL_WHOISCHANNELS, cnick, tnick, strings.Join(whoischannels, " "))
|
||||||
}
|
}
|
||||||
tOper := target.Oper()
|
tOper := target.Oper()
|
||||||
if tOper != nil {
|
if tOper.Visible(hasPrivs) {
|
||||||
rb.Add(nil, client.server.name, RPL_WHOISOPERATOR, cnick, tnick, tOper.WhoisLine)
|
rb.Add(nil, client.server.name, RPL_WHOISOPERATOR, cnick, tnick, tOper.WhoisLine)
|
||||||
}
|
}
|
||||||
if client == target || client.HasRoleCapabs("local_ban") {
|
if client == target || hasPrivs {
|
||||||
rb.Add(nil, client.server.name, RPL_WHOISACTUALLY, cnick, tnick, fmt.Sprintf("%s@%s", targetInfo.username, target.RawHostname()), target.IPString(), client.t("Actual user@host, Actual IP"))
|
rb.Add(nil, client.server.name, RPL_WHOISACTUALLY, cnick, tnick, fmt.Sprintf("%s@%s", targetInfo.username, target.RawHostname()), target.IPString(), client.t("Actual user@host, Actual IP"))
|
||||||
}
|
}
|
||||||
if target.HasMode(modes.TLS) {
|
if target.HasMode(modes.TLS) {
|
||||||
@ -456,7 +456,7 @@ func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
|
|||||||
rb.Add(nil, client.server.name, RPL_WHOISBOT, cnick, tnick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.Config().Network.Name)))
|
rb.Add(nil, client.server.name, RPL_WHOISBOT, cnick, tnick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.Config().Network.Name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if client == target || client.HasMode(modes.Operator) {
|
if client == target || hasPrivs {
|
||||||
for _, session := range target.Sessions() {
|
for _, session := range target.Sessions() {
|
||||||
if session.certfp != "" {
|
if session.certfp != "" {
|
||||||
rb.Add(nil, client.server.name, RPL_WHOISCERTFP, cnick, tnick, fmt.Sprintf(client.t("has client certificate fingerprint %s"), session.certfp))
|
rb.Add(nil, client.server.name, RPL_WHOISCERTFP, cnick, tnick, fmt.Sprintf(client.t("has client certificate fingerprint %s"), session.certfp))
|
||||||
|
2
irctest
2
irctest
@ -1 +1 @@
|
|||||||
Subproject commit 0c069b7418e623b6d64d55e46e3fc82b03a1219c
|
Subproject commit 1ac1c1c6a70e439016eb58edc667dc1e878c1940
|
Loading…
Reference in New Issue
Block a user