diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/command.c | 25 | ||||
-rw-r--r-- | src/common/session.c | 90 | ||||
-rw-r--r-- | src/common/session.h | 2 |
3 files changed, 111 insertions, 6 deletions
diff --git a/src/common/command.c b/src/common/command.c index 5e395dfe1..60795911e 100644 --- a/src/common/command.c +++ b/src/common/command.c @@ -61,7 +61,8 @@ t_weechat_command weechat_commands[] = N_("[(decode_iso | decode_utf | encode) charset]"), N_("decode_iso: charset used for decoding ISO\n" "decode_utf: charset used for decoding UTF\n" - " encode: charset used for encoding messages"), + " encode: charset used for encoding messages\n" + " charset: charset to use (for example: ISO-8859-15, UTF-8,..)"), 0, 2, weechat_cmd_charset, NULL }, { "clear", N_("clear window(s)"), N_("[-all]"), @@ -3067,7 +3068,18 @@ weechat_cmd_upgrade (t_gui_window *window, int argc, char **argv) irc_display_prefix (NULL, NULL, PREFIX_ERROR); gui_printf_nolog (NULL, _("%s can't upgrade: connection to at least " - "one server is pending"), + "one server is pending\n"), + WEECHAT_ERROR); + return -1; + } + /* TODO: remove this test, and fix gnutls save/load in session */ + if (ptr_server->is_connected && ptr_server->ssl_connected) + { + irc_display_prefix (NULL, NULL, PREFIX_ERROR); + gui_printf_nolog (NULL, + _("%s can't upgrade: connection to at least " + "one SSL server is active " + "(should be fixed in a future version)\n"), WEECHAT_ERROR); return -1; } @@ -3105,6 +3117,15 @@ weechat_cmd_upgrade (t_gui_window *window, int argc, char **argv) fifo_remove (); if (weechat_log_file) fclose (weechat_log_file); + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + if (ptr_server->ssl_connected) + { + gnutls_bye (ptr_server->gnutls_sess, GNUTLS_SHUT_RDWR); + gnutls_deinit (ptr_server->gnutls_sess); + } + } #ifdef HAVE_GNUTLS gnutls_certificate_free_credentials (gnutls_xcred); gnutls_global_deinit(); diff --git a/src/common/session.c b/src/common/session.c index 833ea874d..c830e0f7e 100644 --- a/src/common/session.c +++ b/src/common/session.c @@ -30,6 +30,10 @@ #include <stdarg.h> #include <string.h> +#ifdef HAVE_GNUTLS +#include <gnutls/gnutls.h> +#endif + #include "weechat.h" #include "session.h" #include "../irc/irc.h" @@ -190,6 +194,8 @@ int session_save_servers (FILE *file) { int rc; + void *session_data; + size_t session_size; t_irc_server *ptr_server; t_irc_channel *ptr_channel; @@ -226,7 +232,17 @@ session_save_servers (FILE *file) rc = rc && (session_write_int (file, SESSION_SERV_IS_CONNECTED, ptr_server->is_connected)); rc = rc && (session_write_int (file, SESSION_SERV_SSL_CONNECTED, ptr_server->ssl_connected)); #ifdef HAVE_GNUTLS - rc = rc && (session_write_buf (file, SESSION_SERV_GNUTLS_SESS, &(ptr_server->gnutls_sess), sizeof (gnutls_session))); + if (ptr_server->is_connected && ptr_server->ssl_connected) + { + gnutls_session_get_data (ptr_server->gnutls_sess, NULL, &session_size); + if (session_size > 0) + { + session_data = malloc (session_size); + gnutls_session_get_data (ptr_server->gnutls_sess, session_data, &session_size); + rc = rc && (session_write_buf (file, SESSION_SERV_GNUTLS_SESS, &(session_data), session_size)); + free (session_data); + } + } #endif rc = rc && (session_write_str (file, SESSION_SERV_UNTERMINATED_MESSAGE, ptr_server->unterminated_message)); rc = rc && (session_write_str (file, SESSION_SERV_NICK, ptr_server->nick)); @@ -562,7 +578,7 @@ session_read_buf (FILE *file, void *buffer, int length_expected) if (fread ((void *)(&length), sizeof (int), 1, file) == 0) return 0; - if ((length_expected > 0) && (length != length_expected)) + if ((length <= 0) || ((length_expected > 0) && (length != length_expected))) { session_crash (file, _("invalid length for a buffer")); return 0; @@ -578,6 +594,46 @@ session_read_buf (FILE *file, void *buffer, int length_expected) } /* + * session_read_buf_alloc: read buffer from file and allocate it in memory + */ + +int +session_read_buf_alloc (FILE *file, void **buffer, int *buffer_length) +{ + char type; + + session_last_read_pos = ftell (file); + session_last_read_length = sizeof (char); + + if (fread ((void *)(&type), sizeof (char), 1, file) == 0) + return 0; + if (type != SESSION_TYPE_BUF) + { + session_crash (file, _("wrong type in file (expected: %d, read: %d)"), + SESSION_TYPE_BUF, type); + return 0; + } + + session_last_read_pos = ftell (file); + session_last_read_length = sizeof (int); + + if (fread ((void *)(buffer_length), sizeof (int), 1, file) == 0) + return 0; + if (*buffer_length <= 0) + { + session_crash (file, _("invalid length for a buffer")); + return 0; + } + + *buffer = malloc (*buffer_length); + + session_last_read_pos = ftell (file); + session_last_read_length = *buffer_length; + + return (fread (*buffer, *buffer_length, 1, file) > 0); +} + +/* * session_read_object: read an object in file */ @@ -683,6 +739,12 @@ session_load_server (FILE *file) { int object_id, rc; char *server_name; + void *session_data; + size_t session_size; + int session_size_int; +#ifdef HAVE_GNUTLS + const int cert_type_prio[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; +#endif /* read server name */ server_name = NULL; @@ -805,7 +867,29 @@ session_load_server (FILE *file) break; #ifdef HAVE_GNUTLS case SESSION_SERV_GNUTLS_SESS: - rc = rc && (session_read_buf (file, &(session_current_server->gnutls_sess), sizeof (gnutls_session))); + if (gnutls_init (&(session_current_server->gnutls_sess), GNUTLS_CLIENT) != 0) + { + session_crash (file, _("gnutls init error")); + return 0; + } + gnutls_set_default_priority (session_current_server->gnutls_sess); + gnutls_certificate_type_set_priority (session_current_server->gnutls_sess, cert_type_prio); + gnutls_credentials_set (session_current_server->gnutls_sess, GNUTLS_CRD_CERTIFICATE, gnutls_xcred); + session_data = NULL; + rc = rc && (session_read_buf_alloc (file, &session_data, &session_size_int)); + if (rc) + { + session_size = session_size_int; + gnutls_session_set_data (session_current_server->gnutls_sess, session_data, session_size); + free (session_data); + gnutls_transport_set_ptr (session_current_server->gnutls_sess, + (gnutls_transport_ptr) session_current_server->sock); + if (gnutls_handshake (session_current_server->gnutls_sess) < 0) + { + session_crash (file, _("gnutls handshake failed")); + return 0; + } + } break; #endif case SESSION_SERV_UNTERMINATED_MESSAGE: diff --git a/src/common/session.h b/src/common/session.h index f0e29df72..befbd85da 100644 --- a/src/common/session.h +++ b/src/common/session.h @@ -87,7 +87,7 @@ enum t_session_server SESSION_SERV_LAG_NEXT_CHECK, SESSION_SERV_CHARSET_DECODE_ISO, SESSION_SERV_CHARSET_DECODE_UTF, - SESSION_SERV_CHARSET_ENCODE + SESSION_SERV_CHARSET_ENCODE, }; enum t_session_channel |