--- a/loudmouth/lm-ssl-base.c Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-base.c Sat Feb 13 12:16:45 2016 +0100
@@ -16,6 +16,7 @@
* License along with this program; if not, see <https://www.gnu.org/licenses>
*/
+#include "lm-debug.h"
#include "lm-ssl-base.h"
#include "lm-ssl-internals.h"
@@ -34,7 +35,15 @@
base->cipher_list = NULL;
if (expected_fingerprint) {
- base->expected_fingerprint = g_memdup (expected_fingerprint, 16);
+ if (!g_str_has_prefix(expected_fingerprint, LM_FINGERPRINT_PREFIX)) {
+ /* let's set a bogus hash because the user tries to use a hash
+ we don't support now */
+ expected_fingerprint = "wrong_hash_format";
+ g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "Wrong hash format, use "
+ LM_FINGERPRINT_PREFIX"$hash");
+ }
+ base->expected_fingerprint = g_strndup(expected_fingerprint,
+ LM_FINGERPRINT_LENGTH);
} else {
base->expected_fingerprint = NULL;
}
@@ -64,6 +73,39 @@
g_free (base->ca_path);
base->ca_path = g_strdup (ca_path);
}
+
+void
+_lm_ssl_base_set_fingerprint (LmSSLBase *base,
+ const guchar *digest,
+ unsigned int digest_len)
+{
+ gchar hex[LM_FINGERPRINT_LENGTH];
+ gchar *p;
+ int i;
+
+ g_assert(LM_FINGERPRINT_PREFIX != NULL);
+ g_assert(digest != NULL);
+ g_assert(digest_len > 0);
+ g_assert(LM_FINGERPRINT_LENGTH >=
+ (sizeof(LM_FINGERPRINT_PREFIX) + digest_len*2));
+
+ for (p = hex, i = 0; i < digest_len ; i++, p+=2) {
+ g_snprintf(p, 3, "%02x", digest[i]);
+ }
+ g_snprintf(base->fingerprint, LM_FINGERPRINT_LENGTH,
+ "%s%s",
+ LM_FINGERPRINT_PREFIX,
+ hex);
+}
+
+int _lm_ssl_base_check_fingerprint( LmSSLBase *base)
+{
+ if (base->expected_fingerprint == NULL) {
+ return 0;
+ }
+ return g_ascii_strcasecmp(base->expected_fingerprint, base->fingerprint);
+}
+
void
_lm_ssl_base_free_fields (LmSSLBase *base)
{
--- a/loudmouth/lm-ssl-base.h Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-base.h Sat Feb 13 12:16:45 2016 +0100
@@ -31,7 +31,7 @@
gchar *cipher_list;
gchar *ca_path;
gchar *expected_fingerprint;
- char fingerprint[20];
+ char fingerprint[LM_FINGERPRINT_LENGTH];
gboolean use_starttls;
gboolean require_starttls;
@@ -50,6 +50,12 @@
void _lm_ssl_base_set_ca_path (LmSSLBase *base,
const gchar *ca_path);
+void _lm_ssl_base_set_fingerprint (LmSSLBase *base,
+ const guchar *digest,
+ unsigned int digest_len);
+
+int _lm_ssl_base_check_fingerprint( LmSSLBase *base);
+
void _lm_ssl_base_free_fields (LmSSLBase *base);
#endif /* __LM_SSL_BASE_H__ */
--- a/loudmouth/lm-ssl-generic.c Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-generic.c Sat Feb 13 12:16:45 2016 +0100
@@ -136,9 +136,9 @@
* lm_ssl_get_fingerprint:
* @ssl: an #LmSSL
*
- * Returns the MD5 fingerprint of the remote server's certificate.
+ * Returns the fingerprint of the remote server's certificate.
*
- * Return value: A 16-byte array representing the fingerprint or %NULL if unknown.
+ * Return value: A null terminated string representing the fingerprint or %NULL if unknown.
**/
const gchar *
lm_ssl_get_fingerprint (LmSSL *ssl)
--- a/loudmouth/lm-ssl-gnutls.c Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-gnutls.c Sat Feb 13 12:16:45 2016 +0100
@@ -34,6 +34,7 @@
#ifdef HAVE_GNUTLS
#include <gnutls/x509.h>
+#include <gnutls/crypto.h>
struct _LmSSL {
LmSSLBase base;
@@ -109,6 +110,8 @@
if (gnutls_certificate_type_get (ssl->gnutls_session) == GNUTLS_CRT_X509) {
const gnutls_datum_t* cert_list;
guint cert_list_size;
+ gnutls_digest_algorithm_t digest = GNUTLS_DIG_SHA256;
+ guchar digest_bin[LM_FINGERPRINT_LENGTH];
size_t digest_size;
gnutls_x509_crt_t cert;
@@ -139,15 +142,15 @@
gnutls_x509_crt_deinit (cert);
- digest_size = sizeof (base->fingerprint);
+ digest_size = gnutls_hash_get_len(digest);
+ g_assert(digest_size < sizeof(digest_bin));
- if (gnutls_fingerprint (GNUTLS_DIG_MD5, &cert_list[0],
- base->fingerprint,
+ if (gnutls_fingerprint (digest,
+ &cert_list[0],
+ digest_bin,
&digest_size) >= 0) {
- if (base->expected_fingerprint &&
- memcmp (base->expected_fingerprint,
- base->fingerprint,
- digest_size) &&
+ _lm_ssl_base_set_fingerprint(base, digest_bin, digest_size);
+ if (_lm_ssl_base_check_fingerprint(base) != 0 &&
base->func (ssl,
LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
--- a/loudmouth/lm-ssl-openssl.c Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl-openssl.c Sat Feb 13 12:16:45 2016 +0100
@@ -126,8 +126,9 @@
LmSSLBase *base;
long verify_res;
int rc;
- const EVP_MD *digest = EVP_md5();
+ const EVP_MD *digest = EVP_sha256();
unsigned int digest_len;
+ guchar digest_bin[EVP_MD_size(digest)];
X509 *srv_crt;
gchar *cn;
X509_NAME *crt_subj;
@@ -143,17 +144,14 @@
verify_res = SSL_get_verify_result(ssl->ssl);
srv_crt = SSL_get_peer_certificate(ssl->ssl);
- rc = X509_digest(srv_crt, digest, (guchar *) base->fingerprint,
- &digest_len);
+ rc = X509_digest(srv_crt, digest, digest_bin, &digest_len);
if ((rc != 0) && (digest_len == EVP_MD_size(digest))) {
- if (base->expected_fingerprint != NULL) {
- if (memcmp(base->expected_fingerprint, base->fingerprint,
- digest_len) != 0) {
- if (base->func(ssl,
- LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
+ _lm_ssl_base_set_fingerprint(base, digest_bin, digest_len);
+ if (_lm_ssl_base_check_fingerprint(base) != 0) {
+ if (base->func(ssl,
+ LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
+ base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
+ return FALSE;
}
}
} else {
--- a/loudmouth/lm-ssl.h Thu Feb 11 21:01:04 2016 +0100
+++ b/loudmouth/lm-ssl.h Sat Feb 13 12:16:45 2016 +0100
@@ -43,6 +43,9 @@
#error "Only <loudmouth/loudmouth.h> can be included directly, this file may disappear or change contents."
#endif
+#define LM_FINGERPRINT_PREFIX "SHA256:"
+#define LM_FINGERPRINT_LENGTH 72
+
G_BEGIN_DECLS
/**