[PATCH] introduce vendordir for easier config file update
Thorsten Kukuk
kukuk at suse.com
Wed Feb 3 23:54:58 AEDT 2021
Hi,
does nobody have an opinion about this?
Thanks,
Thorsten
On Fri, Jan 29, Thorsten Kukuk wrote:
>
> Hi,
>
> Distributors have one common problem: configuration files and updates.
>
> If a configuration file is modified by an user and the distributor mades
> changes to it, the package manager needs to decide which version of the
> configuration file should be used: the one of the admin or the one from
> the distributor. Independent of the decission, in worst case the service
> is broken until the admin merges the changes manually. Which is not that
> problem with a single system, but could be a lot of work for big clusters.
>
> There is now the include statement, which solves already many cases as
> the admin could put his changes in an extra file, but there are still
> some bigger issues.
>
> As an example for sshd_config: most Linux distributions added meanwhile an
> include statement to read at first files from /etc/ssh/sshd_config.d/*
> This works fine for directives like 'PermitRootLogin', where the first entry
> found wins. But you can have multiple AcceptEnv directives. And there is no
> way for an admin to change the distributor default without editing the
> config file itself, which again leads to update problems in the future.
>
> With ssh_config it's even more complicated: You can have multiple SendEnv
> directives, and you can change them later. This leads now to the situation,
> that you need two include directives: one on the beginning of the
> configuration file, which sets variables which could only be set once,
> and at the end, to remove and modify SendEnv. I don't know currently if
> there are more directives you cannot modify, so that the admin still has
> to modify the original file.
>
> I made a relativ small patch, which tries to follow the "systemd" behavior,
> which is meanwhile used by many more projects:
>
> - There is a distributor/vendor default configuration file in /usr/share/ssh
> - The admin can create his own configuration file in /etc/ssh
> - There is still the possibility to use the include statement to only override
> single directives.
>
> So if there is no admin provided configuration file, the vendor file from
> /usr/share/ssh is used. If there is an admin provided configuration file
> in /etc/ssh, this one will be used by default.
>
> Includes are only used from the configuration file which is really read.
> And if a distribution does not like this, it can still only ship the
> configuration files in /etc/ssh and there is no change in behavior.
>
> Attached is a patch which I'm using currently. I would like to see if
> upstream openssh would support this.
>
> Thorsten
>
> --
> Thorsten Kukuk, Distinguished Engineer, Senior Architect SLES & MicroOS
> SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nuernberg, Germany
> Managing Director: Felix Imendoerffer (HRB 36809, AG Nürnberg)
> diff -urN openssh-8.4p1/dh.c openssh-8.4p1-vendor/dh.c
> --- openssh-8.4p1/dh.c 2020-09-27 09:25:01.000000000 +0200
> +++ openssh-8.4p1-vendor/dh.c 2021-01-29 11:49:40.968418136 +0100
> @@ -151,10 +151,18 @@
> size_t linesize = 0;
> int best, bestcount, which, linenum;
> struct dhgroup dhg;
> + char *dh_moduli_path;
> + struct stat st;
>
> - if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
> + if (stat(_PATH_VENDOR_DH_MODULI, &st) == 0 &&
> + stat(_PATH_DH_MODULI, &st) == -1) {
> + dh_moduli_path = _PATH_VENDOR_DH_MODULI;
> + } else {
> + dh_moduli_path = _PATH_DH_MODULI;
> + }
> + if ((f = fopen(dh_moduli_path, "r")) == NULL) {
> logit("WARNING: could not open %s (%s), using fixed modulus",
> - _PATH_DH_MODULI, strerror(errno));
> + dh_moduli_path, strerror(errno));
> return (dh_new_group_fallback(max));
> }
>
> @@ -185,7 +193,7 @@
>
> if (bestcount == 0) {
> fclose(f);
> - logit("WARNING: no suitable primes in %s", _PATH_DH_MODULI);
> + logit("WARNING: no suitable primes in %s", dh_moduli_path);
> return (dh_new_group_fallback(max));
> }
> which = arc4random_uniform(bestcount);
> @@ -210,7 +218,7 @@
> fclose(f);
> if (bestcount != which + 1) {
> logit("WARNING: selected prime disappeared in %s, giving up",
> - _PATH_DH_MODULI);
> + dh_moduli_path);
> return (dh_new_group_fallback(max));
> }
>
> diff -urN openssh-8.4p1/pathnames.h openssh-8.4p1-vendor/pathnames.h
> --- openssh-8.4p1/pathnames.h 2020-09-27 09:25:01.000000000 +0200
> +++ openssh-8.4p1-vendor/pathnames.h 2021-01-29 11:35:41.655599046 +0100
> @@ -18,6 +18,8 @@
> #define SSHDIR ETCDIR "/ssh"
> #endif
>
> +#define VENDORDIR "/usr/share/ssh"
> +
> #ifndef _PATH_SSH_PIDDIR
> #define _PATH_SSH_PIDDIR "/var/run"
> #endif
> @@ -35,13 +37,16 @@
> * should be world-readable.
> */
> #define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config"
> +#define _PATH_SERVER_VENDOR_CONFIG_FILE VENDORDIR "/sshd_config"
> #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config"
> +#define _PATH_HOST_VENDOR_CONFIG_FILE VENDORDIR "/ssh_config"
> #define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key"
> #define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key"
> #define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key"
> #define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key"
> #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key"
> #define _PATH_DH_MODULI SSHDIR "/moduli"
> +#define _PATH_VENDOR_DH_MODULI VENDORDIR "/moduli"
>
> #ifndef _PATH_SSH_PROGRAM
> #define _PATH_SSH_PROGRAM "/usr/bin/ssh"
> diff -urN openssh-8.4p1/ssh.c openssh-8.4p1-vendor/ssh.c
> --- openssh-8.4p1/ssh.c 2020-09-27 09:25:01.000000000 +0200
> +++ openssh-8.4p1-vendor/ssh.c 2021-01-27 18:22:52.322271681 +0100
> @@ -593,6 +593,7 @@
> process_config_files(const char *host_name, struct passwd *pw, int final_pass,
> int *want_final_pass)
> {
> + struct stat st;
> char buf[PATH_MAX];
> int r;
>
> @@ -611,10 +612,23 @@
> &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
> (final_pass ? SSHCONF_FINAL : 0), want_final_pass);
>
> - /* Read systemwide configuration file after user config. */
> - (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
> - host, host_name, &options,
> - final_pass ? SSHCONF_FINAL : 0, want_final_pass);
> + /* If only the vendor configuration file exists, use that.
> + * Else use the standard configuration file.
> + */
> + if (stat(_PATH_HOST_VENDOR_CONFIG_FILE, &st) == 0 &&
> + stat(_PATH_HOST_CONFIG_FILE, &st) == -1) {
> + /* Read vendor distributed configuration file. */
> + (void)read_config_file(_PATH_HOST_VENDOR_CONFIG_FILE,
> + pw, host, host_name, &options,
> + final_pass ? SSHCONF_FINAL : 0,
> + want_final_pass);
> + } else {
> + /* Read systemwide configuration file after user config. */
> + (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
> + host, host_name, &options,
> + final_pass ? SSHCONF_FINAL : 0,
> + want_final_pass);
> + }
> }
> }
>
> diff -urN openssh-8.4p1/sshd.c openssh-8.4p1-vendor/sshd.c
> --- openssh-8.4p1/sshd.c 2020-09-27 09:25:01.000000000 +0200
> +++ openssh-8.4p1-vendor/sshd.c 2021-01-27 18:25:38.370273280 +0100
> @@ -136,7 +136,7 @@
> ServerOptions options;
>
> /* Name of the server configuration file. */
> -char *config_file_name = _PATH_SERVER_CONFIG_FILE;
> +char *config_file_name = NULL;
>
> /*
> * Debug mode flag. This can be set on the command line. If debug
> @@ -1526,6 +1526,7 @@
> int
> main(int ac, char **av)
> {
> + struct stat st;
> struct ssh *ssh = NULL;
> extern char *optarg;
> extern int optind;
> @@ -1737,7 +1738,21 @@
> */
> (void)atomicio(vwrite, startup_pipe, "\0", 1);
> }
> + } else if (config_file_name == NULL) {
> + /* If only the vendor configuration file exists, use that.
> + * Else use the standard configuration file.
> + */
> + if (stat(_PATH_SERVER_VENDOR_CONFIG_FILE, &st) == 0 &&
> + stat(_PATH_SERVER_CONFIG_FILE, &st) == -1) {
> + /* fill with global distributor settings */
> + config_file_name = _PATH_SERVER_VENDOR_CONFIG_FILE;
> + } else {
> + /* load global admin settings */
> + config_file_name = _PATH_SERVER_CONFIG_FILE;
> + }
> + load_server_config(config_file_name, cfg);
> } else if (strcasecmp(config_file_name, "none") != 0)
> + /* load config specified on commandline */
> load_server_config(config_file_name, cfg);
>
> parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
> diff -urN openssh-8.4p1/ssh-keysign.c openssh-8.4p1-vendor/ssh-keysign.c
> --- openssh-8.4p1/ssh-keysign.c 2020-09-27 09:25:01.000000000 +0200
> +++ openssh-8.4p1-vendor/ssh-keysign.c 2021-01-15 15:03:13.258901048 +0100
> @@ -207,6 +207,8 @@
> initialize_options(&options);
> (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "",
> &options, 0, NULL);
> + (void)read_config_file(_PATH_HOST_VENDOR_CONFIG_FILE, pw, "", "",
> + &options, 0, NULL);
> fill_default_options(&options);
> if (options.enable_ssh_keysign != 1)
> fatal("ssh-keysign not enabled in %s",
--
Thorsten Kukuk, Distinguished Engineer, Senior Architect SLES & MicroOS
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nuernberg, Germany
Managing Director: Felix Imendoerffer (HRB 36809, AG Nürnberg)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: openssh-8.4p1-vendordir.patch
Type: text/x-patch
Size: 5970 bytes
Desc: not available
URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20210203/a3485018/attachment-0001.bin>
More information about the openssh-unix-dev
mailing list