*/
#include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.112 2002/06/23 09:46:51 deraadt Exp $");
-
-#if defined(KRB4)
-#include <krb.h>
-#endif
-#if defined(KRB5)
-#ifdef HEIMDAL
-#include <krb.h>
-#else
-/* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V
- * keytab */
-#define KEYFILE "/etc/krb5.keytab"
-#endif
-#endif
-#ifdef AFS
-#include <kafs.h>
-#endif
+RCSID("$OpenBSD: servconf.c,v 1.142 2005/06/17 02:44:33 djm Exp $");
#include "ssh.h"
#include "log.h"
#include "xmalloc.h"
#include "compat.h"
#include "pathnames.h"
-#include "tildexpand.h"
#include "misc.h"
#include "cipher.h"
#include "kex.h"
static void add_listen_addr(ServerOptions *, char *, u_short);
static void add_one_listen_addr(ServerOptions *, char *, u_short);
-/* AF_UNSPEC or AF_INET or AF_INET6 */
-extern int IPv4or6;
/* Use of privilege separation or not */
extern int use_privsep;
memset(options, 0, sizeof(*options));
/* Portable-specific options */
- options->pam_authentication_via_kbd_int = -1;
+ options->use_pam = -1;
/* Standard Options */
options->num_ports = 0;
options->ports_from_cmdline = 0;
options->listen_addrs = NULL;
+ options->address_family = -1;
options->num_host_key_files = 0;
options->pid_file = NULL;
options->server_key_bits = -1;
options->x11_use_localhost = -1;
options->xauth_location = NULL;
options->strict_modes = -1;
- options->keepalives = -1;
+ options->tcp_keep_alive = -1;
options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
- options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1;
options->hostbased_authentication = -1;
options->hostbased_uses_name_from_packet_only = -1;
options->rsa_authentication = -1;
options->pubkey_authentication = -1;
-#if defined(KRB4) || defined(KRB5)
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
-#endif
-#if defined(AFS) || defined(KRB5)
- options->kerberos_tgt_passing = -1;
-#endif
-#ifdef AFS
- options->afs_token_passing = -1;
-#endif
+ options->kerberos_get_afs_token = -1;
+ options->gss_authentication=-1;
+ options->gss_cleanup_creds = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
+ options->permit_user_env = -1;
options->use_login = -1;
options->compression = -1;
options->allow_tcp_forwarding = -1;
options->max_startups_begin = -1;
options->max_startups_rate = -1;
options->max_startups = -1;
+ options->max_authtries = -1;
options->banner = NULL;
- options->verify_reverse_mapping = -1;
+ options->use_dns = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
+ options->num_accept_env = 0;
/* Needs to be accessable in many places */
use_privsep = -1;
fill_default_server_options(ServerOptions *options)
{
/* Portable-specific options */
- if (options->pam_authentication_via_kbd_int == -1)
- options->pam_authentication_via_kbd_int = 0;
+ if (options->use_pam == -1)
+ options->use_pam = 0;
/* Standard Options */
if (options->protocol == SSH_PROTO_UNKNOWN)
if (options->server_key_bits == -1)
options->server_key_bits = 768;
if (options->login_grace_time == -1)
- options->login_grace_time = 600;
+ options->login_grace_time = 120;
if (options->key_regeneration_time == -1)
options->key_regeneration_time = 3600;
if (options->permit_root_login == PERMIT_NOT_SET)
options->xauth_location = _PATH_XAUTH;
if (options->strict_modes == -1)
options->strict_modes = 1;
- if (options->keepalives == -1)
- options->keepalives = 1;
+ if (options->tcp_keep_alive == -1)
+ options->tcp_keep_alive = 1;
if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
options->log_facility = SYSLOG_FACILITY_AUTH;
if (options->log_level == SYSLOG_LEVEL_NOT_SET)
options->log_level = SYSLOG_LEVEL_INFO;
- if (options->rhosts_authentication == -1)
- options->rhosts_authentication = 0;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 0;
if (options->hostbased_authentication == -1)
options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
-#if defined(KRB4) || defined(KRB5)
if (options->kerberos_authentication == -1)
options->kerberos_authentication = 0;
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
-#endif
-#if defined(AFS) || defined(KRB5)
- if (options->kerberos_tgt_passing == -1)
- options->kerberos_tgt_passing = 0;
-#endif
-#ifdef AFS
- if (options->afs_token_passing == -1)
- options->afs_token_passing = 0;
-#endif
+ if (options->kerberos_get_afs_token == -1)
+ options->kerberos_get_afs_token = 0;
+ if (options->gss_authentication == -1)
+ options->gss_authentication = 0;
+ if (options->gss_cleanup_creds == -1)
+ options->gss_cleanup_creds = 1;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
options->challenge_response_authentication = 1;
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 0;
+ if (options->permit_user_env == -1)
+ options->permit_user_env = 0;
if (options->use_login == -1)
options->use_login = 0;
if (options->compression == -1)
options->max_startups_rate = 100; /* 100% */
if (options->max_startups_begin == -1)
options->max_startups_begin = options->max_startups;
- if (options->verify_reverse_mapping == -1)
- options->verify_reverse_mapping = 0;
+ if (options->max_authtries == -1)
+ options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
+ if (options->use_dns == -1)
+ options->use_dns = 1;
if (options->client_alive_interval == -1)
options->client_alive_interval = 0;
if (options->client_alive_count_max == -1)
if (use_privsep == -1)
use_privsep = 1;
-#if !defined(HAVE_MMAP_ANON_SHARED)
+#ifndef HAVE_MMAP
if (use_privsep && options->compression == 1) {
error("This platform does not support both privilege "
"separation and compression");
typedef enum {
sBadOption, /* == unknown option */
/* Portable-specific options */
- sPAMAuthenticationViaKbdInt,
+ sUsePAM,
/* Standard Options */
sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
sPermitRootLogin, sLogFacility, sLogLevel,
- sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
-#if defined(KRB4) || defined(KRB5)
+ sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
-#endif
-#if defined(AFS) || defined(KRB5)
- sKerberosTgtPassing,
-#endif
-#ifdef AFS
- sAFSTokenPassing,
-#endif
- sChallengeResponseAuthentication,
- sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
+ sKerberosGetAFSToken,
+ sKerberosTgtPassing, sChallengeResponseAuthentication,
+ sPasswordAuthentication, sKbdInteractiveAuthentication,
+ sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
- sStrictModes, sEmptyPasswd, sKeepAlives,
- sUseLogin, sAllowTcpForwarding, sCompression,
+ sStrictModes, sEmptyPasswd, sTCPKeepAlive,
+ sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
- sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
- sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
+ sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
+ sMaxStartups, sMaxAuthTries,
+ sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
+ sGssAuthentication, sGssCleanupCreds, sAcceptEnv,
sUsePrivilegeSeparation,
- sDeprecated
+ sDeprecated, sUnsupported
} ServerOpCodes;
/* Textual representation of the tokens. */
ServerOpCodes opcode;
} keywords[] = {
/* Portable-specific options */
- { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt },
+#ifdef USE_PAM
+ { "usepam", sUsePAM },
+#else
+ { "usepam", sUnsupported },
+#endif
+ { "pamauthenticationviakbdint", sDeprecated },
/* Standard Options */
{ "port", sPort },
{ "hostkey", sHostKeyFile },
{ "permitrootlogin", sPermitRootLogin },
{ "syslogfacility", sLogFacility },
{ "loglevel", sLogLevel },
- { "rhostsauthentication", sRhostsAuthentication },
+ { "rhostsauthentication", sDeprecated },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
{ "hostbasedauthentication", sHostbasedAuthentication },
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
{ "rsaauthentication", sRSAAuthentication },
{ "pubkeyauthentication", sPubkeyAuthentication },
{ "dsaauthentication", sPubkeyAuthentication }, /* alias */
-#if defined(KRB4) || defined(KRB5)
+#ifdef KRB5
{ "kerberosauthentication", sKerberosAuthentication },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
{ "kerberosticketcleanup", sKerberosTicketCleanup },
+#ifdef USE_AFS
+ { "kerberosgetafstoken", sKerberosGetAFSToken },
+#else
+ { "kerberosgetafstoken", sUnsupported },
#endif
-#if defined(AFS) || defined(KRB5)
- { "kerberostgtpassing", sKerberosTgtPassing },
+#else
+ { "kerberosauthentication", sUnsupported },
+ { "kerberosorlocalpasswd", sUnsupported },
+ { "kerberosticketcleanup", sUnsupported },
+ { "kerberosgetafstoken", sUnsupported },
#endif
-#ifdef AFS
- { "afstokenpassing", sAFSTokenPassing },
+ { "kerberostgtpassing", sUnsupported },
+ { "afstokenpassing", sUnsupported },
+#ifdef GSSAPI
+ { "gssapiauthentication", sGssAuthentication },
+ { "gssapicleanupcredentials", sGssCleanupCreds },
+#else
+ { "gssapiauthentication", sUnsupported },
+ { "gssapicleanupcredentials", sUnsupported },
#endif
{ "passwordauthentication", sPasswordAuthentication },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
{ "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
{ "checkmail", sDeprecated },
{ "listenaddress", sListenAddress },
+ { "addressfamily", sAddressFamily },
{ "printmotd", sPrintMotd },
{ "printlastlog", sPrintLastLog },
{ "ignorerhosts", sIgnoreRhosts },
{ "xauthlocation", sXAuthLocation },
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
+ { "permituserenvironment", sPermitUserEnvironment },
{ "uselogin", sUseLogin },
{ "compression", sCompression },
- { "keepalive", sKeepAlives },
+ { "tcpkeepalive", sTCPKeepAlive },
+ { "keepalive", sTCPKeepAlive }, /* obsolete alias */
{ "allowtcpforwarding", sAllowTcpForwarding },
{ "allowusers", sAllowUsers },
{ "denyusers", sDenyUsers },
{ "gatewayports", sGatewayPorts },
{ "subsystem", sSubsystem },
{ "maxstartups", sMaxStartups },
+ { "maxauthtries", sMaxAuthTries },
{ "banner", sBanner },
- { "verifyreversemapping", sVerifyReverseMapping },
- { "reversemappingcheck", sVerifyReverseMapping },
+ { "usedns", sUseDNS },
+ { "verifyreversemapping", sDeprecated },
+ { "reversemappingcheck", sDeprecated },
{ "clientaliveinterval", sClientAliveInterval },
{ "clientalivecountmax", sClientAliveCountMax },
{ "authorizedkeysfile", sAuthorizedKeysFile },
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
{ "useprivilegeseparation", sUsePrivilegeSeparation},
+ { "acceptenv", sAcceptEnv },
{ NULL, sBadOption }
};
static void
add_listen_addr(ServerOptions *options, char *addr, u_short port)
{
- int i;
+ u_int i;
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+ if (options->address_family == -1)
+ options->address_family = AF_UNSPEC;
if (port == 0)
for (i = 0; i < options->num_ports; i++)
add_one_listen_addr(options, addr, options->ports[i]);
int gaierr;
memset(&hints, 0, sizeof(hints));
- hints.ai_family = IPv4or6;
+ hints.ai_family = options->address_family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
snprintf(strport, sizeof strport, "%u", port);
const char *filename, int linenum)
{
char *cp, **charptr, *arg, *p;
- int *intptr, value, i, n;
+ int *intptr, value, n;
ServerOpCodes opcode;
+ u_short port;
+ u_int i;
cp = line;
arg = strdelim(&cp);
opcode = parse_token(arg, filename, linenum);
switch (opcode) {
/* Portable-specific options */
- case sPAMAuthenticationViaKbdInt:
- intptr = &options->pam_authentication_via_kbd_int;
+ case sUsePAM:
+ intptr = &options->use_pam;
goto parse_flag;
/* Standard Options */
case sListenAddress:
arg = strdelim(&cp);
- if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
- fatal("%s line %d: missing inet addr.",
+ if (arg == NULL || *arg == '\0')
+ fatal("%s line %d: missing address",
filename, linenum);
- if (*arg == '[') {
- if ((p = strchr(arg, ']')) == NULL)
- fatal("%s line %d: bad ipv6 inet addr usage.",
- filename, linenum);
- arg++;
- memmove(p, p+1, strlen(p+1)+1);
- } else if (((p = strchr(arg, ':')) == NULL) ||
- (strchr(p+1, ':') != NULL)) {
- add_listen_addr(options, arg, 0);
- break;
- }
- if (*p == ':') {
- u_short port;
+ p = hpdelim(&arg);
+ if (p == NULL)
+ fatal("%s line %d: bad address:port usage",
+ filename, linenum);
+ p = cleanhostname(p);
+ if (arg == NULL)
+ port = 0;
+ else if ((port = a2port(arg)) == 0)
+ fatal("%s line %d: bad port number", filename, linenum);
- p++;
- if (*p == '\0')
- fatal("%s line %d: bad inet addr:port usage.",
- filename, linenum);
- else {
- *(p-1) = '\0';
- if ((port = a2port(p)) == 0)
- fatal("%s line %d: bad port number.",
- filename, linenum);
- add_listen_addr(options, arg, port);
- }
- } else if (*p == '\0')
- add_listen_addr(options, arg, 0);
- else
- fatal("%s line %d: bad inet addr usage.",
+ add_listen_addr(options, p, port);
+
+ break;
+
+ case sAddressFamily:
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing address family.",
filename, linenum);
+ intptr = &options->address_family;
+ if (options->listen_addrs != NULL)
+ fatal("%s line %d: address family must be specified before "
+ "ListenAddress.", filename, linenum);
+ if (strcasecmp(arg, "inet") == 0)
+ value = AF_INET;
+ else if (strcasecmp(arg, "inet6") == 0)
+ value = AF_INET6;
+ else if (strcasecmp(arg, "any") == 0)
+ value = AF_UNSPEC;
+ else
+ fatal("%s line %d: unsupported address family \"%s\".",
+ filename, linenum, arg);
+ if (*intptr == -1)
+ *intptr = value;
break;
case sHostKeyFile:
intptr = &options->ignore_user_known_hosts;
goto parse_flag;
- case sRhostsAuthentication:
- intptr = &options->rhosts_authentication;
- goto parse_flag;
-
case sRhostsRSAAuthentication:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
-#if defined(KRB4) || defined(KRB5)
+
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
-#endif
-#if defined(AFS) || defined(KRB5)
- case sKerberosTgtPassing:
- intptr = &options->kerberos_tgt_passing;
+
+ case sKerberosGetAFSToken:
+ intptr = &options->kerberos_get_afs_token;
goto parse_flag;
-#endif
-#ifdef AFS
- case sAFSTokenPassing:
- intptr = &options->afs_token_passing;
+
+ case sGssAuthentication:
+ intptr = &options->gss_authentication;
+ goto parse_flag;
+
+ case sGssCleanupCreds:
+ intptr = &options->gss_cleanup_creds;
goto parse_flag;
-#endif
case sPasswordAuthentication:
intptr = &options->password_authentication;
intptr = &options->strict_modes;
goto parse_flag;
- case sKeepAlives:
- intptr = &options->keepalives;
+ case sTCPKeepAlive:
+ intptr = &options->tcp_keep_alive;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
+ case sPermitUserEnvironment:
+ intptr = &options->permit_user_env;
+ goto parse_flag;
+
case sUseLogin:
intptr = &options->use_login;
goto parse_flag;
case sGatewayPorts:
intptr = &options->gateway_ports;
- goto parse_flag;
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing yes/no/clientspecified "
+ "argument.", filename, linenum);
+ value = 0; /* silence compiler */
+ if (strcmp(arg, "clientspecified") == 0)
+ value = 2;
+ else if (strcmp(arg, "yes") == 0)
+ value = 1;
+ else if (strcmp(arg, "no") == 0)
+ value = 0;
+ else
+ fatal("%s line %d: Bad yes/no/clientspecified "
+ "argument: %s", filename, linenum, arg);
+ if (*intptr == -1)
+ *intptr = value;
+ break;
- case sVerifyReverseMapping:
- intptr = &options->verify_reverse_mapping;
+ case sUseDNS:
+ intptr = &options->use_dns;
goto parse_flag;
case sLogFacility:
options->max_startups = options->max_startups_begin;
break;
+ case sMaxAuthTries:
+ intptr = &options->max_authtries;
+ goto parse_int;
+
case sBanner:
charptr = &options->banner;
goto parse_filename;
intptr = &options->client_alive_count_max;
goto parse_int;
+ case sAcceptEnv:
+ while ((arg = strdelim(&cp)) && *arg != '\0') {
+ if (strchr(arg, '=') != NULL)
+ fatal("%s line %d: Invalid environment name.",
+ filename, linenum);
+ if (options->num_accept_env >= MAX_ACCEPT_ENV)
+ fatal("%s line %d: too many allow env.",
+ filename, linenum);
+ options->accept_env[options->num_accept_env++] =
+ xstrdup(arg);
+ }
+ break;
+
case sDeprecated:
- log("%s line %d: Deprecated option %s",
+ logit("%s line %d: Deprecated option %s",
+ filename, linenum, arg);
+ while (arg)
+ arg = strdelim(&cp);
+ break;
+
+ case sUnsupported:
+ logit("%s line %d: Unsupported option %s",
filename, linenum, arg);
while (arg)
arg = strdelim(&cp);
/* Reads the server configuration file. */
void
-read_server_config(ServerOptions *options, const char *filename)
+load_server_config(const char *filename, Buffer *conf)
{
- int linenum, bad_options = 0;
- char line[1024];
+ char line[1024], *cp;
FILE *f;
- f = fopen(filename, "r");
- if (!f) {
+ debug2("%s: filename %s", __func__, filename);
+ if ((f = fopen(filename, "r")) == NULL) {
perror(filename);
exit(1);
}
- linenum = 0;
+ buffer_clear(conf);
while (fgets(line, sizeof(line), f)) {
- /* Update line number counter. */
- linenum++;
- if (process_server_config_line(options, line, filename, linenum) != 0)
- bad_options++;
+ /*
+ * Trim out comments and strip whitespace
+ * NB - preserve newlines, they are needed to reproduce
+ * line numbers later for error messages
+ */
+ if ((cp = strchr(line, '#')) != NULL)
+ memcpy(cp, "\n", 2);
+ cp = line + strspn(line, " \t\r");
+
+ buffer_append(conf, cp, strlen(cp));
}
+ buffer_append(conf, "\0", 1);
fclose(f);
+ debug2("%s: done config len = %d", __func__, buffer_len(conf));
+}
+
+void
+parse_server_config(ServerOptions *options, const char *filename, Buffer *conf)
+{
+ int linenum, bad_options = 0;
+ char *cp, *obuf, *cbuf;
+
+ debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
+
+ obuf = cbuf = xstrdup(buffer_ptr(conf));
+ linenum = 1;
+ while ((cp = strsep(&cbuf, "\n")) != NULL) {
+ if (process_server_config_line(options, cp, filename,
+ linenum++) != 0)
+ bad_options++;
+ }
+ xfree(obuf);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
filename, bad_options);