Implemented lm_ssl_set_ca
This enables the application to choose additional certificates to trust
--- a/loudmouth/lm-ssl-base.c Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/lm-ssl-base.c Mon Nov 04 21:30:28 2013 +0100
@@ -59,9 +59,18 @@
}
void
+_lm_ssl_base_set_ca_path (LmSSLBase *base,
+ const gchar *ca_path)
+{
+ if (base->ca_path)
+ g_free (base->ca_path);
+ base->ca_path = g_strdup (ca_path);
+}
+void
_lm_ssl_base_free_fields (LmSSLBase *base)
{
g_free (base->expected_fingerprint);
g_free (base->cipher_list);
+ g_free (base->ca_path);
}
--- a/loudmouth/lm-ssl-base.h Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/lm-ssl-base.h Mon Nov 04 21:30:28 2013 +0100
@@ -31,6 +31,7 @@
gpointer func_data;
GDestroyNotify data_notify;
gchar *cipher_list;
+ gchar *ca_path;
gchar *expected_fingerprint;
char fingerprint[20];
gboolean use_starttls;
@@ -48,6 +49,9 @@
void _lm_ssl_base_set_cipher_list (LmSSLBase *base,
const gchar *cipher_list);
+void _lm_ssl_base_set_ca_path (LmSSLBase *base,
+ const gchar *ca_path);
+
void _lm_ssl_base_free_fields (LmSSLBase *base);
#endif /* __LM_SSL_BASE_H__ */
--- a/loudmouth/lm-ssl-generic.c Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/lm-ssl-generic.c Mon Nov 04 21:30:28 2013 +0100
@@ -176,6 +176,22 @@
}
/**
+ * lm_ssl_set_ca:
+ * @ssl: an #LmSSL
+ * @ca_path: path to a certificate or a directory containing certificates
+ *
+ * Sets a path to certificates which should be trusted.
+ *
+ **/
+
+void
+lm_ssl_set_ca (LmSSL *ssl, const gchar *ca_path)
+{
+ _lm_ssl_base_set_ca_path(LM_SSL_BASE(ssl), ca_path);
+}
+
+
+/**
* lm_ssl_use_starttls:
* @ssl: an #LmSSL
*
--- a/loudmouth/lm-ssl-gnutls.c Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/lm-ssl-gnutls.c Mon Nov 04 21:30:28 2013 +0100
@@ -20,7 +20,11 @@
#include <config.h>
+#include <errno.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <glib.h>
#include "lm-debug.h"
@@ -192,6 +196,72 @@
}
gboolean
+_lm_ssl_set_ca (LmSSL *ssl,
+ const gchar *ca_path)
+{
+ struct stat target;
+
+ if (stat (ca_path, &target) != 0) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
+ "ca_path '%s': no such file or directory", ca_path);
+ return FALSE;
+ }
+
+ if (S_ISDIR (target.st_mode)) {
+ int success = 0;
+ int worked_at_least_once = 0;
+ DIR *dir;
+ struct dirent *entry;
+
+ if ((dir = opendir (ca_path)) == NULL) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
+ "Couldn't open '%s': %s",
+ ca_path, strerror(errno));
+ return FALSE;
+ }
+
+ for (entry = readdir (dir); entry != NULL; entry = readdir (dir)) {
+ struct stat file;
+ gchar *path = g_build_path ("/", ca_path, entry->d_name, NULL);
+
+ if ((stat (path, &file) == 0) && S_ISREG (file.st_mode)) {
+ success = gnutls_certificate_set_x509_trust_file (
+ ssl->gnutls_xcred, path, GNUTLS_X509_FMT_PEM);
+ if (success > 0)
+ worked_at_least_once = 1;
+ if (success < 0) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
+ "Loading of certificate '%s' failed: %s",
+ path, gnutls_strerror(success));
+ }
+ }
+ g_free (path);
+ }
+ closedir (dir);
+
+ if (!worked_at_least_once) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
+ "No certificates in ca_path '%s'. Are they in PEM format?",
+ ca_path);
+ return FALSE;
+ }
+
+ } else if (S_ISREG (target.st_mode)) {
+ int success = 0;
+ success = gnutls_certificate_set_x509_trust_file (ssl->gnutls_xcred,
+ ca_path,
+ GNUTLS_X509_FMT_PEM);
+ if (success < 0) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
+ "Loading of ca_path '%s' failed: %s",
+ ca_path, gnutls_strerror(success));
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+gboolean
_lm_ssl_begin (LmSSL *ssl, gint fd, const gchar *server, GError **error)
{
int ret;
@@ -205,6 +275,9 @@
} else {
gnutls_priority_set_direct (ssl->gnutls_session, "NORMAL", NULL);
}
+ if (base->ca_path) {
+ _lm_ssl_set_ca(ssl, base->ca_path);
+ }
gnutls_credentials_set (ssl->gnutls_session,
GNUTLS_CRD_CERTIFICATE,
ssl->gnutls_xcred);
--- a/loudmouth/lm-ssl-internals.h Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/lm-ssl-internals.h Mon Nov 04 21:30:28 2013 +0100
@@ -32,6 +32,8 @@
GDestroyNotify notify);
void _lm_ssl_initialize (LmSSL *ssl);
+gboolean _lm_ssl_set_ca (LmSSL *ssl,
+ const gchar *ca_path);
gboolean _lm_ssl_begin (LmSSL *ssl,
gint fd,
const gchar *server,
--- a/loudmouth/lm-ssl-openssl.c Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/lm-ssl-openssl.c Mon Nov 04 21:30:28 2013 +0100
@@ -23,6 +23,8 @@
#include <stdio.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <glib.h>
@@ -328,6 +330,35 @@
}
gboolean
+_lm_ssl_set_ca (LmSSL *ssl,
+ const gchar *ca_path)
+{
+ struct stat target;
+ int success = 0;
+
+ if (stat (ca_path, &target) != 0) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
+ "ca_path '%s': no such file or directory", ca_path);
+ return FALSE;
+ }
+
+ if (S_ISDIR (target.st_mode)) {
+ success = SSL_CTX_load_verify_locations(ssl->ssl_ctx, NULL, ca_path);
+ } else if (S_ISREG (target.st_mode)) {
+ success = SSL_CTX_load_verify_locations(ssl->ssl_ctx, ca_path, NULL);
+ }
+ if (success == 0) {
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
+ "Loading of ca_path '%s' failed: %s",
+ ca_path,
+ ERR_error_string(ERR_peek_last_error(), NULL));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
_lm_ssl_begin (LmSSL *ssl, gint fd, const gchar *server, GError **error)
{
gint ssl_ret;
@@ -345,6 +376,10 @@
if (base->cipher_list) {
SSL_CTX_set_cipher_list(ssl->ssl_ctx, base->cipher_list);
}
+ if (base->ca_path) {
+ _lm_ssl_set_ca (ssl, base->ca_path);
+ }
+
ssl->ssl = SSL_new(ssl->ssl_ctx);
if (ssl->ssl == NULL) {
g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "SSL_new() == NULL");
--- a/loudmouth/lm-ssl.h Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/lm-ssl.h Mon Nov 04 21:30:28 2013 +0100
@@ -126,6 +126,9 @@
void lm_ssl_set_cipher_list (LmSSL *ssl,
const gchar *cipher_list);
+void lm_ssl_set_ca (LmSSL *ssl,
+ const gchar *ca_path);
+
const gchar * lm_ssl_get_fingerprint (LmSSL *ssl);
void lm_ssl_use_starttls (LmSSL *ssl,
--- a/loudmouth/loudmouth.sym Fri Oct 25 00:02:50 2013 +0200
+++ b/loudmouth/loudmouth.sym Mon Nov 04 21:30:28 2013 +0100
@@ -90,6 +90,7 @@
lm_ssl_new
lm_ssl_ref
lm_ssl_unref
+lm_ssl_set_ca
lm_ssl_set_cipher_list
lm_ssl_use_starttls
lm_utils_get_localtime