aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Halden <marius.h@lden.org>2016-03-13 01:19:37 +0100
committerMarius Halden <marius.h@lden.org>2016-05-07 14:27:54 +0200
commitc9cf3bf878606ee7d4b3933b7e86af9fb05f58b5 (patch)
tree702b4d95ef35de2b854d407c4db664a7b5a7e039
parent35648353ff877344d577e9247ee6f8cfa15ed940 (diff)
more ssl
-rw-r--r--bitlbee.c21
-rw-r--r--irc.c13
-rw-r--r--lib/ssl_client.h3
-rw-r--r--lib/ssl_gnutls.c48
4 files changed, 77 insertions, 8 deletions
diff --git a/bitlbee.c b/bitlbee.c
index fa8c6795..c725ff0c 100644
--- a/bitlbee.c
+++ b/bitlbee.c
@@ -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);
diff --git a/irc.c b/irc.c
index 9cac0742..563d3fca 100644
--- a/irc.c
+++ b/irc.c
@@ -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) {