⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ossl_tls_funcs.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 4 页
字号:
/**
 * EAPTLS (RFC 2716) Function implementations
 * 
 * Licensed under a dual GPL/BSD license.  (See LICENSE file for more info.)
 *
 * \file ossl_tls_funcs.c
 *
 * \author chris@open1x.org
 *
 * $Id: ossl_tls_funcs.c,v 1.1.2.53 2008/02/04 19:46:50 chessing Exp $
 * $Date: 2008/02/04 19:46:50 $
 */

#ifndef USE_GNUTLS

#ifdef WINDOWS
#define OPENSSL_NO_ENGINE

#include <windows.h>
#endif

#include <stdio.h>
#include <string.h>

#include <openssl/ssl.h>

#ifndef WINDOWS
/* For some reason, including this file on windows right now will cause the compiler to fail.
	Since it generally isn't used, we will disable it on Windows for now. */
#include <openssl/engine.h>
#endif

#include <openssl/ui.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/bio.h>

#ifndef WINDOWS
#include <netinet/in.h>
#include <inttypes.h>
#include <unistd.h>
#endif

#include <string.h>
#include "../../../lib/libxsupconfig/xsupconfig_structs.h"
#include "../../xsup_common.h"
#include "../../../lib/libxsupconfig/xsupconfig.h"
#include "../../context.h"
#include "../../eap_sm.h"
#include "../../eap_types/tls/eaptls.h"
#include "tls_funcs.h"
#include "../../xsup_debug.h"
#include "../../xsup_err.h"
#include "../../frame_structs.h"
#include "../../ipc_events.h"
#include "../../ipc_events_index.h"

#ifdef USE_EFENCE
#include <efence.h>
#endif

// In OpenSSL 0.9.8 we need to explicitly include the SHA header.
#ifndef SHA_DIGEST_LENGTH
#include <openssl/sha.h>
#endif

// If it *STILL* isn't around, then just define it.
#ifndef SHA_DIGEST_LENGTH
#define SHA_DIGEST_LENGTH 20
#endif

int engine_load_dynamic_opensc(struct smartcard *sc);
void set_smartcard_pin(char *pin);
UI_METHOD *UI_noninteractive(void);

/************************************************************************
 *
 * Get the common name field from a certificate for later processing.
 *
 ************************************************************************/
char *get_cert_common_name(SSL *ssl_ctx)
{
  char *commonName = NULL;
  X509 *server_cert;

  TRACE

  if (!xsup_assert((ssl_ctx != NULL), "ssl_ctx != NULL", FALSE))
    return NULL;

  // Get our certificate.
  server_cert = SSL_get_peer_certificate(ssl_ctx);

  if (!server_cert) return NULL;

  commonName = (char *)Malloc(512);
  if (commonName == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to hold the common name!\n");
	  ipc_events_malloc_failed(NULL);
      return NULL;
    }

  if (X509_NAME_get_text_by_NID(X509_get_subject_name(server_cert),
				NID_commonName, commonName, 512) < 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't extract common name from server certificate!\n");
      return NULL;
    }

  debug_printf(DEBUG_TLS_CORE, "Extracted common name of %s\n",commonName);
  return commonName;
}

/************************************************************************
 *
 *  Process an error condition and display some information about it.
 *
 ************************************************************************/
void tls_funcs_process_error()
{
  unsigned long err;

  TRACE

  err = ERR_get_error();
  if (err != 0)
    {
      debug_printf(DEBUG_NORMAL, "OpenSSL Error -- %s\n", 
		   ERR_error_string(err, NULL));
      debug_printf(DEBUG_NORMAL, "Library  : %s\n", ERR_lib_error_string(err));
      debug_printf(DEBUG_NORMAL, "Function : %s\n", ERR_func_error_string(err));
      debug_printf(DEBUG_NORMAL, "Reason   : %s\n", ERR_reason_error_string(err));
    }
}

/************************************************************************
 *
 *  Determine if we have any data pending.  If we do, return the number of
 *  bytes that are pending.
 *
 ************************************************************************/
uint32_t tls_funcs_data_pending(struct tls_vars *mytls_vars)
{
	uint32_t retsize;

  if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
    return 0;

  if (queue_get_size(&mytls_vars->tlsoutqueue, &retsize) < 0)
	  return 0;                // Something was wrong, so we can't have anything more to send.

  return retsize;
}

/************************************************************************
 *
 *  Do some standard checks to be sure our certificate is valid.
 *
 ************************************************************************/
static int ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
  char buf[256];
  X509 *err_cert;
  int err, depth;

  TRACE

  if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
    return XEMALLOC;

  err_cert = X509_STORE_CTX_get_current_cert(ctx);
  err = X509_STORE_CTX_get_error(ctx);
  depth = X509_STORE_CTX_get_error_depth(ctx);
  X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);

  debug_printf(DEBUG_TLS_CORE, "     --- SSL_verify : depth %d\n", depth);

  if (!preverify_ok)
    {
      debug_printf(DEBUG_TLS_CORE, "     --- SSL_verify error : num=%d:%s:depth=%d:%s\n",
		   err, X509_verify_cert_error_string(err), depth, buf);

      // Ignore the self signed certificate error, from OpenSSL.
      if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) preverify_ok = 1;
    }

  debug_printf(DEBUG_TLS_CORE, "preverify_ok = %d\n", preverify_ok);

  return preverify_ok;
}

/***********************************************************************
 *
 *  Initialize the Open SC smart card handler.
 *
 ***********************************************************************/
#ifndef WINDOWS
int tls_funcs_load_engine(struct tls_vars *mytls_vars, struct smartcard *sc)
{
  if(!engine_load_dynamic_opensc(sc))
    {
      debug_printf(DEBUG_NORMAL, "OpenSC Engine will be unavailable!\n");
      return XEGENERROR;
    }

  debug_printf(DEBUG_NORMAL, "Using Engine with ID \"%s\"\n", 
	       sc->engine_id);

  mytls_vars->engine = ENGINE_by_id(sc->engine_id);
  if (!mytls_vars->engine)
    {
      debug_printf(DEBUG_NORMAL, "Engine not available!\n");
      return XETLSINIT;
    }
								       
  /* Now everything that can be done without having a smartcard plugged in
   * is done. The next step is initializing the Engine.
   * This step should probably be done in some place where it can be
   * retried if it fails.
   */

  if (!ENGINE_init(mytls_vars->engine))
    {
      debug_printf(DEBUG_NORMAL, "Can't initialize OpenSC Engine! "
		   "Is the smartcard plugged in?\n");
      /* If we get this error there's probably no smartcard connected -
       * we should be able to retry the call to ENGINE_init() */
      return XETLSINIT;
    }
  return XENONE;
}
#endif  // WINDOWS


/***********************************************************************
 *
 *  Configure the cipher suites to only do TLS_DH_anon_WITH_AES_128_CBC_SHA
 *  this is use with EAP-FAST to provide unauthenticated provisioning.
 *
 ***********************************************************************/
int tls_funcs_set_anon_dh_aes(struct tls_vars *mytls_vars)
{
  if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
    return -1;

  if (!xsup_assert((mytls_vars->ssl != NULL), "mytls_vars->ssl != NULL",
		   FALSE))
    return -1;

  if (SSL_set_cipher_list(mytls_vars->ssl, "ADH-AES128-SHA") != 1)
    {
      // The cipher type wasn't allowed. (Probably not compiled in.)
      debug_printf(DEBUG_NORMAL, "Anonymous cipher ADH-AES128-SHA was not "
		   "available!  It is possible that your OpenSSL was not "
		   "compiled with support for it!\n");
      return -1;
    }

  return 0;
}

/***********************************************************************
 *
 *  Allocate memory, and set up structures needed to complete a TLS
 *  based authentication.
 *
 ***********************************************************************/
int tls_funcs_init(struct tls_vars *mytls_vars, uint8_t eaptype)
{
  TRACE

  if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
    return XETLSINIT;

  // XXX Need to move the global init pieces here. (OpenSSL init stuff.) Once we
  // finish making the changes to allow GNU-TLS as an option.

  if (mytls_vars->ssl)
    {
      SSL_shutdown(mytls_vars->ssl);
      SSL_free(mytls_vars->ssl);
      mytls_vars->ssl = NULL;
    }

  if (mytls_vars->ctx != NULL)
    {
      SSL_CTX_free(mytls_vars->ctx);
      mytls_vars->ctx = NULL;
    }

  mytls_vars->ctx = SSL_CTX_new(TLSv1_method());
  if (mytls_vars->ctx == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't initialize OpenSSL TLS library!\n");
      tls_funcs_process_error();
	  ipc_events_malloc_failed(NULL);
      return XETLSINIT;
    }

  mytls_vars->method_in_use = eaptype;

  return XENONE;
}

/*************************************************************************
*
* Allocate a new context for OpenSSL.
*
**************************************************************************/
int tls_funcs_build_new_session(struct tls_vars *mytls_vars)
{
  TRACE

  if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
    return XEMALLOC;

  if (mytls_vars->ssl)
    {
      SSL_shutdown(mytls_vars->ssl);
  }

  if (mytls_vars->ssl)
  {
      SSL_free(mytls_vars->ssl);
      mytls_vars->ssl = NULL;
    }

  if (mytls_vars->ctx == NULL)
  {
	  debug_printf(DEBUG_NORMAL, "The SSL context is NULL.  (This shouldn't happen.)  Working around it.\n");
	  if (tls_funcs_init(mytls_vars, mytls_vars->method_in_use) != XENONE) return XETLSSTARTFAIL;
  }

  mytls_vars->ssl = SSL_new(mytls_vars->ctx);
  if (!mytls_vars->ssl)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't create SSL object!\n");
      tls_funcs_process_error();
      
      return XETLSSTARTFAIL;
    }

  return XENONE;
}
  
/*************************************************************************
*
*  Handle processing of a start packet.
*
**************************************************************************/
int ossl_funcs_do_start(struct tls_vars *mytls_vars)
{
  SSL_SESSION *sess = NULL;
  unsigned long err;
  int counter, resval = XENONE;
  int mode = 0, ressize = 0;
  uint8_t *tempdata = NULL;

  TRACE

  if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
    return XEMALLOC;

  debug_printf(DEBUG_TLS_CORE, "Got TLS Start!\n");

  mytls_vars->resuming = 0;

  if ((mytls_vars->ssl == NULL) || (mytls_vars->resume != RES_YES))
    {
      resval = tls_funcs_build_new_session(mytls_vars);
      if (resval != XENONE) 
		{
			debug_printf(DEBUG_NORMAL, "Error building a new session!\n");
			return resval;
		}
    } else {
      // We already established a connection, so we probably we need to
      // resume the session.
      if (mytls_vars->resume == RES_YES)
		{
			sess = SSL_get_session(mytls_vars->ssl);
			if (!sess)
				{
					debug_printf(DEBUG_TLS_CORE, "Couldn't get session information!"
						" We won't try to resume this session!\n");
					mytls_vars->resuming = 0;

			      // Clear the old session data.
				    SSL_free(mytls_vars->ssl);

			      // Set up a new session.	
			      resval = tls_funcs_build_new_session(mytls_vars);
			      if (resval != XENONE) return resval;
			    } else {
			      debug_printf(DEBUG_TLS_CORE, "Got session information, trying "
					   "to resume session!\n");
			      mytls_vars->resuming = 1;

	      // We don't want to send an alert to the other end..  So do a 
	      // quiet shutdown.  This violates the TLS standard, but it is 
	      // needed to avoid confusing the other end of the connection 
	      // when we want to do a reconnect!
	      SSL_set_quiet_shutdown(mytls_vars->ssl, 1);
	      
	      // Now, close off our old session.
	      err = 0;
	      counter = 0;

	      SSL_shutdown(mytls_vars->ssl);

	      while ((err == 0) && (counter < 60))
		{
		  err = SSL_shutdown(mytls_vars->ssl);
		  if (err == 0)
		    {
#ifndef WINDOWS
		      sleep(1);
#else
			  Sleep(1000);
#endif
		      counter++;
		    }
		}

	      if (err < 0)
		{
		  debug_printf(DEBUG_NORMAL, "Error trying to shut down SSL "
			       "context data.\n");
		  tls_funcs_process_error();
		}
	    }
	}
    }

  mytls_vars->ssl_in = BIO_new(BIO_s_mem());
  if (!mytls_vars->ssl_in)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't create ssl_in!\n");
      tls_funcs_process_error();
	  ipc_events_malloc_failed(NULL);
      return XETLSSTARTFAIL;
    }

  if (BIO_reset(mytls_vars->ssl_in) < 1)
    {
      debug_printf(DEBUG_NORMAL, "Error : %s:%d\n", __FUNCTION__, __LINE__);
      tls_funcs_process_error();
    }

  mytls_vars->ssl_out = BIO_new(BIO_s_mem());
  if (!mytls_vars->ssl_out)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't create ssl_out!\n");
      tls_funcs_process_error();
	  ipc_events_malloc_failed(NULL);
      return XETLSSTARTFAIL;
    }

  if (BIO_reset(mytls_vars->ssl_out) < 0)
    {
      debug_printf(DEBUG_NORMAL, "Error : %s:%d\n", __FUNCTION__, __LINE__);
      tls_funcs_process_error();
    }

  if (sess != NULL)
    {
      // If we have session information, we need to use it to resume the 
      // session.
      debug_printf(DEBUG_TLS_CORE, "Attempting to resume session...\n");
      if (SSL_set_session(mytls_vars->ssl, sess) <= 0)
	{
	  debug_printf(DEBUG_NORMAL, "There was an error attempting to resume "
		       "the session!\n");
	  tls_funcs_process_error();
	}
    }

  SSL_set_bio(mytls_vars->ssl, mytls_vars->ssl_in, mytls_vars->ssl_out);

  // Set this to SSL_VERIFY_NONE if we don't want to do anything with a failed
  // verification.

  if (mytls_vars->verify_cert == TRUE)
    {
      mode = SSL_VERIFY_PEER;
    }
  else
    {
      mode = SSL_VERIFY_NONE;
    }

  SSL_set_verify(mytls_vars->ssl, mode, ssl_verify_callback);

  err = SSL_connect(mytls_vars->ssl);

  if (err < 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't start handshake!  Error was %d.\n",
		   err);
      err = SSL_get_error(mytls_vars->ssl, err);
      debug_printf(DEBUG_NORMAL, "Error : %d\n", err);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -