Patch: Ciphers, MACs and KexAlgorithms on Match
Armin Wolfermann
aw at osn.de
Mon Jun 9 02:15:29 EST 2014
* Darren Tucker <dtucker at zip.com.au> [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
More information about the openssh-unix-dev
mailing list