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

📄 tls_openssl.c

📁 IEEE 802.11a/b/g 服务器端AP
💻 C
📖 第 1 页 / 共 5 页
字号:
	const char *str;	int w;	wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret);	w = where & ~SSL_ST_MASK;	if (w & SSL_ST_CONNECT)		str = "SSL_connect";	else if (w & SSL_ST_ACCEPT)		str = "SSL_accept";	else		str = "undefined";	if (where & SSL_CB_LOOP) {		wpa_printf(MSG_DEBUG, "SSL: %s:%s",			   str, SSL_state_string_long(ssl));	} else if (where & SSL_CB_ALERT) {		wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",			   where & SSL_CB_READ ?			   "read (remote end reported an error)" :			   "write (local SSL3 detected an error)",			   SSL_alert_type_string_long(ret),			   SSL_alert_desc_string_long(ret));		if ((ret >> 8) == SSL3_AL_FATAL) {			struct tls_connection *conn =				SSL_get_app_data((SSL *) ssl);			if (where & SSL_CB_READ)				conn->read_alerts++;			else				conn->write_alerts++;		}	} else if (where & SSL_CB_EXIT && ret <= 0) {		wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",			   str, ret == 0 ? "failed" : "error",			   SSL_state_string_long(ssl));	}}#ifndef OPENSSL_NO_ENGINE/** * tls_engine_load_dynamic_generic - load any openssl engine * @pre: an array of commands and values that load an engine initialized *       in the engine specific function * @post: an array of commands and values that initialize an already loaded *        engine (or %NULL if not required) * @id: the engine id of the engine to load (only required if post is not %NULL * * This function is a generic function that loads any openssl engine. * * Returns: 0 on success, -1 on failure */static int tls_engine_load_dynamic_generic(const char *pre[],					   const char *post[], const char *id){	ENGINE *engine;	const char *dynamic_id = "dynamic";	engine = ENGINE_by_id(id);	if (engine) {		ENGINE_free(engine);		wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "			   "available", id);		return 0;	}	ERR_clear_error();	engine = ENGINE_by_id(dynamic_id);	if (engine == NULL) {		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",			   dynamic_id,			   ERR_error_string(ERR_get_error(), NULL));		return -1;	}	/* Perform the pre commands. This will load the engine. */	while (pre && pre[0]) {		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]);		if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) {			wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: "				   "%s %s [%s]", pre[0], pre[1],				   ERR_error_string(ERR_get_error(), NULL));			ENGINE_free(engine);			return -1;		}		pre += 2;	}	/*	 * Free the reference to the "dynamic" engine. The loaded engine can	 * now be looked up using ENGINE_by_id().	 */	ENGINE_free(engine);	engine = ENGINE_by_id(id);	if (engine == NULL) {		wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",			   id, ERR_error_string(ERR_get_error(), NULL));		return -1;	}	while (post && post[0]) {		wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);		if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {			wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:"				" %s %s [%s]", post[0], post[1],				   ERR_error_string(ERR_get_error(), NULL));			ENGINE_remove(engine);			ENGINE_free(engine);			return -1;		}		post += 2;	}	ENGINE_free(engine);	return 0;}/** * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc * @pkcs11_so_path: pksc11_so_path from the configuration * @pcks11_module_path: pkcs11_module_path from the configuration */static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,					  const char *pkcs11_module_path){	char *engine_id = "pkcs11";	const char *pre_cmd[] = {		"SO_PATH", NULL /* pkcs11_so_path */,		"ID", NULL /* engine_id */,		"LIST_ADD", "1",		/* "NO_VCHECK", "1", */		"LOAD", NULL,		NULL, NULL	};	const char *post_cmd[] = {		"MODULE_PATH", NULL /* pkcs11_module_path */,		NULL, NULL	};	if (!pkcs11_so_path || !pkcs11_module_path)		return 0;	pre_cmd[1] = pkcs11_so_path;	pre_cmd[3] = engine_id;	post_cmd[1] = pkcs11_module_path;	wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",		   pkcs11_so_path);	return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id);}/** * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc * @opensc_so_path: opensc_so_path from the configuration */static int tls_engine_load_dynamic_opensc(const char *opensc_so_path){	char *engine_id = "opensc";	const char *pre_cmd[] = {		"SO_PATH", NULL /* opensc_so_path */,		"ID", NULL /* engine_id */,		"LIST_ADD", "1",		"LOAD", NULL,		NULL, NULL	};	if (!opensc_so_path)		return 0;	pre_cmd[1] = opensc_so_path;	pre_cmd[3] = engine_id;	wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",		   opensc_so_path);	return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id);}#endif /* OPENSSL_NO_ENGINE */void * tls_init(const struct tls_config *conf){	SSL_CTX *ssl;	if (tls_openssl_ref_count == 0) {		SSL_load_error_strings();		SSL_library_init();		/* TODO: if /dev/urandom is available, PRNG is seeded		 * automatically. If this is not the case, random data should		 * be added here. */#ifdef PKCS12_FUNCS		PKCS12_PBE_add();#endif  /* PKCS12_FUNCS */	}	tls_openssl_ref_count++;	ssl = SSL_CTX_new(TLSv1_method());	if (ssl == NULL)		return NULL;	SSL_CTX_set_info_callback(ssl, ssl_info_cb);#ifndef OPENSSL_NO_ENGINE	if (conf &&	    (conf->opensc_engine_path || conf->pkcs11_engine_path ||	     conf->pkcs11_module_path)) {		wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");		ERR_load_ENGINE_strings();		ENGINE_load_dynamic();		if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||		    tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,						   conf->pkcs11_module_path)) {			tls_deinit(ssl);			return NULL;		}	}#endif /* OPENSSL_NO_ENGINE */	return ssl;}void tls_deinit(void *ssl_ctx){	SSL_CTX *ssl = ssl_ctx;	SSL_CTX_free(ssl);	tls_openssl_ref_count--;	if (tls_openssl_ref_count == 0) {#ifndef OPENSSL_NO_ENGINE		ENGINE_cleanup();#endif /* OPENSSL_NO_ENGINE */		CRYPTO_cleanup_all_ex_data();		ERR_remove_state(0);		ERR_free_strings();		EVP_cleanup();	}}static int tls_engine_init(struct tls_connection *conn, const char *engine_id,			   const char *pin, const char *key_id,			   const char *cert_id, const char *ca_cert_id){#ifndef OPENSSL_NO_ENGINE	int ret = -1;	if (engine_id == NULL) {		wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");		return -1;	}	if (pin == NULL) {		wpa_printf(MSG_ERROR, "ENGINE: Smartcard PIN not set");		return -1;	}	if (key_id == NULL) {		wpa_printf(MSG_ERROR, "ENGINE: Key Id not set");		return -1;	}	ERR_clear_error();	conn->engine = ENGINE_by_id(engine_id);	if (!conn->engine) {		wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",			   engine_id, ERR_error_string(ERR_get_error(), NULL));		goto err;	}	if (ENGINE_init(conn->engine) != 1) {		wpa_printf(MSG_ERROR, "ENGINE: engine init failed "			   "(engine: %s) [%s]", engine_id,			   ERR_error_string(ERR_get_error(), NULL));		goto err;	}	wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");	if (ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {		wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",			   ERR_error_string(ERR_get_error(), NULL));		goto err;	}	/* load private key first in-case PIN is required for cert */	conn->private_key = ENGINE_load_private_key(conn->engine,						    key_id, NULL, NULL);	if (!conn->private_key) {		wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id"				" '%s' [%s]", key_id,			   ERR_error_string(ERR_get_error(), NULL));		ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;		goto err;	}	/* handle a certificate and/or CA certificate */	if (cert_id || ca_cert_id) {		const char *cmd_name = "LOAD_CERT_CTRL";		/* test if the engine supports a LOAD_CERT_CTRL */		if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,				 0, (void *)cmd_name, NULL)) {			wpa_printf(MSG_ERROR, "ENGINE: engine does not support"				   " loading certificates");			ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;			goto err;		}	}	return 0;err:	if (conn->engine) {		ENGINE_free(conn->engine);		conn->engine = NULL;	}	if (conn->private_key) {		EVP_PKEY_free(conn->private_key);		conn->private_key = NULL;	}	return ret;#else /* OPENSSL_NO_ENGINE */	return 0;#endif /* OPENSSL_NO_ENGINE */}static void tls_engine_deinit(struct tls_connection *conn){#ifndef OPENSSL_NO_ENGINE	wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");	if (conn->private_key) {		EVP_PKEY_free(conn->private_key);		conn->private_key = NULL;	}	if (conn->engine) {		ENGINE_finish(conn->engine);		conn->engine = NULL;	}#endif /* OPENSSL_NO_ENGINE */}int tls_get_errors(void *ssl_ctx){	int count = 0;	unsigned long err;	while ((err = ERR_get_error())) {		wpa_printf(MSG_INFO, "TLS - SSL error: %s",			   ERR_error_string(err, NULL));		count++;	}	return count;}struct tls_connection * tls_connection_init(void *ssl_ctx){	SSL_CTX *ssl = ssl_ctx;	struct tls_connection *conn;	long options;	conn = os_zalloc(sizeof(*conn));	if (conn == NULL)		return NULL;	conn->ssl = SSL_new(ssl);	if (conn->ssl == NULL) {		tls_show_errors(MSG_INFO, __func__,				"Failed to initialize new SSL connection");		os_free(conn);		return NULL;	}	SSL_set_app_data(conn->ssl, conn);	options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |		SSL_OP_SINGLE_DH_USE;#ifdef SSL_OP_NO_COMPRESSION	options |= SSL_OP_NO_COMPRESSION;#endif /* SSL_OP_NO_COMPRESSION */	SSL_set_options(conn->ssl, options);	conn->ssl_in = BIO_new(BIO_s_mem());	if (!conn->ssl_in) {		tls_show_errors(MSG_INFO, __func__,				"Failed to create a new BIO for ssl_in");		SSL_free(conn->ssl);		os_free(conn);		return NULL;	}	conn->ssl_out = BIO_new(BIO_s_mem());	if (!conn->ssl_out) {		tls_show_errors(MSG_INFO, __func__,				"Failed to create a new BIO for ssl_out");		SSL_free(conn->ssl);		BIO_free(conn->ssl_in);		os_free(conn);		return NULL;	}	SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out);	return conn;}void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn){	if (conn == NULL)		return;	SSL_free(conn->ssl);	tls_engine_deinit(conn);	os_free(conn->subject_match);	os_free(conn->altsubject_match);	os_free(conn->session_ticket);	os_free(conn);}int tls_connection_established(void *ssl_ctx, struct tls_connection *conn){	return conn ? SSL_is_init_finished(conn->ssl) : 0;}int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn){	if (conn == NULL)		return -1;	/* Shutdown previous TLS connection without notifying the peer	 * because the connection was already terminated in practice	 * and "close notify" shutdown alert would confuse AS. */	SSL_set_quiet_shutdown(conn->ssl, 1);	SSL_shutdown(conn->ssl);	return 0;}static int tls_match_altsubject_component(X509 *cert, int type,					  const char *value, size_t len){	GENERAL_NAME *gen;	void *ext;	int i, found = 0;	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {		gen = sk_GENERAL_NAME_value(ext, i);		if (gen->type != type)			continue;		if (os_strlen((char *) gen->d.ia5->data) == len &&		    os_memcmp(value, gen->d.ia5->data, len) == 0)			found++;	}	return found;}static int tls_match_altsubject(X509 *cert, const char *match){	int type;	const char *pos, *end;	size_t len;	pos = match;	do {		if (os_strncmp(pos, "EMAIL:", 6) == 0) {			type = GEN_EMAIL;			pos += 6;		} else if (os_strncmp(pos, "DNS:", 4) == 0) {			type = GEN_DNS;			pos += 4;		} else if (os_strncmp(pos, "URI:", 4) == 0) {			type = GEN_URI;			pos += 4;		} else {			wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "				   "match '%s'", pos);			return 0;		}		end = os_strchr(pos, ';');		while (end) {			if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||			    os_strncmp(end + 1, "DNS:", 4) == 0 ||			    os_strncmp(end + 1, "URI:", 4) == 0)				break;			end = os_strchr(end + 1, ';');		}		if (end)			len = end - pos;		else			len = os_strlen(pos);		if (tls_match_altsubject_component(cert, type, pos, len) > 0)			return 1;		pos = end + 1;	} while (end);	return 0;}static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx){	char buf[256];	X509 *err_cert;	int err, depth;	SSL *ssl;	struct tls_connection *conn;	char *match, *altmatch;	err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);	err = X509_STORE_CTX_get_error(x509_ctx);	depth = X509_STORE_CTX_get_error_depth(x509_ctx);	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,					 SSL_get_ex_data_X509_STORE_CTX_idx());	X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));	conn = SSL_get_app_data(ssl);	match = conn ? conn->subject_match : NULL;	altmatch = conn ? conn->altsubject_match : NULL;	if (!preverify_ok) {		wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"			   " error %d (%s) depth %d for '%s'", err,			   X509_verify_cert_error_string(err), depth, buf);	} else {		wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "

⌨️ 快捷键说明

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