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

📄 tls.c

📁 RADIUS 服务器介绍 RADIUS服务器支持标准的RADIUS协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * tls.c  * * Version:     $Id: tls.c,v 1.7 2003/07/04 20:10:08 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com> */#include "eap_tls.h"/* * TODO: Check for the type of key exchange *  like conf->dh_key */int load_dh_params(SSL_CTX *ctx, char *file){	DH *dh = NULL;	BIO *bio;	if ((bio = BIO_new_file(file, "r")) == NULL) {		radlog(L_ERR, "rlm_eap_tls: Unable to open DH file - %s", file);		return -1;	}	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);	BIO_free(bio);	if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) {		radlog(L_ERR, "rlm_eap_tls: Unable to set DH parameters");		DH_free(dh);		return -1;	}	DH_free(dh);	return 0;}int generate_eph_rsa_key(SSL_CTX *ctx){	RSA *rsa;	rsa = RSA_generate_key(512, RSA_F4, NULL, NULL);	if (!SSL_CTX_set_tmp_rsa(ctx, rsa)) {		radlog(L_ERR, "rlm_eap_tls: Couldn't set RSA key");		return -1;	}	RSA_free(rsa);	return 0;}/* * Create Global context SSL and use it in every new session * # Load the trusted CAs * # Load the Private key & the certificate * # Set the Context options & Verify options */SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf){	SSL_METHOD *meth;	SSL_CTX *ctx;	int verify_mode = 0;	int ctx_options = 0;	int type;	/*	 * Add all the default ciphers and message digests	 * Create our context	 */	SSL_library_init();	SSL_load_error_strings();	meth = TLSv1_method();	ctx = SSL_CTX_new(meth);	/*	 * Identify the type of certificates that needs to be loaded	 */	if (conf->file_type) {		type = SSL_FILETYPE_PEM;	} else {		type = SSL_FILETYPE_ASN1;	}	/* Load the CAs we trust */	if (!(SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) ||			(!SSL_CTX_set_default_verify_paths(ctx))) {		ERR_print_errors_fp(stderr);		radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list");		return NULL;	}	SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(conf->ca_file));	/* 	 * Set the password to load private key	 */	if (conf->private_key_password) {		SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->private_key_password);		SSL_CTX_set_default_passwd_cb(ctx, cbtls_password);	}	/* Load our keys and certificates*/	if (!(SSL_CTX_use_certificate_file(ctx, conf->certificate_file, type))) {		ERR_print_errors_fp(stderr);		radlog(L_ERR, "rlm_eap_tls: Error reading certificate file");		return NULL;	}	if (!(SSL_CTX_use_PrivateKey_file(ctx, conf->private_key_file, type))) {		ERR_print_errors_fp(stderr);		radlog(L_ERR, "rlm_eap_tls: Error reading private key file");		return NULL;	}	/*	 * Check if the loaded private key is the right one	 */	if (!SSL_CTX_check_private_key(ctx)) {		radlog(L_ERR, "rlm_eap_tls: Private key does not match the certificate public key");		return NULL;	}	/*	 * Set ctx_options	 */	ctx_options |= SSL_OP_NO_SSLv2;   	ctx_options |= SSL_OP_NO_SSLv3;	/*        SSL_OP_SINGLE_DH_USE must be used in order to prevent 	   small subgroup attacks and forward secrecy. Always using       SSL_OP_SINGLE_DH_USE has an impact on the computer time       needed during negotiation, but it is not very large.	 */   	ctx_options |= SSL_OP_SINGLE_DH_USE;	SSL_CTX_set_options(ctx, ctx_options);	/*	 * TODO: Set the RSA & DH	SSL_CTX_set_tmp_rsa_callback(ctx, cbtls_rsa);	SSL_CTX_set_tmp_dh_callback(ctx, cbtls_dh);	 */	/*	 * set the message callback to identify the type of message.	 * For every new session, there can be a different callback argument	SSL_CTX_set_msg_callback(ctx, cbtls_msg);	 */	/* Set Info callback */	SSL_CTX_set_info_callback(ctx, cbtls_info);	/*	 * Set verify modes	 * Always verify the peer certificate	 */	verify_mode |= SSL_VERIFY_PEER;	verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;	verify_mode |= SSL_VERIFY_CLIENT_ONCE;	SSL_CTX_set_verify(ctx, verify_mode, cbtls_verify);	if (conf->verify_depth) {		SSL_CTX_set_verify_depth(ctx, conf->verify_depth);	}	/* Load randomness */	if (!(RAND_load_file(conf->random_file, 1024*1024))) {		ERR_print_errors_fp(stderr);		radlog(L_ERR, "rlm_eap_tls: Error loading randomness");		return NULL;	}	return ctx;}tls_session_t *new_tls_session(eap_tls_t *eaptls){	tls_session_t *state = NULL;	SSL *new_tls = NULL;	int verify_mode = 0;	if ((new_tls = SSL_new(eaptls->ctx)) == NULL) {		radlog(L_ERR, "rlm_eap_tls: Error creating new SSL");		ERR_print_errors_fp(stderr);		return NULL;	}	/* We use the SSL's "app_data" to indicate a call-back */	SSL_set_app_data(new_tls, NULL);	state = (tls_session_t *)malloc(sizeof(tls_session_t));	session_init(state);	state->ssl = new_tls;	/*	 * Create & hook the BIOs to handle the dirty side of the SSL	 * This is *very important* as we want to handle the transmission part.	 * Now the only IO interface that SSL is aware of, is our defined BIO buffers.	 */	state->into_ssl = BIO_new(BIO_s_mem());	state->from_ssl = BIO_new(BIO_s_mem());	SSL_set_bio(state->ssl, state->into_ssl, state->from_ssl);	/*	 * Add the message callback to identify	 * what type of message/handshake is passed	 */	SSL_set_msg_callback(new_tls, cbtls_msg);	SSL_set_msg_callback_arg(new_tls, state);	SSL_set_info_callback(new_tls, cbtls_info);	/* Always verify the peer certificate */	verify_mode |= SSL_VERIFY_PEER;	verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;	verify_mode |= SSL_VERIFY_CLIENT_ONCE;	SSL_set_verify(state->ssl, verify_mode, cbtls_verify);		/* In Server mode we only accept.  */	SSL_set_accept_state(state->ssl);	return state;}static void int_ssl_check(SSL *s, int ret){	int e;	ERR_print_errors_fp(stderr);	e = SSL_get_error(s, ret);	radlog(L_ERR, " Error code is ..... %d\n", e);	switch(e) {		/* These seem to be harmless and already "dealt with" by our		 * non-blocking environment. NB: "ZERO_RETURN" is the clean		 * "error" indicating a successfully closed SSL tunnel. We let		 * this happen because our IO loop should not appear to have		 * broken on this condition - and outside the IO loop, the		 * "shutdown" state is checked. */	case SSL_ERROR_NONE:	case SSL_ERROR_WANT_READ:	case SSL_ERROR_WANT_WRITE:	case SSL_ERROR_WANT_X509_LOOKUP:	case SSL_ERROR_ZERO_RETURN:		radlog(L_ERR, " SSL Error ..... %d\n", e);		return;		/* These seem to be indications of a genuine error that should		 * result in the SSL tunnel being regarded as "dead". */	case SSL_ERROR_SYSCALL:	case SSL_ERROR_SSL:		radlog(L_ERR, " Error in SSL ..... %d\n", e);		SSL_set_app_data(s, (char *)1);		return;	default:		break;	}	radlog(L_ERR, "Unknown Error ..... %d\n", e);	/* For any other errors that (a) exist, and (b) crop up - we need to	 * interpret what to do with them - so "politely inform" the caller that	 * the code needs updating here. */	abort();}/* * We are the server, we always get the dirty data * (Handshake data is also considered as dirty data) * During handshake, since SSL API handles itself, * After clean-up, dirty_out will be filled with  * the data required for handshaking. So we check * if dirty_out is empty then we simply send it back. * As of now, if handshake is successful, then it is EAP-Success * or else EAP-failure should be sent * * Fill the Bio with the dirty data to clean it  * Get the cleaned data from SSL, if it is not Handshake data */int tls_handshake_recv(tls_session_t *ssn){	int err;	BIO_write(ssn->into_ssl, ssn->dirty_in.data, ssn->dirty_in.used);	err = SSL_read(ssn->ssl, ssn->clean_out.data, MAX_RECORD_SIZE);	if (err > 0) {		ssn->clean_out.used = err;	} else {		radlog(L_INFO, "rlm_eap_tls: SSL_read Error");		int_ssl_check(ssn->ssl, err);	}	/* Some Extra STATE information for easy debugging */	/*	if (SSL_is_init_finished(ssn->ssl)) {		printf("SSL Connection Established\n");	}   	if (SSL_in_init(ssn->ssl)) {		printf("In SSL Handshake Phase\n");	}   	if (SSL_in_before(ssn->ssl)) {		printf("Before SSL Handshake Phase\n");	}   	if (SSL_in_accept_init(ssn->ssl)) {		printf("In SSL Accept mode \n");	}   	if (SSL_in_connect_init(ssn->ssl)) {

⌨️ 快捷键说明

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