📄 tls_funcs.c
字号:
/******************************************************************* * EAPTLS (RFC 2716) Function implementations * * Licensed under a dual GPL/BSD license. (See LICENSE file for more info.) * * File: tls_funcs.c * * Authors: Chris.Hessing@utah.edu * * $Id: tls_funcs.c,v 1.58 2006/06/09 23:25:44 chessing Exp $ * $Date: 2006/06/09 23:25:44 $ * $Log: tls_funcs.c,v $ * Revision 1.58 2006/06/09 23:25:44 chessing * More GUI work. * * Revision 1.57 2006/06/05 23:27:36 chessing * Fixed a couple bugs introduced in the TTLS-EAP-MD5 code. Cleaned up some other bugs introduced in this morning's commit. * * Revision 1.56 2006/06/05 19:56:43 chessing * Fixed a 16k memory leak in the config parse code. Cleaned up some of the TLS code. * * Revision 1.55 2006/06/05 01:40:41 chessing * Various small cleanups. * * Revision 1.54 2006/06/02 21:49:18 chessing * More memory leak cleanups, and another patch from Carsten. * * Revision 1.53 2006/06/01 22:49:50 galimorerpg * Converted all instances of u_char to uint8_t * Fixed a bad #include in the generic frame handler. * * Revision 1.52 2006/06/01 04:03:04 chessing * Fixed a problem where we would segfault on a reauth. (We probably need to get this fixed up a bit and release 1.2.6 quickly as a bug fix release.) Added support for TTLS-EAP-MD5 * * Revision 1.51 2006/05/29 04:17:58 chessing * Fixes for some memory leaks. * * Revision 1.50 2006/05/13 03:44:46 chessing * Huge patch as a result of the downtime with SourceForge. Fixed issues with WPA/WPA2. Fixed a segfault when a scan returned a NULL. Changed event handleing to use select() instead of older sleep/non-blocking socket resulting in a faster authentication. Fixed a stack smashing bug that would cause random failures with WPA/WPA2. Added status messages so that when we run in non-debug mode we have some idea of what is going on. Various other code cleanups, bug fixes. * * Revision 1.48 2006/04/25 01:17:44 chessing * LOTS of code cleanups, new error checking/debugging code added, and other misc. fixes/changes. * * Revision 1.47 2006/03/28 21:16:07 chessing * Fixes to EAP-AKA, and PEAP. PEAP now handles inner success messages, and works with Funk SBR. * * Revision 1.46 2005/11/18 19:14:47 chessing * Fixes to the OpenSSL detection settings in the autoconf file. Added some checks for SHA changes in OpenSSL 0.9.8 * * Revision 1.45 2005/11/12 23:59:52 chessing * Some typo/debug patches from Pekka Savola. * * Revision 1.44 2005/10/17 03:56:54 chessing * Updates to the libxsupconfig library. It no longer relies on other source from the main tree, so it can be used safely in other code with problems. * * Revision 1.43 2005/10/14 02:26:18 shaftoe * - cleanup gcc 4 warnings * - (re)add support for a pid in the form of /var/run/xsupplicant.<iface>.pid * * -- Eric Evans <eevans@sym-link.com> * * Revision 1.42 2005/09/14 03:34:54 chessing * Small cosmetic changes. Default association mode is now auto instead of manual. Fixes for bug IDs #1290449 & #1290323. * * Revision 1.41 2005/09/08 16:27:02 chessing * Some small updates to the new state machine code. First attempt at an auto association mode. (It mostly works. ;) * * Revision 1.40 2005/09/05 01:00:37 chessing * Major overhaul to most of the state machines in Xsupplicant. Also added additional error messages to the TLS functions to try to debug the one of the problems reported on the list. Basic testing shows this new code to be more stable than previous code, but it needs more testing. * * Revision 1.39 2005/08/12 03:34:06 chessing * Fix to the TLS implementation, should help avoid some of the weird 'block cipher pad' errors. Also includes a partial implementation of the ability to use static WEP keys based on the SSID in use. * * Revision 1.38 2005/08/09 01:39:18 chessing * Cleaned out old commit notes from the released version. Added a few small features including the ability to disable the friendly warnings that are spit out. (Such as the warning that is displayed when keys aren't rotated after 10 minutes.) We should also be able to start when the interface is down. Last, but not least, we can handle empty network configs. (This may be useful for situations where there isn't a good reason to have a default network defined.) * * *******************************************************************/#include <openssl/ssl.h>#include <openssl/engine.h>#include <openssl/ui.h>#include <openssl/err.h>#include <openssl/rand.h>#include <openssl/hmac.h>#include <openssl/md5.h>#include <netinet/in.h>#include <string.h>#include <inttypes.h>#include <unistd.h>#include "xsupconfig.h"#include "profile.h"#include "eap.h"#include "tls_funcs.h"#include "tls_crypt.h"#include "xsup_debug.h"#include "xsup_err.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#endifint engine_load_dynamic_opensc(struct smartcard *sc);void set_smartcard_pin(char *pin);UI_METHOD *UI_noninteractive(void);char *get_cert_common_name(SSL *ssl_ctx){ char *commonName = NULL; X509 *server_cert; 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"); 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_AUTHTYPES, "Extracted common name of %s\n",commonName); return commonName;}void tls_funcs_process_error(){ unsigned long err; 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)); }}static int ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx){ char buf[256]; X509 *err_cert; int err, depth; 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_AUTHTYPES, " --- SSL_verify : depth %d\n", depth); if (!preverify_ok) { debug_printf(DEBUG_AUTHTYPES, " --- SSL_verify error : num=%d:%s:depth=%d:%s\n", err, X509_verify_cert_error_string(err), depth, buf); if (err == 26) preverify_ok = 1; } return preverify_ok;}int tls_funcs_init(struct generic_eap_data *thisint){ struct tls_vars *mytls_vars; struct config_eap_tls *userdata; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XETLSINIT; if (!xsup_assert((thisint->eap_data != NULL), "thisint->eap_data != NULL", FALSE)) return XETLSINIT; if (!xsup_assert((thisint->eap_conf_data != NULL), "thisint->eap_conf_data != NULL", FALSE)) return XETLSINIT; mytls_vars = (struct tls_vars *)thisint->eap_data; userdata = (struct config_eap_tls *)thisint->eap_conf_data; if (mytls_vars->ctx != NULL) { SSL_CTX_free(mytls_vars->ctx); mytls_vars->ctx = NULL; debug_printf(DEBUG_NORMAL, "mytls_vars->ctx != NULL!!!\n"); } 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(); return XETLSINIT; } // XXX Clean up this code. if (thisint->eapNum == EAP_TYPE_TLS) { if ( userdata->sc.engine_id != NULL ) { if(!engine_load_dynamic_opensc(&userdata->sc)) { debug_printf(DEBUG_NORMAL, "OpenSC Engine will be unavailable!\n"); } debug_printf(DEBUG_NORMAL, "Using Engine with ID \"%s\"\n", userdata->sc.engine_id); mytls_vars->engine = ENGINE_by_id(userdata->sc.engine_id); if (!mytls_vars->engine) { debug_printf(DEBUG_NORMAL, "Engine not available!\n"); /* This error will be unrecoverable - XSupplicant should die */ 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;}int tls_funcs_build_new_session(struct tls_vars *mytls_vars){ if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE)) return XEMALLOC; if (mytls_vars->ssl) { SSL_free(mytls_vars->ssl); mytls_vars->ssl = NULL; } 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;} int tls_funcs_start(struct tls_vars *mytls_vars){ SSL_SESSION *sess = NULL; unsigned long err; int counter, resval = XENONE; if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE)) return XEMALLOC; mytls_vars->resuming = 0; if (!mytls_vars->ssl) { 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_AUTHTYPES, "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_AUTHTYPES, "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) { sleep(1); 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(); return XETLSSTARTFAIL; } if (BIO_reset(mytls_vars->ssl_in) < 1) { printf("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(); return XETLSSTARTFAIL; } if (BIO_reset(mytls_vars->ssl_out) < 0) { printf("Error : %s:%d\n", __FUNCTION__, __LINE__); tls_funcs_process_error(); } SSL_set_bio(mytls_vars->ssl, mytls_vars->ssl_in, mytls_vars->ssl_out); if (sess != NULL) { // If we have session information, we need to use it to resume the // session. debug_printf(DEBUG_AUTHTYPES, "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(); } } // Set this to SSL_VERIFY_NONE if we don't want to do anything with a failed // verification. SSL_set_verify(mytls_vars->ssl, mytls_vars->verify_mode, ssl_verify_callback); return XENONE;}int tls_funcs_parse(struct generic_eap_data *thisint, uint8_t *indata, int insize, char *outdata, int *outsize, int chunksize){ int rc; BUF_MEM *retData; struct tls_vars *mytls_vars; char *retVal; uint32_t length; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; // indata can be NULL (at the start of a TLS conversation. if (!xsup_assert((outdata != NULL), "outdata != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((outsize != NULL), "outsize != NULL", FALSE)) return XEMALLOC; if (insize > 1520) { debug_printf(DEBUG_NORMAL, "Packet passed in to tls_funcs_parse() is too big! Ignoring!\n"); return XEBADPACKETSIZE; } if ((chunksize == 0) || (chunksize > 1398)) { chunksize = 1398; } if (thisint->eap_data == NULL) { debug_printf(DEBUG_NORMAL, "(TLS) eap_data has been destroyed, or not " "allocated!\n"); return XEMALLOC; } mytls_vars = (struct tls_vars *)thisint->eap_data; if (!mytls_vars) { debug_printf(DEBUG_NORMAL, "mytls_vars == NULL!\n"); return XEMALLOC; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -