diff options
author | DukePyrolator <DukePyrolator@anope.org> | 2011-03-12 09:27:16 +0100 |
---|---|---|
committer | DukePyrolator <DukePyrolator@anope.org> | 2011-03-12 09:27:16 +0100 |
commit | fbae3344ff70f9e035292fdc9a6e09efc2702aed (patch) | |
tree | 440df041a811317db159365a6322bae9cd596643 | |
parent | 95469fde3055e1a257fd4e1027617892b912d07c (diff) |
added ns_cert
-rw-r--r-- | data/example.conf | 2 | ||||
-rw-r--r-- | include/account.h | 42 | ||||
-rw-r--r-- | include/modules.h | 18 | ||||
-rw-r--r-- | include/services.h | 1 | ||||
-rw-r--r-- | include/users.h | 7 | ||||
-rw-r--r-- | modules/core/db_plain.cpp | 7 | ||||
-rw-r--r-- | modules/core/ns_cert.cpp | 234 | ||||
-rw-r--r-- | modules/core/ns_ghost.cpp | 3 | ||||
-rw-r--r-- | modules/core/ns_group.cpp | 26 | ||||
-rw-r--r-- | modules/core/ns_identify.cpp | 43 | ||||
-rw-r--r-- | modules/core/ns_recover.cpp | 3 | ||||
-rw-r--r-- | modules/core/ns_release.cpp | 4 | ||||
-rw-r--r-- | modules/core/ns_resetpass.cpp | 23 | ||||
-rw-r--r-- | modules/extra/ns_identify_ldap.cpp | 25 | ||||
-rw-r--r-- | modules/protocol/bahamut.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/inspircd11.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/inspircd12.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/inspircd20.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/ngircd.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/plexus.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/ratbox.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/unreal32.cpp | 1 | ||||
-rw-r--r-- | src/nickcore.cpp | 39 | ||||
-rw-r--r-- | src/nickserv.cpp | 7 | ||||
-rw-r--r-- | src/users.cpp | 57 |
25 files changed, 451 insertions, 98 deletions
diff --git a/data/example.conf b/data/example.conf index 783c1fb14..28ca69dc7 100644 --- a/data/example.conf +++ b/data/example.conf @@ -930,7 +930,7 @@ nickserv * * This directive is optional, but highly recommended. */ - modules = "ns_help ns_register ns_group ns_identify ns_access ns_set ns_saset ns_set_autoop ns_set_email ns_set_greet ns_set_hide ns_set_kill ns_set_language ns_set_message ns_set_private ns_set_secure ns_saset_noexpire ns_drop ns_recover ns_release ns_sendpass ns_ghost ns_alist ns_info ns_list ns_logout ns_status ns_update ns_getpass ns_getemail ns_forbid ns_suspend ns_resetpass ns_ajoin" + modules = "ns_help ns_register ns_group ns_identify ns_access ns_cert ns_set ns_saset ns_set_autoop ns_set_email ns_set_greet ns_set_hide ns_set_kill ns_set_language ns_set_message ns_set_private ns_set_secure ns_saset_noexpire ns_drop ns_recover ns_release ns_sendpass ns_ghost ns_alist ns_info ns_list ns_logout ns_status ns_update ns_getpass ns_getemail ns_forbid ns_suspend ns_resetpass ns_ajoin" /* * Force users to give an e-mail address when they register a nick. diff --git a/include/account.h b/include/account.h index 8615083b9..635606f62 100644 --- a/include/account.h +++ b/include/account.h @@ -152,6 +152,7 @@ class CoreExport NickCore : public Extensible, public Flags<NickCoreFlag, NI_END Anope::string greet; /* Greet associated to the nick */ Anope::string language; /* Language name */ std::vector<Anope::string> access; /* Access list, vector of strings */ + std::vector<Anope::string> cert; /* ssl certificate list, vector of strings */ MemoInfo memos; uint16 channelcount; /* Number of channels currently registered */ @@ -217,6 +218,47 @@ class CoreExport NickCore : public Extensible, public Flags<NickCoreFlag, NI_END * Deletes all the memory allocated in the access list vector and then clears the vector. */ void ClearAccess(); + + /** Add an entry to the nick's certificate list + * + * @param entry The fingerprint to add to the cert list + * + * Adds a new entry into the cert list. + */ + void AddCert(const Anope::string &entry); + + /** Get an entry from the nick's cert list by index + * + * @param entry Index in the certificaate list vector to retrieve + * @return The fingerprint entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds + * + * Retrieves an entry from the certificate list corresponding to the given index. + */ + Anope::string GetCert(unsigned entry) const; + + /** Find an entry in the nick's cert list + * + * @param entry The fingerprint to search for + * @return True if the fingerprint is found in the cert list, false otherwise + * + * Search for an fingerprint within the cert list. + */ + bool FindCert(const Anope::string &entry); + + /** Erase a fingerprint from the nick's certificate list + * + * @param entry The fingerprint to remove + * + * Removes the specified fingerprint from the cert list. + */ + void EraseCert(const Anope::string &entry); + + /** Clears the entire nick's cert list + * + * Deletes all the memory allocated in the certificate list vector and then clears the vector. + */ + void ClearCert(); + }; /** Timer for colliding nicks to force people off of nicknames diff --git a/include/modules.h b/include/modules.h index 8367b084f..97cb49697 100644 --- a/include/modules.h +++ b/include/modules.h @@ -887,6 +887,23 @@ class CoreExport Module : public Extensible */ virtual void OnNickEraseAccess(NickCore *nc, const Anope::string &entry) { } + /** called from NickCore::ClearCert() + * @param nc pointer to the NickCore + */ + virtual void OnNickClearCert(NickCore *nc) { } + + /** Called when a user adds an entry to their cert list + * @param nc The nick + * @param entry The entry + */ + virtual void OnNickAddCert(NickCore *nc, const Anope::string &entry) { } + + /** Called from NickCore::EraseCert() + * @param nc pointer to the NickCore + * @param entry The fingerprint + */ + virtual void OnNickEraseCert(NickCore *nc, const Anope::string &entry) { } + /** Called when a user requests info for a nick * @param source The user requesting info * @param na The nick the user is requesting info from @@ -1059,6 +1076,7 @@ enum Implementation I_OnNickRegister, I_OnNickSuspended, I_OnNickUnsuspended, I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess, + I_OnNickClearCert, I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnFindNick, I_OnFindCore, /* ChanServ */ diff --git a/include/services.h b/include/services.h index 3500e532f..75e21a5cf 100644 --- a/include/services.h +++ b/include/services.h @@ -486,6 +486,7 @@ struct IRCDVar int ts6; /* ircd is TS6 */ const char *globaltldprefix; /* TLD prefix used for Global */ unsigned maxmodes; /* Max modes to send per line */ + int certfp; /* IRCd sends a SSL users certificate fingerprint */ }; /*************************************************************************/ diff --git a/include/users.h b/include/users.h index 667293a3f..30f5c8275 100644 --- a/include/users.h +++ b/include/users.h @@ -164,6 +164,13 @@ class CoreExport User : public Extensible */ void Collide(NickAlias *na); + /** Identify the user to the Nick + * updates last_seen, logs the user in, + * send messages, checks for mails, set vhost and more + * @param the NickAlias + */ + void Identify(NickAlias *na); + /** Login the user to a NickCore * @param core The account the user is useing */ diff --git a/modules/core/db_plain.cpp b/modules/core/db_plain.cpp index c20a78577..550f229a1 100644 --- a/modules/core/db_plain.cpp +++ b/modules/core/db_plain.cpp @@ -485,6 +485,8 @@ class DBPlain : public Module nc->greet = params[0]; else if (key.equals_ci("ACCESS")) nc->AddAccess(params[0]); + else if (key.equals_ci("CERT")) + nc->AddCert(params[0]); else if (key.equals_ci("FLAGS")) nc->FromString(params); else if (key.equals_ci("MI")) @@ -737,6 +739,11 @@ class DBPlain : public Module for (std::vector<Anope::string>::iterator it = nc->access.begin(), it_end = nc->access.end(); it != it_end; ++it) db_buffer << "MD ACCESS " << *it << endl; } + if (!nc->cert.empty()) + { + for (std::vector<Anope::string>::iterator it = nc->cert.begin(), it_end = nc->cert.end(); it != it_end; ++it) + db_buffer << "MD CERT " << *it << endl; + } if (nc->FlagCount()) db_buffer << "MD FLAGS " << ToString(nc->ToString()) << endl; MemoInfo *mi = &nc->memos; diff --git a/modules/core/ns_cert.cpp b/modules/core/ns_cert.cpp new file mode 100644 index 000000000..5581149f6 --- /dev/null +++ b/modules/core/ns_cert.cpp @@ -0,0 +1,234 @@ +/* NickServ core functions + * + * (C) 2003-2011 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" + +class CommandNSCert : public Command +{ + private: + CommandReturn DoServAdminList(CommandSource &source, NickCore *nc) + { + if (nc->cert.empty()) + { + source.Reply(_("Certificate list for \002%s\002 is empty."), nc->display.c_str()); + return MOD_CONT; + } + + if (nc->HasFlag(NI_SUSPENDED)) + { + source.Reply(_(NICK_X_SUSPENDED), nc->display.c_str()); + return MOD_CONT; + } + + source.Reply(_("Certificate list for \002%s\002:"), nc->display.c_str()); + for (unsigned i = 0, end = nc->cert.size(); i < end; ++i) + { + Anope::string fingerprint = nc->GetCert(i); + source.Reply(" %s", fingerprint.c_str()); + } + + return MOD_CONT; + } + + CommandReturn DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask) + { + + if (nc->cert.size() >= Config->NSAccessMax) + { + source.Reply(_("Sorry, you can only have %d certificate entries for a nickname."), Config->NSAccessMax); + return MOD_CONT; + } + + if (!source.u->fingerprint.empty() && !nc->FindCert(source.u->fingerprint)) + { + nc->AddCert(source.u->fingerprint); + source.Reply(_("\002%s\002 added to your certificate list"), source.u->fingerprint.c_str()); + return MOD_CONT; + } + + if (mask.empty()) + { + this->OnSyntaxError(source, "ADD"); + return MOD_CONT; + } + + if (nc->FindCert(mask)) + { + source.Reply(_("Fingerprint \002%s\002 already present on your certificate list."), mask.c_str()); + return MOD_CONT; + } + + nc->AddCert(mask); + source.Reply(_("\002%s\002 added to your certificate list."), mask.c_str()); + return MOD_CONT; + } + + CommandReturn DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask) + { + + if (!source.u->fingerprint.empty() && nc->FindCert(source.u->fingerprint)) + { + nc->EraseCert(source.u->fingerprint); + source.Reply(_("\002%s\002 deleted from your certificate list"), source.u->fingerprint.c_str()); + return MOD_CONT; + } + + if (mask.empty()) + { + this->OnSyntaxError(source, "DEL"); + return MOD_CONT; + } + + if (!nc->FindCert(mask)) + { + source.Reply(_("\002%s\002 not found on your certificate list."), mask.c_str()); + return MOD_CONT; + } + + source.Reply(_("\002%s\002 deleted from your certificate list."), mask.c_str()); + nc->EraseCert(mask); + + return MOD_CONT; + } + + CommandReturn DoList(CommandSource &source, NickCore *nc) + { + User *u = source.u; + + if (nc->cert.empty()) + { + source.Reply(_("Your certificate list is empty."), u->nick.c_str()); + return MOD_CONT; + } + + source.Reply(_("Cert list:")); + for (unsigned i = 0, end = nc->cert.size(); i < end; ++i) + { + Anope::string fingerprint = nc->GetCert(i); + source.Reply(" %s", fingerprint.c_str()); + } + + return MOD_CONT; + } + + public: + CommandNSCert() : Command("CERT", 1, 2) + { + this->SetDesc("Modify the nickname client certificate list"); + } + + CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + const Anope::string &cmd = params[0]; + const Anope::string &mask = params.size() > 1 ? params[1] : ""; + + NickAlias *na; + if (cmd.equals_ci("LIST") && u->Account()->IsServicesOper() && !mask.empty() && (na = findnick(mask))) + return this->DoServAdminList(source, na->nc); + + if (u->Account()->HasFlag(NI_SUSPENDED)) + source.Reply(_(NICK_X_SUSPENDED), u->Account()->display.c_str()); + else if (cmd.equals_ci("ADD")) + return this->DoAdd(source, u->Account(), mask); + else if (cmd.equals_ci("DEL")) + return this->DoDel(source, u->Account(), mask); + else if (cmd.equals_ci("LIST")) + return this->DoList(source, u->Account()); + else + this->OnSyntaxError(source, cmd); + + return MOD_CONT; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + source.Reply(_("Syntax: \002CERT ADD [\037fingerprint\037]\002\n" + " \002CERT DEL [\037<fingerprint>\037]\002\n" + " \002CERT LIST\002\n" + " \n" + "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 %s.\n" + " \n"), NickServ->nick.c_str(), NickServ->nick.c_str()); + 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."), NickServ->nick.c_str()); + return true; + } + + void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + { + SyntaxError(source, "CERT", _("CERT {ADD|DEL|LIST} [\037fingerprint\037]")); + } +}; + +class NSCert : public Module +{ + CommandNSCert commandnscert; + + void DoAutoIdentify(User *u) + { + NickAlias *na = findnick(u->nick); + if (!na) + return; + if (u->IsIdentified() && u->Account() == na->nc) + return; + if (na->HasFlag(NS_FORBIDDEN) || na->nc->HasFlag(NI_SUSPENDED)) + return; + if (!na->nc->FindCert(u->fingerprint)) + return; + + u->Identify(na); + u->SendMessage(NickServ, _("SSL Fingerprint accepted. You are now identified.")); + return; + } + + public: + NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + if (!ircd->certfp) + throw ModuleException("Your IRCd does not support ssl client certificates"); + + Implementation i[] = { I_OnUserNickChange, I_OnFingerprint }; + ModuleManager::Attach(i, this, 2); + + this->AddCommand(NickServ, &commandnscert); + } + + void OnFingerprint(User *u) + { + DoAutoIdentify(u); + } + + void OnUserNickChange(User *u, const Anope::string &oldnick) + { + if (!u->fingerprint.empty()) + DoAutoIdentify(u); + } +}; + +MODULE_INIT(NSCert) diff --git a/modules/core/ns_ghost.cpp b/modules/core/ns_ghost.cpp index 35ffb76c2..dbc11e5f6 100644 --- a/modules/core/ns_ghost.cpp +++ b/modules/core/ns_ghost.cpp @@ -42,7 +42,8 @@ class CommandNSGhost : public Command else if (nick.equals_ci(u->nick)) source.Reply(_("You can't ghost yourself!")); else if ((u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc))) || - (!pass.empty() && enc_check_password(pass, na->nc->pass) == 1)) + (!pass.empty() && enc_check_password(pass, na->nc->pass) == 1) || + (!u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))) { if (!user->IsIdentified() && FindCommand(NickServ, "RECOVER")) source.Reply(_("You may not ghost an unidentified user, use RECOVER instead.")); diff --git a/modules/core/ns_group.cpp b/modules/core/ns_group.cpp index 62fd5f84d..3aa4b6419 100644 --- a/modules/core/ns_group.cpp +++ b/modules/core/ns_group.cpp @@ -16,7 +16,7 @@ class CommandNSGroup : public Command { public: - CommandNSGroup() : Command("GROUP", 2, 2) + CommandNSGroup() : Command("GROUP", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Join a group")); @@ -27,7 +27,7 @@ class CommandNSGroup : public Command User *u = source.u; const Anope::string &nick = params[0]; - Anope::string pass = params[1]; + Anope::string pass = params.size() > 1 ? params[1] : ""; if (readonly) { @@ -78,15 +78,8 @@ class CommandNSGroup : public Command "for more information."), target->nick.c_str(), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); else { - int res = enc_check_password(pass, target->nc->pass); - if (res == -1) - { - Log(LOG_COMMAND, u, this) << "failed group for " << na->nick << " (invalid password)"; - source.Reply(_(PASSWORD_INCORRECT)); - if (bad_password(u)) - return MOD_STOP; - } - else + if ((!pass.empty() && enc_check_password(pass, target->nc->pass)) || + (!u->fingerprint.empty() && target->nc->FindCert(u->fingerprint))) { /* If the nick is already registered, drop it. * If not, check that it is valid. @@ -125,6 +118,17 @@ class CommandNSGroup : public Command check_memos(u); } + else if (pass.empty()) + { + this->OnSyntaxError(source, ""); + } + else + { + Log(LOG_COMMAND, u, this) << "failed group for " << target->nick << " (invalid password)"; + source.Reply(_(PASSWORD_INCORRECT)); + if (bad_password(u)) + return MOD_STOP; + } } return MOD_CONT; } diff --git a/modules/core/ns_identify.cpp b/modules/core/ns_identify.cpp index a15d0a465..742fe986a 100644 --- a/modules/core/ns_identify.cpp +++ b/modules/core/ns_identify.cpp @@ -29,7 +29,7 @@ class CommandNSIdentify : public Command const Anope::string &nick = params.size() == 2 ? params[0] : u->nick; Anope::string pass = params[params.size() - 1]; - NickAlias *na = findnick(nick), *this_na = findnick(u->nick); + NickAlias *na = findnick(nick); if (!na) source.Reply(_(NICK_NOT_REGISTERED)); else if (na->HasFlag(NS_FORBIDDEN)) @@ -59,46 +59,9 @@ class CommandNSIdentify : public Command if (u->IsIdentified()) Log(LOG_COMMAND, u, this) << "to log out of account " << u->Account()->display; - na->last_realname = u->realname; - na->last_seen = Anope::CurTime; - - u->Login(na->nc); - ircdproto->SendAccountLogin(u, u->Account()); - ircdproto->SetAutoIdentificationToken(u); - - if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(NickServ, UMODE_REGISTERED); - - u->UpdateHost(); - - Log(LOG_COMMAND, u, this) << "and identified for account " << u->Account()->display; + Log(LOG_COMMAND, u, this) << "and identified for account " << na->nc->display; source.Reply(_("Password accepted - you are now recognized.")); - if (ircd->vhost) - do_on_id(u); - if (Config->NSModeOnID) - do_setmodes(u); - - FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u)); - - if (Config->NSForceEmail && u->Account()->email.empty()) - { - source.Reply(_("You must now supply an e-mail for your nick.\n" - "This e-mail will allow you to retrieve your password in\n" - "case you forget it.")); - source.Reply(_("Type \002%R%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n" - "Your privacy is respected; this e-mail won't be given to\n" - "any third-party person."), NickServ->nick.c_str()); - } - - if (u->Account()->HasFlag(NI_UNCONFIRMED)) - { - source.Reply(_("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered.")); - time_t time_registered = Anope::CurTime - na->time_registered; - if (Config->NSUnconfirmedExpire > time_registered) - source.Reply(_("Your account will expire, if not confirmed, in %s"), duration(Config->NSUnconfirmedExpire - time_registered).c_str()); - } - - check_memos(u); + u->Identify(na); } } return MOD_CONT; diff --git a/modules/core/ns_recover.cpp b/modules/core/ns_recover.cpp index a994218b8..2118858f5 100644 --- a/modules/core/ns_recover.cpp +++ b/modules/core/ns_recover.cpp @@ -68,7 +68,8 @@ class CommandNSRecover : public Command } else { - if (u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc))) + if (u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc)) || + (!u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))) { u2->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); u2->Collide(na); diff --git a/modules/core/ns_release.cpp b/modules/core/ns_release.cpp index 3468d1119..ff0424577 100644 --- a/modules/core/ns_release.cpp +++ b/modules/core/ns_release.cpp @@ -43,6 +43,7 @@ class CommandNSRelease : public Command if (res == 1) { Log(LOG_COMMAND, u, this) << "released " << na->nick; + na->Release(); source.Reply(_("Services' hold on your nick has been released.")); } else @@ -58,7 +59,8 @@ class CommandNSRelease : public Command } else { - if (u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc))) + if (u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc)) || + (!u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))) { na->Release(); source.Reply(_("Services' hold on your nick has been released.")); diff --git a/modules/core/ns_resetpass.cpp b/modules/core/ns_resetpass.cpp index d7c4029c1..09dea3502 100644 --- a/modules/core/ns_resetpass.cpp +++ b/modules/core/ns_resetpass.cpp @@ -102,30 +102,13 @@ class NSResetPass : public Module na->nc->Shrink("ns_resetpass_code"); na->nc->Shrink("ns_resetpass_time"); - NickAlias *this_na = findnick(u->nick); - - if (this_na && this_na == na) - { - u->UpdateHost(); - na->last_realname = u->realname; - na->last_seen = Anope::CurTime; - u->SetMode(NickServ, UMODE_REGISTERED); - } - - u->Login(na->nc); - ircdproto->SendAccountLogin(u, u->Account()); - ircdproto->SetAutoIdentificationToken(u); + Log(LOG_COMMAND, u, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify to " << na->nick; + na->nc->UnsetFlag(NI_UNCONFIRMED); - FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u)); + u->Identify(na); - Log(LOG_COMMAND, u, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify to " << na->nick; source.Reply(_("You are now identified for your nick. Change your password using \"%R%s SET PASSWORD \002newpassword\002\" now."), Config->s_NickServ.c_str()); - if (ircd->vhost) - do_on_id(u); - if (Config->NSModeOnID) - do_setmodes(u); - check_memos(u); } else return EVENT_CONTINUE; diff --git a/modules/extra/ns_identify_ldap.cpp b/modules/extra/ns_identify_ldap.cpp index 6e01e0103..08b06a18a 100644 --- a/modules/extra/ns_identify_ldap.cpp +++ b/modules/extra/ns_identify_ldap.cpp @@ -42,7 +42,7 @@ class IdentifyInterface : public LDAPInterface, public Command this->requests.erase(it); User *u = *ii->user; - NickAlias *this_na = findnick(u->nick), *na = findnick(ii->account); + NickAlias *na = findnick(ii->account); if (!na) { @@ -60,28 +60,9 @@ class IdentifyInterface : public LDAPInterface, public Command if (u->Account()) Log(LOG_COMMAND, u, this) << "to log out of account " << u->Account()->display; - - na->last_realname = u->realname; - na->last_seen = Anope::CurTime; - - u->Login(na->nc); - ircdproto->SendAccountLogin(u, u->Account()); - ircdproto->SetAutoIdentificationToken(u); - - if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(NickServ, UMODE_REGISTERED); - - u->UpdateHost(); - - Log(LOG_COMMAND, u, this) << "and identified for account " << u->Account()->display << " using LDAP"; + Log(LOG_COMMAND, u, this) << "and identified for account " << na->nc->display << " using LDAP"; u->SendMessage(NickServ, _("Password accepted - you are now recognized.")); - if (ircd->vhost) - do_on_id(u); - if (Config->NSModeOnID) - do_setmodes(u); - - FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u)); - + u->Identify(na); delete ii; } diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index fa714d7b1..68ff578ea 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -36,6 +36,7 @@ IRCDVar myIrcd[] = { 0, /* ts6 */ "$", /* TLD Prefix for Global */ 6, /* Max number of modes we can send per line */ + 0, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index e903bb2a3..4030e40c1 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -36,6 +36,7 @@ IRCDVar myIrcd[] = { 0, /* ts6 */ "$", /* TLD Prefix for Global */ 20, /* Max number of modes we can send per line */ + 0, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index 42e897aa4..ecac4a4f9 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -42,6 +42,7 @@ IRCDVar myIrcd[] = { 1, /* ts6 */ "$", /* TLD Prefix for Global */ 20, /* Max number of modes we can send per line */ + 1, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 5025884ea..40f1a413d 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -42,6 +42,7 @@ IRCDVar myIrcd[] = { 1, /* ts6 */ "$", /* TLD Prefix for Global */ 20, /* Max number of modes we can send per line */ + 1, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp index 7f4f4f9f1..160f74e9c 100644 --- a/modules/protocol/ngircd.cpp +++ b/modules/protocol/ngircd.cpp @@ -35,6 +35,7 @@ IRCDVar myIrcd[] = { 0, /* ts6 */ "$", /* TLD Prefix for Global */ 20, /* Max number of modes we can send per line */ + 0, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index a538479db..edfdfeec4 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -36,6 +36,7 @@ IRCDVar myIrcd[] = { 1, /* ts6 */ "$$", /* TLD Prefix for Global */ 4, /* Max number of modes we can send per line */ + 1, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index ea1c35c83..a5f58057e 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -36,6 +36,7 @@ IRCDVar myIrcd[] = { 1, /* ts6 */ "$$", /* TLD Prefix for Global */ 4, /* Max number of modes we can send per line */ + 0, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/modules/protocol/unreal32.cpp b/modules/protocol/unreal32.cpp index d8351b931..b6e438461 100644 --- a/modules/protocol/unreal32.cpp +++ b/modules/protocol/unreal32.cpp @@ -36,6 +36,7 @@ IRCDVar myIrcd[] = { 0, /* ts6 */ "$", /* TLD Prefix for Global */ 12, /* Max number of modes we can send per line */ + 0, /* IRCd sends a SSL users certificate fingerprint */ } , {NULL} diff --git a/src/nickcore.cpp b/src/nickcore.cpp index 4863d3244..e83d46c47 100644 --- a/src/nickcore.cpp +++ b/src/nickcore.cpp @@ -129,3 +129,42 @@ void NickCore::ClearAccess() FOREACH_MOD(I_OnNickClearAccess, OnNickClearAccess(this)); this->access.clear(); } + +void NickCore::AddCert(const Anope::string &entry) +{ + this->cert.push_back(entry); + FOREACH_MOD(I_OnNickAddCert, OnNickAddCert(this, entry)); +} + +Anope::string NickCore::GetCert(unsigned entry) const +{ + if (this->cert.empty() || entry >= this->cert.size()) + return ""; + return this->cert[entry]; +} + +bool NickCore::FindCert(const Anope::string &entry) +{ + for (unsigned i = 0, end = this->cert.size(); i < end; ++i) + if (this->cert[i] == entry) + return true; + + return false; +} + +void NickCore::EraseCert(const Anope::string &entry) +{ + for (unsigned i = 0, end = this->cert.size(); i < end; ++i) + if (this->cert[i] == entry) + { + FOREACH_MOD(I_OnNickEraseCert, OnNickEraseCert(this, entry)); + this->cert.erase(this->cert.begin() + i); + break; + } +} + +void NickCore::ClearCert() +{ + FOREACH_MOD(I_OnNickClearCert, OnNickClearCert(this)); + this->cert.clear(); +} diff --git a/src/nickserv.cpp b/src/nickserv.cpp index aed4cc973..fb1e52819 100644 --- a/src/nickserv.cpp +++ b/src/nickserv.cpp @@ -185,7 +185,12 @@ int validate_user(User *u) u->Collide(na); return 0; } - + if (!u->IsIdentified() && !u->fingerprint.empty() && na->nc->FindCert(u->fingerprint)) + { + u->SendMessage(NickServ, _("SSL Fingerprint accepted, you are now identified")); + u->Identify(na); + return 1; + } if (!na->nc->HasFlag(NI_SECURE) && u->IsRecognized()) { na->last_seen = Anope::CurTime; diff --git a/src/users.cpp b/src/users.cpp index e343e3ad2..4b6e7368e 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -334,6 +334,63 @@ void User::Collide(NickAlias *na) kill_user(Config->s_NickServ, this, "Services nickname-enforcer kill"); } +/** Identify the user to the Nick + * updates last_seen, logs the user in, + * send messages, checks for mails, set vhost and more + * @param the NickAlias + */ +void User::Identify(NickAlias *na) +{ + if (!na) + { + Log() << "User::Identify() called with NULL pointer"; + return; + } + + if (this->nick.equals_ci(na->nick)) + { + Anope::string last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost(); + na->last_usermask = last_usermask; + na->last_realname = this->realname; + na->last_seen = Anope::CurTime; + } + + this->Login(na->nc); + ircdproto->SendAccountLogin(this, this->Account()); + ircdproto->SetAutoIdentificationToken(this); + + if (na->nc->HasFlag(NI_UNCONFIRMED) == false) + this->SetMode(NickServ, UMODE_REGISTERED); + if (ircd->vhost) + do_on_id(this); + if (Config->NSModeOnID) + do_setmodes(this); + + FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(this)); + + if (Config->NSForceEmail && na->nc->email.empty()) + { + this->SendMessage(NickServ, _("You must now supply an e-mail for your nick.\n" + "This e-mail will allow you to retrieve your password in\n" + "case you forget it.")); + this->SendMessage(NickServ, _("Type \002%R%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n" + "Your privacy is respected; this e-mail won't be given to\n" + "any third-party person."), NickServ->nick.c_str()); + } + + if (na->nc->HasFlag(NI_UNCONFIRMED)) + { + this->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered.")); + time_t time_registered = Anope::CurTime - na->time_registered; + if (Config->NSUnconfirmedExpire > time_registered) + this->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s"), duration(Config->NSUnconfirmedExpire - time_registered).c_str()); + } + + check_memos(this); + +} + + /** Login the user to a NickCore * @param core The account the user is useing */ |