📄 ossl_tls_funcs.c
字号:
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 + -