1 /* X-Chat
2  * Copyright (C) 1998 Peter Zelezny.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
19  * based on Dante source code
20  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
21  *      Inferno Nettverk A/S, Norway.  All rights reserved.
22  */
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 
30 #define WANTSOCKET
31 #define WANTARPA
32 #include "inet.h"
33 
34 #ifdef WIN32
35 #include <winbase.h>
36 #include <io.h>
37 #else
38 #include <signal.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
41 #endif
42 
43 #include "hexchat.h"
44 #include "fe.h"
45 #include "cfgfiles.h"
46 #include "network.h"
47 #include "notify.h"
48 #include "hexchatc.h"
49 #include "inbound.h"
50 #include "outbound.h"
51 #include "text.h"
52 #include "util.h"
53 #include "url.h"
54 #include "proto-irc.h"
55 #include "servlist.h"
56 #include "server.h"
57 
58 #ifdef USE_OPENSSL
59 #include <openssl/ssl.h>		  /* SSL_() */
60 #include <openssl/err.h>		  /* ERR_() */
61 #include "ssl.h"
62 #endif
63 
64 #ifdef USE_OPENSSL
65 /* local variables */
66 static struct session *g_sess = NULL;
67 #endif
68 
69 static GSList *away_list = NULL;
70 GSList *serv_list = NULL;
71 
72 static void auto_reconnect (server *serv, int send_quit, int err);
73 static void server_disconnect (session * sess, int sendquit, int err);
74 static int server_cleanup (server * serv);
75 static void server_connect (server *serv, char *hostname, int port, int no_login);
76 
77 static void
write_error(char * message,GError ** error)78 write_error (char *message, GError **error)
79 {
80 	if (error == NULL || *error == NULL) {
81 		return;
82 	}
83 	g_printerr ("%s: %s\n", message, (*error)->message);
84 	g_clear_error (error);
85 }
86 
87 /* actually send to the socket. This might do a character translation or
88    send via SSL. server/dcc both use this function. */
89 
90 int
tcp_send_real(void * ssl,int sok,GIConv write_converter,char * buf,int len)91 tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len)
92 {
93 	int ret;
94 
95 	gsize buf_encoded_len;
96 	gchar *buf_encoded = text_convert_invalid (buf, len, write_converter, arbitrary_encoding_fallback_string, &buf_encoded_len);
97 #ifdef USE_OPENSSL
98 	if (!ssl)
99 		ret = send (sok, buf_encoded, buf_encoded_len, 0);
100 	else
101 		ret = _SSL_send (ssl, buf_encoded, buf_encoded_len);
102 #else
103 	ret = send (sok, buf_encoded, buf_encoded_len, 0);
104 #endif
105 	g_free (buf_encoded);
106 
107 	return ret;
108 }
109 
110 static int
server_send_real(server * serv,char * buf,int len)111 server_send_real (server *serv, char *buf, int len)
112 {
113 	fe_add_rawlog (serv, buf, len, TRUE);
114 
115 	url_check_line (buf);
116 
117 	return tcp_send_real (serv->ssl, serv->sok, serv->write_converter, buf, len);
118 }
119 
120 /* new throttling system, uses the same method as the Undernet
121    ircu2.10 server; under test, a 200-line paste didn't flood
122    off the client */
123 
124 static int
tcp_send_queue(server * serv)125 tcp_send_queue (server *serv)
126 {
127 	char *buf, *p;
128 	int len, i, pri;
129 	GSList *list;
130 	time_t now = time (0);
131 
132 	/* did the server close since the timeout was added? */
133 	if (!is_server (serv))
134 		return 0;
135 
136 	/* try priority 2,1,0 */
137 	pri = 2;
138 	while (pri >= 0)
139 	{
140 		list = serv->outbound_queue;
141 		while (list)
142 		{
143 			buf = (char *) list->data;
144 			if (buf[0] == pri)
145 			{
146 				buf++;	/* skip the priority byte */
147 				len = strlen (buf);
148 
149 				if (serv->next_send < now)
150 					serv->next_send = now;
151 				if (serv->next_send - now >= 10)
152 				{
153 					/* check for clock skew */
154 					if (now >= serv->prev_now)
155 						return 1;		  /* don't remove the timeout handler */
156 					/* it is skewed, reset to something sane */
157 					serv->next_send = now;
158 				}
159 
160 				for (p = buf, i = len; i && *p != ' '; p++, i--);
161 				serv->next_send += (2 + i / 120);
162 				serv->sendq_len -= len;
163 				serv->prev_now = now;
164 				fe_set_throttle (serv);
165 
166 				server_send_real (serv, buf, len);
167 
168 				buf--;
169 				serv->outbound_queue = g_slist_remove (serv->outbound_queue, buf);
170 				g_free (buf);
171 				list = serv->outbound_queue;
172 			} else
173 			{
174 				list = list->next;
175 			}
176 		}
177 		/* now try pri 0 */
178 		pri--;
179 	}
180 	return 0;						  /* remove the timeout handler */
181 }
182 
183 int
tcp_send_len(server * serv,char * buf,int len)184 tcp_send_len (server *serv, char *buf, int len)
185 {
186 	char *dbuf;
187 	int noqueue = !serv->outbound_queue;
188 
189 	if (!prefs.hex_net_throttle)
190 		return server_send_real (serv, buf, len);
191 
192 	dbuf = g_malloc (len + 2);	/* first byte is the priority */
193 	dbuf[0] = 2;	/* pri 2 for most things */
194 	memcpy (dbuf + 1, buf, len);
195 	dbuf[len + 1] = 0;
196 
197 	/* privmsg and notice get a lower priority */
198 	if (g_ascii_strncasecmp (dbuf + 1, "PRIVMSG", 7) == 0 ||
199 		 g_ascii_strncasecmp (dbuf + 1, "NOTICE", 6) == 0)
200 	{
201 		dbuf[0] = 1;
202 	}
203 	else
204 	{
205 		/* WHO gets the lowest priority */
206 		if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0)
207 			dbuf[0] = 0;
208 		/* as do MODE queries (but not changes) */
209 		else if (g_ascii_strncasecmp (dbuf + 1, "MODE ", 5) == 0)
210 		{
211 			char *mode_str, *mode_str_end, *loc;
212 			/* skip spaces before channel/nickname */
213 			for (mode_str = dbuf + 5; *mode_str == ' '; ++mode_str);
214 			/* skip over channel/nickname */
215 			mode_str = strchr (mode_str, ' ');
216 			if (mode_str)
217 			{
218 				/* skip spaces before mode string */
219 				for (; *mode_str == ' '; ++mode_str);
220 				/* find spaces after end of mode string */
221 				mode_str_end = strchr (mode_str, ' ');
222 				/* look for +/- within the mode string */
223 				loc = strchr (mode_str, '-');
224 				if (loc && (!mode_str_end || loc < mode_str_end))
225 					goto keep_priority;
226 				loc = strchr (mode_str, '+');
227 				if (loc && (!mode_str_end || loc < mode_str_end))
228 					goto keep_priority;
229 			}
230 			dbuf[0] = 0;
231 keep_priority:
232 			;
233 		}
234 	}
235 
236 	serv->outbound_queue = g_slist_append (serv->outbound_queue, dbuf);
237 	serv->sendq_len += len; /* tcp_send_queue uses strlen */
238 
239 	if (tcp_send_queue (serv) && noqueue)
240 		fe_timeout_add (500, tcp_send_queue, serv);
241 
242 	return 1;
243 }
244 
245 void
tcp_sendf(server * serv,const char * fmt,...)246 tcp_sendf (server *serv, const char *fmt, ...)
247 {
248 	va_list args;
249 	/* keep this buffer in BSS. Converting UTF-8 to ISO-8859-x might make the
250       string shorter, so allow alot more than 512 for now. */
251 	static char send_buf[1540];	/* good code hey (no it's not overflowable) */
252 	int len;
253 
254 	va_start (args, fmt);
255 	len = g_vsnprintf (send_buf, sizeof (send_buf) - 1, fmt, args);
256 	va_end (args);
257 
258 	send_buf[sizeof (send_buf) - 1] = '\0';
259 	if (len < 0 || len > (sizeof (send_buf) - 1))
260 		len = strlen (send_buf);
261 
262 	tcp_send_len (serv, send_buf, len);
263 }
264 
265 static int
close_socket_cb(gpointer sok)266 close_socket_cb (gpointer sok)
267 {
268 	closesocket (GPOINTER_TO_INT (sok));
269 	return 0;
270 }
271 
272 static void
close_socket(int sok)273 close_socket (int sok)
274 {
275 	/* close the socket in 5 seconds so the QUIT message is not lost */
276 	fe_timeout_add_seconds (5, close_socket_cb, GINT_TO_POINTER (sok));
277 }
278 
279 /* handle 1 line of text received from the server */
280 
281 static void
server_inline(server * serv,char * line,gssize len)282 server_inline (server *serv, char *line, gssize len)
283 {
284 	gsize len_utf8;
285 	if (!strcmp (serv->encoding, "UTF-8"))
286 		line = text_fixup_invalid_utf8 (line, len, &len_utf8);
287 	else
288 		line = text_convert_invalid (line, len, serv->read_converter, unicode_fallback_string, &len_utf8);
289 
290 	fe_add_rawlog (serv, line, len_utf8, FALSE);
291 
292 	/* let proto-irc.c handle it */
293 	serv->p_inline (serv, line, len_utf8);
294 
295 	g_free (line);
296 }
297 
298 /* read data from socket */
299 
300 static gboolean
server_read(GIOChannel * source,GIOCondition condition,server * serv)301 server_read (GIOChannel *source, GIOCondition condition, server *serv)
302 {
303 	int sok = serv->sok;
304 	int error, i, len;
305 	char lbuf[2050];
306 
307 	while (1)
308 	{
309 #ifdef USE_OPENSSL
310 		if (!serv->ssl)
311 #endif
312 			len = recv (sok, lbuf, sizeof (lbuf) - 2, 0);
313 #ifdef USE_OPENSSL
314 		else
315 			len = _SSL_recv (serv->ssl, lbuf, sizeof (lbuf) - 2);
316 #endif
317 		if (len < 1)
318 		{
319 			error = 0;
320 			if (len < 0)
321 			{
322 				if (would_block ())
323 					return TRUE;
324 				error = sock_error ();
325 			}
326 			if (!serv->end_of_motd)
327 			{
328 				server_disconnect (serv->server_session, FALSE, error);
329 				if (!servlist_cycle (serv))
330 				{
331 					if (prefs.hex_net_auto_reconnect)
332 						auto_reconnect (serv, FALSE, error);
333 				}
334 			} else
335 			{
336 				if (prefs.hex_net_auto_reconnect)
337 					auto_reconnect (serv, FALSE, error);
338 				else
339 					server_disconnect (serv->server_session, FALSE, error);
340 			}
341 			return TRUE;
342 		}
343 
344 		i = 0;
345 
346 		lbuf[len] = 0;
347 
348 		while (i < len)
349 		{
350 			switch (lbuf[i])
351 			{
352 			case '\r':
353 				break;
354 
355 			case '\n':
356 				serv->linebuf[serv->pos] = 0;
357 				server_inline (serv, serv->linebuf, serv->pos);
358 				serv->pos = 0;
359 				break;
360 
361 			default:
362 				serv->linebuf[serv->pos] = lbuf[i];
363 				if (serv->pos >= (sizeof (serv->linebuf) - 1))
364 					fprintf (stderr,
365 								"*** HEXCHAT WARNING: Buffer overflow - non-compliant server!\n");
366 				else
367 					serv->pos++;
368 			}
369 			i++;
370 		}
371 	}
372 }
373 
374 static void
server_connected(server * serv)375 server_connected (server * serv)
376 {
377 	prefs.wait_on_exit = TRUE;
378 	serv->ping_recv = time (0);
379 	serv->lag_sent = 0;
380 	serv->connected = TRUE;
381 	set_nonblocking (serv->sok);
382 	serv->iotag = fe_input_add (serv->sok, FIA_READ|FIA_EX, server_read, serv);
383 	if (!serv->no_login)
384 	{
385 		EMIT_SIGNAL (XP_TE_CONNECTED, serv->server_session, NULL, NULL, NULL,
386 						 NULL, 0);
387 		if (serv->network)
388 		{
389 			serv->p_login (serv,
390 								(!(((ircnet *)serv->network)->flags & FLAG_USE_GLOBAL) &&
391 								 (((ircnet *)serv->network)->user)) ?
392 								(((ircnet *)serv->network)->user) :
393 								prefs.hex_irc_user_name,
394 								(!(((ircnet *)serv->network)->flags & FLAG_USE_GLOBAL) &&
395 								 (((ircnet *)serv->network)->real)) ?
396 								(((ircnet *)serv->network)->real) :
397 								prefs.hex_irc_real_name);
398 		} else
399 		{
400 			serv->p_login (serv, prefs.hex_irc_user_name, prefs.hex_irc_real_name);
401 		}
402 	} else
403 	{
404 		EMIT_SIGNAL (XP_TE_SERVERCONNECTED, serv->server_session, NULL, NULL,
405 						 NULL, NULL, 0);
406 	}
407 
408 	server_set_name (serv, serv->servername);
409 	fe_server_event (serv, FE_SE_CONNECT, 0);
410 }
411 
412 #ifdef WIN32
413 
414 static gboolean
server_close_pipe(int * pipefd)415 server_close_pipe (int *pipefd)	/* see comments below */
416 {
417 	close (pipefd[0]);	/* close WRITE end first to cause an EOF on READ */
418 	close (pipefd[1]);	/* in giowin32, and end that thread. */
419 	g_free (pipefd);
420 	return FALSE;
421 }
422 
423 #endif
424 
425 static void
server_stopconnecting(server * serv)426 server_stopconnecting (server * serv)
427 {
428 	if (serv->iotag)
429 	{
430 		fe_input_remove (serv->iotag);
431 		serv->iotag = 0;
432 	}
433 
434 	if (serv->joindelay_tag)
435 	{
436 		fe_timeout_remove (serv->joindelay_tag);
437 		serv->joindelay_tag = 0;
438 	}
439 
440 #ifndef WIN32
441 	/* kill the child process trying to connect */
442 	kill (serv->childpid, SIGKILL);
443 	waitpid (serv->childpid, NULL, 0);
444 
445 	close (serv->childwrite);
446 	close (serv->childread);
447 #else
448 	PostThreadMessage (serv->childpid, WM_QUIT, 0, 0);
449 
450 	{
451 		/* if we close the pipe now, giowin32 will crash. */
452 		int *pipefd = g_new (int, 2);
453 		pipefd[0] = serv->childwrite;
454 		pipefd[1] = serv->childread;
455 		g_idle_add ((GSourceFunc)server_close_pipe, pipefd);
456 	}
457 #endif
458 
459 #ifdef USE_OPENSSL
460 	if (serv->ssl_do_connect_tag)
461 	{
462 		fe_timeout_remove (serv->ssl_do_connect_tag);
463 		serv->ssl_do_connect_tag = 0;
464 	}
465 #endif
466 
467 	fe_progressbar_end (serv);
468 
469 	serv->connecting = FALSE;
470 	fe_server_event (serv, FE_SE_DISCONNECT, 0);
471 }
472 
473 #ifdef USE_OPENSSL
474 #define	SSLTMOUT	90				  /* seconds */
475 static void
ssl_cb_info(SSL * s,int where,int ret)476 ssl_cb_info (SSL * s, int where, int ret)
477 {
478 /*	char buf[128];*/
479 
480 
481 	return;							  /* FIXME: make debug level adjustable in serverlist or settings */
482 
483 /*	g_snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
484 	if (g_sess)
485 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
486 	else
487 		fprintf (stderr, "%s\n", buf);*/
488 }
489 
490 static int
ssl_cb_verify(int ok,X509_STORE_CTX * ctx)491 ssl_cb_verify (int ok, X509_STORE_CTX * ctx)
492 {
493 	char subject[256];
494 	char issuer[256];
495 	char buf[512];
496 	X509 *current_cert = X509_STORE_CTX_get_current_cert (ctx);
497 
498 	if (!current_cert)
499 		return TRUE;
500 
501 	X509_NAME_oneline (X509_get_subject_name (current_cert),
502 	                   subject, sizeof (subject));
503 	X509_NAME_oneline (X509_get_issuer_name (current_cert),
504 	                   issuer, sizeof (issuer));
505 
506 	g_snprintf (buf, sizeof (buf), "* Subject: %s", subject);
507 	EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
508 	g_snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
509 	EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
510 
511 	return TRUE;
512 }
513 
514 static int
ssl_do_connect(server * serv)515 ssl_do_connect (server * serv)
516 {
517 	char buf[256]; // ERR_error_string() MUST have this size
518 
519 	g_sess = serv->server_session;
520 
521 	/* Set SNI hostname before connect */
522 	SSL_set_tlsext_host_name(serv->ssl, serv->hostname);
523 
524 	if (SSL_connect (serv->ssl) <= 0)
525 	{
526 		char err_buf[128];
527 		int err;
528 
529 		g_sess = NULL;
530 		if ((err = ERR_get_error ()) > 0)
531 		{
532 			ERR_error_string (err, err_buf);
533 			g_snprintf (buf, sizeof (buf), "(%d) %s", err, err_buf);
534 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
535 							 NULL, NULL, 0);
536 
537 			if (ERR_GET_REASON (err) == SSL_R_WRONG_VERSION_NUMBER)
538 				PrintText (serv->server_session, _("Are you sure this is a SSL capable server and port?\n"));
539 
540 			server_cleanup (serv);
541 
542 			if (prefs.hex_net_auto_reconnectonfail)
543 				auto_reconnect (serv, FALSE, -1);
544 
545 			return (0);				  /* remove it (0) */
546 		}
547 	}
548 	g_sess = NULL;
549 
550 	if (SSL_is_init_finished (serv->ssl))
551 	{
552 		struct cert_info cert_info;
553 		struct chiper_info *chiper_info;
554 		int verify_error;
555 		int i;
556 
557 		if (!_SSL_get_cert_info (&cert_info, serv->ssl))
558 		{
559 			g_snprintf (buf, sizeof (buf), "* Certification info:");
560 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
561 							 NULL, 0);
562 			g_snprintf (buf, sizeof (buf), "  Subject:");
563 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
564 							 NULL, 0);
565 			for (i = 0; cert_info.subject_word[i]; i++)
566 			{
567 				g_snprintf (buf, sizeof (buf), "    %s", cert_info.subject_word[i]);
568 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
569 								 NULL, 0);
570 			}
571 			g_snprintf (buf, sizeof (buf), "  Issuer:");
572 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
573 							 NULL, 0);
574 			for (i = 0; cert_info.issuer_word[i]; i++)
575 			{
576 				g_snprintf (buf, sizeof (buf), "    %s", cert_info.issuer_word[i]);
577 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
578 								 NULL, 0);
579 			}
580 			g_snprintf (buf, sizeof (buf), "  Public key algorithm: %s (%d bits)",
581 						 cert_info.algorithm, cert_info.algorithm_bits);
582 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
583 							 NULL, 0);
584 			/*if (cert_info.rsa_tmp_bits)
585 			{
586 				g_snprintf (buf, sizeof (buf),
587 							 "  Public key algorithm uses ephemeral key with %d bits",
588 							 cert_info.rsa_tmp_bits);
589 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
590 								 NULL, 0);
591 			}*/
592 			g_snprintf (buf, sizeof (buf), "  Sign algorithm %s",
593 						 cert_info.sign_algorithm/*, cert_info.sign_algorithm_bits*/);
594 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
595 							 NULL, 0);
596 			g_snprintf (buf, sizeof (buf), "  Valid since %s to %s",
597 						 cert_info.notbefore, cert_info.notafter);
598 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
599 							 NULL, 0);
600 		} else
601 		{
602 			g_snprintf (buf, sizeof (buf), "No Certificate");
603 			goto conn_fail;
604 		}
605 
606 		chiper_info = _SSL_get_cipher_info (serv->ssl);	/* static buffer */
607 		g_snprintf (buf, sizeof (buf), "* Cipher info:");
608 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
609 						 0);
610 		g_snprintf (buf, sizeof (buf), "  Version: %s, cipher %s (%u bits)",
611 					 chiper_info->version, chiper_info->chiper,
612 					 chiper_info->chiper_bits);
613 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
614 						 0);
615 
616 		verify_error = SSL_get_verify_result (serv->ssl);
617 		switch (verify_error)
618 		{
619 		case X509_V_OK:
620 			{
621 				X509 *cert = SSL_get_peer_certificate (serv->ssl);
622 				int hostname_err;
623 				if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0)
624 				{
625 					g_snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s",
626 							 hostname_err, serv->accept_invalid_cert ? " -- Ignored" : "");
627 					if (serv->accept_invalid_cert)
628 						EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0);
629 					else
630 						goto conn_fail;
631 				}
632 				break;
633 			}
634 			/* g_snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
635 			/* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
636 		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
637 		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
638 		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
639 		case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
640 		case X509_V_ERR_CERT_HAS_EXPIRED:
641 			if (serv->accept_invalid_cert)
642 			{
643 				g_snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
644 							 X509_verify_cert_error_string (verify_error),
645 							 verify_error);
646 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
647 								 NULL, 0);
648 				break;
649 			}
650 		default:
651 			g_snprintf (buf, sizeof (buf), "%s.? (%d)",
652 						 X509_verify_cert_error_string (verify_error),
653 						 verify_error);
654 conn_fail:
655 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL,
656 							 NULL, 0);
657 
658 			server_cleanup (serv);
659 
660 			return (0);
661 		}
662 
663 		server_stopconnecting (serv);
664 
665 		/* activate gtk poll */
666 		server_connected (serv);
667 
668 		return (0);					  /* remove it (0) */
669 	} else
670 	{
671 		SSL_SESSION *session = SSL_get_session (serv->ssl);
672 		if (session && SSL_SESSION_get_time (session) + SSLTMOUT < time (NULL))
673 		{
674 			g_snprintf (buf, sizeof (buf), "SSL handshake timed out");
675 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
676 							 NULL, NULL, 0);
677 			server_cleanup (serv); /* ->connecting = FALSE */
678 
679 			if (prefs.hex_net_auto_reconnectonfail)
680 				auto_reconnect (serv, FALSE, -1);
681 
682 			return (0);				  /* remove it (0) */
683 		}
684 
685 		return (1);					  /* call it more (1) */
686 	}
687 }
688 #endif
689 
690 static int
timeout_auto_reconnect(server * serv)691 timeout_auto_reconnect (server *serv)
692 {
693 	if (is_server (serv))  /* make sure it hasnt been closed during the delay */
694 	{
695 		serv->recondelay_tag = 0;
696 		if (!serv->connected && !serv->connecting && serv->server_session)
697 		{
698 			server_connect (serv, serv->hostname, serv->port, FALSE);
699 		}
700 	}
701 	return 0;			  /* returning 0 should remove the timeout handler */
702 }
703 
704 static void
auto_reconnect(server * serv,int send_quit,int err)705 auto_reconnect (server *serv, int send_quit, int err)
706 {
707 	session *s;
708 	int del;
709 
710 	if (serv->server_session == NULL)
711 		return;
712 
713 	if (prefs.hex_irc_reconnect_rejoin)
714 	{
715 		GSList *list;
716 		list = sess_list;
717 		while (list)				  /* make sure auto rejoin can work */
718 		{
719 			s = list->data;
720 			if (s->type == SESS_CHANNEL && s->channel[0])
721 			{
722 				strcpy (s->waitchannel, s->channel);
723 				strcpy (s->willjoinchannel, s->channel);
724 			}
725 			list = list->next;
726 		}
727 	}
728 
729 	if (serv->connected)
730 		server_disconnect (serv->server_session, send_quit, err);
731 
732 	del = prefs.hex_net_reconnect_delay * 1000;
733 	if (del < 1000)
734 		del = 500;				  /* so it doesn't block the gui */
735 
736 #ifndef WIN32
737 	if (err == -1 || err == 0 || err == ECONNRESET || err == ETIMEDOUT)
738 #else
739 	if (err == -1 || err == 0 || err == WSAECONNRESET || err == WSAETIMEDOUT)
740 #endif
741 		serv->reconnect_away = serv->is_away;
742 
743 	/* is this server in a reconnect delay? remove it! */
744 	if (serv->recondelay_tag)
745 	{
746 		fe_timeout_remove (serv->recondelay_tag);
747 		serv->recondelay_tag = 0;
748 	}
749 
750 	serv->recondelay_tag = fe_timeout_add (del, timeout_auto_reconnect, serv);
751 	fe_server_event (serv, FE_SE_RECONDELAY, del);
752 }
753 
754 static void
server_flush_queue(server * serv)755 server_flush_queue (server *serv)
756 {
757 	list_free (&serv->outbound_queue);
758 	serv->sendq_len = 0;
759 	fe_set_throttle (serv);
760 }
761 
762 /* connect() successed */
763 
764 static void
server_connect_success(server * serv)765 server_connect_success (server *serv)
766 {
767 #ifdef USE_OPENSSL
768 #define	SSLDOCONNTMOUT	300
769 	if (serv->use_ssl)
770 	{
771 		char *err;
772 
773 		/* it'll be a memory leak, if connection isn't terminated by
774 		   server_cleanup() */
775 		if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify)))
776 		{
777 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
778 							 NULL, NULL, 0);
779 			server_cleanup (serv);	/* ->connecting = FALSE */
780 			return;
781 		}
782 		serv->ssl = _SSL_socket (serv->ctx, serv->sok);
783 		/* FIXME: it'll be needed by new servers */
784 		/* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */
785 		set_nonblocking (serv->sok);
786 		serv->ssl_do_connect_tag = fe_timeout_add (SSLDOCONNTMOUT,
787 																 ssl_do_connect, serv);
788 		return;
789 	}
790 
791 	serv->ssl = NULL;
792 #endif
793 	server_stopconnecting (serv);	/* ->connecting = FALSE */
794 	/* activate glib poll */
795 	server_connected (serv);
796 }
797 
798 /* receive info from the child-process about connection progress */
799 
800 static gboolean
server_read_child(GIOChannel * source,GIOCondition condition,server * serv)801 server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
802 {
803 	session *sess = serv->server_session;
804 	char tbuf[128];
805 	char outbuf[512];
806 	char host[100];
807 	char ip[100];
808 
809 	waitline2 (source, tbuf, sizeof tbuf);
810 
811 	switch (tbuf[0])
812 	{
813 	case '0':	/* print some text */
814 		waitline2 (source, tbuf, sizeof tbuf);
815 		PrintText (serv->server_session, tbuf);
816 		break;
817 	case '1':						  /* unknown host */
818 		server_stopconnecting (serv);
819 		closesocket (serv->sok4);
820 		if (serv->proxy_sok4 != -1)
821 			closesocket (serv->proxy_sok4);
822 		if (serv->sok6 != -1)
823 			closesocket (serv->sok6);
824 		if (serv->proxy_sok6 != -1)
825 			closesocket (serv->proxy_sok6);
826 		EMIT_SIGNAL (XP_TE_UKNHOST, sess, NULL, NULL, NULL, NULL, 0);
827 		if (!servlist_cycle (serv))
828 			if (prefs.hex_net_auto_reconnectonfail)
829 				auto_reconnect (serv, FALSE, -1);
830 		break;
831 	case '2':						  /* connection failed */
832 		waitline2 (source, tbuf, sizeof tbuf);
833 		server_stopconnecting (serv);
834 		closesocket (serv->sok4);
835 		if (serv->proxy_sok4 != -1)
836 			closesocket (serv->proxy_sok4);
837 		if (serv->sok6 != -1)
838 			closesocket (serv->sok6);
839 		if (serv->proxy_sok6 != -1)
840 			closesocket (serv->proxy_sok6);
841 		EMIT_SIGNAL (XP_TE_CONNFAIL, sess, errorstring (atoi (tbuf)), NULL,
842 						 NULL, NULL, 0);
843 		if (!servlist_cycle (serv))
844 			if (prefs.hex_net_auto_reconnectonfail)
845 				auto_reconnect (serv, FALSE, -1);
846 		break;
847 	case '3':						  /* gethostbyname finished */
848 		waitline2 (source, host, sizeof host);
849 		waitline2 (source, ip, sizeof ip);
850 		waitline2 (source, outbuf, sizeof outbuf);
851 		EMIT_SIGNAL (XP_TE_CONNECT, sess, host, ip, outbuf, NULL, 0);
852 		break;
853 	case '4':						  /* success */
854 		waitline2 (source, tbuf, sizeof (tbuf));
855 		serv->sok = atoi (tbuf);
856 		/* close the one we didn't end up using */
857 		if (serv->sok == serv->sok4)
858 			closesocket (serv->sok6);
859 		else
860 			closesocket (serv->sok4);
861 		if (serv->proxy_sok != -1)
862 		{
863 			if (serv->proxy_sok == serv->proxy_sok4)
864 				closesocket (serv->proxy_sok6);
865 			else
866 				closesocket (serv->proxy_sok4);
867 		}
868 
869 		{
870 			struct sockaddr_storage addr;
871 			int addr_len = sizeof (addr);
872 			guint16 port;
873 			ircnet *net = serv->network;
874 
875 			if (!getsockname (serv->sok, (struct sockaddr *)&addr, &addr_len))
876 			{
877 				if (addr.ss_family == AF_INET)
878 					port = ntohs(((struct sockaddr_in *)&addr)->sin_port);
879 				else
880 					port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port);
881 
882 				g_snprintf (outbuf, sizeof (outbuf), "IDENTD %"G_GUINT16_FORMAT" ", port);
883 				if (net && net->user && !(net->flags & FLAG_USE_GLOBAL))
884 					g_strlcat (outbuf, net->user, sizeof (outbuf));
885 				else
886 					g_strlcat (outbuf, prefs.hex_irc_user_name, sizeof (outbuf));
887 
888 				handle_command (serv->server_session, outbuf, FALSE);
889 			}
890 		}
891 
892 		server_connect_success (serv);
893 		break;
894 	case '5':						  /* prefs ip discovered */
895 		waitline2 (source, tbuf, sizeof tbuf);
896 		prefs.local_ip = inet_addr (tbuf);
897 		break;
898 	case '7':						  /* gethostbyname (prefs.hex_net_bind_host) failed */
899 		sprintf (outbuf,
900 					_("Cannot resolve hostname %s\nCheck your IP Settings!\n"),
901 					prefs.hex_net_bind_host);
902 		PrintText (sess, outbuf);
903 		break;
904 	case '8':
905 		PrintText (sess, _("Proxy traversal failed.\n"));
906 		server_disconnect (sess, FALSE, -1);
907 		break;
908 	case '9':
909 		waitline2 (source, tbuf, sizeof tbuf);
910 		EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, tbuf, NULL, NULL, NULL, 0);
911 		break;
912 	}
913 
914 	return TRUE;
915 }
916 
917 /* kill all sockets & iotags of a server. Stop a connection attempt, or
918    disconnect if already connected. */
919 
920 static int
server_cleanup(server * serv)921 server_cleanup (server * serv)
922 {
923 	fe_set_lag (serv, 0);
924 
925 	if (serv->iotag)
926 	{
927 		fe_input_remove (serv->iotag);
928 		serv->iotag = 0;
929 	}
930 
931 	if (serv->joindelay_tag)
932 	{
933 		fe_timeout_remove (serv->joindelay_tag);
934 		serv->joindelay_tag = 0;
935 	}
936 
937 #ifdef USE_OPENSSL
938 	if (serv->ssl)
939 	{
940 		SSL_shutdown (serv->ssl);
941 		SSL_free (serv->ssl);
942 		serv->ssl = NULL;
943 	}
944 #endif
945 
946 	if (serv->connecting)
947 	{
948 		server_stopconnecting (serv);
949 		closesocket (serv->sok4);
950 		if (serv->proxy_sok4 != -1)
951 			closesocket (serv->proxy_sok4);
952 		if (serv->sok6 != -1)
953 			closesocket (serv->sok6);
954 		if (serv->proxy_sok6 != -1)
955 			closesocket (serv->proxy_sok6);
956 		return 1;
957 	}
958 
959 	if (serv->connected)
960 	{
961 		close_socket (serv->sok);
962 		if (serv->proxy_sok)
963 			close_socket (serv->proxy_sok);
964 		serv->connected = FALSE;
965 		serv->end_of_motd = FALSE;
966 		return 2;
967 	}
968 
969 	/* is this server in a reconnect delay? remove it! */
970 	if (serv->recondelay_tag)
971 	{
972 		fe_timeout_remove (serv->recondelay_tag);
973 		serv->recondelay_tag = 0;
974 		return 3;
975 	}
976 
977 	return 0;
978 }
979 
980 static void
server_disconnect(session * sess,int sendquit,int err)981 server_disconnect (session * sess, int sendquit, int err)
982 {
983 	server *serv = sess->server;
984 	GSList *list;
985 	char tbuf[64];
986 	gboolean shutup = FALSE;
987 
988 	/* send our QUIT reason */
989 	if (sendquit && serv->connected)
990 	{
991 		server_sendquit (sess);
992 	}
993 
994 	fe_server_event (serv, FE_SE_DISCONNECT, 0);
995 
996 	/* close all sockets & io tags */
997 	switch (server_cleanup (serv))
998 	{
999 	case 0:							  /* it wasn't even connected! */
1000 		notc_msg (sess);
1001 		return;
1002 	case 1:							  /* it was in the process of connecting */
1003 		sprintf (tbuf, "%d", sess->server->childpid);
1004 		EMIT_SIGNAL (XP_TE_STOPCONNECT, sess, tbuf, NULL, NULL, NULL, 0);
1005 		return;
1006 	case 3:
1007 		shutup = TRUE;	/* won't print "disconnected" in channels */
1008 	}
1009 
1010 	server_flush_queue (serv);
1011 
1012 	list = sess_list;
1013 	while (list)
1014 	{
1015 		sess = (struct session *) list->data;
1016 		if (sess->server == serv)
1017 		{
1018 			if (!shutup || sess->type == SESS_SERVER)
1019 				/* print "Disconnected" to each window using this server */
1020 				EMIT_SIGNAL (XP_TE_DISCON, sess, errorstring (err), NULL, NULL, NULL, 0);
1021 
1022 			if (!sess->channel[0] || sess->type == SESS_CHANNEL)
1023 				clear_channel (sess);
1024 		}
1025 		list = list->next;
1026 	}
1027 
1028 	serv->pos = 0;
1029 	serv->motd_skipped = FALSE;
1030 	serv->no_login = FALSE;
1031 	serv->servername[0] = 0;
1032 	serv->lag_sent = 0;
1033 
1034 	notify_cleanup ();
1035 }
1036 
1037 /* send a "print text" command to the parent process - MUST END IN \n! */
1038 
1039 static void
proxy_error(int fd,char * msg)1040 proxy_error (int fd, char *msg)
1041 {
1042 	write (fd, "0\n", 2);
1043 	write (fd, msg, strlen (msg));
1044 }
1045 
1046 struct sock_connect
1047 {
1048 	char version;
1049 	char type;
1050 	guint16 port;
1051 	guint32 address;
1052 	char username[10];
1053 };
1054 
1055 /* traverse_socks() returns:
1056  *				0 success                *
1057  *          1 socks traversal failed */
1058 
1059 static int
traverse_socks(int print_fd,int sok,char * serverAddr,int port)1060 traverse_socks (int print_fd, int sok, char *serverAddr, int port)
1061 {
1062 	struct sock_connect sc;
1063 	unsigned char buf[256];
1064 
1065 	sc.version = 4;
1066 	sc.type = 1;
1067 	sc.port = htons (port);
1068 	sc.address = inet_addr (serverAddr);
1069 	g_strlcpy (sc.username, prefs.hex_irc_user_name, sizeof (sc.username));
1070 
1071 	send (sok, (char *) &sc, 8 + strlen (sc.username) + 1, 0);
1072 	buf[1] = 0;
1073 	recv (sok, buf, 10, 0);
1074 	if (buf[1] == 90)
1075 		return 0;
1076 
1077 	g_snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
1078 	proxy_error (print_fd, buf);
1079 	return 1;
1080 }
1081 
1082 struct sock5_connect1
1083 {
1084 	char version;
1085 	char nmethods;
1086 	char method;
1087 };
1088 
1089 static int
traverse_socks5(int print_fd,int sok,char * serverAddr,int port)1090 traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
1091 {
1092 	struct sock5_connect1 sc1;
1093 	unsigned char *sc2;
1094 	unsigned int packetlen, addrlen;
1095 	unsigned char buf[260];
1096 	int auth = prefs.hex_net_proxy_auth && prefs.hex_net_proxy_user[0] && prefs.hex_net_proxy_pass[0];
1097 
1098 	sc1.version = 5;
1099 	sc1.nmethods = 1;
1100 	if (auth)
1101 		sc1.method = 2;  /* Username/Password Authentication (UPA) */
1102 	else
1103 		sc1.method = 0;  /* NO Authentication */
1104 	send (sok, (char *) &sc1, 3, 0);
1105 	if (recv (sok, buf, 2, 0) != 2)
1106 		goto read_error;
1107 
1108 	if (buf[0] != 5)
1109 	{
1110 		proxy_error (print_fd, "SOCKS\tServer is not socks version 5.\n");
1111 		return 1;
1112 	}
1113 
1114 	/* did the server say no auth required? */
1115 	if (buf[1] == 0)
1116 		auth = 0;
1117 
1118 	if (auth)
1119 	{
1120 		int len_u=0, len_p=0;
1121 		unsigned char *u_p_buf;
1122 
1123 		/* authentication sub-negotiation (RFC1929) */
1124 		if (buf[1] != 2)  /* UPA not supported by server */
1125 		{
1126 			proxy_error (print_fd, "SOCKS\tServer doesn't support UPA authentication.\n");
1127 			return 1;
1128 		}
1129 
1130 		/* form the UPA request */
1131 		len_u = strlen (prefs.hex_net_proxy_user);
1132 		len_p = strlen (prefs.hex_net_proxy_pass);
1133 
1134         packetlen = 2 + len_u + 1 + len_p;
1135 		u_p_buf = g_malloc0 (packetlen);
1136 
1137 		u_p_buf[0] = 1;
1138 		u_p_buf[1] = len_u;
1139 		memcpy (u_p_buf + 2, prefs.hex_net_proxy_user, len_u);
1140 		u_p_buf[2 + len_u] = len_p;
1141 		memcpy (u_p_buf + 3 + len_u, prefs.hex_net_proxy_pass, len_p);
1142 
1143 		send (sok, u_p_buf, packetlen, 0);
1144 		g_free(u_p_buf);
1145 
1146 		if ( recv (sok, buf, 2, 0) != 2 )
1147 			goto read_error;
1148 		if ( buf[1] != 0 )
1149 		{
1150 			proxy_error (print_fd, "SOCKS\tAuthentication failed. "
1151 							 "Is username and password correct?\n");
1152 			return 1; /* UPA failed! */
1153 		}
1154 	}
1155 	else
1156 	{
1157 		if (buf[1] != 0)
1158 		{
1159 			proxy_error (print_fd, "SOCKS\tAuthentication required but disabled in settings.\n");
1160 			return 1;
1161 		}
1162 	}
1163 
1164 	addrlen = strlen (serverAddr);
1165 	packetlen = 4 + 1 + addrlen + 2;
1166 	sc2 = g_malloc (packetlen);
1167 	sc2[0] = 5;						  /* version */
1168 	sc2[1] = 1;						  /* command */
1169 	sc2[2] = 0;						  /* reserved */
1170 	sc2[3] = 3;						  /* address type */
1171 	sc2[4] = (unsigned char) addrlen;	/* hostname length */
1172 	memcpy (sc2 + 5, serverAddr, addrlen);
1173 	*((unsigned short *) (sc2 + 5 + addrlen)) = htons (port);
1174 	send (sok, sc2, packetlen, 0);
1175 	g_free (sc2);
1176 
1177 	/* consume all of the reply */
1178 	if (recv (sok, buf, 4, 0) != 4)
1179 		goto read_error;
1180 	if (buf[0] != 5 || buf[1] != 0)
1181 	{
1182 		if (buf[1] == 2)
1183 			g_snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
1184 		else
1185 			g_snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
1186 		proxy_error (print_fd, buf);
1187 		return 1;
1188 	}
1189 	if (buf[3] == 1)	/* IPV4 32bit address */
1190 	{
1191 		if (recv (sok, buf, 6, 0) != 6)
1192 			goto read_error;
1193 	} else if (buf[3] == 4)	/* IPV6 128bit address */
1194 	{
1195 		if (recv (sok, buf, 18, 0) != 18)
1196 			goto read_error;
1197 	} else if (buf[3] == 3)	/* string, 1st byte is size */
1198 	{
1199 		if (recv (sok, buf, 1, 0) != 1)	/* read the string size */
1200 			goto read_error;
1201 		packetlen = buf[0] + 2;	/* can't exceed 260 */
1202 		if (recv (sok, buf, packetlen, 0) != packetlen)
1203 			goto read_error;
1204 	}
1205 
1206 	return 0;	/* success */
1207 
1208 read_error:
1209 	proxy_error (print_fd, "SOCKS\tRead error from server.\n");
1210 	return 1;
1211 }
1212 
1213 static int
traverse_wingate(int print_fd,int sok,char * serverAddr,int port)1214 traverse_wingate (int print_fd, int sok, char *serverAddr, int port)
1215 {
1216 	char buf[128];
1217 
1218 	g_snprintf (buf, sizeof (buf), "%s %d\r\n", serverAddr, port);
1219 	send (sok, buf, strlen (buf), 0);
1220 
1221 	return 0;
1222 }
1223 
1224 /* stuff for HTTP auth is here */
1225 
1226 static void
three_to_four(char * from,char * to)1227 three_to_four (char *from, char *to)
1228 {
1229 	static const char tab64[64]=
1230 	{
1231 		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1232 		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1233 		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1234 		'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1235 	};
1236 
1237 	to[0] = tab64 [ (from[0] >> 2) & 63 ];
1238 	to[1] = tab64 [ ((from[0] << 4) | (from[1] >> 4)) & 63 ];
1239 	to[2] = tab64 [ ((from[1] << 2) | (from[2] >> 6)) & 63 ];
1240 	to[3] = tab64 [ from[2] & 63 ];
1241 };
1242 
1243 void
base64_encode(char * to,char * from,unsigned int len)1244 base64_encode (char *to, char *from, unsigned int len)
1245 {
1246 	while (len >= 3)
1247 	{
1248 		three_to_four (from, to);
1249 		len -= 3;
1250 		from += 3;
1251 		to += 4;
1252 	}
1253 	if (len)
1254 	{
1255 		char three[3] = {0,0,0};
1256 		unsigned int i;
1257 		for (i = 0; i < len; i++)
1258 		{
1259 			three[i] = *from++;
1260 		}
1261 		three_to_four (three, to);
1262 		if (len == 1)
1263 		{
1264 			to[2] = to[3] = '=';
1265 		}
1266 		else if (len == 2)
1267 		{
1268 			to[3] = '=';
1269 		}
1270 		to += 4;
1271 	};
1272 	to[0] = 0;
1273 }
1274 
1275 static int
http_read_line(int print_fd,int sok,char * buf,int len)1276 http_read_line (int print_fd, int sok, char *buf, int len)
1277 {
1278 	len = waitline (sok, buf, len, TRUE);
1279 	if (len >= 1)
1280 	{
1281 		/* print the message out (send it to the parent process) */
1282 		write (print_fd, "0\n", 2);
1283 
1284 		if (buf[len-1] == '\r')
1285 		{
1286 			buf[len-1] = '\n';
1287 			write (print_fd, buf, len);
1288 		} else
1289 		{
1290 			write (print_fd, buf, len);
1291 			write (print_fd, "\n", 1);
1292 		}
1293 	}
1294 
1295 	return len;
1296 }
1297 
1298 static int
traverse_http(int print_fd,int sok,char * serverAddr,int port)1299 traverse_http (int print_fd, int sok, char *serverAddr, int port)
1300 {
1301 	char buf[512];
1302 	char auth_data[256];
1303 	char auth_data2[252];
1304 	int n, n2;
1305 
1306 	n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
1307 					  serverAddr, port);
1308 	if (prefs.hex_net_proxy_auth)
1309 	{
1310 		n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
1311 							prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass);
1312 		base64_encode (auth_data, auth_data2, n2);
1313 		n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
1314 	}
1315 	n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
1316 	send (sok, buf, n, 0);
1317 
1318 	n = http_read_line (print_fd, sok, buf, sizeof (buf));
1319 	/* "HTTP/1.0 200 OK" */
1320 	if (n < 12)
1321 		return 1;
1322 	if (memcmp (buf, "HTTP/", 5) || memcmp (buf + 9, "200", 3))
1323 		return 1;
1324 	while (1)
1325 	{
1326 		/* read until blank line */
1327 		n = http_read_line (print_fd, sok, buf, sizeof (buf));
1328 		if (n < 1 || (n == 1 && buf[0] == '\n'))
1329 			break;
1330 	}
1331 	return 0;
1332 }
1333 
1334 static int
traverse_proxy(int proxy_type,int print_fd,int sok,char * ip,int port,netstore * ns_proxy,int csok4,int csok6,int * csok,char bound)1335 traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
1336 {
1337 	switch (proxy_type)
1338 	{
1339 	case 1:
1340 		return traverse_wingate (print_fd, sok, ip, port);
1341 	case 2:
1342 		return traverse_socks (print_fd, sok, ip, port);
1343 	case 3:
1344 		return traverse_socks5 (print_fd, sok, ip, port);
1345 	case 4:
1346 		return traverse_http (print_fd, sok, ip, port);
1347 	}
1348 
1349 	return 1;
1350 }
1351 
1352 /* this is the child process making the connection attempt */
1353 
1354 static int
server_child(server * serv)1355 server_child (server * serv)
1356 {
1357 	netstore *ns_server;
1358 	netstore *ns_proxy = NULL;
1359 	netstore *ns_local;
1360 	int port = serv->port;
1361 	int error;
1362 	int sok, psok;
1363 	char *hostname = serv->hostname;
1364 	char *real_hostname = NULL;
1365 	char *ip;
1366 	char *proxy_ip = NULL;
1367 	char *local_ip;
1368 	int connect_port;
1369 	char buf[512];
1370 	char bound = 0;
1371 	int proxy_type = 0;
1372 	char *proxy_host = NULL;
1373 	int proxy_port;
1374 
1375 	ns_server = net_store_new ();
1376 
1377 	/* is a hostname set? - bind to it */
1378 	if (prefs.hex_net_bind_host[0])
1379 	{
1380 		ns_local = net_store_new ();
1381 		local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, 0, &real_hostname);
1382 		if (local_ip != NULL)
1383 		{
1384 			g_snprintf (buf, sizeof (buf), "5\n%s\n", local_ip);
1385 			write (serv->childwrite, buf, strlen (buf));
1386 			net_bind (ns_local, serv->sok4, serv->sok6);
1387 			bound = 1;
1388 		} else
1389 		{
1390 			write (serv->childwrite, "7\n", 2);
1391 		}
1392 		net_store_destroy (ns_local);
1393 	}
1394 
1395 	if (!serv->dont_use_proxy) /* blocked in serverlist? */
1396 	{
1397 		if (prefs.hex_net_proxy_type == 5)
1398 		{
1399 			char **proxy_list;
1400 			char *url, *proxy;
1401 			GProxyResolver *resolver;
1402 			GError *error = NULL;
1403 
1404 			resolver = g_proxy_resolver_get_default ();
1405 			url = g_strdup_printf ("irc://%s:%d", hostname, port);
1406 			proxy_list = g_proxy_resolver_lookup (resolver, url, NULL, &error);
1407 
1408 			if (proxy_list) {
1409 				/* can use only one */
1410 				proxy = proxy_list[0];
1411 				if (!strncmp (proxy, "direct", 6))
1412 					proxy_type = 0;
1413 				else if (!strncmp (proxy, "http", 4))
1414 					proxy_type = 4;
1415 				else if (!strncmp (proxy, "socks5", 6))
1416 					proxy_type = 3;
1417 				else if (!strncmp (proxy, "socks", 5))
1418 					proxy_type = 2;
1419 			} else {
1420 				write_error ("Failed to lookup proxy", &error);
1421 			}
1422 
1423 			if (proxy_type) {
1424 				char *c;
1425 				c = strchr (proxy, ':') + 3;
1426 				proxy_host = g_strdup (c);
1427 				c = strchr (proxy_host, ':');
1428 				*c = '\0';
1429 				proxy_port = atoi (c + 1);
1430 			}
1431 
1432 			g_strfreev (proxy_list);
1433 			g_free (url);
1434 		}
1435 
1436 		if (prefs.hex_net_proxy_host[0] &&
1437 			   prefs.hex_net_proxy_type > 0 &&
1438 			   prefs.hex_net_proxy_use != 2) /* proxy is NOT dcc-only */
1439 		{
1440 			proxy_type = prefs.hex_net_proxy_type;
1441 			proxy_host = g_strdup (prefs.hex_net_proxy_host);
1442 			proxy_port = prefs.hex_net_proxy_port;
1443 		}
1444 	}
1445 
1446 	serv->proxy_type = proxy_type;
1447 
1448 	/* first resolve where we want to connect to */
1449 	if (proxy_type > 0)
1450 	{
1451 		g_snprintf (buf, sizeof (buf), "9\n%s\n", proxy_host);
1452 		write (serv->childwrite, buf, strlen (buf));
1453 		ip = net_resolve (ns_server, proxy_host, proxy_port, &real_hostname);
1454 		g_free (proxy_host);
1455 		if (!ip)
1456 		{
1457 			write (serv->childwrite, "1\n", 2);
1458 			goto xit;
1459 		}
1460 		connect_port = proxy_port;
1461 
1462 		/* if using socks4 or MS Proxy, attempt to resolve ip for irc server */
1463 		if ((proxy_type == 2) || (proxy_type == 5))
1464 		{
1465 			ns_proxy = net_store_new ();
1466 			proxy_ip = net_resolve (ns_proxy, hostname, port, &real_hostname);
1467 			if (!proxy_ip)
1468 			{
1469 				write (serv->childwrite, "1\n", 2);
1470 				goto xit;
1471 			}
1472 		} else						  /* otherwise we can just use the hostname */
1473 			proxy_ip = g_strdup (hostname);
1474 	} else
1475 	{
1476 		ip = net_resolve (ns_server, hostname, port, &real_hostname);
1477 		if (!ip)
1478 		{
1479 			write (serv->childwrite, "1\n", 2);
1480 			goto xit;
1481 		}
1482 		connect_port = port;
1483 	}
1484 
1485 	g_snprintf (buf, sizeof (buf), "3\n%s\n%s\n%d\n",
1486 				 real_hostname, ip, connect_port);
1487 	write (serv->childwrite, buf, strlen (buf));
1488 
1489 	if (!serv->dont_use_proxy && (proxy_type == 5))
1490 		error = net_connect (ns_server, serv->proxy_sok4, serv->proxy_sok6, &psok);
1491 	else
1492 	{
1493 		error = net_connect (ns_server, serv->sok4, serv->sok6, &sok);
1494 		psok = sok;
1495 	}
1496 
1497 	if (error != 0)
1498 	{
1499 		g_snprintf (buf, sizeof (buf), "2\n%d\n", sock_error ());
1500 		write (serv->childwrite, buf, strlen (buf));
1501 	} else
1502 	{
1503 		/* connect succeeded */
1504 		if (proxy_ip)
1505 		{
1506 			switch (traverse_proxy (proxy_type, serv->childwrite, psok, proxy_ip, port, ns_proxy, serv->sok4, serv->sok6, &sok, bound))
1507 			{
1508 			case 0:	/* success */
1509 				g_snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
1510 				write (serv->childwrite, buf, strlen (buf));
1511 				break;
1512 			case 1:	/* socks traversal failed */
1513 				write (serv->childwrite, "8\n", 2);
1514 				break;
1515 			}
1516 		} else
1517 		{
1518 			g_snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
1519 			write (serv->childwrite, buf, strlen (buf));
1520 		}
1521 	}
1522 
1523 xit:
1524 
1525 	/* this is probably not needed */
1526 	net_store_destroy (ns_server);
1527 	if (ns_proxy)
1528 		net_store_destroy (ns_proxy);
1529 
1530 	/* no need to free ip/real_hostname, this process is exiting */
1531 #ifdef WIN32
1532 	/* under win32 we use a thread -> shared memory, must free! */
1533 	g_free (proxy_ip);
1534 	g_free (ip);
1535 	g_free (real_hostname);
1536 #endif
1537 
1538 	return 0;
1539 	/* cppcheck-suppress memleak */
1540 }
1541 
1542 static void
server_connect(server * serv,char * hostname,int port,int no_login)1543 server_connect (server *serv, char *hostname, int port, int no_login)
1544 {
1545 	int pid, read_des[2];
1546 	session *sess = serv->server_session;
1547 
1548 #ifdef USE_OPENSSL
1549 	if (!serv->ctx && serv->use_ssl)
1550 	{
1551 		if (!(serv->ctx = _SSL_context_init (ssl_cb_info)))
1552 		{
1553 			fprintf (stderr, "_SSL_context_init failed\n");
1554 			exit (1);
1555 		}
1556 	}
1557 #endif
1558 
1559 	if (!hostname[0])
1560 		return;
1561 
1562 	if (port < 0)
1563 	{
1564 		/* use default port for this server type */
1565 		port = 6667;
1566 #ifdef USE_OPENSSL
1567 		if (serv->use_ssl)
1568 			port = 6697;
1569 #endif
1570 	}
1571 	port &= 0xffff;	/* wrap around */
1572 
1573 	if (serv->connected || serv->connecting || serv->recondelay_tag)
1574 		server_disconnect (sess, TRUE, -1);
1575 
1576 	fe_progressbar_start (sess);
1577 
1578 	EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, hostname, NULL, NULL, NULL, 0);
1579 
1580 	safe_strcpy (serv->servername, hostname, sizeof (serv->servername));
1581 	/* overlap illegal in strncpy */
1582 	if (hostname != serv->hostname)
1583 		safe_strcpy (serv->hostname, hostname, sizeof (serv->hostname));
1584 
1585 #ifdef USE_OPENSSL
1586 	if (serv->use_ssl)
1587 	{
1588 		char *cert_file;
1589 		serv->have_cert = FALSE;
1590 
1591 		/* first try network specific cert/key */
1592 		cert_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
1593 					 get_xdir (), server_get_network (serv, TRUE));
1594 		if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
1595 		{
1596 			if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
1597 				serv->have_cert = TRUE;
1598 		}
1599 		else
1600 		{
1601 			/* if that doesn't exist, try <config>/certs/client.pem */
1602 			cert_file = g_build_filename (get_xdir (), "certs", "client.pem", NULL);
1603 			if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
1604 			{
1605 				if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
1606 					serv->have_cert = TRUE;
1607 			}
1608 		}
1609 		g_free (cert_file);
1610 	}
1611 #endif
1612 
1613 	server_set_defaults (serv);
1614 	serv->connecting = TRUE;
1615 	serv->port = port;
1616 	serv->no_login = no_login;
1617 
1618 	fe_server_event (serv, FE_SE_CONNECTING, 0);
1619 	fe_set_away (serv);
1620 	server_flush_queue (serv);
1621 
1622 #ifdef WIN32
1623 	if (_pipe (read_des, 4096, _O_BINARY) < 0)
1624 #else
1625 	if (pipe (read_des) < 0)
1626 #endif
1627 		return;
1628 #ifdef __EMX__ /* os/2 */
1629 	setmode (read_des[0], O_BINARY);
1630 	setmode (read_des[1], O_BINARY);
1631 #endif
1632 	serv->childread = read_des[0];
1633 	serv->childwrite = read_des[1];
1634 
1635 	/* create both sockets now, drop one later */
1636 	net_sockets (&serv->sok4, &serv->sok6);
1637 	serv->proxy_sok4 = -1;
1638 	serv->proxy_sok6 = -1;
1639 
1640 #ifdef WIN32
1641 	CloseHandle (CreateThread (NULL, 0,
1642 										(LPTHREAD_START_ROUTINE)server_child,
1643 										serv, 0, (DWORD *)&pid));
1644 #else
1645 #ifdef LOOKUPD
1646 	/* CL: net_resolve calls rand() when LOOKUPD is set, so prepare a different
1647 	 * seed for each child. This method gives a bigger variation in seed values
1648 	 * than calling srand(time(0)) in the child itself.
1649 	 */
1650 	rand();
1651 #endif
1652 	switch (pid = fork ())
1653 	{
1654 	case -1:
1655 		return;
1656 
1657 	case 0:
1658 		/* this is the child */
1659 		setuid (getuid ());
1660 		server_child (serv);
1661 		_exit (0);
1662 	}
1663 #endif
1664 	serv->childpid = pid;
1665 #ifdef WIN32
1666 	serv->iotag = fe_input_add (serv->childread, FIA_READ|FIA_FD, server_read_child,
1667 #else
1668 	serv->iotag = fe_input_add (serv->childread, FIA_READ, server_read_child,
1669 #endif
1670 										 serv);
1671 }
1672 
1673 void
server_fill_her_up(server * serv)1674 server_fill_her_up (server *serv)
1675 {
1676 	serv->connect = server_connect;
1677 	serv->disconnect = server_disconnect;
1678 	serv->cleanup = server_cleanup;
1679 	serv->flush_queue = server_flush_queue;
1680 	serv->auto_reconnect = auto_reconnect;
1681 
1682 	proto_fill_her_up (serv);
1683 }
1684 
1685 void
server_set_encoding(server * serv,char * new_encoding)1686 server_set_encoding (server *serv, char *new_encoding)
1687 {
1688 	char *space;
1689 
1690 	g_free (serv->encoding);
1691 
1692 	if (new_encoding)
1693 	{
1694 		serv->encoding = g_strdup (new_encoding);
1695 		/* the serverlist GUI might have added a space
1696 			and short description - remove it. */
1697 		space = strchr (serv->encoding, ' ');
1698 		if (space)
1699 			space[0] = 0;
1700 
1701 		/* Default legacy "IRC" encoding to utf-8. */
1702 		if (g_ascii_strcasecmp (serv->encoding, "IRC") == 0)
1703 		{
1704 			g_free (serv->encoding);
1705 			serv->encoding = g_strdup ("UTF-8");
1706 		}
1707 
1708 		else if (!servlist_check_encoding (serv->encoding))
1709 		{
1710 			g_free (serv->encoding);
1711 			serv->encoding = g_strdup ("UTF-8");
1712 		}
1713 	}
1714 	else
1715 	{
1716 		serv->encoding = g_strdup ("UTF-8");
1717 	}
1718 
1719 	if (serv->read_converter != NULL)
1720 	{
1721 		g_iconv_close (serv->read_converter);
1722 	}
1723 	serv->read_converter = g_iconv_open ("UTF-8", serv->encoding);
1724 
1725 	if (serv->write_converter != NULL)
1726 	{
1727 		g_iconv_close (serv->write_converter);
1728 	}
1729 	serv->write_converter = g_iconv_open (serv->encoding, "UTF-8");
1730 }
1731 
1732 server *
server_new(void)1733 server_new (void)
1734 {
1735 	static int id = 0;
1736 	server *serv;
1737 
1738 	serv = g_new0 (struct server, 1);
1739 
1740 	/* use server.c and proto-irc.c functions */
1741 	server_fill_her_up (serv);
1742 
1743 	serv->id = id++;
1744 	serv->sok = -1;
1745 	strcpy (serv->nick, prefs.hex_irc_nick1);
1746 	server_set_defaults (serv);
1747 
1748 	serv_list = g_slist_prepend (serv_list, serv);
1749 
1750 	fe_new_server (serv);
1751 
1752 	return serv;
1753 }
1754 
1755 int
is_server(server * serv)1756 is_server (server *serv)
1757 {
1758 	return g_slist_find (serv_list, serv) ? 1 : 0;
1759 }
1760 
1761 void
server_set_defaults(server * serv)1762 server_set_defaults (server *serv)
1763 {
1764 	g_free (serv->chantypes);
1765 	g_free (serv->chanmodes);
1766 	g_free (serv->nick_prefixes);
1767 	g_free (serv->nick_modes);
1768 
1769 	serv->chantypes = g_strdup ("#&!+");
1770 	serv->chanmodes = g_strdup ("beI,k,l");
1771 	serv->nick_prefixes = g_strdup ("@%+");
1772 	serv->nick_modes = g_strdup ("ohv");
1773 	serv->modes_per_line = 3; /* https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.3.1 */
1774 	serv->sasl_mech = MECH_PLAIN;
1775 
1776 	if (!serv->encoding)
1777 		server_set_encoding (serv, "UTF-8");
1778 
1779 	serv->nickcount = 1;
1780 	serv->end_of_motd = FALSE;
1781 	serv->sent_capend = FALSE;
1782 	serv->use_listargs = FALSE;
1783 	serv->is_away = FALSE;
1784 	serv->supports_watch = FALSE;
1785 	serv->supports_monitor = FALSE;
1786 	serv->bad_prefix = FALSE;
1787 	serv->use_who = TRUE;
1788 	serv->have_namesx = FALSE;
1789 	serv->have_awaynotify = FALSE;
1790 	serv->have_uhnames = FALSE;
1791 	serv->have_whox = FALSE;
1792 	serv->have_idmsg = FALSE;
1793 	serv->have_accnotify = FALSE;
1794 	serv->have_extjoin = FALSE;
1795 	serv->have_account_tag = FALSE;
1796 	serv->have_server_time = FALSE;
1797 	serv->have_sasl = FALSE;
1798 	serv->have_except = FALSE;
1799 	serv->have_invite = FALSE;
1800 }
1801 
1802 char *
server_get_network(server * serv,gboolean fallback)1803 server_get_network (server *serv, gboolean fallback)
1804 {
1805 	/* check the network list */
1806 	if (serv->network)
1807 		return ((ircnet *)serv->network)->name;
1808 
1809 	/* check the network name given in 005 NETWORK=... */
1810 	if (serv->server_session && *serv->server_session->channel)
1811 		return serv->server_session->channel;
1812 
1813 	if (fallback)
1814 		return serv->servername;
1815 
1816 	return NULL;
1817 }
1818 
1819 void
server_set_name(server * serv,char * name)1820 server_set_name (server *serv, char *name)
1821 {
1822 	GSList *list = sess_list;
1823 	session *sess;
1824 
1825 	if (name[0] == 0)
1826 		name = serv->hostname;
1827 
1828 	/* strncpy parameters must NOT overlap */
1829 	if (name != serv->servername)
1830 	{
1831 		safe_strcpy (serv->servername, name, sizeof (serv->servername));
1832 	}
1833 
1834 	while (list)
1835 	{
1836 		sess = (session *) list->data;
1837 		if (sess->server == serv)
1838 			fe_set_title (sess);
1839 		list = list->next;
1840 	}
1841 
1842 	if (serv->server_session->type == SESS_SERVER)
1843 	{
1844 		if (serv->network)
1845 		{
1846 			safe_strcpy (serv->server_session->channel, ((ircnet *)serv->network)->name, CHANLEN);
1847 		} else
1848 		{
1849 			safe_strcpy (serv->server_session->channel, name, CHANLEN);
1850 		}
1851 		fe_set_channel (serv->server_session);
1852 	}
1853 }
1854 
1855 struct away_msg *
server_away_find_message(server * serv,char * nick)1856 server_away_find_message (server *serv, char *nick)
1857 {
1858 	struct away_msg *away;
1859 	GSList *list = away_list;
1860 	while (list)
1861 	{
1862 		away = (struct away_msg *) list->data;
1863 		if (away->server == serv && !serv->p_cmp (nick, away->nick))
1864 			return away;
1865 		list = list->next;
1866 	}
1867 	return NULL;
1868 }
1869 
1870 static void
server_away_free_messages(server * serv)1871 server_away_free_messages (server *serv)
1872 {
1873 	GSList *list, *next;
1874 	struct away_msg *away;
1875 
1876 	list = away_list;
1877 	while (list)
1878 	{
1879 		away = list->data;
1880 		next = list->next;
1881 		if (away->server == serv)
1882 		{
1883 			away_list = g_slist_remove (away_list, away);
1884 			g_free (away->message);
1885 			g_free (away);
1886 			next = away_list;
1887 		}
1888 		list = next;
1889 	}
1890 }
1891 
1892 void
server_away_save_message(server * serv,char * nick,char * msg)1893 server_away_save_message (server *serv, char *nick, char *msg)
1894 {
1895 	struct away_msg *away = server_away_find_message (serv, nick);
1896 
1897 	if (away)						  /* Change message for known user */
1898 	{
1899 		g_free (away->message);
1900 		away->message = g_strdup (msg);
1901 	}
1902 	else
1903 	{
1904 		/* Create brand new entry */
1905 		away = g_new(struct away_msg, 1);
1906 		away->server = serv;
1907 		safe_strcpy (away->nick, nick, sizeof (away->nick));
1908 		away->message = g_strdup (msg);
1909 		away_list = g_slist_prepend (away_list, away);
1910 	}
1911 }
1912 
1913 void
server_free(server * serv)1914 server_free (server *serv)
1915 {
1916 	serv->cleanup (serv);
1917 
1918 	serv_list = g_slist_remove (serv_list, serv);
1919 
1920 	dcc_notify_kill (serv);
1921 	serv->flush_queue (serv);
1922 	server_away_free_messages (serv);
1923 
1924 	g_free (serv->nick_modes);
1925 	g_free (serv->nick_prefixes);
1926 	g_free (serv->chanmodes);
1927 	g_free (serv->chantypes);
1928 	g_free (serv->bad_nick_prefixes);
1929 	g_free (serv->last_away_reason);
1930 	g_free (serv->encoding);
1931 
1932 	g_iconv_close (serv->read_converter);
1933 	g_iconv_close (serv->write_converter);
1934 
1935 	if (serv->favlist)
1936 		g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
1937 #ifdef USE_OPENSSL
1938 	if (serv->ctx)
1939 		_SSL_context_free (serv->ctx);
1940 #endif
1941 
1942 	fe_server_callback (serv);
1943 
1944 	g_free (serv);
1945 
1946 	notify_cleanup ();
1947 }
1948