Add a login-on-connect module using XQUERY/XRESPONSE. upstream/master
authorMichael Poole <mdpoole@troilus.org>
Fri, 20 Jan 2012 02:29:15 +0000 (21:29 -0500)
committerMichael Poole <mdpoole@troilus.org>
Fri, 20 Jan 2012 02:29:15 +0000 (21:29 -0500)
src/mod-iauth_loc.c [new file with mode: 0644]

diff --git a/src/mod-iauth_loc.c b/src/mod-iauth_loc.c
new file mode 100644 (file)
index 0000000..78668c0
--- /dev/null
@@ -0,0 +1,137 @@
+/* IAuth Login-on-Connect module for srvx 1.x
+ * Copyright 2012 Michael Poole <mdpoole@troilus.org>
+ *
+ * This file is part of srvx.
+ *
+ * srvx is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+
+#include "conf.h"
+#include "log.h"
+#include "nickserv.h"
+
+const char *iauth_loc_module_deps[] = { NULL };
+
+static struct log_type *loc_log;
+
+static struct {
+    struct userNode *debug_bot;
+    struct chanNode *debug_channel;
+} conf;
+
+#if defined(GCC_VARMACROS)
+# define loc_debug(ARGS...) do { if (conf.debug_bot && conf.debug_channel) send_channel_notice(conf.debug_channel, conf.debug_bot, ARGS); } while (0)
+#elif defined(C99_VARMACROS)
+# define loc_debug(...) do { if (conf.debug_bot && conf.debug_channel) send_channel_notice(conf.debug_channel, conf.debug_bot, __VA_ARGS__); } while (0)
+#endif
+
+static void
+iauth_loc_xquery(struct server *source, const char routing[], const char query[])
+{
+    if (!strncmp(query, "LOGIN2 ", strlen("LOGIN2 "))) {
+        /* Make "user" static for better valgrind tests. */
+        static struct userNode user;
+        const char *ip_str, *hostname, *username, *account, *password;
+        struct handle_info *hi = NULL;
+        char *qdup, *saveptr;
+        unsigned int ii;
+        int valid = 0;
+
+        /* Parse the arguments. */
+        qdup = strdup(query + strlen("LOGIN2 "));
+        ip_str   = strtok_r(qdup, " ", &saveptr);
+        hostname = strtok_r(NULL, " ", &saveptr);
+        username = strtok_r(NULL, " ", &saveptr);
+        account  = strtok_r(NULL, " ", &saveptr);
+        password = strtok_r(NULL, " ", &saveptr);
+        if (!password) {
+        login2_bad_syntax:
+            irc_xresponse(source, routing, "NO Bad LOGIN2 syntax");
+            free(qdup);
+            return;
+        }
+
+        /* Set up (the rest of) the fake user. */
+        user.nick = "?";
+        if (!irc_pton(&user.ip, NULL, ip_str))
+            goto login2_bad_syntax;
+        strncpy(user.ident, username, sizeof(user.ident));
+        strncpy(user.hostname, hostname, sizeof(user.hostname));
+
+        /* Check against the account. */
+        hi = get_handle_info(account);
+        if (hi->masks->used == 0)
+            valid = 1;
+        for (ii = 0; ii < hi->masks->used; ++ii) {
+            if (user_matches_glob(&user, hi->masks->list[ii], 0))
+                valid = 1;
+        }
+        if (!checkpass(password, hi ? hi->passwd : ""))
+            valid = 0;
+
+        /* Send our response. */
+        free(qdup);
+        if (valid) {
+            char response[68];
+            snprintf(response, sizeof(response), "OK %s:%lu", hi->handle, hi->registered);
+            irc_xresponse(source, routing, response);
+        } else {
+            irc_xresponse(source, routing, "NO Bad username, account or source");
+        }
+    } /* else unknown or unsupported command */
+}
+
+static void
+iauth_loc_conf_read(void)
+{
+    dict_t node;
+    const char *str1;
+    const char *str2;
+
+
+    node = conf_get_data("modules/blacklist", RECDB_OBJECT);
+    if (node == NULL)
+        return;
+
+    str1 = database_get_data(node, "debug_bot", RECDB_QSTRING);
+    if (str1)
+        conf.debug_bot = GetUserH(str1);
+
+    str1 = database_get_data(node, "debug_channel", RECDB_QSTRING);
+    if (conf.debug_bot && str1) {
+        str2 = database_get_data(node, "debug_channel_modes", RECDB_QSTRING);
+        if (!str2)
+            str2 = "+tinms";
+        conf.debug_channel = AddChannel(str1, now, str2, NULL);
+        AddChannelUser(conf.debug_bot, conf.debug_channel)->modes |= MODE_CHANOP;
+    } else {
+        conf.debug_channel = NULL;
+    }
+}
+
+int
+iauth_loc_init(void)
+{
+    loc_log = log_register_type("iauth_loc", "file:iauth_loc.log");
+    conf_register_reload(iauth_loc_conf_read);
+    reg_xquery_func(iauth_loc_xquery);
+    return 1;
+}
+
+int
+iauth_loc_finalize(void)
+{
+    return 1;
+}