78668c00bba75509a9e53520b722affe1d23f3fb
[srvx.git] / src / mod-iauth_loc.c
1 /* IAuth Login-on-Connect module for srvx 1.x
2  * Copyright 2012 Michael Poole <mdpoole@troilus.org>
3  *
4  * This file is part of srvx.
5  *
6  * srvx is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with srvx; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
19  */
20
21 #include "conf.h"
22 #include "log.h"
23 #include "nickserv.h"
24
25 const char *iauth_loc_module_deps[] = { NULL };
26
27 static struct log_type *loc_log;
28
29 static struct {
30     struct userNode *debug_bot;
31     struct chanNode *debug_channel;
32 } conf;
33
34 #if defined(GCC_VARMACROS)
35 # define loc_debug(ARGS...) do { if (conf.debug_bot && conf.debug_channel) send_channel_notice(conf.debug_channel, conf.debug_bot, ARGS); } while (0)
36 #elif defined(C99_VARMACROS)
37 # define loc_debug(...) do { if (conf.debug_bot && conf.debug_channel) send_channel_notice(conf.debug_channel, conf.debug_bot, __VA_ARGS__); } while (0)
38 #endif
39
40 static void
41 iauth_loc_xquery(struct server *source, const char routing[], const char query[])
42 {
43     if (!strncmp(query, "LOGIN2 ", strlen("LOGIN2 "))) {
44         /* Make "user" static for better valgrind tests. */
45         static struct userNode user;
46         const char *ip_str, *hostname, *username, *account, *password;
47         struct handle_info *hi = NULL;
48         char *qdup, *saveptr;
49         unsigned int ii;
50         int valid = 0;
51
52         /* Parse the arguments. */
53         qdup = strdup(query + strlen("LOGIN2 "));
54         ip_str   = strtok_r(qdup, " ", &saveptr);
55         hostname = strtok_r(NULL, " ", &saveptr);
56         username = strtok_r(NULL, " ", &saveptr);
57         account  = strtok_r(NULL, " ", &saveptr);
58         password = strtok_r(NULL, " ", &saveptr);
59         if (!password) {
60         login2_bad_syntax:
61             irc_xresponse(source, routing, "NO Bad LOGIN2 syntax");
62             free(qdup);
63             return;
64         }
65
66         /* Set up (the rest of) the fake user. */
67         user.nick = "?";
68         if (!irc_pton(&user.ip, NULL, ip_str))
69             goto login2_bad_syntax;
70         strncpy(user.ident, username, sizeof(user.ident));
71         strncpy(user.hostname, hostname, sizeof(user.hostname));
72
73         /* Check against the account. */
74         hi = get_handle_info(account);
75         if (hi->masks->used == 0)
76             valid = 1;
77         for (ii = 0; ii < hi->masks->used; ++ii) {
78             if (user_matches_glob(&user, hi->masks->list[ii], 0))
79                 valid = 1;
80         }
81         if (!checkpass(password, hi ? hi->passwd : ""))
82             valid = 0;
83
84         /* Send our response. */
85         free(qdup);
86         if (valid) {
87             char response[68];
88             snprintf(response, sizeof(response), "OK %s:%lu", hi->handle, hi->registered);
89             irc_xresponse(source, routing, response);
90         } else {
91             irc_xresponse(source, routing, "NO Bad username, account or source");
92         }
93     } /* else unknown or unsupported command */
94 }
95
96 static void
97 iauth_loc_conf_read(void)
98 {
99     dict_t node;
100     const char *str1;
101     const char *str2;
102
103
104     node = conf_get_data("modules/blacklist", RECDB_OBJECT);
105     if (node == NULL)
106         return;
107
108     str1 = database_get_data(node, "debug_bot", RECDB_QSTRING);
109     if (str1)
110         conf.debug_bot = GetUserH(str1);
111
112     str1 = database_get_data(node, "debug_channel", RECDB_QSTRING);
113     if (conf.debug_bot && str1) {
114         str2 = database_get_data(node, "debug_channel_modes", RECDB_QSTRING);
115         if (!str2)
116             str2 = "+tinms";
117         conf.debug_channel = AddChannel(str1, now, str2, NULL);
118         AddChannelUser(conf.debug_bot, conf.debug_channel)->modes |= MODE_CHANOP;
119     } else {
120         conf.debug_channel = NULL;
121     }
122 }
123
124 int
125 iauth_loc_init(void)
126 {
127     loc_log = log_register_type("iauth_loc", "file:iauth_loc.log");
128     conf_register_reload(iauth_loc_conf_read);
129     reg_xquery_func(iauth_loc_xquery);
130     return 1;
131 }
132
133 int
134 iauth_loc_finalize(void)
135 {
136     return 1;
137 }