diff options
-rw-r--r-- | .github/workflows/ci-linux.yml | 3 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | data/modules.example.conf | 10 | ||||
-rw-r--r-- | modules/extra/m_regex_pcre2.cpp | 93 | ||||
-rw-r--r-- | modules/protocol/hybrid.cpp | 102 | ||||
-rw-r--r-- | modules/webcpanel/pages/nickserv/confirm.cpp | 26 | ||||
-rw-r--r-- | modules/webcpanel/pages/nickserv/confirm.h | 24 | ||||
-rw-r--r-- | modules/webcpanel/templates/default/nickserv/confirm.html | 29 | ||||
-rw-r--r-- | modules/webcpanel/webcpanel.cpp | 9 | ||||
-rw-r--r-- | modules/webcpanel/webcpanel.h | 1 |
10 files changed, 271 insertions, 27 deletions
diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index d53a83f2c..0a27f24b3 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -22,6 +22,7 @@ jobs: libgnutls28-dev \ libldap2-dev \ libmysqlclient-dev \ + libpcre2-dev \ libpcre3-dev \ libsqlite3-dev \ libssl-dev \ @@ -29,7 +30,7 @@ jobs: ninja-build - name: Enable extras run: | - for MODULE in m_ldap.cpp m_ldap_authentication.cpp m_ldap_oper.cpp m_mysql.cpp m_regex_pcre.cpp m_regex_posix.cpp m_regex_tre.cpp m_sql_authentication.cpp m_sql_log.cpp m_sql_oper.cpp m_sqlite.cpp m_ssl_gnutls.cpp m_ssl_openssl.cpp stats + for MODULE in m_ldap.cpp m_ldap_authentication.cpp m_ldap_oper.cpp m_mysql.cpp m_regex_pcre.cpp m_regex_pcre2.cpp m_regex_posix.cpp m_regex_tre.cpp m_sql_authentication.cpp m_sql_log.cpp m_sql_oper.cpp m_sqlite.cpp m_ssl_gnutls.cpp m_ssl_openssl.cpp stats do ln -s ${{ github.workspace }}/modules/extra/$MODULE ${{ github.workspace }}/modules done diff --git a/.gitignore b/.gitignore index b2f62b5cd..03a3a02f5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ modules/m_ldap_authentication.cpp modules/m_ldap_oper.cpp modules/m_mysql.cpp modules/m_regex_pcre.cpp +modules/m_regex_pcre2.cpp modules/m_regex_posix.cpp modules/m_regex_tre.cpp modules/m_sql_authentication.cpp diff --git a/data/modules.example.conf b/data/modules.example.conf index 925bee8ad..f06789e41 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -403,11 +403,19 @@ module { name = "help" } /* * m_regex_pcre [EXTRA] * - * Provides the regex engine regex/pcre, which uses the Perl Compatible Regular Expressions library. + * Provides the regex engine regex/pcre, which uses version 1 of the Perl Compatible Regular + * Expressions library. This can not be loaded at the same time as the m_regex_pcre2 module. */ #module { name = "m_regex_pcre" } /* + * m_regex_pcre2 [EXTRA] + * + * Provides the regex engine regex/pcre, which uses version 2 of the Perl Compatible Regular + * Expressions library. This can not be loaded at the same time as the m_regex_pcre module. +#module { name = "m_regex_pcre2" } + +/* * m_regex_posix [EXTRA] * * Provides the regex engine regex/posix, which uses the POSIX compliant regular expressions. diff --git a/modules/extra/m_regex_pcre2.cpp b/modules/extra/m_regex_pcre2.cpp new file mode 100644 index 000000000..a97f0aa73 --- /dev/null +++ b/modules/extra/m_regex_pcre2.cpp @@ -0,0 +1,93 @@ +/* + * + * (C) 2012-2022 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + */ + +/* RequiredLibraries: pcre2-8 */ +/* RequiredWindowsLibraries: libpcre2-8 */ + +#include "module.h" + +#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> + +class PCRERegex : public Regex +{ + pcre2_code *regex; + + public: + PCRERegex(const Anope::string &expr) : Regex(expr) + { + int errcode; + PCRE2_SIZE erroffset; + this->regex = pcre2_compile(reinterpret_cast<PCRE2_SPTR8>(expr.c_str()), expr.length(), PCRE2_CASELESS, &errcode, &erroffset, NULL); + + if (!this->regex) + { + PCRE2_UCHAR error[128]; + pcre2_get_error_message(errcode, error, sizeof error); + throw RegexException("Error in regex " + expr + " at offset " + stringify(erroffset) + ": " + reinterpret_cast<const char*>(error)); + } + } + + ~PCRERegex() + { + pcre2_code_free(this->regex); + } + + bool Matches(const Anope::string &str) + { + pcre2_match_data *unused = pcre2_match_data_create_from_pattern(this->regex, NULL); + int result = pcre2_match(regex, reinterpret_cast<PCRE2_SPTR8>(str.c_str()), str.length(), 0, 0, unused, NULL); + pcre2_match_data_free(unused); + return result >= 0; + } +}; + +class PCRERegexProvider : public RegexProvider +{ + public: + PCRERegexProvider(Module *creator) : RegexProvider(creator, "regex/pcre") { } + + Regex *Compile(const Anope::string &expression) override + { + return new PCRERegex(expression); + } +}; + +class ModuleRegexPCRE : public Module +{ + PCRERegexProvider pcre_regex_provider; + + public: + ModuleRegexPCRE(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), + pcre_regex_provider(this) + { + this->SetPermanent(true); + } + + ~ModuleRegexPCRE() + { + for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(); it != XLineManager::XLineManagers.end(); ++it) + { + XLineManager *xlm = *it; + const std::vector<XLine *> &xlines = xlm->GetList(); + + for (unsigned int i = 0; i < xlines.size(); ++i) + { + XLine *x = xlines[i]; + + if (x->regex && dynamic_cast<PCRERegex *>(x->regex)) + { + delete x->regex; + x->regex = NULL; + } + } + } + } +}; + +MODULE_INIT(ModuleRegexPCRE) diff --git a/modules/protocol/hybrid.cpp b/modules/protocol/hybrid.cpp index 5046030ba..5fa0dcdc4 100644 --- a/modules/protocol/hybrid.cpp +++ b/modules/protocol/hybrid.cpp @@ -372,6 +372,21 @@ struct IRCDMessageCapab : Message::Capab } }; +struct IRCDMessageCertFP: IRCDMessage +{ + IRCDMessageCertFP(Module *creator) : IRCDMessage(creator, "CERTFP", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + /* 0 */ + /* :0MCAAAAAB CERTFP 4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */ + void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override + { + User *u = source.GetUser(); + + u->fingerprint = params[0]; + FOREACH_MOD(OnFingerprint, (u)); + } +}; + struct IRCDMessageEOB : IRCDMessage { IRCDMessageEOB(Module *creator) : IRCDMessage(creator, "EOB", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } @@ -398,6 +413,32 @@ struct IRCDMessageJoin : Message::Join } }; +struct IRCDMessageMetadata : IRCDMessage +{ + IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + /* 0 1 2 3 */ + /* :0MC METADATA client 0MCAAAAAB certfp :4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */ + void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override + { + if (params[0].equals_cs("client")) + { + User *u = User::Find(params[1]); + if (!u) + { + Log(LOG_DEBUG) << "METADATA for nonexistent user " << params[1]; + return; + } + + if (params[2].equals_cs("certfp")) + { + u->fingerprint = params[3]; + FOREACH_MOD(OnFingerprint, (u)); + } + } + } +}; + struct IRCDMessageMLock : IRCDMessage { IRCDMessageMLock(Module *creator) : IRCDMessage(creator, "MLOCK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } @@ -629,21 +670,6 @@ struct IRCDMessageUID : IRCDMessage } }; -struct IRCDMessageCertFP: IRCDMessage -{ - IRCDMessageCertFP(Module *creator) : IRCDMessage(creator, "CERTFP", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - - /* 0 */ - /* :0MCAAAAAB CERTFP 4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */ - void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override - { - User *u = source.GetUser(); - - u->fingerprint = params[0]; - FOREACH_MOD(OnFingerprint, (u)); - } -}; - class ProtoHybrid : public Module { HybridProto ircd_proto; @@ -671,8 +697,10 @@ class ProtoHybrid : public Module /* Our message handlers */ IRCDMessageBMask message_bmask; IRCDMessageCapab message_capab; + IRCDMessageCertFP message_certfp; IRCDMessageEOB message_eob; IRCDMessageJoin message_join; + IRCDMessageMetadata message_metadata; IRCDMessageMLock message_mlock; IRCDMessageNick message_nick; IRCDMessagePass message_pass; @@ -684,7 +712,6 @@ class ProtoHybrid : public Module IRCDMessageTBurst message_tburst; IRCDMessageTMode message_tmode; IRCDMessageUID message_uid; - IRCDMessageCertFP message_certfp; bool use_server_side_mlock; @@ -749,14 +776,41 @@ class ProtoHybrid : public Module public: ProtoHybrid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR), ircd_proto(this), - message_away(this), message_error(this), message_invite(this), message_kick(this), - message_kill(this), message_mode(this), message_motd(this), message_notice(this), message_part(this), - message_ping(this), message_privmsg(this), message_quit(this), message_squit(this), message_stats(this), - message_time(this), message_topic(this), message_version(this), message_whois(this), - message_bmask(this), message_capab(this), message_eob(this), message_join(this), message_mlock(this), - message_nick(this), message_pass(this), message_pong(this), message_server(this), message_sid(this), - message_sjoin(this), message_svsmode(this), message_tburst(this), message_tmode(this), message_uid(this), - message_certfp(this) + message_away(this), + message_error(this), + message_invite(this), + message_kick(this), + message_kill(this), + message_mode(this), + message_motd(this), + message_notice(this), + message_part(this), + message_ping(this), + message_privmsg(this), + message_quit(this), + message_squit(this), + message_stats(this), + message_time(this), + message_topic(this), + message_version(this), + message_whois(this), + message_bmask(this), + message_capab(this), + message_certfp(this), + message_eob(this), + message_join(this), + message_metadata(this), + message_mlock(this), + message_nick(this), + message_pass(this), + message_pong(this), + message_server(this), + message_sid(this), + message_sjoin(this), + message_svsmode(this), + message_tburst(this), + message_tmode(this), + message_uid(this) { if (Config->GetModule(this)) this->AddModes(); diff --git a/modules/webcpanel/pages/nickserv/confirm.cpp b/modules/webcpanel/pages/nickserv/confirm.cpp new file mode 100644 index 000000000..00d2196a4 --- /dev/null +++ b/modules/webcpanel/pages/nickserv/confirm.cpp @@ -0,0 +1,26 @@ +/* + * (C) 2003-2022 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + */ + +#include "../../webcpanel.h" + +WebCPanel::NickServ::Confirm::Confirm(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u) +{ +} + +bool WebCPanel::NickServ::Confirm::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +{ + + std::vector<Anope::string> params; + params.push_back(message.post_data["code"]); + + WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/confirm", params, replacements); + + TemplateFileServer page("nickserv/confirm.html"); + + page.Serve(server, page_name, client, message, reply, replacements); + return true; +} diff --git a/modules/webcpanel/pages/nickserv/confirm.h b/modules/webcpanel/pages/nickserv/confirm.h new file mode 100644 index 000000000..09b286794 --- /dev/null +++ b/modules/webcpanel/pages/nickserv/confirm.h @@ -0,0 +1,24 @@ +/* + * (C) 2003-2022 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + */ + +namespace WebCPanel +{ + +namespace NickServ +{ + +class Confirm : public WebPanelProtectedPage +{ + public: + Confirm(const Anope::string &cat, const Anope::string &u); + + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override; +}; + +} + +} diff --git a/modules/webcpanel/templates/default/nickserv/confirm.html b/modules/webcpanel/templates/default/nickserv/confirm.html new file mode 100644 index 000000000..66dbe34df --- /dev/null +++ b/modules/webcpanel/templates/default/nickserv/confirm.html @@ -0,0 +1,29 @@ +{INCLUDE header.html} + <div class="panel-heading">Confirm your Email</div> + <div class="panel-body"> + {FOR M IN MESSAGES} + <div class="alert alert-info"> + {M}<br> + </div> + {END FOR} + + <em>You can <strong>CONFIRM</strong> your registration by entering your confirmation code below.</em> + + <hr> + + <h4>Confirm your account</h4> + <form class="form-horizontal" method="post" action="/nickserv/confirm"> + <div class="form-group"> + <label class="control-label col-lg-2" for="confirm">Confirmation Code:</label> + <div class="col-lg-5"> + <input class="form-control" type="text" name="code" id="code" placeholder="Code from Email"> + </div> + </div> + <div class="form-group"> + <div class="col-lg-offset-2 col-lg-5"> + <button type="submit" class="btn btn-primary">Confirm Me!</button> + </div> + </div> + </form> + </div> +{INCLUDE footer.html} diff --git a/modules/webcpanel/webcpanel.cpp b/modules/webcpanel/webcpanel.cpp index 0c608857d..b8fa12ca6 100644 --- a/modules/webcpanel/webcpanel.cpp +++ b/modules/webcpanel/webcpanel.cpp @@ -28,6 +28,7 @@ class ModuleWebCPanel : public Module WebCPanel::NickServ::Cert nickserv_cert; WebCPanel::NickServ::Access nickserv_access; WebCPanel::NickServ::Alist nickserv_alist; + WebCPanel::NickServ::Confirm nickserv_confirm; WebCPanel::ChanServ::Info chanserv_info; WebCPanel::ChanServ::Set chanserv_set; @@ -49,7 +50,7 @@ class ModuleWebCPanel : public Module id(this, "webcpanel_id"), ip(this, "webcpanel_ip"), last_login(this, "webcpanel_last_login"), style_css("style.css", "/static/style.css", "text/css"), logo_png("logo.png", "/static/logo.png", "image/png"), cubes_png("cubes.png", "/static/cubes.png", "image/png"), favicon_ico("favicon.ico", "/favicon.ico", "image/x-icon"), index("/"), logout("/logout"), _register("/register"), confirm("/confirm"), - nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_access("NickServ", "/nickserv/access"), nickserv_alist("NickServ", "/nickserv/alist"), + nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_access("NickServ", "/nickserv/access"), nickserv_alist("NickServ", "/nickserv/alist"), nickserv_confirm("NickServ", "/nickserv/confirm"), chanserv_info("ChanServ", "/chanserv/info"), chanserv_set("ChanServ", "/chanserv/set"), chanserv_access("ChanServ", "/chanserv/access"), chanserv_akick("ChanServ", "/chanserv/akick"), chanserv_modes("ChanServ", "/chanserv/modes"), chanserv_drop("ChanServ", "/chanserv/drop"), memoserv_memos("MemoServ", "/memoserv/memos"), hostserv_request("HostServ", "/hostserv/request"), operserv_akill("OperServ", "/operserv/akill") @@ -107,6 +108,11 @@ class ModuleWebCPanel : public Module s.subsections.push_back(ss); provider->RegisterPage(&this->nickserv_alist); + ss.name = "Confirm"; + ss.url = "/nickserv/confirm"; + s.subsections.push_back(ss); + provider->RegisterPage(&this->nickserv_confirm); + panel.sections.push_back(s); } @@ -214,6 +220,7 @@ class ModuleWebCPanel : public Module provider->UnregisterPage(&this->nickserv_cert); provider->UnregisterPage(&this->nickserv_access); provider->UnregisterPage(&this->nickserv_alist); + provider->UnregisterPage(&this->nickserv_confirm); provider->UnregisterPage(&this->chanserv_info); provider->UnregisterPage(&this->chanserv_set); diff --git a/modules/webcpanel/webcpanel.h b/modules/webcpanel/webcpanel.h index d1ae8317f..d9b8c5549 100644 --- a/modules/webcpanel/webcpanel.h +++ b/modules/webcpanel/webcpanel.h @@ -168,6 +168,7 @@ namespace WebPanel #include "pages/nickserv/cert.h" #include "pages/nickserv/access.h" #include "pages/nickserv/alist.h" +#include "pages/nickserv/confirm.h" #include "pages/chanserv/info.h" #include "pages/chanserv/set.h" |