* Darren Tucker <dtucker@xxxxxxxxxx> [08.06.2014 16:56]: > (although I'd call it "Implementation" or some other neutral name so the > same keyword could be used on both client and server). I called it "Version" (the RFC calls it softwareversion) and prepared a rough patch that handles my use case with: Match Version TrileadSSH2Java_213 Ciphers aes128-cbc MACs hmac-sha1 KexAlgorithms diffie-hellman-group-exchange-sha1 If there is enough interest I will polish it up and resubmit later. Index: servconf.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/servconf.c,v retrieving revision 1.249 diff -u -p -u -r1.249 servconf.c --- servconf.c 29 Jan 2014 06:18:35 -0000 1.249 +++ servconf.c 8 Jun 2014 15:58:36 -0000 @@ -57,6 +57,7 @@ static void add_one_listen_addr(ServerOp /* Use of privilege separation or not */ extern int use_privsep; extern Buffer cfg; +extern char *remote_version_string; /* Initializes the server options to their default values. */ @@ -399,8 +400,8 @@ static struct { { "denyusers", sDenyUsers, SSHCFG_ALL }, { "allowgroups", sAllowGroups, SSHCFG_ALL }, { "denygroups", sDenyGroups, SSHCFG_ALL }, - { "ciphers", sCiphers, SSHCFG_GLOBAL }, - { "macs", sMacs, SSHCFG_GLOBAL }, + { "ciphers", sCiphers, SSHCFG_ALL }, + { "macs", sMacs, SSHCFG_ALL }, { "protocol", sProtocol, SSHCFG_GLOBAL }, { "gatewayports", sGatewayPorts, SSHCFG_ALL }, { "subsystem", sSubsystem, SSHCFG_GLOBAL }, @@ -415,7 +416,7 @@ static struct { { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, - { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, + { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, { "acceptenv", sAcceptEnv, SSHCFG_ALL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, { "permittty", sPermitTTY, SSHCFG_ALL }, @@ -427,7 +428,7 @@ static struct { { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, - { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, + { "kexalgorithms", sKexAlgorithms, SSHCFG_ALL }, { "ipqos", sIPQoS, SSHCFG_ALL }, { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, @@ -532,6 +533,7 @@ get_connection_info(int populate, int us ci.address = get_remote_ipaddr(); ci.laddress = get_local_ipaddr(packet_get_connection_in()); ci.lport = get_local_port(); + ci.version = remote_version_string; return &ci; } @@ -612,10 +614,13 @@ match_cfg_line(char **condition, int lin debug3("checking syntax for 'Match %s'", cp); else debug3("checking match for '%s' user %s host %s addr %s " - "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", + "laddr %s lport %d version '%s'", cp, + ci->user ? ci->user : "(null)", ci->host ? ci->host : "(null)", ci->address ? ci->address : "(null)", - ci->laddress ? ci->laddress : "(null)", ci->lport); + ci->laddress ? ci->laddress : "(null)", + ci->lport, + ci->version ? ci->version : "(null)"); while ((attrib = strdelim(&cp)) && *attrib != '\0') { attributes++; @@ -717,6 +722,16 @@ match_cfg_line(char **condition, int lin ci->laddress, port, line); else result = 0; + } else if (strcasecmp(attrib, "version") == 0) { + if (ci == NULL || ci->version == NULL) { + result = 0; + continue; + } + if (strcasecmp(ci->version, arg) != 0) + result = 0; + else + debug("connection from %.100s matched 'Version " + "%.100s' at line %d", ci->version, arg, line); } else { error("Unsupported Match attribute %s", attrib); return -1; @@ -1239,7 +1254,7 @@ process_server_config_line(ServerOptions if (!ciphers_valid(arg)) fatal("%s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : "<NONE>"); - if (options->ciphers == NULL) + if (*activep && options->ciphers == NULL) options->ciphers = xstrdup(arg); break; @@ -1250,7 +1265,7 @@ process_server_config_line(ServerOptions if (!mac_valid(arg)) fatal("%s line %d: Bad SSH2 mac spec '%s'.", filename, linenum, arg ? arg : "<NONE>"); - if (options->macs == NULL) + if (*activep && options->macs == NULL) options->macs = xstrdup(arg); break; @@ -1262,7 +1277,7 @@ process_server_config_line(ServerOptions if (!kex_names_valid(arg)) fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : "<NONE>"); - if (options->kex_algorithms == NULL) + if (*activep && options->kex_algorithms == NULL) options->kex_algorithms = xstrdup(arg); break; @@ -1663,6 +1678,8 @@ int parse_server_match_testspec(struct c " specification %s\n", p+6, p); return -1; } + } else if (strncmp(p, "version=", 8) == 0) { + ci->version = xstrdup(p + 8); } else { fprintf(stderr, "Invalid test mode specification %s\n", p); Index: servconf.h =================================================================== RCS file: /cvs/src/usr.bin/ssh/servconf.h,v retrieving revision 1.112 diff -u -p -u -r1.112 servconf.h --- servconf.h 29 Jan 2014 06:18:35 -0000 1.112 +++ servconf.h 8 Jun 2014 15:58:36 -0000 @@ -190,6 +190,7 @@ struct connection_info { const char *address; /* remote address */ const char *laddress; /* local address */ int lport; /* local port */ + const char *version; /* remote version string */ }; @@ -209,6 +210,9 @@ struct connection_info { M_CP_STROPT(authorized_principals_file); \ M_CP_STROPT(authorized_keys_command); \ M_CP_STROPT(authorized_keys_command_user); \ + M_CP_STROPT(ciphers); \ + M_CP_STROPT(macs); \ + M_CP_STROPT(kex_algorithms); \ M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ M_CP_STRARRAYOPT(allow_users, num_allow_users); \ M_CP_STRARRAYOPT(deny_users, num_deny_users); \ Index: sshd.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/sshd.c,v retrieving revision 1.426 diff -u -p -u -r1.426 sshd.c --- sshd.c 29 Apr 2014 18:01:49 -0000 1.426 +++ sshd.c 8 Jun 2014 15:58:36 -0000 @@ -166,6 +166,7 @@ int num_listen_socks = 0; */ char *client_version_string = NULL; char *server_version_string = NULL; +char *remote_version_string = NULL; /* for rekeying XXX fixme */ Kex *xxx_kex; @@ -460,6 +461,7 @@ sshd_exchange_identification(int sock_in close(sock_out); cleanup_exit(255); } + remote_version_string = xstrdup(remote_version); debug("Client protocol version %d.%d; client software version %.100s", remote_major, remote_minor, remote_version); @@ -1933,6 +1935,10 @@ main(int ac, char **av) alarm(options.login_grace_time); sshd_exchange_identification(sock_in, sock_out); + + /* Match configuration against the connection */ + connection_info = get_connection_info(1, options.use_dns); + parse_server_match_config(&options, connection_info); /* In inetd mode, generate ephemeral key only for proto 1 connections */ if (!compat20 && inetd_flag && sensitive_data.server_key == NULL) Regards, Armin Wolfermann _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev