diff options
author | Marius Halden <marius.h@lden.org> | 2016-03-13 01:19:37 +0100 |
---|---|---|
committer | Marius Halden <marius.h@lden.org> | 2016-05-07 14:27:54 +0200 |
commit | c9cf3bf878606ee7d4b3933b7e86af9fb05f58b5 (patch) | |
tree | 702b4d95ef35de2b854d407c4db664a7b5a7e039 | |
parent | 35648353ff877344d577e9247ee6f8cfa15ed940 (diff) |
more ssl
-rw-r--r-- | bitlbee.c | 21 | ||||
-rw-r--r-- | irc.c | 13 | ||||
-rw-r--r-- | lib/ssl_client.h | 3 | ||||
-rw-r--r-- | lib/ssl_gnutls.c | 48 |
4 files changed, 77 insertions, 8 deletions
@@ -29,6 +29,7 @@ #include "protocols/nogaim.h" #include "help.h" #include "ipc.h" +#include "lib/ssl_client.h" #include <signal.h> #include <stdio.h> #include <errno.h> @@ -169,6 +170,10 @@ int bitlbee_daemon_init() log_link(LOGLVL_WARNING, LOGOUTPUT_SYSLOG); } + if (global.conf->ssl) { + ssl_setup_server(); + } + return(0); } @@ -187,7 +192,11 @@ gboolean bitlbee_io_current_client_read(gpointer data, gint fd, b_input_conditio char line[513]; int st; - st = read(irc->fd, line, sizeof(line) - 1); + if (global.conf->ssl) { + st = ssl_server_read(irc, line, sizeof(line) - 1); + } else { + st = read(irc->fd, line, sizeof(line) - 1); + } if (st == 0) { irc_abort(irc, 1, "Connection reset by peer"); return FALSE; @@ -236,7 +245,11 @@ gboolean bitlbee_io_current_client_write(gpointer data, gint fd, b_input_conditi } size = strlen(irc->sendbuffer); - st = write(irc->fd, irc->sendbuffer, size); + if (global.conf->ssl) { + st = ssl_server_write(irc, irc->sendbuffer, size); + } else { + st = write(irc->fd, irc->sendbuffer, size); + } if (st == 0 || (st < 0 && !sockerr_again())) { irc_abort(irc, 1, "Write error: %s", strerror(errno)); @@ -316,6 +329,10 @@ static gboolean bitlbee_io_new_client(gpointer data, gint fd, b_input_condition /* Make the connection. */ irc = irc_new(new_socket); + if (global.conf->ssl) { + ssl_accept(irc); + } + /* We can store the IPC fd there now. */ global.listen_socket = fds[1]; global.listen_watch_source_id = b_input_add(fds[1], B_EV_IO_READ, ipc_child_read, irc); @@ -281,8 +281,14 @@ void irc_free(irc_t * irc) b_event_remove(irc->w_watch_source_id); } + if (global.conf->ssl) { + gnutls_bye(irc->ssl_session, GNUTLS_SHUT_WR); + } closesocket(irc->fd); irc->fd = -1; + if (global.conf->ssl) { + gnutls_deinit(irc->ssl_session); + } g_hash_table_foreach_remove(irc->nick_user_hash, irc_free_hashkey, NULL); g_hash_table_destroy(irc->nick_user_hash); @@ -665,7 +671,12 @@ void irc_flush(irc_t *irc) } len = strlen(irc->sendbuffer); - if ((n = send(irc->fd, irc->sendbuffer, len, 0)) == len) { + if (global.conf->ssl) { + n = ssl_server_write(irc, irc->sendbuffer, len); + } else { + n = send(irc->fd, irc->sendbuffer, len, 0); + } + if (n == len) { g_free(irc->sendbuffer); irc->sendbuffer = NULL; diff --git a/lib/ssl_client.h b/lib/ssl_client.h index e307a6ce..08debe48 100644 --- a/lib/ssl_client.h +++ b/lib/ssl_client.h @@ -72,7 +72,10 @@ G_MODULE_EXPORT void *ssl_starttls(int fd, char *hostname, gboolean verify, ssl_ G_MODULE_EXPORT int ssl_read(void *conn, char *buf, int len); G_MODULE_EXPORT int ssl_write(void *conn, const char *buf, int len); +G_MODULE_EXPORT gboolean ssl_setup_server(void); G_MODULE_EXPORT gboolean ssl_accept(irc_t *irc); +G_MODULE_EXPORT int ssl_server_read(irc_t *irc, char *buf, int len); +G_MODULE_EXPORT int ssl_server_write(irc_t *irc, const char *buf, int len); /* Now needed by most SSL libs. See for more info: http://www.gnu.org/software/gnutls/manual/gnutls.html#index-gnutls_005frecord_005fcheck_005fpending-209 diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index 1be3e1ed..c37449c4 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -40,6 +40,7 @@ int ssl_errno = 0; static gboolean initialized = FALSE; gnutls_certificate_credentials_t xcred; +gnutls_certificate_credentials_t server_xcred; #include <limits.h> @@ -129,10 +130,8 @@ void *ssl_connect(char *host, int port, gboolean verify, ssl_input_function func gboolean ssl_setup_server() { - gnutls_certificate_credentials_t x509_cred; - - gnutls_certificate_allocate_credentials(&x509_cred); - gnutls_certificate_set_x509_key_file(x509_cred, global.conf->ssl_cert, global.conf->ssl_key, GNUTLS_X509_FMT_PEM); + gnutls_certificate_allocate_credentials(&server_xcred); + gnutls_certificate_set_x509_key_file(server_xcred, global.conf->ssl_cert, global.conf->ssl_key, GNUTLS_X509_FMT_PEM); return TRUE; } @@ -143,6 +142,8 @@ gboolean ssl_accept(irc_t *irc) gnutls_init(&irc->ssl_session, GNUTLS_SERVER); gnutls_transport_set_int(irc->ssl_session, irc->fd); + gnutls_credentials_set(irc->ssl_session, GNUTLS_CRD_CERTIFICATE, server_xcred); + gnutls_certificate_server_set_request(irc->ssl_session, GNUTLS_CERT_REQUEST); do { ret = gnutls_handshake(irc->ssl_session); @@ -152,8 +153,9 @@ gboolean ssl_accept(irc_t *irc) close(irc->fd); gnutls_deinit(irc->ssl_session); - fprintf(stderr, "SSL handshake failed (%s)\n", gnutls_strerror(ret)); + log_message(LOGLVL_INFO, "SSL Handshake failed (%s)", gnutls_strerror(ret)); // XXX + exit(1); return FALSE; } @@ -428,6 +430,24 @@ int ssl_read(void *conn, char *buf, int len) return st; } +int ssl_server_read(irc_t *irc, char *buf, int len) +{ + int st; + + st = gnutls_record_recv(irc->ssl_session, buf, len); + + ssl_errno = SSL_OK; + if (st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED) { + ssl_errno = SSL_AGAIN; + } + + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) { + len = write(2, buf, st); + } + + return st; +} + int ssl_write(void *conn, const char *buf, int len) { int st; @@ -451,6 +471,24 @@ int ssl_write(void *conn, const char *buf, int len) return st; } +int ssl_server_write(irc_t *irc, const char *buf, int len) +{ + int st; + + st = gnutls_record_send(irc->ssl_session, buf, len); + + ssl_errno = SSL_OK; + if (st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED) { + ssl_errno = SSL_AGAIN; + } + + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) { + len = write(2, buf, st); + } + + return st; +} + int ssl_pending(void *conn) { if (conn == NULL) { |