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

📄 tls_openssl.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * 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 */		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){#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;	}	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;	}	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;	conn = wpa_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");		free(conn);		return NULL;	}	SSL_set_app_data(conn->ssl, conn);	SSL_set_options(conn->ssl,			SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |			SSL_OP_SINGLE_DH_USE);	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);		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);		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;	free(conn->pre_shared_secret);	SSL_free(conn->ssl);	tls_engine_deinit(conn);	free(conn->subject_match);	free(conn->altsubject_match);	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(X509 *cert, const char *match){	GENERAL_NAME *gen;	char *field, *tmp;	void *ext;	int i, found = 0;	size_t len;	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);		switch (gen->type) {		case GEN_EMAIL:			field = "EMAIL";			break;		case GEN_DNS:			field = "DNS";			break;		case GEN_URI:			field = "URI";			break;		default:			field = NULL;			wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "				   "unsupported type=%d", gen->type);			break;		}		if (!field)			continue;		wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",			   field, gen->d.ia5->data);		len = strlen(field) + 1 + strlen((char *) gen->d.ia5->data) +			1;		tmp = malloc(len);		if (tmp == NULL)			continue;		snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);		if (strstr(tmp, match))			found++;		free(tmp);	}	return found;}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 - "			   "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",			   preverify_ok, err,			   X509_verify_cert_error_string(err), depth, buf);		if (depth == 0 && match && strstr(buf, match) == NULL) {			wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "				   "match with '%s'", buf, match);			preverify_ok = 0;		} else if (depth == 0 && altmatch &&			   !tls_match_altsubject(err_cert, altmatch)) {			wpa_printf(MSG_WARNING, "TLS: altSubjectName match "				   "'%s' not found", altmatch);			preverify_ok = 0;		}	}	return preverify_ok;}#ifndef OPENSSL_NO_STDIOstatic int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert){	SSL_CTX *ssl_ctx = _ssl_ctx;	X509_LOOKUP *lookup;	int ret = 0;	lookup = X509_STORE_add_lookup(ssl_ctx->cert_store,				       X509_LOOKUP_file());	if (lookup == NULL) {		tls_show_errors(MSG_WARNING, __func__,				"Failed add lookup for X509 store");		return -1;	}	if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) {		unsigned long err = ERR_peek_error();		tls_show_errors(MSG_WARNING, __func__,				"Failed load CA in DER format");		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "				   "cert already in hash table error",				   __func__);		} else			ret = -1;	}	return ret;}#endif /* OPENSSL_NO_STDIO */static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,				  const char *ca_cert, const u8 *ca_cert_blob,				  size_t ca_cert_blob_len, const char *ca_path){	SSL_CTX *ssl_ctx = _ssl_ctx;	if (ca_cert_blob) {		X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob,				      ca_cert_blob_len);		if (cert == NULL) {			tls_show_errors(MSG_WARNING, __func__,					"Failed to parse ca_cert_blob");			return -1;		}		if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {			tls_show_errors(MSG_WARNING, __func__,					"Failed to add ca_cert_blob to "					"certificate store");			X509_free(cert);			return -1;		}		X509_free(cert);		wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "			   "to certificate store", __func__);		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);		return 0;	}#ifdef CONFIG_NATIVE_WINDOWS	if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==	    0) {		wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "			   "system certificate store");		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);		return 0;	}#endif /* CONFIG_NATIVE_WINDOWS */	if (ca_cert || ca_path) {#ifndef OPENSSL_NO_STDIO		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) !=		    1) {			tls_show_errors(MSG_WARNING, __func__,					"Failed to load root certificates");			if (ca_cert &&			    tls_load_ca_der(ssl_ctx, ca_cert) == 0) {

⌨️ 快捷键说明

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