2 * IRC - Internet Relay Chat, ircd/m_svsnick.c
3 * Written by David Herrmann.
11 #include "ircd_alloc.h"
13 #include "ircd_reply.h"
14 #include "ircd_string.h"
15 #include "ircd_features.h"
16 #include "ircd_crypt.h"
32 /* Sends response \r (len: \l) to client \c. */
33 #define webirc_resp(c, r, l) \
34 ssl_send(cli_fd(c), cli_socket(c).ssl, r, l)
36 /* Buffer used in nick replacements. */
37 static char webirc_buf[513];
39 /* Returns 1 if the passwords are the same and 0 if not.
40 * \to_match is the password hash
41 * \passwd is the unhashed password in "$KIND$password" style
43 static unsigned int webirc_pwmatch(const char* to_match, const char* passwd) {
47 crypted = ircd_crypt(to_match, passwd);
50 Debug((DEBUG_NOTICE, "WebIRC: Passwort check: %s = %s", crypted, passwd));
51 res = strcmp(crypted, passwd);
56 /* Checks whether password/host/spoofed host/ip are allowed and returns the corresponding webirc block.
57 * Returns NULL if nothing found.
59 static struct webirc_block *webirc_match(const char *passwd, const char *real_host, const char *real_ip, const char *spoofed_host, const char *spoofed_ip) {
60 struct webirc_block *iter;
61 struct webirc_node *inode;
62 unsigned int matched = 0;
64 if(!GlobalWebIRCConf) {
65 Debug((DEBUG_NOTICE, "WebIRC: no global webirc conf"));
69 iter = GlobalWebIRCConf;
74 /* first check for matching password */
76 /* it's a sorted list an passwords are stored first! */
78 if(inode->type != WEBIRC_PASS) break;
79 Debug((DEBUG_NOTICE, "WebIRC: pass: %s",inode->content));
80 if(webirc_pwmatch(passwd, inode->content)) {
86 } while(inode != iter->list);
88 /* go to next entry */
92 Debug((DEBUG_NOTICE, "WebIRC: Password missmatch"));
94 /* check for matching real-host/ip */
97 /* fast-forward to hosts and then check the hosts */
99 /* everything greater than WEBIRC_HOSTS are the spoofed masks */
100 if(inode->type > WEBIRC_HOST) break;
102 if(inode->type == WEBIRC_HOST) {
104 if(match(inode->content, real_host) == 0 || match(inode->content, real_ip) == 0) {
109 else if(matched) /* do nothing */;
110 else if(match(inode->content, real_host) == 0 || match(inode->content, real_ip) == 0)
115 } while(inode != iter->list);
117 Debug((DEBUG_NOTICE, "WebIRC: host missmatch"));
120 /* check for matching spoofed host/ip */
124 if(inode->type == WEBIRC_SPOOF) {
126 if(match(inode->content, spoofed_host) == 0 || match(inode->content, spoofed_ip) == 0) {
131 else if(matched) /* do nothing */;
132 else if(match(inode->content, spoofed_host) == 0 || match(inode->content, spoofed_ip) == 0)
137 } while(inode != iter->list);
139 Debug((DEBUG_NOTICE, "WebIRC: spoof missmatch"));
142 if(matched) return iter;
144 /* nothing found, try next block */
147 } while(iter != GlobalWebIRCConf);
155 * parv[0] = sender prefix
161 int m_webirc(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) {
162 struct webirc_block *block;
163 struct irc_in_addr addr;
164 const char *con_addr;
165 time_t next_target = 0;
168 const char *nick = (*(cli_name(sptr))) ? cli_name(sptr) : "AUTH";
169 unsigned int auth = (*(cli_name(sptr))) ? 0 : 1;
171 /* servers cannot spoof their ip */
172 if(IsServerPort(sptr)) {
173 /* If a server sends WEBIRC command it's a protocol violation so exit him and do not check FEAT_WEBIRC_REJECT. */
174 IPcheck_connect_fail(sptr);
175 return exit_client(cptr, sptr, &me, "WebIRC not supported on server ports");
178 /* all 4 parameters are required plus the prefix => 5 */
180 return need_more_params(sptr, "WEBIRC");
182 if(strcmp(parv[2], "cgiirc")) {
183 if(feature_bool(FEAT_WEBIRC_REJECT)) {
184 IPcheck_connect_fail(sptr);
185 return exit_client(cptr, sptr, &me, "WebIRC protocol violation (p2).");
188 len = sprintf(webirc_buf, "NOTICE %s :%sWebIRC protocol violation (p2).\r\n", nick, auth ? "*** " : "");
189 webirc_resp(sptr, webirc_buf, len);
190 return 0; /* continue with normal authentication */
194 /* created ip in dotted notation */
195 con_addr = ircd_ntoa(&(cli_ip(sptr)));
196 if(0 == ipmask_parse(parv[4], &addr, NULL)) {
197 if(feature_bool(FEAT_WEBIRC_REJECT)) {
198 IPcheck_connect_fail(sptr);
199 return exit_client(cptr, sptr, &me, "WebIRC protocol violation (p4).");
202 /* bufferoverflow prevented with NICKLEN check above */
203 len = sprintf(webirc_buf, "NOTICE %s :%sWebIRC protocol violation (p4).\r\n", nick, auth ? "*** " : "");
204 webirc_resp(sptr, webirc_buf, len);
205 return 0; /* continue with normal authentication */
209 /* find matching webirc block */
210 block = webirc_match(parv[1], cli_sockhost(sptr), con_addr, parv[3], parv[4]);
212 if(feature_bool(FEAT_WEBIRC_REJECT)) {
213 IPcheck_connect_fail(sptr);
214 return exit_client(cptr, sptr, &me, "WebIRC client rejected, no match found.");
217 len = sprintf(webirc_buf, "NOTICE %s :%sWebIRC spoofing rejected, no match found.\r\n", nick, auth?"*** ":"");
218 webirc_resp(sptr, webirc_buf, len);
219 return 0; /* continue with normal authentication */
223 /* remove the WebIRC ip from the IPcheck entry, we will add the real one later */
224 IPcheck_connect_fail(sptr);
225 IPcheck_disconnect(sptr);
226 ClearIPChecked(sptr);
229 memcpy(cli_real_ip(sptr).in6_16, cli_ip(sptr).in6_16, 16);
230 memcpy(cli_ip(sptr).in6_16, addr.in6_16, 16);
232 /* spoof ip/host strings */
233 ircd_strncpy(cli_real_sock_ip(sptr), cli_sock_ip(sptr), SOCKIPLEN);
234 ircd_strncpy(cli_sock_ip(sptr), parv[4], SOCKIPLEN);
235 ircd_strncpy(cli_real_sockhost(sptr), cli_sockhost(sptr), HOSTLEN);
236 ircd_strncpy(cli_sockhost(sptr), parv[3], HOSTLEN);
237 ircd_strncpy(cli_webirc(sptr), block->name, NICKLEN);
239 /* add the real ip to the IPcheck */
240 if(!IPcheck_local_connect(&cli_ip(sptr), &next_target))
241 return exit_client(cptr, sptr, &me, "Too many connections from your host");
244 /* set WebIRC umode only if enabled */
245 if(feature_bool(FEAT_WEBIRC_UMODE))