diff options
-rw-r--r-- | data/example.conf | 19 | ||||
-rw-r--r-- | data/nickserv.example.conf | 2 | ||||
-rw-r--r-- | modules/commands/ns_access.cpp | 12 | ||||
-rw-r--r-- | modules/commands/ns_ajoin.cpp | 52 | ||||
-rw-r--r-- | modules/commands/ns_cert.cpp | 118 |
5 files changed, 101 insertions, 102 deletions
diff --git a/data/example.conf b/data/example.conf index 445395cf1..d102875d7 100644 --- a/data/example.conf +++ b/data/example.conf @@ -793,8 +793,8 @@ log * memoserv/info - Can see any information with /memoserv info * memoserv/set-limit - Can set the limit of max stored memos on any user and channel * memoserv/no-limit - Can send memos through limits and throttles - * nickserv/access - Can modify other users access list - * nickserv/alist - Can see the access list of other users + * nickserv/access - Can modify other users access and certificate list + * nickserv/alist - Can see the channel access list of other users * nickserv/auspex - Can see any information with /nickserv info * nickserv/confirm - Can confirm other users nicknames * nickserv/drop - Can drop other users nicks @@ -806,7 +806,7 @@ log * chanserv/access/list chanserv/drop chanserv/getkey chanserv/invite * chanserv/list chanserv/suspend chanserv/topic * - * chanserv/saset/bantype chanserv/saset/description chanserv/saset/email + * chanserv/saset/bantype chanserv/saset/description chanserv/saset/email chanserv/saset/keepmodes * chanserv/saset/founder chanserv/saset/keeptopic chanserv/saset/restricted * chanserv/saset/peace chanserv/saset/persist chanserv/saset/private * chanserv/saset/secure chanserv/saset/securefounder chanserv/saset/secureops @@ -815,12 +815,13 @@ log * * memoserv/sendall memoserv/staff * - * nickserv/getpass nickserv/getemail nickserv/suspend - * nickserv/resetpass nickserv/release nickserv/list + * nickserv/getpass nickserv/getemail nickserv/suspend nickserv/ajoin + * nickserv/resetpass nickserv/list * - * nickserv/saset/autoop nickserv/saset/email nickserv/saset/greet nickserv/saset/password - * nickserv/saset/display nickserv/saset/kill nickserv/saset/language nickserv/saset/message - * nickserv/saset/private nickserv/saset/secure nickserv/saset/url nickserv/saset/noexpire + * nickserv/saset/autoop nickserv/saset/email nickserv/saset/greet nickserv/saset/password + * nickserv/saset/display nickserv/saset/kill nickserv/saset/language nickserv/saset/message + * nickserv/saset/private nickserv/saset/secure nickserv/saset/url nickserv/saset/noexpire + * nickserv/saset/keepmodes * * hostserv/set hostserv/del hostserv/list * @@ -829,7 +830,7 @@ log * operserv/news operserv/stats operserv/kick operserv/exception operserv/seen * operserv/mode operserv/session operserv/modinfo operserv/ignore operserv/chanlist * operserv/chankill operserv/akill operserv/sqline operserv/snline operserv/userlist - * operserv/oper operserv/config operserv/umode operserv/logsearch + * operserv/oper operserv/config operserv/umode operserv/logsearch * operserv/modload operserv/jupe operserv/set operserv/noop * operserv/quit operserv/update operserv/reload operserv/restart * operserv/shutdown operserv/svs operserv/oline operserv/kill diff --git a/data/nickserv.example.conf b/data/nickserv.example.conf index bb95282a1..e3afd1607 100644 --- a/data/nickserv.example.conf +++ b/data/nickserv.example.conf @@ -126,7 +126,7 @@ module expire = 21d /* - * Prevents the use of the ACCESS (excluding the LIST subcommand), DROP, FORBID, SUSPEND, + * Prevents the use of the ACCESS and CERT (excluding their LIST subcommand), DROP, FORBID, SUSPEND, * GETPASS and SET PASSWORD commands by services operators on other services operators. * * This directive is optional, but recommended. diff --git a/modules/commands/ns_access.cpp b/modules/commands/ns_access.cpp index 8ea925868..2d18678bd 100644 --- a/modules/commands/ns_access.cpp +++ b/modules/commands/ns_access.cpp @@ -30,7 +30,7 @@ class CommandNSAccess : public Command if (nc->access.size() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax")) { - source.Reply(_("Sorry, you can only have %d access entries for a nickname."), Config->GetModule(this->owner)->Get<unsigned>("accessmax")); + source.Reply(_("Sorry, the maximum of %d access entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("accessmax")); return; } @@ -97,9 +97,9 @@ class CommandNSAccess : public Command CommandNSAccess(Module *creator) : Command(creator, "nickserv/access", 1, 3) { this->SetDesc(_("Modify the list of authorized addresses")); - this->SetSyntax(_("ADD [\037user\037] \037mask\037")); - this->SetSyntax(_("DEL [\037user\037] \037mask\037")); - this->SetSyntax(_("LIST [\037user\037]")); + this->SetSyntax(_("ADD [\037nickname\037] \037mask\037")); + this->SetSyntax(_("DEL [\037nickname\037] \037mask\037")); + this->SetSyntax(_("LIST [\037nickname\037]")); } void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override @@ -145,14 +145,14 @@ class CommandNSAccess : public Command source.Reply(BAD_USERHOST_MASK); source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str()); } + else if (cmd.equals_ci("LIST")) + return this->DoList(source, nc, mask); else if (nc->HasExt("NS_SUSPENDED")) source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); else if (cmd.equals_ci("ADD")) return this->DoAdd(source, nc, mask); else if (cmd.equals_ci("DEL")) return this->DoDel(source, nc, mask); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, nc, mask); else this->OnSyntaxError(source, ""); } diff --git a/modules/commands/ns_ajoin.cpp b/modules/commands/ns_ajoin.cpp index 9a0ab0538..85c15c236 100644 --- a/modules/commands/ns_ajoin.cpp +++ b/modules/commands/ns_ajoin.cpp @@ -127,8 +127,8 @@ class CommandNSAJoin : public Command if ((*channels)->at(i)->channel.equals_ci(chan)) break; - if (*source.nc == nc && (*channels)->size() >= Config->GetModule(this->owner)->Get<unsigned>("ajoinmax")) - source.Reply(_("Your auto join list is full.")); + if ((*channels)->size() >= Config->GetModule(this->owner)->Get<unsigned>("ajoinmax")) + source.Reply(_("Sorry, the maximum of %d auto join entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("ajoinmax")); else if (i != (*channels)->size()) source.Reply(_("%s is already on %s's auto join list."), chan.c_str(), nc->display.c_str()); else if (IRCD->IsChannelValid(chan) == false) @@ -140,7 +140,7 @@ class CommandNSAJoin : public Command entry->channel = chan; entry->key = key; (*channels)->push_back(entry); - source.Reply(_("Added %s to %s's auto join list."), chan.c_str(), nc->display.c_str()); + source.Reply(_("%s added to %s's auto join list."), chan.c_str(), nc->display.c_str()); } } @@ -166,25 +166,36 @@ class CommandNSAJoin : public Command } public: - CommandNSAJoin(Module *creator) : Command(creator, "nickserv/ajoin", 1, 3) + CommandNSAJoin(Module *creator) : Command(creator, "nickserv/ajoin", 1, 4) { this->SetDesc(_("Manage your auto join list")); - this->SetSyntax(_("ADD [\037user\037] \037channel\037 [\037key\037]")); - this->SetSyntax(_("DEL [\037user\037] \037channel\037")); - this->SetSyntax(_("LIST [\037user\037]")); + this->SetSyntax(_("ADD [\037nickname\037] \037channel\037 [\037key\037]")); + this->SetSyntax(_("DEL [\037nickname\037] \037channel\037")); + this->SetSyntax(_("LIST [\037nickname\037]")); } void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - NickCore *nc = source.GetAccount(); - Anope::string param, param2; + const Anope::string &cmd = params[0]; + Anope::string nick, param, param2; - if (params.size() > 1 && source.IsServicesOper() && IRCD->IsNickValid(params[1])) + if (cmd.equals_ci("LIST")) + nick = params.size() > 1 ? params[1] : ""; + else + nick = (params.size() > 2 && IRCD->IsChannelValid(params[2])) ? params[1] : ""; + + NickCore *nc; + if (!nick.empty()) { - NickAlias *na = NickAlias::Find(params[1]); - if (!na) + const NickAlias *na = NickAlias::Find(nick); + if (na == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); + return; + } + else if (na->nc != source.GetAccount() && !source.HasCommand("nickserv/ajoin")) { - source.Reply(NICK_X_NOT_REGISTERED, params[1].c_str()); + source.Reply(ACCESS_DENIED); return; } @@ -194,20 +205,23 @@ class CommandNSAJoin : public Command } else { + nc = source.nc; param = params.size() > 1 ? params[1] : ""; param2 = params.size() > 2 ? params[2] : ""; } - if (params[0].equals_ci("LIST")) - this->DoList(source, nc); + if (cmd.equals_ci("LIST")) + return this->DoList(source, nc); + else if (nc->HasExt("NS_SUSPENDED")) + source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); else if (param.empty()) this->OnSyntaxError(source, ""); else if (Anope::ReadOnly) source.Reply(READ_ONLY_MODE); - else if (params[0].equals_ci("ADD")) - this->DoAdd(source, nc, param, param2); - else if (params[0].equals_ci("DEL")) - this->DoDel(source, nc, param); + else if (cmd.equals_ci("ADD")) + return this->DoAdd(source, nc, param, param2); + else if (cmd.equals_ci("DEL")) + return this->DoDel(source, nc, param); else this->OnSyntaxError(source, ""); } diff --git a/modules/commands/ns_cert.cpp b/modules/commands/ns_cert.cpp index a4a335fa0..5bb3487b1 100644 --- a/modules/commands/ns_cert.cpp +++ b/modules/commands/ns_cert.cpp @@ -134,48 +134,13 @@ struct NSCertListImpl : NSCertList class CommandNSCert : public Command { private: - void DoServAdminList(CommandSource &source, const NickCore *nc) - { - NSCertList *cl = nc->GetExt<NSCertList>("certificates"); - - if (!cl || !cl->GetCertCount()) - { - source.Reply(_("Certificate list for \002%s\002 is empty."), nc->display.c_str()); - return; - } - - if (nc->HasExt("NS_SUSPENDED")) - { - source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Certificate")); - - for (unsigned i = 0; i < cl->GetCertCount(); ++i) - { - const Anope::string &fingerprint = cl->GetCert(i); - ListFormatter::ListEntry entry; - entry["Certificate"] = fingerprint; - list.AddEntry(entry); - } - - source.Reply(_("Certificate list for \002%s\002:"), nc->display.c_str()); - - std::vector<Anope::string> replies; - list.Process(replies); - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask) { NSCertList *cl = nc->Require<NSCertList>("certificates"); if (cl->GetCertCount() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax")) { - source.Reply(_("Sorry, you can only have %d certificate entries for a nickname."), Config->GetModule(this->owner)->Get<unsigned>("accessmax")); + source.Reply(_("Sorry, the maximum of %d certificate entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("accessmax")); return; } @@ -194,12 +159,12 @@ class CommandNSCert : public Command if (cl->FindCert(mask)) { - source.Reply(_("Fingerprint \002%s\002 already present on your certificate list."), mask.c_str()); + source.Reply(_("Fingerprint \002%s\002 already present on %s's certificate list."), mask.c_str(), nc->display.c_str()); return; } cl->AddCert(mask); - source.Reply(_("\002%s\002 added to your certificate list."), mask.c_str()); + source.Reply(_("\002%s\002 added to %s's certificate list."), mask.c_str(), nc->display.c_str()); } void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask) @@ -221,11 +186,11 @@ class CommandNSCert : public Command if (!cl->FindCert(mask)) { - source.Reply(_("\002%s\002 not found on your certificate list."), mask.c_str()); + source.Reply(_("\002%s\002 not found on %s's certificate list."), mask.c_str(), nc->display.c_str()); return; } - source.Reply(_("\002%s\002 deleted from your certificate list."), mask.c_str()); + source.Reply(_("\002%s\002 deleted from %s's certificate list."), mask.c_str(), nc->display.c_str()); cl->EraseCert(mask); cl->Check(); } @@ -236,51 +201,69 @@ class CommandNSCert : public Command if (!cl || !cl->GetCertCount()) { - source.Reply(_("Your certificate list is empty.")); + source.Reply(_("%s's certificate list is empty."), nc->display.c_str()); return; } - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Certificate")); - + source.Reply(_("Certificate list for %s:"), nc->display.c_str()); for (unsigned i = 0; i < cl->GetCertCount(); ++i) { - ListFormatter::ListEntry entry; - entry["Certificate"] = cl->GetCert(i); - list.AddEntry(entry); + Anope::string fingerprint = cl->GetCert(i); + source.Reply(" %s", fingerprint.c_str()); } - - source.Reply(_("Certificate list:")); - std::vector<Anope::string> replies; - list.Process(replies); - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); } public: - CommandNSCert(Module *creator) : Command(creator, "nickserv/cert", 1, 2) + CommandNSCert(Module *creator) : Command(creator, "nickserv/cert", 1, 3) { this->SetDesc(_("Modify the nickname client certificate list")); - this->SetSyntax(_("ADD \037fingerprint\037")); - this->SetSyntax(_("DEL \037fingerprint\037")); - this->SetSyntax("LIST"); + this->SetSyntax(_("ADD [\037nickname\037] \037fingerprint\037")); + this->SetSyntax(_("DEL [\037nickname\037] \037fingerprint\037")); + this->SetSyntax(_("LIST [\037nickname\037]")); } void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { const Anope::string &cmd = params[0]; - const Anope::string &mask = params.size() > 1 ? params[1] : ""; + Anope::string nick, mask; - const NickAlias *na; - if (cmd.equals_ci("LIST") && source.IsServicesOper() && !mask.empty() && (na = NickAlias::Find(mask))) - return this->DoServAdminList(source, na->nc); + if (cmd.equals_ci("LIST")) + nick = params.size() > 1 ? params[1] : ""; + else + { + nick = params.size() == 3 ? params[1] : ""; + mask = params.size() > 1 ? params[params.size() - 1] : ""; + } - NickCore *nc = source.nc; + NickCore *nc; + if (!nick.empty()) + { + const NickAlias *na = NickAlias::Find(nick); + if (na == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); + return; + } + else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/access")) + { + source.Reply(ACCESS_DENIED); + return; + } + else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.GetAccount() != na->nc && na->nc->IsServicesOper() && !cmd.equals_ci("LIST")) + { + source.Reply(_("You may view but not modify the certificate list of other Services Operators.")); + return; + } - if (source.nc->HasExt("NS_SUSPENDED")) - source.Reply(NICK_X_SUSPENDED, source.nc->display.c_str()); - else if (cmd.equals_ci("LIST")) + nc = na->nc; + } + else + nc = source.nc; + + if (cmd.equals_ci("LIST")) return this->DoList(source, nc); + else if (nc->HasExt("NS_SUSPENDED")) + source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); else if (Anope::ReadOnly) source.Reply(READ_ONLY_MODE); else if (cmd.equals_ci("ADD")) @@ -288,7 +271,7 @@ class CommandNSCert : public Command else if (cmd.equals_ci("DEL")) return this->DoDel(source, nc, mask); else - this->OnSyntaxError(source, cmd); + this->OnSyntaxError(source, ""); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override @@ -298,7 +281,8 @@ class CommandNSCert : public Command source.Reply(_("Modifies or displays the certificate list for your nick.\n" "If you connect to IRC and provide a client certificate with a\n" "matching fingerprint in the cert list, your nick will be\n" - "automatically identified to services.\n" + "automatically identified to services. Services Operators\n" + "may provide a nick to modify other users' certificate lists.\n" " \n")); source.Reply(_("Examples:\n" " \n" |