From patchwork Tue Nov 20 23:10:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 612 X-Patchwork-Delegate: a@unstable.cc Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id QHZROUtQ9VtONAAAIUCqbw for ; Wed, 21 Nov 2018 07:32:11 -0500 Received: from proxy10.mail.ord1d.rsapps.net ([172.30.191.6]) by director8.mail.ord1d.rsapps.net with LMTP id WAMlOUtQ9VteFwAAfY0hYg ; Wed, 21 Nov 2018 07:32:11 -0500 Received: from smtp29.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy10.mail.ord1d.rsapps.net with LMTP id 2CbrOEtQ9VveCQAAfSg8FQ ; Wed, 21 Nov 2018 07:32:11 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp29.gate.ord1d.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 77c3df56-ed89-11e8-ae55-525400f257a9-1-1 Received: from [216.105.38.7] ([216.105.38.7:44132] helo=lists.sourceforge.net) by smtp29.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 40/7B-12260-B4055FB5; Wed, 21 Nov 2018 07:32:11 -0500 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1gPRf6-0004PM-I0; Wed, 21 Nov 2018 12:31:20 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1gPRf5-0004PF-2o for openvpn-devel@lists.sourceforge.NET; Wed, 21 Nov 2018 12:31:19 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=JoFTeqJjXgKXL87Smgh+eQxo7wqWisGZOTmgt962dnY=; b=MGLWns7dM3UqQvg/HNQt8P5K3f 1PKoh3sAvLco0TziJd/GV0WeNHoUiVADbPU7PehXzYIT9MpyQ90K3OAVJaFWsTdBzOwDcqNGeCr76 34k4IXCo0I+8XM9CQG5LZ0Wl81liMSRvKFTIpyXhDHNkaQY8s/OD2icj0Z1DjnyiRhXQ=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=JoFTeqJjXgKXL87Smgh+eQxo7wqWisGZOTmgt962dnY=; b=OdSoGtFxyAt+0wJZs+CTtfbjdB hzPK7VDFUMEGwj5vwn2F0tqHlRIuDRikUIzuxh8adfy6GC+WwL7EQuHrqmIFgobLin+n8JenuQRjr h/ZYaMll0Hes7BicLb77IMdSU5A6CNaqqKuXT0XxosQKPYj1bFk1IKo7USBeFuzwmLiw=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1gPRew-008sMu-86 for openvpn-devel@lists.sourceforge.NET; Wed, 21 Nov 2018 12:31:18 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.91 (FreeBSD)) (envelope-from ) id 1gPPSe-000GWC-4m; Wed, 21 Nov 2018 11:10:20 +0100 Received: (nullmailer pid 1849 invoked by uid 10006); Wed, 21 Nov 2018 10:10:20 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 21 Nov 2018 11:10:07 +0100 Message-Id: <20181121101019.1801-2-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181121101019.1801-1-arne@rfc2549.org> References: <20181121101019.1801-1-arne@rfc2549.org> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different X-Headers-End: 1gPRew-008sMu-86 Subject: [Openvpn-devel] [PATCH v4 01/13] client-connect: Split multi_connection_established into separate functions X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Fabian Knittel This patch splits up the multi_connection_established() function. Each new helper function does a specific job. Functions that do a similar job receive a similar calling interface. The patch tries not to reindent code, so that the real changes are as clearly visible as possible. (A follow-up patch will only do indentation changes.) Signed-off-by: Fabian Knittel PATCH v3: Since the code has changed enough from the time the original patch to the current master, the splitting has been redone from the current code. Also some style and minor code changes have been added doing this patch. This elimininates and the big reformatting done before eliminates the follow up patch with indentation changes. The original patch already replaces some instances of option_permission_mask with CLIENT_CONNECT_OPT_MASK. The V3 version does this more consequently. Signed-off-by: Arne Schwabe --- src/openvpn/multi.c | 597 +++++++++++++++++++++++++------------------- src/openvpn/multi.h | 4 +- 2 files changed, 346 insertions(+), 255 deletions(-) diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 8440f311..a4b62151 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -1638,7 +1638,6 @@ static void multi_client_connect_post(struct multi_context *m, struct multi_instance *mi, const char *dc_file, - unsigned int option_permissions_mask, unsigned int *option_types_found) { /* Did script generate a dynamic config file? */ @@ -1647,7 +1646,7 @@ multi_client_connect_post(struct multi_context *m, options_server_import(&mi->context.options, dc_file, D_IMPORT_ERRORS|M_OPTERR, - option_permissions_mask, + CLIENT_CONNECT_OPT_MASK, option_types_found, mi->context.c2.es); @@ -1671,7 +1670,6 @@ static void multi_client_connect_post_plugin(struct multi_context *m, struct multi_instance *mi, const struct plugin_return *pr, - unsigned int option_permissions_mask, unsigned int *option_types_found) { struct plugin_return config; @@ -1689,7 +1687,7 @@ multi_client_connect_post_plugin(struct multi_context *m, options_string_import(&mi->context.options, config.list[i]->value, D_IMPORT_ERRORS|M_OPTERR, - option_permissions_mask, + CLIENT_CONNECT_OPT_MASK, option_types_found, mi->context.c2.es); } @@ -1716,21 +1714,19 @@ multi_client_connect_post_plugin(struct multi_context *m, static void multi_client_connect_mda(struct multi_context *m, struct multi_instance *mi, - const struct buffer_list *config, - unsigned int option_permissions_mask, unsigned int *option_types_found) { - if (config) + if (mi->cc_config) { struct buffer_entry *be; - for (be = config->head; be != NULL; be = be->next) + for (be = mi->cc_config->head; be != NULL; be = be->next) { const char *opt = BSTR(&be->buf); options_string_import(&mi->context.options, opt, D_IMPORT_ERRORS|M_OPTERR, - option_permissions_mask, + CLIENT_CONNECT_OPT_MASK, option_types_found, mi->context.c2.es); } @@ -1773,215 +1769,386 @@ multi_client_connect_setenv(struct multi_context *m, gc_free(&gc); } -/* - * Called as soon as the SSL/TLS connection authenticates. - * - * Instance-specific directives to be processed: - * - * iroute start-ip end-ip - * ifconfig-push local remote-netmask - * push - */ static void -multi_connection_established(struct multi_context *m, struct multi_instance *mi) +multi_client_connect_call_plugin_v1(struct multi_context *m, + struct multi_instance *mi, + unsigned int *option_types_found, + int *cc_succeeded, + int *cc_succeeded_count) { - if (tls_authentication_status(mi->context.c2.tls_multi, 0) == TLS_AUTHENTICATION_SUCCEEDED) +#ifdef ENABLE_PLUGIN + ASSERT(m); + ASSERT(mi); + ASSERT(option_types_found); + ASSERT(cc_succeeded); + ASSERT(cc_succeeded_count); + + /* deprecated callback, use a file for passing back return info */ + if (plugin_defined(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT)) { + struct argv argv = argv_new(); struct gc_arena gc = gc_new(); - unsigned int option_types_found = 0; + const char *dc_file = + platform_create_temp_file(mi->context.options.tmp_dir, "cc", &gc); - const unsigned int option_permissions_mask = - OPT_P_INSTANCE - | OPT_P_INHERIT - | OPT_P_PUSH - | OPT_P_TIMER - | OPT_P_CONFIG - | OPT_P_ECHO - | OPT_P_COMP - | OPT_P_SOCKFLAGS; + if (!dc_file) + { + cc_succeeded = false; + goto cleanup; + } - int cc_succeeded = true; /* client connect script status */ - int cc_succeeded_count = 0; + argv_printf(&argv, "%s", dc_file); + if (plugin_call(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT, + &argv, NULL, mi->context.c2.es) + != OPENVPN_PLUGIN_FUNC_SUCCESS) + { + msg(M_WARN, "WARNING: client-connect plugin call failed"); + *cc_succeeded = false; + } + else + { + multi_client_connect_post(m, mi, dc_file, option_types_found); + (*cc_succeeded_count)++; + } + + { + msg(D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", + dc_file); + } + +cleanup: + argv_reset(&argv); + gc_free(&gc); + } +#endif /* ifdef ENABLE_PLUGIN */ +} - ASSERT(mi->context.c1.tuntap); +static void +multi_client_connect_call_plugin_v2(struct multi_context *m, + struct multi_instance *mi, + unsigned int *option_types_found, + int *cc_succeeded, + int *cc_succeeded_count) +{ +#ifdef ENABLE_PLUGIN + ASSERT(m); + ASSERT(mi); + ASSERT(option_types_found); + ASSERT(cc_succeeded); + ASSERT(cc_succeeded_count); - /* lock down the common name and cert hashes so they can't change during future TLS renegotiations */ - tls_lock_common_name(mi->context.c2.tls_multi); - tls_lock_cert_hash_set(mi->context.c2.tls_multi); + /* V2 callback, use a plugin_return struct for passing back return info */ + if (plugin_defined(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT_V2)) + { + struct plugin_return pr; - /* generate a msg() prefix for this client instance */ - generate_prefix(mi); + plugin_return_init(&pr); - /* delete instances of previous clients with same common-name */ - if (!mi->context.options.duplicate_cn) + if (plugin_call(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT_V2, + NULL, &pr, mi->context.c2.es) + != OPENVPN_PLUGIN_FUNC_SUCCESS) { - multi_delete_dup(m, mi); + msg(M_WARN, "WARNING: client-connect-v2 plugin call failed"); + *cc_succeeded = false; + } + else + { + multi_client_connect_post_plugin(m, mi, &pr, option_types_found); + (*cc_succeeded_count)++; } - /* reset pool handle to null */ - mi->vaddr_handle = -1; + plugin_return_free(&pr); + } +#endif /* ifdef ENABLE_PLUGIN */ +} - /* - * Try to source a dynamic config file from the - * --client-config-dir directory. - */ - if (mi->context.options.client_config_dir) + + +/** + * Runs the --client-connect script if one is defined. + */ +static void +multi_client_connect_call_script(struct multi_context *m, + struct multi_instance *mi, + unsigned int *option_types_found, + int *cc_succeeded, + int *cc_succeeded_count) +{ + if (mi->context.options.client_connect_script) + { + struct argv argv = argv_new(); + struct gc_arena gc = gc_new(); + const char *dc_file = NULL; + + setenv_str(mi->context.c2.es, "script_type", "client-connect"); + + dc_file = platform_create_temp_file(mi->context.options.tmp_dir, + "cc", &gc); + if (!dc_file) { - const char *ccd_file; + *cc_succeeded = false; + goto cleanup; + } - ccd_file = platform_gen_path(mi->context.options.client_config_dir, - tls_common_name(mi->context.c2.tls_multi, - false), - &gc); + argv_parse_cmd(&argv, mi->context.options.client_connect_script); + argv_printf_cat(&argv, "%s", dc_file); - /* try common-name file */ - if (platform_test_file(ccd_file)) - { - options_server_import(&mi->context.options, - ccd_file, - D_IMPORT_ERRORS|M_OPTERR, - option_permissions_mask, - &option_types_found, - mi->context.c2.es); - } - else /* try default file */ - { - ccd_file = platform_gen_path(mi->context.options.client_config_dir, - CCD_DEFAULT, - &gc); + if (openvpn_run_script(&argv, mi->context.c2.es, 0, "--client-connect")) + { + multi_client_connect_post(m, mi, dc_file, option_types_found); + (*cc_succeeded_count)++; + } + else + { + *cc_succeeded = false; + } - if (platform_test_file(ccd_file)) - { - options_server_import(&mi->context.options, - ccd_file, - D_IMPORT_ERRORS|M_OPTERR, - option_permissions_mask, - &option_types_found, - mi->context.c2.es); - } - } + if (!platform_unlink(dc_file)) + { + msg(D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", + dc_file); } +cleanup: + argv_reset(&argv); + gc_free(&gc); + } +} - /* - * Select a virtual address from either --ifconfig-push in --client-config-dir file - * or --ifconfig-pool. - */ - multi_select_virtual_addr(m, mi); +static void +multi_client_connect_late_setup(struct multi_context *m, + struct multi_instance *mi, + const unsigned int option_types_found) +{ + struct gc_arena gc = gc_new(); + /* + * Process sourced options. + */ + do_deferred_options(&mi->context, option_types_found); - /* do --client-connect setenvs */ - multi_client_connect_setenv(m, mi); + /* + * make sure we got ifconfig settings from somewhere + */ + if (!mi->context.c2.push_ifconfig_defined) + { + msg(D_MULTI_ERRORS, "MULTI: no dynamic or static remote" + "--ifconfig address is available for %s", + multi_instance_string(mi, false, &gc)); + } + + /* + * make sure that ifconfig settings comply with constraints + */ + if (!ifconfig_push_constraint_satisfied(&mi->context)) + { + const char *ifconfig_constraint_network = + print_in_addr_t(mi->context.options.push_ifconfig_constraint_network, 0, &gc); + const char *ifconfig_constraint_netmask = + print_in_addr_t(mi->context.options.push_ifconfig_constraint_netmask, 0, &gc); + + /* JYFIXME -- this should cause the connection to fail */ + msg(D_MULTI_ERRORS, "MULTI ERROR: primary virtual IP for %s (%s)" + "violates tunnel network/netmask constraint (%s/%s)", + multi_instance_string(mi, false, &gc), + print_in_addr_t(mi->context.c2.push_ifconfig_local, 0, &gc), + ifconfig_constraint_network, ifconfig_constraint_netmask); + } + + /* + * For routed tunnels, set up internal route to endpoint + * plus add all iroute routes. + */ + if (TUNNEL_TYPE(mi->context.c1.tuntap) == DEV_TYPE_TUN) + { + if (mi->context.c2.push_ifconfig_defined) + { + multi_learn_in_addr_t(m, mi, + mi->context.c2.push_ifconfig_local, + -1, true); + msg(D_MULTI_LOW, "MULTI: primary virtual IP for %s: %s", + multi_instance_string(mi, false, &gc), + print_in_addr_t(mi->context.c2.push_ifconfig_local, 0, &gc)); + } + + if (mi->context.c2.push_ifconfig_ipv6_defined) + { + multi_learn_in6_addr(m, mi, + mi->context.c2.push_ifconfig_ipv6_local, + -1, true); + /* TODO: find out where addresses are "unlearned"!! */ + const char *ifconfig_local_ipv6 = + print_in6_addr(mi->context.c2.push_ifconfig_ipv6_local, 0, &gc); + msg(D_MULTI_LOW, "MULTI: primary virtual IPv6 for %s: %s", + multi_instance_string(mi, false, &gc), + ifconfig_local_ipv6); + } + + /* add routes locally, pointing to new client, if + * --iroute options have been specified */ + multi_add_iroutes(m, mi); -#ifdef ENABLE_PLUGIN /* - * Call client-connect plug-in. + * iroutes represent subnets which are "owned" by a particular + * client. Therefore, do not actually push a route to a client + * if it matches one of the client's iroutes. */ + remove_iroutes_from_push_route_list(&mi->context.options); + } + else if (mi->context.options.iroutes) + { + msg(D_MULTI_ERRORS, "MULTI: --iroute options rejected for %s -- iroute" + "only works with tun-style tunnels", + multi_instance_string(mi, false, &gc)); + } - /* deprecated callback, use a file for passing back return info */ - if (plugin_defined(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT)) - { - struct argv argv = argv_new(); - const char *dc_file = platform_create_temp_file(mi->context.options.tmp_dir, - "cc", &gc); + /* set our client's VPN endpoint for status reporting purposes */ + mi->reporting_addr = mi->context.c2.push_ifconfig_local; + mi->reporting_addr_ipv6 = mi->context.c2.push_ifconfig_ipv6_local; - if (!dc_file) - { - cc_succeeded = false; - goto script_depr_failed; - } + /* set context-level authentication flag */ + mi->context.c2.context_auth = CAS_SUCCEEDED; - argv_printf(&argv, "%s", dc_file); - if (plugin_call(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT, &argv, NULL, mi->context.c2.es) != OPENVPN_PLUGIN_FUNC_SUCCESS) - { - msg(M_WARN, "WARNING: client-connect plugin call failed"); - cc_succeeded = false; - } - else - { - multi_client_connect_post(m, mi, dc_file, option_permissions_mask, &option_types_found); - ++cc_succeeded_count; - } +#ifdef ENABLE_ASYNC_PUSH + /* authentication complete, send push reply */ + if (mi->context.c2.push_request_received) + { + process_incoming_push_request(&mi->context); + } +#endif + gc_free(&gc); +} - if (!platform_unlink(dc_file)) - { - msg(D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", - dc_file); - } -script_depr_failed: - argv_reset(&argv); - } +static void +multi_client_connect_early_setup(struct multi_context *m, + struct multi_instance *mi) +{ + ASSERT(mi->context.c1.tuntap); + /* + * lock down the common name and cert hashes so they can't change + * during future TLS renegotiations + */ + tls_lock_common_name(mi->context.c2.tls_multi); + tls_lock_cert_hash_set(mi->context.c2.tls_multi); - /* V2 callback, use a plugin_return struct for passing back return info */ - if (plugin_defined(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT_V2)) - { - struct plugin_return pr; + /* generate a msg() prefix for this client instance */ + generate_prefix(mi); - plugin_return_init(&pr); + /* delete instances of previous clients with same common-name */ + if (!mi->context.options.duplicate_cn) + { + multi_delete_dup(m, mi); + } - if (plugin_call(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_CONNECT_V2, NULL, &pr, mi->context.c2.es) != OPENVPN_PLUGIN_FUNC_SUCCESS) - { - msg(M_WARN, "WARNING: client-connect-v2 plugin call failed"); - cc_succeeded = false; - } - else - { - multi_client_connect_post_plugin(m, mi, &pr, option_permissions_mask, &option_types_found); - ++cc_succeeded_count; - } + /* reset pool handle to null */ + mi->vaddr_handle = -1; +} - plugin_return_free(&pr); - } -#endif /* ifdef ENABLE_PLUGIN */ +/** + * Try to source a dynamic config file from the + * --client-config-dir directory. + */ +static void +multi_client_connect_source_ccd(struct multi_context *m, + struct multi_instance *mi, + unsigned int *option_types_found) +{ + if (mi->context.options.client_config_dir) + { + struct gc_arena gc = gc_new(); + const char *ccd_file; - /* - * Run --client-connect script. - */ - if (mi->context.options.client_connect_script && cc_succeeded) - { - struct argv argv = argv_new(); - const char *dc_file = NULL; + ccd_file = platform_gen_path(mi->context.options.client_config_dir, + tls_common_name(mi->context.c2.tls_multi, + false), + &gc); - setenv_str(mi->context.c2.es, "script_type", "client-connect"); + /* try common-name file */ + if (platform_test_file(ccd_file)) + { + options_server_import(&mi->context.options, + ccd_file, + D_IMPORT_ERRORS|M_OPTERR, + CLIENT_CONNECT_OPT_MASK, + option_types_found, + mi->context.c2.es); + } + else /* try default file */ + { + ccd_file = platform_gen_path(mi->context.options.client_config_dir, + CCD_DEFAULT, + &gc); - dc_file = platform_create_temp_file(mi->context.options.tmp_dir, - "cc", &gc); - if (!dc_file) + if (platform_test_file(ccd_file)) { - cc_succeeded = false; - goto script_failed; + options_server_import(&mi->context.options, + ccd_file, + D_IMPORT_ERRORS|M_OPTERR, + CLIENT_CONNECT_OPT_MASK, + option_types_found, + mi->context.c2.es); } + } + gc_free(&gc); + } +} + +/* + * Called as soon as the SSL/TLS connection authenticates. + * + * Instance-specific directives to be processed: + * + * iroute start-ip end-ip + * ifconfig-push local remote-netmask + * push + */ +static void +multi_connection_established(struct multi_context *m, struct multi_instance *mi) +{ + if (tls_authentication_status(mi->context.c2.tls_multi, 0) + == TLS_AUTHENTICATION_SUCCEEDED) + { + unsigned int option_types_found = 0; - argv_parse_cmd(&argv, mi->context.options.client_connect_script); - argv_printf_cat(&argv, "%s", dc_file); + int cc_succeeded = true; /* client connect script status */ + int cc_succeeded_count = 0; - if (openvpn_run_script(&argv, mi->context.c2.es, 0, "--client-connect")) - { - multi_client_connect_post(m, mi, dc_file, option_permissions_mask, &option_types_found); - ++cc_succeeded_count; - } - else - { - cc_succeeded = false; - } + multi_client_connect_early_setup(m, mi); - if (!platform_unlink(dc_file)) - { - msg(D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", - dc_file); - } + multi_client_connect_source_ccd(m, mi, &option_types_found); -script_failed: - argv_reset(&argv); - } + /* + * Select a virtual address from either --ifconfig-push in + * --client-config-dir file or --ifconfig-pool. + */ + multi_select_virtual_addr(m, mi); + + /* do --client-connect setenvs */ + multi_client_connect_setenv(m, mi); + + multi_client_connect_call_plugin_v1(m, mi, &option_types_found, + &cc_succeeded, + &cc_succeeded_count); + + multi_client_connect_call_plugin_v2(m, mi, &option_types_found, + &cc_succeeded, + &cc_succeeded_count); /* * Check for client-connect script left by management interface client */ + + if (cc_succeeded) + { + multi_client_connect_call_script(m, mi, &option_types_found, + &cc_succeeded, + &cc_succeeded_count); + + } #ifdef MANAGEMENT_DEF_AUTH if (cc_succeeded && mi->cc_config) { - multi_client_connect_mda(m, mi, mi->cc_config, option_permissions_mask, &option_types_found); - ++cc_succeeded_count; + multi_client_connect_mda(m, mi, &option_types_found); + cc_succeeded_count++; } #endif @@ -1991,99 +2158,21 @@ script_failed: */ if (mi->context.options.disable) { - msg(D_MULTI_ERRORS, "MULTI: client has been rejected due to 'disable' directive"); + msg(D_MULTI_ERRORS, "MULTI: client has been rejected due to" + "'disable' directive"); cc_succeeded = false; cc_succeeded_count = 0; } if (cc_succeeded) { - /* - * Process sourced options. - */ - do_deferred_options(&mi->context, option_types_found); - - /* - * make sure we got ifconfig settings from somewhere - */ - if (!mi->context.c2.push_ifconfig_defined) - { - msg(D_MULTI_ERRORS, "MULTI: no dynamic or static remote --ifconfig address is available for %s", - multi_instance_string(mi, false, &gc)); - } - - /* - * make sure that ifconfig settings comply with constraints - */ - if (!ifconfig_push_constraint_satisfied(&mi->context)) - { - /* JYFIXME -- this should cause the connection to fail */ - msg(D_MULTI_ERRORS, "MULTI ERROR: primary virtual IP for %s (%s) violates tunnel network/netmask constraint (%s/%s)", - multi_instance_string(mi, false, &gc), - print_in_addr_t(mi->context.c2.push_ifconfig_local, 0, &gc), - print_in_addr_t(mi->context.options.push_ifconfig_constraint_network, 0, &gc), - print_in_addr_t(mi->context.options.push_ifconfig_constraint_netmask, 0, &gc)); - } - - /* - * For routed tunnels, set up internal route to endpoint - * plus add all iroute routes. - */ - if (TUNNEL_TYPE(mi->context.c1.tuntap) == DEV_TYPE_TUN) - { - if (mi->context.c2.push_ifconfig_defined) - { - multi_learn_in_addr_t(m, mi, mi->context.c2.push_ifconfig_local, -1, true); - msg(D_MULTI_LOW, "MULTI: primary virtual IP for %s: %s", - multi_instance_string(mi, false, &gc), - print_in_addr_t(mi->context.c2.push_ifconfig_local, 0, &gc)); - } - - if (mi->context.c2.push_ifconfig_ipv6_defined) - { - multi_learn_in6_addr(m, mi, mi->context.c2.push_ifconfig_ipv6_local, -1, true); - /* TODO: find out where addresses are "unlearned"!! */ - msg(D_MULTI_LOW, "MULTI: primary virtual IPv6 for %s: %s", - multi_instance_string(mi, false, &gc), - print_in6_addr(mi->context.c2.push_ifconfig_ipv6_local, 0, &gc)); - } - - /* add routes locally, pointing to new client, if - * --iroute options have been specified */ - multi_add_iroutes(m, mi); - - /* - * iroutes represent subnets which are "owned" by a particular - * client. Therefore, do not actually push a route to a client - * if it matches one of the client's iroutes. - */ - remove_iroutes_from_push_route_list(&mi->context.options); - } - else if (mi->context.options.iroutes) - { - msg(D_MULTI_ERRORS, "MULTI: --iroute options rejected for %s -- iroute only works with tun-style tunnels", - multi_instance_string(mi, false, &gc)); - } - - /* set our client's VPN endpoint for status reporting purposes */ - mi->reporting_addr = mi->context.c2.push_ifconfig_local; - mi->reporting_addr_ipv6 = mi->context.c2.push_ifconfig_ipv6_local; - - /* set context-level authentication flag */ - mi->context.c2.context_auth = CAS_SUCCEEDED; - -#ifdef ENABLE_ASYNC_PUSH - /* authentication complete, send push reply */ - if (mi->context.c2.push_request_received) - { - process_incoming_push_request(&mi->context); - } -#endif + multi_client_connect_late_setup(m, mi, option_types_found); } else { /* set context-level authentication flag */ - mi->context.c2.context_auth = cc_succeeded_count ? CAS_PARTIAL : CAS_FAILED; + mi->context.c2.context_auth = + cc_succeeded_count ? CAS_PARTIAL : CAS_FAILED; } /* set flag so we don't get called again */ @@ -2097,11 +2186,11 @@ script_failed: #ifdef MANAGEMENT_DEF_AUTH if (management) { - management_connection_established(management, &mi->context.c2.mda_context, mi->context.c2.es); + management_connection_established + (management, &mi->context.c2.mda_context, mi->context.c2.es); } #endif - gc_free(&gc); } /* diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 3d3d6875..489c073a 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -628,7 +628,9 @@ multi_process_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags return ret; } - +#define CLIENT_CONNECT_OPT_MASK (OPT_P_INSTANCE | OPT_P_INHERIT \ + |OPT_P_PUSH | OPT_P_TIMER | OPT_P_CONFIG \ + |OPT_P_ECHO | OPT_P_COMP | OPT_P_SOCKFLAGS) static inline bool multi_process_outgoing_link_dowork(struct multi_context *m, struct multi_instance *mi, const unsigned int mpp_flags)