mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
commit
6028953ed4
@ -330,6 +330,10 @@ accounts:
|
|||||||
# PASS as well, so it can be configured to authenticate with SASL only.
|
# PASS as well, so it can be configured to authenticate with SASL only.
|
||||||
skip-server-password: false
|
skip-server-password: false
|
||||||
|
|
||||||
|
# enable login to accounts via the PASS command, e.g., PASS account:password
|
||||||
|
# this is sometimes useful for compatibility with old clients that don't support SASL
|
||||||
|
login-via-pass-command: false
|
||||||
|
|
||||||
# require-sasl controls whether clients are required to have accounts
|
# require-sasl controls whether clients are required to have accounts
|
||||||
# (and sign into them using SASL) to connect to the server
|
# (and sign into them using SASL) to connect to the server
|
||||||
require-sasl:
|
require-sasl:
|
||||||
|
@ -97,6 +97,15 @@ func (s *saslStatus) Clear() {
|
|||||||
*s = saslStatus{}
|
*s = saslStatus{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// what stage the client is at w.r.t. the PASS command:
|
||||||
|
type serverPassStatus uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
serverPassUnsent serverPassStatus = iota
|
||||||
|
serverPassSuccessful
|
||||||
|
serverPassFailed
|
||||||
|
)
|
||||||
|
|
||||||
// Session is an individual client connection to the server (TCP connection
|
// Session is an individual client connection to the server (TCP connection
|
||||||
// and associated per-connection data, such as capabilities). There is a
|
// and associated per-connection data, such as capabilities). There is a
|
||||||
// many-one relationship between sessions and clients.
|
// many-one relationship between sessions and clients.
|
||||||
@ -117,9 +126,9 @@ type Session struct {
|
|||||||
deferredFakelagCount int
|
deferredFakelagCount int
|
||||||
destroyed uint32
|
destroyed uint32
|
||||||
|
|
||||||
certfp string
|
certfp string
|
||||||
sasl saslStatus
|
sasl saslStatus
|
||||||
sentPassCommand bool
|
passStatus serverPassStatus
|
||||||
|
|
||||||
batchCounter uint32
|
batchCounter uint32
|
||||||
|
|
||||||
@ -510,7 +519,7 @@ const (
|
|||||||
func (client *Client) isAuthorized(config *Config, session *Session) AuthOutcome {
|
func (client *Client) isAuthorized(config *Config, session *Session) AuthOutcome {
|
||||||
saslSent := client.account != ""
|
saslSent := client.account != ""
|
||||||
// PASS requirement
|
// PASS requirement
|
||||||
if (config.Server.passwordBytes != nil) && !session.sentPassCommand && !(config.Accounts.SkipServerPassword && saslSent) {
|
if (config.Server.passwordBytes != nil) && session.passStatus != serverPassSuccessful && !(config.Accounts.SkipServerPassword && saslSent) {
|
||||||
return authFailPass
|
return authFailPass
|
||||||
}
|
}
|
||||||
// Tor connections may be required to authenticate with SASL
|
// Tor connections may be required to authenticate with SASL
|
||||||
|
@ -254,12 +254,13 @@ type AccountConfig struct {
|
|||||||
Exempted []string
|
Exempted []string
|
||||||
exemptedNets []net.IPNet
|
exemptedNets []net.IPNet
|
||||||
} `yaml:"require-sasl"`
|
} `yaml:"require-sasl"`
|
||||||
DefaultUserModes *string `yaml:"default-user-modes"`
|
DefaultUserModes *string `yaml:"default-user-modes"`
|
||||||
defaultUserModes modes.ModeChanges
|
defaultUserModes modes.ModeChanges
|
||||||
LDAP ldap.ServerConfig
|
LDAP ldap.ServerConfig
|
||||||
LoginThrottling ThrottleConfig `yaml:"login-throttling"`
|
LoginThrottling ThrottleConfig `yaml:"login-throttling"`
|
||||||
SkipServerPassword bool `yaml:"skip-server-password"`
|
SkipServerPassword bool `yaml:"skip-server-password"`
|
||||||
NickReservation struct {
|
LoginViaPassCommand bool `yaml:"login-via-pass-command"`
|
||||||
|
NickReservation struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
AdditionalNickLimit int `yaml:"additional-nick-limit"`
|
AdditionalNickLimit int `yaml:"additional-nick-limit"`
|
||||||
Method NickEnforcementMethod
|
Method NickEnforcementMethod
|
||||||
@ -1078,6 +1079,9 @@ func LoadConfig(filename string) (config *Config, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if config.Accounts.LoginViaPassCommand && !config.Accounts.SkipServerPassword {
|
||||||
|
return nil, errors.New("Using a server password and login-via-pass-command requires skip-server-password as well")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Accounts.Registration.BcryptCost == 0 {
|
if config.Accounts.Registration.BcryptCost == 0 {
|
||||||
|
@ -2159,18 +2159,53 @@ func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
rb.Add(nil, server.name, ERR_ALREADYREGISTRED, client.nick, client.t("You may not reregister"))
|
rb.Add(nil, server.name, ERR_ALREADYREGISTRED, client.nick, client.t("You may not reregister"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// only give them one try to run the PASS command (all code paths end with this
|
||||||
|
// variable being set):
|
||||||
|
if rb.session.passStatus != serverPassUnsent {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
password := msg.Params[0]
|
||||||
|
config := server.Config()
|
||||||
|
|
||||||
|
if config.Accounts.LoginViaPassCommand {
|
||||||
|
colonIndex := strings.IndexByte(password, ':')
|
||||||
|
if colonIndex != -1 && client.Account() == "" {
|
||||||
|
// TODO consolidate all login throttle checks into AccountManager
|
||||||
|
throttled, _ := client.loginThrottle.Touch()
|
||||||
|
if !throttled {
|
||||||
|
account, accountPass := password[:colonIndex], password[colonIndex+1:]
|
||||||
|
err := server.accounts.AuthenticateByPassphrase(client, account, accountPass)
|
||||||
|
if err == nil {
|
||||||
|
sendSuccessfulAccountAuth(client, rb, false, true)
|
||||||
|
// login-via-pass-command entails that we do not need to check
|
||||||
|
// an actual server password (either no password or skip-server-password)
|
||||||
|
rb.session.passStatus = serverPassSuccessful
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if login-via-PASS failed for any reason, proceed to try and interpret the
|
||||||
|
// provided password as the server password
|
||||||
|
|
||||||
|
serverPassword := config.Server.passwordBytes
|
||||||
|
|
||||||
// if no password exists, skip checking
|
// if no password exists, skip checking
|
||||||
serverPassword := server.Config().Server.passwordBytes
|
|
||||||
if serverPassword == nil {
|
if serverPassword == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the provided password
|
// check the provided password
|
||||||
password := []byte(msg.Params[0])
|
if bcrypt.CompareHashAndPassword(serverPassword, []byte(password)) == nil {
|
||||||
rb.session.sentPassCommand = bcrypt.CompareHashAndPassword(serverPassword, password) == nil
|
rb.session.passStatus = serverPassSuccessful
|
||||||
|
} else {
|
||||||
|
rb.session.passStatus = serverPassFailed
|
||||||
|
}
|
||||||
|
|
||||||
// if they failed the check, we'll bounce them later when they try to complete registration
|
// if they failed the check, we'll bounce them later when they try to complete registration
|
||||||
|
// note in particular that with skip-server-password, you can give the wrong server
|
||||||
|
// password here, then successfully SASL and be admitted
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,6 +351,10 @@ accounts:
|
|||||||
# PASS as well, so it can be configured to authenticate with SASL only.
|
# PASS as well, so it can be configured to authenticate with SASL only.
|
||||||
skip-server-password: false
|
skip-server-password: false
|
||||||
|
|
||||||
|
# enable login to accounts via the PASS command, e.g., PASS account:password
|
||||||
|
# this is sometimes useful for compatibility with old clients that don't support SASL
|
||||||
|
login-via-pass-command: false
|
||||||
|
|
||||||
# require-sasl controls whether clients are required to have accounts
|
# require-sasl controls whether clients are required to have accounts
|
||||||
# (and sign into them using SASL) to connect to the server
|
# (and sign into them using SASL) to connect to the server
|
||||||
require-sasl:
|
require-sasl:
|
||||||
|
Loading…
Reference in New Issue
Block a user