diff --git a/docs/MANUAL.md b/docs/MANUAL.md index 7fd566d7..6b944974 100644 --- a/docs/MANUAL.md +++ b/docs/MANUAL.md @@ -129,17 +129,17 @@ In this section, we'll explain and go through using various features of the Orag In most IRC servers you can use `NickServ` to register an account. You can do the same thing with Oragono, by default, with no other software needed! -These are the two ways you can register an account: +These are the two ways you can register an account, either one will work: - /QUOTE ACC REGISTER * passphrase : - /NS REGISTER * + /QUOTE ACC REGISTER * passphrase + /NS REGISTER -This is the way to go if you want to use a regular password. `` and `` are your username and password, respectively (make sure the leave that one `:` before your actual password!). +This is the way to go if you want to use a regular password. `` and `` are your username and password, respectively; if you go the `/NS REGISTER` route, then your current nickname will become your username. Your password cannot contain spaces, but make sure to use a strong one anyway. + +If you want to use a TLS client certificate instead of a password to authenticate (`SASL EXTERNAL`), then you can use the commands below to do so. (If you're not sure what this is, don't worry – just use the above password method to register an account.) /QUOTE ACC REGISTER * certfp * - /NS REGISTER - -If you want to use a TLS client certificate to authenticate (`SASL CERTFP`), then you can use the above method to do so. If you're not sure what this is, don't worry – just use the above password method to register an account. + /NS REGISTER * Once you've registered, you'll need to setup SASL to login (or use NickServ IDENTIFY). One of the more complete SASL instruction pages is Freenode's page [here](https://freenode.net/kb/answer/sasl). Open up that page, find your IRC client and then setup SASL with your chosen username and password! 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..542f236e 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 must be connected with TLS and a client certificate to do this")) + 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") + } } }