--- a/loudmouth/src/lm-ssl-gnutls.c Wed Mar 31 22:32:38 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2003-2006 Imendio AB
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include <string.h>
-#include <glib.h>
-
-#include "lm-debug.h"
-#include "lm-error.h"
-#include "lm-ssl-base.h"
-#include "lm-ssl-internals.h"
-
-#ifdef HAVE_GNUTLS
-
-#include <gnutls/x509.h>
-
-#define CA_PEM_FILE "/etc/ssl/certs/ca-certificates.crt"
-
-struct _LmSSL {
- LmSSLBase base;
-
- gnutls_session gnutls_session;
- gnutls_certificate_credentials gnutls_xcred;
- gboolean started;
-};
-
-static gboolean ssl_verify_certificate (LmSSL *ssl,
- const gchar *server);
-
-static gboolean
-ssl_verify_certificate (LmSSL *ssl, const gchar *server)
-{
- LmSSLBase *base;
- unsigned int status;
- int rc;
-
- base = LM_SSL_BASE (ssl);
-
- /* This verification function uses the trusted CAs in the credentials
- * structure. So you must have installed one or more CA certificates.
- */
- rc = gnutls_certificate_verify_peers2 (ssl->gnutls_session, &status);
-
- if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) {
- if (base->func (ssl,
- LM_SSL_STATUS_NO_CERT_FOUND,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- if (rc != 0) {
- if (base->func (ssl,
- LM_SSL_STATUS_GENERIC_ERROR,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) {
- if (base->func (ssl,
- LM_SSL_STATUS_NO_CERT_FOUND,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- if (status & GNUTLS_CERT_INVALID
- || status & GNUTLS_CERT_REVOKED) {
- if (base->func (ssl, LM_SSL_STATUS_UNTRUSTED_CERT,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- if (gnutls_certificate_expiration_time_peers (ssl->gnutls_session) < time (0)) {
- if (base->func (ssl, LM_SSL_STATUS_CERT_EXPIRED,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- if (gnutls_certificate_activation_time_peers (ssl->gnutls_session) > time (0)) {
- if (base->func (ssl, LM_SSL_STATUS_CERT_NOT_ACTIVATED,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- if (gnutls_certificate_type_get (ssl->gnutls_session) == GNUTLS_CRT_X509) {
- const gnutls_datum* cert_list;
- guint cert_list_size;
- size_t digest_size;
- gnutls_x509_crt cert;
-
- cert_list = gnutls_certificate_get_peers (ssl->gnutls_session, &cert_list_size);
- if (cert_list == NULL) {
- if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- gnutls_x509_crt_init (&cert);
-
- if (gnutls_x509_crt_import (cert, &cert_list[0],
- GNUTLS_X509_FMT_DER) != 0) {
- if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- if (!gnutls_x509_crt_check_hostname (cert, server)) {
- if (base->func (ssl, LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- gnutls_x509_crt_deinit (cert);
-
- digest_size = sizeof (base->fingerprint);
-
- if (gnutls_fingerprint (GNUTLS_DIG_MD5, &cert_list[0],
- base->fingerprint,
- &digest_size) >= 0) {
- if (base->expected_fingerprint &&
- memcmp (base->expected_fingerprint,
- base->fingerprint,
- digest_size) &&
- base->func (ssl,
- LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
- else if (base->func (ssl, LM_SSL_STATUS_GENERIC_ERROR,
- base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/* From lm-ssl-protected.h */
-
-LmSSL *
-_lm_ssl_new (const gchar *expected_fingerprint,
- LmSSLFunction ssl_function,
- gpointer user_data,
- GDestroyNotify notify)
-{
- LmSSL *ssl;
-
- ssl = g_new0 (LmSSL, 1);
-
- _lm_ssl_base_init ((LmSSLBase *) ssl,
- expected_fingerprint,
- ssl_function, user_data, notify);
-
- return ssl;
-}
-
-void
-_lm_ssl_initialize (LmSSL *ssl)
-{
- gnutls_global_init ();
- gnutls_certificate_allocate_credentials (&ssl->gnutls_xcred);
- gnutls_certificate_set_x509_trust_file(ssl->gnutls_xcred,
- CA_PEM_FILE,
- GNUTLS_X509_FMT_PEM);
-}
-
-gboolean
-_lm_ssl_begin (LmSSL *ssl, gint fd, const gchar *server, GError **error)
-{
- int ret;
- gboolean auth_ok = TRUE;
- const int cert_type_priority[] =
- { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
- const int compression_priority[] =
- { GNUTLS_COMP_DEFLATE, GNUTLS_COMP_NULL, 0 };
-
- gnutls_init (&ssl->gnutls_session, GNUTLS_CLIENT);
- gnutls_set_default_priority (ssl->gnutls_session);
- gnutls_certificate_type_set_priority (ssl->gnutls_session,
- cert_type_priority);
- gnutls_compression_set_priority (ssl->gnutls_session,
- compression_priority);
- gnutls_credentials_set (ssl->gnutls_session,
- GNUTLS_CRD_CERTIFICATE,
- ssl->gnutls_xcred);
-
- gnutls_transport_set_ptr (ssl->gnutls_session,
- (gnutls_transport_ptr_t) fd);
-
- ret = gnutls_handshake (ssl->gnutls_session);
-
- if (ret >= 0) {
- auth_ok = ssl_verify_certificate (ssl, server);
- }
-
- if (ret < 0 || !auth_ok) {
- char *errmsg;
-
- gnutls_perror (ret);
-
- if (!auth_ok) {
- errmsg = "*** GNUTLS authentication error";
- } else {
- errmsg = "*** GNUTLS handshake failed";
- }
-
- g_set_error (error,
- LM_ERROR, LM_ERROR_CONNECTION_OPEN,
- errmsg);
-
- return FALSE;
- }
- lm_verbose ("GNUTLS negotiated compression: %s",
- gnutls_compression_get_name (gnutls_compression_get
- (ssl->gnutls_session)));
-
- ssl->started = TRUE;
-
- return TRUE;
-}
-
-GIOStatus
-_lm_ssl_read (LmSSL *ssl, gchar *buf, gint len, gsize *bytes_read)
-{
- GIOStatus status;
- gint b_read;
-
- *bytes_read = 0;
- b_read = gnutls_record_recv (ssl->gnutls_session, buf, len);
-
- if (b_read == GNUTLS_E_AGAIN) {
- status = G_IO_STATUS_AGAIN;
- }
- else if (b_read == 0) {
- status = G_IO_STATUS_EOF;
- }
- else if (b_read < 0) {
- status = G_IO_STATUS_ERROR;
- } else {
- *bytes_read = (guint) b_read;
- status = G_IO_STATUS_NORMAL;
- }
-
- return status;
-}
-
-gint
-_lm_ssl_send (LmSSL *ssl, const gchar *str, gint len)
-{
- gint bytes_written;
-
- bytes_written = gnutls_record_send (ssl->gnutls_session, str, len);
-
- while (bytes_written < 0) {
- if (bytes_written != GNUTLS_E_INTERRUPTED &&
- bytes_written != GNUTLS_E_AGAIN) {
- return -1;
- }
-
- bytes_written = gnutls_record_send (ssl->gnutls_session,
- str, len);
- }
-
- return bytes_written;
-}
-
-void
-_lm_ssl_close (LmSSL *ssl)
-{
- if (!ssl->started)
- return;
-
- gnutls_deinit (ssl->gnutls_session);
- gnutls_certificate_free_credentials (ssl->gnutls_xcred);
- gnutls_global_deinit ();
-}
-
-void
-_lm_ssl_free (LmSSL *ssl)
-{
- _lm_ssl_base_free_fields (LM_SSL_BASE (ssl));
- g_free (ssl);
-}
-
-#endif /* HAVE_GNUTLS */