1 /*
2  * atheme-services: A collection of minimalist IRC services
3  * phandler.c: Generic protocol handling routines.
4  *
5  * Copyright (c) 2005-2007 Atheme Project (http://www.atheme.org)
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
12  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
15  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
19  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
20  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21  * POSSIBILITY OF SUCH DAMAGE.
22  */
23 
24 #include "atheme.h"
25 #include "uplink.h"
26 
27 unsigned int(*server_login) (void) = generic_server_login;
28 void (*introduce_nick) (user_t *u) = generic_introduce_nick;
29 void (*wallops_sts) (const char *text) = generic_wallops_sts;
30 void (*join_sts) (channel_t *c, user_t *u, bool isnew, char *modes) = generic_join_sts;
31 void (*chan_lowerts) (channel_t *c, user_t *u) = generic_chan_lowerts;
32 void (*kick) (user_t *source, channel_t *c, user_t *u, const char *reason) = generic_kick;
33 void (*msg) (const char *from, const char *target, const char *fmt, ...) = generic_msg;
34 void (*msg_global_sts) (user_t *from, const char *mask, const char *text) = generic_msg_global_sts;
35 void (*notice_user_sts) (user_t *from, user_t *target, const char *text) = generic_notice_user_sts;
36 void (*notice_global_sts) (user_t *from, const char *mask, const char *text) = generic_notice_global_sts;
37 void (*notice_channel_sts) (user_t *from, channel_t *target, const char *text) = generic_notice_channel_sts;
38 void (*wallchops) (user_t *source, channel_t *target, const char *message) = generic_wallchops;
39 void (*numeric_sts) (server_t *from, int numeric, user_t *target, const char *fmt, ...) = generic_numeric_sts;
40 void (*kill_id_sts) (user_t *killer, const char *id, const char *reason) = generic_kill_id_sts;
41 void (*part_sts) (channel_t *c, user_t *u) = generic_part_sts;
42 void (*kline_sts) (const char *server, const char *user, const char *host, long duration, const char *reason) = generic_kline_sts;
43 void (*unkline_sts) (const char *server, const char *user, const char *host) = generic_unkline_sts;
44 void (*xline_sts) (const char *server, const char *realname, long duration, const char *reason) = generic_xline_sts;
45 void (*unxline_sts) (const char *server, const char *realname) = generic_unxline_sts;
46 void (*qline_sts) (const char *server, const char *mask, long duration, const char *reason) = generic_qline_sts;
47 void (*unqline_sts) (const char *server, const char *mask) = generic_unqline_sts;
48 void (*topic_sts) (channel_t *c, user_t *source, const char *setter, time_t ts, time_t prevts, const char *topic) = generic_topic_sts;
49 void (*mode_sts) (char *sender, channel_t *target, char *modes) = generic_mode_sts;
50 void (*ping_sts) (void) = generic_ping_sts;
51 void (*quit_sts) (user_t *u, const char *reason) = generic_quit_sts;
52 void (*ircd_on_login) (user_t *u, myuser_t *account, const char *wantedhost) = generic_on_login;
53 bool (*ircd_on_logout) (user_t *u, const char *account) = generic_on_logout;
54 void (*jupe) (const char *server, const char *reason) = generic_jupe;
55 void (*sethost_sts) (user_t *source, user_t *target, const char *host) = generic_sethost_sts;
56 void (*fnc_sts) (user_t *source, user_t *u, const char *newnick, int type) = generic_fnc_sts;
57 void (*holdnick_sts)(user_t *source, int duration, const char *nick, myuser_t *account) = generic_holdnick_sts;
58 void (*invite_sts) (user_t *source, user_t *target, channel_t *channel) = generic_invite_sts;
59 void (*svslogin_sts) (char *target, char *nick, char *user, char *host, myuser_t *account) = generic_svslogin_sts;
60 void (*sasl_sts) (char *target, char mode, char *data) = generic_sasl_sts;
61 void (*sasl_mechlist_sts) (const char *mechlist) = generic_sasl_mechlist_sts;
62 mowgli_node_t *(*next_matching_ban)(channel_t *c, user_t *u, int type, mowgli_node_t *first) = generic_next_matching_ban;
63 mowgli_node_t *(*next_matching_host_chanacs)(mychan_t *mc, user_t *u, mowgli_node_t *first) = generic_next_matching_host_chanacs;
64 bool (*is_valid_nick)(const char *nick) = generic_is_valid_nick;
65 bool (*is_valid_host)(const char *host) = generic_is_valid_host;
66 bool (*is_valid_username)(const char *username) = generic_is_valid_username;
67 void (*mlock_sts)(channel_t *c) = generic_mlock_sts;
68 void (*topiclock_sts)(channel_t *c) = generic_topiclock_sts;
69 void (*quarantine_sts)(user_t *source, user_t *victim, long duration, const char *reason) = generic_quarantine_sts;
70 bool (*is_extban)(const char *mask) = generic_is_extban;
71 void (*dline_sts)(const char *server, const char *host, long duration, const char *reason) = generic_dline_sts;
72 void (*undline_sts)(const char *server, const char *host) = generic_undline_sts;
73 
generic_server_login(void)74 unsigned int generic_server_login(void)
75 {
76 	/* Nothing to do here. */
77 	return 0;
78 }
79 
generic_introduce_nick(user_t * u)80 void generic_introduce_nick(user_t *u)
81 {
82 	/* Nothing to do here. */
83 }
84 
generic_wallops_sts(const char * text)85 void generic_wallops_sts(const char *text)
86 {
87 	/* ugly, but some ircds offer no alternative -- jilles */
88 	user_t *u;
89 	mowgli_patricia_iteration_state_t state;
90 	char buf[BUFSIZE];
91 
92 	snprintf(buf, sizeof buf, "*** Notice -- %s", text);
93 	MOWGLI_PATRICIA_FOREACH(u, &state, userlist)
94 	{
95 		if (!is_internal_client(u) && is_ircop(u))
96 			notice_user_sts(NULL, u, buf);
97 	}
98 }
99 
generic_join_sts(channel_t * c,user_t * u,bool isnew,char * modes)100 void generic_join_sts(channel_t *c, user_t *u, bool isnew, char *modes)
101 {
102 	/* We can't do anything here. Bail. */
103 }
104 
generic_chan_lowerts(channel_t * c,user_t * u)105 void generic_chan_lowerts(channel_t *c, user_t *u)
106 {
107 	slog(LG_ERROR, "chan_lowerts() called but not supported!");
108 	join_sts(c, u, true, channel_modes(c, true));
109 }
110 
generic_kick(user_t * source,channel_t * c,user_t * u,const char * reason)111 void generic_kick(user_t *source, channel_t *c, user_t *u, const char *reason)
112 {
113 	/* We can't do anything here. Bail. */
114 }
115 
generic_msg(const char * from,const char * target,const char * fmt,...)116 void generic_msg(const char *from, const char *target, const char *fmt, ...)
117 {
118 	va_list ap;
119 	char buf[BUFSIZE];
120 
121 	va_start(ap, fmt);
122 	if (vsnprintf(buf, sizeof buf, fmt, ap) < 0)
123 	{
124 		va_end(ap);
125 		return;
126 	}
127 	va_end(ap);
128 
129 	slog(LG_INFO, "Cannot send message to %s (%s): don't know how. Load a protocol module perhaps?", target, buf);
130 }
131 
generic_msg_global_sts(user_t * from,const char * mask,const char * text)132 void generic_msg_global_sts(user_t *from, const char *mask, const char *text)
133 {
134 	slog(LG_INFO, "Cannot send global message to %s (%s): don't know how. Load a protocol module perhaps?", mask, text);
135 }
136 
generic_notice_user_sts(user_t * from,user_t * target,const char * text)137 void generic_notice_user_sts(user_t *from, user_t *target, const char *text)
138 {
139 	slog(LG_INFO, "Cannot send notice to %s (%s): don't know how. Load a protocol module perhaps?", target->nick, text);
140 }
141 
generic_notice_global_sts(user_t * from,const char * mask,const char * text)142 void generic_notice_global_sts(user_t *from, const char *mask, const char *text)
143 {
144 	slog(LG_INFO, "Cannot send global notice to %s (%s): don't know how. Load a protocol module perhaps?", mask, text);
145 }
146 
generic_notice_channel_sts(user_t * from,channel_t * target,const char * text)147 void generic_notice_channel_sts(user_t *from, channel_t *target, const char *text)
148 {
149 	slog(LG_INFO, "Cannot send notice to %s (%s): don't know how. Load a protocol module perhaps?", target->name, text);
150 }
151 
generic_wallchops(user_t * sender,channel_t * channel,const char * message)152 void generic_wallchops(user_t *sender, channel_t *channel, const char *message)
153 {
154 	/* ugly, but always works -- jilles */
155 	mowgli_node_t *n;
156 	chanuser_t *cu;
157 
158 	MOWGLI_ITER_FOREACH(n, channel->members.head)
159 	{
160 		cu = (chanuser_t *)n->data;
161 		if (cu->user->server != me.me && cu->modes & CSTATUS_OP)
162 			notice(sender->nick, cu->user->nick, "[@%s] %s", channel->name, message);
163 	}
164 }
165 
generic_numeric_sts(server_t * from,int numeric,user_t * target,const char * fmt,...)166 void generic_numeric_sts(server_t *from, int numeric, user_t *target, const char *fmt, ...)
167 {
168 	va_list va;
169 	char buf[BUFSIZE];
170 
171 	va_start(va, fmt);
172 	if (vsnprintf(buf, sizeof buf, fmt, va) < 0)
173 	{
174 		va_end(va);
175 		return;
176 	}
177 	va_end(va);
178 
179 	sts(":%s %d %s %s", SERVER_NAME(from), numeric, CLIENT_NAME(target), buf);
180 }
181 
generic_kill_id_sts(user_t * killer,const char * id,const char * reason)182 void generic_kill_id_sts(user_t *killer, const char *id, const char *reason)
183 {
184 	/* cant do anything here. bail. */
185 }
186 
generic_part_sts(channel_t * c,user_t * u)187 void generic_part_sts(channel_t *c, user_t *u)
188 {
189 	/* cant do anything here. bail. */
190 }
191 
generic_kline_sts(const char * server,const char * user,const char * host,long duration,const char * reason)192 void generic_kline_sts(const char *server, const char *user, const char *host, long duration, const char *reason)
193 {
194 	/* cant do anything here. bail. */
195 }
196 
generic_unkline_sts(const char * server,const char * user,const char * host)197 void generic_unkline_sts(const char *server, const char *user, const char *host)
198 {
199 	/* cant do anything here. bail. */
200 }
201 
generic_xline_sts(const char * server,const char * realname,long duration,const char * reason)202 void generic_xline_sts(const char *server, const char *realname, long duration, const char *reason)
203 {
204 	/* cant do anything here. bail. */
205 }
206 
generic_unxline_sts(const char * server,const char * realname)207 void generic_unxline_sts(const char *server, const char *realname)
208 {
209 	/* cant do anything here. bail. */
210 }
211 
generic_qline_sts(const char * server,const char * mask,long duration,const char * reason)212 void generic_qline_sts(const char *server, const char *mask, long duration, const char *reason)
213 {
214 	/* cant do anything here. bail. */
215 }
216 
generic_unqline_sts(const char * server,const char * mask)217 void generic_unqline_sts(const char *server, const char *mask)
218 {
219 	/* cant do anything here. bail. */
220 }
221 
generic_dline_sts(const char * server,const char * host,long duration,const char * reason)222 void generic_dline_sts(const char *server, const char *host, long duration, const char *reason)
223 {
224 	/* can't do anything here. bail. */
225 }
226 
generic_undline_sts(const char * server,const char * host)227 void generic_undline_sts(const char *server, const char *host)
228 {
229 	/* can't do anything here. bail. */
230 }
231 
generic_topic_sts(channel_t * c,user_t * source,const char * setter,time_t ts,time_t prevts,const char * topic)232 void generic_topic_sts(channel_t *c, user_t *source, const char *setter, time_t ts, time_t prevts, const char *topic)
233 {
234 	/* cant do anything here. bail. */
235 }
236 
generic_mode_sts(char * sender,channel_t * target,char * modes)237 void generic_mode_sts(char *sender, channel_t *target, char *modes)
238 {
239 	/* cant do anything here. bail. */
240 }
241 
generic_ping_sts(void)242 void generic_ping_sts(void)
243 {
244 	/* cant do anything here. bail. */
245 }
246 
generic_quit_sts(user_t * u,const char * reason)247 void generic_quit_sts(user_t *u, const char *reason)
248 {
249 	/* cant do anything here. bail. */
250 }
251 
generic_on_login(user_t * u,myuser_t * account,const char * wantedhost)252 void generic_on_login(user_t *u, myuser_t *account, const char *wantedhost)
253 {
254 	/* nothing to do here. */
255 }
256 
generic_on_logout(user_t * u,const char * account)257 bool generic_on_logout(user_t *u, const char *account)
258 {
259 	/* nothing to do here. */
260 	return false;
261 }
262 
generic_jupe(const char * server,const char * reason)263 void generic_jupe(const char *server, const char *reason)
264 {
265 	/* nothing to do here. */
266 }
267 
generic_sethost_sts(user_t * source,user_t * target,const char * host)268 void generic_sethost_sts(user_t *source, user_t *target, const char *host)
269 {
270 	/* nothing to do here. */
271 }
272 
generic_fnc_sts(user_t * source,user_t * u,const char * newnick,int type)273 void generic_fnc_sts(user_t *source, user_t *u, const char *newnick, int type)
274 {
275 	if (type == FNC_FORCE) /* XXX this does not work properly */
276 		kill_id_sts(source, CLIENT_NAME(u), "Nickname enforcement");
277 }
278 
generic_holdnick_sts(user_t * source,int duration,const char * nick,myuser_t * account)279 void generic_holdnick_sts(user_t *source, int duration, const char *nick, myuser_t *account)
280 {
281 	/* nothing to do here. */
282 }
283 
generic_invite_sts(user_t * source,user_t * target,channel_t * channel)284 void generic_invite_sts(user_t *source, user_t *target, channel_t *channel)
285 {
286 	/* nothing to do here. */
287 }
288 
generic_svslogin_sts(char * target,char * nick,char * user,char * host,myuser_t * account)289 void generic_svslogin_sts(char *target, char *nick, char *user, char *host, myuser_t *account)
290 {
291 	/* nothing to do here. */
292 }
293 
generic_sasl_sts(char * target,char mode,char * data)294 void generic_sasl_sts(char *target, char mode, char *data)
295 {
296 	/* nothing to do here. */
297 }
298 
generic_sasl_mechlist_sts(const char * mechlist)299 void generic_sasl_mechlist_sts(const char *mechlist)
300 {
301 	/* nothing to do here. */
302 }
303 
generic_next_matching_ban(channel_t * c,user_t * u,int type,mowgli_node_t * first)304 mowgli_node_t *generic_next_matching_ban(channel_t *c, user_t *u, int type, mowgli_node_t *first)
305 {
306 	chanban_t *cb;
307 	mowgli_node_t *n;
308 	char hostbuf[NICKLEN+USERLEN+HOSTLEN];
309 	char cloakbuf[NICKLEN+USERLEN+HOSTLEN];
310 	char realbuf[NICKLEN+USERLEN+HOSTLEN];
311 	char ipbuf[NICKLEN+USERLEN+HOSTLEN];
312 
313 	snprintf(hostbuf, sizeof hostbuf, "%s!%s@%s", u->nick, u->user, u->vhost);
314 	snprintf(cloakbuf, sizeof cloakbuf, "%s!%s@%s", u->nick, u->user, u->chost);
315 	snprintf(realbuf, sizeof realbuf, "%s!%s@%s", u->nick, u->user, u->host);
316 	/* will be nick!user@ if ip unknown, doesn't matter */
317 	snprintf(ipbuf, sizeof ipbuf, "%s!%s@%s", u->nick, u->user, u->ip);
318 	MOWGLI_ITER_FOREACH(n, first)
319 	{
320 		cb = n->data;
321 
322 		if (cb->type == type &&
323 				(!match(cb->mask, hostbuf) || !match(cb->mask, cloakbuf) || !match(cb->mask, realbuf) || !match(cb->mask, ipbuf) || (ircd->flags & IRCD_CIDR_BANS && !match_cidr(cb->mask, ipbuf))))
324 			return n;
325 	}
326 	return NULL;
327 }
328 
generic_next_matching_host_chanacs(mychan_t * mc,user_t * u,mowgli_node_t * first)329 mowgli_node_t *generic_next_matching_host_chanacs(mychan_t *mc, user_t *u, mowgli_node_t *first)
330 {
331 	chanacs_t *ca;
332 	mowgli_node_t *n;
333 	char hostbuf[NICKLEN+USERLEN+HOSTLEN];
334 	char hostbuf2[NICKLEN+USERLEN+HOSTLEN];
335 	char ipbuf[NICKLEN+USERLEN+HOSTLEN];
336 
337 	snprintf(hostbuf, sizeof hostbuf, "%s!%s@%s", u->nick, u->user, u->vhost);
338 	snprintf(hostbuf2, sizeof hostbuf2, "%s!%s@%s", u->nick, u->user, u->chost);
339 	/* will be nick!user@ if ip unknown, doesn't matter */
340 	snprintf(ipbuf, sizeof ipbuf, "%s!%s@%s", u->nick, u->user, u->ip);
341 
342 	MOWGLI_ITER_FOREACH(n, first)
343 	{
344 		ca = n->data;
345 
346 		if (ca->entity != NULL)
347 		       continue;
348 		if (!match(ca->host, hostbuf) || !match(ca->host, hostbuf2) || !match(ca->host, ipbuf) || (ircd->flags & IRCD_CIDR_BANS && !match_cidr(ca->host, ipbuf)))
349 			return n;
350 	}
351 	return NULL;
352 }
353 
generic_is_valid_nick(const char * nick)354 bool generic_is_valid_nick(const char *nick)
355 {
356 	const char *iter = nick;
357 
358 	/* nicknames may not normally begin with a number, due to UID collision */
359 	if (IsDigit(*iter))
360 		return false;
361 	if (*iter == '-')
362 		return false;
363 
364 	for (; *iter != '\0'; iter++)
365 	{
366 		if (!IsNickChar(*iter))
367 			return false;
368 	}
369 
370 	return true;
371 }
372 
generic_is_valid_username(const char * username)373 bool generic_is_valid_username(const char *username)
374 {
375 	const char *iter = username;
376 
377 	for (; *iter != '\0'; iter++)
378 	{
379 		if (!IsUserChar(*iter))
380 			return false;
381 	}
382 
383 	return true;
384 }
385 
generic_is_valid_host(const char * host)386 bool generic_is_valid_host(const char *host)
387 {
388 	/* don't know what to do here */
389 	return true;
390 }
391 
generic_mlock_sts(channel_t * c)392 void generic_mlock_sts(channel_t *c)
393 {
394 	/* nothing to do here. */
395 }
396 
generic_topiclock_sts(channel_t * c)397 void generic_topiclock_sts(channel_t *c)
398 {
399 	/* nothing to do here. */
400 }
401 
generic_quarantine_sts(user_t * source,user_t * victim,long duration,const char * reason)402 void generic_quarantine_sts(user_t *source, user_t *victim, long duration, const char *reason)
403 {
404 	/* nothing to do here */
405 }
406 
generic_is_extban(const char * mask)407 bool generic_is_extban(const char *mask)
408 {
409 	return false;
410 }
411 
412 /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
413  * vim:ts=8
414  * vim:sw=8
415  * vim:noexpandtab
416  */
417