mirror of
https://github.com/irssi/irssi.git
synced 2024-11-03 04:27:19 -05:00
Support for sending SSL certificate to server and optionally verify server's
certificate. See the -ssl_* options for /SERVER and /SERVER ADD. Patch by Joel Eriksson <je-irssi@bitnux.com>. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3146 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
b1e2d7b5ef
commit
43b0d36ee1
@ -40,7 +40,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
CHAT_PROTOCOL_REC *proto;
|
||||
SERVER_CONNECT_REC *conn;
|
||||
GHashTable *optlist;
|
||||
char *addr, *portstr, *password, *nick, *chatnet, *host;
|
||||
char *addr, *portstr, *password, *nick, *chatnet, *host, *tmp;
|
||||
void *free_arg;
|
||||
|
||||
g_return_val_if_fail(data != NULL, NULL);
|
||||
@ -88,7 +88,22 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
else if (g_hash_table_lookup(optlist, "4") != NULL)
|
||||
conn->family = AF_INET;
|
||||
|
||||
if(g_hash_table_lookup(optlist, "ssl") != NULL)
|
||||
if (g_hash_table_lookup(optlist, "ssl") != NULL)
|
||||
conn->use_ssl = TRUE;
|
||||
if ((tmp = g_hash_table_lookup(optlist, "ssl_cert")) != NULL)
|
||||
conn->ssl_cert = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "ssl_pkey")) != NULL)
|
||||
conn->ssl_pkey = 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)
|
||||
conn->ssl_cafile = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "ssl_capath")) != NULL)
|
||||
conn->ssl_capath = g_strdup(tmp);
|
||||
if ((conn->ssl_capath != NULL && conn->ssl_capath[0] != '\0')
|
||||
|| (conn->ssl_cafile != NULL && conn->ssl_cafile[0] != '\0'))
|
||||
conn->ssl_verify = TRUE;
|
||||
if ((conn->ssl_cert != NULL && conn->ssl_cert[0] != '\0') || conn->ssl_verify)
|
||||
conn->use_ssl = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "!") != NULL)
|
||||
@ -112,9 +127,11 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
return conn;
|
||||
}
|
||||
|
||||
/* SYNTAX: CONNECT [-4 | -6] [-ssl] [-noproxy] [-ircnet <ircnet>]
|
||||
[-host <hostname>] [-rawlog <file>]
|
||||
<address>|<chatnet> [<port> [<password> [<nick>]]] */
|
||||
/* SYNTAX: CONNECT [-4 | -6] [-ssl] [-ssl_cert <cert>] [-ssl_pkey <pkey>]
|
||||
[-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>]
|
||||
[-noproxy] [-ircnet <ircnet>] [-host <hostname>]
|
||||
[-rawlog <file>]
|
||||
<address>|<chatnet> [<port> [<password> [<nick>]]] */
|
||||
static void cmd_connect(const char *data)
|
||||
{
|
||||
SERVER_CONNECT_REC *conn;
|
||||
@ -214,8 +231,10 @@ 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] [-noproxy] [-ircnet <ircnet>]
|
||||
[-host <hostname>] [-rawlog <file>]
|
||||
/* SYNTAX: SERVER [-4 | -6] [-ssl] [-ssl_cert <cert>] [-ssl_pkey <pkey>]
|
||||
[-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>]
|
||||
[-noproxy] [-ircnet <ircnet>] [-host <hostname>]
|
||||
[-rawlog <file>]
|
||||
[+]<address>|<chatnet> [<port> [<password> [<nick>]]] */
|
||||
static void cmd_server_connect(const char *data, SERVER_REC *server)
|
||||
{
|
||||
@ -445,7 +464,7 @@ void chat_commands_init(void)
|
||||
|
||||
signal_add("default command server", (SIGNAL_FUNC) sig_default_command_server);
|
||||
|
||||
command_set_options("connect", "4 6 !! ssl +host noproxy -rawlog");
|
||||
command_set_options("connect", "4 6 !! ssl +ssl_cert +ssl_pkey ssl_verify +ssl_cafile +ssl_capath +host noproxy -rawlog");
|
||||
command_set_options("join", "invite");
|
||||
command_set_options("msg", "channel nick");
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "module.h"
|
||||
#include "network.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
@ -36,14 +37,20 @@ typedef struct
|
||||
gint fd;
|
||||
GIOChannel *giochan;
|
||||
SSL *ssl;
|
||||
X509 *cert;
|
||||
SSL_CTX *ctx;
|
||||
unsigned int got_cert:1;
|
||||
unsigned int verify:1;
|
||||
} GIOSSLChannel;
|
||||
|
||||
static SSL_CTX *ssl_ctx = NULL;
|
||||
|
||||
static void irssi_ssl_free(GIOChannel *handle)
|
||||
{
|
||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||
g_io_channel_unref(chan->giochan);
|
||||
SSL_free(chan->ssl);
|
||||
if (chan->ctx != ssl_ctx)
|
||||
SSL_CTX_free(chan->ctx);
|
||||
g_free(chan);
|
||||
}
|
||||
|
||||
@ -70,17 +77,63 @@ GIOError ssl_errno(gint e)
|
||||
return G_IO_ERROR_INVAL;
|
||||
}
|
||||
|
||||
static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, X509 *cert)
|
||||
{
|
||||
if (SSL_get_verify_result(ssl) != X509_V_OK) {
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
unsigned int n;
|
||||
char *str;
|
||||
|
||||
g_warning("Could not verify SSL servers certificate:");
|
||||
if ((str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) == NULL)
|
||||
g_warning(" Could not get subject-name from peer certificate");
|
||||
else {
|
||||
g_warning(" Subject : %s", str);
|
||||
free(str);
|
||||
}
|
||||
if ((str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)) == NULL)
|
||||
g_warning(" Could not get issuer-name from peer certificate");
|
||||
else {
|
||||
g_warning(" Issuer : %s", str);
|
||||
free(str);
|
||||
}
|
||||
if (! X509_digest(cert, EVP_md5(), md, &n))
|
||||
g_warning(" Could not get fingerprint from peer certificate");
|
||||
else {
|
||||
char hex[] = "0123456789ABCDEF";
|
||||
char fp[EVP_MAX_MD_SIZE*3];
|
||||
if (n < sizeof(fp)) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
fp[i*3+0] = hex[(md[i] >> 4) & 0xF];
|
||||
fp[i*3+1] = hex[(md[i] >> 0) & 0xF];
|
||||
fp[i*3+2] = i == n - 1 ? '\0' : ':';
|
||||
}
|
||||
g_warning(" MD5 Fingerprint : %s", fp);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GIOError irssi_ssl_cert_step(GIOSSLChannel *chan)
|
||||
{
|
||||
X509 *cert;
|
||||
gint err;
|
||||
switch(err = SSL_do_handshake(chan->ssl))
|
||||
{
|
||||
case 1:
|
||||
if(!(chan->cert = SSL_get_peer_certificate(chan->ssl)))
|
||||
if(!(cert = SSL_get_peer_certificate(chan->ssl)))
|
||||
{
|
||||
g_warning("SSL server supplied no certificate");
|
||||
return G_IO_ERROR_INVAL;
|
||||
}
|
||||
if (chan->verify && ! irssi_ssl_verify(chan->ssl, chan->ctx, cert)) {
|
||||
X509_free(cert);
|
||||
return G_IO_ERROR_INVAL;
|
||||
}
|
||||
X509_free(cert);
|
||||
return G_IO_ERROR_NONE;
|
||||
default:
|
||||
if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
|
||||
@ -96,7 +149,7 @@ static GIOError irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint
|
||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||
gint err;
|
||||
|
||||
if(chan->cert == NULL)
|
||||
if(! chan->got_cert)
|
||||
{
|
||||
gint cert_err = irssi_ssl_cert_step(chan);
|
||||
if(cert_err != G_IO_ERROR_NONE)
|
||||
@ -125,7 +178,7 @@ static GIOError irssi_ssl_write(GIOChannel *handle, gchar *buf, guint len, guint
|
||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||
gint err;
|
||||
|
||||
if(chan->cert == NULL)
|
||||
if(chan->got_cert)
|
||||
{
|
||||
gint cert_err = irssi_ssl_cert_step(chan);
|
||||
if(cert_err != G_IO_ERROR_NONE)
|
||||
@ -208,15 +261,21 @@ GIOStatus ssl_errno(gint e)
|
||||
|
||||
static GIOStatus irssi_ssl_cert_step(GIOSSLChannel *chan)
|
||||
{
|
||||
X509 *cert;
|
||||
gint err;
|
||||
switch(err = SSL_do_handshake(chan->ssl))
|
||||
{
|
||||
case 1:
|
||||
if(!(chan->cert = SSL_get_peer_certificate(chan->ssl)))
|
||||
if(!(cert = SSL_get_peer_certificate(chan->ssl)))
|
||||
{
|
||||
g_warning("SSL server supplied no certificate");
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
if (chan->verify && ! irssi_ssl_verify(chan->ssl, chan->ctx, cert)) {
|
||||
X509_free(cert);
|
||||
return G_IO_STATUS_ERROR;
|
||||
}
|
||||
X509_free(cert);
|
||||
return G_IO_STATUS_NORMAL;
|
||||
default:
|
||||
if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ)
|
||||
@ -232,7 +291,7 @@ static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint
|
||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||
gint err;
|
||||
|
||||
if(chan->cert == NULL)
|
||||
if(! chan->got_cert)
|
||||
{
|
||||
gint cert_err = irssi_ssl_cert_step(chan);
|
||||
if(cert_err != G_IO_STATUS_NORMAL)
|
||||
@ -261,7 +320,7 @@ static GIOStatus irssi_ssl_write(GIOChannel *handle, const gchar *buf, gsize len
|
||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||
gint err;
|
||||
|
||||
if(chan->cert == NULL)
|
||||
if(! chan->got_cert)
|
||||
{
|
||||
gint cert_err = irssi_ssl_cert_step(chan);
|
||||
if(cert_err != G_IO_STATUS_NORMAL)
|
||||
@ -335,8 +394,6 @@ static GIOFuncs irssi_ssl_channel_funcs = {
|
||||
|
||||
#endif
|
||||
|
||||
static SSL_CTX *ssl_ctx = NULL;
|
||||
|
||||
static gboolean irssi_ssl_init(void)
|
||||
{
|
||||
SSL_library_init();
|
||||
@ -353,13 +410,14 @@ static gboolean irssi_ssl_init(void)
|
||||
|
||||
}
|
||||
|
||||
static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle)
|
||||
static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, const char *mycert, const char *mypkey, const char *cafile, const char *capath, gboolean verify)
|
||||
{
|
||||
GIOSSLChannel *chan;
|
||||
GIOChannel *gchan;
|
||||
int err, fd;
|
||||
SSL *ssl;
|
||||
X509 *cert = NULL;
|
||||
SSL_CTX *ctx = NULL;
|
||||
|
||||
g_return_val_if_fail(handle != NULL, NULL);
|
||||
|
||||
@ -369,7 +427,52 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle)
|
||||
if(!(fd = g_io_channel_unix_get_fd(handle)))
|
||||
return NULL;
|
||||
|
||||
if(!(ssl = SSL_new(ssl_ctx)))
|
||||
if (mycert && *mycert) {
|
||||
char *scert = NULL, *spkey = NULL;
|
||||
if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
|
||||
g_error("Could not allocate memory for SSL context");
|
||||
return NULL;
|
||||
}
|
||||
scert = convert_home(mycert);
|
||||
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);
|
||||
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);
|
||||
else if (! SSL_CTX_check_private_key(ctx))
|
||||
g_warning("Private key does not match the certificate");
|
||||
g_free(scert);
|
||||
g_free(spkey);
|
||||
}
|
||||
|
||||
if ((cafile && *cafile) || (capath && *capath)) {
|
||||
char *scafile = NULL;
|
||||
char *scapath = NULL;
|
||||
if (! ctx && (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
|
||||
g_error("Could not allocate memory for SSL context");
|
||||
return NULL;
|
||||
}
|
||||
if (cafile && *cafile)
|
||||
scafile = convert_home(cafile);
|
||||
if (capath && *capath)
|
||||
scapath = convert_home(capath);
|
||||
if (! SSL_CTX_load_verify_locations(ctx, scafile, scapath)) {
|
||||
g_warning("Could not load CA list for verifying SSL server certificate");
|
||||
g_free(scafile);
|
||||
g_free(scapath);
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
g_free(scafile);
|
||||
g_free(scapath);
|
||||
verify = TRUE;
|
||||
}
|
||||
|
||||
if (ctx == NULL)
|
||||
ctx = ssl_ctx;
|
||||
|
||||
if(!(ssl = SSL_new(ctx)))
|
||||
{
|
||||
g_warning("Failed to allocate SSL structure");
|
||||
return NULL;
|
||||
@ -378,6 +481,9 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle)
|
||||
if(!(err = SSL_set_fd(ssl, fd)))
|
||||
{
|
||||
g_warning("Failed to associate socket to SSL stream");
|
||||
SSL_free(ssl);
|
||||
if (ctx != ssl_ctx)
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -391,22 +497,38 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle)
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
break;
|
||||
default:
|
||||
SSL_free(ssl);
|
||||
if (ctx != ssl_ctx)
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if(!(cert = SSL_get_peer_certificate(ssl)))
|
||||
{
|
||||
g_warning("SSL server supplied no certificate");
|
||||
if (ctx != ssl_ctx)
|
||||
SSL_CTX_free(ctx);
|
||||
SSL_free(ssl);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verify && ! irssi_ssl_verify(ssl, ctx, cert)) {
|
||||
SSL_free(ssl);
|
||||
if (ctx != ssl_ctx)
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
X509_free(cert);
|
||||
}
|
||||
|
||||
chan = g_new0(GIOSSLChannel, 1);
|
||||
chan->fd = fd;
|
||||
chan->giochan = handle;
|
||||
chan->ssl = ssl;
|
||||
chan->cert = cert;
|
||||
chan->ctx = ctx;
|
||||
chan->got_cert = cert != NULL;
|
||||
chan->verify = verify;
|
||||
g_io_channel_ref(handle);
|
||||
|
||||
gchan = (GIOChannel *)chan;
|
||||
@ -416,10 +538,10 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle)
|
||||
return gchan;
|
||||
}
|
||||
|
||||
GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify)
|
||||
{
|
||||
GIOChannel *gret = net_connect_ip(ip, port, my_ip);
|
||||
gret = irssi_ssl_get_iochannel(gret);
|
||||
gret = irssi_ssl_get_iochannel(gret, cert, pkey, cafile, capath, verify);
|
||||
return gret;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2);
|
||||
/* Connect to socket */
|
||||
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip);
|
||||
/* Connect to socket with ip address and SSL*/
|
||||
GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip);
|
||||
GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify);
|
||||
/* Connect to socket with ip address */
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip);
|
||||
/* Connect to named UNIX socket */
|
||||
|
@ -23,6 +23,11 @@ char *nick;
|
||||
char *username;
|
||||
char *realname;
|
||||
|
||||
char *ssl_cert;
|
||||
char *ssl_pkey;
|
||||
char *ssl_cafile;
|
||||
char *ssl_capath;
|
||||
|
||||
GIOChannel *connect_handle; /* connect using this handle */
|
||||
|
||||
/* when reconnecting, the old server status */
|
||||
@ -30,6 +35,7 @@ unsigned int reconnection:1; /* we're trying to reconnect */
|
||||
unsigned int no_autojoin_channels:1; /* don't autojoin any channels */
|
||||
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 no_connect:1; /* don't connect() at all, it's done by plugin */
|
||||
char *channels;
|
||||
char *away_reason;
|
||||
|
@ -8,6 +8,11 @@ char *address;
|
||||
int port;
|
||||
char *password;
|
||||
|
||||
char *ssl_cert;
|
||||
char *ssl_pkey;
|
||||
char *ssl_cafile;
|
||||
char *ssl_capath;
|
||||
|
||||
char *own_host; /* address to use when connecting this server */
|
||||
IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */
|
||||
|
||||
@ -19,5 +24,6 @@ unsigned int last_failed:1; /* if last connection attempt failed */
|
||||
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;
|
||||
|
||||
GHashTable *module_data;
|
||||
|
@ -191,6 +191,11 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
|
||||
dest->no_autojoin_channels = src->no_autojoin_channels;
|
||||
|
||||
dest->use_ssl = src->use_ssl;
|
||||
dest->ssl_cert = g_strdup(src->ssl_cert);
|
||||
dest->ssl_pkey = g_strdup(src->ssl_pkey);
|
||||
dest->ssl_verify = src->ssl_verify;
|
||||
dest->ssl_cafile = g_strdup(src->ssl_cafile);
|
||||
dest->ssl_capath = g_strdup(src->ssl_capath);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
@ -163,7 +163,17 @@ static void server_setup_fill_server(SERVER_CONNECT_REC *conn,
|
||||
conn->family = sserver->family;
|
||||
if (sserver->port > 0 && conn->port <= 0)
|
||||
conn->port = sserver->port;
|
||||
|
||||
conn->use_ssl = sserver->use_ssl;
|
||||
if (conn->ssl_cert == NULL && sserver->ssl_cert != NULL && sserver->ssl_cert[0] != '\0')
|
||||
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);
|
||||
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);
|
||||
if (conn->ssl_capath == NULL && sserver->ssl_capath != NULL && sserver->ssl_capath[0] != '\0')
|
||||
conn->ssl_capath = g_strdup(sserver->ssl_capath);
|
||||
|
||||
server_setup_fill_reconn(conn, sserver);
|
||||
|
||||
@ -394,6 +404,15 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
|
||||
rec->address = g_strdup(server);
|
||||
rec->password = g_strdup(config_node_get_str(node, "password", NULL));
|
||||
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_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));
|
||||
if (rec->ssl_cafile || rec->ssl_capath)
|
||||
rec->ssl_verify = TRUE;
|
||||
if (rec->ssl_cert != NULL || rec->ssl_verify)
|
||||
rec->use_ssl = TRUE;
|
||||
rec->port = port;
|
||||
rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE);
|
||||
rec->no_proxy = config_node_get_bool(node, "no_proxy", FALSE);
|
||||
@ -424,6 +443,11 @@ static void server_setup_save(SERVER_SETUP_REC *rec)
|
||||
iconfig_node_set_int(node, "port", rec->port);
|
||||
iconfig_node_set_str(node, "password", rec->password);
|
||||
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_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);
|
||||
iconfig_node_set_str(node, "own_host", rec->own_host);
|
||||
|
||||
iconfig_node_set_str(node, "family",
|
||||
@ -460,6 +484,10 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec)
|
||||
g_free_not_null(rec->own_ip6);
|
||||
g_free_not_null(rec->chatnet);
|
||||
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_cafile);
|
||||
g_free_not_null(rec->ssl_capath);
|
||||
g_free(rec->address);
|
||||
g_free(rec);
|
||||
}
|
||||
@ -517,6 +545,13 @@ void servers_setup_init(void)
|
||||
settings_add_str("server", "user_name", NULL);
|
||||
settings_add_str("server", "real_name", NULL);
|
||||
|
||||
settings_add_bool("server", "use_ssl", FALSE);
|
||||
settings_add_str("server", "ssl_cert", NULL);
|
||||
settings_add_str("server", "ssl_pkey", NULL);
|
||||
settings_add_bool("server", "ssl_verify", FALSE);
|
||||
settings_add_str("server", "ssl_cafile", NULL);
|
||||
settings_add_str("server", "ssl_cacert", NULL);
|
||||
|
||||
settings_add_bool("proxy", "use_proxy", FALSE);
|
||||
settings_add_str("proxy", "proxy_address", "");
|
||||
settings_add_int("proxy", "proxy_port", 6667);
|
||||
|
@ -188,7 +188,8 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
|
||||
port = server->connrec->proxy != NULL ?
|
||||
server->connrec->proxy_port : server->connrec->port;
|
||||
handle = server->connrec->use_ssl ?
|
||||
net_connect_ip_ssl(ip, port, own_ip) :
|
||||
net_connect_ip_ssl(ip, port, own_ip, server->connrec->ssl_cert, server->connrec->ssl_pkey,
|
||||
server->connrec->ssl_cafile, server->connrec->ssl_capath, server->connrec->ssl_verify) :
|
||||
net_connect_ip(ip, port, own_ip);
|
||||
} else {
|
||||
handle = net_connect_unix(unix_socket);
|
||||
@ -584,6 +585,11 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
|
||||
g_free_not_null(conn->username);
|
||||
g_free_not_null(conn->realname);
|
||||
|
||||
g_free_not_null(conn->ssl_cert);
|
||||
g_free_not_null(conn->ssl_pkey);
|
||||
g_free_not_null(conn->ssl_cafile);
|
||||
g_free_not_null(conn->ssl_capath);
|
||||
|
||||
g_free_not_null(conn->channels);
|
||||
g_free_not_null(conn->away_reason);
|
||||
|
||||
|
@ -183,6 +183,11 @@ static void session_save_server(SERVER_REC *server, CONFIG_REC *config,
|
||||
config_node_set_str(config, node, "nick", server->nick);
|
||||
|
||||
config_node_set_bool(config, node, "use_ssl", server->connrec->use_ssl);
|
||||
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_str(config, node, "ssl_cafile", server->connrec->ssl_cafile);
|
||||
config_node_set_str(config, node, "ssl_capath", server->connrec->ssl_capath);
|
||||
|
||||
handle = g_io_channel_unix_get_fd(net_sendbuffer_handle(server->handle));
|
||||
config_node_set_int(config, node, "handle", handle);
|
||||
|
@ -147,6 +147,32 @@ static void cmd_server_add(const char *data)
|
||||
if (g_hash_table_lookup(optlist, "ssl"))
|
||||
rec->use_ssl = TRUE;
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_cert");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_cert = g_strdup(value);
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_pkey");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_pkey = g_strdup(value);
|
||||
|
||||
if (g_hash_table_lookup(optlist, "ssl_verify"))
|
||||
rec->ssl_verify = TRUE;
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_cafile");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_cafile = g_strdup(value);
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_capath");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_capath = g_strdup(value);
|
||||
|
||||
if ((rec->ssl_cafile != NULL && rec->ssl_cafile[0] != '\0')
|
||||
|| (rec->ssl_capath != NULL && rec->ssl_capath[0] != '\0'))
|
||||
rec->ssl_verify = TRUE;
|
||||
|
||||
if ((rec->ssl_cert != NULL && rec->ssl_cert[0] != '\0') || rec->ssl_verify == TRUE)
|
||||
rec->use_ssl = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "auto")) rec->autoconnect = TRUE;
|
||||
if (g_hash_table_lookup(optlist, "noauto")) rec->autoconnect = FALSE;
|
||||
if (g_hash_table_lookup(optlist, "proxy")) rec->no_proxy = FALSE;
|
||||
@ -343,7 +369,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 auto noauto proxy noproxy -host -port");
|
||||
command_set_options("server add", "4 6 ssl +ssl_cert +ssl_pkey 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);
|
||||
|
@ -50,9 +50,11 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target)
|
||||
|
||||
return target;
|
||||
}
|
||||
/* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-auto | -noauto] [-ircnet <ircnet>]
|
||||
[-host <hostname>] [-cmdspeed <ms>] [-cmdmax <count>]
|
||||
[-port <port>] <address> [<port> [<password>]] */
|
||||
/* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-ssl_cert <cert>] [-ssl_pkey <pkey>]
|
||||
[-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>]
|
||||
[-auto | -noauto] [-ircnet <ircnet>] [-host <hostname>]
|
||||
[-cmdspeed <ms>] [-cmdmax <count>] [-port <port>]
|
||||
<address> [<port> [<password>]] */
|
||||
static void sig_server_add_fill(IRC_SERVER_SETUP_REC *rec,
|
||||
GHashTable *optlist)
|
||||
{
|
||||
@ -98,8 +100,21 @@ static void cmd_server_list(const char *data)
|
||||
g_string_append(str, "autoconnect, ");
|
||||
if (rec->no_proxy)
|
||||
g_string_append(str, "noproxy, ");
|
||||
if (rec->use_ssl)
|
||||
g_string_append(str, "SSL, ");
|
||||
if (rec->use_ssl) {
|
||||
g_string_append(str, "ssl, ");
|
||||
if (rec->ssl_cert) {
|
||||
g_string_sprintfa(str, "ssl_cert: %s, ", rec->ssl_cert);
|
||||
if (rec->ssl_pkey)
|
||||
g_string_sprintfa(str, "ssl_pkey: %s, ", rec->ssl_pkey);
|
||||
}
|
||||
if (rec->ssl_verify)
|
||||
g_string_append(str, "ssl_verify, ");
|
||||
if (rec->ssl_cafile)
|
||||
g_string_sprintfa(str, "ssl_cafile: %s, ", rec->ssl_cafile);
|
||||
if (rec->ssl_capath)
|
||||
g_string_sprintfa(str, "ssl_capath: %s, ", rec->ssl_capath);
|
||||
|
||||
}
|
||||
if (rec->max_cmds_at_once > 0)
|
||||
g_string_sprintfa(str, "cmdmax: %d, ", rec->max_cmds_at_once);
|
||||
if (rec->cmd_queue_speed > 0)
|
||||
|
Loading…
Reference in New Issue
Block a user