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