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

📄 gnu_tls_funcs.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 3 页
字号:

  fclose(fp);

  cert.data = certbuf;
  cert.size = size;

  if (gnutls_x509_privkey_import(key, &cert, GNUTLS_X509_FMT_PEM) != 0)
    {
      debug_printf(DEBUG_TLS_CORE, "Couldn't load certificate as PEM! (With"
		   " no password.)  Trying DER.\n");
      
      if (gnutls_x509_privkey_import(key, &cert, GNUTLS_X509_FMT_DER) != 0)
	{
	  debug_printf(DEBUG_TLS_CORE, "Couldn't load certificate as DER! "
		       "(With no password.)  Trying PEM with password.\n");

	  if (gnutls_x509_privkey_import_pkcs8(key, &cert, 
					       GNUTLS_X509_FMT_PEM, userpass,
					       0) != 0)
	    {
	      debug_printf(DEBUG_TLS_CORE, "Couldn't load certificate as PEM"
			   " with password!  Trying DER with password!\n");

	      if (gnutls_x509_privkey_import_pkcs8(key, &cert,
						   GNUTLS_X509_FMT_DER,
						   userpass, 0) != 0)
		{
		  debug_printf(DEBUG_TLS_CORE, "Couldn't load certificate as "
			       "encrypted DER with password!  Trying as "
			       "unencrypted DER with password!\n");

		  if (gnutls_x509_privkey_import_pkcs8(key, &cert,
						       GNUTLS_X509_FMT_DER,
						       userpass,
						       GNUTLS_PKCS_PLAIN) != 0)
		    {
		      debug_printf(DEBUG_TLS_CORE, "Couldn't load certficate"
				   " in any way we know of!  Your certificate"
				   " is either incorrect, or has issues.\n");
		      return XEGENERROR;
		    }
		}
	    }
	}
    }
//#warning Need to set a flag so that we can clean up the privkey import when we shut down.


  return XENONE;
}

/**********************************************************************
 *
 *  This function is called when we recieve a start request (0x20) from 
 *  the server.  It should finalize credentials, and begin the handshake.
 *
 **********************************************************************/
int gnutls_funcs_do_start(struct tls_vars *mytls_vars)
{
  int err = 0;

  err = gnutls_credentials_set(mytls_vars->session, GNUTLS_CRD_CERTIFICATE,
                               mytls_vars->creds);
  if (err != 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't enable credentials.  Error was : "
		   "%s\n", gnutls_strerror(err));
      return XEGENERROR;
    }

  err = gnutls_handshake(mytls_vars->session);

  if ((err != 0) && (err != GNUTLS_E_AGAIN))
    {
      debug_printf(DEBUG_NORMAL, "Couldn't start handshake!  Error was (%d): "
		   "%s\n", err, gnutls_strerror(err));
      return XEGENERROR;
    }

  return XENONE;
}

/*************************************************************************
 *
 *  Verify that the common name field of a certificate matches a user defined
 *  value.  If exact == TRUE, then it must match exactly.  Otherwise, it
 *  must only contain the substring specified by the user.
 *
 *************************************************************************/
uint8_t tls_funcs_check_cn(char *cn, char *tomatch, uint8_t exact)
{
  if (exact == TRUE)
    {
      // Check for an exact match.
      if (strcmp(cn, tomatch) == 0) return TRUE;
    }
  else
    {
//#warning  We should do some additional checks to be sure the substring is at the tail end of the string.  Otherwise a search for "monkey.com" would also match "monkey.com.com" or similar.
      // Check for a substring match.
      if (strstr(cn, tomatch) != NULL) return TRUE;
    }

  return FALSE;
}

/*************************************************************************
 *
 *  Do a bunch of different checks against the certificate chain that we
 *  have.
 *
 *************************************************************************/
int verify_certificate(gnutls_session_t session, char *common_name, 
		       uint8_t exact_match)
{
  unsigned int status;
  const gnutls_datum_t *cert_list;
  int cert_list_size, ret, retval = XENONE;
  gnutls_x509_crt_t cert;
  char dnsname[256];
  size_t dnsnamesize;

  /* This verification function uses the trusted CAs in the credentials
   * structure. So you must have installed one or more CA certificates.
   */
  ret = gnutls_certificate_verify_peers2 (session, &status);

  if (ret < 0)
    {
      debug_printf(DEBUG_NORMAL, "Error checking certificate!\n");
      debug_printf(DEBUG_NORMAL, "Error was (%d) : %s\n", ret, 
		   gnutls_strerror(ret));
      return XEGENERROR;
    }

  if (status & GNUTLS_CERT_INVALID)
    debug_printf(DEBUG_NORMAL, "The certificate is not trusted.\n");

  if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
    debug_printf(DEBUG_NORMAL, "The certificate hasn't got a known issuer.\n");

  if (status & GNUTLS_CERT_REVOKED)
    debug_printf(DEBUG_NORMAL, "The certificate has been revoked.\n");

  if (status != 0)
    {
      debug_printf(DEBUG_NORMAL, "Certificate checks failed!\n");
      return XEGENERROR;
    }

  /* Up to here the process is the same for X.509 certificates and
   * OpenPGP keys. From now on X.509 certificates are assumed. This can
   * be easily extended to work with openpgp keys as well.
   */
  if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509)
    {
      debug_printf(DEBUG_NORMAL, "Certificate is not a valid x.509 "
		   "certificate!\n");
      return XEGENERROR;
    }

  if (gnutls_x509_crt_init (&cert) < 0)
    {
      debug_printf (DEBUG_NORMAL, "Error initializing certificate "
		    "structures.\n");
      retval = XEGENERROR;
      goto deinit;
    }

  cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
  if (cert_list == NULL)
    {
      debug_printf (DEBUG_NORMAL, "The server didn't send us any "
		    "certificates.\n");
      retval = XEGENERROR;
      goto deinit;
    }

  /* This is not a real world example, since we only check the first 
   * certificate in the given chain.
   */
  if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
    {
      debug_printf (DEBUG_NORMAL, "Error parsing certificate.\n");
      retval = XEGENERROR;
      goto deinit;
    }

  /* Beware here we do not check for errors.
   */
  if (gnutls_x509_crt_get_expiration_time (cert) < time (0))
    {
      debug_printf (DEBUG_NORMAL, "The certificate has expired!\n");
      retval = XEGENERROR;
      goto deinit;
    }

  if (gnutls_x509_crt_get_activation_time (cert) > time (0))
    {
      debug_printf (DEBUG_NORMAL, "The certificate is not yet activated!\n");
      retval = XEGENERROR;
      goto deinit;
    }

  dnsnamesize = sizeof(dnsname);

  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0,
				    0, dnsname, &dnsnamesize) < 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't find a common name field in the "
		   "certificate!\n");
      retval = XEGENERROR;
      goto deinit;
    }

  debug_printf(DEBUG_TLS_CORE, "CN = %s\n", dnsname);
  if (common_name != NULL)
    {
      // We need to do a match.
      if (tls_funcs_check_cn(dnsname, common_name, exact_match) != TRUE)
	{
	  if (exact_match == TRUE)
	    {
	      debug_printf(DEBUG_NORMAL, "The certificate's common name did "
			   "not match!  You asked that the certificate's CN "
			   "match '%s' exactly.  But, the certificate's CN "
			   "was '%s'.\n", common_name, dnsname);
	    }
	  else
	    {
	      debug_printf(DEBUG_NORMAL, "The certificate's common name did "
			   "not match!  You asked that the certificate's CN "
			   "contain '%s'.  But, the certificate's CN was "
			   "'%s'.\n", common_name, dnsname);
	    }
	  retval = XEGENERROR;
	  goto deinit;
	}
    }

 deinit:
  gnutls_x509_crt_deinit (cert);

  return retval;
}

/************************************************************************
 *
 *  This function is called to process packets that aren't start packets.
 *
 ************************************************************************/
uint8_t gnutls_funcs_process_other(struct tls_vars *mytls_vars,
				   uint8_t *eappacket)
{
  uint8_t *cur = NULL;
  uint32_t resp_size, packet_size;
  struct eap_header *eaphdr;
  int err = 0;
  uint8_t temp;

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

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

  // Assume we aren't going to send an ACK, until we actually decide we are.
  mytls_vars->send_ack = FALSE;

  eaphdr = (struct eap_header *)eappacket;
  packet_size = ntohs(eaphdr->eap_length);

  // First, process the byte that follows the EAP header.
  cur = (uint8_t *)&eappacket[sizeof(struct eap_header)];
  packet_size -= sizeof(struct eap_header);

  temp = cur[0];

  if ((temp == EAPTLS_ACK) && (packet_size <= (sizeof(struct eap_header)+1)))
    {
      debug_printf(DEBUG_TLS_CORE, "Got an ACK. (Packet size = %d)\n",
                   packet_size);
      return CONT;
    }

  cur++;
  packet_size--;

  if (temp & EAPTLS_LENGTH_INCL)
    {
      // Grab out the total size of the response.
      memcpy(&resp_size, cur, sizeof(uint32_t));
      resp_size = ntohl(resp_size);
      debug_printf(DEBUG_TLS_CORE, "Expecting %d byte(s) worth of response."
		   "\n", resp_size);
      mytls_vars->tlsinsize = resp_size;
      packet_size -= 4;
      cur += 4;
    }

  debug_printf(DEBUG_TLS_CORE, "Copying (%d) : \n", packet_size);
  debug_hex_dump(DEBUG_TLS_CORE, cur, packet_size);

  // If there are more fragments coming, our response should be an ACK.
  if (temp & EAPTLS_MORE_FRAGS) mytls_vars->send_ack = TRUE;

  mytls_vars->tlsindata = realloc(mytls_vars->tlsindata, 
				  (mytls_vars->tlsinptr + packet_size));

  if (mytls_vars->tlsindata == NULL)
    {
      debug_printf(DEBUG_NORMAL, "There was an error getting enough memory "
		   "to hold the packet fragment.\n");
      return EAP_FAIL;
    }

  memcpy((uint8_t *)&mytls_vars->tlsindata[mytls_vars->tlsinptr],
	 cur, packet_size);

  debug_printf(DEBUG_TLS_CORE, "Copied %d byte(s) to our buffer.\n",
	       packet_size);

  mytls_vars->tlsinptr += packet_size;

  if (mytls_vars->send_ack == FALSE)
    {
      if (mytls_vars->tlsinptr != mytls_vars->tlsinsize)
	{
	  debug_printf(DEBUG_NORMAL, "The data we got was not the same size "
		       "as the data we were expecting! (Current offset %d, "
		       "expected offset %d.)\n", mytls_vars->tlsinptr,
		       mytls_vars->tlsinsize);

	  // We should have already freed our buffer before now, so just
	  // clear these values.
	  mytls_vars->tlsinptr = 0;
	  mytls_vars->tlsinsize = 0;
	  return XEGENERROR;
	}

      mytls_vars->tlsinptr = 0;

      err = gnutls_handshake(mytls_vars->session);
      
      if ((err != 0) && (err != GNUTLS_E_AGAIN))
	{
	  debug_printf(DEBUG_NORMAL, "Couldn't continue handshake!  Error was "
		       "(%d): %s\n", err, gnutls_strerror(err));
	  return XEGENERROR;
	}

      if (err == 0)
	{
	  // The handshake is complete.
	  mytls_vars->handshake_done = TRUE;

	  if (mytls_vars->verify_cert == TRUE)
	    {
	      if (verify_certificate(mytls_vars->session, mytls_vars->cncheck, 
				     mytls_vars->cnexact) != XENONE)
		{
		  return XEGENERROR;
		}
	    }
	}
    }

  return XENONE;
}

/**************************************************************************
*
* This function processes the packets, and decides if it is a start, or
* another type of packet.  It then calls the appropriate handler function.
*
***************************************************************************/
uint8_t tls_funcs_process(struct tls_vars *mytls_vars, uint8_t *eappacket)
{
  if (eappacket[sizeof(struct eap_header)] == EAPTLS_START)
    {
      gnutls_funcs_do_start(mytls_vars);
      return CONT;
    }
  else

⌨️ 快捷键说明

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