From 00f3582ac62b9883e85e2cb420c3d9f5d9028188 Mon Sep 17 00:00:00 2001 From: des Date: Mon, 3 Sep 2012 16:51:41 +0000 Subject: Upgrade OpenSSH to 6.1p1. --- crypto/openssh/servconf.c | 266 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 204 insertions(+), 62 deletions(-) (limited to 'crypto/openssh/servconf.c') diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 0b7395b..2664880 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -1,4 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */ + +/* $OpenBSD: servconf.c,v 1.229 2012/07/13 01:35:21 dtucker Exp $ */ /* $FreeBSD$ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -47,6 +48,8 @@ __RCSID("$FreeBSD$"); #include "match.h" #include "channels.h" #include "groupaccess.h" +#include "canohost.h" +#include "packet.h" #include "version.h" static void add_listen_addr(ServerOptions *, char *, int); @@ -141,6 +144,7 @@ initialize_server_options(ServerOptions *options) options->authorized_principals_file = NULL; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; + options->version_addendum = NULL; options->hpn_disabled = -1; options->hpn_buffer_size = -1; options->tcp_rcv_buf_poll = -1; @@ -286,6 +290,21 @@ fill_default_server_options(ServerOptions *options) options->ip_qos_interactive = IPTOS_LOWDELAY; if (options->ip_qos_bulk == -1) options->ip_qos_bulk = IPTOS_THROUGHPUT; + if (options->version_addendum == NULL) + options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); + /* Turn privilege separation on by default */ + if (use_privsep == -1) + use_privsep = PRIVSEP_ON; + +#ifndef HAVE_MMAP + if (use_privsep && options->compression == 1) { + error("This platform does not support both privilege " + "separation and compression"); + error("Compression disabled"); + options->compression = 0; + } +#endif + if (options->hpn_disabled == -1) options->hpn_disabled = 0; if (options->hpn_buffer_size == -1) { @@ -314,23 +333,10 @@ fill_default_server_options(ServerOptions *options) options->hpn_buffer_size = maxlen; else options->hpn_buffer_size *= 1024; - } else + } else { options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; + } } - - /* Turn privilege separation on by default */ - if (use_privsep == -1) - use_privsep = PRIVSEP_ON; - -#ifndef HAVE_MMAP - if (use_privsep && options->compression == 1) { - error("This platform does not support both privilege " - "separation and compression"); - error("Compression disabled"); - options->compression = 0; - } -#endif - } /* Keyword tokens. */ @@ -363,12 +369,11 @@ typedef enum { sUsePrivilegeSeparation, sAllowAgentForwarding, sZeroKnowledgePasswordAuthentication, sHostCertificate, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, - sKexAlgorithms, sIPQoS, + sKexAlgorithms, sIPQoS, sVersionAddendum, sHPNDisabled, sHPNBufferSize, sTcpRcvBufPoll, #ifdef NONE_CIPHER_ENABLED sNoneEnabled, #endif - sVersionAddendum, sDeprecated, sUnsupported } ServerOpCodes; @@ -460,10 +465,10 @@ static struct { { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, - { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, - { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, - { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, - { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, + { "allowusers", sAllowUsers, SSHCFG_ALL }, + { "denyusers", sDenyUsers, SSHCFG_ALL }, + { "allowgroups", sAllowGroups, SSHCFG_ALL }, + { "denygroups", sDenyGroups, SSHCFG_ALL }, { "ciphers", sCiphers, SSHCFG_GLOBAL }, { "macs", sMacs, SSHCFG_GLOBAL }, { "protocol", sProtocol, SSHCFG_GLOBAL }, @@ -481,7 +486,7 @@ static struct { { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, - { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, + { "acceptenv", sAcceptEnv, SSHCFG_ALL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, { "match", sMatch, SSHCFG_ALL }, { "permitopen", sPermitOpen, SSHCFG_ALL }, @@ -493,13 +498,14 @@ static struct { { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, { "ipqos", sIPQoS, SSHCFG_ALL }, + { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, + { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, { "hpndisabled", sHPNDisabled, SSHCFG_ALL }, { "hpnbuffersize", sHPNBufferSize, SSHCFG_ALL }, { "tcprcvbufpoll", sTcpRcvBufPoll, SSHCFG_ALL }, #ifdef NONE_CIPHER_ENABLED { "noneenabled", sNoneEnabled, SSHCFG_ALL }, #endif - { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, { NULL, sBadOption, 0 } }; @@ -588,6 +594,20 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) options->listen_addrs = aitop; } +struct connection_info * +get_connection_info(int populate, int use_dns) +{ + static struct connection_info ci; + + if (!populate) + return &ci; + ci.host = get_canonical_hostname(use_dns); + ci.address = get_remote_ipaddr(); + ci.laddress = get_local_ipaddr(packet_get_connection_in()); + ci.lport = get_local_port(); + return &ci; +} + /* * The strategy for the Match blocks is that the config file is parsed twice. * @@ -649,20 +669,25 @@ out: return result; } +/* + * All of the attributes on a single Match line are ANDed together, so we need to check every + * attribute and set the result to zero if any attribute does not match. + */ static int -match_cfg_line(char **condition, int line, const char *user, const char *host, - const char *address) +match_cfg_line(char **condition, int line, struct connection_info *ci) { - int result = 1; + int result = 1, port; char *arg, *attrib, *cp = *condition; size_t len; - if (user == NULL) + if (ci == NULL) debug3("checking syntax for 'Match %s'", cp); else - debug3("checking match for '%s' user %s host %s addr %s", cp, - user ? user : "(null)", host ? host : "(null)", - address ? address : "(null)"); + debug3("checking match for '%s' user %s host %s addr %s " + "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", + ci->host ? ci->host : "(null)", + ci->address ? ci->address : "(null)", + ci->laddress ? ci->laddress : "(null)", ci->lport); while ((attrib = strdelim(&cp)) && *attrib != '\0') { if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { @@ -671,37 +696,45 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, } len = strlen(arg); if (strcasecmp(attrib, "user") == 0) { - if (!user) { + if (ci == NULL || ci->user == NULL) { result = 0; continue; } - if (match_pattern_list(user, arg, len, 0) != 1) + if (match_pattern_list(ci->user, arg, len, 0) != 1) result = 0; else debug("user %.100s matched 'User %.100s' at " - "line %d", user, arg, line); + "line %d", ci->user, arg, line); } else if (strcasecmp(attrib, "group") == 0) { - switch (match_cfg_line_group(arg, line, user)) { + if (ci == NULL || ci->user == NULL) { + result = 0; + continue; + } + switch (match_cfg_line_group(arg, line, ci->user)) { case -1: return -1; case 0: result = 0; } } else if (strcasecmp(attrib, "host") == 0) { - if (!host) { + if (ci == NULL || ci->host == NULL) { result = 0; continue; } - if (match_hostname(host, arg, len) != 1) + if (match_hostname(ci->host, arg, len) != 1) result = 0; else debug("connection from %.100s matched 'Host " - "%.100s' at line %d", host, arg, line); + "%.100s' at line %d", ci->host, arg, line); } else if (strcasecmp(attrib, "address") == 0) { - switch (addr_match_list(address, arg)) { + if (ci == NULL || ci->address == NULL) { + result = 0; + continue; + } + switch (addr_match_list(ci->address, arg)) { case 1: debug("connection from %.100s matched 'Address " - "%.100s' at line %d", address, arg, line); + "%.100s' at line %d", ci->address, arg, line); break; case 0: case -1: @@ -710,12 +743,47 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, case -2: return -1; } + } else if (strcasecmp(attrib, "localaddress") == 0){ + if (ci == NULL || ci->laddress == NULL) { + result = 0; + continue; + } + switch (addr_match_list(ci->laddress, arg)) { + case 1: + debug("connection from %.100s matched " + "'LocalAddress %.100s' at line %d", + ci->laddress, arg, line); + break; + case 0: + case -1: + result = 0; + break; + case -2: + return -1; + } + } else if (strcasecmp(attrib, "localport") == 0) { + if ((port = a2port(arg)) == -1) { + error("Invalid LocalPort '%s' on Match line", + arg); + return -1; + } + if (ci == NULL || ci->lport == 0) { + result = 0; + continue; + } + /* TODO support port lists */ + if (port == ci->lport) + debug("connection from %.100s matched " + "'LocalPort %d' at line %d", + ci->laddress, port, line); + else + result = 0; } else { error("Unsupported Match attribute %s", attrib); return -1; } } - if (user != NULL) + if (ci != NULL) debug3("match %sfound", result ? "" : "not "); *condition = cp; return result; @@ -754,16 +822,17 @@ static const struct multistate multistate_gatewayports[] = { { NULL, -1 } }; static const struct multistate multistate_privsep[] = { - { "sandbox", PRIVSEP_SANDBOX }, - { "yes", PRIVSEP_ON }, + { "yes", PRIVSEP_NOSANDBOX }, + { "sandbox", PRIVSEP_ON }, + { "nosandbox", PRIVSEP_NOSANDBOX }, { "no", PRIVSEP_OFF }, { NULL, -1 } }; int process_server_config_line(ServerOptions *options, char *line, - const char *filename, int linenum, int *activep, const char *user, - const char *host, const char *address) + const char *filename, int linenum, int *activep, + struct connection_info *connectinfo) { char *cp, **charptr, *arg, *p; int cmdline = 0, *intptr, value, value2, n; @@ -794,7 +863,7 @@ process_server_config_line(ServerOptions *options, char *line, if (*activep && opcode != sMatch) debug3("%s:%d setting %s %s", filename, linenum, arg, cp); if (*activep == 0 && !(flags & SSHCFG_MATCH)) { - if (user == NULL) { + if (connectinfo == NULL) { fatal("%s line %d: Directive '%s' is not allowed " "within a Match block", filename, linenum, arg); } else { /* this is a directive we have already processed */ @@ -1132,6 +1201,8 @@ process_server_config_line(ServerOptions *options, char *line, if (options->num_allow_users >= MAX_ALLOW_USERS) fatal("%s line %d: too many allow users.", filename, linenum); + if (!*activep) + continue; options->allow_users[options->num_allow_users++] = xstrdup(arg); } @@ -1142,6 +1213,8 @@ process_server_config_line(ServerOptions *options, char *line, if (options->num_deny_users >= MAX_DENY_USERS) fatal("%s line %d: too many deny users.", filename, linenum); + if (!*activep) + continue; options->deny_users[options->num_deny_users++] = xstrdup(arg); } @@ -1152,6 +1225,8 @@ process_server_config_line(ServerOptions *options, char *line, if (options->num_allow_groups >= MAX_ALLOW_GROUPS) fatal("%s line %d: too many allow groups.", filename, linenum); + if (!*activep) + continue; options->allow_groups[options->num_allow_groups++] = xstrdup(arg); } @@ -1162,7 +1237,10 @@ process_server_config_line(ServerOptions *options, char *line, if (options->num_deny_groups >= MAX_DENY_GROUPS) fatal("%s line %d: too many deny groups.", filename, linenum); - options->deny_groups[options->num_deny_groups++] = xstrdup(arg); + if (!*activep) + continue; + options->deny_groups[options->num_deny_groups++] = + xstrdup(arg); } break; @@ -1336,7 +1414,7 @@ process_server_config_line(ServerOptions *options, char *line, fatal("%s line %d: too many allow env.", filename, linenum); if (!*activep) - break; + continue; options->accept_env[options->num_accept_env++] = xstrdup(arg); } @@ -1365,7 +1443,7 @@ process_server_config_line(ServerOptions *options, char *line, if (cmdline) fatal("Match directive not supported as a command-line " "option"); - value = match_cfg_line(&cp, linenum, user, host, address); + value = match_cfg_line(&cp, linenum, connectinfo); if (value < 0) fatal("%s line %d: Bad Match condition", filename, linenum); @@ -1385,6 +1463,14 @@ process_server_config_line(ServerOptions *options, char *line, } break; } + if (strcmp(arg, "none") == 0) { + if (*activep && n == -1) { + channel_clear_adm_permitted_opens(); + options->num_permitted_opens = 1; + channel_disable_adm_local_opens(); + } + break; + } if (*activep && n == -1) channel_clear_adm_permitted_opens(); for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { @@ -1393,7 +1479,7 @@ process_server_config_line(ServerOptions *options, char *line, fatal("%s line %d: missing host in PermitOpen", filename, linenum); p = cleanhostname(p); - if (arg == NULL || (port = a2port(arg)) <= 0) + if (arg == NULL || ((port = permitopen_port(arg)) < 0)) fatal("%s line %d: bad port number in " "PermitOpen", filename, linenum); if (*activep && n == -1) @@ -1448,11 +1534,20 @@ process_server_config_line(ServerOptions *options, char *line, break; case sVersionAddendum: - ssh_version_set_addendum(strtok(cp, "\n")); - do { - arg = strdelim(&cp); - } while (arg != NULL && *arg != '\0'); - break; + if (cp == NULL) + fatal("%.200s line %d: Missing argument.", filename, + linenum); + len = strspn(cp, WHITESPACE); + if (*activep && options->version_addendum == NULL) { + if (strcasecmp(cp + len, "none") == 0) + options->version_addendum = xstrdup(""); + else if (strchr(cp + len, '\r') != NULL) + fatal("%.200s line %d: Invalid argument", + filename, linenum); + else + options->version_addendum = xstrdup(cp + len); + } + return 0; case sHPNDisabled: intptr = &options->hpn_disabled; @@ -1501,8 +1596,9 @@ process_server_config_line(ServerOptions *options, char *line, void load_server_config(const char *filename, Buffer *conf) { - char line[1024], *cp; + char line[4096], *cp; FILE *f; + int lineno = 0; debug2("%s: filename %s", __func__, filename); if ((f = fopen(filename, "r")) == NULL) { @@ -1511,6 +1607,9 @@ load_server_config(const char *filename, Buffer *conf) } buffer_clear(conf); while (fgets(line, sizeof(line), f)) { + lineno++; + if (strlen(line) == sizeof(line) - 1) + fatal("%s line %d too long", filename, lineno); /* * Trim out comments and strip whitespace * NB - preserve newlines, they are needed to reproduce @@ -1528,16 +1627,58 @@ load_server_config(const char *filename, Buffer *conf) } void -parse_server_match_config(ServerOptions *options, const char *user, - const char *host, const char *address) +parse_server_match_config(ServerOptions *options, + struct connection_info *connectinfo) { ServerOptions mo; initialize_server_options(&mo); - parse_server_config(&mo, "reprocess config", &cfg, user, host, address); + parse_server_config(&mo, "reprocess config", &cfg, connectinfo); copy_set_server_options(options, &mo, 0); } +int parse_server_match_testspec(struct connection_info *ci, char *spec) +{ + char *p; + + while ((p = strsep(&spec, ",")) && *p != '\0') { + if (strncmp(p, "addr=", 5) == 0) { + ci->address = xstrdup(p + 5); + } else if (strncmp(p, "host=", 5) == 0) { + ci->host = xstrdup(p + 5); + } else if (strncmp(p, "user=", 5) == 0) { + ci->user = xstrdup(p + 5); + } else if (strncmp(p, "laddr=", 6) == 0) { + ci->laddress = xstrdup(p + 6); + } else if (strncmp(p, "lport=", 6) == 0) { + ci->lport = a2port(p + 6); + if (ci->lport == -1) { + fprintf(stderr, "Invalid port '%s' in test mode" + " specification %s\n", p+6, p); + return -1; + } + } else { + fprintf(stderr, "Invalid test mode specification %s\n", + p); + return -1; + } + } + return 0; +} + +/* + * returns 1 for a complete spec, 0 for partial spec and -1 for an + * empty spec. + */ +int server_match_spec_complete(struct connection_info *ci) +{ + if (ci->user && ci->host && ci->address) + return 1; /* complete */ + if (!ci->user && !ci->host && !ci->address) + return -1; /* empty */ + return 0; /* partial */ +} + /* Helper macros */ #define M_CP_INTOPT(n) do {\ if (src->n != -1) \ @@ -1611,7 +1752,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) void parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, - const char *user, const char *host, const char *address) + struct connection_info *connectinfo) { int active, linenum, bad_options = 0; char *cp, *obuf, *cbuf; @@ -1619,11 +1760,11 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); obuf = cbuf = xstrdup(buffer_ptr(conf)); - active = user ? 0 : 1; + active = connectinfo ? 0 : 1; linenum = 1; while ((cp = strsep(&cbuf, "\n")) != NULL) { if (process_server_config_line(options, cp, filename, - linenum++, &active, user, host, address) != 0) + linenum++, &active, connectinfo) != 0) bad_options++; } xfree(obuf); @@ -1835,6 +1976,7 @@ dump_config(ServerOptions *o) dump_cfg_string(sRevokedKeys, o->revoked_keys_file); dump_cfg_string(sAuthorizedPrincipalsFile, o->authorized_principals_file); + dump_cfg_string(sVersionAddendum, o->version_addendum); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); -- cgit v1.1