diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 07:43:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 07:43:00 +0000 |
commit | c7042a16e2e4aac1030d8785c2c874d6a309b06a (patch) | |
tree | 5cc2a7944ee7d0073ecb2ae03b28fdbc4630a484 /servconf.c | |
parent | Adding upstream version 1:9.7p1. (diff) | |
download | openssh-upstream/1%9.8p1.tar.xz openssh-upstream/1%9.8p1.zip |
Adding upstream version 1:9.8p1.upstream/1%9.8p1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | servconf.c | 283 |
1 files changed, 186 insertions, 97 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.405 2024/03/04 02:16:11 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.411 2024/06/12 22:36:00 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * All rights reserved @@ -69,6 +69,10 @@ #include "myproposal.h" #include "digest.h" +#if !defined(SSHD_PAM_SERVICE) +# define SSHD_PAM_SERVICE "sshd" +#endif + static void add_listen_addr(ServerOptions *, const char *, const char *, int); static void add_one_listen_addr(ServerOptions *, const char *, @@ -77,8 +81,6 @@ static void parse_server_config_depth(ServerOptions *options, const char *filename, struct sshbuf *conf, struct include_list *includes, struct connection_info *connectinfo, int flags, int *activep, int depth); -/* Use of privilege separation or not */ -extern int use_privsep; extern struct sshbuf *cfg; /* Initializes the server options to their default values. */ @@ -90,6 +92,7 @@ initialize_server_options(ServerOptions *options) /* Portable-specific options */ options->use_pam = -1; + options->pam_service_name = NULL; /* Standard Options */ options->num_ports = 0; @@ -165,6 +168,18 @@ initialize_server_options(ServerOptions *options) options->per_source_max_startups = -1; options->per_source_masklen_ipv4 = -1; options->per_source_masklen_ipv6 = -1; + options->per_source_penalty_exempt = NULL; + options->per_source_penalty.enabled = -1; + options->per_source_penalty.max_sources4 = -1; + options->per_source_penalty.max_sources6 = -1; + options->per_source_penalty.overflow_mode = -1; + options->per_source_penalty.overflow_mode6 = -1; + options->per_source_penalty.penalty_crash = -1; + options->per_source_penalty.penalty_authfail = -1; + options->per_source_penalty.penalty_noauth = -1; + options->per_source_penalty.penalty_grace = -1; + options->per_source_penalty.penalty_max = -1; + options->per_source_penalty.penalty_min = -1; options->max_authtries = -1; options->max_sessions = -1; options->banner = NULL; @@ -197,6 +212,7 @@ initialize_server_options(ServerOptions *options) options->channel_timeouts = NULL; options->num_channel_timeouts = 0; options->unused_connection_timeout = -1; + options->sshd_session_path = NULL; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ @@ -280,6 +296,8 @@ fill_default_server_options(ServerOptions *options) /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 0; + if (options->pam_service_name == NULL) + options->pam_service_name = xstrdup(SSHD_PAM_SERVICE); /* Standard Options */ if (options->num_host_key_files == 0) { @@ -403,6 +421,28 @@ fill_default_server_options(ServerOptions *options) options->per_source_masklen_ipv4 = 32; if (options->per_source_masklen_ipv6 == -1) options->per_source_masklen_ipv6 = 128; + if (options->per_source_penalty.enabled == -1) + options->per_source_penalty.enabled = 1; + if (options->per_source_penalty.max_sources4 == -1) + options->per_source_penalty.max_sources4 = 65536; + if (options->per_source_penalty.max_sources6 == -1) + options->per_source_penalty.max_sources6 = 65536; + if (options->per_source_penalty.overflow_mode == -1) + options->per_source_penalty.overflow_mode = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; + if (options->per_source_penalty.overflow_mode6 == -1) + options->per_source_penalty.overflow_mode6 = options->per_source_penalty.overflow_mode; + if (options->per_source_penalty.penalty_crash == -1) + options->per_source_penalty.penalty_crash = 90; + if (options->per_source_penalty.penalty_grace == -1) + options->per_source_penalty.penalty_grace = 20; + if (options->per_source_penalty.penalty_authfail == -1) + options->per_source_penalty.penalty_authfail = 5; + if (options->per_source_penalty.penalty_noauth == -1) + options->per_source_penalty.penalty_noauth = 1; + if (options->per_source_penalty.penalty_min == -1) + options->per_source_penalty.penalty_min = 15; + if (options->per_source_penalty.penalty_max == -1) + options->per_source_penalty.penalty_max = 600; if (options->max_authtries == -1) options->max_authtries = DEFAULT_AUTH_FAIL_MAX; if (options->max_sessions == -1) @@ -447,13 +487,11 @@ fill_default_server_options(ServerOptions *options) options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; if (options->unused_connection_timeout == -1) options->unused_connection_timeout = 0; + if (options->sshd_session_path == NULL) + options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION); assemble_algorithms(options); - /* Turn privilege separation and sandboxing on by default */ - if (use_privsep == -1) - use_privsep = PRIVSEP_ON; - #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ @@ -482,6 +520,7 @@ fill_default_server_options(ServerOptions *options) CLEAR_ON_NONE(options->chroot_directory); CLEAR_ON_NONE(options->routing_domain); CLEAR_ON_NONE(options->host_key_agent); + CLEAR_ON_NONE(options->per_source_penalty_exempt); for (i = 0; i < options->num_host_key_files; i++) CLEAR_ON_NONE(options->host_key_files[i]); @@ -498,7 +537,7 @@ fill_default_server_options(ServerOptions *options) typedef enum { sBadOption, /* == unknown option */ /* Portable-specific options */ - sUsePAM, + sUsePAM, sPAMServiceName, /* Standard Options */ sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, @@ -516,6 +555,7 @@ typedef enum { sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms, sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, + sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sAcceptEnv, sSetEnv, sPermitTunnel, @@ -531,6 +571,7 @@ typedef enum { sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, + sSshdSessionPath, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; @@ -549,8 +590,10 @@ static struct { /* Portable-specific options */ #ifdef USE_PAM { "usepam", sUsePAM, SSHCFG_GLOBAL }, + { "pamservicename", sPAMServiceName, SSHCFG_ALL }, #else { "usepam", sUnsupported, SSHCFG_GLOBAL }, + { "pamservicename", sUnsupported, SSHCFG_ALL }, #endif { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, /* Standard Options */ @@ -647,6 +690,8 @@ static struct { { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL }, { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL }, + { "persourcepenalties", sPerSourcePenalties, SSHCFG_GLOBAL }, + { "persourcepenaltyexemptlist", sPerSourcePenaltyExemptList, SSHCFG_GLOBAL }, { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, { "maxsessions", sMaxSessions, SSHCFG_ALL }, { "banner", sBanner, SSHCFG_ALL }, @@ -693,6 +738,7 @@ static struct { { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, + { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, { NULL, sBadOption, 0 } }; @@ -903,95 +949,6 @@ process_queued_listen_addrs(ServerOptions *options) } /* - * Inform channels layer of permitopen options for a single forwarding - * direction (local/remote). - */ -static void -process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode, - char **opens, u_int num_opens) -{ - u_int i; - int port; - char *host, *arg, *oarg; - int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE; - const char *what = lookup_opcode_name(opcode); - - channel_clear_permission(ssh, FORWARD_ADM, where); - if (num_opens == 0) - return; /* permit any */ - - /* handle keywords: "any" / "none" */ - if (num_opens == 1 && strcmp(opens[0], "any") == 0) - return; - if (num_opens == 1 && strcmp(opens[0], "none") == 0) { - channel_disable_admin(ssh, where); - return; - } - /* Otherwise treat it as a list of permitted host:port */ - for (i = 0; i < num_opens; i++) { - oarg = arg = xstrdup(opens[i]); - host = hpdelim(&arg); - if (host == NULL) - fatal_f("missing host in %s", what); - host = cleanhostname(host); - if (arg == NULL || ((port = permitopen_port(arg)) < 0)) - fatal_f("bad port number in %s", what); - /* Send it to channels layer */ - channel_add_permission(ssh, FORWARD_ADM, - where, host, port); - free(oarg); - } -} - -/* - * Inform channels layer of permitopen options from configuration. - */ -void -process_permitopen(struct ssh *ssh, ServerOptions *options) -{ - process_permitopen_list(ssh, sPermitOpen, - options->permitted_opens, options->num_permitted_opens); - process_permitopen_list(ssh, sPermitListen, - options->permitted_listens, - options->num_permitted_listens); -} - -void -process_channel_timeouts(struct ssh *ssh, ServerOptions *options) -{ - int secs; - u_int i; - char *type; - - debug3_f("setting %u timeouts", options->num_channel_timeouts); - channel_clear_timeouts(ssh); - for (i = 0; i < options->num_channel_timeouts; i++) { - if (parse_pattern_interval(options->channel_timeouts[i], - &type, &secs) != 0) { - fatal_f("internal error: bad timeout %s", - options->channel_timeouts[i]); - } - channel_add_timeout(ssh, type, secs); - free(type); - } -} - -struct connection_info * -get_connection_info(struct ssh *ssh, int populate, int use_dns) -{ - static struct connection_info ci; - - if (ssh == NULL || !populate) - return &ci; - ci.host = auth_get_canonical_hostname(ssh, use_dns); - ci.address = ssh_remote_ipaddr(ssh); - ci.laddress = ssh_local_ipaddr(ssh); - ci.lport = ssh_local_port(ssh); - ci.rdomain = ssh_packet_rdomain_in(ssh); - return &ci; -} - -/* * The strategy for the Match blocks is that the config file is parsed twice. * * The first time is at startup. activep is initialized to 1 and the @@ -1370,6 +1327,16 @@ process_server_config_line_depth(ServerOptions *options, char *line, case sUsePAM: intptr = &options->use_pam; goto parse_flag; + case sPAMServiceName: + charptr = &options->pam_service_name; + arg = argv_next(&ac, &av); + if (!arg || *arg == '\0') { + fatal("%s line %d: missing argument.", + filename, linenum); + } + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; /* Standard Options */ case sBadOption: @@ -2035,6 +2002,100 @@ process_server_config_line_depth(ServerOptions *options, char *line, options->per_source_max_startups = value; break; + case sPerSourcePenaltyExemptList: + charptr = &options->per_source_penalty_exempt; + arg = argv_next(&ac, &av); + if (!arg || *arg == '\0') + fatal("%s line %d: missing argument.", + filename, linenum); + if (addr_match_list(NULL, arg) != 0) { + fatal("%s line %d: keyword %s " + "invalid address argument.", + filename, linenum, keyword); + } + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; + + case sPerSourcePenalties: + while ((arg = argv_next(&ac, &av)) != NULL) { + found = 1; + value = -1; + value2 = 0; + p = NULL; + /* Allow no/yes only in first position */ + if (strcasecmp(arg, "no") == 0 || + (value2 = (strcasecmp(arg, "yes") == 0))) { + if (ac > 0) { + fatal("%s line %d: keyword %s \"%s\" " + "argument must appear alone.", + filename, linenum, keyword, arg); + } + if (*activep && + options->per_source_penalty.enabled == -1) + options->per_source_penalty.enabled = value2; + continue; + } else if (strncmp(arg, "crash:", 6) == 0) { + p = arg + 6; + intptr = &options->per_source_penalty.penalty_crash; + } else if (strncmp(arg, "authfail:", 9) == 0) { + p = arg + 9; + intptr = &options->per_source_penalty.penalty_authfail; + } else if (strncmp(arg, "noauth:", 7) == 0) { + p = arg + 7; + intptr = &options->per_source_penalty.penalty_noauth; + } else if (strncmp(arg, "grace-exceeded:", 15) == 0) { + p = arg + 15; + intptr = &options->per_source_penalty.penalty_grace; + } else if (strncmp(arg, "max:", 4) == 0) { + p = arg + 4; + intptr = &options->per_source_penalty.penalty_max; + } else if (strncmp(arg, "min:", 4) == 0) { + p = arg + 4; + intptr = &options->per_source_penalty.penalty_min; + } else if (strncmp(arg, "max-sources4:", 13) == 0) { + intptr = &options->per_source_penalty.max_sources4; + if ((errstr = atoi_err(arg+13, &value)) != NULL) + fatal("%s line %d: %s value %s.", + filename, linenum, keyword, errstr); + } else if (strncmp(arg, "max-sources6:", 13) == 0) { + intptr = &options->per_source_penalty.max_sources6; + if ((errstr = atoi_err(arg+13, &value)) != NULL) + fatal("%s line %d: %s value %s.", + filename, linenum, keyword, errstr); + } else if (strcmp(arg, "overflow:deny-all") == 0) { + intptr = &options->per_source_penalty.overflow_mode; + value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL; + } else if (strcmp(arg, "overflow:permissive") == 0) { + intptr = &options->per_source_penalty.overflow_mode; + value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; + } else if (strcmp(arg, "overflow6:deny-all") == 0) { + intptr = &options->per_source_penalty.overflow_mode6; + value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL; + } else if (strcmp(arg, "overflow6:permissive") == 0) { + intptr = &options->per_source_penalty.overflow_mode6; + value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; + } else { + fatal("%s line %d: unsupported %s keyword %s", + filename, linenum, keyword, arg); + } + /* If no value was parsed above, assume it's a time */ + if (value == -1 && (value = convtime(p)) == -1) { + fatal("%s line %d: invalid %s time value.", + filename, linenum, keyword); + } + if (*activep && *intptr == -1) { + *intptr = value; + /* any option implicitly enables penalties */ + options->per_source_penalty.enabled = 1; + } + } + if (!found) { + fatal("%s line %d: no %s specified", + filename, linenum, keyword); + } + break; + case sMaxAuthTries: intptr = &options->max_authtries; goto parse_int; @@ -2593,6 +2654,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, } goto parse_time; + case sSshdSessionPath: + charptr = &options->sshd_session_path; + goto parse_filename; + case sDeprecated: case sIgnore: case sUnsupported: @@ -3082,6 +3147,7 @@ dump_config(ServerOptions *o) /* integer arguments */ #ifdef USE_PAM dump_cfg_fmtint(sUsePAM, o->use_pam); + dump_cfg_string(sPAMServiceName, o->pam_service_name); #endif dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); @@ -3167,6 +3233,8 @@ dump_config(ServerOptions *o) #if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN) dump_cfg_string(sRDomain, o->routing_domain); #endif + dump_cfg_string(sSshdSessionPath, o->sshd_session_path); + dump_cfg_string(sPerSourcePenaltyExemptList, o->per_source_penalty_exempt); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); @@ -3254,4 +3322,25 @@ dump_config(ServerOptions *o) if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) printf(" verify-required"); printf("\n"); + + if (o->per_source_penalty.enabled) { + printf("persourcepenalties crash:%d authfail:%d noauth:%d " + "grace-exceeded:%d max:%d min:%d max-sources4:%d " + "max-sources6:%d overflow:%s overflow6:%s\n", + o->per_source_penalty.penalty_crash, + o->per_source_penalty.penalty_authfail, + o->per_source_penalty.penalty_noauth, + o->per_source_penalty.penalty_grace, + o->per_source_penalty.penalty_max, + o->per_source_penalty.penalty_min, + o->per_source_penalty.max_sources4, + o->per_source_penalty.max_sources6, + o->per_source_penalty.overflow_mode == + PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ? + "deny-all" : "permissive", + o->per_source_penalty.overflow_mode6 == + PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ? + "deny-all" : "permissive"); + } else + printf("persourcepenalties no\n"); } |