diff --git a/irc/accounts.go b/irc/accounts.go index c0a1cf64..cf976e38 100644 --- a/irc/accounts.go +++ b/irc/accounts.go @@ -397,6 +397,10 @@ func validatePassphrase(passphrase string) error { if len(passphrase) == 0 || len(passphrase) > 600 { return errAccountBadPassphrase } + // we use * as a placeholder in some places, if it's gotten this far then fail + if passphrase == "*" { + return errAccountBadPassphrase + } // for now, just enforce that spaces are not allowed for _, r := range passphrase { if unicode.IsSpace(r) { diff --git a/irc/hostserv.go b/irc/hostserv.go index 698830e3..c3c0ba63 100644 --- a/irc/hostserv.go +++ b/irc/hostserv.go @@ -120,11 +120,12 @@ APPROVE approves a user's vhost request.`, REJECT rejects a user's vhost request, optionally giving them a reason for the rejection.`, - helpShort: `$bREJECT$b rejects a user's vhost request.`, - capabs: []string{"vhosts"}, - enabled: hostservEnabled, - minParams: 1, - maxParams: 2, + helpShort: `$bREJECT$b rejects a user's vhost request.`, + capabs: []string{"vhosts"}, + enabled: hostservEnabled, + minParams: 1, + maxParams: 2, + unsplitFinalParam: true, }, } ) diff --git a/irc/nickserv.go b/irc/nickserv.go index aca40d12..e07c03ae 100644 --- a/irc/nickserv.go +++ b/irc/nickserv.go @@ -110,16 +110,17 @@ INFO gives you information about the given (or your own) user account.`, handler: nsRegisterHandler, // TODO: "email" is an oversimplification here; it's actually any callback, e.g., // person@example.com, mailto:person@example.com, tel:16505551234. - help: `Syntax: $bREGISTER [password]$b + help: `Syntax: $bREGISTER [email]$b -REGISTER lets you register a user account. If the server allows anonymous -registration, you can send an asterisk (*) as the email address. +REGISTER lets you register your current nickname as a user account. If the +server allows anonymous registration, you can omit the e-mail 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).`, +If you are currently logged in with a TLS client certificate and wish to use +it instead of a password to log in, send * as the password.`, helpShort: `$bREGISTER$b lets you register a user account.`, enabled: servCmdRequiresAccreg, - minParams: 2, + minParams: 1, + maxParams: 2, }, "sadrop": { handler: nsDropHandler, @@ -586,20 +587,25 @@ func nsInfoHandler(server *Server, client *Client, command string, params []stri } func nsRegisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) { - // get params - account, email := params[0], params[1] - var passphrase string - if len(params) > 2 { - passphrase = params[2] + details := client.Details() + account := details.nick + passphrase := params[0] + var email string + if 1 < len(params) { + email = params[1] } certfp := client.certfp - if passphrase == "" && certfp == "" { - nsNotice(rb, client.t("You need to either supply a passphrase or be connected via TLS with a client cert")) - return + if passphrase == "*" { + if certfp == "" { + nsNotice(rb, client.t("You need to either supply a passphrase or be connected via TLS with a client cert")) + return + } else { + passphrase = "" + } } - if client.LoggedIntoAccount() { + if details.account != "" { nsNotice(rb, client.t("You're already logged into an account")) return } @@ -608,13 +614,6 @@ func nsRegisterHandler(server *Server, client *Client, command string, params [] return } - // 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)) - } - config := server.AccountConfig() var callbackNamespace, callbackValue string noneCallbackAllowed := false @@ -630,7 +629,7 @@ func nsRegisterHandler(server *Server, client *Client, command string, params [] callbackNamespace = "*" } else { callbackNamespace, callbackValue = parseCallback(email, config) - if callbackNamespace == "" { + if callbackNamespace == "" || callbackValue == "" { nsNotice(rb, client.t("Registration requires a valid e-mail address")) return } diff --git a/irc/services.go b/irc/services.go index 5e8026df..5396e4ec 100644 --- a/irc/services.go +++ b/irc/services.go @@ -26,17 +26,18 @@ type ircService struct { // defines a command associated with a service, e.g., NICKSERV IDENTIFY type serviceCommand struct { - aliasOf string // marks this command as an alias of another - capabs []string // oper capabs the given user has to have to access this command - handler func(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) - help string - helpStrings []string - helpShort string - authRequired bool - hidden bool - enabled func(*Config) bool // is this command enabled in the server config? - minParams int - maxParams int // split into at most n params, with last param containing remaining unsplit text + aliasOf string // marks this command as an alias of another + capabs []string // oper capabs the given user has to have to access this command + handler func(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) + help string + helpStrings []string + helpShort string + enabled func(*Config) bool // is this command enabled in the server config? + authRequired bool + hidden bool + minParams int + maxParams int // optional, if set it's an error if the user passes more than this many params + unsplitFinalParam bool // split into at most maxParams, with last param containing unsplit text } // looks up a command in the table of command definitions for a service, resolving aliases @@ -109,7 +110,7 @@ func serviceCmdHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb params := msg.Params[1:] cmd := lookupServiceCommand(service.Commands, commandName) // for a maxParams command, join all final parameters together if necessary - if cmd != nil && cmd.maxParams != 0 && cmd.maxParams < len(params) { + if cmd != nil && cmd.unsplitFinalParam && cmd.maxParams < len(params) { newParams := make([]string, cmd.maxParams) copy(newParams, params[:cmd.maxParams-1]) newParams[cmd.maxParams-1] = strings.Join(params[cmd.maxParams-1:], " ") @@ -130,7 +131,7 @@ func servicePrivmsgHandler(service *ircService, server *Server, client *Client, commandName := strings.ToLower(params[0]) cmd := lookupServiceCommand(service.Commands, commandName) // reparse if needed - if cmd != nil && cmd.maxParams != 0 { + if cmd != nil && cmd.unsplitFinalParam { params = utils.FieldsN(message, cmd.maxParams+1)[1:] } else { params = params[1:] @@ -150,7 +151,7 @@ func serviceRunCommand(service *ircService, server *Server, client *Client, cmd return } - if len(params) < cmd.minParams { + if len(params) < cmd.minParams || (0 < cmd.maxParams && cmd.maxParams < len(params)) { sendNotice(fmt.Sprintf(client.t("Invalid parameters. For usage, do /msg %[1]s HELP %[2]s"), service.Name, strings.ToUpper(commandName))) return } @@ -277,6 +278,10 @@ func initializeServices() { log.Fatal(fmt.Sprintf("help entry missing for %s command %s", serviceName, commandName)) } } + + if commandInfo.maxParams == 0 && commandInfo.unsplitFinalParam { + log.Fatal("unsplitFinalParam requires use of maxParams") + } } }