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() {
|
func (am *AccountManager) buildNickToAccountIndex() {
|
||||||
if am.server.AccountConfig().NickReservation == NickReservationDisabled {
|
if am.server.AccountConfig().NickReservation.Enabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +98,12 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
|
|||||||
return errAccountCreation
|
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)
|
accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
|
||||||
accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
|
accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
|
||||||
registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
|
registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
|
||||||
|
@ -99,9 +99,10 @@ func (clients *ClientManager) SetNick(client *Client, newNick string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var reservedAccount string
|
var reservedAccount string
|
||||||
reservation := client.server.AccountConfig().NickReservation
|
var method NickReservationMethod
|
||||||
if reservation != NickReservationDisabled {
|
if client.server.AccountConfig().NickReservation.Enabled {
|
||||||
reservedAccount = client.server.accounts.NickToAccount(newcfnick)
|
reservedAccount = client.server.accounts.NickToAccount(newcfnick)
|
||||||
|
method = client.server.AccountConfig().NickReservation.Method
|
||||||
}
|
}
|
||||||
|
|
||||||
clients.Lock()
|
clients.Lock()
|
||||||
@ -113,7 +114,7 @@ func (clients *ClientManager) SetNick(client *Client, newNick string) error {
|
|||||||
if currentNewEntry != nil && currentNewEntry != client {
|
if currentNewEntry != nil && currentNewEntry != client {
|
||||||
return errNicknameInUse
|
return errNicknameInUse
|
||||||
}
|
}
|
||||||
if reservation == NickReservationStrict && reservedAccount != client.Account() {
|
if method == NickReservationStrict && reservedAccount != client.Account() {
|
||||||
return errNicknameReserved
|
return errNicknameReserved
|
||||||
}
|
}
|
||||||
clients.byNick[newcfnick] = client
|
clients.byNick[newcfnick] = client
|
||||||
|
@ -58,40 +58,10 @@ func (conf *PassConfig) PasswordBytes() []byte {
|
|||||||
return bytes
|
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 {
|
type AccountConfig struct {
|
||||||
Registration AccountRegistrationConfig
|
Registration AccountRegistrationConfig
|
||||||
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
||||||
NickReservation NickReservation `yaml:"nick-reservation"`
|
NickReservation NickReservationConfig `yaml:"nick-reservation"`
|
||||||
NickReservationTimeout time.Duration `yaml:"nick-reservation-timeout"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountRegistrationConfig controls account registration.
|
// AccountRegistrationConfig controls account registration.
|
||||||
@ -119,6 +89,39 @@ type AccountRegistrationConfig struct {
|
|||||||
AllowMultiplePerConnection bool `yaml:"allow-multiple-per-connection"`
|
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.
|
// ChannelRegistrationConfig controls channel registration.
|
||||||
type ChannelRegistrationConfig struct {
|
type ChannelRegistrationConfig struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
|
@ -183,13 +183,13 @@ type NickTimer struct {
|
|||||||
|
|
||||||
// NewNickTimer sets up a new nick timer (returning nil if timeout enforcement is not enabled)
|
// NewNickTimer sets up a new nick timer (returning nil if timeout enforcement is not enabled)
|
||||||
func NewNickTimer(client *Client) *NickTimer {
|
func NewNickTimer(client *Client) *NickTimer {
|
||||||
config := client.server.AccountConfig()
|
config := client.server.AccountConfig().NickReservation
|
||||||
if config.NickReservation != NickReservationWithTimeout {
|
if !(config.Enabled && config.Method == NickReservationWithTimeout) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
nt := NickTimer{
|
nt := NickTimer{
|
||||||
client: client,
|
client: client,
|
||||||
timeout: config.NickReservationTimeout,
|
timeout: config.RenameTimeout,
|
||||||
}
|
}
|
||||||
return &nt
|
return &nt
|
||||||
}
|
}
|
||||||
@ -239,6 +239,6 @@ func (nt *NickTimer) sendWarning() {
|
|||||||
|
|
||||||
func (nt *NickTimer) processTimeout() {
|
func (nt *NickTimer) processTimeout() {
|
||||||
baseMsg := "Nick is reserved and authentication timeout expired: %v"
|
baseMsg := "Nick is reserved and authentication timeout expired: %v"
|
||||||
nt.client.Quit(fmt.Sprintf(nt.client.t(baseMsg), nt.timeout))
|
nt.client.Notice(fmt.Sprintf(nt.client.t(baseMsg), nt.timeout))
|
||||||
nt.client.destroy(false)
|
nt.client.server.RandomlyRename(nt.client)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
package irc
|
package irc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -72,3 +74,18 @@ func performNickChange(server *Server, client *Client, target *Client, newnick s
|
|||||||
}
|
}
|
||||||
return false
|
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.accountConfig = &config.Accounts
|
||||||
server.configurableStateMutex.Unlock()
|
server.configurableStateMutex.Unlock()
|
||||||
|
|
||||||
nickReservationPreviouslyDisabled := oldAccountConfig != nil && oldAccountConfig.NickReservation == NickReservationDisabled
|
nickReservationPreviouslyDisabled := oldAccountConfig != nil && !oldAccountConfig.NickReservation.Enabled
|
||||||
nickReservationNowEnabled := config.Accounts.NickReservation != NickReservationDisabled
|
nickReservationNowEnabled := config.Accounts.NickReservation.Enabled
|
||||||
if nickReservationPreviouslyDisabled && nickReservationNowEnabled {
|
if nickReservationPreviouslyDisabled && nickReservationNowEnabled {
|
||||||
server.accounts.buildNickToAccountIndex()
|
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
|
// elistMatcher takes and matches ELIST conditions
|
||||||
type elistMatcher struct {
|
type elistMatcher struct {
|
||||||
MinClientsActive bool
|
MinClientsActive bool
|
||||||
|
24
oragono.yaml
24
oragono.yaml
@ -159,13 +159,23 @@ accounts:
|
|||||||
# is account authentication enabled?
|
# is account authentication enabled?
|
||||||
authentication-enabled: true
|
authentication-enabled: true
|
||||||
|
|
||||||
# will the server enforce that only the account holder can use the account name as a nick?
|
# nick-reservation controls how, and whether, nicknames are linked to accounts
|
||||||
# options:
|
nick-reservation:
|
||||||
# `disabled`: no enforcement
|
# is there any enforcement of reserved nicknames?
|
||||||
# `timeout` (auth to nickserv within some period of time or you're disconnected)
|
enabled: false
|
||||||
# `strict`: must authenticate up front with SASL
|
|
||||||
nick-reservation: disabled
|
# method describes how nickname reservation is handled
|
||||||
nick-reservation-timeout: 30s
|
# 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
|
# channel options
|
||||||
channels:
|
channels:
|
||||||
|
Loading…
Reference in New Issue
Block a user