mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-22 11:59:40 +01:00
implement review feedback
1. If both fingerprint and hash are specified, require both instead of either 2. Implement auto-oper on connect
This commit is contained in:
parent
6033d9f569
commit
b717402b5e
@ -1354,3 +1354,18 @@ func (client *Client) CheckInvited(casefoldedChannel string) (invited bool) {
|
||||
delete(client.invitedTo, casefoldedChannel)
|
||||
return
|
||||
}
|
||||
|
||||
// Implements auto-oper by certfp (scans for an auto-eligible operator block that matches
|
||||
// the client's cert, then applies it).
|
||||
func (client *Client) attemptAutoOper(session *Session) {
|
||||
if client.certfp == "" || client.HasMode(modes.Operator) {
|
||||
return
|
||||
}
|
||||
for _, oper := range client.server.Config().operators {
|
||||
if oper.Auto && oper.Pass == nil && utils.CertfpsMatch(oper.Fingerprint, client.certfp) {
|
||||
rb := NewResponseBuffer(session)
|
||||
applyOper(client, oper, rb)
|
||||
rb.Send(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,6 +212,7 @@ type OperConfig struct {
|
||||
WhoisLine string `yaml:"whois-line"`
|
||||
Password string
|
||||
Fingerprint string
|
||||
Auto bool
|
||||
Modes string
|
||||
}
|
||||
|
||||
@ -461,6 +462,7 @@ type Oper struct {
|
||||
Vhost string
|
||||
Pass []byte
|
||||
Fingerprint string
|
||||
Auto bool
|
||||
Modes []modes.ModeChange
|
||||
}
|
||||
|
||||
@ -477,11 +479,18 @@ func (conf *Config) Operators(oc map[string]*OperClass) (map[string]*Oper, error
|
||||
}
|
||||
oper.Name = name
|
||||
|
||||
oper.Pass, err = decodeLegacyPasswordHash(opConf.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if opConf.Password != "" {
|
||||
oper.Pass, err = decodeLegacyPasswordHash(opConf.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
oper.Fingerprint = opConf.Fingerprint
|
||||
oper.Auto = opConf.Auto
|
||||
|
||||
if oper.Pass == nil && oper.Fingerprint == "" {
|
||||
return nil, fmt.Errorf("Oper %s has neither a password nor a fingerprint", name)
|
||||
}
|
||||
|
||||
oper.Vhost = opConf.Vhost
|
||||
class, exists := oc[opConf.Class]
|
||||
|
@ -2177,14 +2177,19 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
return false
|
||||
}
|
||||
|
||||
authorized := false
|
||||
// must have a matching oper block and not fail any enabled checks
|
||||
// (config validation ensures that there is at least one check)
|
||||
oper := server.GetOperator(msg.Params[0])
|
||||
authorized := oper != nil
|
||||
if oper != nil {
|
||||
if utils.CertfpsMatch(oper.Fingerprint, client.certfp) {
|
||||
authorized = true
|
||||
} else if 1 < len(msg.Params) {
|
||||
password := []byte(msg.Params[1])
|
||||
authorized = (bcrypt.CompareHashAndPassword(oper.Pass, password) == nil)
|
||||
if oper.Fingerprint != "" && !utils.CertfpsMatch(oper.Fingerprint, client.certfp) {
|
||||
authorized = false
|
||||
} else if oper.Pass != nil {
|
||||
if len(msg.Params) == 1 {
|
||||
authorized = false
|
||||
} else if bcrypt.CompareHashAndPassword(oper.Pass, []byte(msg.Params[1])) != nil {
|
||||
authorized = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !authorized {
|
||||
@ -2193,9 +2198,17 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
return true
|
||||
}
|
||||
|
||||
oldNickmask := client.NickMaskString()
|
||||
applyOper(client, oper, rb)
|
||||
return false
|
||||
}
|
||||
|
||||
// applies operator status to a client, who MUST NOT already be an operator
|
||||
func applyOper(client *Client, oper *Oper, rb *ResponseBuffer) {
|
||||
details := client.Details()
|
||||
oldNickmask := details.nickMask
|
||||
client.SetOper(oper)
|
||||
if client.NickMaskString() != oldNickmask {
|
||||
newNickmask := client.NickMaskString()
|
||||
if newNickmask != oldNickmask {
|
||||
client.sendChghost(oldNickmask, oper.Vhost)
|
||||
}
|
||||
|
||||
@ -2208,17 +2221,14 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
copy(modeChanges[1:], oper.Modes)
|
||||
applied := ApplyUserModeChanges(client, modeChanges, true)
|
||||
|
||||
rb.Add(nil, server.name, RPL_YOUREOPER, client.nick, client.t("You are now an IRC operator"))
|
||||
rb.Add(nil, server.name, "MODE", client.nick, applied.String())
|
||||
client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), client.nickMaskString, oper.Name))
|
||||
|
||||
server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), client.nickMaskString, oper.Name))
|
||||
|
||||
// client may now be unthrottled by the fakelag system
|
||||
rb.Broadcast(nil, client.server.name, RPL_YOUREOPER, details.nick, client.t("You are now an IRC operator"))
|
||||
rb.Broadcast(nil, client.server.name, "MODE", details.nick, applied.String())
|
||||
for _, session := range client.Sessions() {
|
||||
// client may now be unthrottled by the fakelag system
|
||||
session.resetFakelag()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// PART <channel>{,<channel>} [<reason>]
|
||||
|
@ -77,6 +77,18 @@ func (rb *ResponseBuffer) Add(tags map[string]string, prefix string, command str
|
||||
rb.AddMessage(ircmsg.MakeMessage(tags, prefix, command, params...))
|
||||
}
|
||||
|
||||
// Broadcast adds a standard new message to our queue, then sends an unlabeled copy
|
||||
// to all other sessions.
|
||||
func (rb *ResponseBuffer) Broadcast(tags map[string]string, prefix string, command string, params ...string) {
|
||||
// can't reuse the IrcMessage object because of tag pollution :-\
|
||||
rb.Add(tags, prefix, command, params...)
|
||||
for _, session := range rb.session.client.Sessions() {
|
||||
if session != rb.session {
|
||||
session.Send(tags, prefix, command, params...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddFromClient adds a new message from a specific client to our queue.
|
||||
func (rb *ResponseBuffer) AddFromClient(time time.Time, msgid string, fromNickMask string, fromAccount string, tags map[string]string, command string, params ...string) {
|
||||
msg := ircmsg.MakeMessage(nil, fromNickMask, command, params...)
|
||||
|
@ -440,6 +440,9 @@ func (server *Server) playRegistrationBurst(session *Session) {
|
||||
if modestring != "+" {
|
||||
session.Send(nil, d.nickMask, RPL_UMODEIS, d.nick, modestring)
|
||||
}
|
||||
|
||||
c.attemptAutoOper(session)
|
||||
|
||||
if server.logger.IsLoggingRawIO() {
|
||||
session.Send(nil, c.server.name, "NOTICE", d.nick, c.t("This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
|
||||
}
|
||||
|
16
oragono.yaml
16
oragono.yaml
@ -446,13 +446,19 @@ opers:
|
||||
# modes are the modes to auto-set upon opering-up
|
||||
modes: +is acjknoqtux
|
||||
|
||||
# password to login with /OPER command
|
||||
# generated using "oragono genpasswd"
|
||||
# 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
|
||||
# password is required to oper up (e.g., /OPER dan mypassword). to generate
|
||||
# the hash, use `oragono genpasswd`.
|
||||
password: "$2a$04$LiytCxaY0lI.guDj2pBN4eLRD5cdM2OLDwqmGAgB6M2OPirbF5Jcu"
|
||||
|
||||
# if you're logged in using the client cert with this SHA-256 fingerprint,
|
||||
# you'll be able to /OPER without a password
|
||||
fingerprint: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"
|
||||
# if a SHA-256 certificate fingerprint is configured here, then it will be
|
||||
# required to /OPER. if you comment out the password hash above, then you can
|
||||
# /OPER without a password.
|
||||
#fingerprint: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"
|
||||
# if 'auto' is set (and no password hash is set), operator permissions will be
|
||||
# granted automatically as soon as you connect with the right fingerprint.
|
||||
#auto: true
|
||||
|
||||
# logging, takes inspiration from Insp
|
||||
logging:
|
||||
|
Loading…
Reference in New Issue
Block a user