diff --git a/NEWS b/NEWS index f21ee455..91a209b8 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ v0.8.16-rc1 2013-06-26 The Irssi team configuration file. + Disabled support for the insecure SSLv2 protocol. + Various documentation enhancements. + + Add -ssl_pass to /connect and /server (see bug #305). - Fix crashing bug that can happen if the terminal height decreases before the first window is created. - Fixed minor compiler warnings. @@ -21,7 +22,7 @@ v0.8.16-rc1 2013-06-26 The Irssi team - Fixed signal handling for /exec'd commands. Irssi now sends the signal to the process group id instead of the process id. - Fixed segfault generated by SSL disconnections (see bug #752). - - Fix compilation when built with -Werror=format-security. Patch by + - Fix compilation when build with -Werror=format-security. Patch by Jaroslav Skarvada. v0.8.15 2010-04-03 The Irssi team diff --git a/docs/help/in/connect.in b/docs/help/in/connect.in index a00e383d..c06ce999 100644 --- a/docs/help/in/connect.in +++ b/docs/help/in/connect.in @@ -5,6 +5,7 @@ -ssl: use SSL when connecting -ssl_cert: The SSL client certificate file (implies -ssl) -ssl_pkey: The SSL client private key (if not included in the certificate file) + -ssl_pass: The password for the SSL client private key or certificate. -ssl_verify: Verify servers SSL certificate -ssl_cafile: File with list of CA certificates (implies -ssl_verify) -ssl_capath: Directory with CA certificates (implies -ssl_verify) diff --git a/docs/help/in/server.in b/docs/help/in/server.in index 18d837bc..5f2909ce 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -5,6 +5,7 @@ -ssl: use SSL when connecting -ssl_cert: The SSL client certificate file (implies -ssl) -ssl_pkey: The SSL client private key (if not included in the certificate file) + -ssl_pass: The password for the SSL client private key or certificate. -ssl_verify: Verify servers SSL certificate -ssl_cafile: File with list of CA certificates (implies -ssl_verify) -ssl_capath: Directory with CA certificates (implies -ssl_verify) diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index f5d0e9f8..c128439d 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -98,6 +98,8 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, conn->ssl_cert = g_strdup(tmp); if ((tmp = g_hash_table_lookup(optlist, "ssl_pkey")) != NULL) conn->ssl_pkey = g_strdup(tmp); + if ((tmp = g_hash_table_lookup(optlist, "ssl_pass")) != NULL) + conn->ssl_pass = g_strdup(tmp); if (g_hash_table_lookup(optlist, "ssl_verify") != NULL) conn->ssl_verify = TRUE; if ((tmp = g_hash_table_lookup(optlist, "ssl_cafile")) != NULL) @@ -134,7 +136,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, return conn; } -/* SYNTAX: CONNECT [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] +/* SYNTAX: CONNECT [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] [-!] [-noautosendcmd] [-noproxy] [-network ] [-host ] @@ -240,7 +242,7 @@ static void sig_default_command_server(const char *data, SERVER_REC *server, signal_emit("command server connect", 3, data, server, item); } -/* SYNTAX: SERVER [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] +/* SYNTAX: SERVER [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] [-!] [-noautosendcmd] [-noproxy] [-network ] [-host ] @@ -458,7 +460,7 @@ void chat_commands_init(void) signal_add("default command server", (SIGNAL_FUNC) sig_default_command_server); signal_add("server sendmsg", (SIGNAL_FUNC) sig_server_sendmsg); - command_set_options("connect", "4 6 !! -network ssl +ssl_cert +ssl_pkey ssl_verify +ssl_cafile +ssl_capath +host noproxy -rawlog noautosendcmd"); + command_set_options("connect", "4 6 !! -network ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +host noproxy -rawlog noautosendcmd"); command_set_options("msg", "channel nick"); } diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 514f748e..6a0d078c 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -429,6 +429,24 @@ static gboolean irssi_ssl_init(void) } +static int get_pem_password_callback(char *buffer, int max_length, int rwflag, void *pass) +{ + char *password; + size_t length; + + if (pass == NULL) + return 0; + + password = (char *)pass; + length = strlen(pass); + + if (length > max_length) + return 0; + + memcpy(buffer, password, length + 1); + return length; +} + static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_REC *server) { GIOSSLChannel *chan; @@ -439,6 +457,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ const char *mycert = server->connrec->ssl_cert; const char *mypkey = server->connrec->ssl_pkey; + const char *mypass = server->connrec->ssl_pass; const char *cafile = server->connrec->ssl_cafile; const char *capath = server->connrec->ssl_capath; gboolean verify = server->connrec->ssl_verify; @@ -457,6 +476,8 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return NULL; } SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_default_passwd_cb(ctx, get_pem_password_callback); + SSL_CTX_set_default_passwd_cb_userdata(ctx, mypass); if (mycert && *mycert) { char *scert = NULL, *spkey = NULL; @@ -464,9 +485,9 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ if (mypkey && *mypkey) spkey = convert_home(mypkey); if (! SSL_CTX_use_certificate_file(ctx, scert, SSL_FILETYPE_PEM)) - g_warning("Loading of client certificate '%s' failed", mycert); + g_warning("Loading of client certificate '%s' failed: %s", mycert, ERR_reason_error_string(ERR_get_error())); else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM)) - g_warning("Loading of private key '%s' failed", mypkey ? mypkey : mycert); + g_warning("Loading of private key '%s' failed: %s", mypkey ? mypkey : mycert, ERR_reason_error_string(ERR_get_error())); else if (! SSL_CTX_check_private_key(ctx)) g_warning("Private key does not match the certificate"); g_free(scert); diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index a9588f04..17537508 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -25,6 +25,7 @@ char *realname; char *ssl_cert; char *ssl_pkey; +char *ssl_pass; char *ssl_cafile; char *ssl_capath; diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h index b7a0c80d..ae797559 100644 --- a/src/core/server-setup-rec.h +++ b/src/core/server-setup-rec.h @@ -10,6 +10,7 @@ char *password; char *ssl_cert; char *ssl_pkey; +char *ssl_pass; char *ssl_cafile; char *ssl_capath; diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 83b90db3..fcb0180b 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -169,6 +169,8 @@ static void server_setup_fill_server(SERVER_CONNECT_REC *conn, conn->ssl_cert = g_strdup(sserver->ssl_cert); if (conn->ssl_pkey == NULL && sserver->ssl_pkey != NULL && sserver->ssl_pkey[0] != '\0') conn->ssl_pkey = g_strdup(sserver->ssl_pkey); + if (conn->ssl_pass == NULL && sserver->ssl_pass != NULL && sserver->ssl_pass[0] != '\0') + conn->ssl_pass = g_strdup(sserver->ssl_pass); conn->ssl_verify = sserver->ssl_verify; if (conn->ssl_cafile == NULL && sserver->ssl_cafile != NULL && sserver->ssl_cafile[0] != '\0') conn->ssl_cafile = g_strdup(sserver->ssl_cafile); @@ -396,6 +398,7 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node) rec->use_ssl = config_node_get_bool(node, "use_ssl", FALSE); rec->ssl_cert = g_strdup(config_node_get_str(node, "ssl_cert", NULL)); rec->ssl_pkey = g_strdup(config_node_get_str(node, "ssl_pkey", NULL)); + rec->ssl_pass = g_strdup(config_node_get_str(node, "ssl_pass", NULL)); rec->ssl_verify = config_node_get_bool(node, "ssl_verify", FALSE); rec->ssl_cafile = g_strdup(config_node_get_str(node, "ssl_cafile", NULL)); rec->ssl_capath = g_strdup(config_node_get_str(node, "ssl_capath", NULL)); @@ -435,6 +438,7 @@ static void server_setup_save(SERVER_SETUP_REC *rec) iconfig_node_set_bool(node, "use_ssl", rec->use_ssl); iconfig_node_set_str(node, "ssl_cert", rec->ssl_cert); iconfig_node_set_str(node, "ssl_pkey", rec->ssl_pkey); + iconfig_node_set_str(node, "ssl_pass", rec->ssl_pass); iconfig_node_set_bool(node, "ssl_verify", rec->ssl_verify); iconfig_node_set_str(node, "ssl_cafile", rec->ssl_cafile); iconfig_node_set_str(node, "ssl_capath", rec->ssl_capath); @@ -476,6 +480,7 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec) g_free_not_null(rec->password); g_free_not_null(rec->ssl_cert); g_free_not_null(rec->ssl_pkey); + g_free_not_null(rec->ssl_pass); g_free_not_null(rec->ssl_cafile); g_free_not_null(rec->ssl_capath); g_free(rec->address); diff --git a/src/core/servers.c b/src/core/servers.c index d0e6bb7e..eb2be4de 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -635,6 +635,7 @@ void server_connect_unref(SERVER_CONNECT_REC *conn) g_free_not_null(conn->ssl_cert); g_free_not_null(conn->ssl_pkey); + g_free_not_null(conn->ssl_pass); g_free_not_null(conn->ssl_cafile); g_free_not_null(conn->ssl_capath); diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index e4b32bdb..f13829db 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -158,6 +158,10 @@ static void cmd_server_add(const char *data) if (value != NULL && *value != '\0') rec->ssl_pkey = g_strdup(value); + value = g_hash_table_lookup(optlist, "ssl_pass"); + if (value != NULL && *value != '\0') + rec->ssl_pass = g_strdup(value); + if (g_hash_table_lookup(optlist, "ssl_verify")) rec->ssl_verify = TRUE; @@ -383,7 +387,7 @@ void fe_server_init(void) command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove); command_bind_first("server", NULL, (SIGNAL_FUNC) server_command); command_bind_first("disconnect", NULL, (SIGNAL_FUNC) server_command); - command_set_options("server add", "4 6 ssl +ssl_cert +ssl_pkey ssl_verify +ssl_cafile +ssl_capath auto noauto proxy noproxy -host -port"); + command_set_options("server add", "4 6 ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath auto noauto proxy noproxy -host -port"); signal_add("server looking", (SIGNAL_FUNC) sig_server_looking); signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting); diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c index 9bc68762..fbfe4d9d 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -50,7 +50,7 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target) return target; } -/* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] +/* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] [-auto | -noauto] [-network ] [-host ] [-cmdspeed ] [-cmdmax ] [-port ] @@ -112,6 +112,8 @@ static void cmd_server_list(const char *data) g_string_append_printf(str, "ssl_cert: %s, ", rec->ssl_cert); if (rec->ssl_pkey) g_string_append_printf(str, "ssl_pkey: %s, ", rec->ssl_pkey); + if (rec->ssl_pass) + g_string_append_printf(str, "(pass), "); } if (rec->ssl_verify) g_string_append(str, "ssl_verify, ");