1
0
mirror of https://github.com/anope/anope.git synced 2026-06-24 10:16:37 +02:00
Files
anope/modules/commands/ns_cert.cpp
T

238 lines
6.2 KiB
C++

/* NickServ core functions
*
* (C) 2003-2013 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*/
#include "module.h"
static unsigned accessmax;
class CommandNSCert : public Command
{
private:
void DoServAdminList(CommandSource &source, const NickCore *nc)
{
if (nc->cert.empty())
{
source.Reply(_("Certificate list for \002%s\002 is empty."), nc->display.c_str());
return;
}
if (nc->HasExt("SUSPENDED"))
{
source.Reply(NICK_X_SUSPENDED, nc->display.c_str());
return;
}
ListFormatter list;
list.AddColumn("Certificate");
for (unsigned i = 0, end = nc->cert.size(); i < end; ++i)
{
Anope::string fingerprint = nc->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]);
return;
}
void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask)
{
if (nc->cert.size() >= 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"));
return;
}
if (source.GetUser() && !source.GetUser()->fingerprint.empty() && !nc->FindCert(source.GetUser()->fingerprint))
{
nc->AddCert(source.GetUser()->fingerprint);
source.Reply(_("\002%s\002 added to your certificate list."), source.GetUser()->fingerprint.c_str());
return;
}
if (mask.empty())
{
this->OnSyntaxError(source, "ADD");
return;
}
if (nc->FindCert(mask))
{
source.Reply(_("Fingerprint \002%s\002 already present on your certificate list."), mask.c_str());
return;
}
nc->AddCert(mask);
source.Reply(_("\002%s\002 added to your certificate list."), mask.c_str());
return;
}
void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask)
{
if (source.GetUser() && !source.GetUser()->fingerprint.empty() && nc->FindCert(source.GetUser()->fingerprint))
{
nc->EraseCert(source.GetUser()->fingerprint);
source.Reply(_("\002%s\002 deleted from your certificate list."), source.GetUser()->fingerprint.c_str());
return;
}
if (mask.empty())
{
this->OnSyntaxError(source, "DEL");
return;
}
if (!nc->FindCert(mask))
{
source.Reply(_("\002%s\002 not found on your certificate list."), mask.c_str());
return;
}
source.Reply(_("\002%s\002 deleted from your certificate list."), mask.c_str());
nc->EraseCert(mask);
return;
}
void DoList(CommandSource &source, const NickCore *nc)
{
if (nc->cert.empty())
{
source.Reply(_("Your certificate list is empty."));
return;
}
ListFormatter list;
list.AddColumn("Certificate");
for (unsigned i = 0, end = nc->cert.size(); i < end; ++i)
{
ListFormatter::ListEntry entry;
entry["Certificate"] = nc->GetCert(i);
list.AddEntry(entry);
}
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)
{
this->SetDesc("Modify the nickname client certificate list");
this->SetSyntax("ADD \037fingerprint\037");
this->SetSyntax("DEL \037fingerprint\037");
this->SetSyntax("LIST");
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
{
const Anope::string &cmd = params[0];
const Anope::string &mask = params.size() > 1 ? params[1] : "";
const NickAlias *na;
if (cmd.equals_ci("LIST") && source.IsServicesOper() && !mask.empty() && (na = NickAlias::Find(mask)))
return this->DoServAdminList(source, na->nc);
NickCore *nc = source.nc;
if (source.nc->HasExt("SUSPENDED"))
source.Reply(NICK_X_SUSPENDED, source.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);
else
this->OnSyntaxError(source, cmd);
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
{
this->SendSyntax(source);
source.Reply(" ");
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"
" \n"));
source.Reply(_("Examples:\n"
" \n"
" \002CERT ADD <fingerprint>\002\n"
" Adds this fingerprint to the certificate list and\n"
" automatically identifies you when you connect to IRC\n"
" using this certificate.\n"
" \n"
" \002CERT DEL <fingerprint>\002\n"
" Reverses the previous command.\n"
" \n"
" \002CERT LIST\002\n"
" Displays the current certificate list."));
return true;
}
};
class NSCert : public Module
{
CommandNSCert commandnscert;
void DoAutoIdentify(User *u)
{
NickAlias *na = NickAlias::Find(u->nick);
BotInfo *NickServ = Config->GetClient("NickServ");
if (!NickServ || !na)
return;
if (u->IsIdentified() && u->Account() == na->nc)
return;
if (na->nc->HasExt("SUSPENDED"))
return;
if (!na->nc->FindCert(u->fingerprint))
return;
u->Identify(na);
u->SendMessage(NickServ, _("SSL Fingerprint accepted. You are now identified."));
Log(u) << "automatically identified for account " << na->nc->display << " using a valid SSL fingerprint";
return;
}
public:
NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnscert(this)
{
if (!IRCD || !IRCD->CanCertFP)
throw ModuleException("Your IRCd does not support ssl client certificates");
}
void OnFingerprint(User *u) anope_override
{
DoAutoIdentify(u);
}
};
MODULE_INIT(NSCert)