mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
changes to nick reservation
* Clients are now renamed, not disconnected, on reservation timeout * Nick reservation config is now its own subsection
This commit is contained in:
parent
73391f11a6
commit
988cb22692
@ -51,7 +51,7 @@ func NewAccountManager(server *Server) *AccountManager {
|
||||
}
|
||||
|
||||
func (am *AccountManager) buildNickToAccountIndex() {
|
||||
if am.server.AccountConfig().NickReservation == NickReservationDisabled {
|
||||
if am.server.AccountConfig().NickReservation.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
@ -98,6 +98,12 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
|
||||
return errAccountCreation
|
||||
}
|
||||
|
||||
// can't register a guest nickname
|
||||
renamePrefix := strings.ToLower(am.server.AccountConfig().NickReservation.RenamePrefix)
|
||||
if renamePrefix != "" && strings.HasPrefix(casefoldedAccount, renamePrefix) {
|
||||
return errAccountAlreadyRegistered
|
||||
}
|
||||
|
||||
accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
|
||||
accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
|
||||
registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
|
||||
|
@ -99,9 +99,10 @@ func (clients *ClientManager) SetNick(client *Client, newNick string) error {
|
||||
}
|
||||
|
||||
var reservedAccount string
|
||||
reservation := client.server.AccountConfig().NickReservation
|
||||
if reservation != NickReservationDisabled {
|
||||
var method NickReservationMethod
|
||||
if client.server.AccountConfig().NickReservation.Enabled {
|
||||
reservedAccount = client.server.accounts.NickToAccount(newcfnick)
|
||||
method = client.server.AccountConfig().NickReservation.Method
|
||||
}
|
||||
|
||||
clients.Lock()
|
||||
@ -113,7 +114,7 @@ func (clients *ClientManager) SetNick(client *Client, newNick string) error {
|
||||
if currentNewEntry != nil && currentNewEntry != client {
|
||||
return errNicknameInUse
|
||||
}
|
||||
if reservation == NickReservationStrict && reservedAccount != client.Account() {
|
||||
if method == NickReservationStrict && reservedAccount != client.Account() {
|
||||
return errNicknameReserved
|
||||
}
|
||||
clients.byNick[newcfnick] = client
|
||||
|
@ -58,40 +58,10 @@ func (conf *PassConfig) PasswordBytes() []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
type NickReservation int
|
||||
|
||||
const (
|
||||
NickReservationDisabled NickReservation = iota
|
||||
NickReservationWithTimeout
|
||||
NickReservationStrict
|
||||
)
|
||||
|
||||
func (nr *NickReservation) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var orig, raw string
|
||||
var err error
|
||||
if err = unmarshal(&orig); err != nil {
|
||||
return err
|
||||
}
|
||||
if raw, err = Casefold(orig); err != nil {
|
||||
return err
|
||||
}
|
||||
if raw == "disabled" || raw == "false" || raw == "" {
|
||||
*nr = NickReservationDisabled
|
||||
} else if raw == "timeout" {
|
||||
*nr = NickReservationWithTimeout
|
||||
} else if raw == "strict" {
|
||||
*nr = NickReservationStrict
|
||||
} else {
|
||||
return errors.New(fmt.Sprintf("invalid nick-reservation value: %s", orig))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AccountConfig struct {
|
||||
Registration AccountRegistrationConfig
|
||||
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
||||
NickReservation NickReservation `yaml:"nick-reservation"`
|
||||
NickReservationTimeout time.Duration `yaml:"nick-reservation-timeout"`
|
||||
Registration AccountRegistrationConfig
|
||||
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
||||
NickReservation NickReservationConfig `yaml:"nick-reservation"`
|
||||
}
|
||||
|
||||
// AccountRegistrationConfig controls account registration.
|
||||
@ -119,6 +89,39 @@ type AccountRegistrationConfig struct {
|
||||
AllowMultiplePerConnection bool `yaml:"allow-multiple-per-connection"`
|
||||
}
|
||||
|
||||
type NickReservationMethod int
|
||||
|
||||
const (
|
||||
NickReservationWithTimeout NickReservationMethod = iota
|
||||
NickReservationStrict
|
||||
)
|
||||
|
||||
func (nr *NickReservationMethod) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var orig, raw string
|
||||
var err error
|
||||
if err = unmarshal(&orig); err != nil {
|
||||
return err
|
||||
}
|
||||
if raw, err = Casefold(orig); err != nil {
|
||||
return err
|
||||
}
|
||||
if raw == "timeout" {
|
||||
*nr = NickReservationWithTimeout
|
||||
} else if raw == "strict" {
|
||||
*nr = NickReservationStrict
|
||||
} else {
|
||||
return errors.New(fmt.Sprintf("invalid nick-reservation.method value: %s", orig))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NickReservationConfig struct {
|
||||
Enabled bool
|
||||
Method NickReservationMethod
|
||||
RenameTimeout time.Duration `yaml:"rename-timeout"`
|
||||
RenamePrefix string `yaml:"rename-prefix"`
|
||||
}
|
||||
|
||||
// ChannelRegistrationConfig controls channel registration.
|
||||
type ChannelRegistrationConfig struct {
|
||||
Enabled bool
|
||||
|
@ -183,13 +183,13 @@ type NickTimer struct {
|
||||
|
||||
// NewNickTimer sets up a new nick timer (returning nil if timeout enforcement is not enabled)
|
||||
func NewNickTimer(client *Client) *NickTimer {
|
||||
config := client.server.AccountConfig()
|
||||
if config.NickReservation != NickReservationWithTimeout {
|
||||
config := client.server.AccountConfig().NickReservation
|
||||
if !(config.Enabled && config.Method == NickReservationWithTimeout) {
|
||||
return nil
|
||||
}
|
||||
nt := NickTimer{
|
||||
client: client,
|
||||
timeout: config.NickReservationTimeout,
|
||||
timeout: config.RenameTimeout,
|
||||
}
|
||||
return &nt
|
||||
}
|
||||
@ -239,6 +239,6 @@ func (nt *NickTimer) sendWarning() {
|
||||
|
||||
func (nt *NickTimer) processTimeout() {
|
||||
baseMsg := "Nick is reserved and authentication timeout expired: %v"
|
||||
nt.client.Quit(fmt.Sprintf(nt.client.t(baseMsg), nt.timeout))
|
||||
nt.client.destroy(false)
|
||||
nt.client.Notice(fmt.Sprintf(nt.client.t(baseMsg), nt.timeout))
|
||||
nt.client.server.RandomlyRename(nt.client)
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
package irc
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@ -72,3 +74,18 @@ func performNickChange(server *Server, client *Client, target *Client, newnick s
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (server *Server) RandomlyRename(client *Client) {
|
||||
prefix := server.AccountConfig().NickReservation.RenamePrefix
|
||||
if prefix == "" {
|
||||
prefix = "Guest-"
|
||||
}
|
||||
buf := make([]byte, 8)
|
||||
rand.Read(buf)
|
||||
nick := fmt.Sprintf("%s%s", prefix, hex.EncodeToString(buf))
|
||||
rb := NewResponseBuffer(client)
|
||||
performNickChange(server, client, client, nick, rb)
|
||||
rb.Send()
|
||||
// technically performNickChange can fail to change the nick,
|
||||
// but if they're still delinquent, the timer will get them later
|
||||
}
|
||||
|
@ -810,8 +810,8 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
|
||||
server.accountConfig = &config.Accounts
|
||||
server.configurableStateMutex.Unlock()
|
||||
|
||||
nickReservationPreviouslyDisabled := oldAccountConfig != nil && oldAccountConfig.NickReservation == NickReservationDisabled
|
||||
nickReservationNowEnabled := config.Accounts.NickReservation != NickReservationDisabled
|
||||
nickReservationPreviouslyDisabled := oldAccountConfig != nil && !oldAccountConfig.NickReservation.Enabled
|
||||
nickReservationNowEnabled := config.Accounts.NickReservation.Enabled
|
||||
if nickReservationPreviouslyDisabled && nickReservationNowEnabled {
|
||||
server.accounts.buildNickToAccountIndex()
|
||||
}
|
||||
@ -1113,13 +1113,6 @@ func (server *Server) setupListeners(config *Config) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetDefaultChannelModes returns our default channel modes.
|
||||
func (server *Server) GetDefaultChannelModes() modes.Modes {
|
||||
server.configurableStateMutex.RLock()
|
||||
defer server.configurableStateMutex.RUnlock()
|
||||
return server.defaultChannelModes
|
||||
}
|
||||
|
||||
// elistMatcher takes and matches ELIST conditions
|
||||
type elistMatcher struct {
|
||||
MinClientsActive bool
|
||||
|
24
oragono.yaml
24
oragono.yaml
@ -159,13 +159,23 @@ accounts:
|
||||
# is account authentication enabled?
|
||||
authentication-enabled: true
|
||||
|
||||
# will the server enforce that only the account holder can use the account name as a nick?
|
||||
# options:
|
||||
# `disabled`: no enforcement
|
||||
# `timeout` (auth to nickserv within some period of time or you're disconnected)
|
||||
# `strict`: must authenticate up front with SASL
|
||||
nick-reservation: disabled
|
||||
nick-reservation-timeout: 30s
|
||||
# nick-reservation controls how, and whether, nicknames are linked to accounts
|
||||
nick-reservation:
|
||||
# is there any enforcement of reserved nicknames?
|
||||
enabled: false
|
||||
|
||||
# method describes how nickname reservation is handled
|
||||
# timeout: let the user change to the registered nickname, give them X seconds
|
||||
# to login and then rename them if they haven't done so
|
||||
# strict: don't let the user change to the registered nickname unless they're
|
||||
# already logged-in using SASL or NickServ
|
||||
method: timeout
|
||||
|
||||
# rename-timeout - this is how long users have 'til they're renamed
|
||||
rename-timeout: 30s
|
||||
|
||||
# rename-prefix - this is the prefix to use when renaming clients (e.g. Guest-AB54U31)
|
||||
rename-prefix: Guest-
|
||||
|
||||
# channel options
|
||||
channels:
|
||||
|
Loading…
Reference in New Issue
Block a user