Hello all. I wrote this small patch that allows having multiple tags on a configuration block in the openssh client configuration. For instance, with this configuration: > Host test-host > Tag change-hostname change-port-and-user > Tag jump-to-mybox > > Match tagged change-hostname > Hostname new-hostname > > Match tagged change-port-and-user > Port 12345 > Tag change-user > > Match tagged change-user > User bilbo > > Match tagged jump-to-mybox > ProxyJump mybox > > Match tagged nocheck > StrictHostKeyChecking false > UserKnownHostsFile /dev/null > > Match tagged frodo-identity > IdentityFile ~/.ssh/id_ed25519_frodo the following parameters can be obtained: > gandalf@mybox $ ssh -P nocheck -P frodo-identity test-host -G | > > grep -E "^(user|hostname|port|strictho stkeychecking|identityfile|` > > `userknownhostsfile|tag|proxyjump) " > user bilbo > hostname new-hostname > port 12345 > stricthostkeychecking false > identityfile ~/.ssh/id_ed25519_frodo > userknownhostsfile /dev/null > tag nocheck > tag frodo-identity > tag change-hostname > tag change-port-and-user > tag jump-to-mybox > tag change-user > proxyjump mybox > gandalf@mybox $ Obviously, this is just an example of use, and such brief match blocks are not useful in real cases. The example is only meant to demonstrate the potential of the modification. In the example, I also added multiple tags from the command line with the `-P` option. I believe this change is very convenient for having a sort of multiple inheritance in configuration files. I hope you find it interesting. Regards -- vincenzo
From bc6b9aac3b68f214665b7522851b659f87929a00 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo <kurganme@xxxxxxxxx> Date: Thu, 2 Jan 2025 14:14:18 +0100 Subject: [PATCH] Make it possible to have multiple tags on a configuration block. --- readconf.c | 29 +++++++++++++++++++++++------ readconf.h | 3 ++- ssh.c | 7 +++++-- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/readconf.c b/readconf.c index 3d9cc6dbb..83c90ab80 100644 --- a/readconf.c +++ b/readconf.c @@ -712,6 +712,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, { char *arg, *oattrib, *attrib, *cmd, *host, *criteria; const char *ruser; + u_int i; int r, this_result, result = 1, attributes = 0, negate; /* @@ -814,9 +815,16 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "tagged") == 0) { - criteria = xstrdup(options->tag == NULL ? "" : - options->tag); - r = match_pattern_list(criteria, arg, 0) == 1; + criteria = xstrdup(arg); + r = 0; + for (i = 0; i < options->num_tag; i++) { + r = match_pattern_list( + options->tag[i], arg, 0) == 1; + debug3("%.200s line %d: match test for tag " + "\"%.100s\" in \"%.200s\": %d", + filename, linenum, options->tag[i], arg, r); + if (r) break; + } if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "exec") == 0) { @@ -1432,8 +1440,14 @@ parse_char_array: goto parse_string; case oTag: - charptr = &options->tag; - goto parse_string; + while ((arg = argv_next(&ac, &av)) != NULL) { + if (*activep) { + opt_array_append(filename, linenum, + lookup_opcode_name(opcode), + &options->tag, &options->num_tag, arg); + } + } + break; case oHostKeyAlias: charptr = &options->host_key_alias; @@ -2676,6 +2690,7 @@ initialize_options(Options * options) options->enable_escape_commandline = -1; options->obscure_keystroke_timing_interval = -1; options->tag = NULL; + options->num_tag = 0; options->channel_timeouts = NULL; options->num_channel_timeouts = 0; } @@ -3056,6 +3071,8 @@ free_options(Options *o) free(o->jump_host); free(o->jump_extra); free(o->ignored_unknown); + FREE_ARRAY(u_int, o->num_tag, o->tag); + free(o->tag); explicit_bzero(o, sizeof(*o)); #undef FREE_ARRAY } @@ -3628,7 +3645,6 @@ dump_client_config(Options *o, const char *host) dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); dump_cfg_string(oXAuthLocation, o->xauth_location); dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); - dump_cfg_string(oTag, o->tag); /* Forwards */ dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); @@ -3647,6 +3663,7 @@ dump_client_config(Options *o, const char *host) o->num_log_verbose, o->log_verbose); dump_cfg_strarray_oneline(oChannelTimeout, o->num_channel_timeouts, o->channel_timeouts); + dump_cfg_strarray(oTag, o->num_tag, o->tag); /* Special cases */ diff --git a/readconf.h b/readconf.h index 9447d5d6e..efa2c88d7 100644 --- a/readconf.h +++ b/readconf.h @@ -70,7 +70,8 @@ typedef struct { char *kex_algorithms; /* SSH2 kex methods in order of preference. */ char *ca_sign_algorithms; /* Allowed CA signature algorithms */ char *hostname; /* Real host to connect. */ - char *tag; /* Configuration tag name. */ + u_int num_tag; /* Configuration tag names. */ + char **tag; char *host_key_alias; /* hostname alias for .ssh/known_hosts */ char *proxy_command; /* Proxy command for connecting the host. */ char *user; /* User to log in as. */ diff --git a/ssh.c b/ssh.c index 0019281f4..6e0c3c397 100644 --- a/ssh.c +++ b/ssh.c @@ -811,8 +811,11 @@ main(int ac, char **av) fatal("Invalid multiplex command."); break; case 'P': - if (options.tag == NULL) - options.tag = xstrdup(optarg); + options.tag = xrecallocarray(options.tag, + options.num_tag, options.num_tag + 1, + sizeof(*options.tag)); + options.tag[options.num_tag] = xstrdup(optarg); + options.num_tag++; break; case 'Q': cp = NULL; -- 2.47.1
_______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev