loudmouth/src/lm-ssl-openssl.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
--- a/loudmouth/src/lm-ssl-openssl.c	Tue Feb 02 01:10:06 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,469 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006 Imendio AB
- *  and/or its subsidiary/subsidiaries. All rights reserved.
- *
- * 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 <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <glib.h>
-
-#include "lm-debug.h"
-#include "lm-error.h"
-#include "lm-ssl-base.h"
-#include "lm-ssl-internals.h"
-
-#ifdef EMULATOR
-#include "libloudmouth_wsd_solution.h"
-GET_STATIC_VAR_FROM_TLS(initialized, lm_ssl_openssl, gboolean)
-  #define initialized (*GET_WSD_VAR_NAME(initialized, lm_ssl_openssl, s) () )
-#endif
-#ifdef HAVE_OPENSSL
-
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-
-#define LM_SSL_CN_MAX		63
-
-struct _LmSSL {
-	LmSSLBase base;
-
-	SSL_METHOD *ssl_method;
-	SSL_CTX *ssl_ctx;
-	SSL *ssl;
-	/*BIO *bio;*/
-};
-
-int ssl_verify_cb (int preverify_ok, X509_STORE_CTX *x509_ctx);
-
-static gboolean ssl_verify_certificate (LmSSL *ssl, const gchar *server);
-static GIOStatus ssl_io_status_from_return (LmSSL *ssl, gint error);
-
-/*static char _ssl_error_code[11];*/
-
-static void
-ssl_print_state (LmSSL *ssl, const char *func, int val)
-{
-	unsigned long errid;
-	const char *errmsg;
-
-	switch (SSL_get_error(ssl->ssl, val)) {
-		case SSL_ERROR_NONE:
-			g_warning ("%s(): %i / SSL_ERROR_NONE",
-				   func, val);
-			break;
-		case SSL_ERROR_ZERO_RETURN:
-			g_warning ("%s(): %i / SSL_ERROR_ZERO_RETURN",
-				   func, val);
-			break;
-		case SSL_ERROR_WANT_READ:
-			g_warning ("%s(): %i / SSL_ERROR_WANT_READ",
-				   func, val);
-			break;
-		case SSL_ERROR_WANT_WRITE:
-			g_warning ("%s(): %i / SSL_ERROR_WANT_WRITE",
-				   func, val);
-			break;
-		case SSL_ERROR_WANT_X509_LOOKUP:
-			g_warning ("%s(): %i / SSL_ERROR_WANT_X509_LOOKUP",
-				   func, val);
-			break;
-		case SSL_ERROR_SYSCALL:
-			g_warning ("%s(): %i / SSL_ERROR_SYSCALL",
-				   func, val);
-			break;
-		case SSL_ERROR_SSL:
-			g_warning ("%s(): %i / SSL_ERROR_SSL",
-				   func, val);
-			break;
-	}
-	do {
-		errid = ERR_get_error();
-		if (errid) {
-			errmsg = ERR_error_string(errid, NULL);
-			g_warning ("\t%s", errmsg);
-		}
-	} while (errid != 0);
-}
-
-/*static const char *
-ssl_get_x509_err (long verify_res)
-{
-	sprintf(_ssl_error_code, "%ld", verify_res);
-	return _ssl_error_code;
-}*/
-
-	
-int
-ssl_verify_cb (int preverify_ok, X509_STORE_CTX *x509_ctx)
-{
-	/* As this callback doesn't get auxiliary pointer parameter we
-	 * cannot really use this. However, we can retrieve results later. */
-    UNUSED_FORMAL_PARAM(preverify_ok);
-    UNUSED_FORMAL_PARAM(x509_ctx);
-	return 1;
-}
-
-static gboolean
-ssl_verify_certificate (LmSSL *ssl, const gchar *server)
-{
-	gboolean retval = TRUE;
-	LmSSLBase *base;
-	long verify_res;
-	unsigned int digest_len;
-	X509 *srv_crt;
-	gchar *cn;
-	X509_NAME *crt_subj;
-
-  return TRUE ; // hack - to bypass certificate verification error- Pankaj
-/*
-	base = LM_SSL_BASE(ssl);
-
-	//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
-	//       "%s: Cipher: %s/%s/%i\n",
-	//       __FILE__,
-	//       SSL_get_cipher_version(ssl->ssl),
-	//       SSL_get_cipher_name(ssl->ssl),
-	//       SSL_get_cipher_bits(ssl->ssl, NULL));
-	
-	lm_verbose("\n[ssl_verify_certificate]:Cipher: %s/%s/%i\n",
-	       SSL_get_cipher_version(ssl->ssl),
-	       SSL_get_cipher_name(ssl->ssl),
-	       SSL_get_cipher_bits(ssl->ssl, NULL));
-
-	verify_res = SSL_get_verify_result(ssl->ssl);
-	srv_crt = SSL_get_peer_certificate(ssl->ssl);
-	if (base->expected_fingerprint != NULL) {
-		X509_digest(srv_crt, EVP_md5(), (guchar *) base->fingerprint,
-			&digest_len);
-		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;
-			}
-		}
-	}
-    //g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
-	  //     "%s: SSL_get_verify_result() = %ld\n",
-	  //     __FILE__,
-	  //     verify_res);
-	lm_verbose("[ssl_verify_certificate]: SSL_get_verify_result() = %ld\n", verify_res);
-	switch (verify_res) {
-		case X509_V_OK:
-			break;
-		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
-			// special case for self signed certificates? 
-		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
-		case X509_V_ERR_UNABLE_TO_GET_CRL:
-		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
-			if (base->func(ssl,
-				LM_SSL_STATUS_NO_CERT_FOUND,
-				base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
-				retval = FALSE;
-			}
-			break;
-		case X509_V_ERR_INVALID_CA:
-		case X509_V_ERR_CERT_UNTRUSTED:
-		case X509_V_ERR_CERT_REVOKED:
-			if (base->func(ssl,
-				LM_SSL_STATUS_UNTRUSTED_CERT,
-				base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
-				retval = FALSE;
-			}
-			break;
-		case X509_V_ERR_CERT_NOT_YET_VALID:
-		case X509_V_ERR_CRL_NOT_YET_VALID:
-			if (base->func(ssl,
-				LM_SSL_STATUS_CERT_NOT_ACTIVATED,
-				base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
-				retval = FALSE;
-			}
-			break;
-		case X509_V_ERR_CERT_HAS_EXPIRED:
-		case X509_V_ERR_CRL_HAS_EXPIRED:
-			if (base->func(ssl,
-				LM_SSL_STATUS_CERT_EXPIRED,
-				base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
-				retval = FALSE;
-			}
-			break;
-		default:
-			if (base->func(ssl, LM_SSL_STATUS_GENERIC_ERROR,
-				base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
-				retval = FALSE;
-			}
-	}
-	//if (retval == FALSE) {
-	//	g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
-	//		ssl_get_x509_err(verify_res), NULL);
-	//}
-	crt_subj = X509_get_subject_name(srv_crt);
-	cn = (gchar *) g_malloc0(LM_SSL_CN_MAX + 1);
-	
-	if (X509_NAME_get_text_by_NID(crt_subj, NID_commonName, cn, LM_SSL_CN_MAX) > 0) {
-		gchar *domain = cn;
-
-		//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
-		//      "%s: server = '%s', cn = '%s'\n",
-		//      __FILE__, server, cn);
-		lm_verbose("%s: server = '%s', cn = '%s'\n",
-		      __FILE__, server, cn);
-		
-		if ((cn[0] == '*') && (cn[1] == '.')) {
-			domain = strstr (cn, server);
-		}
-
-		if ((domain == NULL) || (strncmp (server, domain, LM_SSL_CN_MAX) != 0)) {
-			if (base->func (ssl,
-					LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH,
-					base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
-				retval = FALSE;
-			}
-    	}
-	} else {
-		g_warning ("X509_NAME_get_text_by_NID() failed");
-	}
-
-	//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, 
-	//       "%s:\n\tIssuer: %s\n\tSubject: %s\n\tFor: %s\n",
-	//       __FILE__,
-	//       X509_NAME_oneline(X509_get_issuer_name(srv_crt), NULL, 0),
-	//       X509_NAME_oneline(X509_get_subject_name(srv_crt), NULL, 0),
-	//       cn);
-	       
-	lm_verbose("%s:\n\tIssuer: %s\n\tSubject: %s\n\tFor: %s\n",
-	       __FILE__,
-	       X509_NAME_oneline(X509_get_issuer_name(srv_crt), NULL, 0),
-	       X509_NAME_oneline(X509_get_subject_name(srv_crt), NULL, 0),
-	       cn);
-
-	g_free(cn);
-	
-	//return TRUE ; // hack - to bypass certificate verification error- Pankaj
-	return retval;
-	*/
-}
-
-static GIOStatus
-ssl_io_status_from_return (LmSSL *ssl, gint ret)
-{
-	gint      error;
-	GIOStatus status;
-
-	if (ret > 0) return G_IO_STATUS_NORMAL;
-
-	error = SSL_get_error(ssl->ssl, ret);
-	switch (error) {
-		case SSL_ERROR_WANT_READ:
-		case SSL_ERROR_WANT_WRITE:
-			status = G_IO_STATUS_AGAIN;
-			break;
-		case SSL_ERROR_ZERO_RETURN:
-			status = G_IO_STATUS_EOF;
-			break;
-		default:
-			status = G_IO_STATUS_ERROR;
-	}
-
-	return status;
-}
-
-/* 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) 
-{
-#ifndef EMULATOR
-	static gboolean initialized = FALSE;
-#endif
-	/*const char *cert_file = NULL;*/
-
-	if (!initialized) {
-		SSL_library_init();
-		/* FIXME: Is this needed when we are not in debug? */
-		SSL_load_error_strings();
-		initialized = TRUE;
-	}
-
-	ssl->ssl_method = TLSv1_client_method();
-	if (ssl->ssl_method == NULL) {
-		g_warning ("TLSv1_client_method() == NULL");
-		abort();
-	}
-	ssl->ssl_ctx = SSL_CTX_new(ssl->ssl_method);
-	if (ssl->ssl_ctx == NULL) {
-		g_warning ("SSL_CTX_new() == NULL");
-		abort();
-	}
-	/*if (access("/etc/ssl/cert.pem", R_OK) == 0)
-		cert_file = "/etc/ssl/cert.pem";
-	if (!SSL_CTX_load_verify_locations(ssl->ssl_ctx,
-		cert_file, "/etc/ssl/certs")) {
-		g_warning("SSL_CTX_load_verify_locations() failed");
-	}*/
-	SSL_CTX_set_default_verify_paths (ssl->ssl_ctx);
-	SSL_CTX_set_verify (ssl->ssl_ctx, SSL_VERIFY_PEER, ssl_verify_cb);
-}
-
-gboolean
-_lm_ssl_begin (LmSSL *ssl, gint fd, const gchar *server, GError **error)
-{
-	gint ssl_ret;
-	GIOStatus status;
-
-	if (!ssl->ssl_ctx) {
-		g_set_error (error,
-			     LM_ERROR, LM_ERROR_CONNECTION_OPEN,
-			     "No SSL Context for OpenSSL");
-		return FALSE;
-	}
-
-	ssl->ssl = SSL_new(ssl->ssl_ctx);
-	if (ssl->ssl == NULL) {
-		g_warning ("SSL_new() == NULL");
-		g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
-			    "SSL_new()");
-		return FALSE;
-	}
-
-	if (!SSL_set_fd (ssl->ssl, fd)) {
-		g_warning ("SSL_set_fd() failed");
-		g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
-			"SSL_set_fd()");
-		return FALSE;
-	}
-	/*ssl->bio = BIO_new_socket (fd, BIO_NOCLOSE);
-	if (ssl->bio == NULL) {
-		g_warning("BIO_new_socket() failed");
-		g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
-			"BIO_new_socket()");
-		return FALSE;
-	}
-	SSL_set_bio(ssl->ssl, ssl->bio, ssl->bio);*/
-
-	do {
-		ssl_ret = SSL_connect(ssl->ssl);
-		if (ssl_ret <= 0) {
-			status = ssl_io_status_from_return(ssl, ssl_ret);
-			if (status != G_IO_STATUS_AGAIN) {
-				lm_verbose("[_lm_ssl_begin] errno for ssl connect:[%d], ssl_ret[%d]\n", errno, ssl_ret);
-				lm_verbose("\n[_lm_ssl_begin] ssl_io_status_from_return return status failed..:[%d]\n", status);
-				ssl_print_state(ssl, "SSL_connect",
-					ssl_ret);
-				g_set_error(error, LM_ERROR,
-					LM_ERROR_CONNECTION_OPEN,
-					"SSL_connect()");
-				return FALSE;
-			}
-		}
-	} while (ssl_ret <= 0);
-
-	lm_verbose("\n[_lm_ssl_begin] errno for ssl connect:[%d], ssl_ret[%d]\n", errno, ssl_ret);
-	// log
-	{
-	long verify_res;	
-	verify_res = SSL_get_verify_result(ssl->ssl);
-	lm_verbose("[_lm_ssl_begin]: After SSL Connect : SSL_get_verify_result() = %ld\n", verify_res);
-	}
-
-	if (!ssl_verify_certificate (ssl, server)) {
-		g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
-			"*** SSL certificate verification failed");
-		return FALSE;
-	}
-	
-	return TRUE; 
-}
-
-GIOStatus
-_lm_ssl_read (LmSSL *ssl, gchar *buf, gint len, gsize *bytes_read)
-{
-	GIOStatus status;
-	gint ssl_ret;
-
-	*bytes_read = 0;
-	ssl_ret = SSL_read(ssl->ssl, buf, len);
-	status = ssl_io_status_from_return(ssl, ssl_ret);
-	if (status == G_IO_STATUS_NORMAL) {
-		*bytes_read = ssl_ret;
-	}
-	
-	return status;
-}
-
-gint
-_lm_ssl_send (LmSSL *ssl, const gchar *str, gint len)
-{
-	GIOStatus status;
-	gint ssl_ret;
-
-	do {
-		ssl_ret = SSL_write(ssl->ssl, str, len);
-		if (ssl_ret <= 0) {
-			status = ssl_io_status_from_return(ssl, ssl_ret);
-			if (status != G_IO_STATUS_AGAIN)
-				return -1;
-		}
-	} while (ssl_ret <= 0);
-
-	return ssl_ret;
-}
-
-void 
-_lm_ssl_close (LmSSL *ssl)
-{
-	if (ssl->ssl != NULL) {
-		SSL_shutdown(ssl->ssl);
-		SSL_free(ssl->ssl);
-		ssl->ssl = NULL;
-	}
-}
-
-void
-_lm_ssl_free (LmSSL *ssl)
-{
-	SSL_CTX_free(ssl->ssl_ctx);
-	ssl->ssl_ctx = NULL;
-
-	_lm_ssl_base_free_fields (LM_SSL_BASE(ssl));
-	g_free (ssl);
-}
-
-#endif /* HAVE_GNUTLS */