diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | doc/de/autogen/user/weechat_options.txt | 5 | ||||
-rw-r--r-- | doc/en/autogen/user/weechat_options.txt | 5 | ||||
-rw-r--r-- | doc/fr/autogen/user/weechat_options.txt | 5 | ||||
-rw-r--r-- | doc/it/autogen/user/weechat_options.txt | 5 | ||||
-rw-r--r-- | po/cs.po | 6 | ||||
-rw-r--r-- | po/de.po | 7 | ||||
-rw-r--r-- | po/es.po | 7 | ||||
-rw-r--r-- | po/fr.po | 9 | ||||
-rw-r--r-- | po/hu.po | 6 | ||||
-rw-r--r-- | po/it.po | 6 | ||||
-rw-r--r-- | po/pl.po | 7 | ||||
-rw-r--r-- | po/pt_BR.po | 5 | ||||
-rw-r--r-- | po/ru.po | 6 | ||||
-rw-r--r-- | po/weechat.pot | 5 | ||||
-rw-r--r-- | src/core/wee-config.c | 6 | ||||
-rw-r--r-- | src/core/wee-config.h | 1 | ||||
-rw-r--r-- | src/core/wee-hook.c | 22 | ||||
-rw-r--r-- | src/core/wee-hook.h | 4 | ||||
-rw-r--r-- | src/core/wee-network.c | 135 |
20 files changed, 235 insertions, 21 deletions
@@ -1,12 +1,14 @@ WeeChat ChangeLog ================= Sébastien Helleu <flashcode@flashtux.org> -v0.3.4-dev, 2010-11-14 +v0.3.4-dev, 2010-11-18 Version 0.3.4 (under dev!) -------------------------- +* core: fix infinite loop on gnutls handshake when connecting with SSL to server + on wrong port or server with SSL problems (bug #27487) * core: fix data sent to callback of hook_process (some data was sometimes missing), use a 64KB buffer for child output and send data to callback only when buffer is full diff --git a/doc/de/autogen/user/weechat_options.txt b/doc/de/autogen/user/weechat_options.txt index 46e216972..7a044afe8 100644 --- a/doc/de/autogen/user/weechat_options.txt +++ b/doc/de/autogen/user/weechat_options.txt @@ -588,6 +588,11 @@ ** Typ: Zeichenkette ** Werte: beliebige Zeichenkette (Standardwert: `"%h/ssl/CAs.pem"`) +* *weechat.network.gnutls_handshake_timeout* +** Beschreibung: `timeout (in seconds) for gnutls handshake` +** Typ: integer +** Werte: 1 .. 2147483647 (Standardwert: `30`) + * *weechat.plugin.autoload* ** Beschreibung: `Eine durch Kommata getrennte Liste der Erweiterungen die beim Programmstart automatisch geladen werden sollen, "*" lädt alle gefundenen Erweiterungen. Beginnt der Name hingegen mit "!" wird die Erweiterung nicht geladen. Suchmuster können mit einem Joker ("*") beginnen oder enden um mehrere Erweiterungen zu laden (Beispiele: "*" oder "*,!lua,!tcl")` ** Typ: Zeichenkette diff --git a/doc/en/autogen/user/weechat_options.txt b/doc/en/autogen/user/weechat_options.txt index 225cd21c1..c7ef6665f 100644 --- a/doc/en/autogen/user/weechat_options.txt +++ b/doc/en/autogen/user/weechat_options.txt @@ -588,6 +588,11 @@ ** type: string ** values: any string (default value: `"%h/ssl/CAs.pem"`) +* *weechat.network.gnutls_handshake_timeout* +** description: `timeout (in seconds) for gnutls handshake` +** type: integer +** values: 1 .. 2147483647 (default value: `30`) + * *weechat.plugin.autoload* ** description: `comma separated list of plugins to load automatically at startup, "*" means all plugins found, a name beginning with "!" is a negative value to prevent a plugin from being loaded, names can start or end with "*" to match several plugins (examples: "*" or "*,!lua,!tcl")` ** type: string diff --git a/doc/fr/autogen/user/weechat_options.txt b/doc/fr/autogen/user/weechat_options.txt index 0bbf00937..8a3fe004e 100644 --- a/doc/fr/autogen/user/weechat_options.txt +++ b/doc/fr/autogen/user/weechat_options.txt @@ -588,6 +588,11 @@ ** type: chaîne ** valeurs: toute chaîne (valeur par défaut: `"%h/ssl/CAs.pem"`) +* *weechat.network.gnutls_handshake_timeout* +** description: `délai d'attente maximum (en secondes) pour la poignée de main (handshake) gnutls` +** type: entier +** valeurs: 1 .. 2147483647 (valeur par défaut: `30`) + * *weechat.plugin.autoload* ** description: `liste des extensions à charger automatiquement au démarrage (séparées par des virgules), "*" signifie toutes les extensions trouvées, un nom commençant par "!" est une valeur négative pour empêcher une extension d'être chargée, les noms peuvent commencer ou se terminer par "*" pour indiquer plusieurs extensions (exemples: "*" ou "*,!lua,!tcl")` ** type: chaîne diff --git a/doc/it/autogen/user/weechat_options.txt b/doc/it/autogen/user/weechat_options.txt index cfc22c7b6..139fd70e4 100644 --- a/doc/it/autogen/user/weechat_options.txt +++ b/doc/it/autogen/user/weechat_options.txt @@ -588,6 +588,11 @@ ** tipo: stringa ** valori: qualsiasi stringa (valore predefinito: `"%h/ssl/CAs.pem"`) +* *weechat.network.gnutls_handshake_timeout* +** descrizione: `timeout (in seconds) for gnutls handshake` +** tipo: intero +** valori: 1 .. 2147483647 (valore predefinito: `30`) + * *weechat.plugin.autoload* ** descrizione: `elenco separato da virgole di plugin da caricare automaticamente all'avvio, "*" equivale a tutti i plugin trovati. un nome che comincia con "!" è un valore negativo per impedire il caricamento di un plugin, i nomi possono iniziare o finire con "*" per corrispondere a più plugin (esempi: "*" oppure "*,!lua,!tcl")` ** tipo: stringa @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-06 11:55+0100\n" "Last-Translator: Jiri Golembiovsky <golemj@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -2261,6 +2261,10 @@ msgstr "" "cesta pro hledání pluginů (\"%h\" bude nahrazeno domácím adresářem WeeChat, " "\"~/.weechat\" je výchozí)" +#, fuzzy +msgid "timeout (in seconds) for gnutls handshake" +msgstr "časový limit (v sekundách) před vzdaním SASL autentizace" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " @@ -22,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.3-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-06 11:55+0100\n" "Last-Translator: Nils G.\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -2363,6 +2363,11 @@ msgstr "" "Suchpfad für Erweiterungen (\"%h\"' wird durch das WeeChat-Basisverzeichnis " "ersetzt, voreingestellt ist \"~/.weechat\")" +#, fuzzy +msgid "timeout (in seconds) for gnutls handshake" +msgstr "" +"Zeitüberschreitung (in Sekunden) bis zum Abbruch der SASL Authentifizierung" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-06 11:56+0100\n" "Last-Translator: Elián Hanisch <lambdae2@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -2288,6 +2288,11 @@ msgstr "" "ruta para encontrar plugins (\"%h\" será reemplazado por el directorio raíz " "de WeeChat, \"~/.weechat\" por defecto)" +#, fuzzy +msgid "timeout (in seconds) for gnutls handshake" +msgstr "" +"tiempo de espera (en segundos) antes de abandonar la autenticación por SASL" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " @@ -21,8 +21,8 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" -"PO-Revision-Date: 2010-11-13 10:12+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" +"PO-Revision-Date: 2010-11-18 17:29+0100\n" "Last-Translator: Sebastien Helleu <flashcode@flashtux.org>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" "Language: French\n" @@ -2321,6 +2321,11 @@ msgstr "" "fichier contenant les autorités de certification (\"%h\" sera remplacé par " "le répertoire de base WeeChat, par défaut: \"~/.weechat\")" +msgid "timeout (in seconds) for gnutls handshake" +msgstr "" +"délai d'attente maximum (en secondes) pour la poignée de main (handshake) " +"gnutls" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-05 17:17+0100\n" "Last-Translator: Andras Voroskoi <voroskoi@frugalware.org>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -2104,6 +2104,10 @@ msgstr "" "könyvtára, alapértelmezésben ~/.weechat, kerül)" #, fuzzy +msgid "timeout (in seconds) for gnutls handshake" +msgstr "SSL használata a a kapcsolathoz" + +#, fuzzy msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-06 11:56+0100\n" "Last-Translator: Marco Paolone <marcopaolone@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -2301,6 +2301,10 @@ msgstr "" "percorso per la ricerca dei plugin (\"%h\" sarà sostituito dalla home di " "WeeChat, \"~/.weechat come predefinita)" +#, fuzzy +msgid "timeout (in seconds) for gnutls handshake" +msgstr "timeout (in secondi) prima di annullare l'autenticazione SASL" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-06 11:56+0100\n" "Last-Translator: Krzysztof Koroscik <soltys@szluug.org>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -2289,6 +2289,11 @@ msgstr "" "ścieżka wyszukiwania wtyczek (\"%h\" zostanie zastąpione katalogiem domowym " "WeeChat - domyślnie \"~/.weechat\")" +#, fuzzy +msgid "timeout (in seconds) for gnutls handshake" +msgstr "" +"czas oczekiwania (w sekundach) przed zaprzestaniem uwierzytelniania SASL" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " diff --git a/po/pt_BR.po b/po/pt_BR.po index ed7d86c72..0ea8a77da 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-13 09:26+0100\n" "Last-Translator: Ivan Sichmann Freitas <ivansichfreitas@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -1843,6 +1843,9 @@ msgid "" "WeeChat home, \"~/.weechat\" by default)" msgstr "" +msgid "timeout (in seconds) for gnutls handshake" +msgstr "" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.3.4-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: 2010-11-05 17:17+0100\n" "Last-Translator: Pavel Shevchuk <stlwrt@gmail.com>\n" "Language-Team: weechat-dev <weechat-dev@nongnu.org>\n" @@ -2119,6 +2119,10 @@ msgstr "" "умолчанию - ~/.weechat)" #, fuzzy +msgid "timeout (in seconds) for gnutls handshake" +msgstr "использовать SSL при связи с сервером" + +#, fuzzy msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " diff --git a/po/weechat.pot b/po/weechat.pot index 7aa5aff52..5f675f7d9 100644 --- a/po/weechat.pot +++ b/po/weechat.pot @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2010-11-12 21:37+0100\n" +"POT-Creation-Date: 2010-11-18 17:28+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -1783,6 +1783,9 @@ msgid "" "WeeChat home, \"~/.weechat\" by default)" msgstr "" +msgid "timeout (in seconds) for gnutls handshake" +msgstr "" + msgid "" "comma separated list of plugins to load automatically at startup, \"*\" " "means all plugins found, a name beginning with \"!\" is a negative value to " diff --git a/src/core/wee-config.c b/src/core/wee-config.c index f0324af09..cb3526758 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -186,6 +186,7 @@ struct t_config_option *config_history_display_default; /* config, network section */ struct t_config_option *config_network_gnutls_ca_file; +struct t_config_option *config_network_gnutls_handshake_timeout; /* config, plugin section */ @@ -2034,6 +2035,11 @@ config_weechat_init_options () N_("file containing the certificate authorities (\"%h\" will be " "replaced by WeeChat home, \"~/.weechat\" by default)"), NULL, 0, 0, "%h/ssl/CAs.pem", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + config_network_gnutls_handshake_timeout = config_file_new_option ( + weechat_config_file, ptr_section, + "gnutls_handshake_timeout", "integer", + N_("timeout (in seconds) for gnutls handshake"), + NULL, 1, INT_MAX, "30", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); /* plugin */ ptr_section = config_file_new_section (weechat_config_file, "plugin", diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 99046f5a0..d84476384 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -207,6 +207,7 @@ extern struct t_config_option *config_history_max_visited_buffers; extern struct t_config_option *config_history_display_default; extern struct t_config_option *config_network_gnutls_ca_file; +extern struct t_config_option *config_network_gnutls_handshake_timeout; extern struct t_config_option *config_plugin_autoload; extern struct t_config_option *config_plugin_debug; diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index d7c674a11..e1c852b17 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -1687,6 +1687,10 @@ hook_connect (struct t_weechat_plugin *plugin, const char *proxy, const char *ad new_hook_connect->child_write = -1; new_hook_connect->child_pid = 0; new_hook_connect->hook_fd = NULL; + new_hook_connect->handshake_hook_fd = NULL; + new_hook_connect->handshake_hook_timer = NULL; + new_hook_connect->handshake_fd_flags = 0; + new_hook_connect->handshake_ip_address = NULL; hook_add_to_list (new_hook); @@ -2695,6 +2699,12 @@ unhook (struct t_hook *hook) free (HOOK_CONNECT(hook, local_hostname)); if (HOOK_CONNECT(hook, hook_fd)) unhook (HOOK_CONNECT(hook, hook_fd)); + if (HOOK_CONNECT(hook, handshake_hook_fd)) + unhook (HOOK_CONNECT(hook, handshake_hook_fd)); + if (HOOK_CONNECT(hook, handshake_hook_timer)) + unhook (HOOK_CONNECT(hook, handshake_hook_timer)); + if (HOOK_CONNECT(hook, handshake_ip_address)) + free (HOOK_CONNECT(hook, handshake_ip_address)); if (HOOK_CONNECT(hook, child_pid) > 0) { kill (HOOK_CONNECT(hook, child_pid), SIGKILL); @@ -3001,6 +3011,14 @@ hook_add_to_infolist_type (struct t_infolist *infolist, return 0; if (!infolist_new_var_pointer (ptr_item, "hook_fd", HOOK_CONNECT(ptr_hook, hook_fd))) return 0; + if (!infolist_new_var_pointer (ptr_item, "handshake_hook_fd", HOOK_CONNECT(ptr_hook, handshake_hook_fd))) + return 0; + if (!infolist_new_var_pointer (ptr_item, "handshake_hook_timer", HOOK_CONNECT(ptr_hook, handshake_hook_timer))) + return 0; + if (!infolist_new_var_integer (ptr_item, "handshake_fd_flags", HOOK_CONNECT(ptr_hook, handshake_fd_flags))) + return 0; + if (!infolist_new_var_string (ptr_item, "handshake_ip_address", HOOK_CONNECT(ptr_hook, handshake_ip_address))) + return 0; } break; case HOOK_TYPE_PRINT: @@ -3332,6 +3350,10 @@ hook_print_log () log_printf (" child_write . . . . . : %d", HOOK_CONNECT(ptr_hook, child_write)); log_printf (" child_pid . . . . . . : %d", HOOK_CONNECT(ptr_hook, child_pid)); log_printf (" hook_fd . . . . . . . : 0x%lx", HOOK_CONNECT(ptr_hook, hook_fd)); + log_printf (" handshake_hook_fd . . : 0x%lx", HOOK_CONNECT(ptr_hook, handshake_hook_fd)); + log_printf (" handshake_hook_timer. : 0x%lx", HOOK_CONNECT(ptr_hook, handshake_hook_timer)); + log_printf (" handshake_fd_flags. . : %d", HOOK_CONNECT(ptr_hook, handshake_fd_flags)); + log_printf (" handshake_ip_address. : '%s'", HOOK_CONNECT(ptr_hook, handshake_ip_address)); } break; case HOOK_TYPE_PRINT: diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index e842865f3..2cd9fd760 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -226,6 +226,10 @@ struct t_hook_connect int child_write; /* to write data in pipe for child */ pid_t child_pid; /* pid of child process (connecting) */ struct t_hook *hook_fd; /* pointer to fd hook */ + struct t_hook *handshake_hook_fd; /* fd hook for handshake */ + struct t_hook *handshake_hook_timer; /* timer for handshake timeout */ + int handshake_fd_flags; /* socket flags saved for handshake */ + char *handshake_ip_address; /* ip address (used for handshake) */ }; /* hook print */ diff --git a/src/core/wee-network.c b/src/core/wee-network.c index cdb4bbe05..972cbfdac 100644 --- a/src/core/wee-network.c +++ b/src/core/wee-network.c @@ -27,6 +27,7 @@ #endif #include <unistd.h> +#include <fcntl.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -726,6 +727,94 @@ network_connect_child (struct t_hook *hook_connect) } /* + * network_connect_gnutls_handshake_fd_cb: callback for gnutls handshake + * (used to not block WeeChat if + * handshake takes some time to finish) + */ + +#ifdef HAVE_GNUTLS +int +network_connect_gnutls_handshake_fd_cb (void *arg_hook_connect, int fd) +{ + struct t_hook *hook_connect; + int rc, direction, flags; + + /* make C compiler happy */ + (void) fd; + + hook_connect = (struct t_hook *)arg_hook_connect; + + rc = gnutls_handshake (*HOOK_CONNECT(hook_connect, gnutls_sess)); + + if ((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) + { + direction = gnutls_record_get_direction (*HOOK_CONNECT(hook_connect, gnutls_sess)); + flags = HOOK_FD(HOOK_CONNECT(hook_connect, handshake_hook_fd), flags); + if ((((flags & HOOK_FD_FLAG_READ) == HOOK_FD_FLAG_READ) + && (direction != 0)) + || (((flags & HOOK_FD_FLAG_WRITE) == HOOK_FD_FLAG_WRITE) + && (direction != 1))) + { + HOOK_FD(HOOK_CONNECT(hook_connect, handshake_hook_fd), flags) = + (direction) ? HOOK_FD_FLAG_WRITE: HOOK_FD_FLAG_READ; + } + } + else if (rc != GNUTLS_E_SUCCESS) + { + (void) (HOOK_CONNECT(hook_connect, callback)) + (hook_connect->callback_data, + WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR, + rc, + gnutls_strerror (rc), + HOOK_CONNECT(hook_connect, handshake_ip_address)); + unhook (hook_connect); + } + else + { + fcntl (HOOK_CONNECT(hook_connect, sock), F_SETFL, + HOOK_CONNECT(hook_connect, handshake_fd_flags)); + unhook (HOOK_CONNECT(hook_connect, handshake_hook_fd)); + (void) (HOOK_CONNECT(hook_connect, callback)) + (hook_connect->callback_data, WEECHAT_HOOK_CONNECT_OK, 0, NULL, + HOOK_CONNECT(hook_connect, handshake_ip_address)); + unhook (hook_connect); + } + + return WEECHAT_RC_OK; +} +#endif + +/* + * network_connect_gnutls_handshake_timer_cb: timer for timeout on handshake + */ + +#ifdef HAVE_GNUTLS +int +network_connect_gnutls_handshake_timer_cb (void *arg_hook_connect, + int remaining_calls) +{ + struct t_hook *hook_connect; + + /* make C compiler happy */ + (void) remaining_calls; + + hook_connect = (struct t_hook *)arg_hook_connect; + + HOOK_CONNECT(hook_connect, handshake_hook_timer) = NULL; + + (void) (HOOK_CONNECT(hook_connect, callback)) + (hook_connect->callback_data, + WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR, + GNUTLS_E_EXPIRED, + gnutls_strerror (GNUTLS_E_EXPIRED), + HOOK_CONNECT(hook_connect, handshake_ip_address)); + unhook (hook_connect); + + return WEECHAT_RC_OK; +} +#endif + +/* * network_connect_child_read_cb: read connection progress from child process */ @@ -737,7 +826,7 @@ network_connect_child_read_cb (void *arg_hook_connect, int fd) int num_read; long size_ip; #ifdef HAVE_GNUTLS - int rc; + int rc, direction; #endif /* make C compiler happy */ @@ -780,21 +869,47 @@ network_connect_child_read_cb (void *arg_hook_connect, int fd) #ifdef HAVE_GNUTLS if (HOOK_CONNECT(hook_connect, gnutls_sess)) { + /* + * the socket needs to be non-blocking since the call to + * gnutls_handshake can block + */ + HOOK_CONNECT(hook_connect, handshake_fd_flags) = + fcntl (HOOK_CONNECT(hook_connect, sock), F_GETFL); + fcntl (HOOK_CONNECT(hook_connect, sock), F_SETFL, + HOOK_CONNECT(hook_connect, handshake_fd_flags) | O_NONBLOCK); gnutls_transport_set_ptr (*HOOK_CONNECT(hook_connect, gnutls_sess), (gnutls_transport_ptr) ((unsigned long) HOOK_CONNECT(hook_connect, sock))); - if (HOOK_CONNECT(hook_connect, gnutls_dhkey_size) > 0) { + if (HOOK_CONNECT (hook_connect, gnutls_dhkey_size) > 0) + { gnutls_dh_set_prime_bits (*HOOK_CONNECT(hook_connect, gnutls_sess), (unsigned int) HOOK_CONNECT(hook_connect, gnutls_dhkey_size)); } - while (1) + rc = gnutls_handshake (*HOOK_CONNECT(hook_connect, gnutls_sess)); + if ((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { - rc = gnutls_handshake (*HOOK_CONNECT(hook_connect, gnutls_sess)); - if ((rc == GNUTLS_E_SUCCESS) - || ((rc != GNUTLS_E_AGAIN) && (rc != GNUTLS_E_INTERRUPTED))) - break; - usleep (1000); + /* + * gnutls was unable to proceed with the handshake without + * blocking: non fatal error, we just have to wait for an + * event about handshake + */ + direction = gnutls_record_get_direction (*HOOK_CONNECT(hook_connect, gnutls_sess)); + HOOK_CONNECT(hook_connect, handshake_ip_address) = ip_address; + HOOK_CONNECT(hook_connect, handshake_hook_fd) = + hook_fd (hook_connect->plugin, + HOOK_CONNECT(hook_connect, sock), + (!direction ? 1 : 0), (direction ? 1 : 0), 0, + //1, 1, 0, + &network_connect_gnutls_handshake_fd_cb, + hook_connect); + HOOK_CONNECT(hook_connect, handshake_hook_timer) = + hook_timer (hook_connect->plugin, + CONFIG_INTEGER(config_network_gnutls_handshake_timeout) * 1000, + 0, 1, + &network_connect_gnutls_handshake_timer_cb, + hook_connect); + return WEECHAT_RC_OK; } - if (rc != GNUTLS_E_SUCCESS) + else if (rc != GNUTLS_E_SUCCESS) { (void) (HOOK_CONNECT(hook_connect, callback)) (hook_connect->callback_data, @@ -807,6 +922,8 @@ network_connect_child_read_cb (void *arg_hook_connect, int fd) free (ip_address); return WEECHAT_RC_OK; } + fcntl (HOOK_CONNECT(hook_connect, sock), F_SETFL, + HOOK_CONNECT(hook_connect, handshake_fd_flags)); } #endif } |