1 /*
2  * server.c: Things dealing with server connections, etc.
3  *
4  * Written By Michael Sandrof
5  *
6  * Copyright (c) 1990 Michael Sandrof.
7  * Copyright (c) 1991, 1992 Troy Rollo.
8  * Copyright (c) 1992-2018 Matthew R. Green.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "irc.h"
36 IRCII_RCSID("@(#)$eterna: server.c,v 1.249 2021/03/14 18:22:31 mrg Exp $");
37 
38 #ifdef HAVE_SYS_UN_H
39 # include <sys/un.h>
40 
41 int	connect_to_unix(int, u_char *);
42 #endif /* HAVE_SYS_UN_H */
43 
44 #include "server.h"
45 #include "screen.h"
46 #include "ircaux.h"
47 #include "whois.h"
48 #include "lastlog.h"
49 #include "exec.h"
50 #include "window.h"
51 #include "output.h"
52 #include "names.h"
53 #include "parse.h"
54 #include "list.h"
55 #include "newio.h"
56 #include "vars.h"
57 #include "hook.h"
58 #include "icb.h"
59 #include "server.h"
60 #include "notice.h"
61 #include "ssl.h"
62 #include "sl_irc.h"
63 
64 #include <assert.h>
65 
66 /* Server: a structure for the server_list */
67 typedef	struct
68 {
69 	u_char	*name;			/* the name of the server */
70 	u_char	*itsname;		/* the server's idea of its name */
71 	u_char	*password;		/* password for that server */
72 	int	port;			/* port number on that server */
73 	u_char	*proxy_name;		/* HTTP proxy server to use */
74 	int	proxy_port;		/* port number for proxy server */
75 	u_char	*nickname;		/* nickname for this server */
76 	u_char	*away;			/* away message for this server */
77 	int	operator;		/* true if operator */
78 	int	oper_command;		/* true just after an oper() command is
79 					   given.  Used to tell the difference
80 					   between an incorrect password
81 					   generated by an oper() command and
82 					   one generated when connecting to a
83 					   new server */
84 	int	version;		/* the version of the server -
85 					   defined above */
86 	u_char	*version_string;	/* what is says */
87 	int	whois;			/* true if server sends numeric 318 */
88 	int	flags;			/* Various flags */
89 	int	connected;		/* true if connection is assured */
90 	int	write;			/* write descriptor */
91 	int	read;			/* read descriptior */
92 	pid_t	pid;			/* process id of server */
93 	int	eof;			/* eof flag for server */
94 	int	motd;			/* motd flag (used in notice.c) */
95 	int	sent;			/* set if something has been sent,
96 					   used for redirect */
97 	u_char	*buffer;		/* buffer of what dgets() doesn't get */
98 	WhoisQueue *WQ_head;		/* WHOIS Queue head */
99 	WhoisQueue *WQ_tail;		/* WHOIS Queue tail */
100 	WhoisStuff whois_stuff;		/* Whois Queue current collection buf */
101 	WhoInfo *who_info;		/* /who command info */
102 	int	close_serv;		/* Server to close when LOGGED_IN */
103 	CtcpFlood *ctcp_flood;		/* flood info for CTCP */
104 	u_char	*group;			/* ICB group */
105 	u_char	*icbmode;		/* ICB initial mode */
106 	ChannelList *chan_list;		/* list of channels for this server */
107 	void	(*parse_server)(u_char *); /* pointer to parser for this
108 					      server */
109 	int	server_group;		/* group this server belongs to */
110 	int	attempting_to_connect;	/* are we trying to connect this
111 					   server? */
112 	struct	addrinfo *res, *res0;	/* current lookup; for non blocking
113 					   support */
114 	SOCKADDR_STORAGE *localaddr;	/* currently bound local port */
115 	int 	localaddrlen;		/* length of above */
116 	SslInfo	*ssl_info;		/* handle for ssl routines */
117 	server_ssl_level ssl_level;	/* what sort of SSL to do */
118 	void	*server_private;	/* private data per protocol */
119 	server_private_cb_type server_private_cb; /* callback to free
120 					   server_private */
121 }	Server;
122 
123 /* default SSL for IRC connections */
124 static	server_ssl_level irc_ssl_level = SSL_OFF;
125 
126 /* SGroup: a structure for server groups. */
127 typedef struct ser_group_list SGroup;
128 struct ser_group_list
129 {
130 	SGroup	*next;
131 	u_char	*name;
132 	int	number;
133 };
134 
135 static	void	add_to_server_buffer(int, u_char *);
136 static	void	login_to_server(int);
137 static	int	connect_to_server_direct(u_char *, int, u_char *, int);
138 static	int	connect_to_server_process(u_char *, int, u_char *, int);
139 static	void	irc2_login_to_server(int);
140 static	void	server_group_get_connected_next(int);
141 static	int	reconnect_to_server(int, int);
142 static	void	parse_server(u_char *);
143 static	ssl_init_status	server_check_ssl(int);
144 static	void	reestablish_close_server(int, int);
145 
146 /* server_list: the list of servers that the user can connect to,etc */
147 static	Server	*server_list = NULL;
148 
149 /* number_of_servers_count: in the server list */
150 static	int	number_of_servers_count = 0;
151 
152 /* server_group_list:  list of server groups */
153 static	SGroup	*server_group_list = NULL;
154 
155 static	int	primary_server = -1;
156 
157 /*
158  * from_server: server we're currently interested in; set for window
159  * operations or pretending to be on another server.
160  */
161 static	int	from_server = -1;
162 
163 static	int	never_connected_local = 1;	/* true until first connection
164 						 * is made */
165 static	int	connected_to_server_local = 0;	/* true when connection is
166 						 * confirmed */
167 static	int	parsing_server_index = -1;	/* set to the server we last
168 						   got a message from */
169 
170 static	u_char	*default_proxy_name;
171 static	int	default_proxy_port;
172 
173 #define DEFAULT_SERVER_VERSION Server2_8
174 
175 #define DEFAULT_PROXY_PORT	3128
176 
177 /*
178  * close_server: Given an index into the server list, this closes the
179  * connection to the corresponding server.  It does no checking on the
180  * validity of the index.  It also first sends a "QUIT" to the server being
181  * closed
182  */
183 void
close_server(int server_index,u_char * message)184 close_server(int server_index, u_char *message)
185 {
186 	int	i,
187 		min,
188 		max;
189 
190 	Debug(DB_SERVER, "entered. server %d: '%s'", server_index, message);
191 	if (server_index == -1)
192 	{
193 		min = 0;
194 		max = number_of_servers();
195 	}
196 	else
197 	{
198 		min = server_index;
199 		max = server_index + 1;
200 	}
201 	for (i = min; i < max; i++)
202 	{
203 		int	old_server = from_server;
204 
205 		Debug(DB_SERVER, "server %d: '%s'", i, message);
206 		if (server_list[i].flags & CLOSE_PENDING)
207 			continue;
208 
209 		if (i == primary_server)
210 			clean_whois_queue();
211 
212 		from_server = -1;
213 		mark_not_connected(i);
214 		from_server = old_server;
215 
216 		if (server_list[i].server_private)
217 			server_list[i].server_private_cb(
218 				&server_list[i].server_private);
219 
220 		server_list[i].operator = 0;
221 		server_list[i].connected = 0;
222 		server_list[i].buffer = NULL;
223 		server_list[i].flags = SERVER_2_6_2;
224 		if (-1 != server_list[i].write)
225 		{
226 			if (message && *message)
227 			{
228 				u_char	*buffer = NULL;
229 
230 				malloc_snprintf(&buffer, "QUIT :%s\n", message);
231 				/* XXX retval */
232 				ssl_write(server_list[i].ssl_info,
233 					  server_list[i].write, CP(buffer),
234 					  my_strlen(buffer));
235 				new_free(&buffer);
236 			}
237 			new_close(server_list[i].write);
238 			if (server_list[i].write == server_list[i].read)
239 				server_list[i].read = -1;
240 			server_list[i].write = -1;
241 		}
242 
243 		if (server_list[i].ssl_info)
244 		{
245 			dgets_clear_ssl_info(server_list[i].read);
246 			ssl_close_connection(&server_list[i].ssl_info);
247 		}
248 
249 		if (-1 != server_list[i].read)
250 		{
251 			new_close(server_list[i].read);
252 			server_list[i].read = -1;
253 		}
254 		if (-1 != server_list[i].pid)
255 		{
256 			kill(server_list[i].pid, SIGKILL);
257 			server_list[i].pid = (pid_t) -1;
258 		}
259 	}
260 }
261 
262 /*
263  * server_set_bits: Sets the proper bits in the fd_set structure according to
264  * which servers in the server list have currently active read descriptors.
265  */
266 
267 void
server_set_bits(fd_set * rd,fd_set * wd)268 server_set_bits(fd_set *rd, fd_set *wd)
269 {
270 	int	i;
271 
272 	for (i = 0; i < number_of_servers(); i++)
273 	{
274 		if (server_list[i].read != -1)
275 			FD_SET(server_list[i].read, rd);
276 #ifdef NON_BLOCKING_CONNECTS
277 		if (server_list[i].write != -1 &&
278 		    !(server_list[i].flags & (LOGGED_IN|CLOSE_PENDING|CONNECTED)))
279 			FD_SET(server_list[i].write, wd);
280 #endif /* NON_BLOCKING_CONNECTS */
281 	}
282 }
283 
284 static int
reconnect_to_server(int si,int fi)285 reconnect_to_server(int si, int fi)
286 {
287 	return connect_to_server(server_list[si].name, server_list[si].port, server_list[si].nickname, fi);
288 }
289 
290 static void
reestablish_close_server(int server,int old_server)291 reestablish_close_server(int server, int old_server)
292 {
293 	if (server_list[old_server].flags & CLOSE_PENDING)
294 	{
295 		Win_Trav wt;
296 		Window *tmp;
297 
298 		say("Connection to server %s resumed...", server_list[old_server].name);
299 		server_list[server].close_serv = -1;
300 		server_list[old_server].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
301 		server_list[old_server].flags |= LOGGED_IN;
302 		server_list[old_server].connected = 1;
303 		wt.init = 1;
304 		while ((tmp = window_traverse(&wt)))
305 			if (window_get_server(tmp) == server)
306 			{
307 				window_set_server(window_get_refnum(tmp), old_server, WIN_ALL);
308 				break;
309 			}
310 	}
311 	window_check_servers();
312 }
313 
314 /*
315  * do_server: check the given fd_set against the currently open servers in
316  * the server list.  If one have information available to be read, it is read
317  * and and parsed appropriately.  If an EOF is detected from an open server,
318  * one of two things occurs. 1) If the server was the primary server,
319  * get_connected() is called to maintain the connection status of the user.
320  * 2) If the server wasn't a primary server, connect_to_server() is called to
321  * try to keep that connection alive.
322  */
323 void
do_server(fd_set * rd,fd_set * wd)324 do_server(fd_set *rd, fd_set *wd)
325 {
326 	u_char	lbuf[BIG_BUFFER_SIZE];
327 	int	des, j;
328 	static	int	times = 0;
329 	int	old_timeout;
330 	u_char	*close_msg;
331 
332 	for (j = 0; j < number_of_servers(); j++)
333 	{
334 		close_msg = empty_string();
335 #ifdef NON_BLOCKING_CONNECTS
336 		/*
337 		 *	deraadt@theos.com suggests that every fd awaiting connection
338 		 *	should be run at this point.
339 		 */
340 		if ((des = server_list[j].write) != -1 && /*FD_ISSET(des, wd) &&*/
341 		    !(server_list[j].flags & (LOGGED_IN|CONNECTED))) {
342 			SOCKADDR_STORAGE sa;
343 			socklen_t salen = sizeof sa;
344 
345 			if (getpeername(server_list[j].write, (struct sockaddr *) &sa, &salen) != -1)
346 				login_to_server((from_server = j));
347 		}
348 #endif /* NON_BLOCKING_CONNECTS */
349 		if ((des = server_list[j].read) != -1 && FD_ISSET(des, rd))
350 		{
351 			int	junk;
352 			u_char 	*bufptr;
353 			u_char	*s;
354 			int	i = j; /* i is always j? */
355 			int	old_sep = -1;
356 			int	is_icb;
357 			size_t	len;
358 
359 			from_server = i;
360 			is_icb = server_get_version(from_server) == ServerICB;
361 
362 			if (!(server_list[j].flags & LOGGED_IN))
363 			{
364 				/* If we're not logged in, try again, or keep going. */
365 				login_to_server((from_server = j));
366 				if (!(server_list[j].flags & LOGGED_IN))
367 					goto real_continue;
368 			}
369 #if 0
370 			Debug(DB_SERVER, "ssl_info[%d] = %p (des = %d)", j,
371 			      server_list[j].ssl_info, des);
372 #endif
373 
374 			if (is_icb)
375 				old_sep = dgets_set_separator('\0');
376 
377 			old_timeout = dgets_timeout(1);
378 			s = server_list[from_server].buffer;
379 			bufptr = lbuf;
380 			if (s && *s)
381 			{
382 				len = my_strlen(s);
383 				my_strncpy(lbuf, s, len);
384 				bufptr += len;
385 			}
386 			else
387 				len = 0;
388 			if (len >= sizeof(lbuf))
389 				goto buffer_is_full_hack;	/* XXX */
390 			junk = dgets(bufptr, (sizeof(lbuf) - len), des);
391 			(void) dgets_timeout(old_timeout);
392 
393 			switch (junk)
394 			{
395 			case -2:
396 				/* SSL retry */
397 				goto real_continue;
398 			case -1:
399 				add_to_server_buffer(from_server, lbuf);
400 				goto real_continue;
401 			case 0:
402 			{
403 #ifdef NON_BLOCKING_CONNECTS
404 				int	old_serv = server_list[i].close_serv;
405 			/* Get this here before close_server() clears it -Sol */
406 				int	logged_in = server_list[i].flags & LOGGED_IN;
407 #endif /* NON_BLOCKING_CONNECTS */
408 
409 				close_server(i, close_msg);
410 				say("Connection closed from %s: %s", server_list[i].name,
411 					dgets_errno() == -1 ? "Remote end closed connection" : strerror(dgets_errno()));
412 #ifdef NON_BLOCKING_CONNECTS
413 				if (!logged_in && server_list[i].res0)
414 				{
415 					say("Trying next IP address for %s...", server_list[i].name);
416 					if (reconnect_to_server(i, -1)) {
417 						say("Connection to server %s failed...", server_list[i].name);
418 						clean_whois_queue();
419 						window_check_servers();
420 					}
421 					goto real_continue;
422 				}
423 
424 				if (!logged_in && old_serv != -1)
425 				{
426 					if (old_serv == i)	/* a hack?  you bet */
427 						goto a_hack;
428 					reestablish_close_server(i, old_serv);
429 					break;
430 				}
431 a_hack:
432 #endif /* NON_BLOCKING_CONNECTS */
433 				if (i == primary_server)
434 				{
435 					if (server_list[i].eof)
436 					{
437 						say("Unable to connect to server %s",
438 							server_list[i].name);
439 						if (i == number_of_servers() - 1)
440   						{
441 							clean_whois_queue();
442 							window_check_servers();
443 							if (!connected_to_server())
444 								say("Use /SERVER to connect to a server");
445 							times = 0;
446 						}
447 						else
448 							server_group_get_connected_next(i);
449 					}
450 					else
451 					{
452 						if (times++ > 1)
453 						{
454 							clean_whois_queue();
455 							window_check_servers();
456 							if (!connected_to_server())
457 								say("Use /SERVER to connect to a server");
458 							times = 0;
459   						}
460 						else
461 							get_connected(i);
462 					}
463 				}
464 				else if (server_list[i].eof)
465 				{
466 					say("Connection to server %s lost.", server_list[i].name);
467 					clean_whois_queue();
468 					window_check_servers();
469 				}
470 				else
471 				{
472 					if (reconnect_to_server(i, -1)) {
473 						say("Connection to server %s lost.", server_list[i].name);
474 						clean_whois_queue();
475 						window_check_servers();
476 					}
477 				}
478 				server_list[i].eof = 1;
479 				break;
480 			}
481 			default:
482 buffer_is_full_hack:
483 				{
484 					int	old_psi = parsing_server_index;
485 
486 					parsing_server_index = i;
487 					parse_server(lbuf);
488 					new_free(&server_list[i].buffer);
489 					parsing_server_index = old_psi;
490 					break;
491 				}
492 			}
493 real_continue:
494 			from_server = primary_server;
495 			if (is_icb && old_sep != -1)
496 				(void)dgets_set_separator(old_sep);
497 		}
498 	}
499 }
500 
501 /*
502  * find_in_server_list: given a server name, this tries to match it against
503  * names in the server list, returning the index into the list if found, or
504  * -1 if not found
505  */
506 int
find_in_server_list(u_char * server,int port,u_char * nick)507 find_in_server_list(u_char *server, int port, u_char *nick)
508 {
509 	int	i, maybe = -1;
510 	size_t	len;
511 
512 	len = my_strlen(server);
513 	for (i = 0; i < number_of_servers(); i++)
514 	{
515 		if (port && server_list[i].port &&
516 		    port != server_list[i].port)
517 			continue;
518 
519 		if (my_strnicmp(server, server_list[i].name, len) != 0)
520 			continue;
521 
522 		if (nick)
523 		{
524 			if (server_list[i].nickname == NULL)
525 			{
526 				maybe = i;
527 				continue;
528 			}
529 			if (my_stricmp(server_list[i].nickname, nick))
530 				continue;
531 		}
532 		maybe = i;
533 		break;
534 	}
535 	return (maybe);
536 }
537 
538 /*
539  * parse_server_index:  given a string, this checks if it's a number, and if
540  * so checks it validity as a server index.  Otherwise -1 is returned
541  */
542 int
parse_server_index(u_char * str)543 parse_server_index(u_char *str)
544 {
545 	int	i;
546 
547 	if (is_number(str))
548 	{
549 		i = my_atoi(str);
550 		if (i >= 0 && i < number_of_servers())
551 			return i;
552 	}
553 	return -1;
554 }
555 
556 /*
557  * add_to_server_list: adds the given server to the server_list.  If the
558  * server is already in the server list it is not re-added... however, if the
559  * SL_ADD_OVERWRITE flag is true, the port and passwords are updated to the
560  * values passes.  If the server is not on the list, it is added to the end.
561  * In either case, the server is made the current server.
562  */
563 void
add_to_server_list(u_char * server,int port,u_char * proxy_name,int proxy_port,u_char * password,u_char * nick,int group,int type,int flags)564 add_to_server_list(u_char *server, int port, u_char *proxy_name, int proxy_port,
565 		   u_char *password, u_char *nick,
566 		   int group, int type, int flags)
567 {
568 	Debug(DB_SERVER, "server '%s' port %d pass '%s' nick '%s' group %d "
569 			 "type %d flags %x proxy %s:%d", server, port, password,
570 			 nick, group, type, flags,
571 			 proxy_name ? proxy_name : UP("<>"), proxy_port);
572 	if (port == -1)
573 		port = CHOOSE_PORT(type);
574 	if ((from_server = find_in_server_list(server, port, nick)) == -1)
575 	{
576 		from_server = number_of_servers_count++;
577 		if (server_list)
578 			server_list = new_realloc(server_list, number_of_servers_count * sizeof(*server_list));
579 		else
580 			server_list = new_malloc(number_of_servers_count * sizeof(*server_list));
581 		server_list[from_server].name = NULL;
582 		server_list[from_server].proxy_name = NULL;
583 		server_list[from_server].itsname = NULL;
584 		server_list[from_server].password = NULL;
585 		server_list[from_server].away = NULL;
586 		server_list[from_server].version_string = NULL;
587 		server_list[from_server].operator = 0;
588 		server_list[from_server].read = -1;
589 		server_list[from_server].write = -1;
590 		server_list[from_server].pid = -1;
591 		server_list[from_server].whois = 0;
592 		server_list[from_server].flags = SERVER_2_6_2;
593 		server_list[from_server].nickname = NULL;
594 		server_list[from_server].connected = 0;
595 		server_list[from_server].eof = 0;
596 		server_list[from_server].motd = 1;
597 		server_list[from_server].group = NULL;
598 		server_list[from_server].icbmode = NULL;
599 		server_list[from_server].chan_list = NULL;
600 		malloc_strcpy(&server_list[from_server].name, server);
601 		if (password && *password)
602 			malloc_strcpy(&server_list[from_server].password, password);
603 		if (nick && *nick)
604 			malloc_strcpy(&server_list[from_server].nickname, nick);
605 		server_list[from_server].port = port;
606 		if (proxy_name)
607 			malloc_strcpy(&server_list[from_server].proxy_name, proxy_name);
608 		server_list[from_server].proxy_port = proxy_port;
609 		server_list[from_server].WQ_head = NULL;
610 		server_list[from_server].WQ_tail = NULL;
611 		server_list[from_server].whois_stuff.nick = NULL;
612 		server_list[from_server].whois_stuff.user = NULL;
613 		server_list[from_server].whois_stuff.host = NULL;
614 		server_list[from_server].whois_stuff.channel = NULL;
615 		server_list[from_server].whois_stuff.channels = NULL;
616 		server_list[from_server].whois_stuff.name = NULL;
617 		server_list[from_server].whois_stuff.server = NULL;
618 		server_list[from_server].whois_stuff.server_stuff = NULL;
619 		server_list[from_server].whois_stuff.away = NULL;
620 		server_list[from_server].whois_stuff.oper = 0;
621 		server_list[from_server].whois_stuff.chop = 0;
622 		server_list[from_server].whois_stuff.not_on = 0;
623 		server_list[from_server].who_info = alloc_who_info();
624 		server_list[from_server].buffer = NULL;
625 		server_list[from_server].close_serv = -1;
626 		server_list[from_server].localaddr = 0;
627 		server_list[from_server].localaddrlen = 0;
628 		server_list[from_server].ssl_info = NULL;
629 		server_list[from_server].server_private = NULL;
630 		if (flags & SL_ADD_DO_SSL_VERIFY)
631 			server_list[from_server].ssl_level = SSL_VERIFY;
632 		else if (flags & SL_ADD_DO_SSL)
633 			server_list[from_server].ssl_level = SSL_ON;
634 		else
635 			server_list[from_server].ssl_level = SSL_OFF;
636 		switch (type)
637 		{
638 		case ServerICB:
639 			server_list[from_server].parse_server = icb_parse_server;
640 			break;
641 		case -1:
642 			/* default */
643 			if (client_default_is_icb())
644 			{
645 				type = ServerICB;
646 				server_list[from_server].parse_server = icb_parse_server;
647 				break;
648 			}
649 			type = DEFAULT_SERVER_VERSION;
650 			/* FALLTHROUGH */
651 		default:
652 			server_list[from_server].parse_server = irc2_parse_server;
653 		}
654 		server_list[from_server].version = type;
655 
656 		server_list[from_server].ctcp_flood = ctcp_new_flood();
657 
658 		if (group == -1)
659 			server_list[from_server].server_group = 0;
660 		else
661 			server_list[from_server].server_group = group;
662 		server_list[from_server].res = 0;
663 		server_list[from_server].res0 = 0;
664 	}
665 	else
666 	{
667 		if (flags & SL_ADD_OVERWRITE)
668 		{
669 			server_list[from_server].port = port;
670 			if (password)
671 			{
672 				if (*password)
673 					malloc_strcpy(&(server_list[from_server].password), password);
674 				else
675 					new_free(&(server_list[from_server].password));
676 			}
677 			if (nick && *nick)
678 				malloc_strcpy(&(server_list[from_server].nickname), nick);
679 			if (group != -1)
680 				server_list[from_server].server_group = group;
681 		}
682 		if (server_list[from_server].res0)
683 		{
684 			freeaddrinfo(server_list[from_server].res0);
685 			server_list[from_server].res0 = 0;
686 		}
687 		server_list[from_server].res = 0;
688 		if ((int) my_strlen(server) > (int) my_strlen(server_list[from_server].name))
689 			malloc_strcpy(&(server_list[from_server].name), server);
690 	}
691 }
692 
693 void
ctcp_reply_backlog_change(int size)694 ctcp_reply_backlog_change(int size)
695 {
696 	int	i;
697 
698 	if (size <= 0)
699 		size = 1;
700 	for (i = 0; i < number_of_servers(); i++)
701 		ctcp_refresh_flood(server_list[i].ctcp_flood, size);
702 }
703 
704 void
remove_from_server_list(int i)705 remove_from_server_list(int i)
706 {
707 	int	old_server = from_server;
708 
709 	from_server = i;
710 	clean_whois_queue();
711 	from_server = old_server;
712 
713 	close_server(i, NULL);
714 
715 	if (server_list[i].name)
716 		new_free(&server_list[i].name);
717 	if (server_list[i].itsname)
718 		new_free(&server_list[i].itsname);
719 	if (server_list[i].password)
720 		new_free(&server_list[i].password);
721 	if (server_list[i].away)
722 		new_free(&server_list[i].away);
723 	if (server_list[i].version_string)
724 		new_free(&server_list[i].version_string);
725 	if (server_list[i].nickname)
726 		new_free(&server_list[i].nickname);
727 	if (server_list[i].group)
728 		new_free(&server_list[i].group);
729 	if (server_list[i].icbmode)
730 		new_free(&server_list[i].icbmode);
731 	if (server_list[i].whois_stuff.nick)
732 		new_free(&server_list[i].whois_stuff.nick);
733 	if (server_list[i].whois_stuff.user)
734 		new_free(&server_list[i].whois_stuff.user);
735 	if (server_list[i].whois_stuff.host)
736 		new_free(&server_list[i].whois_stuff.host);
737 	if (server_list[i].whois_stuff.channel)
738 		new_free(&server_list[i].whois_stuff.channel);
739 	if (server_list[i].whois_stuff.channels)
740 		new_free(&server_list[i].whois_stuff.channels);
741 	if (server_list[i].whois_stuff.name)
742 		new_free(&server_list[i].whois_stuff.name);
743 	if (server_list[i].whois_stuff.server)
744 		new_free(&server_list[i].whois_stuff.server);
745 	if (server_list[i].whois_stuff.server_stuff)
746 		new_free(&server_list[i].whois_stuff.server_stuff);
747 	if (server_list[i].ctcp_flood)
748 		ctcp_clear_flood(&server_list[i].ctcp_flood);
749 	if (server_list[i].res0)
750 		freeaddrinfo(server_list[i].res0);
751 
752 	/* update all the structs with server in them */
753 	window_server_delete(i);
754 	channel_server_delete(i);	/* fix `higher' servers */
755 	clear_channel_list(i);
756 	exec_server_delete(i);
757 	if (i < primary_server)
758 		--primary_server;
759 	if (i < from_server)
760 		--from_server;
761 
762 	memmove(&server_list[i], &server_list[i + 1], (number_of_servers() - i - 1) * sizeof(*server_list));
763 	server_list = new_realloc(server_list, --number_of_servers_count * sizeof(*server_list));
764 
765 	if (from_server >= number_of_servers_count)
766 		from_server = -1;
767 }
768 
769 int
ssl_level_to_sa_flags(server_ssl_level level)770 ssl_level_to_sa_flags(server_ssl_level level)
771 {
772 	assert(level != SSL_UNKNOWN);
773 	if (level == SSL_VERIFY)
774 		return SL_ADD_DO_SSL_VERIFY;
775 	else if (level == SSL_ON)
776 		return SL_ADD_DO_SSL;
777 	return 0;
778 }
779 
780 static void
server_split_proxy_port(u_char * proxy_and_port,u_char ** name,int * port)781 server_split_proxy_port(u_char *proxy_and_port, u_char **name, int *port)
782 {
783 	u_char	*sport;
784 
785 	if ((sport = my_index(proxy_and_port, ':')) == NULL)
786 	{
787 		*port = DEFAULT_PROXY_PORT;
788 	}
789 	else
790 	{
791 		*sport++ = '\0';
792 		*port = my_atoi(sport);
793 	}
794 
795 	*name = proxy_and_port;
796 }
797 
798 /*
799  * parse_server_info:  This parses a single string of the form
800  * "server:portnum:password:nickname[:icbgroup]".  It the points port to the portnum
801  * portion and password to the password portion.  This chews up the original
802  * string, so upon return, name will only point the the name.  If portnum
803  * or password are missing or empty,  their respective returned value will
804  * point to null.  if extra is non NULL, it is set to anything after the
805  * final : after the nickname..
806  *
807  * Note:  this will set *type if it sees the IRC/ or ICB/ at the start of
808  * the "name".  The server group name will be set by prepending ":group:" to
809  * the server, so any of these is valid:
810  *
811  *	:group:server:portnum:...
812  *	ICB/:group:server:portnum:...
813  *	server:portnum:...
814  *	ICB/server:portnum:...
815  *
816  * SSLIRC/ and SSLIRCNOCHECK/ prefixes also enable using an SSL connection
817  * to the server, the latter version does not perform any certificate
818  * verification.
819  *
820  * In addition, the PROXY/proxy.host:port/ and NOPROXY/ prefixes may be
821  * present (currently, only *before* any other prefix.)
822  */
823 void
parse_server_info(u_char ** name,u_char ** port,u_char ** password,u_char ** nick,u_char ** group,u_char ** extra,int * type,server_ssl_level * level,u_char ** proxy_name,int * proxy_port)824 parse_server_info(u_char **name, u_char **port, u_char **password,
825 		  u_char **nick, u_char **group, u_char **extra,
826 		  int *type, server_ssl_level *level,
827 		  u_char **proxy_name, int *proxy_port)
828 {
829 	u_char *ptr, *ename, *savename = NULL;
830 	u_char *epname, *pname;
831 
832 	Debug(DB_SERVER, "got %s", *name);
833 	Debug(DB_PROXY, "got %s port %d", *proxy_name ? *proxy_name : UP("<>"), *proxy_port);
834 	*port = *password = *nick = *extra = NULL;
835 
836 	if (my_strncmp(*name, "PROXY/", 6) == 0)
837 	{
838 		pname = (*name) + 6;
839 		if ((epname = my_index(pname, '/')) == NULL)
840 		{
841 			yell("--- Unable to parse server info: %s", *name);
842 			return;
843 		}
844 		*epname++ = '\0';
845 
846 		server_split_proxy_port(pname, proxy_name, proxy_port);
847 		Debug(DB_PROXY, "set proxy_name %s port %d", *proxy_name, *proxy_port);
848 		*name = epname;
849 	}
850 	else
851 	if (my_strncmp(*name, "NO_PROXY/", 9) == 0)
852 	{
853 		*proxy_port = -1;
854 		*name += 9;
855 	}
856 
857 	if (my_strncmp(*name, "IRC/", 4) == 0)
858 	{
859 		*type = DEFAULT_SERVER_VERSION;
860 		*level = SSL_OFF;
861 		*name += 4;
862 	}
863 	else
864 	if (my_strncmp(*name, "SSLIRC/", 7) == 0)
865 	{
866 		*type = DEFAULT_SERVER_VERSION;
867 		*level = SSL_VERIFY;
868 		*name += 7;
869 	}
870 	else
871 	if (my_strncmp(*name, "SSLIRCNOCHECK/", 14) == 0)
872 	{
873 		*type = DEFAULT_SERVER_VERSION;
874 		*level = SSL_ON;
875 		*name += 14;
876 	}
877 	else
878 	if (my_strncmp(*name, "ICB/", 4) == 0)
879 	{
880 		*type = ServerICB;
881 		*level = SSL_OFF;
882 		*name += 4;
883 	}
884 	else
885 	if (*level == SSL_UNKNOWN)
886 		*level = irc_ssl_level;
887 
888 	/* check for :group: processing */
889 	if (**name == ':')
890 	{
891 		if ((ename = my_index((*name)+1, ':')))
892 		{
893 			*ename = '\0';
894 			if (group)
895 				*group = *name + 1;
896 			*name = ename + 1;	/* now points to empty or : we hope */
897 		}
898 	}
899 
900 	/* check for [i:p:v:6]:port style */
901 	if (**name == '[')
902 	{
903 		if ((ename = my_index((*name)+1, ']')))
904 		{
905 			*ename = '\0';
906 			savename = *name + 1;
907 			*name = ename + 1;	/* now points to empty or : we hope */
908 		}
909 	}
910 
911 	if ((ptr = my_index(*name, ':')) != NULL)
912 	{
913 		*(ptr++) = '\0';
914 		if (my_strlen(ptr) == 0)
915 			*port = NULL;
916 		else
917 		{
918 			*port = ptr;
919 			if ((ptr = my_index(ptr, ':')) != NULL)
920 			{
921 				*(ptr++) = '\0';
922 				if (my_strlen(ptr) == 0)
923 					*password = NULL;
924 				else
925 				{
926 					*password = ptr;
927 					if ((ptr = my_index(ptr, ':'))
928 							!= NULL)
929 					{
930 						*(ptr++) = '\0';
931 						if (!my_strlen(ptr))
932 							*nick = NULL;
933 						else
934 						{
935 							*nick = ptr;
936 							if (extra && (ptr = my_index(ptr, ':'))
937 									!= NULL)
938 							{
939 								*(ptr++) = '\0';
940 								if (!my_strlen(ptr))
941 									*extra = NULL;
942 								else
943 									*extra = ptr;
944 							}
945 						}
946 					}
947 				}
948 			}
949 		}
950 	}
951 	if (savename)
952 		*name = savename;
953 	Debug(DB_PROXY, "got %s port %d", *proxy_name ? *proxy_name : UP("<>"), *proxy_port);
954 }
955 
956 /*
957  * build_server_list: given a whitespace separated list of server names this
958  * builds a list of those servers using add_to_server_list().  Since
959  * add_to_server_list() is used to added each server specification, this can
960  * be called many many times to add more servers to the server list.  Each
961  * element in the server list case have one of the following forms:
962  *
963  * servername
964  *
965  * servername:port
966  *
967  * servername:port:password
968  *
969  * servername::password
970  *
971  * Note also that this routine mucks around with the server string passed to it,
972  * so make sure this is ok.
973  *
974  * A new format for ICB and more support is:
975  *
976  *	type/<type-specifc-format>
977  *
978  * eg:
979  *	IRC/server:port:pass:nick:#foo:#bar:&baz
980  * means connect to server on port port with pass and nick, and then to join
981  * channels #foo, #bar and &baz.  this is not implemented beyond the nick...
982  *
983  * or
984  *	ICB/[:group:]server:port:pass:nick:group:mode
985  * which is all the things needed at connection startup.  this is done.
986  */
987 void
build_server_list(u_char * servers)988 build_server_list(u_char *servers)
989 {
990 	u_char	*host,
991 		*rest,
992 		*extra,
993 		*mode,
994 		*password = NULL,
995 		*port = NULL,
996 		*group = NULL,
997 		*nick = NULL,
998 		*proxy_name = NULL;
999 	int	port_num,
1000 		proxy_port = 0,
1001 		type = -1;
1002 
1003 	if (servers == NULL)
1004 		return;
1005 	while (servers)
1006 	{
1007 		if ((rest = my_index(servers, '\n')) != NULL)
1008 			*rest++ = '\0';
1009 		while ((host = next_arg(servers, &servers)) != NULL)
1010 		{
1011 			server_ssl_level level = SSL_UNKNOWN;
1012 
1013 			parse_server_info(&host, &port, &password, &nick,
1014 					  &group, &extra, &type, &level,
1015 					  &proxy_name, &proxy_port);
1016 			if (port && *port)
1017 			{
1018 				port_num = my_atoi(port);
1019 				if (!port_num)
1020 					port_num = CHOOSE_PORT(type);
1021 			}
1022 			else
1023 				port_num = CHOOSE_PORT(type);
1024 			if (!nick)
1025 				nick = my_nickname();
1026 
1027 			add_to_server_list(host, port_num, proxy_name, proxy_port,
1028 					   password, nick,
1029 					   find_server_group(group, 1), type,
1030 					   ssl_level_to_sa_flags(level));
1031 			if (extra)
1032 			{
1033 				switch (type)
1034 				{
1035 				case ServerICB:
1036 					if ((mode = my_index(extra, ':')) && mode[1])
1037 						*mode++ = 0;
1038 					else
1039 						mode = NULL;
1040 					server_set_icbgroup(from_server, extra);
1041 					server_set_icbmode(from_server, mode);
1042 					break;
1043 				default:
1044 					break;
1045 					/* nothing yet */
1046 				}
1047 			}
1048 		}
1049 		servers = rest;
1050 	}
1051 }
1052 
1053 /*
1054  * connect_to_server_direct: handles the tcp connection to a server.  If
1055  * successful, the user is disconnected from any previously connected server,
1056  * the new server is added to the server list, and the user is registered on
1057  * the new server.  If connection to the server is not successful,  the
1058  * reason for failure is displayed and the previous server connection is
1059  * resumed uniterrupted.
1060  *
1061  * This version of connect_to_server() connects directly to a server
1062  */
1063 static	int
connect_to_server_direct(u_char * server_name,int port,u_char * nick,int server_index)1064 connect_to_server_direct(u_char *server_name, int port, u_char *nick, int server_index)
1065 {
1066 	int	new_des;
1067 	struct	addrinfo *r = 0, *r0 = 0;
1068 	u_char	*connect_name;
1069 	int	connect_port;
1070 	u_char	*proxy_name = NULL;
1071 	int	proxy_port = 0;
1072 
1073 	if (server_index >= 0)
1074 		server_list[server_index].oper_command = 0;
1075 	errno = 0;
1076 
1077 	connect_name = server_name;
1078 	connect_port = port;
1079 
1080 	/* does this server use a proxy, or is there a non-ignored default? */
1081 	if (server_index >= 0 &&
1082 	    server_index < number_of_servers() &&
1083 	    server_list[server_index].proxy_port != -1)
1084 	{
1085 		if (server_list[server_index].proxy_name)
1086 		{
1087 			connect_name = server_list[server_index].proxy_name;
1088 			connect_port = server_list[server_index].proxy_port;
1089 			proxy_name = connect_name;
1090 			proxy_port = connect_port;
1091 		}
1092 		else if (default_proxy_name)
1093 		{
1094 			connect_name = default_proxy_name;
1095 			connect_port = default_proxy_port;
1096 			proxy_name = connect_name;
1097 			proxy_port = connect_port;
1098 		}
1099 	}
1100 
1101 #ifdef HAVE_SYS_UN_H
1102 	if (*server_name == '/')
1103 		new_des = connect_to_unix(port, server_name);
1104 	else
1105 #endif /* HAVE_SYS_UN_H */
1106 	{
1107 		if (server_index >= 0 &&
1108 		    server_list[server_index].res &&
1109 		    server_list[server_index].res0)
1110 		{
1111 			new_des = connect_by_number(connect_port, connect_name,
1112 					1, &server_list[server_index].res,
1113 					&server_list[server_index].res0);
1114 		}
1115 		else
1116 		{
1117 			new_des = connect_by_number(connect_port, connect_name,
1118 					1, &r, &r0);
1119 		}
1120 	}
1121 	if (new_des < 0)
1122 	{
1123 		int	error = errno;
1124 
1125 		char *e = NULL;
1126 		switch (new_des)
1127 		{
1128 		default:
1129 		case -2:
1130 			error = 0;
1131 		case -1:
1132 			e = "Unknown host";
1133 			break;
1134 		case -3:
1135 			e = "socket";
1136 			break;
1137 		case -4:
1138 			e = "connect";
1139 			break;
1140 		}
1141 
1142 		if (proxy_name)
1143 			say("Unable to connect to port %d of server %s "
1144 			    "(proxy %s:%d): %s%s%s",
1145 			    port, server_name,
1146 			    proxy_name, proxy_port,
1147 			    e, error ? ": " : "", error ? strerror(error) : "");
1148 		else
1149 			say("Unable to connect to port %d of server %s: %s%s%s",
1150 			    port, server_name,
1151 			    e, error ? ": " : "", error ? strerror(error) : "");
1152 		if (is_server_open(from_server))
1153 			say("Connection to server %s resumed...", server_list[from_server].name);
1154 		return (-1);
1155 	}
1156 
1157 	update_all_status();
1158 	add_to_server_list(server_name, port, proxy_name, proxy_port, NULL,
1159 			   nick, -1, server_get_version(from_server),
1160 			   SL_ADD_OVERWRITE);
1161 
1162 	if (server_list[from_server].localaddr)
1163 		new_free(&server_list[from_server].localaddr);
1164 	server_list[from_server].localaddr = 0;
1165 
1166 #ifdef HAVE_SYS_UN_H
1167 	if (*server_name == '/')
1168 	{
1169 		server_list[from_server].localaddr = 0;
1170 		server_list[from_server].localaddrlen = 0;
1171 	}
1172 	else
1173 #endif /* HAVE_SYS_UN_H */
1174 	{
1175 		SOCKADDR_STORAGE *localaddr = new_malloc(sizeof *localaddr);
1176 		socklen_t address_len = sizeof *localaddr;
1177 
1178 		if (getsockname(new_des, (struct sockaddr *) localaddr, &address_len)
1179 		    >= 0)
1180 		{
1181 			server_list[from_server].localaddr = localaddr;
1182 			server_list[from_server].localaddrlen = address_len;
1183 		}
1184 		else
1185 		{
1186 			close(new_des);
1187 			say("Could not getsockname(): %s", strerror(errno));
1188 			new_free(&localaddr);
1189 			return -1;
1190 		}
1191 	}
1192 	if (port)
1193 	{
1194 		server_list[from_server].read = new_des;
1195 		server_list[from_server].write = new_des;
1196 	}
1197 	else
1198 		server_list[from_server].read = new_des;
1199 	if (!server_list[from_server].res0 && r && r0)
1200 	{
1201 		server_list[from_server].res = r;
1202 		server_list[from_server].res0 = r0;
1203 	}
1204 	else if (r0)
1205 		freeaddrinfo(r0);
1206 
1207 	server_list[from_server].operator = 0;
1208 	return (0);
1209 }
1210 
1211 /*
1212  * connect_to_server_process: handles the tcp connection to a server.  If
1213  * successful, the user is disconnected from any previously connected server,
1214  * the new server is added to the server list, and the user is registered on
1215  * the new server.  If connection to the server is not successful,  the
1216  * reason for failure is displayed and the previous server connection is
1217  * resumed uniterrupted.
1218  *
1219  * This version of connect_to_server() uses the ircio process to talk to a
1220  * server
1221  */
1222 static	int
connect_to_server_process(u_char * server_name,int port,u_char * nick,int server_index)1223 connect_to_server_process(u_char *server_name, int port, u_char *nick, int server_index)
1224 {
1225 	int	write_des[2],
1226 		read_des[2],
1227 		pid,
1228 		c;
1229 	u_char	*path,
1230 		*name = NULL,
1231 		*s;
1232 	u_char	buffer[BIG_BUFFER_SIZE];
1233 	int	old_timeout;
1234 
1235 	path = UP(IRCIO_PATH);
1236 	if ((s = my_rindex(path, '/')) != NULL)
1237 		malloc_strcpy(&name, s + 1);
1238 	if (!name)
1239 		name = path;
1240 	if (*path == '\0')
1241 		return (connect_to_server_direct(server_name, port, nick, server_index));
1242 	if (server_index >= 0)
1243 		server_list[server_index].oper_command = 0;
1244 	write_des[0] = -1;
1245 	write_des[1] = -1;
1246 	if (pipe(write_des) || pipe(read_des))
1247 	{
1248 		if (write_des[0] != -1)
1249 		{
1250 			new_close(write_des[0]);
1251 			new_close(write_des[1]);
1252 		}
1253 		say("Couldn't start new process: %s", strerror(errno));
1254 		return (connect_to_server_direct(server_name, port, nick, server_index));
1255 	}
1256 	switch (pid = fork())
1257 	{
1258 	case -1:
1259 		say("Couldn't start new process: %s\n", strerror(errno));
1260 		return (-1);
1261 	case 0:
1262 		(void) MY_SIGNAL(SIGINT, (sigfunc *)SIG_IGN, 0);
1263 		dup2(read_des[1], 1);
1264 		dup2(write_des[0], 0);
1265 		new_close(read_des[0]);
1266 		new_close(read_des[1]);
1267 		new_close(write_des[0]);
1268 		new_close(write_des[1]);
1269 		snprintf(CP(buffer), sizeof buffer, "%u", port);
1270 		(void)setuid(getuid());
1271 		execl(CP(path), CP(name), server_name, buffer, NULL);
1272 		printf("-5 0\n"); /* -1 - -4 returned by connect_by_number() */
1273 		fflush(stdout);
1274 		_exit(1);
1275 	default:
1276 		new_close(read_des[1]);
1277 		new_close(write_des[0]);
1278 		break;
1279 	}
1280 	old_timeout = dgets_timeout(3);
1281 	c = dgets(buffer, sizeof buffer, read_des[0]);
1282 	(void) dgets_timeout(old_timeout);
1283 	if ((c == 0) || ((c = my_atoi(buffer)) != 0))
1284 	{
1285 		if (c == -5)
1286 			return (connect_to_server_direct(server_name, port, nick, server_index));
1287 		else
1288 		{
1289 			u_char *ptr;
1290 
1291 			if ((ptr = my_index(buffer, ' ')) != NULL)
1292 			{
1293 				ptr++;
1294 				if (my_atoi(ptr) > 0)
1295 		say("Unable to connect to port %d of server %s: %s",
1296 			port, server_name, strerror(my_atoi(ptr)));
1297 				else
1298 		say("Unable to connect to port %d of server %s: Unknown host",
1299 							port, server_name);
1300 			}
1301 			else
1302 		say("Unable to connect to port %d of server %s: Unknown host",
1303 							port, server_name);
1304 			if (is_server_open(from_server))
1305 				say("Connection to server %s resumed...",
1306 						server_list[from_server].name);
1307 			new_close(read_des[0]);
1308 			new_close(write_des[1]);
1309 			return (-1);
1310 		}
1311 	}
1312 	update_all_status();
1313 	add_to_server_list(server_name, port, NULL/*proxy*/, 0/*proxy port*/,
1314 			   NULL, nick, -1, server_get_version(from_server),
1315 			   SL_ADD_OVERWRITE);
1316 	server_list[from_server].read = read_des[0];
1317 	server_list[from_server].write = write_des[1];
1318 	server_list[from_server].pid = pid;
1319 	server_list[from_server].operator = 0;
1320 	return (0);
1321 }
1322 
1323 /*
1324  * connect_to_server: Given a name and portnumber, this will attempt to
1325  * connect to that server using either a direct connection or process
1326  * connection, depending on the value of using_ircio().  If connection
1327  * is successful, the proper NICK, USER, and PASS commands are sent to the
1328  * server.  If the c_server parameter is not -1, then the server with that
1329  * index will be closed upon successful connection here. Also, if connection
1330  * is successful, the attempting_to_connect variable is incremented.  This is
1331  * checked in the notice.c routines to make sure that connection was truely
1332  * successful (and not closed immediately by the server).
1333  */
1334 int
connect_to_server(u_char * server_name,int port,u_char * nick,int c_server)1335 connect_to_server(u_char *server_name, int port, u_char *nick, int c_server)
1336 {
1337 	int	server_index;
1338 	SOCKADDR_STORAGE	sa;
1339 	socklen_t salen = sizeof sa;
1340 	int rv;
1341 
1342 	save_message_from();
1343 	message_from(NULL, LOG_CURRENT);
1344 	server_index = find_in_server_list(server_name, port, nick);
1345 	if (server_index < 0)
1346 	{
1347 		yell("connect_to_server: server_index returned -1 from find_in_server_list()");
1348 		yell("aborting!");
1349 		abort();
1350 	}
1351 	server_list[server_index].attempting_to_connect = 1;
1352 	/*
1353 	 * check if the server doesn't exist, or that we're not already
1354 	 * connected to it.  note that "connected" also means logged in.
1355 	 */
1356 	if (!is_server_connected(server_index))
1357 	{
1358 		if (is_server_open(server_index))
1359 			close_server(server_index, empty_string());
1360 		if (port == -1)
1361 			port = server_list[server_index].port;
1362 		if (port == -1)
1363 			port = CHOOSE_PORT(server_list[server_index].version);
1364 		say("Connecting to port %d of server %s", port, server_name);
1365 
1366 		if (!ignore_ircrc())
1367 			load_ircquick();
1368 
1369 		if (using_ircio())
1370 			rv = connect_to_server_process(server_name, port, nick, server_index);
1371 		else
1372 			rv = connect_to_server_direct(server_name, port, nick, server_index);
1373 		if (rv)
1374 		{
1375 			server_list[server_index].attempting_to_connect = 0;
1376 			restore_message_from();
1377 			return -1;
1378 		}
1379 		if ((c_server != -1) && (c_server != from_server))
1380 		{
1381 #ifdef NON_BLOCKING_CONNECTS
1382 #if defined(GKM)
1383 			say("--- server %s will be closed when we connect", server_list[c_server].name);
1384 			if (server_list[c_server].flags & CLOSE_PENDING)
1385 				say("--- why are we flagging this for closing a second time?");
1386 #endif /* GKM */
1387 			server_list[from_server].close_serv = c_server;
1388 			server_list[c_server].flags |= CLOSE_PENDING;
1389 			server_list[c_server].connected = 0;
1390 #else
1391 			close_server(c_server, empty_string());
1392 #endif /* NON_BLOCKING_CONNECTS */
1393 		}
1394 		else
1395 		{
1396 			server_list[from_server].close_serv = -1;
1397 		}
1398 		if (server_list[from_server].nickname == NULL)
1399 			malloc_strcpy(&server_list[from_server].nickname, my_nickname());
1400 		server_list[from_server].flags &= ~LOGGED_IN;
1401 		/*
1402 		 * this used to be an ifndef NON_BLOCKING_CONNECTS .. we want to do this
1403 		 * whenever the connection is valid, it's possible for a connect to be
1404 		 * "immediate".
1405 		 */
1406 		if (is_server_open(from_server) &&
1407 		    (using_ircio() ||
1408 		    getpeername(server_list[from_server].read, (struct sockaddr *) &sa, &salen) != -1))
1409 			login_to_server(from_server);
1410 	}
1411 	else
1412 	{
1413 		if (port == -1)
1414 		{
1415 			if (server_index != -1)
1416 				port = server_list[server_index].port;
1417 			else
1418 				port = CHOOSE_PORT(server_get_version(server_index));
1419 		}
1420 		say("Connected to port %d of server %s", port, server_name);
1421 		from_server = server_index;
1422 		if ((c_server != -1) && (c_server != from_server))
1423 			close_server(c_server, empty_string());
1424 	}
1425 	update_all_status();
1426 	restore_message_from();
1427 	return 0;
1428 }
1429 
1430 static void
login_to_server_nonblocking(int server)1431 login_to_server_nonblocking(int server)
1432 {
1433 #ifdef NON_BLOCKING_CONNECTS
1434 	int	old_serv = server_list[server].close_serv;
1435 
1436 	/* clean up after ourselves */
1437 	if (server_list[server].res0)
1438 	{
1439 		freeaddrinfo(server_list[server].res0);
1440 		server_list[server].res0 = 0;
1441 	}
1442 	server_list[server].res = 0;
1443 	if (old_serv != -1)
1444 	{
1445 #if defined(GKM)
1446 		say("--- closing server %s - changing servers", server_list[server_list[server].close_serv].name);
1447 		if (!(server_list[server_list[server].close_serv].flags & CLOSE_PENDING))
1448 			say("--- uh oh. closing a server that wasn't CLOSE_PENDING");
1449 #endif /* GKM */
1450 		if (server_list[old_serv].flags & CLEAR_PENDING)
1451 			clear_channel_list(old_serv);   /* Channels were
1452 							   transfered -Sol */
1453 		server_list[old_serv].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
1454 		close_server(old_serv, empty_string());
1455 		server_list[server].close_serv = -1;
1456 		/* should we pause here to let the net catch up with us? */
1457 	}
1458 #if defined(GKM)
1459 	else
1460 	{
1461 		say("--- no server to close in login_to_server()");
1462 	}
1463 #endif /* GKM */
1464 #endif /* NON_BLOCKING_CONNECTS */
1465 }
1466 
1467 /*
1468  * Check if we should attempt to initiate an SSL connection or not.
1469  * Returns SSL_INIT_OK if there was no error, either no SSL or SSL
1470  * started OK.  Returns SSL_INIT_FAIL if SSL failed, either to work
1471  * at all or if certificate verification failed.  Returns
1472  * SSL_INIT_PENDING if the connection establishment is still ongoing.
1473  */
1474 static	ssl_init_status
server_check_ssl(int server)1475 server_check_ssl(int server)
1476 {
1477 	ssl_init_status	status;
1478 
1479 	if (server_list[server].ssl_level == SSL_OFF)
1480 		return SSL_INIT_OK;
1481 
1482 	if (server_list[server].flags & SSL_DONE)
1483 		return SSL_INIT_OK;
1484 
1485 	status = ssl_init_connection(server, server_list[server].read,
1486 				     &server_list[server].ssl_info);
1487 	Debug(DB_SERVER, "server = %d; status = %d; set: %p", server, status,
1488 	      server_list[server].ssl_info);
1489 	if (status == SSL_INIT_FAIL)
1490 	{
1491 		if (server_list[server].ssl_level == SSL_OFF)
1492 		{
1493 			yell("SSL off, why did we try to allocate one?");
1494 			Debug(DB_SERVER, "SSL off");
1495 		}
1496 		else
1497 		{
1498 			Debug(DB_SERVER, "ssl_init_connection failed");
1499 			yell("-- SSL init failed; closing server %s",
1500 			     server_list[server].name);
1501 		}
1502 	}
1503 	else if (status == SSL_INIT_OK)
1504 	{
1505 		server_list[server].flags |= SSL_DONE;
1506 		dgets_set_ssl_info(server_list[server].read,
1507 				   server_list[server].ssl_info);
1508 	}
1509 
1510 	return status;
1511 }
1512 
1513 /*
1514  * we're looking for eg:
1515  *
1516  * HTTP/1.1 200 Connection established
1517  * Proxy-Agent: Privoxy/3.0.19
1518  * <blank line>
1519  *
1520  * return values:
1521  *   -1  -  proxy login not completed, retry
1522  *    0  -  proxy login complete
1523  *    1  -  failed some how; close shop.
1524  */
1525 static int
server_check_http_response(int server,u_char * lbuf,size_t buflen)1526 server_check_http_response(int server, u_char *lbuf, size_t buflen)
1527 {
1528 	Debug(DB_PROXY, "server %d: buf \"%s\"", server, lbuf);
1529 	if ((server_list[server].flags & PROXY_REPLY) == 0)
1530 	{
1531 		u_char	*arg, *args = lbuf;
1532 
1533 		arg = next_arg(args, &args);
1534 
1535 		if (arg &&
1536 		    ((my_stricmp(UP("HTTP/1.0"), arg) == 0) ||
1537 		     (my_stricmp(UP("HTTP/1.1"), arg) == 0)))
1538 		{
1539 			arg = next_arg(args, &args);
1540 
1541 			if (my_stricmp(UP("200"), arg) == 0)
1542 			{
1543 				server_list[server].flags |= PROXY_REPLY;
1544 				Debug(DB_PROXY, "got HTTP 200 reply!");
1545 				return -1;
1546 			}
1547 		}
1548 		Debug(DB_PROXY, "did not get HTTP 200 reply.");
1549 		yell("-- proxy reply when we expected 200 was: \"%s\"", lbuf);
1550 		return 1;
1551 	}
1552 	/* be generous */
1553 	if (lbuf[0] == '\0' ||
1554 	    (lbuf[0] == '\n' && lbuf[1] == '\0') ||
1555 	    (lbuf[0] == '\n' && lbuf[1] == '\r' && lbuf[2] == '\0') ||
1556 	    (lbuf[0] == '\r' && lbuf[1] == '\n' && lbuf[2] == '\0'))
1557 	{
1558 		Debug(DB_PROXY, "got empty string, end of http reply! done!");
1559 		return 0;
1560 	}
1561 
1562 	/* probably just a header, we could check? */
1563 	Debug(DB_PROXY, "not empty, keep going.  should be http header.");
1564 	return -1;
1565 }
1566 
1567 static	void
login_to_server(int server)1568 login_to_server(int server)
1569 {
1570 	ssl_init_status status;
1571 	u_char	*proxy_name;
1572 
1573 	Debug(DB_SERVER, "server %d", server);
1574 
1575 	if ((server_list[server].flags & CONNECTED) == 0)
1576 	{
1577 		/*
1578 		 * If we're CONNECTED, we've gone through the non-blocking
1579 		 * connect.  If we're LOGGED_IN, that means that we've sent
1580 		 * the login sequence, and for SSL that means SSL has
1581 		 * successfully initialised.
1582 		 */
1583 		server_list[server].flags |= CONNECTED;
1584 
1585 #ifdef NON_BLOCKING_CONNECTS
1586 		if (using_ircio() == 0)
1587 		{
1588 			set_blocking(server_list[server].read);
1589 			if (server_list[server].read != server_list[server].write)
1590 				set_blocking(server_list[server].write);
1591 		}
1592 #endif /* NON_BLOCKING_CONNECTS */
1593 	}
1594 
1595 	proxy_name = server_get_proxy_name(server, 1);
1596 	if (proxy_name &&
1597 	    (server_list[server].flags & PROXY_CONNECT) == 0)
1598 	{
1599 		u_char	*buf = NULL;
1600 		int	len, rv;
1601 
1602 		malloc_snprintf(&buf, "CONNECT %s:%d HTTP/1.1\nHost:\n\n",
1603 		         server_list[server].name,
1604 		         server_list[server].port);
1605 		len = my_strlen(buf);
1606 		rv = write(server_list[server].write, CP(buf), len);
1607 		new_free(&buf);
1608 		if (rv != len)
1609 		{
1610 			yell("--- proxy login failed.");
1611 			Debug(DB_PROXY, "proxy write failed, closing.");
1612 			goto failed_recover;
1613 		}
1614 
1615 		server_list[server].flags |= PROXY_CONNECT;
1616 		Debug(DB_PROXY, "proxy: send CONNECT %s:%d (from_server = %d)",
1617 		      server_list[server].name, server_list[server].port, from_server);
1618 
1619 		/* XXX need to eat HTTP reply, before doing final login */
1620 		return;
1621 	}
1622 
1623 	/*
1624 	 * if we've sent proxy stuff, but haven't completed it yet, we
1625 	 * need to eat the HTTP reply.
1626 	 */
1627 	if ((server_list[server].flags & PROXY_CONNECT) != 0 &&
1628 	    (server_list[server].flags & PROXY_DONE) == 0)
1629 	{
1630 		u_char	lbuf[BIG_BUFFER_SIZE];
1631 		u_char 	*bufptr;
1632 		u_char	*s;
1633 		int	old_timeout;
1634 		int	junk;
1635 			size_t	len;
1636 
1637 		old_timeout = dgets_timeout(1);
1638 		s = server_list[server].buffer;
1639 		bufptr = lbuf;
1640 		if (s && *s)
1641 		{
1642 			len = my_strlen(s);
1643 			if (len >= sizeof(lbuf))
1644 				goto buffer_is_full_hack;
1645 			my_strncpy(lbuf, s, len);
1646 			bufptr += len;
1647 		}
1648 		else
1649 			len = 0;
1650 		junk = dgets(bufptr, sizeof(lbuf) - len, server_list[server].read);
1651 		(void) dgets_timeout(old_timeout);
1652 
1653 		switch (junk)
1654 		{
1655 		case -2:
1656 			/* shouldn't happen! SSL retry */
1657 			yell("--- proxy http reponse got -2 / SSL retry!?");
1658 			Debug(DB_PROXY, "proxy http reponse got -2 / SSL retry, closing.");
1659 			goto failed_recover;
1660 		case -1:
1661 			Debug(DB_PROXY, "added \"%s\" to the server buffer for proxy.", lbuf);
1662 			add_to_server_buffer(server, lbuf);
1663 			return;
1664 		case 0:
1665 			goto failed_recover;
1666 		default:
1667 buffer_is_full_hack:
1668 			switch (server_check_http_response(server, lbuf, sizeof lbuf))
1669 			{
1670 			case -1:
1671 				Debug(DB_PROXY, "got retry on http response server %d", server);
1672 				return;
1673 			case 0:
1674 				Debug(DB_PROXY, "proxy setup complete, server %d!", server);
1675 				server_list[server].flags |= PROXY_DONE;
1676 				return;
1677 			case 1:
1678 				yell("--- proxy http login failed, closing");
1679 				Debug(DB_PROXY, "proxy http login failed, closing server %d", server);
1680 				goto failed_recover;
1681 			default:
1682 				yell("--- help! this shouldn't happen.  not -1/0/1");
1683 				goto failed_recover;
1684 			}
1685 		}
1686 	}
1687 
1688 	status = server_check_ssl(server);
1689 	if (status == SSL_INIT_PENDING)
1690 	{
1691 		return;
1692 	}
1693 	if (status == SSL_INIT_FAIL)
1694 	{
1695 		int	old_serv;
1696 		int	logged_in;
1697 
1698 		Debug(DB_SERVER, "SSL failed, closing.");
1699 failed_recover:
1700 		old_serv = server_list[server].close_serv;
1701 		logged_in = server_list[server].flags & LOGGED_IN;
1702 
1703 		close_server(server, UP("proxy/SSL Failed."));
1704 		if (!logged_in && old_serv != -1 && old_serv != server)
1705 			reestablish_close_server(server, old_serv);
1706 		return;
1707 	}
1708 	server_list[server].flags |= LOGGED_IN;
1709 	login_to_server_nonblocking(server);
1710 	if (server_get_version(server) == ServerICB)
1711 		icb_login_to_server(server);
1712 	else
1713 		irc2_login_to_server(server);
1714 	window_copy_prev_server(server);
1715 }
1716 
1717 static	void
irc2_login_to_server(int server)1718 irc2_login_to_server(int server)
1719 {
1720 	if (server_get_version(server) == ServerICB)
1721 	{
1722 		yell("--- ICB called irc2_login_to_server???");
1723 		return;
1724 	}
1725 
1726 	if (server_list[server].password)
1727 		send_to_server("PASS %s", server_list[server].password);
1728 	send_to_server("NICK %s", server_list[server].nickname);
1729 	send_to_server("USER %s %s %s :%s", my_username(), irc_umode(),
1730 		server_list[server].name, my_realname());
1731 }
1732 
1733 /*
1734  * get_connected: This function connects the primary server for IRCII.  It
1735  * attempts to connect to the given server.  If this isn't possible, it
1736  * traverses the server list trying to keep the user connected at all cost.
1737  * oldconn is set if this connection is really an old connection being
1738  * resurected (eg. connection to server failed).
1739  */
1740 void
get_connected(int server)1741 get_connected(int server)
1742 {
1743 	int	s,
1744 		ret = -1;
1745 
1746 	if (server_list)
1747 	{
1748 		int	already_connected = 0;
1749 
1750 		if (server == number_of_servers())
1751 			server = 0;
1752 		else if (server < 0)
1753 			server = number_of_servers() - 1;
1754 		s = server;
1755 		if (reconnect_to_server(server, primary_server))
1756 		{
1757 			while (server_list[server].read == -1)
1758 			{
1759 				server++;
1760 				if (server == number_of_servers())
1761 					server = 0;
1762 				if (server == s)
1763 				{
1764 					clean_whois_queue();
1765 					say("Use /SERVER to connect to a server");
1766 					break;
1767 				}
1768 				from_server = server;
1769 				already_connected = is_server_connected(server);
1770 				ret = reconnect_to_server(server, primary_server);
1771 			}
1772 			if (!ret)
1773 				from_server = server;
1774 			else
1775 				from_server = -1;
1776 		}
1777 		if (from_server != -1) {
1778 			int flags;
1779 
1780 			flags = (already_connected ? 0 : WIN_TRANSFER);
1781 			window_set_server(-1, from_server, flags);
1782 		}
1783 	}
1784 	else
1785 	{
1786 		clean_whois_queue();
1787 		say("Use /SERVER to connect to a server");
1788 	}
1789 }
1790 
1791 /*
1792  * read_server_file: reads hostname:portnum:password server information from
1793  * a file and adds this stuff to the server list.  See build_server_list()/
1794  */
1795 int
read_server_file(void)1796 read_server_file(void)
1797 {
1798 	FILE *fp;
1799 	u_char format[11];
1800 	u_char *file_path;
1801 	u_char *free_path = NULL;
1802 	u_char	buffer[FS_BUFFER_SIZE];
1803 
1804 	if ((file_path = my_getenv("IRCSERVERSFILE")) == NULL)
1805 	{
1806 		malloc_strcpy(&free_path, my_irc_lib());
1807 		malloc_strcat(&free_path, UP(SERVERS_FILE));
1808 		file_path = free_path;
1809 	}
1810 	snprintf(CP(format), sizeof format, "%%%ds", (int)sizeof buffer);
1811 	fp = fopen(CP(file_path), "r");
1812 	new_free(&free_path);
1813 	if (NULL != fp)
1814 	{
1815 		while (fscanf(fp, CP(format), buffer) != EOF)
1816 			build_server_list(buffer);
1817 		fclose(fp);
1818 		return (0);
1819 	}
1820 	return (1);
1821 }
1822 
1823 /* display_server_list: just guess what this does */
1824 void
display_server_list(void)1825 display_server_list(void)
1826 {
1827 	int	i;
1828 
1829 	if (from_server >= number_of_servers())
1830 		from_server = -1;
1831 
1832 	if (server_list)
1833 	{
1834 		if (from_server != -1)
1835 			say("Current server: %s %d",
1836 					server_list[from_server].name,
1837 					server_list[from_server].port);
1838 		else
1839 			say("Current server: <None>");
1840 		if (primary_server != -1)
1841 			say("Primary server: %s %d",
1842 				server_list[primary_server].name,
1843 				server_list[primary_server].port);
1844 		else
1845 			say("Primary server: <None>");
1846 		if (client_default_is_icb())
1847 			say("Using ICB connections by default");
1848 		if (default_proxy_name)
1849 			say("Using proxy server: %s port %d by default",
1850 			    default_proxy_name, default_proxy_port);
1851 		say("Server list:");
1852 		for (i = 0; i < number_of_servers(); i++)
1853 		{
1854 			u_char	*proxy_msg = NULL;
1855 			u_char	*icb_msg;
1856 			u_char	*group_msg = NULL;
1857 			u_char	*pname = NULL;
1858 			const u_char	*ssl_val;
1859 			int	pport = 0;
1860 
1861 			switch (server_list[i].ssl_level) {
1862 			case SSL_ON:
1863 				ssl_val = UP(" (with unchecked TLS)");
1864 				break;
1865 			case SSL_VERIFY:
1866 				ssl_val = UP(" (with TLS)");
1867 				break;
1868 			default:
1869 				ssl_val = empty_string();
1870 				break;
1871 			}
1872 
1873 			icb_msg = server_list[i].version == ServerICB ?
1874 				    (u_char *) " (ICB connection)" : empty_string();
1875 			if (server_list[i].server_group)
1876 				malloc_snprintf(&group_msg, " [group: %s]",
1877 				    find_server_group_name(server_list[i].server_group));
1878 			else
1879 				malloc_strcat(&group_msg, empty_string());
1880 
1881 			pport = server_get_proxy_port(i, 0);
1882 			if (pport == -1)
1883 				malloc_snprintf(&proxy_msg, " (no proxy)");
1884 			else if ((pname = server_get_proxy_name(i, 0)))
1885 				malloc_snprintf(&proxy_msg,
1886 					 " (proxy on server %s port %d)",
1887 					 pname, pport);
1888 			else
1889 				malloc_strcat(&proxy_msg, empty_string());
1890 
1891 			if (!server_list[i].nickname)
1892 			{
1893 				say("\t%d) %s %d%s%s%s%s%s", i,
1894 					server_list[i].name,
1895 					server_list[i].port,
1896 					server_list[i].read == -1 ?
1897 					    UP(" (not connected)") : empty_string(),
1898 					group_msg,
1899 					icb_msg,
1900 					proxy_msg,
1901 					ssl_val);
1902 			}
1903 			else
1904 			{
1905 				say("\t%d) %s %d (%s%s)%s%s%s%s", i,
1906 					server_list[i].name,
1907 					server_list[i].port,
1908 					(server_list[i].read == -1) ?
1909 					    UP("was ") : empty_string(),
1910 					server_list[i].nickname,
1911 					group_msg,
1912 					icb_msg,
1913 					proxy_msg,
1914 					ssl_val);
1915 			}
1916 			new_free(&proxy_msg);
1917 			new_free(&group_msg);
1918 #ifdef GKM
1919 			say("\t\tflags: %s%s%s%s%s%s%s",
1920 				server_list[i].flags & SERVER_2_6_2 ? UP("SERVER_2_6_2 ") : empty_string(),
1921 				server_list[i].flags & USER_MODE_I ? UP("USER_MODE_I ") : empty_string(),
1922 				server_list[i].flags & USER_MODE_W ? UP("USER_MODE_W ") : empty_string(),
1923 				server_list[i].flags & USER_MODE_S ? UP("USER_MODE_S ") : empty_string(),
1924 				server_list[i].flags & CLOSE_PENDING ? UP("CLOSE_PENDING ") : empty_string(),
1925 				server_list[i].flags & CLEAR_PENDING ? UP("CLEAR_PENDING ") : empty_string(),
1926 				server_list[i].flags & LOGGED_IN ? UP("LOGGED_IN ") : empty_string() );
1927 			say("\t\tclose_serv=%d, connected=%d, read=%d, eof=%d", server_list[i].close_serv, server_list[i].connected, server_list[i].read, server_list[i].eof);
1928 #endif /* GKM */
1929 		}
1930 	}
1931 	else
1932 		say("The server list is empty");
1933 }
1934 
1935 void
mark_all_away(u_char * command,u_char * message)1936 mark_all_away(u_char *command, u_char *message)
1937 {
1938 	int	old_server;
1939 
1940 	old_server = from_server;
1941 	for (from_server = 0; from_server < number_of_servers(); from_server++)
1942 	{
1943 		if (is_server_connected(from_server))
1944 			send_to_server("%s :%s", command, message);
1945 	}
1946 	from_server = old_server;
1947 }
1948 
1949 
1950 /*
1951  * server_set_password: this sets the password for the server with the given
1952  * index.  If password is null, the password for the given server is returned
1953  */
1954 u_char	*
server_set_password(int server_index,u_char * password)1955 server_set_password(int server_index, u_char *password)
1956 {
1957 
1958 	if (server_list)
1959 	{
1960 		if (password)
1961 			malloc_strcpy(&(server_list[server_index].password), password);
1962 		return (server_list[server_index].password);
1963 	}
1964 	else
1965 		return (NULL);
1966 }
1967 
1968 /*
1969  * ICB support
1970  */
1971 void
server_set_icbgroup(int server_index,u_char * group)1972 server_set_icbgroup(int server_index, u_char *group)
1973 {
1974 
1975 	malloc_strcpy(&server_list[server_index].group, group);
1976 }
1977 
1978 void
server_set_icbmode(int server_index,u_char * mode)1979 server_set_icbmode(int server_index, u_char *mode)
1980 {
1981 
1982 	malloc_strcpy(&server_list[server_index].icbmode, mode);
1983 }
1984 
1985 /*
1986  * server: the /SERVER command. Read the SERVER help page about
1987  */
1988 void
servercmd(u_char * command,u_char * args,u_char * subargs)1989 servercmd(u_char *command, u_char *args, u_char *subargs)
1990 {
1991 	u_char	*server,
1992 		*port,
1993 		*proxy_name = NULL,
1994 		*proxy_port_str = NULL,
1995 		*extra,
1996 		*newmode,
1997 		*password = NULL,
1998 		*nick = NULL,
1999 		*group = NULL;
2000 	int	port_num,
2001 		proxy_port = 0,
2002 		i,
2003 		new_server_flags,
2004 		type = -1;
2005 	server_ssl_level level = SSL_UNKNOWN;
2006 
2007 	if ((server = next_arg(args, &args)) != NULL)
2008 	{
2009 		while (*server == '-')
2010 		{
2011 			size_t	len;
2012 
2013 			/*
2014 			 * old usage of `/server -' handled here.
2015 			 */
2016 			if (*++server == '\0')
2017 			{
2018 				get_connected(primary_server - 1);
2019 				return;
2020 			}
2021 			upper(server);
2022 			len = my_strlen(server);
2023 			/*
2024 			 * just don't return if you want to perform some action in one of
2025 			 * the flag handling sections.
2026 			 */
2027 			if (!my_strncmp(server, "ICB", len))
2028 				type = ServerICB;
2029 			else if (!my_strncmp(server, "IRC", len))
2030 				type = DEFAULT_SERVER_VERSION;
2031 			else if (!my_strncmp(server, "SSL", len))
2032 				level = SSL_VERIFY;
2033 			else if (!my_strncmp(server, "SSLNOCHECK", len))
2034 				level = SSL_ON;
2035 			else if (!my_strncmp(server, "NOSSL", len))
2036 				level = SSL_OFF;
2037 			else if (!my_strncmp(server, "DELETE", len))
2038 			{
2039 				if ((server = next_arg(args, &args)) != NULL)
2040 				{
2041 					if ((i = parse_server_index(server)) == -1)
2042 					{
2043 						if (-1 == (i = find_in_server_list(server, 0, 0)))
2044 						{
2045 							say("No such server in list");
2046 							return;
2047 						}
2048 					}
2049 					if (server_list[i].connected)
2050 					{
2051 						say("Can not delete server that is already open");
2052 						return;
2053 					}
2054 					remove_from_server_list(i);
2055 					return;
2056 				}
2057 				say("Need server number for -DELETE");
2058 				return;
2059 			}
2060 			else if (!my_strncmp(server, "GROUP", len))
2061 			{
2062 				if ((group = next_arg(args, &args)) == NULL)
2063 				{
2064 					say("SERVER -GROUP needs <group> and <server>");
2065 					return;
2066 				}
2067 			}
2068 			else if (!my_strncmp(server, "PROXY", len))
2069 			{
2070 				if ((proxy_name = next_arg(args, &args)) == NULL ||
2071 				    (proxy_port_str = next_arg(args, &args)) == NULL)
2072 				{
2073 					say("SERVER -PROXY needs <proxy> and <host>");
2074 					return;
2075 				}
2076 				proxy_port = my_atoi(proxy_port_str);
2077 			}
2078 			else
2079 			{
2080 				say("SERVER: %s is an unknown flag", server);
2081 				return;
2082 			}
2083 			if ((server = next_arg(args, &args)) == NULL)
2084 			{
2085 				say("SERVER: need a server name");
2086 				return;
2087 			}
2088 		}
2089 
2090 		if (my_index(server, ':') != NULL)
2091 		{
2092 			parse_server_info(&server, &port, &password, &nick,
2093 			    group ? 0 : &group, &extra, &type, &level,
2094 			    &proxy_name, &proxy_port);
2095 			if (!my_strlen(server))
2096 			{
2097 				say("Server name required");
2098 				return;
2099 			}
2100 			if (port && *port) {
2101 				port_num = my_atoi(port);
2102 				if (!port_num)
2103 					port_num = CHOOSE_PORT(type);
2104 			} else
2105 				/* consider port = next_arg() */
2106 				port_num = CHOOSE_PORT(type);
2107 		}
2108 		else
2109 		{
2110 			if ((port = next_arg(args, &args)) != NULL)
2111 			{
2112 				port_num = my_atoi(port);
2113 				if (!port_num)
2114 					port_num = CHOOSE_PORT(type);
2115 				if ((password = next_arg(args, &args)) != NULL)
2116 					nick = next_arg(args, &args);
2117 			}
2118 			else
2119 				port_num = CHOOSE_PORT(type);
2120 
2121 			if (level == SSL_UNKNOWN)
2122 				level = irc_ssl_level;
2123 			extra = NULL;
2124 		}
2125 
2126 		/*
2127 		 * We need to not do this in the case "server" is really a
2128 		 * valid server number.
2129 		 */
2130 		if (parse_server_index(server) == -1)
2131 			add_to_server_list(server, port_num,
2132 					   proxy_name, proxy_port, password,
2133 					   nick, -1, type,
2134 					   ssl_level_to_sa_flags(level));
2135 
2136 		if (group && *group)
2137 			server_list[from_server].server_group = find_server_group(group, 1);
2138 
2139 		if (extra && type == ServerICB)
2140 		{
2141 			if ((newmode = my_index(extra, ':')))
2142 			{
2143 				*newmode++ = 0;
2144 				malloc_strcpy(&(server_list[from_server].icbmode), newmode);
2145 			}
2146 			malloc_strcpy(&(server_list[from_server].group), extra);
2147 		}
2148 
2149 		if (*server == '+' || *server == '=' || *server == '~')
2150 		{
2151 			if (group)
2152 				add_server_to_server_group(
2153 				    window_get_server(curr_scr_win), group);
2154 
2155 			if (*(server+1))
2156 			{
2157 				u_char	servinfo[INPUT_BUFFER_SIZE+1];
2158 
2159 				if (*server == '+')
2160 					server++;
2161 				/* Reconstitute whole server info so
2162 				  window_get_connected can parse it -Sol */
2163 				snprintf(CP(servinfo), sizeof servinfo, "%s:%d:%s:%s",
2164 					server, port_num,
2165 					password ? password : empty_string(),
2166 					nick ? nick : empty_string());
2167 				window_get_connected(curr_scr_win, servinfo,
2168 				    -1, NULL, proxy_name, proxy_port,
2169 				    group, type, level);
2170 			}
2171 			else
2172 				get_connected(primary_server + 1);
2173 			return;
2174 		}
2175 		/*
2176 		 * work in progress.. window_get_prev_server() needs to be set for
2177 		 * all windows that used to be associated with a server as it
2178 		 * switches [successfully] to a new server.
2179 		 * this'll be fun since that can happen in server.c and
2180 		 * window.c and non-blocking-connects will throw yet another
2181 		 * wrench into things since we only want it to happen on
2182 		 * a successful connect. - gkm
2183 		 */
2184 		else if (*server == '.')
2185 		{
2186 			if (*(++server))
2187 			{
2188 				say("syntax error - nothing may be specified after the '.'");
2189 				return;
2190 			}
2191 			if (get_current_screen() && curr_scr_win &&
2192 			    (i = window_get_prev_server(curr_scr_win)) != -1)
2193 			{
2194 				if (group)
2195 					add_server_to_server_group(i, group);
2196 
2197 				window_restore_server(i);
2198 				if (!proxy_name && server_list[i].proxy_name)
2199 					proxy_name = server_list[i].proxy_name;
2200 				if (proxy_port == 0 && server_list[i].proxy_port)
2201 					proxy_port = server_list[i].proxy_port;
2202 				window_get_connected(curr_scr_win, NULL,
2203 				    window_get_server(curr_scr_win), NULL,
2204 				    proxy_name, proxy_port,
2205 				    group, type, level);
2206 			}
2207 			else
2208 				say("No server previously in use in this window");
2209 			return;
2210 		}
2211 		if ((i = parse_server_index(server)) != -1)
2212 		{
2213 			server = server_list[i].name;
2214 			if (server_list[i].port != -1)
2215 				port_num = server_list[i].port;
2216 			if (server_list[i].nickname && !nick)
2217 				nick = server_list[i].nickname;
2218 		}
2219 		else
2220 			i = find_in_server_list(server, port_num, nick);
2221 
2222 		if (group)
2223 			add_server_to_server_group(i, group);
2224 
2225 		if (is_server_connected(i))
2226 		{
2227 			/*
2228 			 * We reset the log level only if the "new" server
2229 			 * already has windows associated with it : here it's
2230 			 * equivalent to its already being connected. -Sol
2231 			 */
2232 			new_server_flags = 0;
2233 		}
2234 		else
2235 			new_server_flags = WIN_TRANSFER;
2236 		if (connect_to_server(server, port_num, nick, primary_server) != -1)
2237 		{
2238 			if (primary_server > -1 && from_server != primary_server &&
2239 			    !server_list[from_server].away &&
2240 			    server_list[primary_server].away)
2241 				malloc_strcpy(&server_list[from_server].away,
2242 				    server_list[primary_server].away);
2243 			window_set_server(-1, from_server, new_server_flags);
2244 		}
2245 	}
2246 	else
2247 		display_server_list();
2248 }
2249 
2250 /*
2251  * flush_server: eats all output from server, until there is at least a
2252  * second delay between bits of servers crap... useful to abort a /links.
2253  */
2254 void
flush_server(void)2255 flush_server(void)
2256 {
2257 	fd_set rd;
2258 	struct timeval time_out;
2259 	int	flushing = 1;
2260 	int	des;
2261 	int	old_timeout;
2262 	u_char	buffer[BIG_BUFFER_SIZE];
2263 
2264 	if ((des = server_list[from_server].read) == -1)
2265 		return;
2266 	time_out.tv_usec = 0;
2267 	time_out.tv_sec = 1;
2268 	old_timeout = dgets_timeout(1);
2269 	while (flushing)
2270 	{
2271 		FD_ZERO(&rd);
2272 		FD_SET(des, &rd);
2273 		switch (new_select(&rd, NULL, &time_out))
2274 		{
2275 		case -1:
2276 		case 0:
2277 			flushing = 0;
2278 			break;
2279 		default:
2280 			if (FD_ISSET(des, &rd))
2281 			{
2282 				switch (dgets(buffer, sizeof buffer, des))
2283 				{
2284 				case -2:
2285 					/* SSL retry */
2286 					break;
2287 				case -1:
2288 				case 0:
2289 					flushing = 0;
2290 					break;
2291 				default:
2292 					break;
2293 				}
2294 			}
2295 			break;
2296 		}
2297 	}
2298 	/* make sure we've read a full line from server */
2299 	FD_ZERO(&rd);
2300 	FD_SET(des, &rd);
2301 	if (new_select(&rd, NULL, &time_out) > 0)
2302 		dgets(buffer, sizeof buffer, des);
2303 	(void) dgets_timeout(old_timeout);
2304 }
2305 
2306 /*
2307  * server_set_whois: sets the whois value for the given server index.  If the
2308  * whois value is 0, it assumes the server doesn't send End of WHOIS commands
2309  * and the whois.c routines use the old fashion way of getting whois info. If
2310  * the whois value is non-zero, then the server sends End of WHOIS and things
2311  * can be done more effienciently
2312  */
2313 void
server_set_whois(int server_index,int value)2314 server_set_whois(int server_index, int value)
2315 {
2316 	server_list[server_index].whois = value;
2317 }
2318 
2319 /* server_get_whois: Returns the whois value for the given server index */
2320 int
server_get_whois(int server_index)2321 server_get_whois(int server_index)
2322 {
2323 	if (server_index == -1)
2324 		server_index = primary_server;
2325 	return (server_list[server_index].whois);
2326 }
2327 
2328 
2329 void
server_set_2_6_2(int server_index,int value)2330 server_set_2_6_2(int server_index, int value)
2331 {
2332 	server_set_flag(server_index, SERVER_2_6_2, value);
2333 }
2334 
2335 int
server_get_2_6_2(int server_index)2336 server_get_2_6_2(int server_index)
2337 {
2338 	if (server_index == -1)
2339 		server_index = primary_server;
2340 	return (server_get_flag(server_index, SERVER_2_6_2));
2341 }
2342 
2343 void
server_set_flag(int server_index,int flag,int value)2344 server_set_flag(int server_index, int flag, int value)
2345 {
2346 	if (server_index == -1)
2347 		server_index = primary_server;
2348 	if (value)
2349 		server_list[server_index].flags |= flag;
2350 	else
2351 		server_list[server_index].flags &= ~flag;
2352 }
2353 
2354 int
server_get_flag(int server_index,int value)2355 server_get_flag(int server_index, int value)
2356 {
2357 	if (server_index == -1)
2358 		server_index = primary_server;
2359 	return server_list[server_index].flags & value;
2360 }
2361 
2362 /* get ICB group */
2363 u_char *
server_get_icbgroup(int server_index)2364 server_get_icbgroup(int server_index)
2365 {
2366 	u_char	*group;
2367 
2368 	if (server_index == -1)
2369 		server_index = primary_server;
2370 	group = server_list[server_index].group ? server_list[server_index].group : empty_string();
2371 	return (group);
2372 }
2373 
2374 /* get ICB mode */
2375 u_char *
server_get_icbmode(int server_index)2376 server_get_icbmode(int server_index)
2377 {
2378 	u_char	*mode;
2379 
2380 	if (server_index == -1)
2381 		server_index = primary_server;
2382 	mode = server_list[server_index].icbmode ? server_list[server_index].icbmode : empty_string();
2383 	return (mode);
2384 }
2385 
2386 /*
2387  * server_get_password: get the passwor for this server.
2388  */
2389 u_char *
server_get_password(int server_index)2390 server_get_password(int server_index)
2391 {
2392 	if (server_index == -1)
2393 		server_index = primary_server;
2394 	return (server_list[server_index].password);
2395 }
2396 
2397 /*
2398  * server_set_version: Sets the server version for the given server type.  A
2399  * zero version means pre 2.6, a one version means 2.6 aso. (look server.h
2400  * for typedef)
2401  */
2402 void
server_set_version(int server_index,int version)2403 server_set_version(int server_index, int version)
2404 {
2405 	if (server_index == -1)
2406 		server_index = primary_server;
2407 	server_list[server_index].version = version;
2408 }
2409 
2410 /*
2411  * server_get_version: returns the server version value for the given server
2412  * index
2413  */
2414 int
server_get_version(int server_index)2415 server_get_version(int server_index)
2416 {
2417 	if (server_index == -1)
2418 		server_index = primary_server;
2419 	if (server_index == -1)
2420 		return DEFAULT_SERVER_VERSION;
2421 	else
2422 		return (server_list[server_index].version);
2423 }
2424 
2425 /* server_get_name: returns the name for the given server index */
2426 u_char	*
server_get_name(int server_index)2427 server_get_name(int server_index)
2428 {
2429 	if (server_index == -1)
2430 		server_index = primary_server;
2431 	return (server_list[server_index].name);
2432 }
2433 
2434 /* server_set_itsname: returns the server's idea of its name */
2435 u_char	*
server_get_itsname(int server_index)2436 server_get_itsname(int server_index)
2437 {
2438 	if (server_index == -1)
2439 		server_index = primary_server;
2440 	if (server_list[server_index].itsname)
2441 		return server_list[server_index].itsname;
2442 	else if (server_list[server_index].name)
2443 		return server_list[server_index].name;
2444 	else
2445 		return UP("<None>");
2446 }
2447 
2448 void
server_set_itsname(int server_index,u_char * name)2449 server_set_itsname(int server_index, u_char *name)
2450 {
2451 	if (server_index == -1)
2452 		server_index = primary_server;
2453 	malloc_strcpy(&server_list[server_index].itsname, name);
2454 }
2455 
2456 /*
2457  * is_server_open: Returns true if the given server index represents a server
2458  * with a live connection, returns false otherwise
2459  */
2460 int
is_server_open(int server_index)2461 is_server_open(int server_index)
2462 {
2463 	if (server_index < 0)
2464 		return (0);
2465 	return (server_list[server_index].read != -1);
2466 }
2467 
2468 /*
2469  * is_server_connected: returns true if the given server is connected.  This
2470  * means that both the tcp connection is open and the user is properly
2471  * registered
2472  */
2473 int
is_server_connected(int server_index)2474 is_server_connected(int server_index)
2475 {
2476 	if (server_index < 0)
2477 		return (0);
2478 	return (server_list[server_index].connected && (server_list[server_index].flags & LOGGED_IN));
2479 }
2480 
2481 /* server_get_port: Returns the connection port for the given server index */
2482 int
server_get_port(int server_index)2483 server_get_port(int server_index)
2484 {
2485 	if (server_index == -1)
2486 		server_index = primary_server;
2487 	return (server_list[server_index].port);
2488 }
2489 
2490 /*
2491  * server_get_nickname: returns the current nickname for the given server
2492  * index
2493  */
2494 u_char	*
server_get_nickname(int server_index)2495 server_get_nickname(int server_index)
2496 {
2497 	if ((server_index != -1) && server_list[server_index].nickname)
2498 		return (server_list[server_index].nickname);
2499 	else
2500 		return my_nickname();
2501 }
2502 
2503 
2504 
2505 /* server_get_qhead - get the head of the whois queue */
2506 WhoisQueue *
server_get_qhead(int server_index)2507 server_get_qhead(int server_index)
2508 {
2509 	if (server_index >= 0)
2510 		return server_list[server_index].WQ_head;
2511 	return NULL;
2512 }
2513 
2514 /* server_get_whois_stuff */
2515 WhoisStuff *
server_get_whois_stuff(int server_index)2516 server_get_whois_stuff(int server_index)
2517 {
2518 	if (server_index >= 0)
2519 		return &server_list[server_index].whois_stuff;
2520 	return NULL;
2521 }
2522 
2523 /* server_get_qtail - get the tail of the whois queue */
2524 WhoisQueue *
server_get_qtail(int server_index)2525 server_get_qtail(int server_index)
2526 {
2527 	if (server_index >= 0)
2528 		return server_list[server_index].WQ_tail;
2529 	return NULL;
2530 }
2531 
2532 
2533 /* server_set_qhead - set the head of the whois queue */
2534 void
server_set_qhead(int server_index,WhoisQueue * value)2535 server_set_qhead(int server_index, WhoisQueue *value)
2536 {
2537 	if (server_index >= 0)
2538 		server_list[server_index].WQ_head = value;
2539 }
2540 
2541 /* server_set_qtail - set the tail of the whois queue */
2542 void
server_set_qtail(int server_index,WhoisQueue * value)2543 server_set_qtail(int server_index, WhoisQueue *value)
2544 {
2545 	if (server_index >= 0)
2546 		server_list[server_index].WQ_tail = value;
2547 }
2548 
2549 
2550 /*
2551  * server_get_operator: returns true if the user has op privs on the server,
2552  * false otherwise
2553  */
2554 int
server_get_operator(int server_index)2555 server_get_operator(int server_index)
2556 {
2557 	return (server_list[server_index].operator);
2558 }
2559 
2560 /*
2561  * server_set_operator: If flag is non-zero, marks the user as having op
2562  * privs on the given server.
2563  */
2564 void
server_set_operator(int server_index,int flag)2565 server_set_operator(int server_index, int flag)
2566 {
2567 	server_list[server_index].operator = flag;
2568 }
2569 
2570 /*
2571  * server_set_nickname: sets the nickname for the given server to nickname.
2572  * This nickname is then used for all future connections to that server
2573  * (unless changed with NICK while connected to the server
2574  */
2575 void
server_set_nickname(int server_index,u_char * nick)2576 server_set_nickname(int server_index, u_char *nick)
2577 {
2578 	if (server_index >= 0)
2579 	{
2580 		malloc_strcpy(&(server_list[server_index].nickname), nick);
2581 		if (server_index == primary_server)
2582 			set_nickname(nick);
2583 	}
2584 	update_all_status();
2585 }
2586 
2587 void
server_set_motd(int server_index,int flag)2588 server_set_motd(int server_index, int flag)
2589 {
2590 	if (server_index >= 0)
2591 		server_list[server_index].motd = flag;
2592 }
2593 
2594 int
server_get_motd(int server_index)2595 server_get_motd(int server_index)
2596 {
2597 	if (server_index >= 0)
2598 		return(server_list[server_index].motd);
2599 	return (0);
2600 }
2601 
2602 void
server_is_connected(int server_index,int value)2603 server_is_connected(int server_index, int value)
2604 {
2605 	server_list[server_index].connected = value;
2606 	if (value)
2607 		server_list[server_index].eof = 0;
2608 }
2609 
2610 /* send_to_server: sends the given info the the server */
2611 void
send_to_server(const char * format,...)2612 send_to_server(const char *format, ...)
2613 {
2614 	static	int	in_send_to_server = 0;
2615 	u_char	lbuf[BIG_BUFFER_SIZE];	/* make this buffer *much*
2616 					 * bigger than needed */
2617 	u_char	*buf = lbuf;
2618 	int	des;
2619 	size_t	len;
2620 	int	server = from_server;
2621 	va_list vlist;
2622 
2623 	va_start(vlist, format);
2624 
2625 	if (in_send_to_server)
2626 		return;
2627 	//memset(lbuf, 0, sizeof(lbuf));
2628 	in_send_to_server = 1;
2629 	if (server == -1)
2630 		server = primary_server;
2631 	if (server != -1 && ((des = server_list[server].write) != -1) &&
2632 	    (server_list[server].flags & LOGGED_IN) )
2633 	{
2634 		/* save space for the packet length */
2635 		if (server_get_version(server) == ServerICB)
2636 			buf++;
2637 		server_list[server].sent = 1;
2638 		vsnprintf(CP(buf), sizeof lbuf, format, vlist);
2639 		va_end(vlist);
2640 		len = my_strlen(buf);
2641 		if (len > (IRCD_BUFFER_SIZE - 2))
2642 			lbuf[IRCD_BUFFER_SIZE - 2] = '\0';
2643 		/*
2644 		 * for ICB, we send a final nul, and for IRC, we have
2645 		 * a final newline.
2646 		 */
2647 		len++;
2648 		if (do_hook(RAW_SEND_LIST, "%s", lbuf))
2649 		{
2650 			if (server_get_version(server) == ServerICB)
2651 			{
2652 				/*
2653 				 * we depend on our caller to split things
2654 				 * up for the ICB server
2655 				 */
2656 				if (len > 254)
2657 					len = 254;
2658 				lbuf[len] = 0;
2659 				lbuf[0] = (u_char)len;
2660 				lbuf[++len] = 0;
2661 			}
2662 			else
2663 				my_strmcat(buf, "\n", IRCD_BUFFER_SIZE);
2664 
2665 			/* XXX retval */
2666 			ssl_write(server_list[server].ssl_info,
2667 				  server_list[server].write, CP(lbuf), len);
2668 		}
2669 	}
2670 	else if (!in_redirect() && !connected_to_server())
2671 		say("You are not connected to a server, use /SERVER to connect.");
2672 	in_send_to_server = 0;
2673 }
2674 
2675 #ifdef HAVE_SYS_UN_H
2676 /*
2677  * Connect to a UNIX domain socket. Only works for servers.
2678  * submitted by Avalon for use with server 2.7.2 and beyond.
2679  */
2680 int
connect_to_unix(int port,u_char * path)2681 connect_to_unix(int port, u_char *path)
2682 {
2683 	struct	sockaddr_un un;
2684 	int	    sock;
2685 
2686 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
2687 
2688 	un.sun_family = AF_UNIX;
2689 	if (snprintf(un.sun_path, sizeof un.sun_path, "%-.100s/%-.6d", path, port) != sizeof un.sun_path)
2690 	{
2691 		yell("--- sun_path truncated: wanted '%-.100s/%-.6d'", path, port);
2692 	}
2693 
2694 	if (connect(sock, (struct sockaddr *)&un, (int)my_strlen(path)+2) == -1)
2695 	{
2696 		new_close(sock);
2697 		return -1;
2698 	}
2699 	return sock;
2700 }
2701 #endif /* HAVE_SYS_UN_H */
2702 
2703 /*
2704  * close_all_server: Used whn creating new screens to close all the open
2705  * server connections in the child process...
2706  */
2707 void
close_all_server(void)2708 close_all_server(void)
2709 {
2710 	int	i;
2711 
2712 	for (i = 0; i < number_of_servers(); i++)
2713 	{
2714 		if (server_list[i].read != -1)
2715 			new_close(server_list[i].read);
2716 		if (server_list[i].write != -1)
2717 			new_close(server_list[i].write);
2718 	}
2719 }
2720 
2721 u_char	*
create_server_list(void)2722 create_server_list(void)
2723 {
2724 	int	i;
2725 	u_char	*value = NULL;
2726 	StringList *sl;
2727 
2728 	sl = sl_init();
2729 	for (i = 0; i < number_of_servers(); i++)
2730 		if (server_list[i].read != -1)
2731 			sl_add(sl, CP(server_get_itsname(i)));
2732 	value = sl_concat(sl, UP(" "));
2733 	sl_free(sl, 0);
2734 
2735 	return value;
2736 }
2737 
2738 static	void
add_to_server_buffer(int server,u_char * buf)2739 add_to_server_buffer(int server, u_char *buf)
2740 {
2741 	if (buf && *buf)
2742 	{
2743 		if (server_list[server].buffer)
2744 			malloc_strcat(&server_list[server].buffer, buf);
2745 		else
2746 			malloc_strcpy(&server_list[server].buffer, buf);
2747 	}
2748 }
2749 
2750 void
disconnectcmd(u_char * command,u_char * args,u_char * subargs)2751 disconnectcmd(u_char *command, u_char *args, u_char *subargs)
2752 {
2753 	u_char	*server;
2754 	u_char	*message;
2755 	int	i;
2756 	int	old_serv;
2757 
2758 	if ((server = next_arg(args, &args)) != NULL && server[0] != '*' && server[1] != '\0')
2759 	{
2760 		i = parse_server_index(server);
2761 		if (-1 == i)
2762 		{
2763 			say("No such server!");
2764 			return;
2765 		}
2766 	}
2767 	else
2768 		i = get_window_server(0);
2769 	/*
2770 	 * XXX - this is a major kludge.  i should never equal -1 at
2771 	 * this point.  we only do this because something has gotten
2772 	 * *really* confused at this point.  .mrg.
2773 	 */
2774 	if (i == -1)
2775 	{
2776 		for (i = 0; i < number_of_servers(); i++)
2777 		{
2778 			server_list[i].eof = -1;
2779 			server_list[i].connected = 0;
2780 			new_close(server_list[i].read);
2781 			new_close(server_list[i].write);
2782 		}
2783 		goto done;
2784 	}
2785 	if (!args || !*args)
2786 		message = UP("Disconnecting");
2787 	else
2788 		message = args;
2789 	if (-1 == server_list[i].write)
2790 	{
2791 		say("That server isn't connected!");
2792 		return;
2793 	}
2794 	server = server_list[i].itsname ? server_list[i].itsname :
2795 		server_list[i].name ? server_list[i].name : (u_char *) "unknown?";
2796 	say("Disconnecting from server %s", server);
2797 	old_serv = server_list[i].close_serv;
2798 	close_server(i, message);
2799 	server_list[i].eof = 1;
2800 	if (old_serv != -1 && old_serv != i)
2801 	{
2802 		Window *tmp;
2803 		Win_Trav wt;
2804 
2805 		say("Connection to server %s resumed...", server_list[old_serv].name);
2806 		server_list[i].close_serv = -1;
2807 		server_list[old_serv].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
2808 		server_list[old_serv].flags |= LOGGED_IN;
2809 		server_list[old_serv].connected = 1;
2810 		wt.init = 1;
2811 		while ((tmp = window_traverse(&wt)))
2812 			if (window_get_server(tmp) == i)
2813 			{
2814 				window_set_server(window_get_refnum(tmp), old_serv, WIN_ALL);
2815 				break;
2816 			}
2817 	}
2818 done:
2819 	clean_whois_queue();
2820 	window_check_servers();
2821 	if (!connected_to_server())
2822 		say("You are not connected to a server. Use /SERVER to connect.");
2823 }
2824 
2825 /*
2826  * parse_server: feed this line into the right server parser
2827  */
2828 static void
parse_server(u_char * line)2829 parse_server(u_char *line)
2830 {
2831 	server_list[parsing_server_index].parse_server(line);
2832 }
2833 
2834 int
server_get_server_group(int server_index)2835 server_get_server_group(int server_index)
2836 {
2837 	if (server_index < 0 && server_index >= number_of_servers())
2838 		server_index = from_server;
2839 
2840 	return server_list[server_index].server_group;
2841 }
2842 
2843 void
server_set_server_group(int server_index,int group)2844 server_set_server_group(int server_index, int group)
2845 {
2846 	if (server_index < 0 && server_index >= number_of_servers())
2847 		server_index = from_server;
2848 
2849 	server_list[server_index].server_group = group;
2850 }
2851 
2852 static void
server_group_get_connected_next(int si)2853 server_group_get_connected_next(int si)
2854 {
2855 	int i, group;
2856 
2857 	group = server_list[si].server_group;
2858 
2859 	for (i = si + 1; i != si; i = (i + 1) % number_of_servers())
2860 		if (server_list[i].server_group == group)
2861 		{
2862 			say("Ok, trying server %s...", server_get_itsname(si));
2863 			get_connected(i);
2864 			return;
2865 		}
2866 	say("No servers available.");
2867 }
2868 
2869 void
add_server_to_server_group(int server,u_char * group)2870 add_server_to_server_group(int server, u_char *group)
2871 {
2872 	int	i = find_server_group(group, 1);
2873 
2874 	server_list[server].server_group = i;
2875 	say("Server %s's server group is now %s", server_get_itsname(server), group);
2876 }
2877 
2878 int
find_server_group(u_char * group,int add)2879 find_server_group(u_char *group, int add)
2880 {
2881 	static	int	next = 1;
2882 	SGroup *g;
2883 
2884 	if (!group || !*group)
2885 		return 0;
2886 
2887 	g = (SGroup *) find_in_list((List **)(void *)&server_group_list, group, 0);
2888 	if (g)
2889 		goto end;
2890 
2891 	if (!add)
2892 		return 0;
2893 
2894 	g = new_malloc(sizeof *g);
2895 	g->name = NULL;
2896 	malloc_strcpy(&g->name, group);
2897 	g->number = next++;
2898 	add_to_list((List **)(void *)&server_group_list, (List *) g);
2899 end:
2900 	return g->number;
2901 }
2902 
2903 u_char	*
find_server_group_name(int number)2904 find_server_group_name(int number)
2905 {
2906 	SGroup *g = server_group_list;
2907 
2908 	for (; g; g = g->next)
2909 		if (g->number == number)
2910 			return g->name;
2911 	return empty_string();
2912 }
2913 
2914 int
active_server_group(int sgroup)2915 active_server_group(int sgroup)
2916 {
2917 	int i;
2918 
2919 	/* kinda blah - returns first active server in that group */
2920 	for (i = 0; i < number_of_servers(); i++)
2921 		if (server_list[i].connected)
2922 			return i;
2923 
2924 	return -1;
2925 }
2926 
2927 void
server_set_version_string(int server,u_char * ver)2928 server_set_version_string(int server, u_char *ver)
2929 {
2930 	if (ver)
2931 		malloc_strcpy(&server_list[server].version_string, ver);
2932 	else
2933 		new_free(&server_list[server].version_string);
2934 }
2935 
2936 u_char *
server_get_version_string(int server)2937 server_get_version_string(int server)
2938 {
2939 	return server_list[server].version_string;
2940 }
2941 
2942 void
server_set_away(int server,u_char * away)2943 server_set_away(int server, u_char *away)
2944 {
2945 	if (away)
2946 		malloc_strcpy(&server_list[server].away, away);
2947 	else
2948 		new_free(&server_list[server].away);
2949 }
2950 
2951 u_char *
server_get_away(int server)2952 server_get_away(int server)
2953 {
2954 	return server_list[server].away;
2955 }
2956 
2957 void
server_get_local_ip_info(int server,SOCKADDR_STORAGE ** sa,socklen_t * salen)2958 server_get_local_ip_info(int server, SOCKADDR_STORAGE **sa, socklen_t *salen)
2959 {
2960 	if (sa)
2961 		*sa = server_list[from_server].localaddr;
2962 	if (salen)
2963 		*salen = server_list[from_server].localaddrlen;
2964 }
2965 
2966 void
server_set_chan_list(int server,ChannelList * chan)2967 server_set_chan_list(int server, ChannelList *chan)
2968 {
2969 	server_list[server].chan_list = chan;
2970 }
2971 
2972 ChannelList *
server_get_chan_list(int server)2973 server_get_chan_list(int server)
2974 {
2975 	return server_list[server].chan_list;
2976 }
2977 
2978 void
server_set_attempting_to_connect(int server,int attempt)2979 server_set_attempting_to_connect(int server, int attempt)
2980 {
2981 	server_list[server].attempting_to_connect = attempt;
2982 }
2983 
2984 int
server_get_attempting_to_connect(int server)2985 server_get_attempting_to_connect(int server)
2986 {
2987 	return server_list[server].attempting_to_connect;
2988 }
2989 
2990 void
server_set_sent(int server,int sent)2991 server_set_sent(int server, int sent)
2992 {
2993 	server_list[server].sent = sent;
2994 }
2995 
2996 int
server_get_sent(int server)2997 server_get_sent(int server)
2998 {
2999 	return server_list[server].sent;
3000 }
3001 
3002 CtcpFlood *
server_get_ctcp_flood(int server_index)3003 server_get_ctcp_flood(int server_index)
3004 {
3005 	if (server_index < 0 && server_index >= number_of_servers())
3006 		server_index = from_server;
3007 
3008 	return server_list[server_index].ctcp_flood;
3009 }
3010 
3011 int
number_of_servers(void)3012 number_of_servers(void)
3013 {
3014 	return number_of_servers_count;
3015 }
3016 
3017 void
unset_never_connected(void)3018 unset_never_connected(void)
3019 {
3020 	never_connected_local = 0;
3021 }
3022 
3023 int
never_connected(void)3024 never_connected(void)
3025 {
3026 	return never_connected_local;
3027 }
3028 
3029 void
set_connected_to_server(int val)3030 set_connected_to_server(int val)
3031 {
3032 	connected_to_server_local = val;
3033 }
3034 
3035 int
connected_to_server(void)3036 connected_to_server(void)
3037 {
3038 	return connected_to_server_local;
3039 }
3040 
3041 WhoInfo *
server_get_who_info(void)3042 server_get_who_info(void)
3043 {
3044 	return server_list[from_server].who_info;
3045 }
3046 
3047 int
server_get_oper_command(void)3048 server_get_oper_command(void)
3049 {
3050 	return server_list[from_server].oper_command;
3051 }
3052 
3053 void
server_set_oper_command(int val)3054 server_set_oper_command(int val)
3055 {
3056 	server_list[from_server].oper_command = val;
3057 }
3058 
3059 int
parsing_server(void)3060 parsing_server(void)
3061 {
3062 	return parsing_server_index;
3063 }
3064 
3065 int
get_primary_server(void)3066 get_primary_server(void)
3067 {
3068 	return primary_server;
3069 }
3070 
3071 void
set_primary_server(int server)3072 set_primary_server(int server)
3073 {
3074 	primary_server = server;
3075 }
3076 
3077 int
get_from_server(void)3078 get_from_server(void)
3079 {
3080 	return from_server;
3081 }
3082 
3083 int
set_from_server(int server)3084 set_from_server(int server)
3085 {
3086 	int	old_from_server = from_server;
3087 
3088 	from_server = server;
3089 	return old_from_server;
3090 }
3091 
3092 server_ssl_level
server_do_ssl(int server)3093 server_do_ssl(int server)
3094 {
3095 	return server_list[server].ssl_level;
3096 }
3097 
3098 void
server_default_encryption(u_char * proto,u_char * type)3099 server_default_encryption(u_char *proto, u_char *type)
3100 {
3101 	if (my_stricmp(proto, UP("ICB")) == 0)
3102 	{
3103 		yell("No ICB SSL support yet.");
3104 		return;
3105 	}
3106 	if (my_stricmp(proto, UP("IRC")) != 0)
3107 	{
3108 		yell("Only support IRC and ICB.");
3109 		return;
3110 	}
3111 
3112 	/* OK, irc SSL here. */
3113 	if (my_stricmp(type, UP("check")) == 0)
3114 	{
3115 		irc_ssl_level = SSL_VERIFY;
3116 		return;
3117 	}
3118 
3119 	if (my_stricmp(type, UP("nocheck")) == 0)
3120 	{
3121 		irc_ssl_level = SSL_ON;
3122 		return;
3123 	}
3124 
3125 	if (my_stricmp(type, UP("off")) == 0)
3126 	{
3127 		irc_ssl_level = SSL_OFF;
3128 		return;
3129 	}
3130 }
3131 
3132 void	*
server_get_server_private(int server)3133 server_get_server_private(int server)
3134 {
3135 	return server_list[server].server_private;
3136 }
3137 
3138 void
server_set_server_private(int server,void * data,server_private_cb_type cb)3139 server_set_server_private(int server, void *data, server_private_cb_type cb)
3140 {
3141 	if (server < 0 && server >= number_of_servers())
3142 		server = from_server;
3143 
3144 	server_list[server].server_private = data;
3145 	server_list[server].server_private_cb = cb;
3146 }
3147 
3148 u_char	*
server_get_proxy_name(int server,int use_default)3149 server_get_proxy_name(int server, int use_default)
3150 {
3151 	u_char	*name;
3152 
3153 	if (server < 0 && server >= number_of_servers())
3154 		return NULL;
3155 	name = server_list[server].proxy_name;
3156 	if (server_list[server].proxy_port == -1)
3157 		name = NULL;
3158 	else if (name == NULL && use_default)
3159 		name = default_proxy_name;
3160 
3161 	Debug(DB_PROXY, "returning name '%s'", name ? name : UP("<>"));
3162 	return name;
3163 }
3164 
3165 int
server_get_proxy_port(int server,int use_default)3166 server_get_proxy_port(int server, int use_default)
3167 {
3168 	int port;
3169 
3170 	if (server < 0 && server >= number_of_servers())
3171 		return 0;
3172 	port = server_list[server].proxy_port;
3173 	if (port == 0 && use_default)
3174 		port = default_proxy_port;
3175 
3176 	Debug(DB_PROXY, "returning port %d", port);
3177 	return port;
3178 }
3179 
3180 void
server_set_default_proxy(u_char * proxy_and_port)3181 server_set_default_proxy(u_char *proxy_and_port)
3182 {
3183 	server_split_proxy_port(proxy_and_port,
3184 				&default_proxy_name, &default_proxy_port);
3185 	Debug(DB_PROXY, "set server '%s' port '%d'", default_proxy_name, default_proxy_port);
3186 }
3187