diff --git a/docs/help/in/server.in b/docs/help/in/server.in index f6706daf..32fdeced 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -20,6 +20,7 @@ certificate file. -ssl_pass: The password for the SSL client private key or certificate. -ssl_verify: Verifies the SSL certificate of the server. + -ssl_self_signed: OK if verified certificate is self signed. -ssl_cafile: The file with the list of CA certificates. -ssl_capath: The directory which contains the CA certificates. -auto: Automatically connects to the server on startup. diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 8d1ac3eb..ed266c05 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -102,6 +102,8 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, conn->ssl_pass = g_strdup(tmp); if (g_hash_table_lookup(optlist, "ssl_verify") != NULL) conn->ssl_verify = TRUE; + if (g_hash_table_lookup(optlist, "ssl_self_signed") != NULL) + conn->ssl_self_signed = TRUE; if ((tmp = g_hash_table_lookup(optlist, "ssl_cafile")) != NULL) conn->ssl_cafile = g_strdup(tmp); if ((tmp = g_hash_table_lookup(optlist, "ssl_capath")) != NULL) @@ -137,7 +139,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, } /* SYNTAX: CONNECT [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] - [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] + [-ssl_verify] [-ssl_self_signed] [-ssl_cafile ] [-ssl_capath ] [-!] [-noautosendcmd] [-noproxy] [-network ] [-host ] [-rawlog ] @@ -243,7 +245,7 @@ static void sig_default_command_server(const char *data, SERVER_REC *server, } /* SYNTAX: SERVER [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] - [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] + [-ssl_verify] [-ssl_self_signed] [-ssl_cafile ] [-ssl_capath ] [-!] [-noautosendcmd] [-noproxy] [-network ] [-host ] [-rawlog ] @@ -483,7 +485,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_pass 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_self_signed +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 e16403ec..23eb83db 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -46,6 +46,7 @@ typedef struct SSL *ssl; SSL_CTX *ctx; unsigned int verify:1; + unsigned int self_signed:1; SERVER_REC *server; int port; } GIOSSLChannel; @@ -206,6 +207,7 @@ static gboolean irssi_ssl_verify_hostname(X509 *cert, const char *hostname) static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, const char* hostname, int port, X509 *cert, SERVER_REC *server) { long result; + gboolean self_signed = server->connrec->ssl_self_signed; #ifdef HAVE_DANE int dane_ret; struct val_daneparams daneparams; @@ -242,6 +244,8 @@ static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, const char* hostname, i result = SSL_get_verify_result(ssl); if (result != X509_V_OK) { + if ((result != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && !self_signed) || + (result != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN && !self_signed)) { unsigned char md[EVP_MAX_MD_SIZE]; unsigned int n; char *str; @@ -276,6 +280,9 @@ static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, const char* hostname, i } } return FALSE; + } else { + g_warning(" WARNING: Accepting self signed Certificate"); + } } else if (! irssi_ssl_verify_hostname(cert, hostname)){ return FALSE; } @@ -461,6 +468,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ const char *cafile = server->connrec->ssl_cafile; const char *capath = server->connrec->ssl_capath; gboolean verify = server->connrec->ssl_verify; + gboolean self_signed = server->connrec->ssl_self_signed; g_return_val_if_fail(handle != NULL, NULL); @@ -542,6 +550,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ chan->server = server; chan->port = port; chan->verify = verify; + chan->self_signed = self_signed; gchan = (GIOChannel *)chan; gchan->funcs = &irssi_ssl_channel_funcs; diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index 17537508..17a7fc08 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -39,6 +39,7 @@ unsigned int no_autosendcmd:1; /* don't execute autosendcmd */ unsigned int unix_socket:1; /* Connect using named unix socket */ unsigned int use_ssl:1; /* this connection uses SSL */ unsigned int ssl_verify:1; +unsigned int ssl_self_signed:1; unsigned int no_connect:1; /* don't connect() at all, it's done by plugin */ char *channels; char *away_reason; diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h index ae797559..c11db9b0 100644 --- a/src/core/server-setup-rec.h +++ b/src/core/server-setup-rec.h @@ -26,5 +26,6 @@ unsigned int banned:1; /* if we're banned from this server */ unsigned int dns_error:1; /* DNS said the host doesn't exist */ unsigned int use_ssl:1; /* this connection uses SSL */ unsigned int ssl_verify:1; +unsigned int ssl_self_signed:1; GHashTable *module_data; diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index d99a5405..b795b94e 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -195,6 +195,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) dest->ssl_cert = g_strdup(src->ssl_cert); dest->ssl_pkey = g_strdup(src->ssl_pkey); dest->ssl_verify = src->ssl_verify; + dest->ssl_self_signed = src->ssl_self_signed; dest->ssl_cafile = g_strdup(src->ssl_cafile); dest->ssl_capath = g_strdup(src->ssl_capath); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 27d9f1f0..c8081b17 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -175,6 +175,7 @@ static void server_setup_fill_server(SERVER_CONNECT_REC *conn, 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; + conn->ssl_self_signed = sserver->ssl_self_signed; if (conn->ssl_cafile == NULL && sserver->ssl_cafile != NULL && sserver->ssl_cafile[0] != '\0') conn->ssl_cafile = g_strdup(sserver->ssl_cafile); if (conn->ssl_capath == NULL && sserver->ssl_capath != NULL && sserver->ssl_capath[0] != '\0') @@ -403,6 +404,7 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node) 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_self_signed = config_node_get_bool(node, "ssl_self_signed", 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)); if (rec->ssl_cafile || rec->ssl_capath) @@ -443,6 +445,7 @@ static void server_setup_save(SERVER_SETUP_REC *rec) 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_bool(node, "ssl_self_signed", rec->ssl_self_signed); iconfig_node_set_str(node, "ssl_cafile", rec->ssl_cafile); iconfig_node_set_str(node, "ssl_capath", rec->ssl_capath); iconfig_node_set_str(node, "own_host", rec->own_host); diff --git a/src/core/session.c b/src/core/session.c index b3002632..49edcb66 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -163,6 +163,7 @@ static void session_save_server(SERVER_REC *server, CONFIG_REC *config, config_node_set_str(config, node, "ssl_cert", server->connrec->ssl_cert); config_node_set_str(config, node, "ssl_pkey", server->connrec->ssl_pkey); config_node_set_bool(config, node, "ssl_verify", server->connrec->ssl_verify); + config_node_set_bool(config, node, "ssl_self_signed", server->connrec->ssl_self_signed); config_node_set_str(config, node, "ssl_cafile", server->connrec->ssl_cafile); config_node_set_str(config, node, "ssl_capath", server->connrec->ssl_capath); diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index 2dec1d8a..5b9240b3 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -164,6 +164,9 @@ static void cmd_server_add(const char *data) if (g_hash_table_lookup(optlist, "ssl_verify")) rec->ssl_verify = TRUE; + + if (g_hash_table_lookup(optlist, "ssl_self_signed")) + rec->ssl_self_signed = TRUE; value = g_hash_table_lookup(optlist, "ssl_cafile"); if (value != NULL && *value != '\0') @@ -387,7 +390,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_pass ssl_verify +ssl_cafile +ssl_capath auto noauto proxy noproxy -host -port noautosendcmd"); + command_set_options("server add", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify ssl_self_signed +ssl_cafile +ssl_capath auto noauto proxy noproxy -host -port noautosendcmd"); 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 abde1112..531efe36 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -51,7 +51,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 ] [-ssl_pass ] - [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] + [-ssl_verify] [-ssl_self_signed] [-ssl_cafile ] [-ssl_capath ] [-auto | -noauto] [-network ] [-host ] [-cmdspeed ] [-cmdmax ] [-port ]
[ []] */ @@ -117,6 +117,8 @@ static void cmd_server_list(const char *data) } if (rec->ssl_verify) g_string_append(str, "ssl_verify, "); + if (rec->ssl_self_signed) + g_string_append(str, "ssl_self_signed, "); if (rec->ssl_cafile) g_string_append_printf(str, "ssl_cafile: %s, ", rec->ssl_cafile); if (rec->ssl_capath)