1240075Sdes 2323124Sdes/* $OpenBSD: servconf.c,v 1.292 2016/06/23 05:17:51 djm Exp $ */ 357429Smarkm/* 457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 557429Smarkm * All rights reserved 660576Skris * 765674Skris * As far as I am concerned, the code I have written for this software 865674Skris * can be used freely for any purpose. Any derived versions of this 965674Skris * software must be clearly marked as such, and if the derived work is 1065674Skris * incompatible with the protocol description in the RFC file, it must be 1165674Skris * called by a name other than "ssh" or "Secure Shell". 1257429Smarkm */ 1357429Smarkm 1457429Smarkm#include "includes.h" 15162856Sdes__RCSID("$FreeBSD: stable/10/crypto/openssh/servconf.c 323124 2017-09-01 22:52:18Z des $"); 1657429Smarkm 17162856Sdes#include <sys/types.h> 18162856Sdes#include <sys/socket.h> 19162856Sdes 20221420Sdes#include <netinet/in.h> 21221420Sdes#include <netinet/in_systm.h> 22221420Sdes#include <netinet/ip.h> 23221420Sdes 24255767Sdes#include <ctype.h> 25162856Sdes#include <netdb.h> 26162856Sdes#include <pwd.h> 27162856Sdes#include <stdio.h> 28162856Sdes#include <stdlib.h> 29162856Sdes#include <string.h> 30162856Sdes#include <signal.h> 31162856Sdes#include <unistd.h> 32295367Sdes#include <limits.h> 33162856Sdes#include <stdarg.h> 34181111Sdes#include <errno.h> 35255767Sdes#ifdef HAVE_UTIL_H 36255767Sdes#include <util.h> 37255767Sdes#endif 38162856Sdes 39181111Sdes#include "openbsd-compat/sys-queue.h" 40162856Sdes#include "xmalloc.h" 4157429Smarkm#include "ssh.h" 4276262Sgreen#include "log.h" 43162856Sdes#include "buffer.h" 44295367Sdes#include "misc.h" 4557429Smarkm#include "servconf.h" 4660576Skris#include "compat.h" 4776262Sgreen#include "pathnames.h" 4876262Sgreen#include "cipher.h" 49162856Sdes#include "key.h" 5076262Sgreen#include "kex.h" 5176262Sgreen#include "mac.h" 52162856Sdes#include "match.h" 53162856Sdes#include "channels.h" 54162856Sdes#include "groupaccess.h" 55240075Sdes#include "canohost.h" 56240075Sdes#include "packet.h" 57248619Sdes#include "hostfile.h" 58248619Sdes#include "auth.h" 59295367Sdes#include "myproposal.h" 60295367Sdes#include "digest.h" 61204917Sdes#include "version.h" 6257429Smarkm 63192595Sdesstatic void add_listen_addr(ServerOptions *, char *, int); 64192595Sdesstatic void add_one_listen_addr(ServerOptions *, char *, int); 6557429Smarkm 6698684Sdes/* Use of privilege separation or not */ 6798684Sdesextern int use_privsep; 68162856Sdesextern Buffer cfg; 6976262Sgreen 7057429Smarkm/* Initializes the server options to their default values. */ 7157429Smarkm 7260576Skrisvoid 7357429Smarkminitialize_server_options(ServerOptions *options) 7457429Smarkm{ 7557429Smarkm memset(options, 0, sizeof(*options)); 7698941Sdes 7798941Sdes /* Portable-specific options */ 78124211Sdes options->use_pam = -1; 7998941Sdes 8098941Sdes /* Standard Options */ 8157429Smarkm options->num_ports = 0; 8257429Smarkm options->ports_from_cmdline = 0; 83295367Sdes options->queued_listen_addrs = NULL; 84295367Sdes options->num_queued_listens = 0; 8557429Smarkm options->listen_addrs = NULL; 86147005Sdes options->address_family = -1; 8776262Sgreen options->num_host_key_files = 0; 88204917Sdes options->num_host_cert_files = 0; 89255767Sdes options->host_key_agent = NULL; 9060576Skris options->pid_file = NULL; 9157429Smarkm options->server_key_bits = -1; 9257429Smarkm options->login_grace_time = -1; 9357429Smarkm options->key_regeneration_time = -1; 9476262Sgreen options->permit_root_login = PERMIT_NOT_SET; 9557429Smarkm options->ignore_rhosts = -1; 9657429Smarkm options->ignore_user_known_hosts = -1; 9757429Smarkm options->print_motd = -1; 9876262Sgreen options->print_lastlog = -1; 9957429Smarkm options->x11_forwarding = -1; 10057429Smarkm options->x11_display_offset = -1; 10192559Sdes options->x11_use_localhost = -1; 102262566Sdes options->permit_tty = -1; 103295367Sdes options->permit_user_rc = -1; 10465674Skris options->xauth_location = NULL; 10557429Smarkm options->strict_modes = -1; 106126277Sdes options->tcp_keep_alive = -1; 10792559Sdes options->log_facility = SYSLOG_FACILITY_NOT_SET; 10892559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 10957429Smarkm options->rhosts_rsa_authentication = -1; 11076262Sgreen options->hostbased_authentication = -1; 11176262Sgreen options->hostbased_uses_name_from_packet_only = -1; 112295367Sdes options->hostbased_key_types = NULL; 113295367Sdes options->hostkeyalgorithms = NULL; 11457429Smarkm options->rsa_authentication = -1; 11576262Sgreen options->pubkey_authentication = -1; 116295367Sdes options->pubkey_key_types = NULL; 11773400Sassar options->kerberos_authentication = -1; 11892559Sdes options->kerberos_or_local_passwd = -1; 11992559Sdes options->kerberos_ticket_cleanup = -1; 120126277Sdes options->kerberos_get_afs_token = -1; 121124211Sdes options->gss_authentication=-1; 122124211Sdes options->gss_cleanup_creds = -1; 123295367Sdes options->gss_strict_acceptor = -1; 12457429Smarkm options->password_authentication = -1; 12569591Sgreen options->kbd_interactive_authentication = -1; 12692559Sdes options->challenge_response_authentication = -1; 12757429Smarkm options->permit_empty_passwd = -1; 128106130Sdes options->permit_user_env = -1; 12957429Smarkm options->use_login = -1; 13098684Sdes options->compression = -1; 131255767Sdes options->rekey_limit = -1; 132255767Sdes options->rekey_interval = -1; 13369591Sgreen options->allow_tcp_forwarding = -1; 134295367Sdes options->allow_streamlocal_forwarding = -1; 135181111Sdes options->allow_agent_forwarding = -1; 13657429Smarkm options->num_allow_users = 0; 13757429Smarkm options->num_deny_users = 0; 13857429Smarkm options->num_allow_groups = 0; 13957429Smarkm options->num_deny_groups = 0; 14060576Skris options->ciphers = NULL; 14176262Sgreen options->macs = NULL; 142221420Sdes options->kex_algorithms = NULL; 14360576Skris options->protocol = SSH_PROTO_UNKNOWN; 144295367Sdes options->fwd_opts.gateway_ports = -1; 145295367Sdes options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 146295367Sdes options->fwd_opts.streamlocal_bind_unlink = -1; 14765674Skris options->num_subsystems = 0; 14865674Skris options->max_startups_begin = -1; 14965674Skris options->max_startups_rate = -1; 15065674Skris options->max_startups = -1; 151137019Sdes options->max_authtries = -1; 152181111Sdes options->max_sessions = -1; 15376262Sgreen options->banner = NULL; 154124211Sdes options->use_dns = -1; 15576262Sgreen options->client_alive_interval = -1; 15676262Sgreen options->client_alive_count_max = -1; 157226046Sdes options->num_authkeys_files = 0; 158137019Sdes options->num_accept_env = 0; 159157019Sdes options->permit_tun = -1; 160162856Sdes options->num_permitted_opens = -1; 161162856Sdes options->adm_forced_command = NULL; 162181111Sdes options->chroot_directory = NULL; 163248619Sdes options->authorized_keys_command = NULL; 164248619Sdes options->authorized_keys_command_user = NULL; 165204917Sdes options->revoked_keys_file = NULL; 166204917Sdes options->trusted_user_ca_keys = NULL; 167215116Sdes options->authorized_principals_file = NULL; 168295367Sdes options->authorized_principals_command = NULL; 169295367Sdes options->authorized_principals_command_user = NULL; 170221420Sdes options->ip_qos_interactive = -1; 171221420Sdes options->ip_qos_bulk = -1; 172240075Sdes options->version_addendum = NULL; 173295367Sdes options->fingerprint_hash = -1; 17457429Smarkm} 17557429Smarkm 176295367Sdes/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 177295367Sdesstatic int 178295367Sdesoption_clear_or_none(const char *o) 179295367Sdes{ 180295367Sdes return o == NULL || strcasecmp(o, "none") == 0; 181295367Sdes} 182295367Sdes 183296781Sdesstatic void 184296781Sdesassemble_algorithms(ServerOptions *o) 185296781Sdes{ 186296781Sdes if (kex_assemble_names(KEX_SERVER_ENCRYPT, &o->ciphers) != 0 || 187296781Sdes kex_assemble_names(KEX_SERVER_MAC, &o->macs) != 0 || 188296781Sdes kex_assemble_names(KEX_SERVER_KEX, &o->kex_algorithms) != 0 || 189296781Sdes kex_assemble_names(KEX_DEFAULT_PK_ALG, 190296781Sdes &o->hostkeyalgorithms) != 0 || 191296781Sdes kex_assemble_names(KEX_DEFAULT_PK_ALG, 192296781Sdes &o->hostbased_key_types) != 0 || 193296781Sdes kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->pubkey_key_types) != 0) 194296781Sdes fatal("kex_assemble_names failed"); 195296781Sdes} 196296781Sdes 19760576Skrisvoid 19857429Smarkmfill_default_server_options(ServerOptions *options) 19957429Smarkm{ 200295367Sdes int i; 201295367Sdes 20298941Sdes /* Portable-specific options */ 203124211Sdes if (options->use_pam == -1) 204124279Sdes options->use_pam = 1; 20598941Sdes 20698941Sdes /* Standard Options */ 20776262Sgreen if (options->protocol == SSH_PROTO_UNKNOWN) 208126271Sdes options->protocol = SSH_PROTO_2; 209295367Sdes if (options->protocol & SSH_PROTO_1) 210295367Sdes error("WARNING: SSH protocol version 1 enabled"); 21176262Sgreen if (options->num_host_key_files == 0) { 21276262Sgreen /* fill default hostkeys for protocols */ 21376262Sgreen if (options->protocol & SSH_PROTO_1) 21492559Sdes options->host_key_files[options->num_host_key_files++] = 21592559Sdes _PATH_HOST_KEY_FILE; 21692559Sdes if (options->protocol & SSH_PROTO_2) { 21792559Sdes options->host_key_files[options->num_host_key_files++] = 218231584Sed _PATH_HOST_RSA_KEY_FILE; 219181111Sdes options->host_key_files[options->num_host_key_files++] = 22092559Sdes _PATH_HOST_DSA_KEY_FILE; 221221420Sdes#ifdef OPENSSL_HAS_ECC 222221420Sdes options->host_key_files[options->num_host_key_files++] = 223221420Sdes _PATH_HOST_ECDSA_KEY_FILE; 224221420Sdes#endif 225262566Sdes options->host_key_files[options->num_host_key_files++] = 226262566Sdes _PATH_HOST_ED25519_KEY_FILE; 22792559Sdes } 22876262Sgreen } 229204917Sdes /* No certificates by default */ 23057429Smarkm if (options->num_ports == 0) 23157429Smarkm options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 232295367Sdes if (options->address_family == -1) 233295367Sdes options->address_family = AF_UNSPEC; 23457429Smarkm if (options->listen_addrs == NULL) 23576262Sgreen add_listen_addr(options, NULL, 0); 23660576Skris if (options->pid_file == NULL) 237295367Sdes options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); 23857429Smarkm if (options->server_key_bits == -1) 239181111Sdes options->server_key_bits = 1024; 24057429Smarkm if (options->login_grace_time == -1) 24199048Sdes options->login_grace_time = 120; 24257429Smarkm if (options->key_regeneration_time == -1) 24357429Smarkm options->key_regeneration_time = 3600; 24476262Sgreen if (options->permit_root_login == PERMIT_NOT_SET) 24599048Sdes options->permit_root_login = PERMIT_NO; 24657429Smarkm if (options->ignore_rhosts == -1) 24757565Smarkm options->ignore_rhosts = 1; 24857429Smarkm if (options->ignore_user_known_hosts == -1) 24957429Smarkm options->ignore_user_known_hosts = 0; 25057429Smarkm if (options->print_motd == -1) 25157429Smarkm options->print_motd = 1; 25276262Sgreen if (options->print_lastlog == -1) 25376262Sgreen options->print_lastlog = 1; 25457429Smarkm if (options->x11_forwarding == -1) 25599048Sdes options->x11_forwarding = 1; 25657429Smarkm if (options->x11_display_offset == -1) 25757565Smarkm options->x11_display_offset = 10; 25892559Sdes if (options->x11_use_localhost == -1) 25992559Sdes options->x11_use_localhost = 1; 26065674Skris if (options->xauth_location == NULL) 261295367Sdes options->xauth_location = xstrdup(_PATH_XAUTH); 262262566Sdes if (options->permit_tty == -1) 263262566Sdes options->permit_tty = 1; 264295367Sdes if (options->permit_user_rc == -1) 265295367Sdes options->permit_user_rc = 1; 26657429Smarkm if (options->strict_modes == -1) 26757429Smarkm options->strict_modes = 1; 268126277Sdes if (options->tcp_keep_alive == -1) 269126277Sdes options->tcp_keep_alive = 1; 27092559Sdes if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 27157429Smarkm options->log_facility = SYSLOG_FACILITY_AUTH; 27292559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 27357429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 27457429Smarkm if (options->rhosts_rsa_authentication == -1) 27557565Smarkm options->rhosts_rsa_authentication = 0; 27676262Sgreen if (options->hostbased_authentication == -1) 27776262Sgreen options->hostbased_authentication = 0; 27876262Sgreen if (options->hostbased_uses_name_from_packet_only == -1) 27976262Sgreen options->hostbased_uses_name_from_packet_only = 0; 28057429Smarkm if (options->rsa_authentication == -1) 28157429Smarkm options->rsa_authentication = 1; 28276262Sgreen if (options->pubkey_authentication == -1) 28376262Sgreen options->pubkey_authentication = 1; 28499048Sdes if (options->kerberos_authentication == -1) 285124211Sdes options->kerberos_authentication = 0; 28692559Sdes if (options->kerberos_or_local_passwd == -1) 28792559Sdes options->kerberos_or_local_passwd = 1; 28892559Sdes if (options->kerberos_ticket_cleanup == -1) 28992559Sdes options->kerberos_ticket_cleanup = 1; 290126277Sdes if (options->kerberos_get_afs_token == -1) 291126277Sdes options->kerberos_get_afs_token = 0; 292124211Sdes if (options->gss_authentication == -1) 293124211Sdes options->gss_authentication = 0; 294124211Sdes if (options->gss_cleanup_creds == -1) 295124211Sdes options->gss_cleanup_creds = 1; 296295367Sdes if (options->gss_strict_acceptor == -1) 297295367Sdes options->gss_strict_acceptor = 0; 29857429Smarkm if (options->password_authentication == -1) 299126009Sdes options->password_authentication = 0; 30069591Sgreen if (options->kbd_interactive_authentication == -1) 30169591Sgreen options->kbd_interactive_authentication = 0; 30292559Sdes if (options->challenge_response_authentication == -1) 30395456Sdes options->challenge_response_authentication = 1; 30457429Smarkm if (options->permit_empty_passwd == -1) 30557565Smarkm options->permit_empty_passwd = 0; 306106130Sdes if (options->permit_user_env == -1) 307106130Sdes options->permit_user_env = 0; 30857429Smarkm if (options->use_login == -1) 30957429Smarkm options->use_login = 0; 31098684Sdes if (options->compression == -1) 311149753Sdes options->compression = COMP_DELAYED; 312255767Sdes if (options->rekey_limit == -1) 313255767Sdes options->rekey_limit = 0; 314255767Sdes if (options->rekey_interval == -1) 315255767Sdes options->rekey_interval = 0; 31669591Sgreen if (options->allow_tcp_forwarding == -1) 317248619Sdes options->allow_tcp_forwarding = FORWARD_ALLOW; 318295367Sdes if (options->allow_streamlocal_forwarding == -1) 319295367Sdes options->allow_streamlocal_forwarding = FORWARD_ALLOW; 320181111Sdes if (options->allow_agent_forwarding == -1) 321181111Sdes options->allow_agent_forwarding = 1; 322295367Sdes if (options->fwd_opts.gateway_ports == -1) 323295367Sdes options->fwd_opts.gateway_ports = 0; 32465674Skris if (options->max_startups == -1) 325248619Sdes options->max_startups = 100; 32665674Skris if (options->max_startups_rate == -1) 327248619Sdes options->max_startups_rate = 30; /* 30% */ 32865674Skris if (options->max_startups_begin == -1) 329248619Sdes options->max_startups_begin = 10; 330137019Sdes if (options->max_authtries == -1) 331137019Sdes options->max_authtries = DEFAULT_AUTH_FAIL_MAX; 332181111Sdes if (options->max_sessions == -1) 333181111Sdes options->max_sessions = DEFAULT_SESSIONS_MAX; 334124211Sdes if (options->use_dns == -1) 335124211Sdes options->use_dns = 1; 33676262Sgreen if (options->client_alive_interval == -1) 33792559Sdes options->client_alive_interval = 0; 33876262Sgreen if (options->client_alive_count_max == -1) 33976262Sgreen options->client_alive_count_max = 3; 340226046Sdes if (options->num_authkeys_files == 0) { 341226046Sdes options->authorized_keys_files[options->num_authkeys_files++] = 342226046Sdes xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); 343226046Sdes options->authorized_keys_files[options->num_authkeys_files++] = 344226046Sdes xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2); 34592559Sdes } 346157019Sdes if (options->permit_tun == -1) 347157019Sdes options->permit_tun = SSH_TUNMODE_NO; 348221420Sdes if (options->ip_qos_interactive == -1) 349221420Sdes options->ip_qos_interactive = IPTOS_LOWDELAY; 350221420Sdes if (options->ip_qos_bulk == -1) 351221420Sdes options->ip_qos_bulk = IPTOS_THROUGHPUT; 352240075Sdes if (options->version_addendum == NULL) 353240075Sdes options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 354295367Sdes if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 355295367Sdes options->fwd_opts.streamlocal_bind_mask = 0177; 356295367Sdes if (options->fwd_opts.streamlocal_bind_unlink == -1) 357295367Sdes options->fwd_opts.streamlocal_bind_unlink = 0; 358295367Sdes if (options->fingerprint_hash == -1) 359295367Sdes options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 360295367Sdes 361296781Sdes assemble_algorithms(options); 362295367Sdes 363296781Sdes /* Turn privilege separation and sandboxing on by default */ 364240075Sdes if (use_privsep == -1) 365262566Sdes use_privsep = PRIVSEP_ON; 366240075Sdes 367295367Sdes#define CLEAR_ON_NONE(v) \ 368295367Sdes do { \ 369295367Sdes if (option_clear_or_none(v)) { \ 370295367Sdes free(v); \ 371295367Sdes v = NULL; \ 372295367Sdes } \ 373295367Sdes } while(0) 374295367Sdes CLEAR_ON_NONE(options->pid_file); 375295367Sdes CLEAR_ON_NONE(options->xauth_location); 376295367Sdes CLEAR_ON_NONE(options->banner); 377295367Sdes CLEAR_ON_NONE(options->trusted_user_ca_keys); 378295367Sdes CLEAR_ON_NONE(options->revoked_keys_file); 379295367Sdes CLEAR_ON_NONE(options->authorized_principals_file); 380296781Sdes CLEAR_ON_NONE(options->adm_forced_command); 381296781Sdes CLEAR_ON_NONE(options->chroot_directory); 382295367Sdes for (i = 0; i < options->num_host_key_files; i++) 383295367Sdes CLEAR_ON_NONE(options->host_key_files[i]); 384295367Sdes for (i = 0; i < options->num_host_cert_files; i++) 385295367Sdes CLEAR_ON_NONE(options->host_cert_files[i]); 386295367Sdes#undef CLEAR_ON_NONE 387295367Sdes 388323124Sdes /* Similar handling for AuthenticationMethods=any */ 389323124Sdes if (options->num_auth_methods == 1 && 390323124Sdes strcmp(options->auth_methods[0], "any") == 0) { 391323124Sdes free(options->auth_methods[0]); 392323124Sdes options->auth_methods[0] = NULL; 393323124Sdes options->num_auth_methods = 0; 394323124Sdes } 395323124Sdes 396240075Sdes#ifndef HAVE_MMAP 397240075Sdes if (use_privsep && options->compression == 1) { 398240075Sdes error("This platform does not support both privilege " 399240075Sdes "separation and compression"); 400240075Sdes error("Compression disabled"); 401240075Sdes options->compression = 0; 402240075Sdes } 403240075Sdes#endif 404240075Sdes 40557429Smarkm} 40657429Smarkm 40757429Smarkm/* Keyword tokens. */ 40857429Smarkmtypedef enum { 40957429Smarkm sBadOption, /* == unknown option */ 41098941Sdes /* Portable-specific options */ 411124211Sdes sUsePAM, 41298941Sdes /* Standard Options */ 413295367Sdes sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, 414295367Sdes sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel, 415124211Sdes sRhostsRSAAuthentication, sRSAAuthentication, 41692559Sdes sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 417126277Sdes sKerberosGetAFSToken, 418124211Sdes sKerberosTgtPassing, sChallengeResponseAuthentication, 419147005Sdes sPasswordAuthentication, sKbdInteractiveAuthentication, 420147005Sdes sListenAddress, sAddressFamily, 42176262Sgreen sPrintMotd, sPrintLastLog, sIgnoreRhosts, 42292559Sdes sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 423262566Sdes sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, 424106130Sdes sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, 425255767Sdes sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 42676262Sgreen sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 427295367Sdes sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes, 428295367Sdes sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, 429124211Sdes sBanner, sUseDNS, sHostbasedAuthentication, 430295367Sdes sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, 431295367Sdes sHostKeyAlgorithms, 432295367Sdes sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, 433295367Sdes sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 434295367Sdes sAcceptEnv, sPermitTunnel, 435181111Sdes sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 436181111Sdes sUsePrivilegeSeparation, sAllowAgentForwarding, 437264377Sdes sHostCertificate, 438215116Sdes sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 439295367Sdes sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, 440240075Sdes sKexAlgorithms, sIPQoS, sVersionAddendum, 441248619Sdes sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 442295367Sdes sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, 443295367Sdes sStreamLocalBindMask, sStreamLocalBindUnlink, 444295367Sdes sAllowStreamLocalForwarding, sFingerprintHash, 445124211Sdes sDeprecated, sUnsupported 44657429Smarkm} ServerOpCodes; 44757429Smarkm 448162856Sdes#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ 449162856Sdes#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 450162856Sdes#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 451162856Sdes 45257429Smarkm/* Textual representation of the tokens. */ 45357429Smarkmstatic struct { 45457429Smarkm const char *name; 45557429Smarkm ServerOpCodes opcode; 456162856Sdes u_int flags; 45757429Smarkm} keywords[] = { 45898941Sdes /* Portable-specific options */ 459124211Sdes#ifdef USE_PAM 460162856Sdes { "usepam", sUsePAM, SSHCFG_GLOBAL }, 461124211Sdes#else 462162856Sdes { "usepam", sUnsupported, SSHCFG_GLOBAL }, 46399048Sdes#endif 464162856Sdes { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, 46598941Sdes /* Standard Options */ 466162856Sdes { "port", sPort, SSHCFG_GLOBAL }, 467162856Sdes { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 468162856Sdes { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 469255767Sdes { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, 470162856Sdes { "pidfile", sPidFile, SSHCFG_GLOBAL }, 471162856Sdes { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, 472162856Sdes { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 473162856Sdes { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, 474181111Sdes { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, 475162856Sdes { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 476162856Sdes { "loglevel", sLogLevel, SSHCFG_GLOBAL }, 477162856Sdes { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, 478181111Sdes { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, 479181111Sdes { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, 480215116Sdes { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, 481295367Sdes { "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL }, 482295367Sdes { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, 483181111Sdes { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, 484181111Sdes { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 485295367Sdes { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL }, 486197679Sdes { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 487124211Sdes#ifdef KRB5 488181111Sdes { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 489162856Sdes { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 490162856Sdes { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 491126277Sdes#ifdef USE_AFS 492162856Sdes { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, 493124211Sdes#else 494162856Sdes { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 495126277Sdes#endif 496126277Sdes#else 497181111Sdes { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, 498162856Sdes { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, 499162856Sdes { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, 500162856Sdes { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 50173400Sassar#endif 502162856Sdes { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, 503162856Sdes { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, 504124211Sdes#ifdef GSSAPI 505181111Sdes { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 506162856Sdes { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 507295367Sdes { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, 508124211Sdes#else 509181111Sdes { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, 510162856Sdes { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 511295367Sdes { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, 51257429Smarkm#endif 513181111Sdes { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 514181111Sdes { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 515162856Sdes { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 516162856Sdes { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ 517162856Sdes { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 518162856Sdes { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 519162856Sdes { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, 520162856Sdes { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 521296781Sdes#ifdef DISABLE_LASTLOG 522296781Sdes { "printlastlog", sUnsupported, SSHCFG_GLOBAL }, 523296781Sdes#else 524162856Sdes { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 525296781Sdes#endif 526162856Sdes { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, 527162856Sdes { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 528162856Sdes { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 529162856Sdes { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 530162856Sdes { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 531162856Sdes { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 532162856Sdes { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 533192595Sdes { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, 534162856Sdes { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 535162856Sdes { "uselogin", sUseLogin, SSHCFG_GLOBAL }, 536162856Sdes { "compression", sCompression, SSHCFG_GLOBAL }, 537255767Sdes { "rekeylimit", sRekeyLimit, SSHCFG_ALL }, 538162856Sdes { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, 539162856Sdes { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ 540162856Sdes { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 541181111Sdes { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, 542240075Sdes { "allowusers", sAllowUsers, SSHCFG_ALL }, 543240075Sdes { "denyusers", sDenyUsers, SSHCFG_ALL }, 544240075Sdes { "allowgroups", sAllowGroups, SSHCFG_ALL }, 545240075Sdes { "denygroups", sDenyGroups, SSHCFG_ALL }, 546162856Sdes { "ciphers", sCiphers, SSHCFG_GLOBAL }, 547162856Sdes { "macs", sMacs, SSHCFG_GLOBAL }, 548162856Sdes { "protocol", sProtocol, SSHCFG_GLOBAL }, 549162856Sdes { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 550162856Sdes { "subsystem", sSubsystem, SSHCFG_GLOBAL }, 551162856Sdes { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 552181111Sdes { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, 553181111Sdes { "maxsessions", sMaxSessions, SSHCFG_ALL }, 554181111Sdes { "banner", sBanner, SSHCFG_ALL }, 555162856Sdes { "usedns", sUseDNS, SSHCFG_GLOBAL }, 556162856Sdes { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, 557162856Sdes { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, 558162856Sdes { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 559162856Sdes { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 560215116Sdes { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, 561226046Sdes { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, 562197679Sdes { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, 563240075Sdes { "acceptenv", sAcceptEnv, SSHCFG_ALL }, 564215116Sdes { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 565262566Sdes { "permittty", sPermitTTY, SSHCFG_ALL }, 566295367Sdes { "permituserrc", sPermitUserRC, SSHCFG_ALL }, 567197679Sdes { "match", sMatch, SSHCFG_ALL }, 568162856Sdes { "permitopen", sPermitOpen, SSHCFG_ALL }, 569162856Sdes { "forcecommand", sForceCommand, SSHCFG_ALL }, 570181111Sdes { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 571204917Sdes { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, 572204917Sdes { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, 573204917Sdes { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, 574215116Sdes { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, 575221420Sdes { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, 576221420Sdes { "ipqos", sIPQoS, SSHCFG_ALL }, 577248619Sdes { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, 578248619Sdes { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 579295367Sdes { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL }, 580295367Sdes { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL }, 581240075Sdes { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 582248619Sdes { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 583295367Sdes { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, 584295367Sdes { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, 585295367Sdes { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, 586295367Sdes { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, 587294693Sdes { "noneenabled", sUnsupported, SSHCFG_ALL }, 588294693Sdes { "hpndisabled", sDeprecated, SSHCFG_ALL }, 589294693Sdes { "hpnbuffersize", sDeprecated, SSHCFG_ALL }, 590294693Sdes { "tcprcvbufpoll", sDeprecated, SSHCFG_ALL }, 591162856Sdes { NULL, sBadOption, 0 } 59257429Smarkm}; 59357429Smarkm 594181111Sdesstatic struct { 595181111Sdes int val; 596181111Sdes char *text; 597181111Sdes} tunmode_desc[] = { 598181111Sdes { SSH_TUNMODE_NO, "no" }, 599181111Sdes { SSH_TUNMODE_POINTOPOINT, "point-to-point" }, 600181111Sdes { SSH_TUNMODE_ETHERNET, "ethernet" }, 601181111Sdes { SSH_TUNMODE_YES, "yes" }, 602181111Sdes { -1, NULL } 603181111Sdes}; 604181111Sdes 60557429Smarkm/* 60676262Sgreen * Returns the number of the token pointed to by cp or sBadOption. 60757429Smarkm */ 60857429Smarkm 60960576Skrisstatic ServerOpCodes 61057429Smarkmparse_token(const char *cp, const char *filename, 611162856Sdes int linenum, u_int *flags) 61257429Smarkm{ 61376262Sgreen u_int i; 61457429Smarkm 61557429Smarkm for (i = 0; keywords[i].name; i++) 616162856Sdes if (strcasecmp(cp, keywords[i].name) == 0) { 617162856Sdes *flags = keywords[i].flags; 61857429Smarkm return keywords[i].opcode; 619162856Sdes } 62057429Smarkm 62176262Sgreen error("%s: line %d: Bad configuration option: %s", 62276262Sgreen filename, linenum, cp); 62357429Smarkm return sBadOption; 62457429Smarkm} 62557429Smarkm 626204917Sdeschar * 627204917Sdesderelativise_path(const char *path) 628204917Sdes{ 629295367Sdes char *expanded, *ret, cwd[PATH_MAX]; 630204917Sdes 631295367Sdes if (strcasecmp(path, "none") == 0) 632295367Sdes return xstrdup("none"); 633204917Sdes expanded = tilde_expand_filename(path, getuid()); 634204917Sdes if (*expanded == '/') 635204917Sdes return expanded; 636207319Sdes if (getcwd(cwd, sizeof(cwd)) == NULL) 637204917Sdes fatal("%s: getcwd: %s", __func__, strerror(errno)); 638204917Sdes xasprintf(&ret, "%s/%s", cwd, expanded); 639255767Sdes free(expanded); 640204917Sdes return ret; 641204917Sdes} 642204917Sdes 64392559Sdesstatic void 644192595Sdesadd_listen_addr(ServerOptions *options, char *addr, int port) 64557429Smarkm{ 646149753Sdes u_int i; 64757429Smarkm 64876262Sgreen if (port == 0) 64976262Sgreen for (i = 0; i < options->num_ports; i++) 65076262Sgreen add_one_listen_addr(options, addr, options->ports[i]); 65176262Sgreen else 65276262Sgreen add_one_listen_addr(options, addr, port); 65357429Smarkm} 65457429Smarkm 65592559Sdesstatic void 656192595Sdesadd_one_listen_addr(ServerOptions *options, char *addr, int port) 65776262Sgreen{ 65876262Sgreen struct addrinfo hints, *ai, *aitop; 65976262Sgreen char strport[NI_MAXSERV]; 66076262Sgreen int gaierr; 66176262Sgreen 66276262Sgreen memset(&hints, 0, sizeof(hints)); 663147005Sdes hints.ai_family = options->address_family; 66476262Sgreen hints.ai_socktype = SOCK_STREAM; 66576262Sgreen hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 666192595Sdes snprintf(strport, sizeof strport, "%d", port); 66776262Sgreen if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 66876262Sgreen fatal("bad addr or host: %s (%s)", 66976262Sgreen addr ? addr : "<NULL>", 670181111Sdes ssh_gai_strerror(gaierr)); 67176262Sgreen for (ai = aitop; ai->ai_next; ai = ai->ai_next) 67276262Sgreen ; 67376262Sgreen ai->ai_next = options->listen_addrs; 67476262Sgreen options->listen_addrs = aitop; 67576262Sgreen} 67676262Sgreen 677295367Sdes/* 678295367Sdes * Queue a ListenAddress to be processed once we have all of the Ports 679295367Sdes * and AddressFamily options. 680295367Sdes */ 681295367Sdesstatic void 682295367Sdesqueue_listen_addr(ServerOptions *options, char *addr, int port) 683295367Sdes{ 684295367Sdes options->queued_listen_addrs = xreallocarray( 685295367Sdes options->queued_listen_addrs, options->num_queued_listens + 1, 686295367Sdes sizeof(addr)); 687295367Sdes options->queued_listen_ports = xreallocarray( 688295367Sdes options->queued_listen_ports, options->num_queued_listens + 1, 689295367Sdes sizeof(port)); 690295367Sdes options->queued_listen_addrs[options->num_queued_listens] = 691295367Sdes xstrdup(addr); 692295367Sdes options->queued_listen_ports[options->num_queued_listens] = port; 693295367Sdes options->num_queued_listens++; 694295367Sdes} 695295367Sdes 696295367Sdes/* 697295367Sdes * Process queued (text) ListenAddress entries. 698295367Sdes */ 699295367Sdesstatic void 700295367Sdesprocess_queued_listen_addrs(ServerOptions *options) 701295367Sdes{ 702295367Sdes u_int i; 703295367Sdes 704295367Sdes if (options->num_ports == 0) 705295367Sdes options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 706295367Sdes if (options->address_family == -1) 707295367Sdes options->address_family = AF_UNSPEC; 708295367Sdes 709295367Sdes for (i = 0; i < options->num_queued_listens; i++) { 710295367Sdes add_listen_addr(options, options->queued_listen_addrs[i], 711295367Sdes options->queued_listen_ports[i]); 712295367Sdes free(options->queued_listen_addrs[i]); 713295367Sdes options->queued_listen_addrs[i] = NULL; 714295367Sdes } 715295367Sdes free(options->queued_listen_addrs); 716295367Sdes options->queued_listen_addrs = NULL; 717295367Sdes free(options->queued_listen_ports); 718295367Sdes options->queued_listen_ports = NULL; 719295367Sdes options->num_queued_listens = 0; 720295367Sdes} 721295367Sdes 722240075Sdesstruct connection_info * 723240075Sdesget_connection_info(int populate, int use_dns) 724240075Sdes{ 725323124Sdes struct ssh *ssh = active_state; /* XXX */ 726240075Sdes static struct connection_info ci; 727240075Sdes 728240075Sdes if (!populate) 729240075Sdes return &ci; 730323124Sdes ci.host = auth_get_canonical_hostname(ssh, use_dns); 731323124Sdes ci.address = ssh_remote_ipaddr(ssh); 732323124Sdes ci.laddress = ssh_local_ipaddr(ssh); 733323124Sdes ci.lport = ssh_local_port(ssh); 734240075Sdes return &ci; 735240075Sdes} 736240075Sdes 737162856Sdes/* 738162856Sdes * The strategy for the Match blocks is that the config file is parsed twice. 739162856Sdes * 740162856Sdes * The first time is at startup. activep is initialized to 1 and the 741162856Sdes * directives in the global context are processed and acted on. Hitting a 742162856Sdes * Match directive unsets activep and the directives inside the block are 743162856Sdes * checked for syntax only. 744162856Sdes * 745162856Sdes * The second time is after a connection has been established but before 746162856Sdes * authentication. activep is initialized to 2 and global config directives 747162856Sdes * are ignored since they have already been processed. If the criteria in a 748162856Sdes * Match block is met, activep is set and the subsequent directives 749162856Sdes * processed and actioned until EOF or another Match block unsets it. Any 750162856Sdes * options set are copied into the main server config. 751162856Sdes * 752162856Sdes * Potential additions/improvements: 753162856Sdes * - Add Match support for pre-kex directives, eg Protocol, Ciphers. 754162856Sdes * 755162856Sdes * - Add a Tag directive (idea from David Leonard) ala pf, eg: 756162856Sdes * Match Address 192.168.0.* 757162856Sdes * Tag trusted 758162856Sdes * Match Group wheel 759162856Sdes * Tag trusted 760162856Sdes * Match Tag trusted 761162856Sdes * AllowTcpForwarding yes 762162856Sdes * GatewayPorts clientspecified 763162856Sdes * [...] 764162856Sdes * 765162856Sdes * - Add a PermittedChannelRequests directive 766162856Sdes * Match Group shell 767162856Sdes * PermittedChannelRequests session,forwarded-tcpip 768162856Sdes */ 769162856Sdes 770162856Sdesstatic int 771162856Sdesmatch_cfg_line_group(const char *grps, int line, const char *user) 772162856Sdes{ 773162856Sdes int result = 0; 774162856Sdes struct passwd *pw; 775162856Sdes 776162856Sdes if (user == NULL) 777162856Sdes goto out; 778162856Sdes 779162856Sdes if ((pw = getpwnam(user)) == NULL) { 780162856Sdes debug("Can't match group at line %d because user %.100s does " 781162856Sdes "not exist", line, user); 782162856Sdes } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 783162856Sdes debug("Can't Match group because user %.100s not in any group " 784162856Sdes "at line %d", user, line); 785181111Sdes } else if (ga_match_pattern_list(grps) != 1) { 786181111Sdes debug("user %.100s does not match group list %.100s at line %d", 787181111Sdes user, grps, line); 788162856Sdes } else { 789181111Sdes debug("user %.100s matched group list %.100s at line %d", user, 790181111Sdes grps, line); 791162856Sdes result = 1; 792162856Sdes } 793162856Sdesout: 794162856Sdes ga_free(); 795162856Sdes return result; 796162856Sdes} 797162856Sdes 798240075Sdes/* 799248619Sdes * All of the attributes on a single Match line are ANDed together, so we need 800262566Sdes * to check every attribute and set the result to zero if any attribute does 801248619Sdes * not match. 802240075Sdes */ 803162856Sdesstatic int 804240075Sdesmatch_cfg_line(char **condition, int line, struct connection_info *ci) 805162856Sdes{ 806262566Sdes int result = 1, attributes = 0, port; 807162856Sdes char *arg, *attrib, *cp = *condition; 808162856Sdes 809240075Sdes if (ci == NULL) 810162856Sdes debug3("checking syntax for 'Match %s'", cp); 811162856Sdes else 812240075Sdes debug3("checking match for '%s' user %s host %s addr %s " 813240075Sdes "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", 814240075Sdes ci->host ? ci->host : "(null)", 815240075Sdes ci->address ? ci->address : "(null)", 816240075Sdes ci->laddress ? ci->laddress : "(null)", ci->lport); 817162856Sdes 818162856Sdes while ((attrib = strdelim(&cp)) && *attrib != '\0') { 819262566Sdes attributes++; 820262566Sdes if (strcasecmp(attrib, "all") == 0) { 821262566Sdes if (attributes != 1 || 822262566Sdes ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 823262566Sdes error("'all' cannot be combined with other " 824262566Sdes "Match attributes"); 825262566Sdes return -1; 826262566Sdes } 827262566Sdes *condition = cp; 828262566Sdes return 1; 829262566Sdes } 830162856Sdes if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 831162856Sdes error("Missing Match criteria for %s", attrib); 832162856Sdes return -1; 833162856Sdes } 834162856Sdes if (strcasecmp(attrib, "user") == 0) { 835240075Sdes if (ci == NULL || ci->user == NULL) { 836162856Sdes result = 0; 837162856Sdes continue; 838162856Sdes } 839295367Sdes if (match_pattern_list(ci->user, arg, 0) != 1) 840162856Sdes result = 0; 841162856Sdes else 842162856Sdes debug("user %.100s matched 'User %.100s' at " 843240075Sdes "line %d", ci->user, arg, line); 844162856Sdes } else if (strcasecmp(attrib, "group") == 0) { 845240075Sdes if (ci == NULL || ci->user == NULL) { 846240075Sdes result = 0; 847240075Sdes continue; 848240075Sdes } 849240075Sdes switch (match_cfg_line_group(arg, line, ci->user)) { 850162856Sdes case -1: 851162856Sdes return -1; 852162856Sdes case 0: 853162856Sdes result = 0; 854162856Sdes } 855162856Sdes } else if (strcasecmp(attrib, "host") == 0) { 856240075Sdes if (ci == NULL || ci->host == NULL) { 857162856Sdes result = 0; 858162856Sdes continue; 859162856Sdes } 860295367Sdes if (match_hostname(ci->host, arg) != 1) 861162856Sdes result = 0; 862162856Sdes else 863162856Sdes debug("connection from %.100s matched 'Host " 864240075Sdes "%.100s' at line %d", ci->host, arg, line); 865162856Sdes } else if (strcasecmp(attrib, "address") == 0) { 866240075Sdes if (ci == NULL || ci->address == NULL) { 867240075Sdes result = 0; 868240075Sdes continue; 869240075Sdes } 870240075Sdes switch (addr_match_list(ci->address, arg)) { 871181111Sdes case 1: 872181111Sdes debug("connection from %.100s matched 'Address " 873240075Sdes "%.100s' at line %d", ci->address, arg, line); 874181111Sdes break; 875181111Sdes case 0: 876181111Sdes case -1: 877162856Sdes result = 0; 878181111Sdes break; 879181111Sdes case -2: 880181111Sdes return -1; 881162856Sdes } 882240075Sdes } else if (strcasecmp(attrib, "localaddress") == 0){ 883240075Sdes if (ci == NULL || ci->laddress == NULL) { 884240075Sdes result = 0; 885240075Sdes continue; 886240075Sdes } 887240075Sdes switch (addr_match_list(ci->laddress, arg)) { 888240075Sdes case 1: 889240075Sdes debug("connection from %.100s matched " 890240075Sdes "'LocalAddress %.100s' at line %d", 891240075Sdes ci->laddress, arg, line); 892240075Sdes break; 893240075Sdes case 0: 894240075Sdes case -1: 895240075Sdes result = 0; 896240075Sdes break; 897240075Sdes case -2: 898240075Sdes return -1; 899240075Sdes } 900240075Sdes } else if (strcasecmp(attrib, "localport") == 0) { 901240075Sdes if ((port = a2port(arg)) == -1) { 902240075Sdes error("Invalid LocalPort '%s' on Match line", 903240075Sdes arg); 904240075Sdes return -1; 905240075Sdes } 906240075Sdes if (ci == NULL || ci->lport == 0) { 907240075Sdes result = 0; 908240075Sdes continue; 909240075Sdes } 910240075Sdes /* TODO support port lists */ 911240075Sdes if (port == ci->lport) 912240075Sdes debug("connection from %.100s matched " 913240075Sdes "'LocalPort %d' at line %d", 914240075Sdes ci->laddress, port, line); 915240075Sdes else 916240075Sdes result = 0; 917162856Sdes } else { 918162856Sdes error("Unsupported Match attribute %s", attrib); 919162856Sdes return -1; 920162856Sdes } 921162856Sdes } 922262566Sdes if (attributes == 0) { 923262566Sdes error("One or more attributes required for Match"); 924262566Sdes return -1; 925262566Sdes } 926240075Sdes if (ci != NULL) 927162856Sdes debug3("match %sfound", result ? "" : "not "); 928162856Sdes *condition = cp; 929162856Sdes return result; 930162856Sdes} 931162856Sdes 932162856Sdes#define WHITESPACE " \t\r\n" 933162856Sdes 934226046Sdes/* Multistate option parsing */ 935226046Sdesstruct multistate { 936226046Sdes char *key; 937226046Sdes int value; 938226046Sdes}; 939226046Sdesstatic const struct multistate multistate_addressfamily[] = { 940226046Sdes { "inet", AF_INET }, 941226046Sdes { "inet6", AF_INET6 }, 942226046Sdes { "any", AF_UNSPEC }, 943226046Sdes { NULL, -1 } 944226046Sdes}; 945226046Sdesstatic const struct multistate multistate_permitrootlogin[] = { 946226046Sdes { "without-password", PERMIT_NO_PASSWD }, 947295367Sdes { "prohibit-password", PERMIT_NO_PASSWD }, 948226046Sdes { "forced-commands-only", PERMIT_FORCED_ONLY }, 949226046Sdes { "yes", PERMIT_YES }, 950226046Sdes { "no", PERMIT_NO }, 951226046Sdes { NULL, -1 } 952226046Sdes}; 953226046Sdesstatic const struct multistate multistate_compression[] = { 954226046Sdes { "delayed", COMP_DELAYED }, 955226046Sdes { "yes", COMP_ZLIB }, 956226046Sdes { "no", COMP_NONE }, 957226046Sdes { NULL, -1 } 958226046Sdes}; 959226046Sdesstatic const struct multistate multistate_gatewayports[] = { 960226046Sdes { "clientspecified", 2 }, 961226046Sdes { "yes", 1 }, 962226046Sdes { "no", 0 }, 963226046Sdes { NULL, -1 } 964226046Sdes}; 965226046Sdesstatic const struct multistate multistate_privsep[] = { 966240075Sdes { "yes", PRIVSEP_NOSANDBOX }, 967240075Sdes { "sandbox", PRIVSEP_ON }, 968240075Sdes { "nosandbox", PRIVSEP_NOSANDBOX }, 969226046Sdes { "no", PRIVSEP_OFF }, 970226046Sdes { NULL, -1 } 971226046Sdes}; 972248619Sdesstatic const struct multistate multistate_tcpfwd[] = { 973248619Sdes { "yes", FORWARD_ALLOW }, 974248619Sdes { "all", FORWARD_ALLOW }, 975248619Sdes { "no", FORWARD_DENY }, 976248619Sdes { "remote", FORWARD_REMOTE }, 977248619Sdes { "local", FORWARD_LOCAL }, 978248619Sdes { NULL, -1 } 979248619Sdes}; 980226046Sdes 98192559Sdesint 98292559Sdesprocess_server_config_line(ServerOptions *options, char *line, 983240075Sdes const char *filename, int linenum, int *activep, 984240075Sdes struct connection_info *connectinfo) 98557429Smarkm{ 98676262Sgreen char *cp, **charptr, *arg, *p; 987255767Sdes int cmdline = 0, *intptr, value, value2, n, port; 988181111Sdes SyslogFacility *log_facility_ptr; 989181111Sdes LogLevel *log_level_ptr; 99057429Smarkm ServerOpCodes opcode; 991162856Sdes u_int i, flags = 0; 992162856Sdes size_t len; 993255767Sdes long long val64; 994226046Sdes const struct multistate *multistate_ptr; 99557429Smarkm 99692559Sdes cp = line; 997162856Sdes if ((arg = strdelim(&cp)) == NULL) 998162856Sdes return 0; 99992559Sdes /* Ignore leading whitespace */ 100092559Sdes if (*arg == '\0') 100165674Skris arg = strdelim(&cp); 100292559Sdes if (!arg || !*arg || *arg == '#') 100392559Sdes return 0; 100492559Sdes intptr = NULL; 100592559Sdes charptr = NULL; 1006162856Sdes opcode = parse_token(arg, filename, linenum, &flags); 1007162856Sdes 1008162856Sdes if (activep == NULL) { /* We are processing a command line directive */ 1009162856Sdes cmdline = 1; 1010162856Sdes activep = &cmdline; 1011162856Sdes } 1012162856Sdes if (*activep && opcode != sMatch) 1013162856Sdes debug3("%s:%d setting %s %s", filename, linenum, arg, cp); 1014162856Sdes if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 1015240075Sdes if (connectinfo == NULL) { 1016162856Sdes fatal("%s line %d: Directive '%s' is not allowed " 1017162856Sdes "within a Match block", filename, linenum, arg); 1018162856Sdes } else { /* this is a directive we have already processed */ 1019162856Sdes while (arg) 1020162856Sdes arg = strdelim(&cp); 1021162856Sdes return 0; 1022162856Sdes } 1023162856Sdes } 1024162856Sdes 102592559Sdes switch (opcode) { 102698941Sdes /* Portable-specific options */ 1027124211Sdes case sUsePAM: 1028124211Sdes intptr = &options->use_pam; 102998941Sdes goto parse_flag; 103098941Sdes 103198941Sdes /* Standard Options */ 103292559Sdes case sBadOption: 103392559Sdes return -1; 103492559Sdes case sPort: 103592559Sdes /* ignore ports from configfile if cmdline specifies ports */ 103692559Sdes if (options->ports_from_cmdline) 103792559Sdes return 0; 103892559Sdes if (options->num_ports >= MAX_PORTS) 103992559Sdes fatal("%s line %d: too many ports.", 104092559Sdes filename, linenum); 104192559Sdes arg = strdelim(&cp); 104292559Sdes if (!arg || *arg == '\0') 104392559Sdes fatal("%s line %d: missing port number.", 104492559Sdes filename, linenum); 104592559Sdes options->ports[options->num_ports++] = a2port(arg); 1046192595Sdes if (options->ports[options->num_ports-1] <= 0) 104792559Sdes fatal("%s line %d: Badly formatted port number.", 104892559Sdes filename, linenum); 104992559Sdes break; 105057429Smarkm 105192559Sdes case sServerKeyBits: 105292559Sdes intptr = &options->server_key_bits; 1053181111Sdes parse_int: 105492559Sdes arg = strdelim(&cp); 105592559Sdes if (!arg || *arg == '\0') 105692559Sdes fatal("%s line %d: missing integer value.", 105792559Sdes filename, linenum); 105892559Sdes value = atoi(arg); 1059162856Sdes if (*activep && *intptr == -1) 106092559Sdes *intptr = value; 106192559Sdes break; 106257429Smarkm 106392559Sdes case sLoginGraceTime: 106492559Sdes intptr = &options->login_grace_time; 1065181111Sdes parse_time: 106692559Sdes arg = strdelim(&cp); 106792559Sdes if (!arg || *arg == '\0') 106892559Sdes fatal("%s line %d: missing time value.", 106992559Sdes filename, linenum); 107092559Sdes if ((value = convtime(arg)) == -1) 107192559Sdes fatal("%s line %d: invalid time value.", 107292559Sdes filename, linenum); 1073295367Sdes if (*activep && *intptr == -1) 107492559Sdes *intptr = value; 107592559Sdes break; 107657429Smarkm 107792559Sdes case sKeyRegenerationTime: 107892559Sdes intptr = &options->key_regeneration_time; 107992559Sdes goto parse_time; 108057429Smarkm 108192559Sdes case sListenAddress: 108292559Sdes arg = strdelim(&cp); 1083147005Sdes if (arg == NULL || *arg == '\0') 1084147005Sdes fatal("%s line %d: missing address", 108592559Sdes filename, linenum); 1086149753Sdes /* check for bare IPv6 address: no "[]" and 2 or more ":" */ 1087149753Sdes if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL 1088149753Sdes && strchr(p+1, ':') != NULL) { 1089295367Sdes queue_listen_addr(options, arg, 0); 1090149753Sdes break; 1091149753Sdes } 1092147005Sdes p = hpdelim(&arg); 1093147005Sdes if (p == NULL) 1094147005Sdes fatal("%s line %d: bad address:port usage", 1095147005Sdes filename, linenum); 1096147005Sdes p = cleanhostname(p); 1097147005Sdes if (arg == NULL) 1098147005Sdes port = 0; 1099192595Sdes else if ((port = a2port(arg)) <= 0) 1100147005Sdes fatal("%s line %d: bad port number", filename, linenum); 110157429Smarkm 1102295367Sdes queue_listen_addr(options, p, port); 1103147005Sdes 1104147005Sdes break; 1105147005Sdes 1106147005Sdes case sAddressFamily: 1107226046Sdes intptr = &options->address_family; 1108226046Sdes multistate_ptr = multistate_addressfamily; 1109226046Sdes parse_multistate: 1110147005Sdes arg = strdelim(&cp); 1111149753Sdes if (!arg || *arg == '\0') 1112226046Sdes fatal("%s line %d: missing argument.", 1113149753Sdes filename, linenum); 1114226046Sdes value = -1; 1115226046Sdes for (i = 0; multistate_ptr[i].key != NULL; i++) { 1116226046Sdes if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1117226046Sdes value = multistate_ptr[i].value; 1118226046Sdes break; 1119226046Sdes } 1120226046Sdes } 1121226046Sdes if (value == -1) 1122226046Sdes fatal("%s line %d: unsupported option \"%s\".", 1123147005Sdes filename, linenum, arg); 1124226046Sdes if (*activep && *intptr == -1) 1125147005Sdes *intptr = value; 112692559Sdes break; 112757429Smarkm 112892559Sdes case sHostKeyFile: 112992559Sdes intptr = &options->num_host_key_files; 113092559Sdes if (*intptr >= MAX_HOSTKEYS) 113192559Sdes fatal("%s line %d: too many host keys specified (max %d).", 113292559Sdes filename, linenum, MAX_HOSTKEYS); 113392559Sdes charptr = &options->host_key_files[*intptr]; 1134181111Sdes parse_filename: 113592559Sdes arg = strdelim(&cp); 113692559Sdes if (!arg || *arg == '\0') 113792559Sdes fatal("%s line %d: missing file name.", 113892559Sdes filename, linenum); 1139162856Sdes if (*activep && *charptr == NULL) { 1140204917Sdes *charptr = derelativise_path(arg); 114192559Sdes /* increase optional counter */ 114292559Sdes if (intptr != NULL) 114392559Sdes *intptr = *intptr + 1; 114492559Sdes } 114592559Sdes break; 114660576Skris 1147255767Sdes case sHostKeyAgent: 1148255767Sdes charptr = &options->host_key_agent; 1149255767Sdes arg = strdelim(&cp); 1150255767Sdes if (!arg || *arg == '\0') 1151255767Sdes fatal("%s line %d: missing socket name.", 1152255767Sdes filename, linenum); 1153255767Sdes if (*activep && *charptr == NULL) 1154255767Sdes *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? 1155255767Sdes xstrdup(arg) : derelativise_path(arg); 1156255767Sdes break; 1157255767Sdes 1158204917Sdes case sHostCertificate: 1159204917Sdes intptr = &options->num_host_cert_files; 1160204917Sdes if (*intptr >= MAX_HOSTKEYS) 1161204917Sdes fatal("%s line %d: too many host certificates " 1162204917Sdes "specified (max %d).", filename, linenum, 1163204917Sdes MAX_HOSTCERTS); 1164204917Sdes charptr = &options->host_cert_files[*intptr]; 1165204917Sdes goto parse_filename; 1166204917Sdes break; 1167204917Sdes 116892559Sdes case sPidFile: 116992559Sdes charptr = &options->pid_file; 117092559Sdes goto parse_filename; 117157429Smarkm 117292559Sdes case sPermitRootLogin: 117392559Sdes intptr = &options->permit_root_login; 1174226046Sdes multistate_ptr = multistate_permitrootlogin; 1175226046Sdes goto parse_multistate; 117692559Sdes 117792559Sdes case sIgnoreRhosts: 117892559Sdes intptr = &options->ignore_rhosts; 1179181111Sdes parse_flag: 118092559Sdes arg = strdelim(&cp); 118192559Sdes if (!arg || *arg == '\0') 118292559Sdes fatal("%s line %d: missing yes/no argument.", 118392559Sdes filename, linenum); 118492559Sdes value = 0; /* silence compiler */ 118592559Sdes if (strcmp(arg, "yes") == 0) 118692559Sdes value = 1; 118792559Sdes else if (strcmp(arg, "no") == 0) 118892559Sdes value = 0; 118992559Sdes else 119092559Sdes fatal("%s line %d: Bad yes/no argument: %s", 119192559Sdes filename, linenum, arg); 1192162856Sdes if (*activep && *intptr == -1) 119392559Sdes *intptr = value; 119492559Sdes break; 119557429Smarkm 119692559Sdes case sIgnoreUserKnownHosts: 119792559Sdes intptr = &options->ignore_user_known_hosts; 119892559Sdes goto parse_flag; 119957429Smarkm 120092559Sdes case sRhostsRSAAuthentication: 120192559Sdes intptr = &options->rhosts_rsa_authentication; 120292559Sdes goto parse_flag; 120357429Smarkm 120492559Sdes case sHostbasedAuthentication: 120592559Sdes intptr = &options->hostbased_authentication; 120692559Sdes goto parse_flag; 120776262Sgreen 120892559Sdes case sHostbasedUsesNameFromPacketOnly: 120992559Sdes intptr = &options->hostbased_uses_name_from_packet_only; 121092559Sdes goto parse_flag; 121176262Sgreen 1212295367Sdes case sHostbasedAcceptedKeyTypes: 1213295367Sdes charptr = &options->hostbased_key_types; 1214295367Sdes parse_keytypes: 1215295367Sdes arg = strdelim(&cp); 1216295367Sdes if (!arg || *arg == '\0') 1217295367Sdes fatal("%s line %d: Missing argument.", 1218295367Sdes filename, linenum); 1219295367Sdes if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1)) 1220295367Sdes fatal("%s line %d: Bad key types '%s'.", 1221295367Sdes filename, linenum, arg ? arg : "<NONE>"); 1222295367Sdes if (*activep && *charptr == NULL) 1223295367Sdes *charptr = xstrdup(arg); 1224295367Sdes break; 1225295367Sdes 1226295367Sdes case sHostKeyAlgorithms: 1227295367Sdes charptr = &options->hostkeyalgorithms; 1228295367Sdes goto parse_keytypes; 1229295367Sdes 123092559Sdes case sRSAAuthentication: 123192559Sdes intptr = &options->rsa_authentication; 123292559Sdes goto parse_flag; 123357429Smarkm 123492559Sdes case sPubkeyAuthentication: 123592559Sdes intptr = &options->pubkey_authentication; 123692559Sdes goto parse_flag; 1237124211Sdes 1238295367Sdes case sPubkeyAcceptedKeyTypes: 1239295367Sdes charptr = &options->pubkey_key_types; 1240295367Sdes goto parse_keytypes; 1241295367Sdes 124292559Sdes case sKerberosAuthentication: 124392559Sdes intptr = &options->kerberos_authentication; 124492559Sdes goto parse_flag; 124557429Smarkm 124692559Sdes case sKerberosOrLocalPasswd: 124792559Sdes intptr = &options->kerberos_or_local_passwd; 124892559Sdes goto parse_flag; 124992559Sdes 125092559Sdes case sKerberosTicketCleanup: 125192559Sdes intptr = &options->kerberos_ticket_cleanup; 125292559Sdes goto parse_flag; 1253124211Sdes 1254126277Sdes case sKerberosGetAFSToken: 1255126277Sdes intptr = &options->kerberos_get_afs_token; 1256126277Sdes goto parse_flag; 1257126277Sdes 1258124211Sdes case sGssAuthentication: 1259124211Sdes intptr = &options->gss_authentication; 126092559Sdes goto parse_flag; 1261124211Sdes 1262124211Sdes case sGssCleanupCreds: 1263124211Sdes intptr = &options->gss_cleanup_creds; 126492559Sdes goto parse_flag; 126557429Smarkm 1266295367Sdes case sGssStrictAcceptor: 1267295367Sdes intptr = &options->gss_strict_acceptor; 1268295367Sdes goto parse_flag; 1269295367Sdes 127092559Sdes case sPasswordAuthentication: 127192559Sdes intptr = &options->password_authentication; 127292559Sdes goto parse_flag; 127357565Smarkm 127492559Sdes case sKbdInteractiveAuthentication: 127592559Sdes intptr = &options->kbd_interactive_authentication; 127692559Sdes goto parse_flag; 127757429Smarkm 127892559Sdes case sChallengeResponseAuthentication: 127992559Sdes intptr = &options->challenge_response_authentication; 128092559Sdes goto parse_flag; 128157429Smarkm 128292559Sdes case sPrintMotd: 128392559Sdes intptr = &options->print_motd; 128492559Sdes goto parse_flag; 128557429Smarkm 128692559Sdes case sPrintLastLog: 128792559Sdes intptr = &options->print_lastlog; 128892559Sdes goto parse_flag; 128969591Sgreen 129092559Sdes case sX11Forwarding: 129192559Sdes intptr = &options->x11_forwarding; 129292559Sdes goto parse_flag; 129357429Smarkm 129492559Sdes case sX11DisplayOffset: 129592559Sdes intptr = &options->x11_display_offset; 129692559Sdes goto parse_int; 129757429Smarkm 129892559Sdes case sX11UseLocalhost: 129992559Sdes intptr = &options->x11_use_localhost; 130092559Sdes goto parse_flag; 130157429Smarkm 130292559Sdes case sXAuthLocation: 130392559Sdes charptr = &options->xauth_location; 130492559Sdes goto parse_filename; 130576262Sgreen 1306262566Sdes case sPermitTTY: 1307262566Sdes intptr = &options->permit_tty; 1308262566Sdes goto parse_flag; 1309262566Sdes 1310295367Sdes case sPermitUserRC: 1311295367Sdes intptr = &options->permit_user_rc; 1312295367Sdes goto parse_flag; 1313295367Sdes 131492559Sdes case sStrictModes: 131592559Sdes intptr = &options->strict_modes; 131692559Sdes goto parse_flag; 131757429Smarkm 1318126277Sdes case sTCPKeepAlive: 1319126277Sdes intptr = &options->tcp_keep_alive; 132092559Sdes goto parse_flag; 132157429Smarkm 132292559Sdes case sEmptyPasswd: 132392559Sdes intptr = &options->permit_empty_passwd; 132492559Sdes goto parse_flag; 132576262Sgreen 1326106130Sdes case sPermitUserEnvironment: 1327106130Sdes intptr = &options->permit_user_env; 1328106130Sdes goto parse_flag; 1329106130Sdes 133092559Sdes case sUseLogin: 133192559Sdes intptr = &options->use_login; 133292559Sdes goto parse_flag; 133357429Smarkm 133498684Sdes case sCompression: 133598684Sdes intptr = &options->compression; 1336226046Sdes multistate_ptr = multistate_compression; 1337226046Sdes goto parse_multistate; 133898684Sdes 1339255767Sdes case sRekeyLimit: 1340255767Sdes arg = strdelim(&cp); 1341255767Sdes if (!arg || *arg == '\0') 1342255767Sdes fatal("%.200s line %d: Missing argument.", filename, 1343255767Sdes linenum); 1344255767Sdes if (strcmp(arg, "default") == 0) { 1345255767Sdes val64 = 0; 1346255767Sdes } else { 1347255767Sdes if (scan_scaled(arg, &val64) == -1) 1348255767Sdes fatal("%.200s line %d: Bad number '%s': %s", 1349255767Sdes filename, linenum, arg, strerror(errno)); 1350255767Sdes if (val64 != 0 && val64 < 16) 1351255767Sdes fatal("%.200s line %d: RekeyLimit too small", 1352255767Sdes filename, linenum); 1353255767Sdes } 1354255767Sdes if (*activep && options->rekey_limit == -1) 1355296781Sdes options->rekey_limit = val64; 1356255767Sdes if (cp != NULL) { /* optional rekey interval present */ 1357255767Sdes if (strcmp(cp, "none") == 0) { 1358255767Sdes (void)strdelim(&cp); /* discard */ 1359255767Sdes break; 1360255767Sdes } 1361255767Sdes intptr = &options->rekey_interval; 1362255767Sdes goto parse_time; 1363255767Sdes } 1364255767Sdes break; 1365255767Sdes 136692559Sdes case sGatewayPorts: 1367295367Sdes intptr = &options->fwd_opts.gateway_ports; 1368226046Sdes multistate_ptr = multistate_gatewayports; 1369226046Sdes goto parse_multistate; 137057429Smarkm 1371124211Sdes case sUseDNS: 1372124211Sdes intptr = &options->use_dns; 137392559Sdes goto parse_flag; 137457429Smarkm 137592559Sdes case sLogFacility: 1376181111Sdes log_facility_ptr = &options->log_facility; 137792559Sdes arg = strdelim(&cp); 137892559Sdes value = log_facility_number(arg); 137992559Sdes if (value == SYSLOG_FACILITY_NOT_SET) 138092559Sdes fatal("%.200s line %d: unsupported log facility '%s'", 138192559Sdes filename, linenum, arg ? arg : "<NONE>"); 1382181111Sdes if (*log_facility_ptr == -1) 1383181111Sdes *log_facility_ptr = (SyslogFacility) value; 138492559Sdes break; 138557429Smarkm 138692559Sdes case sLogLevel: 1387181111Sdes log_level_ptr = &options->log_level; 138892559Sdes arg = strdelim(&cp); 138992559Sdes value = log_level_number(arg); 139092559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 139192559Sdes fatal("%.200s line %d: unsupported log level '%s'", 139292559Sdes filename, linenum, arg ? arg : "<NONE>"); 1393181111Sdes if (*log_level_ptr == -1) 1394181111Sdes *log_level_ptr = (LogLevel) value; 139592559Sdes break; 139660576Skris 139792559Sdes case sAllowTcpForwarding: 139892559Sdes intptr = &options->allow_tcp_forwarding; 1399248619Sdes multistate_ptr = multistate_tcpfwd; 1400248619Sdes goto parse_multistate; 140176262Sgreen 1402295367Sdes case sAllowStreamLocalForwarding: 1403295367Sdes intptr = &options->allow_streamlocal_forwarding; 1404295367Sdes multistate_ptr = multistate_tcpfwd; 1405295367Sdes goto parse_multistate; 1406295367Sdes 1407181111Sdes case sAllowAgentForwarding: 1408181111Sdes intptr = &options->allow_agent_forwarding; 1409181111Sdes goto parse_flag; 1410181111Sdes 141198684Sdes case sUsePrivilegeSeparation: 141298684Sdes intptr = &use_privsep; 1413226046Sdes multistate_ptr = multistate_privsep; 1414226046Sdes goto parse_multistate; 141598684Sdes 141692559Sdes case sAllowUsers: 141792559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 141892559Sdes if (options->num_allow_users >= MAX_ALLOW_USERS) 141992559Sdes fatal("%s line %d: too many allow users.", 142092559Sdes filename, linenum); 1421240075Sdes if (!*activep) 1422240075Sdes continue; 142399063Sdes options->allow_users[options->num_allow_users++] = 142499063Sdes xstrdup(arg); 142592559Sdes } 142692559Sdes break; 142757429Smarkm 142892559Sdes case sDenyUsers: 142992559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 143092559Sdes if (options->num_deny_users >= MAX_DENY_USERS) 1431162856Sdes fatal("%s line %d: too many deny users.", 143292559Sdes filename, linenum); 1433240075Sdes if (!*activep) 1434240075Sdes continue; 143599063Sdes options->deny_users[options->num_deny_users++] = 143699063Sdes xstrdup(arg); 143792559Sdes } 143892559Sdes break; 143957429Smarkm 144092559Sdes case sAllowGroups: 144192559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 144292559Sdes if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 144392559Sdes fatal("%s line %d: too many allow groups.", 144492559Sdes filename, linenum); 1445240075Sdes if (!*activep) 1446240075Sdes continue; 144799063Sdes options->allow_groups[options->num_allow_groups++] = 144899063Sdes xstrdup(arg); 144992559Sdes } 145092559Sdes break; 145169591Sgreen 145292559Sdes case sDenyGroups: 145392559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 145492559Sdes if (options->num_deny_groups >= MAX_DENY_GROUPS) 145592559Sdes fatal("%s line %d: too many deny groups.", 145692559Sdes filename, linenum); 1457240075Sdes if (!*activep) 1458240075Sdes continue; 1459240075Sdes options->deny_groups[options->num_deny_groups++] = 1460240075Sdes xstrdup(arg); 146192559Sdes } 146292559Sdes break; 146357429Smarkm 146492559Sdes case sCiphers: 146592559Sdes arg = strdelim(&cp); 146692559Sdes if (!arg || *arg == '\0') 146792559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 1468295367Sdes if (!ciphers_valid(*arg == '+' ? arg + 1 : arg)) 146992559Sdes fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 147092559Sdes filename, linenum, arg ? arg : "<NONE>"); 147192559Sdes if (options->ciphers == NULL) 147292559Sdes options->ciphers = xstrdup(arg); 147392559Sdes break; 147457429Smarkm 147592559Sdes case sMacs: 147692559Sdes arg = strdelim(&cp); 147792559Sdes if (!arg || *arg == '\0') 147892559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 1479295367Sdes if (!mac_valid(*arg == '+' ? arg + 1 : arg)) 148092559Sdes fatal("%s line %d: Bad SSH2 mac spec '%s'.", 148192559Sdes filename, linenum, arg ? arg : "<NONE>"); 148292559Sdes if (options->macs == NULL) 148392559Sdes options->macs = xstrdup(arg); 148492559Sdes break; 148557429Smarkm 1486221420Sdes case sKexAlgorithms: 1487221420Sdes arg = strdelim(&cp); 1488221420Sdes if (!arg || *arg == '\0') 1489221420Sdes fatal("%s line %d: Missing argument.", 1490221420Sdes filename, linenum); 1491295367Sdes if (!kex_names_valid(*arg == '+' ? arg + 1 : arg)) 1492221420Sdes fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", 1493221420Sdes filename, linenum, arg ? arg : "<NONE>"); 1494221420Sdes if (options->kex_algorithms == NULL) 1495221420Sdes options->kex_algorithms = xstrdup(arg); 1496221420Sdes break; 1497221420Sdes 149892559Sdes case sProtocol: 149992559Sdes intptr = &options->protocol; 150092559Sdes arg = strdelim(&cp); 150192559Sdes if (!arg || *arg == '\0') 150292559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 150392559Sdes value = proto_spec(arg); 150492559Sdes if (value == SSH_PROTO_UNKNOWN) 150592559Sdes fatal("%s line %d: Bad protocol spec '%s'.", 150692559Sdes filename, linenum, arg ? arg : "<NONE>"); 150792559Sdes if (*intptr == SSH_PROTO_UNKNOWN) 150892559Sdes *intptr = value; 150992559Sdes break; 151057429Smarkm 151192559Sdes case sSubsystem: 151292559Sdes if (options->num_subsystems >= MAX_SUBSYSTEMS) { 151392559Sdes fatal("%s line %d: too many subsystems defined.", 151492559Sdes filename, linenum); 151592559Sdes } 151692559Sdes arg = strdelim(&cp); 151792559Sdes if (!arg || *arg == '\0') 151892559Sdes fatal("%s line %d: Missing subsystem name.", 151992559Sdes filename, linenum); 1520162856Sdes if (!*activep) { 1521162856Sdes arg = strdelim(&cp); 1522162856Sdes break; 1523162856Sdes } 152492559Sdes for (i = 0; i < options->num_subsystems; i++) 152592559Sdes if (strcmp(arg, options->subsystem_name[i]) == 0) 152692559Sdes fatal("%s line %d: Subsystem '%s' already defined.", 152792559Sdes filename, linenum, arg); 152892559Sdes options->subsystem_name[options->num_subsystems] = xstrdup(arg); 152992559Sdes arg = strdelim(&cp); 153092559Sdes if (!arg || *arg == '\0') 153192559Sdes fatal("%s line %d: Missing subsystem command.", 153292559Sdes filename, linenum); 153392559Sdes options->subsystem_command[options->num_subsystems] = xstrdup(arg); 1534162856Sdes 1535162856Sdes /* Collect arguments (separate to executable) */ 1536162856Sdes p = xstrdup(arg); 1537162856Sdes len = strlen(p) + 1; 1538162856Sdes while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { 1539162856Sdes len += 1 + strlen(arg); 1540295367Sdes p = xreallocarray(p, 1, len); 1541162856Sdes strlcat(p, " ", len); 1542162856Sdes strlcat(p, arg, len); 1543162856Sdes } 1544162856Sdes options->subsystem_args[options->num_subsystems] = p; 154592559Sdes options->num_subsystems++; 154692559Sdes break; 154760576Skris 154892559Sdes case sMaxStartups: 154992559Sdes arg = strdelim(&cp); 155092559Sdes if (!arg || *arg == '\0') 155192559Sdes fatal("%s line %d: Missing MaxStartups spec.", 155292559Sdes filename, linenum); 155392559Sdes if ((n = sscanf(arg, "%d:%d:%d", 155492559Sdes &options->max_startups_begin, 155592559Sdes &options->max_startups_rate, 155692559Sdes &options->max_startups)) == 3) { 155792559Sdes if (options->max_startups_begin > 155892559Sdes options->max_startups || 155992559Sdes options->max_startups_rate > 100 || 156092559Sdes options->max_startups_rate < 1) 156192559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 156292559Sdes filename, linenum); 156392559Sdes } else if (n != 1) 156492559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 156592559Sdes filename, linenum); 156692559Sdes else 156792559Sdes options->max_startups = options->max_startups_begin; 156892559Sdes break; 156976262Sgreen 1570137019Sdes case sMaxAuthTries: 1571137019Sdes intptr = &options->max_authtries; 1572137019Sdes goto parse_int; 1573137019Sdes 1574181111Sdes case sMaxSessions: 1575181111Sdes intptr = &options->max_sessions; 1576181111Sdes goto parse_int; 1577181111Sdes 157892559Sdes case sBanner: 157992559Sdes charptr = &options->banner; 158092559Sdes goto parse_filename; 1581181111Sdes 158292559Sdes /* 158392559Sdes * These options can contain %X options expanded at 158492559Sdes * connect time, so that you can specify paths like: 158592559Sdes * 158692559Sdes * AuthorizedKeysFile /etc/ssh_keys/%u 158792559Sdes */ 158892559Sdes case sAuthorizedKeysFile: 1589226046Sdes if (*activep && options->num_authkeys_files == 0) { 1590226046Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1591226046Sdes if (options->num_authkeys_files >= 1592226046Sdes MAX_AUTHKEYS_FILES) 1593226046Sdes fatal("%s line %d: " 1594226046Sdes "too many authorized keys files.", 1595226046Sdes filename, linenum); 1596226046Sdes options->authorized_keys_files[ 1597226046Sdes options->num_authkeys_files++] = 1598226046Sdes tilde_expand_filename(arg, getuid()); 1599226046Sdes } 1600226046Sdes } 1601226046Sdes return 0; 1602226046Sdes 1603215116Sdes case sAuthorizedPrincipalsFile: 1604215116Sdes charptr = &options->authorized_principals_file; 1605207319Sdes arg = strdelim(&cp); 1606207319Sdes if (!arg || *arg == '\0') 1607207319Sdes fatal("%s line %d: missing file name.", 1608207319Sdes filename, linenum); 1609207319Sdes if (*activep && *charptr == NULL) { 1610207319Sdes *charptr = tilde_expand_filename(arg, getuid()); 1611207319Sdes /* increase optional counter */ 1612207319Sdes if (intptr != NULL) 1613207319Sdes *intptr = *intptr + 1; 1614207319Sdes } 1615207319Sdes break; 161660576Skris 161792559Sdes case sClientAliveInterval: 161892559Sdes intptr = &options->client_alive_interval; 161992559Sdes goto parse_time; 162057432Smarkm 162192559Sdes case sClientAliveCountMax: 162292559Sdes intptr = &options->client_alive_count_max; 162392559Sdes goto parse_int; 162465674Skris 1625137019Sdes case sAcceptEnv: 1626137019Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1627137019Sdes if (strchr(arg, '=') != NULL) 1628137019Sdes fatal("%s line %d: Invalid environment name.", 1629137019Sdes filename, linenum); 1630137019Sdes if (options->num_accept_env >= MAX_ACCEPT_ENV) 1631137019Sdes fatal("%s line %d: too many allow env.", 1632137019Sdes filename, linenum); 1633162856Sdes if (!*activep) 1634240075Sdes continue; 1635137019Sdes options->accept_env[options->num_accept_env++] = 1636137019Sdes xstrdup(arg); 1637137019Sdes } 1638137019Sdes break; 1639137019Sdes 1640157019Sdes case sPermitTunnel: 1641157019Sdes intptr = &options->permit_tun; 1642157019Sdes arg = strdelim(&cp); 1643157019Sdes if (!arg || *arg == '\0') 1644157019Sdes fatal("%s line %d: Missing yes/point-to-point/" 1645157019Sdes "ethernet/no argument.", filename, linenum); 1646181111Sdes value = -1; 1647181111Sdes for (i = 0; tunmode_desc[i].val != -1; i++) 1648181111Sdes if (strcmp(tunmode_desc[i].text, arg) == 0) { 1649181111Sdes value = tunmode_desc[i].val; 1650181111Sdes break; 1651181111Sdes } 1652181111Sdes if (value == -1) 1653157019Sdes fatal("%s line %d: Bad yes/point-to-point/ethernet/" 1654157019Sdes "no argument: %s", filename, linenum, arg); 1655295367Sdes if (*activep && *intptr == -1) 1656157019Sdes *intptr = value; 1657157019Sdes break; 1658157019Sdes 1659162856Sdes case sMatch: 1660162856Sdes if (cmdline) 1661162856Sdes fatal("Match directive not supported as a command-line " 1662162856Sdes "option"); 1663240075Sdes value = match_cfg_line(&cp, linenum, connectinfo); 1664162856Sdes if (value < 0) 1665162856Sdes fatal("%s line %d: Bad Match condition", filename, 1666162856Sdes linenum); 1667162856Sdes *activep = value; 1668162856Sdes break; 1669162856Sdes 1670162856Sdes case sPermitOpen: 1671162856Sdes arg = strdelim(&cp); 1672162856Sdes if (!arg || *arg == '\0') 1673162856Sdes fatal("%s line %d: missing PermitOpen specification", 1674162856Sdes filename, linenum); 1675181111Sdes n = options->num_permitted_opens; /* modified later */ 1676162856Sdes if (strcmp(arg, "any") == 0) { 1677181111Sdes if (*activep && n == -1) { 1678162856Sdes channel_clear_adm_permitted_opens(); 1679162856Sdes options->num_permitted_opens = 0; 1680162856Sdes } 1681162856Sdes break; 1682162856Sdes } 1683240075Sdes if (strcmp(arg, "none") == 0) { 1684240075Sdes if (*activep && n == -1) { 1685240075Sdes options->num_permitted_opens = 1; 1686240075Sdes channel_disable_adm_local_opens(); 1687240075Sdes } 1688240075Sdes break; 1689240075Sdes } 1690181111Sdes if (*activep && n == -1) 1691181111Sdes channel_clear_adm_permitted_opens(); 1692162856Sdes for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { 1693162856Sdes p = hpdelim(&arg); 1694162856Sdes if (p == NULL) 1695162856Sdes fatal("%s line %d: missing host in PermitOpen", 1696162856Sdes filename, linenum); 1697162856Sdes p = cleanhostname(p); 1698240075Sdes if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 1699162856Sdes fatal("%s line %d: bad port number in " 1700162856Sdes "PermitOpen", filename, linenum); 1701181111Sdes if (*activep && n == -1) 1702162856Sdes options->num_permitted_opens = 1703162856Sdes channel_add_adm_permitted_opens(p, port); 1704162856Sdes } 1705162856Sdes break; 1706162856Sdes 1707162856Sdes case sForceCommand: 1708295367Sdes if (cp == NULL || *cp == '\0') 1709162856Sdes fatal("%.200s line %d: Missing argument.", filename, 1710162856Sdes linenum); 1711162856Sdes len = strspn(cp, WHITESPACE); 1712162856Sdes if (*activep && options->adm_forced_command == NULL) 1713162856Sdes options->adm_forced_command = xstrdup(cp + len); 1714162856Sdes return 0; 1715162856Sdes 1716181111Sdes case sChrootDirectory: 1717181111Sdes charptr = &options->chroot_directory; 1718181111Sdes 1719181111Sdes arg = strdelim(&cp); 1720181111Sdes if (!arg || *arg == '\0') 1721181111Sdes fatal("%s line %d: missing file name.", 1722181111Sdes filename, linenum); 1723181111Sdes if (*activep && *charptr == NULL) 1724181111Sdes *charptr = xstrdup(arg); 1725181111Sdes break; 1726181111Sdes 1727204917Sdes case sTrustedUserCAKeys: 1728204917Sdes charptr = &options->trusted_user_ca_keys; 1729204917Sdes goto parse_filename; 1730204917Sdes 1731204917Sdes case sRevokedKeys: 1732204917Sdes charptr = &options->revoked_keys_file; 1733204917Sdes goto parse_filename; 1734204917Sdes 1735221420Sdes case sIPQoS: 1736221420Sdes arg = strdelim(&cp); 1737221420Sdes if ((value = parse_ipqos(arg)) == -1) 1738221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1739221420Sdes filename, linenum, arg); 1740221420Sdes arg = strdelim(&cp); 1741221420Sdes if (arg == NULL) 1742221420Sdes value2 = value; 1743221420Sdes else if ((value2 = parse_ipqos(arg)) == -1) 1744221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1745221420Sdes filename, linenum, arg); 1746221420Sdes if (*activep) { 1747221420Sdes options->ip_qos_interactive = value; 1748221420Sdes options->ip_qos_bulk = value2; 1749221420Sdes } 1750221420Sdes break; 1751221420Sdes 175299047Sdes case sVersionAddendum: 1753295367Sdes if (cp == NULL || *cp == '\0') 1754240075Sdes fatal("%.200s line %d: Missing argument.", filename, 1755240075Sdes linenum); 1756240075Sdes len = strspn(cp, WHITESPACE); 1757240075Sdes if (*activep && options->version_addendum == NULL) { 1758240075Sdes if (strcasecmp(cp + len, "none") == 0) 1759240075Sdes options->version_addendum = xstrdup(""); 1760240075Sdes else if (strchr(cp + len, '\r') != NULL) 1761240075Sdes fatal("%.200s line %d: Invalid argument", 1762240075Sdes filename, linenum); 1763240075Sdes else 1764240075Sdes options->version_addendum = xstrdup(cp + len); 1765240075Sdes } 1766240075Sdes return 0; 176799047Sdes 1768248619Sdes case sAuthorizedKeysCommand: 1769295367Sdes if (cp == NULL) 1770295367Sdes fatal("%.200s line %d: Missing argument.", filename, 1771295367Sdes linenum); 1772248619Sdes len = strspn(cp, WHITESPACE); 1773248619Sdes if (*activep && options->authorized_keys_command == NULL) { 1774248619Sdes if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) 1775248619Sdes fatal("%.200s line %d: AuthorizedKeysCommand " 1776248619Sdes "must be an absolute path", 1777248619Sdes filename, linenum); 1778248619Sdes options->authorized_keys_command = xstrdup(cp + len); 1779248619Sdes } 1780248619Sdes return 0; 1781248619Sdes 1782248619Sdes case sAuthorizedKeysCommandUser: 1783248619Sdes charptr = &options->authorized_keys_command_user; 1784248619Sdes 1785248619Sdes arg = strdelim(&cp); 1786295367Sdes if (!arg || *arg == '\0') 1787295367Sdes fatal("%s line %d: missing AuthorizedKeysCommandUser " 1788295367Sdes "argument.", filename, linenum); 1789248619Sdes if (*activep && *charptr == NULL) 1790248619Sdes *charptr = xstrdup(arg); 1791248619Sdes break; 1792248619Sdes 1793295367Sdes case sAuthorizedPrincipalsCommand: 1794295367Sdes if (cp == NULL) 1795295367Sdes fatal("%.200s line %d: Missing argument.", filename, 1796295367Sdes linenum); 1797295367Sdes len = strspn(cp, WHITESPACE); 1798295367Sdes if (*activep && 1799295367Sdes options->authorized_principals_command == NULL) { 1800295367Sdes if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) 1801295367Sdes fatal("%.200s line %d: " 1802295367Sdes "AuthorizedPrincipalsCommand must be " 1803295367Sdes "an absolute path", filename, linenum); 1804295367Sdes options->authorized_principals_command = 1805295367Sdes xstrdup(cp + len); 1806295367Sdes } 1807295367Sdes return 0; 1808295367Sdes 1809295367Sdes case sAuthorizedPrincipalsCommandUser: 1810295367Sdes charptr = &options->authorized_principals_command_user; 1811295367Sdes 1812295367Sdes arg = strdelim(&cp); 1813295367Sdes if (!arg || *arg == '\0') 1814295367Sdes fatal("%s line %d: missing " 1815295367Sdes "AuthorizedPrincipalsCommandUser argument.", 1816295367Sdes filename, linenum); 1817295367Sdes if (*activep && *charptr == NULL) 1818295367Sdes *charptr = xstrdup(arg); 1819295367Sdes break; 1820295367Sdes 1821248619Sdes case sAuthenticationMethods: 1822295367Sdes if (options->num_auth_methods == 0) { 1823323124Sdes value = 0; /* seen "any" pseudo-method */ 1824323124Sdes value2 = 0; /* sucessfully parsed any method */ 1825248619Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1826248619Sdes if (options->num_auth_methods >= 1827248619Sdes MAX_AUTH_METHODS) 1828248619Sdes fatal("%s line %d: " 1829248619Sdes "too many authentication methods.", 1830248619Sdes filename, linenum); 1831323124Sdes if (strcmp(arg, "any") == 0) { 1832323124Sdes if (options->num_auth_methods > 0) { 1833323124Sdes fatal("%s line %d: \"any\" " 1834323124Sdes "must appear alone in " 1835323124Sdes "AuthenticationMethods", 1836323124Sdes filename, linenum); 1837323124Sdes } 1838323124Sdes value = 1; 1839323124Sdes } else if (value) { 1840323124Sdes fatal("%s line %d: \"any\" must appear " 1841323124Sdes "alone in AuthenticationMethods", 1842323124Sdes filename, linenum); 1843323124Sdes } else if (auth2_methods_valid(arg, 0) != 0) { 1844248619Sdes fatal("%s line %d: invalid " 1845248619Sdes "authentication method list.", 1846248619Sdes filename, linenum); 1847323124Sdes } 1848323124Sdes value2 = 1; 1849295367Sdes if (!*activep) 1850295367Sdes continue; 1851248619Sdes options->auth_methods[ 1852248619Sdes options->num_auth_methods++] = xstrdup(arg); 1853248619Sdes } 1854323124Sdes if (value2 == 0) { 1855323124Sdes fatal("%s line %d: no AuthenticationMethods " 1856323124Sdes "specified", filename, linenum); 1857323124Sdes } 1858248619Sdes } 1859248619Sdes return 0; 1860248619Sdes 1861295367Sdes case sStreamLocalBindMask: 1862295367Sdes arg = strdelim(&cp); 1863295367Sdes if (!arg || *arg == '\0') 1864295367Sdes fatal("%s line %d: missing StreamLocalBindMask " 1865295367Sdes "argument.", filename, linenum); 1866295367Sdes /* Parse mode in octal format */ 1867295367Sdes value = strtol(arg, &p, 8); 1868295367Sdes if (arg == p || value < 0 || value > 0777) 1869295367Sdes fatal("%s line %d: Bad mask.", filename, linenum); 1870295367Sdes if (*activep) 1871295367Sdes options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 1872295367Sdes break; 1873295367Sdes 1874295367Sdes case sStreamLocalBindUnlink: 1875295367Sdes intptr = &options->fwd_opts.streamlocal_bind_unlink; 1876295367Sdes goto parse_flag; 1877295367Sdes 1878295367Sdes case sFingerprintHash: 1879295367Sdes arg = strdelim(&cp); 1880295367Sdes if (!arg || *arg == '\0') 1881295367Sdes fatal("%.200s line %d: Missing argument.", 1882295367Sdes filename, linenum); 1883295367Sdes if ((value = ssh_digest_alg_by_name(arg)) == -1) 1884295367Sdes fatal("%.200s line %d: Invalid hash algorithm \"%s\".", 1885295367Sdes filename, linenum, arg); 1886295367Sdes if (*activep) 1887295367Sdes options->fingerprint_hash = value; 1888295367Sdes break; 1889295367Sdes 189092559Sdes case sDeprecated: 1891124211Sdes logit("%s line %d: Deprecated option %s", 189292559Sdes filename, linenum, arg); 189392559Sdes while (arg) 189492559Sdes arg = strdelim(&cp); 189592559Sdes break; 189692559Sdes 1897124211Sdes case sUnsupported: 1898124211Sdes logit("%s line %d: Unsupported option %s", 1899124211Sdes filename, linenum, arg); 1900124211Sdes while (arg) 1901124211Sdes arg = strdelim(&cp); 1902124211Sdes break; 1903124211Sdes 190492559Sdes default: 190592559Sdes fatal("%s line %d: Missing handler for opcode %s (%d)", 190692559Sdes filename, linenum, arg, opcode); 190792559Sdes } 190892559Sdes if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 190992559Sdes fatal("%s line %d: garbage at end of line; \"%.200s\".", 191092559Sdes filename, linenum, arg); 191192559Sdes return 0; 191292559Sdes} 191376227Sgreen 191492559Sdes/* Reads the server configuration file. */ 191592559Sdes 191692559Sdesvoid 1917137019Sdesload_server_config(const char *filename, Buffer *conf) 191892559Sdes{ 1919240075Sdes char line[4096], *cp; 192092559Sdes FILE *f; 1921240075Sdes int lineno = 0; 192292559Sdes 1923137019Sdes debug2("%s: filename %s", __func__, filename); 1924137019Sdes if ((f = fopen(filename, "r")) == NULL) { 192592559Sdes perror(filename); 192692559Sdes exit(1); 192757429Smarkm } 1928137019Sdes buffer_clear(conf); 192992559Sdes while (fgets(line, sizeof(line), f)) { 1930240075Sdes lineno++; 1931240075Sdes if (strlen(line) == sizeof(line) - 1) 1932240075Sdes fatal("%s line %d too long", filename, lineno); 1933137019Sdes /* 1934137019Sdes * Trim out comments and strip whitespace 1935137019Sdes * NB - preserve newlines, they are needed to reproduce 1936137019Sdes * line numbers later for error messages 1937137019Sdes */ 1938137019Sdes if ((cp = strchr(line, '#')) != NULL) 1939137019Sdes memcpy(cp, "\n", 2); 1940137019Sdes cp = line + strspn(line, " \t\r"); 1941137019Sdes 1942137019Sdes buffer_append(conf, cp, strlen(cp)); 1943137019Sdes } 1944137019Sdes buffer_append(conf, "\0", 1); 1945137019Sdes fclose(f); 1946137019Sdes debug2("%s: done config len = %d", __func__, buffer_len(conf)); 1947137019Sdes} 1948137019Sdes 1949137019Sdesvoid 1950240075Sdesparse_server_match_config(ServerOptions *options, 1951240075Sdes struct connection_info *connectinfo) 1952137019Sdes{ 1953162856Sdes ServerOptions mo; 1954162856Sdes 1955162856Sdes initialize_server_options(&mo); 1956240075Sdes parse_server_config(&mo, "reprocess config", &cfg, connectinfo); 1957181111Sdes copy_set_server_options(options, &mo, 0); 1958162856Sdes} 1959162856Sdes 1960240075Sdesint parse_server_match_testspec(struct connection_info *ci, char *spec) 1961240075Sdes{ 1962240075Sdes char *p; 1963240075Sdes 1964240075Sdes while ((p = strsep(&spec, ",")) && *p != '\0') { 1965240075Sdes if (strncmp(p, "addr=", 5) == 0) { 1966240075Sdes ci->address = xstrdup(p + 5); 1967240075Sdes } else if (strncmp(p, "host=", 5) == 0) { 1968240075Sdes ci->host = xstrdup(p + 5); 1969240075Sdes } else if (strncmp(p, "user=", 5) == 0) { 1970240075Sdes ci->user = xstrdup(p + 5); 1971240075Sdes } else if (strncmp(p, "laddr=", 6) == 0) { 1972240075Sdes ci->laddress = xstrdup(p + 6); 1973240075Sdes } else if (strncmp(p, "lport=", 6) == 0) { 1974240075Sdes ci->lport = a2port(p + 6); 1975240075Sdes if (ci->lport == -1) { 1976240075Sdes fprintf(stderr, "Invalid port '%s' in test mode" 1977240075Sdes " specification %s\n", p+6, p); 1978240075Sdes return -1; 1979240075Sdes } 1980240075Sdes } else { 1981240075Sdes fprintf(stderr, "Invalid test mode specification %s\n", 1982240075Sdes p); 1983240075Sdes return -1; 1984240075Sdes } 1985240075Sdes } 1986240075Sdes return 0; 1987240075Sdes} 1988240075Sdes 1989240075Sdes/* 1990240075Sdes * returns 1 for a complete spec, 0 for partial spec and -1 for an 1991240075Sdes * empty spec. 1992240075Sdes */ 1993240075Sdesint server_match_spec_complete(struct connection_info *ci) 1994240075Sdes{ 1995240075Sdes if (ci->user && ci->host && ci->address) 1996240075Sdes return 1; /* complete */ 1997240075Sdes if (!ci->user && !ci->host && !ci->address) 1998240075Sdes return -1; /* empty */ 1999240075Sdes return 0; /* partial */ 2000240075Sdes} 2001240075Sdes 2002181111Sdes/* 2003181111Sdes * Copy any supported values that are set. 2004181111Sdes * 2005197679Sdes * If the preauth flag is set, we do not bother copying the string or 2006181111Sdes * array values that are not used pre-authentication, because any that we 2007181111Sdes * do use must be explictly sent in mm_getpwnamallow(). 2008181111Sdes */ 2009162856Sdesvoid 2010181111Sdescopy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) 2011162856Sdes{ 2012262566Sdes#define M_CP_INTOPT(n) do {\ 2013262566Sdes if (src->n != -1) \ 2014262566Sdes dst->n = src->n; \ 2015262566Sdes} while (0) 2016262566Sdes 2017181111Sdes M_CP_INTOPT(password_authentication); 2018181111Sdes M_CP_INTOPT(gss_authentication); 2019181111Sdes M_CP_INTOPT(rsa_authentication); 2020181111Sdes M_CP_INTOPT(pubkey_authentication); 2021181111Sdes M_CP_INTOPT(kerberos_authentication); 2022181111Sdes M_CP_INTOPT(hostbased_authentication); 2023215116Sdes M_CP_INTOPT(hostbased_uses_name_from_packet_only); 2024181111Sdes M_CP_INTOPT(kbd_interactive_authentication); 2025181111Sdes M_CP_INTOPT(permit_root_login); 2026192595Sdes M_CP_INTOPT(permit_empty_passwd); 2027181111Sdes 2028181111Sdes M_CP_INTOPT(allow_tcp_forwarding); 2029295367Sdes M_CP_INTOPT(allow_streamlocal_forwarding); 2030181111Sdes M_CP_INTOPT(allow_agent_forwarding); 2031215116Sdes M_CP_INTOPT(permit_tun); 2032295367Sdes M_CP_INTOPT(fwd_opts.gateway_ports); 2033323124Sdes M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); 2034181111Sdes M_CP_INTOPT(x11_display_offset); 2035181111Sdes M_CP_INTOPT(x11_forwarding); 2036181111Sdes M_CP_INTOPT(x11_use_localhost); 2037262566Sdes M_CP_INTOPT(permit_tty); 2038295367Sdes M_CP_INTOPT(permit_user_rc); 2039181111Sdes M_CP_INTOPT(max_sessions); 2040181111Sdes M_CP_INTOPT(max_authtries); 2041221420Sdes M_CP_INTOPT(ip_qos_interactive); 2042221420Sdes M_CP_INTOPT(ip_qos_bulk); 2043255767Sdes M_CP_INTOPT(rekey_limit); 2044255767Sdes M_CP_INTOPT(rekey_interval); 2045181111Sdes 2046323124Sdes /* 2047323124Sdes * The bind_mask is a mode_t that may be unsigned, so we can't use 2048323124Sdes * M_CP_INTOPT - it does a signed comparison that causes compiler 2049323124Sdes * warnings. 2050323124Sdes */ 2051323124Sdes if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) { 2052323124Sdes dst->fwd_opts.streamlocal_bind_mask = 2053323124Sdes src->fwd_opts.streamlocal_bind_mask; 2054323124Sdes } 2055323124Sdes 2056262566Sdes /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ 2057262566Sdes#define M_CP_STROPT(n) do {\ 2058262566Sdes if (src->n != NULL && dst->n != src->n) { \ 2059262566Sdes free(dst->n); \ 2060262566Sdes dst->n = src->n; \ 2061262566Sdes } \ 2062262566Sdes} while(0) 2063262566Sdes#define M_CP_STRARRAYOPT(n, num_n) do {\ 2064262566Sdes if (src->num_n != 0) { \ 2065262566Sdes for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \ 2066262566Sdes dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ 2067262566Sdes } \ 2068262566Sdes} while(0) 2069262566Sdes 2070226046Sdes /* See comment in servconf.h */ 2071226046Sdes COPY_MATCH_STRING_OPTS(); 2072226046Sdes 2073296781Sdes /* Arguments that accept '+...' need to be expanded */ 2074296781Sdes assemble_algorithms(dst); 2075296781Sdes 2076226046Sdes /* 2077226046Sdes * The only things that should be below this point are string options 2078226046Sdes * which are only used after authentication. 2079226046Sdes */ 2080181111Sdes if (preauth) 2081181111Sdes return; 2082226046Sdes 2083296781Sdes /* These options may be "none" to clear a global setting */ 2084181111Sdes M_CP_STROPT(adm_forced_command); 2085296781Sdes if (option_clear_or_none(dst->adm_forced_command)) { 2086296781Sdes free(dst->adm_forced_command); 2087296781Sdes dst->adm_forced_command = NULL; 2088296781Sdes } 2089181111Sdes M_CP_STROPT(chroot_directory); 2090296781Sdes if (option_clear_or_none(dst->chroot_directory)) { 2091296781Sdes free(dst->chroot_directory); 2092296781Sdes dst->chroot_directory = NULL; 2093296781Sdes } 2094162856Sdes} 2095162856Sdes 2096181111Sdes#undef M_CP_INTOPT 2097181111Sdes#undef M_CP_STROPT 2098226046Sdes#undef M_CP_STRARRAYOPT 2099181111Sdes 2100162856Sdesvoid 2101162856Sdesparse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 2102240075Sdes struct connection_info *connectinfo) 2103162856Sdes{ 2104162856Sdes int active, linenum, bad_options = 0; 2105137019Sdes char *cp, *obuf, *cbuf; 2106137019Sdes 2107137019Sdes debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); 2108137019Sdes 2109323124Sdes if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) 2110323124Sdes fatal("%s: sshbuf_dup_string failed", __func__); 2111240075Sdes active = connectinfo ? 0 : 1; 2112137019Sdes linenum = 1; 2113147005Sdes while ((cp = strsep(&cbuf, "\n")) != NULL) { 2114137019Sdes if (process_server_config_line(options, cp, filename, 2115240075Sdes linenum++, &active, connectinfo) != 0) 211692559Sdes bad_options++; 211792559Sdes } 2118255767Sdes free(obuf); 211976262Sgreen if (bad_options > 0) 212092559Sdes fatal("%s: terminating, %d bad configuration options", 212176262Sgreen filename, bad_options); 2122295367Sdes process_queued_listen_addrs(options); 212357429Smarkm} 2124181111Sdes 2125181111Sdesstatic const char * 2126226046Sdesfmt_multistate_int(int val, const struct multistate *m) 2127226046Sdes{ 2128226046Sdes u_int i; 2129226046Sdes 2130226046Sdes for (i = 0; m[i].key != NULL; i++) { 2131226046Sdes if (m[i].value == val) 2132226046Sdes return m[i].key; 2133226046Sdes } 2134226046Sdes return "UNKNOWN"; 2135226046Sdes} 2136226046Sdes 2137226046Sdesstatic const char * 2138181111Sdesfmt_intarg(ServerOpCodes code, int val) 2139181111Sdes{ 2140226046Sdes if (val == -1) 2141226046Sdes return "unset"; 2142226046Sdes switch (code) { 2143226046Sdes case sAddressFamily: 2144226046Sdes return fmt_multistate_int(val, multistate_addressfamily); 2145226046Sdes case sPermitRootLogin: 2146226046Sdes return fmt_multistate_int(val, multistate_permitrootlogin); 2147226046Sdes case sGatewayPorts: 2148226046Sdes return fmt_multistate_int(val, multistate_gatewayports); 2149226046Sdes case sCompression: 2150226046Sdes return fmt_multistate_int(val, multistate_compression); 2151226046Sdes case sUsePrivilegeSeparation: 2152226046Sdes return fmt_multistate_int(val, multistate_privsep); 2153248619Sdes case sAllowTcpForwarding: 2154248619Sdes return fmt_multistate_int(val, multistate_tcpfwd); 2155295367Sdes case sAllowStreamLocalForwarding: 2156295367Sdes return fmt_multistate_int(val, multistate_tcpfwd); 2157295367Sdes case sFingerprintHash: 2158295367Sdes return ssh_digest_alg_name(val); 2159226046Sdes case sProtocol: 2160181111Sdes switch (val) { 2161181111Sdes case SSH_PROTO_1: 2162181111Sdes return "1"; 2163181111Sdes case SSH_PROTO_2: 2164181111Sdes return "2"; 2165181111Sdes case (SSH_PROTO_1|SSH_PROTO_2): 2166181111Sdes return "2,1"; 2167181111Sdes default: 2168181111Sdes return "UNKNOWN"; 2169181111Sdes } 2170226046Sdes default: 2171226046Sdes switch (val) { 2172226046Sdes case 0: 2173226046Sdes return "no"; 2174226046Sdes case 1: 2175226046Sdes return "yes"; 2176226046Sdes default: 2177226046Sdes return "UNKNOWN"; 2178226046Sdes } 2179181111Sdes } 2180181111Sdes} 2181181111Sdes 2182181111Sdesstatic const char * 2183181111Sdeslookup_opcode_name(ServerOpCodes code) 2184181111Sdes{ 2185181111Sdes u_int i; 2186181111Sdes 2187181111Sdes for (i = 0; keywords[i].name != NULL; i++) 2188181111Sdes if (keywords[i].opcode == code) 2189181111Sdes return(keywords[i].name); 2190181111Sdes return "UNKNOWN"; 2191181111Sdes} 2192181111Sdes 2193181111Sdesstatic void 2194181111Sdesdump_cfg_int(ServerOpCodes code, int val) 2195181111Sdes{ 2196181111Sdes printf("%s %d\n", lookup_opcode_name(code), val); 2197181111Sdes} 2198181111Sdes 2199181111Sdesstatic void 2200295367Sdesdump_cfg_oct(ServerOpCodes code, int val) 2201295367Sdes{ 2202295367Sdes printf("%s 0%o\n", lookup_opcode_name(code), val); 2203295367Sdes} 2204295367Sdes 2205295367Sdesstatic void 2206181111Sdesdump_cfg_fmtint(ServerOpCodes code, int val) 2207181111Sdes{ 2208181111Sdes printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2209181111Sdes} 2210181111Sdes 2211181111Sdesstatic void 2212181111Sdesdump_cfg_string(ServerOpCodes code, const char *val) 2213181111Sdes{ 2214181111Sdes if (val == NULL) 2215181111Sdes return; 2216295367Sdes printf("%s %s\n", lookup_opcode_name(code), 2217295367Sdes val == NULL ? "none" : val); 2218181111Sdes} 2219181111Sdes 2220181111Sdesstatic void 2221181111Sdesdump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) 2222181111Sdes{ 2223181111Sdes u_int i; 2224181111Sdes 2225181111Sdes for (i = 0; i < count; i++) 2226226046Sdes printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2227181111Sdes} 2228181111Sdes 2229226046Sdesstatic void 2230226046Sdesdump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) 2231226046Sdes{ 2232226046Sdes u_int i; 2233226046Sdes 2234323124Sdes if (count <= 0 && code != sAuthenticationMethods) 2235295367Sdes return; 2236226046Sdes printf("%s", lookup_opcode_name(code)); 2237226046Sdes for (i = 0; i < count; i++) 2238226046Sdes printf(" %s", vals[i]); 2239323124Sdes if (code == sAuthenticationMethods && count == 0) 2240323124Sdes printf(" any"); 2241226046Sdes printf("\n"); 2242226046Sdes} 2243226046Sdes 2244181111Sdesvoid 2245181111Sdesdump_config(ServerOptions *o) 2246181111Sdes{ 2247181111Sdes u_int i; 2248181111Sdes int ret; 2249181111Sdes struct addrinfo *ai; 2250181111Sdes char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL; 2251295367Sdes char *laddr1 = xstrdup(""), *laddr2 = NULL; 2252181111Sdes 2253181111Sdes /* these are usually at the top of the config */ 2254181111Sdes for (i = 0; i < o->num_ports; i++) 2255181111Sdes printf("port %d\n", o->ports[i]); 2256181111Sdes dump_cfg_fmtint(sProtocol, o->protocol); 2257181111Sdes dump_cfg_fmtint(sAddressFamily, o->address_family); 2258181111Sdes 2259295367Sdes /* 2260295367Sdes * ListenAddress must be after Port. add_one_listen_addr pushes 2261295367Sdes * addresses onto a stack, so to maintain ordering we need to 2262295367Sdes * print these in reverse order. 2263295367Sdes */ 2264181111Sdes for (ai = o->listen_addrs; ai; ai = ai->ai_next) { 2265181111Sdes if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, 2266181111Sdes sizeof(addr), port, sizeof(port), 2267181111Sdes NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { 2268181111Sdes error("getnameinfo failed: %.100s", 2269181111Sdes (ret != EAI_SYSTEM) ? gai_strerror(ret) : 2270181111Sdes strerror(errno)); 2271181111Sdes } else { 2272295367Sdes laddr2 = laddr1; 2273181111Sdes if (ai->ai_family == AF_INET6) 2274295367Sdes xasprintf(&laddr1, "listenaddress [%s]:%s\n%s", 2275295367Sdes addr, port, laddr2); 2276181111Sdes else 2277295367Sdes xasprintf(&laddr1, "listenaddress %s:%s\n%s", 2278295367Sdes addr, port, laddr2); 2279295367Sdes free(laddr2); 2280181111Sdes } 2281181111Sdes } 2282295367Sdes printf("%s", laddr1); 2283295367Sdes free(laddr1); 2284181111Sdes 2285181111Sdes /* integer arguments */ 2286192595Sdes#ifdef USE_PAM 2287295367Sdes dump_cfg_fmtint(sUsePAM, o->use_pam); 2288192595Sdes#endif 2289181111Sdes dump_cfg_int(sServerKeyBits, o->server_key_bits); 2290181111Sdes dump_cfg_int(sLoginGraceTime, o->login_grace_time); 2291181111Sdes dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time); 2292181111Sdes dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); 2293181111Sdes dump_cfg_int(sMaxAuthTries, o->max_authtries); 2294192595Sdes dump_cfg_int(sMaxSessions, o->max_sessions); 2295181111Sdes dump_cfg_int(sClientAliveInterval, o->client_alive_interval); 2296181111Sdes dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); 2297295367Sdes dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); 2298181111Sdes 2299181111Sdes /* formatted integer arguments */ 2300181111Sdes dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); 2301181111Sdes dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); 2302181111Sdes dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); 2303181111Sdes dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication); 2304181111Sdes dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); 2305181111Sdes dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, 2306181111Sdes o->hostbased_uses_name_from_packet_only); 2307181111Sdes dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication); 2308181111Sdes dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); 2309192595Sdes#ifdef KRB5 2310181111Sdes dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); 2311181111Sdes dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); 2312181111Sdes dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); 2313192595Sdes# ifdef USE_AFS 2314181111Sdes dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); 2315192595Sdes# endif 2316192595Sdes#endif 2317192595Sdes#ifdef GSSAPI 2318181111Sdes dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 2319181111Sdes dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 2320192595Sdes#endif 2321181111Sdes dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 2322181111Sdes dump_cfg_fmtint(sKbdInteractiveAuthentication, 2323181111Sdes o->kbd_interactive_authentication); 2324181111Sdes dump_cfg_fmtint(sChallengeResponseAuthentication, 2325181111Sdes o->challenge_response_authentication); 2326181111Sdes dump_cfg_fmtint(sPrintMotd, o->print_motd); 2327296781Sdes#ifndef DISABLE_LASTLOG 2328181111Sdes dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); 2329296781Sdes#endif 2330181111Sdes dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); 2331181111Sdes dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); 2332262566Sdes dump_cfg_fmtint(sPermitTTY, o->permit_tty); 2333295367Sdes dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); 2334181111Sdes dump_cfg_fmtint(sStrictModes, o->strict_modes); 2335181111Sdes dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); 2336181111Sdes dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); 2337181111Sdes dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 2338181111Sdes dump_cfg_fmtint(sUseLogin, o->use_login); 2339181111Sdes dump_cfg_fmtint(sCompression, o->compression); 2340295367Sdes dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); 2341181111Sdes dump_cfg_fmtint(sUseDNS, o->use_dns); 2342181111Sdes dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 2343295367Sdes dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); 2344295367Sdes dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); 2345323124Sdes dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2346181111Sdes dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); 2347295367Sdes dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); 2348181111Sdes 2349181111Sdes /* string arguments */ 2350181111Sdes dump_cfg_string(sPidFile, o->pid_file); 2351181111Sdes dump_cfg_string(sXAuthLocation, o->xauth_location); 2352295367Sdes dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT); 2353295367Sdes dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC); 2354181111Sdes dump_cfg_string(sBanner, o->banner); 2355181111Sdes dump_cfg_string(sForceCommand, o->adm_forced_command); 2356204917Sdes dump_cfg_string(sChrootDirectory, o->chroot_directory); 2357204917Sdes dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); 2358204917Sdes dump_cfg_string(sRevokedKeys, o->revoked_keys_file); 2359215116Sdes dump_cfg_string(sAuthorizedPrincipalsFile, 2360215116Sdes o->authorized_principals_file); 2361295367Sdes dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' 2362295367Sdes ? "none" : o->version_addendum); 2363248619Sdes dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); 2364248619Sdes dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); 2365295367Sdes dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); 2366295367Sdes dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); 2367255767Sdes dump_cfg_string(sHostKeyAgent, o->host_key_agent); 2368295367Sdes dump_cfg_string(sKexAlgorithms, 2369295367Sdes o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX); 2370295367Sdes dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ? 2371295367Sdes o->hostbased_key_types : KEX_DEFAULT_PK_ALG); 2372295367Sdes dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ? 2373295367Sdes o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); 2374295367Sdes dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ? 2375295367Sdes o->pubkey_key_types : KEX_DEFAULT_PK_ALG); 2376181111Sdes 2377181111Sdes /* string arguments requiring a lookup */ 2378181111Sdes dump_cfg_string(sLogLevel, log_level_name(o->log_level)); 2379181111Sdes dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); 2380181111Sdes 2381181111Sdes /* string array arguments */ 2382226046Sdes dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, 2383226046Sdes o->authorized_keys_files); 2384181111Sdes dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, 2385181111Sdes o->host_key_files); 2386295367Sdes dump_cfg_strarray(sHostCertificate, o->num_host_cert_files, 2387204917Sdes o->host_cert_files); 2388181111Sdes dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); 2389181111Sdes dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); 2390181111Sdes dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); 2391181111Sdes dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); 2392181111Sdes dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); 2393248619Sdes dump_cfg_strarray_oneline(sAuthenticationMethods, 2394248619Sdes o->num_auth_methods, o->auth_methods); 2395181111Sdes 2396181111Sdes /* other arguments */ 2397181111Sdes for (i = 0; i < o->num_subsystems; i++) 2398181111Sdes printf("subsystem %s %s\n", o->subsystem_name[i], 2399181111Sdes o->subsystem_args[i]); 2400181111Sdes 2401181111Sdes printf("maxstartups %d:%d:%d\n", o->max_startups_begin, 2402181111Sdes o->max_startups_rate, o->max_startups); 2403181111Sdes 2404181111Sdes for (i = 0; tunmode_desc[i].val != -1; i++) 2405181111Sdes if (tunmode_desc[i].val == o->permit_tun) { 2406181111Sdes s = tunmode_desc[i].text; 2407181111Sdes break; 2408181111Sdes } 2409181111Sdes dump_cfg_string(sPermitTunnel, s); 2410181111Sdes 2411226046Sdes printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2412226046Sdes printf("%s\n", iptos2str(o->ip_qos_bulk)); 2413221420Sdes 2414296781Sdes printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, 2415255767Sdes o->rekey_interval); 2416255767Sdes 2417181111Sdes channel_print_adm_permitted_opens(); 2418181111Sdes} 2419