1240075Sdes 2264377Sdes/* $OpenBSD: servconf.c,v 1.249 2014/01/29 06:18:35 djm Exp $ */ 3224638Sbrooks/* $FreeBSD$ */ 457429Smarkm/* 557429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 657429Smarkm * All rights reserved 760576Skris * 865674Skris * As far as I am concerned, the code I have written for this software 965674Skris * can be used freely for any purpose. Any derived versions of this 1065674Skris * software must be clearly marked as such, and if the derived work is 1165674Skris * incompatible with the protocol description in the RFC file, it must be 1265674Skris * called by a name other than "ssh" or "Secure Shell". 1357429Smarkm */ 1457429Smarkm 1557429Smarkm#include "includes.h" 16162856Sdes__RCSID("$FreeBSD$"); 1757429Smarkm 18162856Sdes#include <sys/types.h> 19162856Sdes#include <sys/socket.h> 20162856Sdes 21221420Sdes#include <netinet/in.h> 22221420Sdes#include <netinet/in_systm.h> 23221420Sdes#include <netinet/ip.h> 24221420Sdes 25255767Sdes#include <ctype.h> 26162856Sdes#include <netdb.h> 27162856Sdes#include <pwd.h> 28162856Sdes#include <stdio.h> 29162856Sdes#include <stdlib.h> 30162856Sdes#include <string.h> 31162856Sdes#include <signal.h> 32162856Sdes#include <unistd.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" 4457429Smarkm#include "servconf.h" 4560576Skris#include "compat.h" 4676262Sgreen#include "pathnames.h" 4776262Sgreen#include "misc.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" 59204917Sdes#include "version.h" 6057429Smarkm 61192595Sdesstatic void add_listen_addr(ServerOptions *, char *, int); 62192595Sdesstatic void add_one_listen_addr(ServerOptions *, char *, int); 6357429Smarkm 6498684Sdes/* Use of privilege separation or not */ 6598684Sdesextern int use_privsep; 66162856Sdesextern Buffer cfg; 6776262Sgreen 6857429Smarkm/* Initializes the server options to their default values. */ 6957429Smarkm 7060576Skrisvoid 7157429Smarkminitialize_server_options(ServerOptions *options) 7257429Smarkm{ 7357429Smarkm memset(options, 0, sizeof(*options)); 7498941Sdes 7598941Sdes /* Portable-specific options */ 76124211Sdes options->use_pam = -1; 7798941Sdes 7898941Sdes /* Standard Options */ 7957429Smarkm options->num_ports = 0; 8057429Smarkm options->ports_from_cmdline = 0; 8157429Smarkm options->listen_addrs = NULL; 82147005Sdes options->address_family = -1; 8376262Sgreen options->num_host_key_files = 0; 84204917Sdes options->num_host_cert_files = 0; 85255767Sdes options->host_key_agent = NULL; 8660576Skris options->pid_file = NULL; 8757429Smarkm options->server_key_bits = -1; 8857429Smarkm options->login_grace_time = -1; 8957429Smarkm options->key_regeneration_time = -1; 9076262Sgreen options->permit_root_login = PERMIT_NOT_SET; 9157429Smarkm options->ignore_rhosts = -1; 9257429Smarkm options->ignore_user_known_hosts = -1; 9357429Smarkm options->print_motd = -1; 9476262Sgreen options->print_lastlog = -1; 9557429Smarkm options->x11_forwarding = -1; 9657429Smarkm options->x11_display_offset = -1; 9792559Sdes options->x11_use_localhost = -1; 98262566Sdes options->permit_tty = -1; 9965674Skris options->xauth_location = NULL; 10057429Smarkm options->strict_modes = -1; 101126277Sdes options->tcp_keep_alive = -1; 10292559Sdes options->log_facility = SYSLOG_FACILITY_NOT_SET; 10392559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 10457429Smarkm options->rhosts_rsa_authentication = -1; 10576262Sgreen options->hostbased_authentication = -1; 10676262Sgreen options->hostbased_uses_name_from_packet_only = -1; 10757429Smarkm options->rsa_authentication = -1; 10876262Sgreen options->pubkey_authentication = -1; 10973400Sassar options->kerberos_authentication = -1; 11092559Sdes options->kerberos_or_local_passwd = -1; 11192559Sdes options->kerberos_ticket_cleanup = -1; 112126277Sdes options->kerberos_get_afs_token = -1; 113124211Sdes options->gss_authentication=-1; 114124211Sdes options->gss_cleanup_creds = -1; 11557429Smarkm options->password_authentication = -1; 11669591Sgreen options->kbd_interactive_authentication = -1; 11792559Sdes options->challenge_response_authentication = -1; 11857429Smarkm options->permit_empty_passwd = -1; 119106130Sdes options->permit_user_env = -1; 12057429Smarkm options->use_login = -1; 12198684Sdes options->compression = -1; 122255767Sdes options->rekey_limit = -1; 123255767Sdes options->rekey_interval = -1; 12469591Sgreen options->allow_tcp_forwarding = -1; 125181111Sdes options->allow_agent_forwarding = -1; 12657429Smarkm options->num_allow_users = 0; 12757429Smarkm options->num_deny_users = 0; 12857429Smarkm options->num_allow_groups = 0; 12957429Smarkm options->num_deny_groups = 0; 13060576Skris options->ciphers = NULL; 13176262Sgreen options->macs = NULL; 132221420Sdes options->kex_algorithms = NULL; 13360576Skris options->protocol = SSH_PROTO_UNKNOWN; 13460576Skris options->gateway_ports = -1; 13565674Skris options->num_subsystems = 0; 13665674Skris options->max_startups_begin = -1; 13765674Skris options->max_startups_rate = -1; 13865674Skris options->max_startups = -1; 139137019Sdes options->max_authtries = -1; 140181111Sdes options->max_sessions = -1; 14176262Sgreen options->banner = NULL; 142124211Sdes options->use_dns = -1; 14376262Sgreen options->client_alive_interval = -1; 14476262Sgreen options->client_alive_count_max = -1; 145226046Sdes options->num_authkeys_files = 0; 146137019Sdes options->num_accept_env = 0; 147157019Sdes options->permit_tun = -1; 148162856Sdes options->num_permitted_opens = -1; 149162856Sdes options->adm_forced_command = NULL; 150181111Sdes options->chroot_directory = NULL; 151248619Sdes options->authorized_keys_command = NULL; 152248619Sdes options->authorized_keys_command_user = NULL; 153204917Sdes options->revoked_keys_file = NULL; 154204917Sdes options->trusted_user_ca_keys = NULL; 155215116Sdes options->authorized_principals_file = NULL; 156221420Sdes options->ip_qos_interactive = -1; 157221420Sdes options->ip_qos_bulk = -1; 158240075Sdes options->version_addendum = NULL; 159224638Sbrooks options->hpn_disabled = -1; 160224638Sbrooks options->hpn_buffer_size = -1; 161224638Sbrooks options->tcp_rcv_buf_poll = -1; 162224638Sbrooks#ifdef NONE_CIPHER_ENABLED 163224638Sbrooks options->none_enabled = -1; 164224638Sbrooks#endif 16557429Smarkm} 16657429Smarkm 16760576Skrisvoid 16857429Smarkmfill_default_server_options(ServerOptions *options) 16957429Smarkm{ 17098941Sdes /* Portable-specific options */ 171124211Sdes if (options->use_pam == -1) 172124279Sdes options->use_pam = 1; 17398941Sdes 17498941Sdes /* Standard Options */ 17576262Sgreen if (options->protocol == SSH_PROTO_UNKNOWN) 176126271Sdes options->protocol = SSH_PROTO_2; 17776262Sgreen if (options->num_host_key_files == 0) { 17876262Sgreen /* fill default hostkeys for protocols */ 17976262Sgreen if (options->protocol & SSH_PROTO_1) 18092559Sdes options->host_key_files[options->num_host_key_files++] = 18192559Sdes _PATH_HOST_KEY_FILE; 18292559Sdes if (options->protocol & SSH_PROTO_2) { 18392559Sdes options->host_key_files[options->num_host_key_files++] = 184231584Sed _PATH_HOST_RSA_KEY_FILE; 185181111Sdes options->host_key_files[options->num_host_key_files++] = 18692559Sdes _PATH_HOST_DSA_KEY_FILE; 187221420Sdes#ifdef OPENSSL_HAS_ECC 188221420Sdes options->host_key_files[options->num_host_key_files++] = 189221420Sdes _PATH_HOST_ECDSA_KEY_FILE; 190221420Sdes#endif 191262566Sdes options->host_key_files[options->num_host_key_files++] = 192262566Sdes _PATH_HOST_ED25519_KEY_FILE; 19392559Sdes } 19476262Sgreen } 195204917Sdes /* No certificates by default */ 19657429Smarkm if (options->num_ports == 0) 19757429Smarkm options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 19857429Smarkm if (options->listen_addrs == NULL) 19976262Sgreen add_listen_addr(options, NULL, 0); 20060576Skris if (options->pid_file == NULL) 20176262Sgreen options->pid_file = _PATH_SSH_DAEMON_PID_FILE; 20257429Smarkm if (options->server_key_bits == -1) 203181111Sdes options->server_key_bits = 1024; 20457429Smarkm if (options->login_grace_time == -1) 20599048Sdes options->login_grace_time = 120; 20657429Smarkm if (options->key_regeneration_time == -1) 20757429Smarkm options->key_regeneration_time = 3600; 20876262Sgreen if (options->permit_root_login == PERMIT_NOT_SET) 20999048Sdes options->permit_root_login = PERMIT_NO; 21057429Smarkm if (options->ignore_rhosts == -1) 21157565Smarkm options->ignore_rhosts = 1; 21257429Smarkm if (options->ignore_user_known_hosts == -1) 21357429Smarkm options->ignore_user_known_hosts = 0; 21457429Smarkm if (options->print_motd == -1) 21557429Smarkm options->print_motd = 1; 21676262Sgreen if (options->print_lastlog == -1) 21776262Sgreen options->print_lastlog = 1; 21857429Smarkm if (options->x11_forwarding == -1) 21999048Sdes options->x11_forwarding = 1; 22057429Smarkm if (options->x11_display_offset == -1) 22157565Smarkm options->x11_display_offset = 10; 22292559Sdes if (options->x11_use_localhost == -1) 22392559Sdes options->x11_use_localhost = 1; 22465674Skris if (options->xauth_location == NULL) 22592559Sdes options->xauth_location = _PATH_XAUTH; 226262566Sdes if (options->permit_tty == -1) 227262566Sdes options->permit_tty = 1; 22857429Smarkm if (options->strict_modes == -1) 22957429Smarkm options->strict_modes = 1; 230126277Sdes if (options->tcp_keep_alive == -1) 231126277Sdes options->tcp_keep_alive = 1; 23292559Sdes if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 23357429Smarkm options->log_facility = SYSLOG_FACILITY_AUTH; 23492559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 23557429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 23657429Smarkm if (options->rhosts_rsa_authentication == -1) 23757565Smarkm options->rhosts_rsa_authentication = 0; 23876262Sgreen if (options->hostbased_authentication == -1) 23976262Sgreen options->hostbased_authentication = 0; 24076262Sgreen if (options->hostbased_uses_name_from_packet_only == -1) 24176262Sgreen options->hostbased_uses_name_from_packet_only = 0; 24257429Smarkm if (options->rsa_authentication == -1) 24357429Smarkm options->rsa_authentication = 1; 24476262Sgreen if (options->pubkey_authentication == -1) 24576262Sgreen options->pubkey_authentication = 1; 24699048Sdes if (options->kerberos_authentication == -1) 247124211Sdes options->kerberos_authentication = 0; 24892559Sdes if (options->kerberos_or_local_passwd == -1) 24992559Sdes options->kerberos_or_local_passwd = 1; 25092559Sdes if (options->kerberos_ticket_cleanup == -1) 25192559Sdes options->kerberos_ticket_cleanup = 1; 252126277Sdes if (options->kerberos_get_afs_token == -1) 253126277Sdes options->kerberos_get_afs_token = 0; 254124211Sdes if (options->gss_authentication == -1) 255124211Sdes options->gss_authentication = 0; 256124211Sdes if (options->gss_cleanup_creds == -1) 257124211Sdes options->gss_cleanup_creds = 1; 25857429Smarkm if (options->password_authentication == -1) 259126009Sdes options->password_authentication = 0; 26069591Sgreen if (options->kbd_interactive_authentication == -1) 26169591Sgreen options->kbd_interactive_authentication = 0; 26292559Sdes if (options->challenge_response_authentication == -1) 26395456Sdes options->challenge_response_authentication = 1; 26457429Smarkm if (options->permit_empty_passwd == -1) 26557565Smarkm options->permit_empty_passwd = 0; 266106130Sdes if (options->permit_user_env == -1) 267106130Sdes options->permit_user_env = 0; 26857429Smarkm if (options->use_login == -1) 26957429Smarkm options->use_login = 0; 27098684Sdes if (options->compression == -1) 271149753Sdes options->compression = COMP_DELAYED; 272255767Sdes if (options->rekey_limit == -1) 273255767Sdes options->rekey_limit = 0; 274255767Sdes if (options->rekey_interval == -1) 275255767Sdes options->rekey_interval = 0; 27669591Sgreen if (options->allow_tcp_forwarding == -1) 277248619Sdes options->allow_tcp_forwarding = FORWARD_ALLOW; 278181111Sdes if (options->allow_agent_forwarding == -1) 279181111Sdes options->allow_agent_forwarding = 1; 28060576Skris if (options->gateway_ports == -1) 28160576Skris options->gateway_ports = 0; 28265674Skris if (options->max_startups == -1) 283248619Sdes options->max_startups = 100; 28465674Skris if (options->max_startups_rate == -1) 285248619Sdes options->max_startups_rate = 30; /* 30% */ 28665674Skris if (options->max_startups_begin == -1) 287248619Sdes options->max_startups_begin = 10; 288137019Sdes if (options->max_authtries == -1) 289137019Sdes options->max_authtries = DEFAULT_AUTH_FAIL_MAX; 290181111Sdes if (options->max_sessions == -1) 291181111Sdes options->max_sessions = DEFAULT_SESSIONS_MAX; 292124211Sdes if (options->use_dns == -1) 293124211Sdes options->use_dns = 1; 29476262Sgreen if (options->client_alive_interval == -1) 29592559Sdes options->client_alive_interval = 0; 29676262Sgreen if (options->client_alive_count_max == -1) 29776262Sgreen options->client_alive_count_max = 3; 298226046Sdes if (options->num_authkeys_files == 0) { 299226046Sdes options->authorized_keys_files[options->num_authkeys_files++] = 300226046Sdes xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); 301226046Sdes options->authorized_keys_files[options->num_authkeys_files++] = 302226046Sdes xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2); 30392559Sdes } 304157019Sdes if (options->permit_tun == -1) 305157019Sdes options->permit_tun = SSH_TUNMODE_NO; 306221420Sdes if (options->ip_qos_interactive == -1) 307221420Sdes options->ip_qos_interactive = IPTOS_LOWDELAY; 308221420Sdes if (options->ip_qos_bulk == -1) 309221420Sdes options->ip_qos_bulk = IPTOS_THROUGHPUT; 310240075Sdes if (options->version_addendum == NULL) 311240075Sdes options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 312240075Sdes /* Turn privilege separation on by default */ 313240075Sdes if (use_privsep == -1) 314262566Sdes use_privsep = PRIVSEP_ON; 315240075Sdes 316240075Sdes#ifndef HAVE_MMAP 317240075Sdes if (use_privsep && options->compression == 1) { 318240075Sdes error("This platform does not support both privilege " 319240075Sdes "separation and compression"); 320240075Sdes error("Compression disabled"); 321240075Sdes options->compression = 0; 322240075Sdes } 323240075Sdes#endif 324240075Sdes 325231584Sed if (options->hpn_disabled == -1) 326224638Sbrooks options->hpn_disabled = 0; 327224638Sbrooks if (options->hpn_buffer_size == -1) { 328224638Sbrooks /* 329224638Sbrooks * HPN buffer size option not explicitly set. Try to figure 330224638Sbrooks * out what value to use or resort to default. 331224638Sbrooks */ 332224638Sbrooks options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; 333224638Sbrooks if (!options->hpn_disabled) { 334224638Sbrooks sock_get_rcvbuf(&options->hpn_buffer_size, 0); 335224638Sbrooks debug ("HPN Buffer Size: %d", options->hpn_buffer_size); 336224638Sbrooks } 337224638Sbrooks } else { 338224638Sbrooks /* 339224638Sbrooks * In the case that the user sets both values in a 340224638Sbrooks * contradictory manner hpn_disabled overrrides hpn_buffer_size. 341224638Sbrooks */ 342224638Sbrooks if (options->hpn_disabled <= 0) { 343224638Sbrooks u_int maxlen; 34498684Sdes 345224638Sbrooks maxlen = buffer_get_max_len(); 346224638Sbrooks if (options->hpn_buffer_size == 0) 347224638Sbrooks options->hpn_buffer_size = 1; 348224638Sbrooks /* Limit the maximum buffer to BUFFER_MAX_LEN. */ 349224638Sbrooks if (options->hpn_buffer_size > maxlen / 1024) 350224638Sbrooks options->hpn_buffer_size = maxlen; 351224638Sbrooks else 352224638Sbrooks options->hpn_buffer_size *= 1024; 353240075Sdes } else { 354224638Sbrooks options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; 355240075Sdes } 356224638Sbrooks } 35757429Smarkm} 35857429Smarkm 35957429Smarkm/* Keyword tokens. */ 36057429Smarkmtypedef enum { 36157429Smarkm sBadOption, /* == unknown option */ 36298941Sdes /* Portable-specific options */ 363124211Sdes sUsePAM, 36498941Sdes /* Standard Options */ 36557429Smarkm sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, 36657429Smarkm sPermitRootLogin, sLogFacility, sLogLevel, 367124211Sdes sRhostsRSAAuthentication, sRSAAuthentication, 36892559Sdes sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 369126277Sdes sKerberosGetAFSToken, 370124211Sdes sKerberosTgtPassing, sChallengeResponseAuthentication, 371147005Sdes sPasswordAuthentication, sKbdInteractiveAuthentication, 372147005Sdes sListenAddress, sAddressFamily, 37376262Sgreen sPrintMotd, sPrintLastLog, sIgnoreRhosts, 37492559Sdes sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 375262566Sdes sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, 376106130Sdes sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, 377255767Sdes sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 37876262Sgreen sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 379137019Sdes sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, 380181111Sdes sMaxStartups, sMaxAuthTries, sMaxSessions, 381124211Sdes sBanner, sUseDNS, sHostbasedAuthentication, 38292559Sdes sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 383226046Sdes sClientAliveCountMax, sAuthorizedKeysFile, 384157019Sdes sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, 385181111Sdes sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 386181111Sdes sUsePrivilegeSeparation, sAllowAgentForwarding, 387264377Sdes sHostCertificate, 388215116Sdes sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 389240075Sdes sKexAlgorithms, sIPQoS, sVersionAddendum, 390248619Sdes sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 391255767Sdes sAuthenticationMethods, sHostKeyAgent, 392224638Sbrooks sHPNDisabled, sHPNBufferSize, sTcpRcvBufPoll, 393224638Sbrooks#ifdef NONE_CIPHER_ENABLED 394224638Sbrooks sNoneEnabled, 395224638Sbrooks#endif 396124211Sdes sDeprecated, sUnsupported 39757429Smarkm} ServerOpCodes; 39857429Smarkm 399162856Sdes#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ 400162856Sdes#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 401162856Sdes#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 402162856Sdes 40357429Smarkm/* Textual representation of the tokens. */ 40457429Smarkmstatic struct { 40557429Smarkm const char *name; 40657429Smarkm ServerOpCodes opcode; 407162856Sdes u_int flags; 40857429Smarkm} keywords[] = { 40998941Sdes /* Portable-specific options */ 410124211Sdes#ifdef USE_PAM 411162856Sdes { "usepam", sUsePAM, SSHCFG_GLOBAL }, 412124211Sdes#else 413162856Sdes { "usepam", sUnsupported, SSHCFG_GLOBAL }, 41499048Sdes#endif 415162856Sdes { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, 41698941Sdes /* Standard Options */ 417162856Sdes { "port", sPort, SSHCFG_GLOBAL }, 418162856Sdes { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 419162856Sdes { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 420255767Sdes { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, 421162856Sdes { "pidfile", sPidFile, SSHCFG_GLOBAL }, 422162856Sdes { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, 423162856Sdes { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 424162856Sdes { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, 425181111Sdes { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, 426162856Sdes { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 427162856Sdes { "loglevel", sLogLevel, SSHCFG_GLOBAL }, 428162856Sdes { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, 429181111Sdes { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, 430181111Sdes { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, 431215116Sdes { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, 432181111Sdes { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, 433181111Sdes { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 434197679Sdes { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 435124211Sdes#ifdef KRB5 436181111Sdes { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 437162856Sdes { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 438162856Sdes { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 439126277Sdes#ifdef USE_AFS 440162856Sdes { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, 441124211Sdes#else 442162856Sdes { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 443126277Sdes#endif 444126277Sdes#else 445181111Sdes { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, 446162856Sdes { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, 447162856Sdes { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, 448162856Sdes { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 44973400Sassar#endif 450162856Sdes { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, 451162856Sdes { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, 452124211Sdes#ifdef GSSAPI 453181111Sdes { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 454162856Sdes { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 455124211Sdes#else 456181111Sdes { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, 457162856Sdes { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 45857429Smarkm#endif 459181111Sdes { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 460181111Sdes { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 461162856Sdes { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 462162856Sdes { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ 463162856Sdes { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 464162856Sdes { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 465162856Sdes { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, 466162856Sdes { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 467162856Sdes { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 468162856Sdes { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, 469162856Sdes { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 470162856Sdes { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 471162856Sdes { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 472162856Sdes { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 473162856Sdes { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 474162856Sdes { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 475192595Sdes { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, 476162856Sdes { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 477162856Sdes { "uselogin", sUseLogin, SSHCFG_GLOBAL }, 478162856Sdes { "compression", sCompression, SSHCFG_GLOBAL }, 479255767Sdes { "rekeylimit", sRekeyLimit, SSHCFG_ALL }, 480162856Sdes { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, 481162856Sdes { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ 482162856Sdes { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 483181111Sdes { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, 484240075Sdes { "allowusers", sAllowUsers, SSHCFG_ALL }, 485240075Sdes { "denyusers", sDenyUsers, SSHCFG_ALL }, 486240075Sdes { "allowgroups", sAllowGroups, SSHCFG_ALL }, 487240075Sdes { "denygroups", sDenyGroups, SSHCFG_ALL }, 488162856Sdes { "ciphers", sCiphers, SSHCFG_GLOBAL }, 489162856Sdes { "macs", sMacs, SSHCFG_GLOBAL }, 490162856Sdes { "protocol", sProtocol, SSHCFG_GLOBAL }, 491162856Sdes { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 492162856Sdes { "subsystem", sSubsystem, SSHCFG_GLOBAL }, 493162856Sdes { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 494181111Sdes { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, 495181111Sdes { "maxsessions", sMaxSessions, SSHCFG_ALL }, 496181111Sdes { "banner", sBanner, SSHCFG_ALL }, 497162856Sdes { "usedns", sUseDNS, SSHCFG_GLOBAL }, 498162856Sdes { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, 499162856Sdes { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, 500162856Sdes { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 501162856Sdes { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 502215116Sdes { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, 503226046Sdes { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, 504197679Sdes { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, 505240075Sdes { "acceptenv", sAcceptEnv, SSHCFG_ALL }, 506215116Sdes { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 507262566Sdes { "permittty", sPermitTTY, SSHCFG_ALL }, 508197679Sdes { "match", sMatch, SSHCFG_ALL }, 509162856Sdes { "permitopen", sPermitOpen, SSHCFG_ALL }, 510162856Sdes { "forcecommand", sForceCommand, SSHCFG_ALL }, 511181111Sdes { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 512204917Sdes { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, 513204917Sdes { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, 514204917Sdes { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, 515215116Sdes { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, 516221420Sdes { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, 517221420Sdes { "ipqos", sIPQoS, SSHCFG_ALL }, 518248619Sdes { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, 519248619Sdes { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 520240075Sdes { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 521248619Sdes { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 522224638Sbrooks { "hpndisabled", sHPNDisabled, SSHCFG_ALL }, 523224638Sbrooks { "hpnbuffersize", sHPNBufferSize, SSHCFG_ALL }, 524224638Sbrooks { "tcprcvbufpoll", sTcpRcvBufPoll, SSHCFG_ALL }, 525224638Sbrooks#ifdef NONE_CIPHER_ENABLED 526224638Sbrooks { "noneenabled", sNoneEnabled, SSHCFG_ALL }, 527224638Sbrooks#endif 528162856Sdes { NULL, sBadOption, 0 } 52957429Smarkm}; 53057429Smarkm 531181111Sdesstatic struct { 532181111Sdes int val; 533181111Sdes char *text; 534181111Sdes} tunmode_desc[] = { 535181111Sdes { SSH_TUNMODE_NO, "no" }, 536181111Sdes { SSH_TUNMODE_POINTOPOINT, "point-to-point" }, 537181111Sdes { SSH_TUNMODE_ETHERNET, "ethernet" }, 538181111Sdes { SSH_TUNMODE_YES, "yes" }, 539181111Sdes { -1, NULL } 540181111Sdes}; 541181111Sdes 54257429Smarkm/* 54376262Sgreen * Returns the number of the token pointed to by cp or sBadOption. 54457429Smarkm */ 54557429Smarkm 54660576Skrisstatic ServerOpCodes 54757429Smarkmparse_token(const char *cp, const char *filename, 548162856Sdes int linenum, u_int *flags) 54957429Smarkm{ 55076262Sgreen u_int i; 55157429Smarkm 55257429Smarkm for (i = 0; keywords[i].name; i++) 553162856Sdes if (strcasecmp(cp, keywords[i].name) == 0) { 554162856Sdes *flags = keywords[i].flags; 55557429Smarkm return keywords[i].opcode; 556162856Sdes } 55757429Smarkm 55876262Sgreen error("%s: line %d: Bad configuration option: %s", 55976262Sgreen filename, linenum, cp); 56057429Smarkm return sBadOption; 56157429Smarkm} 56257429Smarkm 563204917Sdeschar * 564204917Sdesderelativise_path(const char *path) 565204917Sdes{ 566207319Sdes char *expanded, *ret, cwd[MAXPATHLEN]; 567204917Sdes 568204917Sdes expanded = tilde_expand_filename(path, getuid()); 569204917Sdes if (*expanded == '/') 570204917Sdes return expanded; 571207319Sdes if (getcwd(cwd, sizeof(cwd)) == NULL) 572204917Sdes fatal("%s: getcwd: %s", __func__, strerror(errno)); 573204917Sdes xasprintf(&ret, "%s/%s", cwd, expanded); 574255767Sdes free(expanded); 575204917Sdes return ret; 576204917Sdes} 577204917Sdes 57892559Sdesstatic void 579192595Sdesadd_listen_addr(ServerOptions *options, char *addr, int port) 58057429Smarkm{ 581149753Sdes u_int i; 58257429Smarkm 58357429Smarkm if (options->num_ports == 0) 58457429Smarkm options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 585147005Sdes if (options->address_family == -1) 586147005Sdes options->address_family = AF_UNSPEC; 58776262Sgreen if (port == 0) 58876262Sgreen for (i = 0; i < options->num_ports; i++) 58976262Sgreen add_one_listen_addr(options, addr, options->ports[i]); 59076262Sgreen else 59176262Sgreen add_one_listen_addr(options, addr, port); 59257429Smarkm} 59357429Smarkm 59492559Sdesstatic void 595192595Sdesadd_one_listen_addr(ServerOptions *options, char *addr, int port) 59676262Sgreen{ 59776262Sgreen struct addrinfo hints, *ai, *aitop; 59876262Sgreen char strport[NI_MAXSERV]; 59976262Sgreen int gaierr; 60076262Sgreen 60176262Sgreen memset(&hints, 0, sizeof(hints)); 602147005Sdes hints.ai_family = options->address_family; 60376262Sgreen hints.ai_socktype = SOCK_STREAM; 60476262Sgreen hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 605192595Sdes snprintf(strport, sizeof strport, "%d", port); 60676262Sgreen if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 60776262Sgreen fatal("bad addr or host: %s (%s)", 60876262Sgreen addr ? addr : "<NULL>", 609181111Sdes ssh_gai_strerror(gaierr)); 61076262Sgreen for (ai = aitop; ai->ai_next; ai = ai->ai_next) 61176262Sgreen ; 61276262Sgreen ai->ai_next = options->listen_addrs; 61376262Sgreen options->listen_addrs = aitop; 61476262Sgreen} 61576262Sgreen 616240075Sdesstruct connection_info * 617240075Sdesget_connection_info(int populate, int use_dns) 618240075Sdes{ 619240075Sdes static struct connection_info ci; 620240075Sdes 621240075Sdes if (!populate) 622240075Sdes return &ci; 623240075Sdes ci.host = get_canonical_hostname(use_dns); 624240075Sdes ci.address = get_remote_ipaddr(); 625240075Sdes ci.laddress = get_local_ipaddr(packet_get_connection_in()); 626240075Sdes ci.lport = get_local_port(); 627240075Sdes return &ci; 628240075Sdes} 629240075Sdes 630162856Sdes/* 631162856Sdes * The strategy for the Match blocks is that the config file is parsed twice. 632162856Sdes * 633162856Sdes * The first time is at startup. activep is initialized to 1 and the 634162856Sdes * directives in the global context are processed and acted on. Hitting a 635162856Sdes * Match directive unsets activep and the directives inside the block are 636162856Sdes * checked for syntax only. 637162856Sdes * 638162856Sdes * The second time is after a connection has been established but before 639162856Sdes * authentication. activep is initialized to 2 and global config directives 640162856Sdes * are ignored since they have already been processed. If the criteria in a 641162856Sdes * Match block is met, activep is set and the subsequent directives 642162856Sdes * processed and actioned until EOF or another Match block unsets it. Any 643162856Sdes * options set are copied into the main server config. 644162856Sdes * 645162856Sdes * Potential additions/improvements: 646162856Sdes * - Add Match support for pre-kex directives, eg Protocol, Ciphers. 647162856Sdes * 648162856Sdes * - Add a Tag directive (idea from David Leonard) ala pf, eg: 649162856Sdes * Match Address 192.168.0.* 650162856Sdes * Tag trusted 651162856Sdes * Match Group wheel 652162856Sdes * Tag trusted 653162856Sdes * Match Tag trusted 654162856Sdes * AllowTcpForwarding yes 655162856Sdes * GatewayPorts clientspecified 656162856Sdes * [...] 657162856Sdes * 658162856Sdes * - Add a PermittedChannelRequests directive 659162856Sdes * Match Group shell 660162856Sdes * PermittedChannelRequests session,forwarded-tcpip 661162856Sdes */ 662162856Sdes 663162856Sdesstatic int 664162856Sdesmatch_cfg_line_group(const char *grps, int line, const char *user) 665162856Sdes{ 666162856Sdes int result = 0; 667162856Sdes struct passwd *pw; 668162856Sdes 669162856Sdes if (user == NULL) 670162856Sdes goto out; 671162856Sdes 672162856Sdes if ((pw = getpwnam(user)) == NULL) { 673162856Sdes debug("Can't match group at line %d because user %.100s does " 674162856Sdes "not exist", line, user); 675162856Sdes } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 676162856Sdes debug("Can't Match group because user %.100s not in any group " 677162856Sdes "at line %d", user, line); 678181111Sdes } else if (ga_match_pattern_list(grps) != 1) { 679181111Sdes debug("user %.100s does not match group list %.100s at line %d", 680181111Sdes user, grps, line); 681162856Sdes } else { 682181111Sdes debug("user %.100s matched group list %.100s at line %d", user, 683181111Sdes grps, line); 684162856Sdes result = 1; 685162856Sdes } 686162856Sdesout: 687162856Sdes ga_free(); 688162856Sdes return result; 689162856Sdes} 690162856Sdes 691240075Sdes/* 692248619Sdes * All of the attributes on a single Match line are ANDed together, so we need 693262566Sdes * to check every attribute and set the result to zero if any attribute does 694248619Sdes * not match. 695240075Sdes */ 696162856Sdesstatic int 697240075Sdesmatch_cfg_line(char **condition, int line, struct connection_info *ci) 698162856Sdes{ 699262566Sdes int result = 1, attributes = 0, port; 700162856Sdes char *arg, *attrib, *cp = *condition; 701162856Sdes size_t len; 702162856Sdes 703240075Sdes if (ci == NULL) 704162856Sdes debug3("checking syntax for 'Match %s'", cp); 705162856Sdes else 706240075Sdes debug3("checking match for '%s' user %s host %s addr %s " 707240075Sdes "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", 708240075Sdes ci->host ? ci->host : "(null)", 709240075Sdes ci->address ? ci->address : "(null)", 710240075Sdes ci->laddress ? ci->laddress : "(null)", ci->lport); 711162856Sdes 712162856Sdes while ((attrib = strdelim(&cp)) && *attrib != '\0') { 713262566Sdes attributes++; 714262566Sdes if (strcasecmp(attrib, "all") == 0) { 715262566Sdes if (attributes != 1 || 716262566Sdes ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 717262566Sdes error("'all' cannot be combined with other " 718262566Sdes "Match attributes"); 719262566Sdes return -1; 720262566Sdes } 721262566Sdes *condition = cp; 722262566Sdes return 1; 723262566Sdes } 724162856Sdes if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 725162856Sdes error("Missing Match criteria for %s", attrib); 726162856Sdes return -1; 727162856Sdes } 728162856Sdes len = strlen(arg); 729162856Sdes if (strcasecmp(attrib, "user") == 0) { 730240075Sdes if (ci == NULL || ci->user == NULL) { 731162856Sdes result = 0; 732162856Sdes continue; 733162856Sdes } 734240075Sdes if (match_pattern_list(ci->user, arg, len, 0) != 1) 735162856Sdes result = 0; 736162856Sdes else 737162856Sdes debug("user %.100s matched 'User %.100s' at " 738240075Sdes "line %d", ci->user, arg, line); 739162856Sdes } else if (strcasecmp(attrib, "group") == 0) { 740240075Sdes if (ci == NULL || ci->user == NULL) { 741240075Sdes result = 0; 742240075Sdes continue; 743240075Sdes } 744240075Sdes switch (match_cfg_line_group(arg, line, ci->user)) { 745162856Sdes case -1: 746162856Sdes return -1; 747162856Sdes case 0: 748162856Sdes result = 0; 749162856Sdes } 750162856Sdes } else if (strcasecmp(attrib, "host") == 0) { 751240075Sdes if (ci == NULL || ci->host == NULL) { 752162856Sdes result = 0; 753162856Sdes continue; 754162856Sdes } 755240075Sdes if (match_hostname(ci->host, arg, len) != 1) 756162856Sdes result = 0; 757162856Sdes else 758162856Sdes debug("connection from %.100s matched 'Host " 759240075Sdes "%.100s' at line %d", ci->host, arg, line); 760162856Sdes } else if (strcasecmp(attrib, "address") == 0) { 761240075Sdes if (ci == NULL || ci->address == NULL) { 762240075Sdes result = 0; 763240075Sdes continue; 764240075Sdes } 765240075Sdes switch (addr_match_list(ci->address, arg)) { 766181111Sdes case 1: 767181111Sdes debug("connection from %.100s matched 'Address " 768240075Sdes "%.100s' at line %d", ci->address, arg, line); 769181111Sdes break; 770181111Sdes case 0: 771181111Sdes case -1: 772162856Sdes result = 0; 773181111Sdes break; 774181111Sdes case -2: 775181111Sdes return -1; 776162856Sdes } 777240075Sdes } else if (strcasecmp(attrib, "localaddress") == 0){ 778240075Sdes if (ci == NULL || ci->laddress == NULL) { 779240075Sdes result = 0; 780240075Sdes continue; 781240075Sdes } 782240075Sdes switch (addr_match_list(ci->laddress, arg)) { 783240075Sdes case 1: 784240075Sdes debug("connection from %.100s matched " 785240075Sdes "'LocalAddress %.100s' at line %d", 786240075Sdes ci->laddress, arg, line); 787240075Sdes break; 788240075Sdes case 0: 789240075Sdes case -1: 790240075Sdes result = 0; 791240075Sdes break; 792240075Sdes case -2: 793240075Sdes return -1; 794240075Sdes } 795240075Sdes } else if (strcasecmp(attrib, "localport") == 0) { 796240075Sdes if ((port = a2port(arg)) == -1) { 797240075Sdes error("Invalid LocalPort '%s' on Match line", 798240075Sdes arg); 799240075Sdes return -1; 800240075Sdes } 801240075Sdes if (ci == NULL || ci->lport == 0) { 802240075Sdes result = 0; 803240075Sdes continue; 804240075Sdes } 805240075Sdes /* TODO support port lists */ 806240075Sdes if (port == ci->lport) 807240075Sdes debug("connection from %.100s matched " 808240075Sdes "'LocalPort %d' at line %d", 809240075Sdes ci->laddress, port, line); 810240075Sdes else 811240075Sdes result = 0; 812162856Sdes } else { 813162856Sdes error("Unsupported Match attribute %s", attrib); 814162856Sdes return -1; 815162856Sdes } 816162856Sdes } 817262566Sdes if (attributes == 0) { 818262566Sdes error("One or more attributes required for Match"); 819262566Sdes return -1; 820262566Sdes } 821240075Sdes if (ci != NULL) 822162856Sdes debug3("match %sfound", result ? "" : "not "); 823162856Sdes *condition = cp; 824162856Sdes return result; 825162856Sdes} 826162856Sdes 827162856Sdes#define WHITESPACE " \t\r\n" 828162856Sdes 829226046Sdes/* Multistate option parsing */ 830226046Sdesstruct multistate { 831226046Sdes char *key; 832226046Sdes int value; 833226046Sdes}; 834226046Sdesstatic const struct multistate multistate_addressfamily[] = { 835226046Sdes { "inet", AF_INET }, 836226046Sdes { "inet6", AF_INET6 }, 837226046Sdes { "any", AF_UNSPEC }, 838226046Sdes { NULL, -1 } 839226046Sdes}; 840226046Sdesstatic const struct multistate multistate_permitrootlogin[] = { 841226046Sdes { "without-password", PERMIT_NO_PASSWD }, 842226046Sdes { "forced-commands-only", PERMIT_FORCED_ONLY }, 843226046Sdes { "yes", PERMIT_YES }, 844226046Sdes { "no", PERMIT_NO }, 845226046Sdes { NULL, -1 } 846226046Sdes}; 847226046Sdesstatic const struct multistate multistate_compression[] = { 848226046Sdes { "delayed", COMP_DELAYED }, 849226046Sdes { "yes", COMP_ZLIB }, 850226046Sdes { "no", COMP_NONE }, 851226046Sdes { NULL, -1 } 852226046Sdes}; 853226046Sdesstatic const struct multistate multistate_gatewayports[] = { 854226046Sdes { "clientspecified", 2 }, 855226046Sdes { "yes", 1 }, 856226046Sdes { "no", 0 }, 857226046Sdes { NULL, -1 } 858226046Sdes}; 859226046Sdesstatic const struct multistate multistate_privsep[] = { 860240075Sdes { "yes", PRIVSEP_NOSANDBOX }, 861240075Sdes { "sandbox", PRIVSEP_ON }, 862240075Sdes { "nosandbox", PRIVSEP_NOSANDBOX }, 863226046Sdes { "no", PRIVSEP_OFF }, 864226046Sdes { NULL, -1 } 865226046Sdes}; 866248619Sdesstatic const struct multistate multistate_tcpfwd[] = { 867248619Sdes { "yes", FORWARD_ALLOW }, 868248619Sdes { "all", FORWARD_ALLOW }, 869248619Sdes { "no", FORWARD_DENY }, 870248619Sdes { "remote", FORWARD_REMOTE }, 871248619Sdes { "local", FORWARD_LOCAL }, 872248619Sdes { NULL, -1 } 873248619Sdes}; 874226046Sdes 87592559Sdesint 87692559Sdesprocess_server_config_line(ServerOptions *options, char *line, 877240075Sdes const char *filename, int linenum, int *activep, 878240075Sdes struct connection_info *connectinfo) 87957429Smarkm{ 88076262Sgreen char *cp, **charptr, *arg, *p; 881255767Sdes int cmdline = 0, *intptr, value, value2, n, port; 882181111Sdes SyslogFacility *log_facility_ptr; 883181111Sdes LogLevel *log_level_ptr; 88457429Smarkm ServerOpCodes opcode; 885162856Sdes u_int i, flags = 0; 886162856Sdes size_t len; 887255767Sdes long long val64; 888226046Sdes const struct multistate *multistate_ptr; 88957429Smarkm 89092559Sdes cp = line; 891162856Sdes if ((arg = strdelim(&cp)) == NULL) 892162856Sdes return 0; 89392559Sdes /* Ignore leading whitespace */ 89492559Sdes if (*arg == '\0') 89565674Skris arg = strdelim(&cp); 89692559Sdes if (!arg || !*arg || *arg == '#') 89792559Sdes return 0; 89892559Sdes intptr = NULL; 89992559Sdes charptr = NULL; 900162856Sdes opcode = parse_token(arg, filename, linenum, &flags); 901162856Sdes 902162856Sdes if (activep == NULL) { /* We are processing a command line directive */ 903162856Sdes cmdline = 1; 904162856Sdes activep = &cmdline; 905162856Sdes } 906162856Sdes if (*activep && opcode != sMatch) 907162856Sdes debug3("%s:%d setting %s %s", filename, linenum, arg, cp); 908162856Sdes if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 909240075Sdes if (connectinfo == NULL) { 910162856Sdes fatal("%s line %d: Directive '%s' is not allowed " 911162856Sdes "within a Match block", filename, linenum, arg); 912162856Sdes } else { /* this is a directive we have already processed */ 913162856Sdes while (arg) 914162856Sdes arg = strdelim(&cp); 915162856Sdes return 0; 916162856Sdes } 917162856Sdes } 918162856Sdes 91992559Sdes switch (opcode) { 92098941Sdes /* Portable-specific options */ 921124211Sdes case sUsePAM: 922124211Sdes intptr = &options->use_pam; 92398941Sdes goto parse_flag; 92498941Sdes 92598941Sdes /* Standard Options */ 92692559Sdes case sBadOption: 92792559Sdes return -1; 92892559Sdes case sPort: 92992559Sdes /* ignore ports from configfile if cmdline specifies ports */ 93092559Sdes if (options->ports_from_cmdline) 93192559Sdes return 0; 93292559Sdes if (options->listen_addrs != NULL) 93392559Sdes fatal("%s line %d: ports must be specified before " 93492559Sdes "ListenAddress.", filename, linenum); 93592559Sdes if (options->num_ports >= MAX_PORTS) 93692559Sdes fatal("%s line %d: too many ports.", 93792559Sdes filename, linenum); 93892559Sdes arg = strdelim(&cp); 93992559Sdes if (!arg || *arg == '\0') 94092559Sdes fatal("%s line %d: missing port number.", 94192559Sdes filename, linenum); 94292559Sdes options->ports[options->num_ports++] = a2port(arg); 943192595Sdes if (options->ports[options->num_ports-1] <= 0) 94492559Sdes fatal("%s line %d: Badly formatted port number.", 94592559Sdes filename, linenum); 94692559Sdes break; 94757429Smarkm 94892559Sdes case sServerKeyBits: 94992559Sdes intptr = &options->server_key_bits; 950181111Sdes parse_int: 95192559Sdes arg = strdelim(&cp); 95292559Sdes if (!arg || *arg == '\0') 95392559Sdes fatal("%s line %d: missing integer value.", 95492559Sdes filename, linenum); 95592559Sdes value = atoi(arg); 956162856Sdes if (*activep && *intptr == -1) 95792559Sdes *intptr = value; 95892559Sdes break; 95957429Smarkm 96092559Sdes case sLoginGraceTime: 96192559Sdes intptr = &options->login_grace_time; 962181111Sdes parse_time: 96392559Sdes arg = strdelim(&cp); 96492559Sdes if (!arg || *arg == '\0') 96592559Sdes fatal("%s line %d: missing time value.", 96692559Sdes filename, linenum); 96792559Sdes if ((value = convtime(arg)) == -1) 96892559Sdes fatal("%s line %d: invalid time value.", 96992559Sdes filename, linenum); 97092559Sdes if (*intptr == -1) 97192559Sdes *intptr = value; 97292559Sdes break; 97357429Smarkm 97492559Sdes case sKeyRegenerationTime: 97592559Sdes intptr = &options->key_regeneration_time; 97692559Sdes goto parse_time; 97757429Smarkm 97892559Sdes case sListenAddress: 97992559Sdes arg = strdelim(&cp); 980147005Sdes if (arg == NULL || *arg == '\0') 981147005Sdes fatal("%s line %d: missing address", 98292559Sdes filename, linenum); 983149753Sdes /* check for bare IPv6 address: no "[]" and 2 or more ":" */ 984149753Sdes if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL 985149753Sdes && strchr(p+1, ':') != NULL) { 986149753Sdes add_listen_addr(options, arg, 0); 987149753Sdes break; 988149753Sdes } 989147005Sdes p = hpdelim(&arg); 990147005Sdes if (p == NULL) 991147005Sdes fatal("%s line %d: bad address:port usage", 992147005Sdes filename, linenum); 993147005Sdes p = cleanhostname(p); 994147005Sdes if (arg == NULL) 995147005Sdes port = 0; 996192595Sdes else if ((port = a2port(arg)) <= 0) 997147005Sdes fatal("%s line %d: bad port number", filename, linenum); 99857429Smarkm 999147005Sdes add_listen_addr(options, p, port); 1000147005Sdes 1001147005Sdes break; 1002147005Sdes 1003147005Sdes case sAddressFamily: 1004226046Sdes intptr = &options->address_family; 1005226046Sdes multistate_ptr = multistate_addressfamily; 1006226046Sdes if (options->listen_addrs != NULL) 1007226046Sdes fatal("%s line %d: address family must be specified " 1008226046Sdes "before ListenAddress.", filename, linenum); 1009226046Sdes parse_multistate: 1010147005Sdes arg = strdelim(&cp); 1011149753Sdes if (!arg || *arg == '\0') 1012226046Sdes fatal("%s line %d: missing argument.", 1013149753Sdes filename, linenum); 1014226046Sdes value = -1; 1015226046Sdes for (i = 0; multistate_ptr[i].key != NULL; i++) { 1016226046Sdes if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1017226046Sdes value = multistate_ptr[i].value; 1018226046Sdes break; 1019226046Sdes } 1020226046Sdes } 1021226046Sdes if (value == -1) 1022226046Sdes fatal("%s line %d: unsupported option \"%s\".", 1023147005Sdes filename, linenum, arg); 1024226046Sdes if (*activep && *intptr == -1) 1025147005Sdes *intptr = value; 102692559Sdes break; 102757429Smarkm 102892559Sdes case sHostKeyFile: 102992559Sdes intptr = &options->num_host_key_files; 103092559Sdes if (*intptr >= MAX_HOSTKEYS) 103192559Sdes fatal("%s line %d: too many host keys specified (max %d).", 103292559Sdes filename, linenum, MAX_HOSTKEYS); 103392559Sdes charptr = &options->host_key_files[*intptr]; 1034181111Sdes parse_filename: 103592559Sdes arg = strdelim(&cp); 103692559Sdes if (!arg || *arg == '\0') 103792559Sdes fatal("%s line %d: missing file name.", 103892559Sdes filename, linenum); 1039162856Sdes if (*activep && *charptr == NULL) { 1040204917Sdes *charptr = derelativise_path(arg); 104192559Sdes /* increase optional counter */ 104292559Sdes if (intptr != NULL) 104392559Sdes *intptr = *intptr + 1; 104492559Sdes } 104592559Sdes break; 104660576Skris 1047255767Sdes case sHostKeyAgent: 1048255767Sdes charptr = &options->host_key_agent; 1049255767Sdes arg = strdelim(&cp); 1050255767Sdes if (!arg || *arg == '\0') 1051255767Sdes fatal("%s line %d: missing socket name.", 1052255767Sdes filename, linenum); 1053255767Sdes if (*activep && *charptr == NULL) 1054255767Sdes *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? 1055255767Sdes xstrdup(arg) : derelativise_path(arg); 1056255767Sdes break; 1057255767Sdes 1058204917Sdes case sHostCertificate: 1059204917Sdes intptr = &options->num_host_cert_files; 1060204917Sdes if (*intptr >= MAX_HOSTKEYS) 1061204917Sdes fatal("%s line %d: too many host certificates " 1062204917Sdes "specified (max %d).", filename, linenum, 1063204917Sdes MAX_HOSTCERTS); 1064204917Sdes charptr = &options->host_cert_files[*intptr]; 1065204917Sdes goto parse_filename; 1066204917Sdes break; 1067204917Sdes 106892559Sdes case sPidFile: 106992559Sdes charptr = &options->pid_file; 107092559Sdes goto parse_filename; 107157429Smarkm 107292559Sdes case sPermitRootLogin: 107392559Sdes intptr = &options->permit_root_login; 1074226046Sdes multistate_ptr = multistate_permitrootlogin; 1075226046Sdes goto parse_multistate; 107692559Sdes 107792559Sdes case sIgnoreRhosts: 107892559Sdes intptr = &options->ignore_rhosts; 1079181111Sdes parse_flag: 108092559Sdes arg = strdelim(&cp); 108192559Sdes if (!arg || *arg == '\0') 108292559Sdes fatal("%s line %d: missing yes/no argument.", 108392559Sdes filename, linenum); 108492559Sdes value = 0; /* silence compiler */ 108592559Sdes if (strcmp(arg, "yes") == 0) 108692559Sdes value = 1; 108792559Sdes else if (strcmp(arg, "no") == 0) 108892559Sdes value = 0; 108992559Sdes else 109092559Sdes fatal("%s line %d: Bad yes/no argument: %s", 109192559Sdes filename, linenum, arg); 1092162856Sdes if (*activep && *intptr == -1) 109392559Sdes *intptr = value; 109492559Sdes break; 109557429Smarkm 109692559Sdes case sIgnoreUserKnownHosts: 109792559Sdes intptr = &options->ignore_user_known_hosts; 109892559Sdes goto parse_flag; 109957429Smarkm 110092559Sdes case sRhostsRSAAuthentication: 110192559Sdes intptr = &options->rhosts_rsa_authentication; 110292559Sdes goto parse_flag; 110357429Smarkm 110492559Sdes case sHostbasedAuthentication: 110592559Sdes intptr = &options->hostbased_authentication; 110692559Sdes goto parse_flag; 110776262Sgreen 110892559Sdes case sHostbasedUsesNameFromPacketOnly: 110992559Sdes intptr = &options->hostbased_uses_name_from_packet_only; 111092559Sdes goto parse_flag; 111176262Sgreen 111292559Sdes case sRSAAuthentication: 111392559Sdes intptr = &options->rsa_authentication; 111492559Sdes goto parse_flag; 111557429Smarkm 111692559Sdes case sPubkeyAuthentication: 111792559Sdes intptr = &options->pubkey_authentication; 111892559Sdes goto parse_flag; 1119124211Sdes 112092559Sdes case sKerberosAuthentication: 112192559Sdes intptr = &options->kerberos_authentication; 112292559Sdes goto parse_flag; 112357429Smarkm 112492559Sdes case sKerberosOrLocalPasswd: 112592559Sdes intptr = &options->kerberos_or_local_passwd; 112692559Sdes goto parse_flag; 112792559Sdes 112892559Sdes case sKerberosTicketCleanup: 112992559Sdes intptr = &options->kerberos_ticket_cleanup; 113092559Sdes goto parse_flag; 1131124211Sdes 1132126277Sdes case sKerberosGetAFSToken: 1133126277Sdes intptr = &options->kerberos_get_afs_token; 1134126277Sdes goto parse_flag; 1135126277Sdes 1136124211Sdes case sGssAuthentication: 1137124211Sdes intptr = &options->gss_authentication; 113892559Sdes goto parse_flag; 1139124211Sdes 1140124211Sdes case sGssCleanupCreds: 1141124211Sdes intptr = &options->gss_cleanup_creds; 114292559Sdes goto parse_flag; 114357429Smarkm 114492559Sdes case sPasswordAuthentication: 114592559Sdes intptr = &options->password_authentication; 114692559Sdes goto parse_flag; 114757565Smarkm 114892559Sdes case sKbdInteractiveAuthentication: 114992559Sdes intptr = &options->kbd_interactive_authentication; 115092559Sdes goto parse_flag; 115157429Smarkm 115292559Sdes case sChallengeResponseAuthentication: 115392559Sdes intptr = &options->challenge_response_authentication; 115492559Sdes goto parse_flag; 115557429Smarkm 115692559Sdes case sPrintMotd: 115792559Sdes intptr = &options->print_motd; 115892559Sdes goto parse_flag; 115957429Smarkm 116092559Sdes case sPrintLastLog: 116192559Sdes intptr = &options->print_lastlog; 116292559Sdes goto parse_flag; 116369591Sgreen 116492559Sdes case sX11Forwarding: 116592559Sdes intptr = &options->x11_forwarding; 116692559Sdes goto parse_flag; 116757429Smarkm 116892559Sdes case sX11DisplayOffset: 116992559Sdes intptr = &options->x11_display_offset; 117092559Sdes goto parse_int; 117157429Smarkm 117292559Sdes case sX11UseLocalhost: 117392559Sdes intptr = &options->x11_use_localhost; 117492559Sdes goto parse_flag; 117557429Smarkm 117692559Sdes case sXAuthLocation: 117792559Sdes charptr = &options->xauth_location; 117892559Sdes goto parse_filename; 117976262Sgreen 1180262566Sdes case sPermitTTY: 1181262566Sdes intptr = &options->permit_tty; 1182262566Sdes goto parse_flag; 1183262566Sdes 118492559Sdes case sStrictModes: 118592559Sdes intptr = &options->strict_modes; 118692559Sdes goto parse_flag; 118757429Smarkm 1188126277Sdes case sTCPKeepAlive: 1189126277Sdes intptr = &options->tcp_keep_alive; 119092559Sdes goto parse_flag; 119157429Smarkm 119292559Sdes case sEmptyPasswd: 119392559Sdes intptr = &options->permit_empty_passwd; 119492559Sdes goto parse_flag; 119576262Sgreen 1196106130Sdes case sPermitUserEnvironment: 1197106130Sdes intptr = &options->permit_user_env; 1198106130Sdes goto parse_flag; 1199106130Sdes 120092559Sdes case sUseLogin: 120192559Sdes intptr = &options->use_login; 120292559Sdes goto parse_flag; 120357429Smarkm 120498684Sdes case sCompression: 120598684Sdes intptr = &options->compression; 1206226046Sdes multistate_ptr = multistate_compression; 1207226046Sdes goto parse_multistate; 120898684Sdes 1209255767Sdes case sRekeyLimit: 1210255767Sdes arg = strdelim(&cp); 1211255767Sdes if (!arg || *arg == '\0') 1212255767Sdes fatal("%.200s line %d: Missing argument.", filename, 1213255767Sdes linenum); 1214255767Sdes if (strcmp(arg, "default") == 0) { 1215255767Sdes val64 = 0; 1216255767Sdes } else { 1217255767Sdes if (scan_scaled(arg, &val64) == -1) 1218255767Sdes fatal("%.200s line %d: Bad number '%s': %s", 1219255767Sdes filename, linenum, arg, strerror(errno)); 1220255767Sdes /* check for too-large or too-small limits */ 1221255767Sdes if (val64 > UINT_MAX) 1222255767Sdes fatal("%.200s line %d: RekeyLimit too large", 1223255767Sdes filename, linenum); 1224255767Sdes if (val64 != 0 && val64 < 16) 1225255767Sdes fatal("%.200s line %d: RekeyLimit too small", 1226255767Sdes filename, linenum); 1227255767Sdes } 1228255767Sdes if (*activep && options->rekey_limit == -1) 1229255767Sdes options->rekey_limit = (u_int32_t)val64; 1230255767Sdes if (cp != NULL) { /* optional rekey interval present */ 1231255767Sdes if (strcmp(cp, "none") == 0) { 1232255767Sdes (void)strdelim(&cp); /* discard */ 1233255767Sdes break; 1234255767Sdes } 1235255767Sdes intptr = &options->rekey_interval; 1236255767Sdes goto parse_time; 1237255767Sdes } 1238255767Sdes break; 1239255767Sdes 124092559Sdes case sGatewayPorts: 124192559Sdes intptr = &options->gateway_ports; 1242226046Sdes multistate_ptr = multistate_gatewayports; 1243226046Sdes goto parse_multistate; 124457429Smarkm 1245124211Sdes case sUseDNS: 1246124211Sdes intptr = &options->use_dns; 124792559Sdes goto parse_flag; 124857429Smarkm 124992559Sdes case sLogFacility: 1250181111Sdes log_facility_ptr = &options->log_facility; 125192559Sdes arg = strdelim(&cp); 125292559Sdes value = log_facility_number(arg); 125392559Sdes if (value == SYSLOG_FACILITY_NOT_SET) 125492559Sdes fatal("%.200s line %d: unsupported log facility '%s'", 125592559Sdes filename, linenum, arg ? arg : "<NONE>"); 1256181111Sdes if (*log_facility_ptr == -1) 1257181111Sdes *log_facility_ptr = (SyslogFacility) value; 125892559Sdes break; 125957429Smarkm 126092559Sdes case sLogLevel: 1261181111Sdes log_level_ptr = &options->log_level; 126292559Sdes arg = strdelim(&cp); 126392559Sdes value = log_level_number(arg); 126492559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 126592559Sdes fatal("%.200s line %d: unsupported log level '%s'", 126692559Sdes filename, linenum, arg ? arg : "<NONE>"); 1267181111Sdes if (*log_level_ptr == -1) 1268181111Sdes *log_level_ptr = (LogLevel) value; 126992559Sdes break; 127060576Skris 127192559Sdes case sAllowTcpForwarding: 127292559Sdes intptr = &options->allow_tcp_forwarding; 1273248619Sdes multistate_ptr = multistate_tcpfwd; 1274248619Sdes goto parse_multistate; 127576262Sgreen 1276181111Sdes case sAllowAgentForwarding: 1277181111Sdes intptr = &options->allow_agent_forwarding; 1278181111Sdes goto parse_flag; 1279181111Sdes 128098684Sdes case sUsePrivilegeSeparation: 128198684Sdes intptr = &use_privsep; 1282226046Sdes multistate_ptr = multistate_privsep; 1283226046Sdes goto parse_multistate; 128498684Sdes 128592559Sdes case sAllowUsers: 128692559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 128792559Sdes if (options->num_allow_users >= MAX_ALLOW_USERS) 128892559Sdes fatal("%s line %d: too many allow users.", 128992559Sdes filename, linenum); 1290240075Sdes if (!*activep) 1291240075Sdes continue; 129299063Sdes options->allow_users[options->num_allow_users++] = 129399063Sdes xstrdup(arg); 129492559Sdes } 129592559Sdes break; 129657429Smarkm 129792559Sdes case sDenyUsers: 129892559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 129992559Sdes if (options->num_deny_users >= MAX_DENY_USERS) 1300162856Sdes fatal("%s line %d: too many deny users.", 130192559Sdes filename, linenum); 1302240075Sdes if (!*activep) 1303240075Sdes continue; 130499063Sdes options->deny_users[options->num_deny_users++] = 130599063Sdes xstrdup(arg); 130692559Sdes } 130792559Sdes break; 130857429Smarkm 130992559Sdes case sAllowGroups: 131092559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 131192559Sdes if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 131292559Sdes fatal("%s line %d: too many allow groups.", 131392559Sdes filename, linenum); 1314240075Sdes if (!*activep) 1315240075Sdes continue; 131699063Sdes options->allow_groups[options->num_allow_groups++] = 131799063Sdes xstrdup(arg); 131892559Sdes } 131992559Sdes break; 132069591Sgreen 132192559Sdes case sDenyGroups: 132292559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 132392559Sdes if (options->num_deny_groups >= MAX_DENY_GROUPS) 132492559Sdes fatal("%s line %d: too many deny groups.", 132592559Sdes filename, linenum); 1326240075Sdes if (!*activep) 1327240075Sdes continue; 1328240075Sdes options->deny_groups[options->num_deny_groups++] = 1329240075Sdes xstrdup(arg); 133092559Sdes } 133192559Sdes break; 133257429Smarkm 133392559Sdes case sCiphers: 133492559Sdes arg = strdelim(&cp); 133592559Sdes if (!arg || *arg == '\0') 133692559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 133792559Sdes if (!ciphers_valid(arg)) 133892559Sdes fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 133992559Sdes filename, linenum, arg ? arg : "<NONE>"); 134092559Sdes if (options->ciphers == NULL) 134192559Sdes options->ciphers = xstrdup(arg); 134292559Sdes break; 134357429Smarkm 134492559Sdes case sMacs: 134592559Sdes arg = strdelim(&cp); 134692559Sdes if (!arg || *arg == '\0') 134792559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 134892559Sdes if (!mac_valid(arg)) 134992559Sdes fatal("%s line %d: Bad SSH2 mac spec '%s'.", 135092559Sdes filename, linenum, arg ? arg : "<NONE>"); 135192559Sdes if (options->macs == NULL) 135292559Sdes options->macs = xstrdup(arg); 135392559Sdes break; 135457429Smarkm 1355221420Sdes case sKexAlgorithms: 1356221420Sdes arg = strdelim(&cp); 1357221420Sdes if (!arg || *arg == '\0') 1358221420Sdes fatal("%s line %d: Missing argument.", 1359221420Sdes filename, linenum); 1360221420Sdes if (!kex_names_valid(arg)) 1361221420Sdes fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", 1362221420Sdes filename, linenum, arg ? arg : "<NONE>"); 1363221420Sdes if (options->kex_algorithms == NULL) 1364221420Sdes options->kex_algorithms = xstrdup(arg); 1365221420Sdes break; 1366221420Sdes 136792559Sdes case sProtocol: 136892559Sdes intptr = &options->protocol; 136992559Sdes arg = strdelim(&cp); 137092559Sdes if (!arg || *arg == '\0') 137192559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 137292559Sdes value = proto_spec(arg); 137392559Sdes if (value == SSH_PROTO_UNKNOWN) 137492559Sdes fatal("%s line %d: Bad protocol spec '%s'.", 137592559Sdes filename, linenum, arg ? arg : "<NONE>"); 137692559Sdes if (*intptr == SSH_PROTO_UNKNOWN) 137792559Sdes *intptr = value; 137892559Sdes break; 137957429Smarkm 138092559Sdes case sSubsystem: 138192559Sdes if (options->num_subsystems >= MAX_SUBSYSTEMS) { 138292559Sdes fatal("%s line %d: too many subsystems defined.", 138392559Sdes filename, linenum); 138492559Sdes } 138592559Sdes arg = strdelim(&cp); 138692559Sdes if (!arg || *arg == '\0') 138792559Sdes fatal("%s line %d: Missing subsystem name.", 138892559Sdes filename, linenum); 1389162856Sdes if (!*activep) { 1390162856Sdes arg = strdelim(&cp); 1391162856Sdes break; 1392162856Sdes } 139392559Sdes for (i = 0; i < options->num_subsystems; i++) 139492559Sdes if (strcmp(arg, options->subsystem_name[i]) == 0) 139592559Sdes fatal("%s line %d: Subsystem '%s' already defined.", 139692559Sdes filename, linenum, arg); 139792559Sdes options->subsystem_name[options->num_subsystems] = xstrdup(arg); 139892559Sdes arg = strdelim(&cp); 139992559Sdes if (!arg || *arg == '\0') 140092559Sdes fatal("%s line %d: Missing subsystem command.", 140192559Sdes filename, linenum); 140292559Sdes options->subsystem_command[options->num_subsystems] = xstrdup(arg); 1403162856Sdes 1404162856Sdes /* Collect arguments (separate to executable) */ 1405162856Sdes p = xstrdup(arg); 1406162856Sdes len = strlen(p) + 1; 1407162856Sdes while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { 1408162856Sdes len += 1 + strlen(arg); 1409162856Sdes p = xrealloc(p, 1, len); 1410162856Sdes strlcat(p, " ", len); 1411162856Sdes strlcat(p, arg, len); 1412162856Sdes } 1413162856Sdes options->subsystem_args[options->num_subsystems] = p; 141492559Sdes options->num_subsystems++; 141592559Sdes break; 141660576Skris 141792559Sdes case sMaxStartups: 141892559Sdes arg = strdelim(&cp); 141992559Sdes if (!arg || *arg == '\0') 142092559Sdes fatal("%s line %d: Missing MaxStartups spec.", 142192559Sdes filename, linenum); 142292559Sdes if ((n = sscanf(arg, "%d:%d:%d", 142392559Sdes &options->max_startups_begin, 142492559Sdes &options->max_startups_rate, 142592559Sdes &options->max_startups)) == 3) { 142692559Sdes if (options->max_startups_begin > 142792559Sdes options->max_startups || 142892559Sdes options->max_startups_rate > 100 || 142992559Sdes options->max_startups_rate < 1) 143092559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 143192559Sdes filename, linenum); 143292559Sdes } else if (n != 1) 143392559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 143492559Sdes filename, linenum); 143592559Sdes else 143692559Sdes options->max_startups = options->max_startups_begin; 143792559Sdes break; 143876262Sgreen 1439137019Sdes case sMaxAuthTries: 1440137019Sdes intptr = &options->max_authtries; 1441137019Sdes goto parse_int; 1442137019Sdes 1443181111Sdes case sMaxSessions: 1444181111Sdes intptr = &options->max_sessions; 1445181111Sdes goto parse_int; 1446181111Sdes 144792559Sdes case sBanner: 144892559Sdes charptr = &options->banner; 144992559Sdes goto parse_filename; 1450181111Sdes 145192559Sdes /* 145292559Sdes * These options can contain %X options expanded at 145392559Sdes * connect time, so that you can specify paths like: 145492559Sdes * 145592559Sdes * AuthorizedKeysFile /etc/ssh_keys/%u 145692559Sdes */ 145792559Sdes case sAuthorizedKeysFile: 1458226046Sdes if (*activep && options->num_authkeys_files == 0) { 1459226046Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1460226046Sdes if (options->num_authkeys_files >= 1461226046Sdes MAX_AUTHKEYS_FILES) 1462226046Sdes fatal("%s line %d: " 1463226046Sdes "too many authorized keys files.", 1464226046Sdes filename, linenum); 1465226046Sdes options->authorized_keys_files[ 1466226046Sdes options->num_authkeys_files++] = 1467226046Sdes tilde_expand_filename(arg, getuid()); 1468226046Sdes } 1469226046Sdes } 1470226046Sdes return 0; 1471226046Sdes 1472215116Sdes case sAuthorizedPrincipalsFile: 1473215116Sdes charptr = &options->authorized_principals_file; 1474207319Sdes arg = strdelim(&cp); 1475207319Sdes if (!arg || *arg == '\0') 1476207319Sdes fatal("%s line %d: missing file name.", 1477207319Sdes filename, linenum); 1478207319Sdes if (*activep && *charptr == NULL) { 1479207319Sdes *charptr = tilde_expand_filename(arg, getuid()); 1480207319Sdes /* increase optional counter */ 1481207319Sdes if (intptr != NULL) 1482207319Sdes *intptr = *intptr + 1; 1483207319Sdes } 1484207319Sdes break; 148560576Skris 148692559Sdes case sClientAliveInterval: 148792559Sdes intptr = &options->client_alive_interval; 148892559Sdes goto parse_time; 148957432Smarkm 149092559Sdes case sClientAliveCountMax: 149192559Sdes intptr = &options->client_alive_count_max; 149292559Sdes goto parse_int; 149365674Skris 1494137019Sdes case sAcceptEnv: 1495137019Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1496137019Sdes if (strchr(arg, '=') != NULL) 1497137019Sdes fatal("%s line %d: Invalid environment name.", 1498137019Sdes filename, linenum); 1499137019Sdes if (options->num_accept_env >= MAX_ACCEPT_ENV) 1500137019Sdes fatal("%s line %d: too many allow env.", 1501137019Sdes filename, linenum); 1502162856Sdes if (!*activep) 1503240075Sdes continue; 1504137019Sdes options->accept_env[options->num_accept_env++] = 1505137019Sdes xstrdup(arg); 1506137019Sdes } 1507137019Sdes break; 1508137019Sdes 1509157019Sdes case sPermitTunnel: 1510157019Sdes intptr = &options->permit_tun; 1511157019Sdes arg = strdelim(&cp); 1512157019Sdes if (!arg || *arg == '\0') 1513157019Sdes fatal("%s line %d: Missing yes/point-to-point/" 1514157019Sdes "ethernet/no argument.", filename, linenum); 1515181111Sdes value = -1; 1516181111Sdes for (i = 0; tunmode_desc[i].val != -1; i++) 1517181111Sdes if (strcmp(tunmode_desc[i].text, arg) == 0) { 1518181111Sdes value = tunmode_desc[i].val; 1519181111Sdes break; 1520181111Sdes } 1521181111Sdes if (value == -1) 1522157019Sdes fatal("%s line %d: Bad yes/point-to-point/ethernet/" 1523157019Sdes "no argument: %s", filename, linenum, arg); 1524157019Sdes if (*intptr == -1) 1525157019Sdes *intptr = value; 1526157019Sdes break; 1527157019Sdes 1528162856Sdes case sMatch: 1529162856Sdes if (cmdline) 1530162856Sdes fatal("Match directive not supported as a command-line " 1531162856Sdes "option"); 1532240075Sdes value = match_cfg_line(&cp, linenum, connectinfo); 1533162856Sdes if (value < 0) 1534162856Sdes fatal("%s line %d: Bad Match condition", filename, 1535162856Sdes linenum); 1536162856Sdes *activep = value; 1537162856Sdes break; 1538162856Sdes 1539162856Sdes case sPermitOpen: 1540162856Sdes arg = strdelim(&cp); 1541162856Sdes if (!arg || *arg == '\0') 1542162856Sdes fatal("%s line %d: missing PermitOpen specification", 1543162856Sdes filename, linenum); 1544181111Sdes n = options->num_permitted_opens; /* modified later */ 1545162856Sdes if (strcmp(arg, "any") == 0) { 1546181111Sdes if (*activep && n == -1) { 1547162856Sdes channel_clear_adm_permitted_opens(); 1548162856Sdes options->num_permitted_opens = 0; 1549162856Sdes } 1550162856Sdes break; 1551162856Sdes } 1552240075Sdes if (strcmp(arg, "none") == 0) { 1553240075Sdes if (*activep && n == -1) { 1554240075Sdes options->num_permitted_opens = 1; 1555240075Sdes channel_disable_adm_local_opens(); 1556240075Sdes } 1557240075Sdes break; 1558240075Sdes } 1559181111Sdes if (*activep && n == -1) 1560181111Sdes channel_clear_adm_permitted_opens(); 1561162856Sdes for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { 1562162856Sdes p = hpdelim(&arg); 1563162856Sdes if (p == NULL) 1564162856Sdes fatal("%s line %d: missing host in PermitOpen", 1565162856Sdes filename, linenum); 1566162856Sdes p = cleanhostname(p); 1567240075Sdes if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 1568162856Sdes fatal("%s line %d: bad port number in " 1569162856Sdes "PermitOpen", filename, linenum); 1570181111Sdes if (*activep && n == -1) 1571162856Sdes options->num_permitted_opens = 1572162856Sdes channel_add_adm_permitted_opens(p, port); 1573162856Sdes } 1574162856Sdes break; 1575162856Sdes 1576162856Sdes case sForceCommand: 1577162856Sdes if (cp == NULL) 1578162856Sdes fatal("%.200s line %d: Missing argument.", filename, 1579162856Sdes linenum); 1580162856Sdes len = strspn(cp, WHITESPACE); 1581162856Sdes if (*activep && options->adm_forced_command == NULL) 1582162856Sdes options->adm_forced_command = xstrdup(cp + len); 1583162856Sdes return 0; 1584162856Sdes 1585181111Sdes case sChrootDirectory: 1586181111Sdes charptr = &options->chroot_directory; 1587181111Sdes 1588181111Sdes arg = strdelim(&cp); 1589181111Sdes if (!arg || *arg == '\0') 1590181111Sdes fatal("%s line %d: missing file name.", 1591181111Sdes filename, linenum); 1592181111Sdes if (*activep && *charptr == NULL) 1593181111Sdes *charptr = xstrdup(arg); 1594181111Sdes break; 1595181111Sdes 1596204917Sdes case sTrustedUserCAKeys: 1597204917Sdes charptr = &options->trusted_user_ca_keys; 1598204917Sdes goto parse_filename; 1599204917Sdes 1600204917Sdes case sRevokedKeys: 1601204917Sdes charptr = &options->revoked_keys_file; 1602204917Sdes goto parse_filename; 1603204917Sdes 1604221420Sdes case sIPQoS: 1605221420Sdes arg = strdelim(&cp); 1606221420Sdes if ((value = parse_ipqos(arg)) == -1) 1607221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1608221420Sdes filename, linenum, arg); 1609221420Sdes arg = strdelim(&cp); 1610221420Sdes if (arg == NULL) 1611221420Sdes value2 = value; 1612221420Sdes else if ((value2 = parse_ipqos(arg)) == -1) 1613221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1614221420Sdes filename, linenum, arg); 1615221420Sdes if (*activep) { 1616221420Sdes options->ip_qos_interactive = value; 1617221420Sdes options->ip_qos_bulk = value2; 1618221420Sdes } 1619221420Sdes break; 1620221420Sdes 162199047Sdes case sVersionAddendum: 1622240075Sdes if (cp == NULL) 1623240075Sdes fatal("%.200s line %d: Missing argument.", filename, 1624240075Sdes linenum); 1625240075Sdes len = strspn(cp, WHITESPACE); 1626240075Sdes if (*activep && options->version_addendum == NULL) { 1627240075Sdes if (strcasecmp(cp + len, "none") == 0) 1628240075Sdes options->version_addendum = xstrdup(""); 1629240075Sdes else if (strchr(cp + len, '\r') != NULL) 1630240075Sdes fatal("%.200s line %d: Invalid argument", 1631240075Sdes filename, linenum); 1632240075Sdes else 1633240075Sdes options->version_addendum = xstrdup(cp + len); 1634240075Sdes } 1635240075Sdes return 0; 163699047Sdes 1637248619Sdes case sAuthorizedKeysCommand: 1638248619Sdes len = strspn(cp, WHITESPACE); 1639248619Sdes if (*activep && options->authorized_keys_command == NULL) { 1640248619Sdes if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) 1641248619Sdes fatal("%.200s line %d: AuthorizedKeysCommand " 1642248619Sdes "must be an absolute path", 1643248619Sdes filename, linenum); 1644248619Sdes options->authorized_keys_command = xstrdup(cp + len); 1645248619Sdes } 1646248619Sdes return 0; 1647248619Sdes 1648248619Sdes case sAuthorizedKeysCommandUser: 1649248619Sdes charptr = &options->authorized_keys_command_user; 1650248619Sdes 1651248619Sdes arg = strdelim(&cp); 1652248619Sdes if (*activep && *charptr == NULL) 1653248619Sdes *charptr = xstrdup(arg); 1654248619Sdes break; 1655248619Sdes 1656248619Sdes case sAuthenticationMethods: 1657248619Sdes if (*activep && options->num_auth_methods == 0) { 1658248619Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1659248619Sdes if (options->num_auth_methods >= 1660248619Sdes MAX_AUTH_METHODS) 1661248619Sdes fatal("%s line %d: " 1662248619Sdes "too many authentication methods.", 1663248619Sdes filename, linenum); 1664248619Sdes if (auth2_methods_valid(arg, 0) != 0) 1665248619Sdes fatal("%s line %d: invalid " 1666248619Sdes "authentication method list.", 1667248619Sdes filename, linenum); 1668248619Sdes options->auth_methods[ 1669248619Sdes options->num_auth_methods++] = xstrdup(arg); 1670248619Sdes } 1671248619Sdes } 1672248619Sdes return 0; 1673248619Sdes 1674224638Sbrooks case sHPNDisabled: 1675224638Sbrooks intptr = &options->hpn_disabled; 1676224638Sbrooks goto parse_flag; 1677224638Sbrooks 1678224638Sbrooks case sHPNBufferSize: 1679224638Sbrooks intptr = &options->hpn_buffer_size; 1680224638Sbrooks goto parse_int; 1681224638Sbrooks 1682224638Sbrooks case sTcpRcvBufPoll: 1683224638Sbrooks intptr = &options->tcp_rcv_buf_poll; 1684224638Sbrooks goto parse_flag; 1685224638Sbrooks 1686224638Sbrooks#ifdef NONE_CIPHER_ENABLED 1687224638Sbrooks case sNoneEnabled: 1688224638Sbrooks intptr = &options->none_enabled; 1689224638Sbrooks goto parse_flag; 1690224638Sbrooks#endif 1691224638Sbrooks 169292559Sdes case sDeprecated: 1693124211Sdes logit("%s line %d: Deprecated option %s", 169492559Sdes filename, linenum, arg); 169592559Sdes while (arg) 169692559Sdes arg = strdelim(&cp); 169792559Sdes break; 169892559Sdes 1699124211Sdes case sUnsupported: 1700124211Sdes logit("%s line %d: Unsupported option %s", 1701124211Sdes filename, linenum, arg); 1702124211Sdes while (arg) 1703124211Sdes arg = strdelim(&cp); 1704124211Sdes break; 1705124211Sdes 170692559Sdes default: 170792559Sdes fatal("%s line %d: Missing handler for opcode %s (%d)", 170892559Sdes filename, linenum, arg, opcode); 170992559Sdes } 171092559Sdes if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 171192559Sdes fatal("%s line %d: garbage at end of line; \"%.200s\".", 171292559Sdes filename, linenum, arg); 171392559Sdes return 0; 171492559Sdes} 171576227Sgreen 171692559Sdes/* Reads the server configuration file. */ 171792559Sdes 171892559Sdesvoid 1719137019Sdesload_server_config(const char *filename, Buffer *conf) 172092559Sdes{ 1721240075Sdes char line[4096], *cp; 172292559Sdes FILE *f; 1723240075Sdes int lineno = 0; 172492559Sdes 1725137019Sdes debug2("%s: filename %s", __func__, filename); 1726137019Sdes if ((f = fopen(filename, "r")) == NULL) { 172792559Sdes perror(filename); 172892559Sdes exit(1); 172957429Smarkm } 1730137019Sdes buffer_clear(conf); 173192559Sdes while (fgets(line, sizeof(line), f)) { 1732240075Sdes lineno++; 1733240075Sdes if (strlen(line) == sizeof(line) - 1) 1734240075Sdes fatal("%s line %d too long", filename, lineno); 1735137019Sdes /* 1736137019Sdes * Trim out comments and strip whitespace 1737137019Sdes * NB - preserve newlines, they are needed to reproduce 1738137019Sdes * line numbers later for error messages 1739137019Sdes */ 1740137019Sdes if ((cp = strchr(line, '#')) != NULL) 1741137019Sdes memcpy(cp, "\n", 2); 1742137019Sdes cp = line + strspn(line, " \t\r"); 1743137019Sdes 1744137019Sdes buffer_append(conf, cp, strlen(cp)); 1745137019Sdes } 1746137019Sdes buffer_append(conf, "\0", 1); 1747137019Sdes fclose(f); 1748137019Sdes debug2("%s: done config len = %d", __func__, buffer_len(conf)); 1749137019Sdes} 1750137019Sdes 1751137019Sdesvoid 1752240075Sdesparse_server_match_config(ServerOptions *options, 1753240075Sdes struct connection_info *connectinfo) 1754137019Sdes{ 1755162856Sdes ServerOptions mo; 1756162856Sdes 1757162856Sdes initialize_server_options(&mo); 1758240075Sdes parse_server_config(&mo, "reprocess config", &cfg, connectinfo); 1759181111Sdes copy_set_server_options(options, &mo, 0); 1760162856Sdes} 1761162856Sdes 1762240075Sdesint parse_server_match_testspec(struct connection_info *ci, char *spec) 1763240075Sdes{ 1764240075Sdes char *p; 1765240075Sdes 1766240075Sdes while ((p = strsep(&spec, ",")) && *p != '\0') { 1767240075Sdes if (strncmp(p, "addr=", 5) == 0) { 1768240075Sdes ci->address = xstrdup(p + 5); 1769240075Sdes } else if (strncmp(p, "host=", 5) == 0) { 1770240075Sdes ci->host = xstrdup(p + 5); 1771240075Sdes } else if (strncmp(p, "user=", 5) == 0) { 1772240075Sdes ci->user = xstrdup(p + 5); 1773240075Sdes } else if (strncmp(p, "laddr=", 6) == 0) { 1774240075Sdes ci->laddress = xstrdup(p + 6); 1775240075Sdes } else if (strncmp(p, "lport=", 6) == 0) { 1776240075Sdes ci->lport = a2port(p + 6); 1777240075Sdes if (ci->lport == -1) { 1778240075Sdes fprintf(stderr, "Invalid port '%s' in test mode" 1779240075Sdes " specification %s\n", p+6, p); 1780240075Sdes return -1; 1781240075Sdes } 1782240075Sdes } else { 1783240075Sdes fprintf(stderr, "Invalid test mode specification %s\n", 1784240075Sdes p); 1785240075Sdes return -1; 1786240075Sdes } 1787240075Sdes } 1788240075Sdes return 0; 1789240075Sdes} 1790240075Sdes 1791240075Sdes/* 1792240075Sdes * returns 1 for a complete spec, 0 for partial spec and -1 for an 1793240075Sdes * empty spec. 1794240075Sdes */ 1795240075Sdesint server_match_spec_complete(struct connection_info *ci) 1796240075Sdes{ 1797240075Sdes if (ci->user && ci->host && ci->address) 1798240075Sdes return 1; /* complete */ 1799240075Sdes if (!ci->user && !ci->host && !ci->address) 1800240075Sdes return -1; /* empty */ 1801240075Sdes return 0; /* partial */ 1802240075Sdes} 1803240075Sdes 1804181111Sdes/* 1805181111Sdes * Copy any supported values that are set. 1806181111Sdes * 1807197679Sdes * If the preauth flag is set, we do not bother copying the string or 1808181111Sdes * array values that are not used pre-authentication, because any that we 1809181111Sdes * do use must be explictly sent in mm_getpwnamallow(). 1810181111Sdes */ 1811162856Sdesvoid 1812181111Sdescopy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) 1813162856Sdes{ 1814262566Sdes#define M_CP_INTOPT(n) do {\ 1815262566Sdes if (src->n != -1) \ 1816262566Sdes dst->n = src->n; \ 1817262566Sdes} while (0) 1818262566Sdes 1819181111Sdes M_CP_INTOPT(password_authentication); 1820181111Sdes M_CP_INTOPT(gss_authentication); 1821181111Sdes M_CP_INTOPT(rsa_authentication); 1822181111Sdes M_CP_INTOPT(pubkey_authentication); 1823181111Sdes M_CP_INTOPT(kerberos_authentication); 1824181111Sdes M_CP_INTOPT(hostbased_authentication); 1825215116Sdes M_CP_INTOPT(hostbased_uses_name_from_packet_only); 1826181111Sdes M_CP_INTOPT(kbd_interactive_authentication); 1827181111Sdes M_CP_INTOPT(permit_root_login); 1828192595Sdes M_CP_INTOPT(permit_empty_passwd); 1829181111Sdes 1830181111Sdes M_CP_INTOPT(allow_tcp_forwarding); 1831181111Sdes M_CP_INTOPT(allow_agent_forwarding); 1832215116Sdes M_CP_INTOPT(permit_tun); 1833181111Sdes M_CP_INTOPT(gateway_ports); 1834181111Sdes M_CP_INTOPT(x11_display_offset); 1835181111Sdes M_CP_INTOPT(x11_forwarding); 1836181111Sdes M_CP_INTOPT(x11_use_localhost); 1837262566Sdes M_CP_INTOPT(permit_tty); 1838181111Sdes M_CP_INTOPT(max_sessions); 1839181111Sdes M_CP_INTOPT(max_authtries); 1840221420Sdes M_CP_INTOPT(ip_qos_interactive); 1841221420Sdes M_CP_INTOPT(ip_qos_bulk); 1842255767Sdes M_CP_INTOPT(rekey_limit); 1843255767Sdes M_CP_INTOPT(rekey_interval); 1844181111Sdes 1845262566Sdes /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ 1846262566Sdes#define M_CP_STROPT(n) do {\ 1847262566Sdes if (src->n != NULL && dst->n != src->n) { \ 1848262566Sdes free(dst->n); \ 1849262566Sdes dst->n = src->n; \ 1850262566Sdes } \ 1851262566Sdes} while(0) 1852262566Sdes#define M_CP_STRARRAYOPT(n, num_n) do {\ 1853262566Sdes if (src->num_n != 0) { \ 1854262566Sdes for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \ 1855262566Sdes dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ 1856262566Sdes } \ 1857262566Sdes} while(0) 1858262566Sdes 1859226046Sdes /* See comment in servconf.h */ 1860226046Sdes COPY_MATCH_STRING_OPTS(); 1861226046Sdes 1862226046Sdes /* 1863226046Sdes * The only things that should be below this point are string options 1864226046Sdes * which are only used after authentication. 1865226046Sdes */ 1866181111Sdes if (preauth) 1867181111Sdes return; 1868226046Sdes 1869181111Sdes M_CP_STROPT(adm_forced_command); 1870181111Sdes M_CP_STROPT(chroot_directory); 1871162856Sdes} 1872162856Sdes 1873181111Sdes#undef M_CP_INTOPT 1874181111Sdes#undef M_CP_STROPT 1875226046Sdes#undef M_CP_STRARRAYOPT 1876181111Sdes 1877162856Sdesvoid 1878162856Sdesparse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1879240075Sdes struct connection_info *connectinfo) 1880162856Sdes{ 1881162856Sdes int active, linenum, bad_options = 0; 1882137019Sdes char *cp, *obuf, *cbuf; 1883137019Sdes 1884137019Sdes debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); 1885137019Sdes 1886137019Sdes obuf = cbuf = xstrdup(buffer_ptr(conf)); 1887240075Sdes active = connectinfo ? 0 : 1; 1888137019Sdes linenum = 1; 1889147005Sdes while ((cp = strsep(&cbuf, "\n")) != NULL) { 1890137019Sdes if (process_server_config_line(options, cp, filename, 1891240075Sdes linenum++, &active, connectinfo) != 0) 189292559Sdes bad_options++; 189392559Sdes } 1894255767Sdes free(obuf); 189576262Sgreen if (bad_options > 0) 189692559Sdes fatal("%s: terminating, %d bad configuration options", 189776262Sgreen filename, bad_options); 189857429Smarkm} 1899181111Sdes 1900181111Sdesstatic const char * 1901226046Sdesfmt_multistate_int(int val, const struct multistate *m) 1902226046Sdes{ 1903226046Sdes u_int i; 1904226046Sdes 1905226046Sdes for (i = 0; m[i].key != NULL; i++) { 1906226046Sdes if (m[i].value == val) 1907226046Sdes return m[i].key; 1908226046Sdes } 1909226046Sdes return "UNKNOWN"; 1910226046Sdes} 1911226046Sdes 1912226046Sdesstatic const char * 1913181111Sdesfmt_intarg(ServerOpCodes code, int val) 1914181111Sdes{ 1915226046Sdes if (val == -1) 1916226046Sdes return "unset"; 1917226046Sdes switch (code) { 1918226046Sdes case sAddressFamily: 1919226046Sdes return fmt_multistate_int(val, multistate_addressfamily); 1920226046Sdes case sPermitRootLogin: 1921226046Sdes return fmt_multistate_int(val, multistate_permitrootlogin); 1922226046Sdes case sGatewayPorts: 1923226046Sdes return fmt_multistate_int(val, multistate_gatewayports); 1924226046Sdes case sCompression: 1925226046Sdes return fmt_multistate_int(val, multistate_compression); 1926226046Sdes case sUsePrivilegeSeparation: 1927226046Sdes return fmt_multistate_int(val, multistate_privsep); 1928248619Sdes case sAllowTcpForwarding: 1929248619Sdes return fmt_multistate_int(val, multistate_tcpfwd); 1930226046Sdes case sProtocol: 1931181111Sdes switch (val) { 1932181111Sdes case SSH_PROTO_1: 1933181111Sdes return "1"; 1934181111Sdes case SSH_PROTO_2: 1935181111Sdes return "2"; 1936181111Sdes case (SSH_PROTO_1|SSH_PROTO_2): 1937181111Sdes return "2,1"; 1938181111Sdes default: 1939181111Sdes return "UNKNOWN"; 1940181111Sdes } 1941226046Sdes default: 1942226046Sdes switch (val) { 1943226046Sdes case 0: 1944226046Sdes return "no"; 1945226046Sdes case 1: 1946226046Sdes return "yes"; 1947226046Sdes default: 1948226046Sdes return "UNKNOWN"; 1949226046Sdes } 1950181111Sdes } 1951181111Sdes} 1952181111Sdes 1953181111Sdesstatic const char * 1954181111Sdeslookup_opcode_name(ServerOpCodes code) 1955181111Sdes{ 1956181111Sdes u_int i; 1957181111Sdes 1958181111Sdes for (i = 0; keywords[i].name != NULL; i++) 1959181111Sdes if (keywords[i].opcode == code) 1960181111Sdes return(keywords[i].name); 1961181111Sdes return "UNKNOWN"; 1962181111Sdes} 1963181111Sdes 1964181111Sdesstatic void 1965181111Sdesdump_cfg_int(ServerOpCodes code, int val) 1966181111Sdes{ 1967181111Sdes printf("%s %d\n", lookup_opcode_name(code), val); 1968181111Sdes} 1969181111Sdes 1970181111Sdesstatic void 1971181111Sdesdump_cfg_fmtint(ServerOpCodes code, int val) 1972181111Sdes{ 1973181111Sdes printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 1974181111Sdes} 1975181111Sdes 1976181111Sdesstatic void 1977181111Sdesdump_cfg_string(ServerOpCodes code, const char *val) 1978181111Sdes{ 1979181111Sdes if (val == NULL) 1980181111Sdes return; 1981181111Sdes printf("%s %s\n", lookup_opcode_name(code), val); 1982181111Sdes} 1983181111Sdes 1984181111Sdesstatic void 1985181111Sdesdump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) 1986181111Sdes{ 1987181111Sdes u_int i; 1988181111Sdes 1989181111Sdes for (i = 0; i < count; i++) 1990226046Sdes printf("%s %s\n", lookup_opcode_name(code), vals[i]); 1991181111Sdes} 1992181111Sdes 1993226046Sdesstatic void 1994226046Sdesdump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) 1995226046Sdes{ 1996226046Sdes u_int i; 1997226046Sdes 1998226046Sdes printf("%s", lookup_opcode_name(code)); 1999226046Sdes for (i = 0; i < count; i++) 2000226046Sdes printf(" %s", vals[i]); 2001226046Sdes printf("\n"); 2002226046Sdes} 2003226046Sdes 2004181111Sdesvoid 2005181111Sdesdump_config(ServerOptions *o) 2006181111Sdes{ 2007181111Sdes u_int i; 2008181111Sdes int ret; 2009181111Sdes struct addrinfo *ai; 2010181111Sdes char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL; 2011181111Sdes 2012181111Sdes /* these are usually at the top of the config */ 2013181111Sdes for (i = 0; i < o->num_ports; i++) 2014181111Sdes printf("port %d\n", o->ports[i]); 2015181111Sdes dump_cfg_fmtint(sProtocol, o->protocol); 2016181111Sdes dump_cfg_fmtint(sAddressFamily, o->address_family); 2017181111Sdes 2018181111Sdes /* ListenAddress must be after Port */ 2019181111Sdes for (ai = o->listen_addrs; ai; ai = ai->ai_next) { 2020181111Sdes if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, 2021181111Sdes sizeof(addr), port, sizeof(port), 2022181111Sdes NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { 2023181111Sdes error("getnameinfo failed: %.100s", 2024181111Sdes (ret != EAI_SYSTEM) ? gai_strerror(ret) : 2025181111Sdes strerror(errno)); 2026181111Sdes } else { 2027181111Sdes if (ai->ai_family == AF_INET6) 2028181111Sdes printf("listenaddress [%s]:%s\n", addr, port); 2029181111Sdes else 2030181111Sdes printf("listenaddress %s:%s\n", addr, port); 2031181111Sdes } 2032181111Sdes } 2033181111Sdes 2034181111Sdes /* integer arguments */ 2035192595Sdes#ifdef USE_PAM 2036192595Sdes dump_cfg_int(sUsePAM, o->use_pam); 2037192595Sdes#endif 2038181111Sdes dump_cfg_int(sServerKeyBits, o->server_key_bits); 2039181111Sdes dump_cfg_int(sLoginGraceTime, o->login_grace_time); 2040181111Sdes dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time); 2041181111Sdes dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); 2042181111Sdes dump_cfg_int(sMaxAuthTries, o->max_authtries); 2043192595Sdes dump_cfg_int(sMaxSessions, o->max_sessions); 2044181111Sdes dump_cfg_int(sClientAliveInterval, o->client_alive_interval); 2045181111Sdes dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); 2046181111Sdes 2047181111Sdes /* formatted integer arguments */ 2048181111Sdes dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); 2049181111Sdes dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); 2050181111Sdes dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); 2051181111Sdes dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication); 2052181111Sdes dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); 2053181111Sdes dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, 2054181111Sdes o->hostbased_uses_name_from_packet_only); 2055181111Sdes dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication); 2056181111Sdes dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); 2057192595Sdes#ifdef KRB5 2058181111Sdes dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); 2059181111Sdes dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); 2060181111Sdes dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); 2061192595Sdes# ifdef USE_AFS 2062181111Sdes dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); 2063192595Sdes# endif 2064192595Sdes#endif 2065192595Sdes#ifdef GSSAPI 2066181111Sdes dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 2067181111Sdes dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 2068192595Sdes#endif 2069181111Sdes dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 2070181111Sdes dump_cfg_fmtint(sKbdInteractiveAuthentication, 2071181111Sdes o->kbd_interactive_authentication); 2072181111Sdes dump_cfg_fmtint(sChallengeResponseAuthentication, 2073181111Sdes o->challenge_response_authentication); 2074181111Sdes dump_cfg_fmtint(sPrintMotd, o->print_motd); 2075181111Sdes dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); 2076181111Sdes dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); 2077181111Sdes dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); 2078262566Sdes dump_cfg_fmtint(sPermitTTY, o->permit_tty); 2079181111Sdes dump_cfg_fmtint(sStrictModes, o->strict_modes); 2080181111Sdes dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); 2081181111Sdes dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); 2082181111Sdes dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 2083181111Sdes dump_cfg_fmtint(sUseLogin, o->use_login); 2084181111Sdes dump_cfg_fmtint(sCompression, o->compression); 2085181111Sdes dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); 2086181111Sdes dump_cfg_fmtint(sUseDNS, o->use_dns); 2087181111Sdes dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 2088181111Sdes dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); 2089181111Sdes 2090181111Sdes /* string arguments */ 2091181111Sdes dump_cfg_string(sPidFile, o->pid_file); 2092181111Sdes dump_cfg_string(sXAuthLocation, o->xauth_location); 2093262566Sdes dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : 2094262566Sdes cipher_alg_list(',', 0)); 2095262566Sdes dump_cfg_string(sMacs, o->macs ? o->macs : mac_alg_list(',')); 2096181111Sdes dump_cfg_string(sBanner, o->banner); 2097181111Sdes dump_cfg_string(sForceCommand, o->adm_forced_command); 2098204917Sdes dump_cfg_string(sChrootDirectory, o->chroot_directory); 2099204917Sdes dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); 2100204917Sdes dump_cfg_string(sRevokedKeys, o->revoked_keys_file); 2101215116Sdes dump_cfg_string(sAuthorizedPrincipalsFile, 2102215116Sdes o->authorized_principals_file); 2103240075Sdes dump_cfg_string(sVersionAddendum, o->version_addendum); 2104248619Sdes dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); 2105248619Sdes dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); 2106255767Sdes dump_cfg_string(sHostKeyAgent, o->host_key_agent); 2107262566Sdes dump_cfg_string(sKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : 2108262566Sdes kex_alg_list(',')); 2109181111Sdes 2110181111Sdes /* string arguments requiring a lookup */ 2111181111Sdes dump_cfg_string(sLogLevel, log_level_name(o->log_level)); 2112181111Sdes dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); 2113181111Sdes 2114181111Sdes /* string array arguments */ 2115226046Sdes dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, 2116226046Sdes o->authorized_keys_files); 2117181111Sdes dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, 2118181111Sdes o->host_key_files); 2119204917Sdes dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files, 2120204917Sdes o->host_cert_files); 2121181111Sdes dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); 2122181111Sdes dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); 2123181111Sdes dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); 2124181111Sdes dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); 2125181111Sdes dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); 2126248619Sdes dump_cfg_strarray_oneline(sAuthenticationMethods, 2127248619Sdes o->num_auth_methods, o->auth_methods); 2128181111Sdes 2129181111Sdes /* other arguments */ 2130181111Sdes for (i = 0; i < o->num_subsystems; i++) 2131181111Sdes printf("subsystem %s %s\n", o->subsystem_name[i], 2132181111Sdes o->subsystem_args[i]); 2133181111Sdes 2134181111Sdes printf("maxstartups %d:%d:%d\n", o->max_startups_begin, 2135181111Sdes o->max_startups_rate, o->max_startups); 2136181111Sdes 2137181111Sdes for (i = 0; tunmode_desc[i].val != -1; i++) 2138181111Sdes if (tunmode_desc[i].val == o->permit_tun) { 2139181111Sdes s = tunmode_desc[i].text; 2140181111Sdes break; 2141181111Sdes } 2142181111Sdes dump_cfg_string(sPermitTunnel, s); 2143181111Sdes 2144226046Sdes printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2145226046Sdes printf("%s\n", iptos2str(o->ip_qos_bulk)); 2146221420Sdes 2147255767Sdes printf("rekeylimit %lld %d\n", (long long)o->rekey_limit, 2148255767Sdes o->rekey_interval); 2149255767Sdes 2150181111Sdes channel_print_adm_permitted_opens(); 2151181111Sdes} 2152