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

📄 gnu_tls_funcs.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
 * TLS implementation using GNUTLS.
 *
 * Licensed under a dual GPL/BSD license.  (See LICENSE file for more info.)
 *
 * \file gnu_tls_funcs.c
 *
 * \author chris@open1x.org
 *
 * $Id: gnu_tls_funcs.c,v 1.1.2.23 2007/04/20 18:35:54 chessing Exp $
 * $Date: 2007/04/20 18:35:54 $
 * $Log: gnu_tls_funcs.c,v $
 * Revision 1.1.2.23  2007/04/20 18:35:54  chessing
 * Work on the debug/trace output.  Added a WHOLE BUNCH of new debug levels.  Fixed a couple of small bugs, and cleaned out some cruft.
 *
 * Revision 1.1.2.22  2007/02/07 07:17:40  chessing
 * Updated my e-mail address in all source files.  Replaced strcpy() with a safer version.  Updated Strncpy() to be a little safer.
 *
 **/
#ifdef USE_GNUTLS

#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

#ifdef WINDOWS
#include <winsock2.h>
#endif

#include "../../profile.h"
#include "../../eap_sm.h"
#include "eaptls.h"
#include "tls_funcs.h"
#include "../../xsup_common.h"
#include "../../xsup_err.h"
#include "../../xsup_debug.h"
#include "../../frame_structs.h"

static uint8_t inited = 0;

//#warning Add gnutls_alert code.

/**********************************************************************
 *
 *  This callback function is used by GNU-TLS to put data in our buffer
 *  that we will need to send out.  Other functions are responsible for
 *  actually sending the data.  This function just queues it.
 *
 **********************************************************************/
ssize_t tls_funcs_push(gnutls_transport_ptr_t ptr,
		       const void *buf, size_t bufsiz)
{
  struct tls_vars *mytls_vars;

  mytls_vars = (struct tls_vars *)ptr;

  mytls_vars->tlsoutdata = realloc(mytls_vars->tlsoutdata, 
				   mytls_vars->tlsoutsize + bufsiz);

  memcpy((uint8_t *)&mytls_vars->tlsoutdata[mytls_vars->tlsoutsize],
	 buf, bufsiz);

  mytls_vars->tlsoutsize += bufsiz;

  debug_printf(DEBUG_TLS_CORE, "There are now %d byte(s) in the waiting "
	       "buffer.\n", mytls_vars->tlsoutsize);

  debug_printf(DEBUG_TLS_CORE, "Buffer dump (%d) : \n", 
	       mytls_vars->tlsoutsize);
  debug_hex_dump(DEBUG_TLS_CORE, mytls_vars->tlsoutdata,
		 mytls_vars->tlsoutsize);

  return bufsiz;
}

/***********************************************************************
 *
 *  This callback function is used by GNU-TLS to take data from our buffer
 *  and process it.  Other functions are responsible for filling the buffer.
 *  This function just sends it to GNU-TLS. 
 *
 ***********************************************************************/
ssize_t tls_funcs_pull(gnutls_transport_ptr_t ptr,
		       void *buf, size_t bufsiz)
{
  struct tls_vars *mytls_vars = NULL;
  ssize_t retsize = 0;

  mytls_vars = (struct tls_vars *)ptr;

  debug_printf(DEBUG_TLS_CORE, "Total data in memory : %d byte(s)\n",
               mytls_vars->tlsinsize);


  // If we don't have anything to send, ask GNU-TLS to wait.
  if (mytls_vars->tlsindata == NULL)
    {
      errno = EWOULDBLOCK;
      return -1;
    }

  // Otherwise, return "bufsiz" (or less) worth of data.  
  if (mytls_vars->tlsinsize <= bufsiz)
    {
      // We can send everything we have.
      memcpy((uint8_t *)buf, mytls_vars->tlsindata, mytls_vars->tlsinsize);
      mytls_vars->tlsinptr = mytls_vars->tlsinsize;
      retsize = mytls_vars->tlsinsize;
      debug_printf(DEBUG_TLS_CORE, "Returned complete packet of %d byte(s) to"
		   " GNU-TLS.\n", retsize);
    }
  else
    {
      // Send a chunk.
      retsize = (mytls_vars->tlsinsize - mytls_vars->tlsinptr);
      if (retsize > bufsiz) retsize = bufsiz;

      memcpy((uint8_t *)buf, 
	     (uint8_t *)&mytls_vars->tlsindata[mytls_vars->tlsinptr],
	     retsize);

      mytls_vars->tlsinptr += retsize;

      debug_printf(DEBUG_TLS_CORE, "Returned a fragment of %d byte(s) to "
		   "GNU-TLS.\n", retsize);
    }

  if (mytls_vars->tlsinptr >= mytls_vars->tlsinsize)
    {
      debug_printf(DEBUG_TLS_CORE, "Finished with this data chunk. "
		   "Freeing.\n");
      FREE(mytls_vars->tlsindata);
      mytls_vars->tlsinptr = 0;
      mytls_vars->tlsinsize = 0;
    }

  return retsize;
}

/***********************************************************************
 *
 *  This callback function is used by GNU-TLS to allow us to do something
 *  with it's log data.  The verbosity of the log data is configured in
 *  tls_funcs_init().
 *
 ***********************************************************************/
void tls_log(int level, const char *logline)
{
  debug_printf(DEBUG_NORMAL, "GNUTLS Log : %s\n", logline);
}

/***********************************************************************
 *
 *  Do whatever we need to do in order to set up GNU-TLS and get it to the
 *  point that we can use it to authenticate.
 *
 ***********************************************************************/
int tls_funcs_init(struct tls_vars *mytls_vars)
{
  int err = 0;
  int allowed_protos[3] = { GNUTLS_TLS1_0, GNUTLS_TLS1_1, 0};
  int allowed_certs[2] = { GNUTLS_CRT_X509, 0 };

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

  debug_printf(DEBUG_TLS_CORE, "(TLS Engine : GNU) Initing\n");

//#warning Find a better way to handle this!
  if (inited == 0)
    {
      debug_printf(DEBUG_TLS_CORE, "(TLS Engine) Doing global init!\n");
      if (gnutls_global_init() != 0)
	{
	  debug_printf(DEBUG_NORMAL, "Couldn't initialize GNU-TLS global state!\n");
	  return XEGENERROR;
	}

      gnutls_global_set_log_function(tls_log);
      if (debug_getlevel() == DEBUG_TLS_CORE)
	{
	  gnutls_global_set_log_level(10);               // Maximum logging.
	} 
    }

//#warning Session resume here!

  if (mytls_vars->session != NULL)
    {
      // Clear any active sessions so we can start again.
      debug_printf(DEBUG_TLS_CORE, "(TLS Engine) Cleaning up old session "
		   "data.\n");
      gnutls_deinit(mytls_vars->session);
      mytls_vars->handshake_done = FALSE;
    }

  if (gnutls_init(&mytls_vars->session, GNUTLS_CLIENT) != 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't initialize the GNU-TLS library!\n");
      return XEGENERROR;
    }

  err = gnutls_set_default_priority(mytls_vars->session);

  if (err != 0)
    {
      debug_printf(DEBUG_NORMAL, "Using default priorities. : %s\n", 
		   gnutls_strerror(err));
      return XEGENERROR;
    }

  err = gnutls_certificate_type_set_priority(mytls_vars->session, 
					     allowed_certs);

  if (err != 0)
    {
      debug_printf(DEBUG_NORMAL, "Setting certificate type priorities : %s\n",
		   gnutls_strerror(err));
      return XEGENERROR;
    }

  err = gnutls_protocol_set_priority(mytls_vars->session, allowed_protos);

  if (err != 0)
    {
      debug_printf(DEBUG_NORMAL, "Setting allowed protocols : %s\n",
		   gnutls_strerror(err));
      return XEGENERROR;
    }

  gnutls_transport_set_push_function(mytls_vars->session, tls_funcs_push);
  gnutls_transport_set_pull_function(mytls_vars->session, tls_funcs_pull);
  gnutls_transport_set_ptr(mytls_vars->session,
                           (gnutls_transport_ptr) mytls_vars);


  err = gnutls_certificate_allocate_credentials(&mytls_vars->creds);

  if (err != 0)
    {
      debug_printf(DEBUG_NORMAL, "Allocating credentials : %s\n",
		   gnutls_strerror(err));
      return XEGENERROR;
    }

  return XENONE;
}


/*************************************************************************
 *
 *  Load any root certificates that the user would want to use.  Note :
 *  This functions differently than the older OpenSSL method.
 *
 *************************************************************************/
int tls_funcs_load_root_certs(struct tls_vars *mytls_vars, 
			      char *root_cert, char *root_dir, 
			      char *crl_dir)
{
  int err = 0;

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

//#warning Fix these!
  if (root_dir != NULL)
    {
      debug_printf(DEBUG_NORMAL, "Certificate directories aren't supported "
		   "yet!\n");
      // Continue in case a root_cert is also set.
    }

  if (crl_dir != NULL)
    {
      debug_printf(DEBUG_NORMAL, "CRL directories aren't supported yet!\n");
      // Use gnutls_certificate_set_x509_crl_file()
      // Continue, because this is non-fatal.
    }

  if (root_cert == NULL)
    {
      debug_printf(DEBUG_NORMAL, "You *MUST* specify a root CA "
		   "certificate!\n");
      return XEGENERROR;
    }

  if (mytls_vars->creds == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate credentials.\n");
      return XEGENERROR;
    }

  err = gnutls_certificate_set_x509_trust_file(mytls_vars->creds, root_cert,
					       GNUTLS_X509_FMT_PEM);
  if (err < 1)
    {
      debug_printf(DEBUG_TLS_CORE, "Non-fatal error loading certificate (%d) "
		   ": %s -- Trying to load as DER.\n", err, 
		   gnutls_strerror(err));

      // It may be a DER certificate.  So try that instead.
      err = gnutls_certificate_set_x509_trust_file(mytls_vars->creds, 
						   root_cert, 
						   GNUTLS_X509_FMT_DER);

      if (err < 1)
	{
	  debug_printf(DEBUG_NORMAL, "Error loading root CA certificate!\n");
	  return XEGENERROR;
	}
    }

  return XENONE;
}

//#warning Need to add loading of random data functions.

/************************************************************************
 *
 *  Load a user certificate in to GNU-TLS so that it can be used for
 *  authentication.
 *
 ************************************************************************/
int tls_funcs_load_user_cert(struct tls_vars *mytls_vars, char *user_cert,
			     char *user_key, char *userpass)
{
  gnutls_x509_privkey key;
  uint8_t *certbuf;
  FILE *fp;
  size_t size;
  gnutls_datum cert;

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

  if (user_cert == NULL)
    {
      debug_printf(DEBUG_NORMAL, "No user certificate to load!\n");
      return XEGENERROR;
    }

  if (user_key == NULL)
    {
      debug_printf(DEBUG_NORMAL, "No user key file to load!\n");
      return XEGENERROR;
    }

  if (userpass == NULL)
    {
      debug_printf(DEBUG_NORMAL, "No password provided!\n");
      return XEGENERROR;
    }

//#warning Need to import the user certificate.

  gnutls_x509_privkey_init(&key);

  certbuf = Malloc(64 * 1024);
  if (certbuf == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store "
		   "user certificate.\n");
      return XEMALLOC;
    }

  // Open the certificate key file.
  fp = fopen(user_key, "r");
  if (fp == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't open file '%s'.\n");
      return XEGENERROR;
    }

  size = fread(certbuf, 1, (64 * 1024)-1, fp);

  if (ferror(fp) != 0)
    {
      debug_printf(DEBUG_NORMAL, "File read error at %s:%d!\n", __FUNCTION__,
		   __LINE__);
      return XEGENERROR;
    }

⌨️ 快捷键说明

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