diff --git a/irc/accounts.go b/irc/accounts.go index ce5f0e41..284e9d2e 100644 --- a/irc/accounts.go +++ b/irc/accounts.go @@ -821,7 +821,7 @@ func (am *AccountManager) dispatchMailtoCallback(client *Client, account string, return } -func (am *AccountManager) Verify(client *Client, account string, code string) error { +func (am *AccountManager) Verify(client *Client, account string, code string, admin bool) error { casefoldedAccount, err := CasefoldName(account) var skeleton string if err != nil || account == "" || account == "*" { @@ -884,18 +884,20 @@ func (am *AccountManager) Verify(client *Client, account string, code string) er return errAccountAlreadyVerified } - // actually verify the code - // a stored code of "" means a none callback / no code required - success := false - storedCode, err := tx.Get(verificationCodeKey) - if err == nil { - // this is probably unnecessary - if storedCode == "" || utils.SecretTokensMatch(storedCode, code) { - success = true + if !admin { + // actually verify the code + // a stored code of "" means a none callback / no code required + success := false + storedCode, err := tx.Get(verificationCodeKey) + if err == nil { + // this is probably unnecessary + if storedCode == "" || utils.SecretTokensMatch(storedCode, code) { + success = true + } + } + if !success { + return errAccountVerificationInvalidCode } - } - if !success { - return errAccountVerificationInvalidCode } // verify the account @@ -964,7 +966,7 @@ func (am *AccountManager) Verify(client *Client, account string, code string) er func (am *AccountManager) SARegister(account, passphrase string) (err error) { err = am.Register(nil, account, "admin", "", passphrase, "") if err == nil { - err = am.Verify(nil, account, "") + err = am.Verify(nil, account, "", true) } return } diff --git a/irc/handlers.go b/irc/handlers.go index 0b5e470c..8f102f30 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -2632,7 +2632,7 @@ func registerHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res switch err { case nil: if callbackNamespace == "*" { - err := server.accounts.Verify(client, accountName, "") + err := server.accounts.Verify(client, accountName, "", true) if err == nil { if client.registered { if !fixupNickEqualsAccount(client, rb, config, "") { @@ -2684,7 +2684,7 @@ func verifyHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respo } accountName, verificationCode := msg.Params[0], msg.Params[1] - err := server.accounts.Verify(client, accountName, verificationCode) + err := server.accounts.Verify(client, accountName, verificationCode, false) if err == nil && client.registered { if !fixupNickEqualsAccount(client, rb, config, "") { err = errNickAccountMismatch diff --git a/irc/nickserv.go b/irc/nickserv.go index 44139359..aab52186 100644 --- a/irc/nickserv.go +++ b/irc/nickserv.go @@ -164,7 +164,17 @@ SAREGISTER registers an account on someone else's behalf. This is for use in configurations that require SASL for all connections; an administrator can set use this command to set up user accounts.`, helpShort: `$bSAREGISTER$b registers an account on someone else's behalf.`, - enabled: servCmdRequiresAuthEnabled, + enabled: servCmdRequiresAuthEnabled, // deliberate + capabs: []string{"accreg"}, + minParams: 1, + }, + "saverify": { + handler: nsSaverifyHandler, + help: `Syntax: $bSAVERIFY $b + +SAVERIFY manually verifies an account that is pending verification.`, + helpShort: `$bSAREGISTER$b registers an account on someone else's behalf.`, + enabled: servCmdRequiresAuthEnabled, // deliberate capabs: []string{"accreg"}, minParams: 1, }, @@ -996,7 +1006,7 @@ func nsRegisterHandler(service *ircService, server *Server, client *Client, comm err := server.accounts.Register(client, account, callbackNamespace, callbackValue, passphrase, rb.session.certfp) if err == nil { if callbackNamespace == "*" { - err = server.accounts.Verify(client, account, "") + err = server.accounts.Verify(client, account, "", true) if err == nil && fixupNickEqualsAccount(client, rb, config, service.prefix) { sendSuccessfulRegResponse(service, client, rb) } @@ -1038,6 +1048,16 @@ func nsSaregisterHandler(service *ircService, server *Server, client *Client, co } } +func nsSaverifyHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) { + account := params[0] + err := server.accounts.Verify(nil, account, "", true) + if err == nil { + service.Notice(rb, fmt.Sprintf(client.t("Successfully verified account %s"), account)) + } else { + service.Notice(rb, fmt.Sprintf(client.t("Failed to verify account %s: %v"), account, err.Error())) + } +} + func nsUnregisterHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) { erase := command == "erase" @@ -1106,7 +1126,7 @@ func nsUnregisterHandler(service *ircService, server *Server, client *Client, co func nsVerifyHandler(service *ircService, server *Server, client *Client, command string, params []string, rb *ResponseBuffer) { username, code := params[0], params[1] - err := server.accounts.Verify(client, username, code) + err := server.accounts.Verify(client, username, code, false) var errorMessage string if err != nil {