Sorry for the late response, but better late then never. So, ACK to this patch!
-Steffan On 25-11-13 13:32, David Sommerseth wrote: > From: David Sommerseth <dav...@redhat.com> > > Commit 0f2bc0dd92f43c9 started to introduce some file sanity > checking before OpenVPN started to avoid harder to explain issues > due to missing files or directories later on. But that commit > did not consider --chroot at all. Which would basically cause > OpenVPN to complain on non-missing files, because it would not > consider that the files where inside a chroot. > > This patch is based on the thoughts in a patch by Josh Cepek [1], > but trying to simplify it at bit. > > [1] <http://thread.gmane.org/gmane.network.openvpn.devel/7873>, > (Message-ID: l142b7$15v$1...@ger.gmane.org) > > [v2 - Simplify the changes in check_cmd_access(), let the chroot > tackling happen only in check_file_access_chroot() only] > > Trac-ticket: 330 > Signed-off-by: David Sommerseth <dav...@redhat.com> > --- > src/openvpn/options.c | 82 > ++++++++++++++++++++++++++++++++++++++------------- > 1 file changed, 61 insertions(+), 21 deletions(-) > > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > index e925397..247442f 100644 > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -5,7 +5,7 @@ > * packet encryption, packet authentication, and > * packet compression. > * > - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sa...@openvpn.net> > + * Copyright (C) 2002-2013 OpenVPN Technologies, Inc. <sa...@openvpn.net> > * Copyright (C) 2008-2013 David Sommerseth <d...@users.sourceforge.net> > * > * This program is free software; you can redistribute it and/or modify > @@ -2626,6 +2626,44 @@ check_file_access(const int type, const char *file, > const int mode, const char * > return (errcode != 0 ? true : false); > } > > +/* A wrapper for check_file_access() which also takes a chroot directory. > + * If chroot is NULL, behaviour is exactly the same as calling > check_file_access() directly, > + * otherwise it will look for the file inside the given chroot directory > instead. > + */ > +static bool > +check_file_access_chroot(const char *chroot, const int type, const char > *file, const int mode, const char *opt) > +{ > + bool ret = false; > + > + /* If no file configured, no errors to look for */ > + if (!file) > + return false; > + > + /* If chroot is set, look for the file/directory inside the chroot */ > + if( chroot ) > + { > + struct gc_arena gc = gc_new(); > + struct buffer chroot_file; > + int len = 0; > + > + /* Build up a new full path including chroot directory */ > + len = strlen(chroot) + strlen(PATH_SEPARATOR_STR) + strlen(file) + 1; > + chroot_file = alloc_buf_gc(len, &gc); > + buf_printf(&chroot_file, "%s%s%s", chroot, PATH_SEPARATOR_STR, file); > + ASSERT (chroot_file.len > 0); > + > + ret = check_file_access(type, BSTR(&chroot_file), mode, opt); > + gc_free(&gc); > + } > + else > + { > + /* No chroot in play, just call core file check function */ > + ret = check_file_access(type, file, mode, opt); > + } > + return ret; > +} > + > + > /* > * Verifies that the path in the "command" that comes after certain script > options (e.g., --up) is a > * valid file with appropriate permissions. > @@ -2643,7 +2681,7 @@ check_file_access(const int type, const char *file, > const int mode, const char * > * check_file_access() arguments. > */ > static bool > -check_cmd_access(const char *command, const char *opt) > +check_cmd_access(const char *command, const char *opt, const char *chroot) > { > struct argv argv; > bool return_code; > @@ -2662,7 +2700,7 @@ check_cmd_access(const char *command, const char *opt) > * only requires X_OK to function on Unix - a scenario not unlikely to > * be seen on suid binaries. > */ > - return_code = check_file_access(CHKACC_FILE, argv.argv[0], X_OK, opt); > + return_code = check_file_access_chroot(chroot, CHKACC_FILE, > argv.argv[0], X_OK, opt); > else > { > msg (M_NOPREFIX|M_OPTERR, "%s fails with '%s': No path to executable.", > @@ -2688,7 +2726,7 @@ options_postprocess_filechecks (struct options *options) > #ifdef ENABLE_SSL > errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->dh_file, > R_OK, "--dh"); > errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->ca_file, > R_OK, "--ca"); > - errs |= check_file_access (CHKACC_FILE, options->ca_path, R_OK, > "--capath"); > + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, > options->ca_path, R_OK, "--capath"); > errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->cert_file, > R_OK, "--cert"); > errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, > options->extra_certs_file, R_OK, > "--extra-certs"); > @@ -2701,10 +2739,10 @@ options_postprocess_filechecks (struct options > *options) > "--pkcs12"); > > if (options->ssl_flags & SSLF_CRL_VERIFY_DIR) > - errs |= check_file_access (CHKACC_FILE, options->crl_file, R_OK|X_OK, > + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, > options->crl_file, R_OK|X_OK, > "--crl-verify directory"); > else > - errs |= check_file_access (CHKACC_FILE, options->crl_file, R_OK, > + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, > options->crl_file, R_OK, > "--crl-verify"); > > errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, > options->tls_auth_file, R_OK, > @@ -2746,13 +2784,13 @@ options_postprocess_filechecks (struct options > *options) > > /* ** Config related ** */ > #ifdef ENABLE_SSL > - errs |= check_file_access (CHKACC_FILE, options->tls_export_cert, > + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, > options->tls_export_cert, > R_OK|W_OK|X_OK, "--tls-export-cert"); > #endif /* ENABLE_SSL */ > #if P2MP_SERVER > - errs |= check_file_access (CHKACC_FILE, options->client_config_dir, > + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, > options->client_config_dir, > R_OK|X_OK, "--client-config-dir"); > - errs |= check_file_access (CHKACC_FILE, options->tmp_dir, > + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, > options->tmp_dir, > R_OK|W_OK|X_OK, "Temporary directory > (--tmp-dir)"); > > #endif /* P2MP_SERVER */ > @@ -4017,7 +4055,8 @@ static void > set_user_script (struct options *options, > const char **script, > const char *new_script, > - const char *type) > + const char *type, > + bool in_chroot) > { > if (*script) { > msg (M_WARN, "Multiple --%s scripts defined. " > @@ -4032,8 +4071,9 @@ set_user_script (struct options *options, > openvpn_snprintf (script_name, sizeof(script_name), > "--%s script", type); > > - if (check_cmd_access (*script, script_name)) > + if (check_cmd_access (*script, script_name, (in_chroot ? > options->chroot_dir : NULL))) > msg (M_USAGE, "Please correct this error."); > + > } > #endif > } > @@ -4551,7 +4591,7 @@ add_option (struct options *options, > set_user_script (options, > &options->ipchange, > string_substitute (p[1], ',', ' ', &options->gc), > - "ipchange"); > + "ipchange", true); > } > else if (streq (p[0], "float")) > { > @@ -4597,14 +4637,14 @@ add_option (struct options *options, > VERIFY_PERMISSION (OPT_P_SCRIPT); > if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) > goto err; > - set_user_script (options, &options->up_script, p[1], "up"); > + set_user_script (options, &options->up_script, p[1], "up", false); > } > else if (streq (p[0], "down") && p[1]) > { > VERIFY_PERMISSION (OPT_P_SCRIPT); > if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) > goto err; > - set_user_script (options, &options->down_script, p[1], "down"); > + set_user_script (options, &options->down_script, p[1], "down", true); > } > else if (streq (p[0], "down-pre")) > { > @@ -5312,7 +5352,7 @@ add_option (struct options *options, > VERIFY_PERMISSION (OPT_P_SCRIPT); > if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) > goto err; > - set_user_script (options, &options->route_script, p[1], "route-up"); > + set_user_script (options, &options->route_script, p[1], "route-up", > false); > } > else if (streq (p[0], "route-pre-down") && p[1]) > { > @@ -5322,7 +5362,7 @@ add_option (struct options *options, > set_user_script (options, > &options->route_predown_script, > p[1], > - "route-pre-down"); > + "route-pre-down", true); > } > else if (streq (p[0], "route-noexec")) > { > @@ -5691,7 +5731,7 @@ add_option (struct options *options, > } > set_user_script (options, > &options->auth_user_pass_verify_script, > - p[1], "auth-user-pass-verify"); > + p[1], "auth-user-pass-verify", true); > } > else if (streq (p[0], "client-connect") && p[1]) > { > @@ -5699,7 +5739,7 @@ add_option (struct options *options, > if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) > goto err; > set_user_script (options, &options->client_connect_script, > - p[1], "client-connect"); > + p[1], "client-connect", true); > } > else if (streq (p[0], "client-disconnect") && p[1]) > { > @@ -5707,7 +5747,7 @@ add_option (struct options *options, > if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) > goto err; > set_user_script (options, &options->client_disconnect_script, > - p[1], "client-disconnect"); > + p[1], "client-disconnect", true); > } > else if (streq (p[0], "learn-address") && p[1]) > { > @@ -5715,7 +5755,7 @@ add_option (struct options *options, > if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) > goto err; > set_user_script (options, &options->learn_address_script, > - p[1], "learn-address"); > + p[1], "learn-address", true); > } > else if (streq (p[0], "tmp-dir") && p[1]) > { > @@ -6675,7 +6715,7 @@ add_option (struct options *options, > goto err; > set_user_script (options, &options->tls_verify, > string_substitute (p[1], ',', ' ', &options->gc), > - "tls-verify"); > + "tls-verify", true); > } > #ifndef ENABLE_CRYPTO_POLARSSL > else if (streq (p[0], "tls-export-cert") && p[1]) >