From 47533395802689aaa611256bc0ec56b3a5672098 Mon Sep 17 00:00:00 2001 From: Brandon Turner Date: Mon, 26 Aug 2013 14:08:18 -0500 Subject: [PATCH 1/3] Add ns_goodmail for whitelist NickServ emails This adds support for whitelisting email domains allowed to register nicks with NickServ. It is the opposite of the included badmail module. --- README.md | 6 ++ ns_goodmail.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 ns_goodmail.c diff --git a/README.md b/README.md index 59ce6b8..c1f142e 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,12 @@ encrypted and you want to set SOPER passwords. Generates a random password. +#### ns_goodmail.c + +Maintains a whitelist of email domains that are allowed to +register NickServ nicks. This allows you to say only +\*@example.com email address can register nicks. + #### ns_guestnoreg.c Disallows the registration of nicks beginning with a string diff --git a/ns_goodmail.c b/ns_goodmail.c new file mode 100644 index 0000000..1f9ccad --- /dev/null +++ b/ns_goodmail.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2013 Brandon Turner + * Rights to this code are as documented in doc/LICENSE. + * + * Restrict registration to certain email addresses. + * + */ + +#include "atheme.h" + +DECLARE_MODULE_V1 +( + "contrib/ns_goodmail", false, _modinit, _moddeinit, + PACKAGE_STRING, + "Atheme Development Group " +); + +static void check_registration(hook_user_register_check_t *hdata); +static void ns_cmd_goodmail(sourceinfo_t *si, int parc, char *parv[]); + +static void write_bedb(database_handle_t *db); +static void db_h_be(database_handle_t *db, const char *type); + +command_t ns_goodmail = { "GOODMAIL", N_("Restrict registration to certain email addresses."), PRIV_USER_ADMIN, 3, ns_cmd_goodmail, { .path = "contrib/ns_goodmail" } }; + +struct goodmail_ { + char *mail; + time_t mail_ts; + char *creator; + char *reason; +}; + +typedef struct goodmail_ goodmail_t; + +mowgli_list_t ns_maillist; + +void _modinit(module_t *m) +{ + if (!module_find_published("backend/opensex")) + { + slog(LG_INFO, "Module %s requires use of the OpenSEX database backend, refusing to load.", m->name); + m->mflags = MODTYPE_FAIL; + return; + } + + hook_add_event("user_can_register"); + hook_add_user_can_register(check_registration); + hook_add_db_write(write_bedb); + + db_register_type_handler("BE", db_h_be); + + service_named_bind_command("nickserv", &ns_goodmail); +} + +void _moddeinit(module_unload_intent_t intent) +{ + hook_del_user_can_register(check_registration); + hook_del_db_write(write_bedb); + + db_unregister_type_handler("BE"); + + service_named_unbind_command("nickserv", &ns_goodmail); +} + +static void write_bedb(database_handle_t *db) +{ + mowgli_node_t *n; + + MOWGLI_ITER_FOREACH(n, ns_maillist.head) + { + goodmail_t *l = n->data; + + db_start_row(db, "BE"); + db_write_word(db, l->mail); + db_write_time(db, l->mail_ts); + db_write_word(db, l->creator); + db_write_str(db, l->reason); + db_commit_row(db); + } +} + +static void db_h_be(database_handle_t *db, const char *type) +{ + const char *mail = db_sread_word(db); + time_t mail_ts = db_sread_time(db); + const char *creator = db_sread_word(db); + const char *reason = db_sread_str(db); + + goodmail_t *l = smalloc(sizeof(goodmail_t)); + l->mail = sstrdup(mail); + l->mail_ts = mail_ts; + l->creator = sstrdup(creator); + l->reason = sstrdup(reason); + mowgli_node_add(l, mowgli_node_create(), &ns_maillist); +} +static void check_registration(hook_user_register_check_t *hdata) +{ + mowgli_node_t *n; + goodmail_t *l; + + if (hdata->approved) + return; + + MOWGLI_ITER_FOREACH(n, ns_maillist.head) + { + l = n->data; + + if (!match(l->mail, hdata->email)) + { + return; + } + } + + command_fail(hdata->si, fault_noprivs, "Sorry, we do not accept registrations with email addresses from that domain. Use another address."); + hdata->approved = 1; + slog(LG_INFO, "REGISTER:GOODMAIL: %s to \2%s\2 by \2%s\2", + hdata->account, hdata->email, + hdata->si->su != NULL ? hdata->si->su->nick : get_source_name(hdata->si)); +} + +static void ns_cmd_goodmail(sourceinfo_t *si, int parc, char *parv[]) +{ + char *action = parv[0]; + char *email = parv[1]; + char *reason = parv[2]; + mowgli_node_t *n, *tn; + goodmail_t *l; + + if (!action) + { + command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "goodmail"); + command_fail(si, fault_needmoreparams, _("Syntax: goodmail ADD|DEL|LIST [parameters]")); + return; + } + + if (!strcasecmp("ADD", action)) + { + if (!email || !reason) + { + command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "goodmail"); + command_fail(si, fault_needmoreparams, _("Syntax: goodmail ADD ")); + return; + } + + if (si->smu == NULL) + { + command_fail(si, fault_noprivs, _("You are not logged in.")); + return; + } + + /* search for it */ + MOWGLI_ITER_FOREACH(n, ns_maillist.head) + { + l = n->data; + + if (!irccasecmp(l->mail, email)) + { + command_success_nodata(si, _("Email \2%s\2 has already been whitelisted."), email); + return; + } + } + + l = smalloc(sizeof(goodmail_t)); + l->mail = sstrdup(email); + l->mail_ts = CURRTIME;; + l->creator = sstrdup(get_source_name(si)); + l->reason = sstrdup(reason); + + logcommand(si, CMDLOG_ADMIN, "goodmail:ADD: \2%s\2 (Reason: \2%s\2)", email, reason); + + n = mowgli_node_create(); + mowgli_node_add(l, n, &ns_maillist); + + command_success_nodata(si, _("You have whitelisted email address \2%s\2."), email); + return; + } + else if (!strcasecmp("DEL", action)) + { + if (!email) + { + command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "goodmail"); + command_fail(si, fault_needmoreparams, _("Syntax: goodmail DEL ")); + return; + } + + MOWGLI_ITER_FOREACH_SAFE(n, tn, ns_maillist.head) + { + l = n->data; + + if (!irccasecmp(l->mail, email)) + { + logcommand(si, CMDLOG_ADMIN, "goodmail:DEL: \2%s\2", l->mail); + + mowgli_node_delete(n, &ns_maillist); + + free(l->mail); + free(l->creator); + free(l->reason); + free(l); + + return; + } + } + command_success_nodata(si, _("Email pattern \2%s\2 not found in goodmail database."), email); + return; + } + else if (!strcasecmp("LIST", action)) + { + char buf[BUFSIZE]; + struct tm tm; + + MOWGLI_ITER_FOREACH(n, ns_maillist.head) + { + l = n->data; + + tm = *localtime(&l->mail_ts); + strftime(buf, BUFSIZE, TIME_FORMAT, &tm); + command_success_nodata(si, "Email: \2%s\2, Reason: \2%s\2 (%s - %s)", + l->mail, l->reason, l->creator, buf); + } + command_success_nodata(si, "End of list."); + logcommand(si, CMDLOG_GET, "goodmail:LIST"); + return; + } + else + { + command_fail(si, fault_badparams, STR_INVALID_PARAMS, "goodmail"); + return; + } +} + +/* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs + * vim:ts=8 + * vim:sw=8 + * vim:noexpandtab + */ From 1c580ba787d68840d8b41d679fa56d4c53e539d3 Mon Sep 17 00:00:00 2001 From: Brandon Turner Date: Mon, 26 Aug 2013 14:08:40 -0500 Subject: [PATCH 2/3] Add help text for ns_goodmail module I wasn't sure how to contribute help files to the contrib repo. Feel free to delete this if it doesn't make sense. --- help/default/ns_goodmail | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 help/default/ns_goodmail diff --git a/help/default/ns_goodmail b/help/default/ns_goodmail new file mode 100644 index 0000000..7ecf150 --- /dev/null +++ b/help/default/ns_goodmail @@ -0,0 +1,35 @@ +Help for GOODMAIL: + +GOODMAIL allows you to maintain a whitelist of email addresses that +are allowed to be used to register accounts. Any email not on this +list will not be allowed to be registered. + +These email addresses are saved to the Atheme database and are kept +between services restarts. + +In GOODMAIL ADD, you are able to use glob matching to whitelist email +addresses that match a pattern. + +Syntax: GOODMAIL ADD [reason] + +Examples: + /msg &nick& GOODMAIL ADD jdhore1@gmail.com bar reason + /msg &nick& GOODMAIL ADD *@aol.com bar reason + /msg &nick& GOODMAIL ADD *@*.tk foo reason + +GOODMAIL DEL allows you to remove entries from the list of currently +whitelisted email addresses. + +Syntax: GOODMAIL DEL + +Examples: + /msg &nick& GOODMAIL DEL foo@bar.com + /msg &nick& GOODMAIL DEL *@aol.com + +GOODMAIL LIST allows you to list the currently whitelisted email +addresses. + +Syntax: GOODMAIL LIST + +Examples: + /msg &nick& GOODMAIL LIST From d53ea99f451e2c45096d72d002c0e7036e647464 Mon Sep 17 00:00:00 2001 From: Brandon Turner Date: Mon, 26 Aug 2013 21:04:40 -0500 Subject: [PATCH 3/3] Use GE verb for ns_goodmail database storage --- ns_goodmail.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ns_goodmail.c b/ns_goodmail.c index 1f9ccad..a255a52 100644 --- a/ns_goodmail.c +++ b/ns_goodmail.c @@ -18,8 +18,8 @@ DECLARE_MODULE_V1 static void check_registration(hook_user_register_check_t *hdata); static void ns_cmd_goodmail(sourceinfo_t *si, int parc, char *parv[]); -static void write_bedb(database_handle_t *db); -static void db_h_be(database_handle_t *db, const char *type); +static void write_gedb(database_handle_t *db); +static void db_h_ge(database_handle_t *db, const char *type); command_t ns_goodmail = { "GOODMAIL", N_("Restrict registration to certain email addresses."), PRIV_USER_ADMIN, 3, ns_cmd_goodmail, { .path = "contrib/ns_goodmail" } }; @@ -45,9 +45,9 @@ void _modinit(module_t *m) hook_add_event("user_can_register"); hook_add_user_can_register(check_registration); - hook_add_db_write(write_bedb); + hook_add_db_write(write_gedb); - db_register_type_handler("BE", db_h_be); + db_register_type_handler("GE", db_h_ge); service_named_bind_command("nickserv", &ns_goodmail); } @@ -55,14 +55,14 @@ void _modinit(module_t *m) void _moddeinit(module_unload_intent_t intent) { hook_del_user_can_register(check_registration); - hook_del_db_write(write_bedb); + hook_del_db_write(write_gedb); - db_unregister_type_handler("BE"); + db_unregister_type_handler("GE"); service_named_unbind_command("nickserv", &ns_goodmail); } -static void write_bedb(database_handle_t *db) +static void write_gedb(database_handle_t *db) { mowgli_node_t *n; @@ -70,7 +70,7 @@ static void write_bedb(database_handle_t *db) { goodmail_t *l = n->data; - db_start_row(db, "BE"); + db_start_row(db, "GE"); db_write_word(db, l->mail); db_write_time(db, l->mail_ts); db_write_word(db, l->creator); @@ -79,7 +79,7 @@ static void write_bedb(database_handle_t *db) } } -static void db_h_be(database_handle_t *db, const char *type) +static void db_h_ge(database_handle_t *db, const char *type) { const char *mail = db_sread_word(db); time_t mail_ts = db_sread_time(db);