2017-03-11 13:01:40 +01:00
// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license
package irc
import (
2018-02-02 14:44:52 +01:00
"fmt"
2018-04-01 03:22:06 +02:00
2018-06-19 10:03:40 +02:00
"github.com/goshuirc/irc-go/ircfmt"
2017-03-11 13:01:40 +01:00
)
2018-04-19 08:48:19 +02:00
// "enabled" callbacks for specific nickserv commands
2019-01-04 04:32:07 +01:00
func servCmdRequiresAccreg ( config * Config ) bool {
return config . Accounts . Registration . Enabled
2018-04-19 08:48:19 +02:00
}
2019-01-04 04:32:07 +01:00
func servCmdRequiresAuthEnabled ( config * Config ) bool {
return config . Accounts . AuthenticationEnabled
2018-04-19 08:48:19 +02:00
}
2019-02-15 01:51:55 +01:00
func servCmdRequiresNickRes ( config * Config ) bool {
2019-01-04 04:32:07 +01:00
return config . Accounts . AuthenticationEnabled && config . Accounts . NickReservation . Enabled
2018-08-06 11:02:47 +02:00
}
2019-01-04 04:32:07 +01:00
func nsEnforceEnabled ( config * Config ) bool {
2019-02-15 01:51:55 +01:00
return servCmdRequiresNickRes ( config ) && config . Accounts . NickReservation . AllowCustomEnforcement
2019-01-02 16:08:44 +01:00
}
2019-02-18 04:59:13 +01:00
var (
// ZNC's nickserv module will not detect this unless it is:
// 1. sent with prefix `nickserv`
// 2. contains the string "identify"
// 3. contains at least one of several other magic strings ("msg" works)
2019-04-15 00:13:01 +02:00
nsTimeoutNotice = ` This nickname is reserved. Please login within %v (using $b/msg NickServ IDENTIFY <password>$b or SASL), or switch to a different nickname. `
2019-02-18 04:59:13 +01:00
)
2018-04-01 03:22:06 +02:00
const nickservHelp = ` NickServ lets you register and login to an account .
2018-02-02 14:44:52 +01:00
2018-04-01 03:22:06 +02:00
To see in - depth help for a specific NickServ command , try :
$ b / NS HELP < command > $ b
Here are the commands you can use :
% s `
var (
2018-04-19 08:48:19 +02:00
nickservCommands = map [ string ] * serviceCommand {
2018-04-01 03:22:06 +02:00
"drop" : {
handler : nsDropHandler ,
help : ` Syntax : $ bDROP [ nickname ] $ b
DROP de - links the given ( or your current ) nickname from your user account . ` ,
2018-04-19 08:48:19 +02:00
helpShort : ` $bDROP$b de-links your current (or the given) nickname from your user account. ` ,
2019-02-15 01:51:55 +01:00
enabled : servCmdRequiresNickRes ,
2018-04-19 08:48:19 +02:00
authRequired : true ,
2018-04-01 03:22:06 +02:00
} ,
2019-01-02 16:08:44 +01:00
"enforce" : {
handler : nsEnforceHandler ,
help : ` Syntax : $ bENFORCE [ method ] $ b
ENFORCE lets you specify a custom enforcement mechanism for your registered
nicknames . Your options are :
1. ' none ' [ no enforcement , overriding the server default ]
2. ' timeout ' [ anyone using the nick must authenticate before a deadline ,
or else they will be renamed ]
3. ' strict ' [ you must already be authenticated to use the nick ]
4. ' default ' [ use the server default ]
With no arguments , queries your current enforcement status . ` ,
helpShort : ` $bENFORCE$b lets you change how your nicknames are reserved. ` ,
authRequired : true ,
enabled : nsEnforceEnabled ,
} ,
2018-04-01 03:22:06 +02:00
"ghost" : {
handler : nsGhostHandler ,
help : ` Syntax : $ bGHOST < nickname > $ b
GHOST disconnects the given user from the network if they ' re logged in with the
same user account , letting you reclaim your nickname . ` ,
2018-04-19 08:48:19 +02:00
helpShort : ` $bGHOST$b reclaims your nickname. ` ,
authRequired : true ,
2019-01-04 04:32:07 +01:00
minParams : 1 ,
2018-04-01 03:22:06 +02:00
} ,
"group" : {
handler : nsGroupHandler ,
help : ` Syntax : $ bGROUP $ b
2019-02-22 03:53:01 +01:00
GROUP links your current nickname with your logged - in account , so other people
will not be able to use it . ` ,
2018-04-19 08:48:19 +02:00
helpShort : ` $bGROUP$b links your current nickname to your user account. ` ,
2019-02-15 01:51:55 +01:00
enabled : servCmdRequiresNickRes ,
2018-04-19 08:48:19 +02:00
authRequired : true ,
2018-04-01 03:22:06 +02:00
} ,
"identify" : {
handler : nsIdentifyHandler ,
help : ` Syntax : $ bIDENTIFY < username > [ password ] $ b
IDENTIFY lets you login to the given username using either password auth , or
certfp ( your client certificate ) if a password is not given . ` ,
helpShort : ` $bIDENTIFY$b lets you login to your account. ` ,
2019-01-04 04:32:07 +01:00
minParams : 1 ,
2018-04-01 03:22:06 +02:00
} ,
"info" : {
handler : nsInfoHandler ,
help : ` Syntax : $ bINFO [ username ] $ b
INFO gives you information about the given ( or your own ) user account . ` ,
helpShort : ` $bINFO$b gives you information on a user account. ` ,
} ,
"register" : {
handler : nsRegisterHandler ,
2018-04-01 03:29:13 +02:00
// TODO: "email" is an oversimplification here; it's actually any callback, e.g.,
// person@example.com, mailto:person@example.com, tel:16505551234.
2018-04-01 03:22:06 +02:00
help : ` Syntax : $ bREGISTER < username > < email > [ password ] $ b
REGISTER lets you register a user account . If the server allows anonymous
registration , you can send an asterisk ( * ) as the email address .
If the password is left out , your account will be registered to your TLS client
certificate ( and you will need to use that certificate to login in future ) . ` ,
helpShort : ` $bREGISTER$b lets you register a user account. ` ,
2018-04-19 08:48:19 +02:00
enabled : servCmdRequiresAccreg ,
2019-01-04 04:32:07 +01:00
minParams : 2 ,
2018-04-01 03:22:06 +02:00
} ,
"sadrop" : {
handler : nsDropHandler ,
help : ` Syntax : $ bSADROP < nickname > $ b
2018-04-19 08:48:19 +02:00
SADROP forcibly de - links the given nickname from the attached user account . ` ,
helpShort : ` $bSADROP$b forcibly de-links the given nickname from its user account. ` ,
2018-08-15 04:48:06 +02:00
capabs : [ ] string { "accreg" } ,
2019-02-15 01:51:55 +01:00
enabled : servCmdRequiresNickRes ,
2019-01-04 04:32:07 +01:00
minParams : 1 ,
2018-04-01 03:22:06 +02:00
} ,
2019-02-05 06:19:03 +01:00
"saregister" : {
handler : nsSaregisterHandler ,
help : ` Syntax : $ bSAREGISTER < username > < password > $ b
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. ` ,
2019-02-15 01:51:55 +01:00
enabled : servCmdRequiresAuthEnabled ,
2019-02-05 06:19:03 +01:00
capabs : [ ] string { "accreg" } ,
minParams : 2 ,
} ,
2018-04-01 03:22:06 +02:00
"unregister" : {
handler : nsUnregisterHandler ,
2018-06-19 10:03:40 +02:00
help : ` Syntax : $ bUNREGISTER < username > [ code ] $ b
2018-04-01 03:22:06 +02:00
2018-06-19 10:03:40 +02:00
UNREGISTER lets you delete your user account ( or someone else ' s , if you ' re an
IRC operator with the correct permissions ) . To prevent accidental
unregistrations , a verification code is required ; invoking the command without
a code will display the necessary code . ` ,
2018-04-01 03:22:06 +02:00
helpShort : ` $bUNREGISTER$b lets you delete your user account. ` ,
2019-02-15 01:51:55 +01:00
enabled : servCmdRequiresAuthEnabled ,
2019-01-04 04:32:07 +01:00
minParams : 1 ,
2018-04-01 03:22:06 +02:00
} ,
"verify" : {
handler : nsVerifyHandler ,
help : ` Syntax : $ bVERIFY < username > < code > $ b
VERIFY lets you complete an account registration , if the server requires email
or other verification . ` ,
helpShort : ` $bVERIFY$b lets you complete account registration. ` ,
2018-04-19 08:48:19 +02:00
enabled : servCmdRequiresAccreg ,
2019-01-04 04:32:07 +01:00
minParams : 2 ,
2018-04-01 03:22:06 +02:00
} ,
2018-11-29 00:21:41 +01:00
"passwd" : {
handler : nsPasswdHandler ,
help : ` Syntax : $ bPASSWD < current > < new > < new_again > $ b
Or : $ bPASSWD < username > < new > $ b
PASSWD lets you change your account password . You must supply your current
password and confirm the new one by typing it twice . If you ' re an IRC operator
with the correct permissions , you can use PASSWD to reset someone else ' s
password by supplying their username and then the desired password . ` ,
helpShort : ` $bPASSWD$b lets you change your password. ` ,
enabled : servCmdRequiresAuthEnabled ,
2019-01-04 04:32:07 +01:00
minParams : 2 ,
2018-11-29 00:21:41 +01:00
} ,
2018-04-01 03:22:06 +02:00
}
)
2018-04-01 03:52:37 +02:00
// nsNotice sends the client a notice from NickServ
2018-03-14 17:51:53 +01:00
func nsNotice ( rb * ResponseBuffer , text string ) {
rb . Add ( nil , "NickServ" , "NOTICE" , rb . target . Nick ( ) , text )
}
2019-01-04 04:32:07 +01:00
func nsDropHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
2018-04-01 03:22:06 +02:00
sadrop := command == "sadrop"
2019-01-04 04:32:07 +01:00
var nick string
if len ( params ) > 0 {
nick = params [ 0 ]
} else {
nick = client . NickCasefolded ( )
}
2018-04-01 03:22:06 +02:00
err := server . accounts . SetNickReserved ( client , nick , sadrop , false )
if err == nil {
nsNotice ( rb , fmt . Sprintf ( client . t ( "Successfully ungrouped nick %s with your account" ) , nick ) )
} else if err == errAccountNotLoggedIn {
nsNotice ( rb , client . t ( "You're not logged into an account" ) )
} else if err == errAccountCantDropPrimaryNick {
nsNotice ( rb , client . t ( "You can't ungroup your primary nickname (try unregistering your account instead)" ) )
} else {
nsNotice ( rb , client . t ( "Could not ungroup nick" ) )
}
}
2019-01-04 04:32:07 +01:00
func nsGhostHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
nick := params [ 0 ]
2018-04-01 03:22:06 +02:00
ghost := server . clients . Get ( nick )
if ghost == nil {
nsNotice ( rb , client . t ( "No such nick" ) )
return
} else if ghost == client {
nsNotice ( rb , client . t ( "You can't GHOST yourself (try /QUIT instead)" ) )
2018-02-12 07:09:30 +01:00
return
}
2018-04-09 18:29:19 +02:00
authorized := false
account := client . Account ( )
if account != "" {
// the user must either own the nick, or the target client
authorized = ( server . accounts . NickToAccount ( nick ) == account ) || ( ghost . Account ( ) == account )
}
if ! authorized {
nsNotice ( rb , client . t ( "You don't own that nick" ) )
return
}
2019-04-12 06:08:46 +02:00
ghost . Quit ( fmt . Sprintf ( ghost . t ( "GHOSTed by %s" ) , client . Nick ( ) ) , nil )
ghost . destroy ( false , nil )
2018-04-01 03:22:06 +02:00
}
2019-01-04 04:32:07 +01:00
func nsGroupHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
2019-01-31 00:59:49 +01:00
nick := client . Nick ( )
2018-04-01 03:22:06 +02:00
err := server . accounts . SetNickReserved ( client , nick , false , true )
if err == nil {
nsNotice ( rb , fmt . Sprintf ( client . t ( "Successfully grouped nick %s with your account" ) , nick ) )
} else if err == errAccountTooManyNicks {
nsNotice ( rb , client . t ( "You have too many nicks reserved already (you can remove some with /NS DROP)" ) )
} else if err == errNicknameReserved {
nsNotice ( rb , client . t ( "That nickname is already reserved by someone else" ) )
2018-02-12 07:09:30 +01:00
} else {
2018-04-01 03:22:06 +02:00
nsNotice ( rb , client . t ( "Error reserving nickname" ) )
2018-02-12 07:09:30 +01:00
}
}
2019-01-01 22:45:37 +01:00
func nsLoginThrottleCheck ( client * Client , rb * ResponseBuffer ) ( success bool ) {
throttled , remainingTime := client . loginThrottle . Touch ( )
if throttled {
nsNotice ( rb , fmt . Sprintf ( client . t ( "Please wait at least %v and try again" ) , remainingTime ) )
return false
}
return true
}
2019-01-04 04:32:07 +01:00
func nsIdentifyHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
2019-01-06 02:59:42 +01:00
if client . LoggedIntoAccount ( ) {
nsNotice ( rb , client . t ( "You're already logged into an account" ) )
return
}
2018-04-01 03:22:06 +02:00
loginSuccessful := false
2019-02-13 08:17:56 +01:00
var username , passphrase string
if len ( params ) == 1 {
if client . certfp != "" {
username = params [ 0 ]
} else {
// XXX undocumented compatibility mode with other nickservs, allowing
// /msg NickServ identify passphrase
username = client . NickCasefolded ( )
passphrase = params [ 0 ]
}
} else {
username = params [ 0 ]
2019-01-04 04:32:07 +01:00
passphrase = params [ 1 ]
}
2018-04-01 03:22:06 +02:00
// try passphrase
2019-01-04 04:32:07 +01:00
if passphrase != "" {
2019-01-01 22:45:37 +01:00
if ! nsLoginThrottleCheck ( client , rb ) {
return
}
2018-04-01 03:22:06 +02:00
err := server . accounts . AuthenticateByPassphrase ( client , username , passphrase )
loginSuccessful = ( err == nil )
}
// try certfp
if ! loginSuccessful && client . certfp != "" {
err := server . accounts . AuthenticateByCertFP ( client )
loginSuccessful = ( err == nil )
}
if loginSuccessful {
2019-04-08 02:40:19 +02:00
sendSuccessfulAccountAuth ( client , rb , true , true )
2018-04-01 03:22:06 +02:00
} else {
nsNotice ( rb , client . t ( "Could not login with your TLS certificate or supplied username/password" ) )
}
2018-02-20 10:20:30 +01:00
}
2019-01-04 04:32:07 +01:00
func nsInfoHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
var accountName string
if len ( params ) > 0 {
nick := params [ 0 ]
if server . AccountConfig ( ) . NickReservation . Enabled {
accountName = server . accounts . NickToAccount ( nick )
if accountName == "" {
nsNotice ( rb , client . t ( "That nickname is not registered" ) )
return
}
} else {
accountName = nick
}
} else {
accountName = client . Account ( )
2018-04-01 03:22:06 +02:00
if accountName == "" {
2019-01-04 04:32:07 +01:00
nsNotice ( rb , client . t ( "You're not logged into an account" ) )
2018-04-01 03:22:06 +02:00
return
}
}
account , err := server . accounts . LoadAccount ( accountName )
if err != nil || ! account . Verified {
nsNotice ( rb , client . t ( "Account does not exist" ) )
2019-01-04 04:32:07 +01:00
return
2018-04-01 03:22:06 +02:00
}
nsNotice ( rb , fmt . Sprintf ( client . t ( "Account: %s" ) , account . Name ) )
registeredAt := account . RegisteredAt . Format ( "Jan 02, 2006 15:04:05Z" )
nsNotice ( rb , fmt . Sprintf ( client . t ( "Registered at: %s" ) , registeredAt ) )
// TODO nicer formatting for this
for _ , nick := range account . AdditionalNicks {
nsNotice ( rb , fmt . Sprintf ( client . t ( "Additional grouped nick: %s" ) , nick ) )
}
2019-02-06 10:32:04 +01:00
for _ , channel := range server . accounts . ChannelsForAccount ( accountName ) {
nsNotice ( rb , fmt . Sprintf ( client . t ( "Registered channel: %s" ) , channel ) )
}
2018-04-01 03:22:06 +02:00
}
2019-01-04 04:32:07 +01:00
func nsRegisterHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
2018-04-01 03:22:06 +02:00
// get params
2019-02-05 06:19:03 +01:00
account , email := params [ 0 ] , params [ 1 ]
2019-01-04 04:32:07 +01:00
var passphrase string
2019-01-09 21:03:44 +01:00
if len ( params ) > 2 {
2019-01-04 04:32:07 +01:00
passphrase = params [ 2 ]
}
2018-04-01 03:22:06 +02:00
2018-02-20 10:20:30 +01:00
certfp := client . certfp
if passphrase == "" && certfp == "" {
2018-03-14 17:51:53 +01:00
nsNotice ( rb , client . t ( "You need to either supply a passphrase or be connected via TLS with a client cert" ) )
2018-02-20 10:20:30 +01:00
return
}
2018-02-03 12:38:28 +01:00
if client . LoggedIntoAccount ( ) {
2018-08-15 04:50:20 +02:00
nsNotice ( rb , client . t ( "You're already logged into an account" ) )
return
2018-02-03 12:38:28 +01:00
}
2018-02-02 14:44:52 +01:00
2019-02-06 02:09:36 +01:00
if ! nsLoginThrottleCheck ( client , rb ) {
return
}
2019-02-23 12:27:19 +01:00
// band-aid to let users know if they mix up the order of registration params
if email == "*" {
nsNotice ( rb , client . t ( "Registering your account with no email address" ) )
} else {
nsNotice ( rb , fmt . Sprintf ( client . t ( "Registering your account with email address %s" ) , email ) )
}
2018-02-20 10:20:30 +01:00
config := server . AccountConfig ( )
var callbackNamespace , callbackValue string
noneCallbackAllowed := false
2018-03-02 23:04:24 +01:00
for _ , callback := range config . Registration . EnabledCallbacks {
2018-02-20 10:20:30 +01:00
if callback == "*" {
noneCallbackAllowed = true
}
2018-02-03 12:38:28 +01:00
}
2018-02-20 10:20:30 +01:00
// XXX if ACC REGISTER allows registration with the `none` callback, then ignore
// any callback that was passed here (to avoid confusion in the case where the ircd
// has no mail server configured). otherwise, register using the provided callback:
if noneCallbackAllowed {
callbackNamespace = "*"
} else {
callbackNamespace , callbackValue = parseCallback ( email , config )
if callbackNamespace == "" {
2018-03-14 17:51:53 +01:00
nsNotice ( rb , client . t ( "Registration requires a valid e-mail address" ) )
2018-02-20 10:20:30 +01:00
return
2018-02-02 14:44:52 +01:00
}
2018-02-03 12:38:28 +01:00
}
2018-02-02 14:44:52 +01:00
2018-02-20 10:20:30 +01:00
err := server . accounts . Register ( client , account , callbackNamespace , callbackValue , passphrase , client . certfp )
2018-02-11 11:30:40 +01:00
if err == nil {
2018-02-20 10:20:30 +01:00
if callbackNamespace == "*" {
err = server . accounts . Verify ( client , account , "" )
if err == nil {
sendSuccessfulRegResponse ( client , rb , true )
}
} else {
2019-02-22 03:37:11 +01:00
messageTemplate := client . t ( "Account created, pending verification; verification code has been sent to %s" )
message := fmt . Sprintf ( messageTemplate , fmt . Sprintf ( "%s:%s" , callbackNamespace , callbackValue ) )
2018-03-14 17:51:53 +01:00
nsNotice ( rb , message )
2018-02-20 10:20:30 +01:00
}
2018-02-11 11:30:40 +01:00
}
2018-02-02 14:44:52 +01:00
2018-02-03 12:38:28 +01:00
// details could not be stored and relevant numerics have been dispatched, abort
2019-04-08 03:36:48 +02:00
message , _ := registrationErrorToMessageAndCode ( err )
2018-02-03 12:38:28 +01:00
if err != nil {
2019-04-08 03:36:48 +02:00
nsNotice ( rb , client . t ( message ) )
2018-02-03 12:38:28 +01:00
return
}
}
2018-02-02 14:44:52 +01:00
2019-02-05 06:19:03 +01:00
func nsSaregisterHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
account , passphrase := params [ 0 ] , params [ 1 ]
err := server . accounts . Register ( nil , account , "admin" , "" , passphrase , "" )
if err == nil {
err = server . accounts . Verify ( nil , account , "" )
}
if err != nil {
var errMsg string
if err == errAccountAlreadyRegistered || err == errAccountAlreadyVerified {
errMsg = client . t ( "Account already exists" )
} else if err == errAccountBadPassphrase {
errMsg = client . t ( "Passphrase contains forbidden characters or is otherwise invalid" )
} else {
server . logger . Error ( "services" , "unknown error from saregister" , err . Error ( ) )
errMsg = client . t ( "Could not register" )
}
nsNotice ( rb , errMsg )
} else {
nsNotice ( rb , fmt . Sprintf ( client . t ( "Successfully registered account %s" ) , account ) )
}
}
2019-01-04 04:32:07 +01:00
func nsUnregisterHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
username := params [ 0 ]
var verificationCode string
if len ( params ) > 1 {
verificationCode = params [ 1 ]
2018-03-02 23:04:24 +01:00
}
2018-04-01 03:22:06 +02:00
if username == "" {
2018-06-19 10:03:40 +02:00
nsNotice ( rb , client . t ( "You must specify an account" ) )
2018-03-02 23:04:24 +01:00
return
2018-04-01 03:22:06 +02:00
}
2018-06-19 10:03:40 +02:00
account , err := server . accounts . LoadAccount ( username )
if err == errAccountDoesNotExist {
nsNotice ( rb , client . t ( "Invalid account name" ) )
return
} else if err != nil {
nsNotice ( rb , client . t ( "Internal error" ) )
2018-03-02 23:04:24 +01:00
return
}
2018-06-19 10:03:40 +02:00
cfname , _ := CasefoldName ( username )
if ! ( cfname == client . Account ( ) || client . HasRoleCapabs ( "accreg" ) ) {
2018-04-01 03:22:06 +02:00
nsNotice ( rb , client . t ( "Insufficient oper privs" ) )
2018-03-02 23:04:24 +01:00
return
}
2018-06-19 10:03:40 +02:00
expectedCode := unregisterConfirmationCode ( account . Name , account . RegisteredAt )
if expectedCode != verificationCode {
nsNotice ( rb , ircfmt . Unescape ( client . t ( "$bWarning: unregistering this account will remove its stored privileges.$b" ) ) )
2019-02-22 03:37:11 +01:00
nsNotice ( rb , fmt . Sprintf ( client . t ( "To confirm account unregistration, type: /NS UNREGISTER %[1]s %[2]s" ) , cfname , expectedCode ) )
2018-06-19 10:03:40 +02:00
return
}
2018-04-01 03:22:06 +02:00
err = server . accounts . Unregister ( cfname )
if err == errAccountDoesNotExist {
nsNotice ( rb , client . t ( err . Error ( ) ) )
} else if err != nil {
nsNotice ( rb , client . t ( "Error while unregistering account" ) )
2018-03-02 23:04:24 +01:00
} else {
2018-04-01 03:22:06 +02:00
nsNotice ( rb , fmt . Sprintf ( client . t ( "Successfully unregistered account %s" ) , cfname ) )
2019-02-13 08:42:35 +01:00
server . logger . Info ( "accounts" , "client" , client . Nick ( ) , "unregistered account" , cfname )
2018-03-02 23:04:24 +01:00
}
}
2019-01-04 04:32:07 +01:00
func nsVerifyHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
username , code := params [ 0 ] , params [ 1 ]
2018-04-01 03:22:06 +02:00
err := server . accounts . Verify ( client , username , code )
2018-03-02 23:04:24 +01:00
2018-04-01 03:22:06 +02:00
var errorMessage string
if err == errAccountVerificationInvalidCode || err == errAccountAlreadyVerified {
errorMessage = err . Error ( )
} else if err != nil {
errorMessage = errAccountVerificationFailed . Error ( )
2018-03-02 23:04:24 +01:00
}
2018-04-01 03:22:06 +02:00
if errorMessage != "" {
nsNotice ( rb , client . t ( errorMessage ) )
return
2018-03-02 23:04:24 +01:00
}
2018-04-01 03:22:06 +02:00
sendSuccessfulRegResponse ( client , rb , true )
2018-03-02 23:04:24 +01:00
}
2018-11-29 00:21:41 +01:00
2019-01-04 04:32:07 +01:00
func nsPasswdHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
2018-11-29 00:21:41 +01:00
var target string
var newPassword string
var errorMessage string
2019-01-01 22:45:37 +01:00
hasPrivs := client . HasRoleCapabs ( "accreg" )
if ! hasPrivs && ! nsLoginThrottleCheck ( client , rb ) {
return
}
2019-01-04 04:32:07 +01:00
switch len ( params ) {
2018-11-29 00:21:41 +01:00
case 2 :
2019-01-01 22:45:37 +01:00
if ! hasPrivs {
2018-11-29 00:21:41 +01:00
errorMessage = "Insufficient privileges"
} else {
2019-01-04 04:32:07 +01:00
target , newPassword = params [ 0 ] , params [ 1 ]
2018-11-29 00:21:41 +01:00
}
case 3 :
target = client . Account ( )
if target == "" {
errorMessage = "You're not logged into an account"
2019-01-04 04:32:07 +01:00
} else if params [ 1 ] != params [ 2 ] {
2018-11-29 00:21:41 +01:00
errorMessage = "Passwords do not match"
} else {
// check that they correctly supplied the preexisting password
2019-01-04 04:32:07 +01:00
_ , err := server . accounts . checkPassphrase ( target , params [ 0 ] )
2018-11-29 00:21:41 +01:00
if err != nil {
errorMessage = "Password incorrect"
} else {
2019-01-04 04:32:07 +01:00
newPassword = params [ 1 ]
2018-11-29 00:21:41 +01:00
}
}
default :
errorMessage = "Invalid parameters"
}
if errorMessage != "" {
nsNotice ( rb , client . t ( errorMessage ) )
return
}
err := server . accounts . setPassword ( target , newPassword )
if err == nil {
nsNotice ( rb , client . t ( "Password changed" ) )
} else {
2018-12-31 17:33:42 +01:00
server . logger . Error ( "internal" , "could not upgrade user password:" , err . Error ( ) )
2018-11-29 00:21:41 +01:00
nsNotice ( rb , client . t ( "Password could not be changed due to server error" ) )
}
}
2019-01-02 16:08:44 +01:00
2019-01-04 04:32:07 +01:00
func nsEnforceHandler ( server * Server , client * Client , command string , params [ ] string , rb * ResponseBuffer ) {
if len ( params ) == 0 {
2019-01-02 16:08:44 +01:00
status := server . accounts . getStoredEnforcementStatus ( client . Account ( ) )
nsNotice ( rb , fmt . Sprintf ( client . t ( "Your current nickname enforcement is: %s" ) , status ) )
} else {
2019-01-04 04:32:07 +01:00
method , err := nickReservationFromString ( params [ 0 ] )
2019-01-02 16:08:44 +01:00
if err != nil {
nsNotice ( rb , client . t ( "Invalid parameters" ) )
return
}
err = server . accounts . SetEnforcementStatus ( client . Account ( ) , method )
if err == nil {
nsNotice ( rb , client . t ( "Enforcement method set" ) )
} else {
server . logger . Error ( "internal" , "couldn't store NS ENFORCE data" , err . Error ( ) )
nsNotice ( rb , client . t ( "An error occurred" ) )
}
}
}