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

📄 ossl_tls_funcs.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 4 页
字号:
      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));
	}

      tls_funcs_process_error();
      return XEGENERROR;
    }

  tempdata = Malloc(1500);
  if (tempdata == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store return "
		   "TLS data!\n");
	  ipc_events_malloc_failed(NULL);
      return XEMALLOC;
    }

  ressize = BIO_read(mytls_vars->ssl_out, 
				     tempdata, 1500);
  if (ressize <= 0)
  {
#if 0
	  if (BIO_should_retry(mytls_vars->ssl_out) == TRUE)
	  {
		  printf("Should retry.\n");
	  }
	  else
	  {
		  printf("********************************************************Failure! (%d)\n", ressize);
	  }
#endif
    FREE(tempdata);
	return XEGENERROR;
  }

  // If a queue already exists, destroy it.
  if (NULL != mytls_vars->tlsoutqueue) queue_destroy(&mytls_vars->tlsoutqueue);
  if (NULL != mytls_vars->tlsinqueue) queue_destroy(&mytls_vars->tlsinqueue);

  // Make sure our queue is ready to accept the data.
  if (NULL == mytls_vars->tlsoutqueue)
  {
	  debug_printf(DEBUG_TLS_CORE, "Creating a new queue!\n");
	  if (queue_create(&mytls_vars->tlsoutqueue) < 0)
	  {
		  debug_printf(DEBUG_NORMAL, "Couldn't create data queue for response data!\n");
		  FREE(tempdata);
		  return XEGENERROR;
	  }
  }

  if (queue_enqueue(&mytls_vars->tlsoutqueue, tempdata, ressize) < 0)
  {
	  debug_printf(DEBUG_NORMAL, "Couldn't enqueue response data!  Destroying queue.\n");
	  if (queue_destroy(&mytls_vars->tlsoutqueue) < 0)
	  {
		  debug_printf(DEBUG_NORMAL, "Couldn't destroy queue!  This is *REALLY* bad!\n");
		  FREE(tempdata);
		  return XEGENERROR;
	  }
  }

  FREE(tempdata);

  BIO_reset(mytls_vars->ssl_out);
  BIO_reset(mytls_vars->ssl_in);

  return XENONE;
}

/**************************************************************************
 *
 * Process packets that aren't start packets.
 *
 **************************************************************************/
uint8_t ossl_funcs_process_other(struct tls_vars *mytls_vars,
				 uint8_t *eappacket)
{
  uint8_t *cur = NULL;
  uint8_t *tempdata = NULL;
  uint32_t resp_size = 0, packet_size = 0;
  struct eap_header *eaphdr = NULL;
  int err = 0;
  uint8_t temp = 0;
  uint16_t size = 0;
  uint16_t insize = 0;
  char error_str[256];
  context *ctx = NULL;

  TRACE

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

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

  if (mytls_vars->ssl == NULL) 
  {
	  debug_printf(DEBUG_NORMAL, "The server sent a mid-conversation message when we expected a start.  If this is a wireless connection, it is likely that the wireless card hopped to a new AP in the middle of a conversation.\n");
	  ctx = event_core_get_active_ctx();
	  if (ctx != NULL) statemachine_reinit(ctx);
	  return DONE;
  }

  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->expected_in = resp_size;
      packet_size -= 4;
      cur += 4;
    }

  if (temp == 0x00)
  {
	  // We got a TLS message that doesn't contain a length value.  So, it is probably
	  // all inclusive.
	  if (mytls_vars->expected_in == 0)
	  {
		  // Yup.  It is.
		  mytls_vars->expected_in = packet_size;
		  debug_printf(DEBUG_TLS_CORE, "Expecting a total of %d byte(s). (Single packet message)\n", mytls_vars->expected_in);
	  }
  }

  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->in_so_far += packet_size;
  
  if (BIO_write(mytls_vars->ssl_in, cur, packet_size) < 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't BIO_write!\n");
      return DONE;
    }

  if (mytls_vars->send_ack == FALSE)
    {
      if (mytls_vars->in_so_far != mytls_vars->expected_in)
        {
          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->in_so_far,
                       mytls_vars->expected_in);

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

      debug_printf(DEBUG_TLS_CORE, "Writing %d byte(s) of data to OpenSSL:\n",
		   mytls_vars->expected_in);

	  mytls_vars->in_so_far = 0;
	  mytls_vars->expected_in =0;

      err = SSL_connect(mytls_vars->ssl);

      if (err != 1) 
        {
			err = ERR_get_error();
			if (err != 0)
			{
				sprintf(error_str, "Authentication handshake failed.  Reason : %s", ERR_reason_error_string(err));
				debug_printf(DEBUG_NORMAL, "%s\n", error_str);
				ipc_events_error(NULL, IPC_EVENT_ERROR_TEXT, error_str);

				tls_funcs_deinit(mytls_vars);

				return DONE;
			}
        }

      size = BIO_ctrl_pending(mytls_vars->ssl_out);

	  if (size > 0)
	  {
		tempdata = Malloc(size);
		if (tempdata == NULL)
		{
		  debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store OpenSSL's response data!\n");
		  return DONE;
		}

		err = BIO_read(mytls_vars->ssl_out, 
			 tempdata, size);
		if (err > 0)
			{
				if (mytls_vars->tlsoutqueue == NULL)
				{
					if (queue_create(&mytls_vars->tlsoutqueue) < 0)
					{
						debug_printf(DEBUG_NORMAL, "Couldn't create queue data for OpenSSL's TLS response data!\n");
						FREE(tempdata);
						return DONE;
					}
				}

				if (queue_enqueue(&mytls_vars->tlsoutqueue, tempdata, size) < 0)
				{
					debug_printf(DEBUG_NORMAL, "Couldn't enqueue OpenSSL's TLS response data!\n");
					FREE(tempdata);
					return DONE;
				}
			}
			else
			{
				debug_printf(DEBUG_NORMAL, "The BIO claimed there was data "
					"available, but it got an error returning it to "
					"us!\n");
			}
		FREE(tempdata);
	  }
	}
#if 0
      else
	{
	  if (size == 0)
	    {

	      debug_printf(DEBUG_TLS_CORE, "Nothing to return, ACKing!\n");
		}
    }
#endif

  if (SSL_get_state(mytls_vars->ssl) == 0x0003)
    {
	  if (tls_funcs_cn_check(mytls_vars) != XENONE)
	    {
	      debug_printf(DEBUG_NORMAL, "Failed certificate common name "
			   "check!\n");
		  queue_destroy(&mytls_vars->tlsinqueue);
		  queue_destroy(&mytls_vars->tlsoutqueue);
	      return DONE;
	    }
	  else
	  {
        mytls_vars->handshake_done = TRUE;
	  }
    }

  return MAY_CONT;
}

/**************************************************************************
 *
 * 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)
{
  TRACE

  if (eappacket[sizeof(struct eap_header)] == EAPTLS_START)
    {
      if (ossl_funcs_do_start(mytls_vars) == 0)
	  {
		return CONT;
	  }
	  else
	  {
		  return EAP_FAIL;
	  }
    }
  else
    {
      return ossl_funcs_process_other(mytls_vars, eappacket);
    }
}

/**************************************************************************
 *
 *  This function pulls data out of the queue that needs to be sent to the
 *  authentication server.
 *
 ***************************************************************************/
int tls_funcs_get_packet(struct tls_vars *mytls_vars, int maxsize,
			 uint8_t **result, uint16_t *res_size)
{
  uint8_t *retdata = NULL;
  uint8_t *dequeue_data = NULL;
  uint8_t *dataptr = NULL;
  uint32_t retlen = 0;
  uint32_t cpysize = 0;
  uint32_t queuesize = 0;
  int more = 0;
  int athead = 0;

  TRACE

  if ((mytls_vars->tlsoutqueue == NULL) && (mytls_vars->send_ack == TRUE))
    {
      retdata = Malloc(1);
      if (retdata == NULL)
        {
          debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for return "
                       "buffer!\n");
		  ipc_events_malloc_failed(NULL);
          return XEMALLOC;
        }

      debug_printf(DEBUG_TLS_CORE, "Sending ACK!\n");
      retdata[0] = EAPTLS_ACK;
      *res_size = 1;
      (*result) = retdata;

      return XENONE;
    }

	  if (queue_get_size(&mytls_vars->tlsoutqueue, &queuesize) < 0)
	  {
		  if (mytls_vars->tlsoutqueue != NULL) debug_printf(DEBUG_NORMAL, "Error getting queue depth!\n");
		  return XEGENERROR;
	  }

	  athead = queue_at_head(&mytls_vars->tlsoutqueue);

  if (queuesize == 0)
    {
      debug_printf(DEBUG_TLS_CORE, "No data left to send.\n");
      (*result) = NULL;
      *res_size = 0;
      return XENONE;
    }

	  (*res_size) = maxsize - 6;  // Leave room in case we need to slap a length header on.

	  more = queue_dequeue(&mytls_vars->tlsoutqueue, &dequeue_data, (uint32_t *)res_size);

  	  if (more < 0) 
	  {
		  debug_printf(DEBUG_NORMAL, "Couldn't get more fragments to send to authenticator.\n");
		  return XEGENERROR;  
	  }

	  // If we are at the head of the list, we need to send a length.
	  if ((athead == TRUE) && (more == TRUE))
	  {
		retdata = Malloc((*res_size) + 5);
		if (retdata == NULL) return XEMALLOC;

		dataptr = (uint8_t *)&retdata[5];
		retdata[0] = EAPTLS_LENGTH_INCL;  // Length is included in this message.
		cpysize = (*res_size);
		retlen = htonl(queuesize);
		memcpy(&retdata[1], &retlen, sizeof(uint32_t));
		(*res_size)+=5;
	  }
	  else
	  {
		  retdata = Malloc((*res_size)+1);
		  if (retdata == NULL) return XEMALLOC;

		  cpysize = (*res_size);
		  dataptr = (uint8_t *)&retdata[1];
		  (*res_size)++;
	  }

	  // If more == TRUE then we have more fragments, and need to include that indication
	  if (more == TRUE) 
	  {
		  retdata[0] |= EAPTLS_MORE_FRAGS;
	  }
	  else
	  {
		  retdata[0] |= EAPTLS_FINAL;
	  }

	  memcpy(dataptr, dequeue_data, cpysize);

	  FREE(dequeue_data);

	  if (queue_queue_done(&mytls_vars->tlsoutqueue) != 0)
	  {
		  debug_printf(DEBUG_TLS_CORE, "Finished with queue... Freeing.\n");
		  if (queue_destroy(&mytls_vars->tlsoutqueue) != 0)
		  {
			  debug_printf(DEBUG_NORMAL, "Couldn't destroy queue data!  (We will probably leak memory.)\n");
		  }
	  }

	  debug_printf(DEBUG_TLS_CORE, "TLS Returns (%d bytes) :\n", (*res_size));
	  debug_hex_dump(DEBUG_TLS_CORE, retdata, (*res_size));

	  (*result) = retdata;

	  return XENONE;
}

/***********************************************************************
 *
 *  Check the CN field of a certificate against what the user has requested
 *  that we test with.
 *
 ***********************************************************************/
int tls_funcs_cn_check(struct tls_vars *mytls_vars)
{
  char *cnname = NULL;
  char *temp = NULL;

  TRACE

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

  if (mytls_vars->cncheck != NULL)
    {
      cnname = get_cert_common_name(mytls_vars->ssl);

      debug_printf(DEBUG_TLS_CORE, "Certificate CN : %s\n",cnname);

      // mytls_vars->cncheck == NULL, do nothing.
      debug_printf(DEBUG_TLS_CORE, "Doing a CN Check!\n");

      if (mytls_vars->cnexact == 1)
	{
	  debug_printf(DEBUG_TLS_CORE, "Looking for an exact match!\n");

	  if (cnname != NULL)
	    {
	      if (strcmp(mytls_vars->cncheck, cnname) != 0)
		{
		  debug_printf(DEBUG_NORMAL, "Certificate CN didn't "
			  "match!  (Server : %s    Us : %s)\n", cnname, mytls_vars->cncheck);
		  FREE(cnname);
		  return XEBADCN;
		} else {
		  debug_printf(DEBUG_TLS_CORE, "Certificate CN matched!\n");
		}
	    }
	} else {
	  debug_printf(DEBUG_TLS_CORE, "Looking for a relative match!\n");

	  temp = mytls_vars->cncheck;
	  if (cnname != NULL)
	    {
	      if (strstr(cnname, temp) == NULL)
		{
		  debug_printf(DEBUG_NORMAL, "Certificate CN didn't "
			  "match!   (Server : %s    Us : %s)\n", cnname, temp);
		  FREE(cnname);
		  return XEBADCN;
		} else {
		  debug_printf(DEBUG_TLS_CORE, "Certificate CN matched!\n");
		}
	    }
	}
    }

  FREE(cnname);

  return XENONE;
}

/**********************************************************************
 *
 *  Provide some form of error messages from OpenSSL back to the user.
 *
 **********************************************************************/
static void ssl_info_callback(SSL *ssl, int w, int r)
{
  TRACE

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

  debug_printf(DEBUG_TLS_CORE, "     --- SSL : %s\n", SSL_state_string_long(ssl));
  if (w & SSL_CB_ALERT)
    debug_printf(DEBUG_TLS_CORE, "     --- ALERT : %s\n", SSL_alert_desc_string_long(r));

⌨️ 快捷键说明

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