1240075Sdes 2255767Sdes/* $OpenBSD: servconf.c,v 1.240 2013/07/19 07:37:48 markus 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; 9865674Skris options->xauth_location = NULL; 9957429Smarkm options->strict_modes = -1; 100126277Sdes options->tcp_keep_alive = -1; 10192559Sdes options->log_facility = SYSLOG_FACILITY_NOT_SET; 10292559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 10357429Smarkm options->rhosts_rsa_authentication = -1; 10476262Sgreen options->hostbased_authentication = -1; 10576262Sgreen options->hostbased_uses_name_from_packet_only = -1; 10657429Smarkm options->rsa_authentication = -1; 10776262Sgreen options->pubkey_authentication = -1; 10873400Sassar options->kerberos_authentication = -1; 10992559Sdes options->kerberos_or_local_passwd = -1; 11092559Sdes options->kerberos_ticket_cleanup = -1; 111126277Sdes options->kerberos_get_afs_token = -1; 112124211Sdes options->gss_authentication=-1; 113124211Sdes options->gss_cleanup_creds = -1; 11457429Smarkm options->password_authentication = -1; 11569591Sgreen options->kbd_interactive_authentication = -1; 11692559Sdes options->challenge_response_authentication = -1; 11757429Smarkm options->permit_empty_passwd = -1; 118106130Sdes options->permit_user_env = -1; 11957429Smarkm options->use_login = -1; 12098684Sdes options->compression = -1; 121255767Sdes options->rekey_limit = -1; 122255767Sdes options->rekey_interval = -1; 12369591Sgreen options->allow_tcp_forwarding = -1; 124181111Sdes options->allow_agent_forwarding = -1; 12557429Smarkm options->num_allow_users = 0; 12657429Smarkm options->num_deny_users = 0; 12757429Smarkm options->num_allow_groups = 0; 12857429Smarkm options->num_deny_groups = 0; 12960576Skris options->ciphers = NULL; 13076262Sgreen options->macs = NULL; 131221420Sdes options->kex_algorithms = NULL; 13260576Skris options->protocol = SSH_PROTO_UNKNOWN; 13360576Skris options->gateway_ports = -1; 13465674Skris options->num_subsystems = 0; 13565674Skris options->max_startups_begin = -1; 13665674Skris options->max_startups_rate = -1; 13765674Skris options->max_startups = -1; 138137019Sdes options->max_authtries = -1; 139181111Sdes options->max_sessions = -1; 14076262Sgreen options->banner = NULL; 141124211Sdes options->use_dns = -1; 14276262Sgreen options->client_alive_interval = -1; 14376262Sgreen options->client_alive_count_max = -1; 144226046Sdes options->num_authkeys_files = 0; 145137019Sdes options->num_accept_env = 0; 146157019Sdes options->permit_tun = -1; 147162856Sdes options->num_permitted_opens = -1; 148162856Sdes options->adm_forced_command = NULL; 149181111Sdes options->chroot_directory = NULL; 150248619Sdes options->authorized_keys_command = NULL; 151248619Sdes options->authorized_keys_command_user = NULL; 152192595Sdes options->zero_knowledge_password_authentication = -1; 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 19192559Sdes } 19276262Sgreen } 193204917Sdes /* No certificates by default */ 19457429Smarkm if (options->num_ports == 0) 19557429Smarkm options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 19657429Smarkm if (options->listen_addrs == NULL) 19776262Sgreen add_listen_addr(options, NULL, 0); 19860576Skris if (options->pid_file == NULL) 19976262Sgreen options->pid_file = _PATH_SSH_DAEMON_PID_FILE; 20057429Smarkm if (options->server_key_bits == -1) 201181111Sdes options->server_key_bits = 1024; 20257429Smarkm if (options->login_grace_time == -1) 20399048Sdes options->login_grace_time = 120; 20457429Smarkm if (options->key_regeneration_time == -1) 20557429Smarkm options->key_regeneration_time = 3600; 20676262Sgreen if (options->permit_root_login == PERMIT_NOT_SET) 20799048Sdes options->permit_root_login = PERMIT_NO; 20857429Smarkm if (options->ignore_rhosts == -1) 20957565Smarkm options->ignore_rhosts = 1; 21057429Smarkm if (options->ignore_user_known_hosts == -1) 21157429Smarkm options->ignore_user_known_hosts = 0; 21257429Smarkm if (options->print_motd == -1) 21357429Smarkm options->print_motd = 1; 21476262Sgreen if (options->print_lastlog == -1) 21576262Sgreen options->print_lastlog = 1; 21657429Smarkm if (options->x11_forwarding == -1) 21799048Sdes options->x11_forwarding = 1; 21857429Smarkm if (options->x11_display_offset == -1) 21957565Smarkm options->x11_display_offset = 10; 22092559Sdes if (options->x11_use_localhost == -1) 22192559Sdes options->x11_use_localhost = 1; 22265674Skris if (options->xauth_location == NULL) 22392559Sdes options->xauth_location = _PATH_XAUTH; 22457429Smarkm if (options->strict_modes == -1) 22557429Smarkm options->strict_modes = 1; 226126277Sdes if (options->tcp_keep_alive == -1) 227126277Sdes options->tcp_keep_alive = 1; 22892559Sdes if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 22957429Smarkm options->log_facility = SYSLOG_FACILITY_AUTH; 23092559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 23157429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 23257429Smarkm if (options->rhosts_rsa_authentication == -1) 23357565Smarkm options->rhosts_rsa_authentication = 0; 23476262Sgreen if (options->hostbased_authentication == -1) 23576262Sgreen options->hostbased_authentication = 0; 23676262Sgreen if (options->hostbased_uses_name_from_packet_only == -1) 23776262Sgreen options->hostbased_uses_name_from_packet_only = 0; 23857429Smarkm if (options->rsa_authentication == -1) 23957429Smarkm options->rsa_authentication = 1; 24076262Sgreen if (options->pubkey_authentication == -1) 24176262Sgreen options->pubkey_authentication = 1; 24299048Sdes if (options->kerberos_authentication == -1) 243124211Sdes options->kerberos_authentication = 0; 24492559Sdes if (options->kerberos_or_local_passwd == -1) 24592559Sdes options->kerberos_or_local_passwd = 1; 24692559Sdes if (options->kerberos_ticket_cleanup == -1) 24792559Sdes options->kerberos_ticket_cleanup = 1; 248126277Sdes if (options->kerberos_get_afs_token == -1) 249126277Sdes options->kerberos_get_afs_token = 0; 250124211Sdes if (options->gss_authentication == -1) 251124211Sdes options->gss_authentication = 0; 252124211Sdes if (options->gss_cleanup_creds == -1) 253124211Sdes options->gss_cleanup_creds = 1; 25457429Smarkm if (options->password_authentication == -1) 255126009Sdes options->password_authentication = 0; 25669591Sgreen if (options->kbd_interactive_authentication == -1) 25769591Sgreen options->kbd_interactive_authentication = 0; 25892559Sdes if (options->challenge_response_authentication == -1) 25995456Sdes options->challenge_response_authentication = 1; 26057429Smarkm if (options->permit_empty_passwd == -1) 26157565Smarkm options->permit_empty_passwd = 0; 262106130Sdes if (options->permit_user_env == -1) 263106130Sdes options->permit_user_env = 0; 26457429Smarkm if (options->use_login == -1) 26557429Smarkm options->use_login = 0; 26698684Sdes if (options->compression == -1) 267149753Sdes options->compression = COMP_DELAYED; 268255767Sdes if (options->rekey_limit == -1) 269255767Sdes options->rekey_limit = 0; 270255767Sdes if (options->rekey_interval == -1) 271255767Sdes options->rekey_interval = 0; 27269591Sgreen if (options->allow_tcp_forwarding == -1) 273248619Sdes options->allow_tcp_forwarding = FORWARD_ALLOW; 274181111Sdes if (options->allow_agent_forwarding == -1) 275181111Sdes options->allow_agent_forwarding = 1; 27660576Skris if (options->gateway_ports == -1) 27760576Skris options->gateway_ports = 0; 27865674Skris if (options->max_startups == -1) 279248619Sdes options->max_startups = 100; 28065674Skris if (options->max_startups_rate == -1) 281248619Sdes options->max_startups_rate = 30; /* 30% */ 28265674Skris if (options->max_startups_begin == -1) 283248619Sdes options->max_startups_begin = 10; 284137019Sdes if (options->max_authtries == -1) 285137019Sdes options->max_authtries = DEFAULT_AUTH_FAIL_MAX; 286181111Sdes if (options->max_sessions == -1) 287181111Sdes options->max_sessions = DEFAULT_SESSIONS_MAX; 288124211Sdes if (options->use_dns == -1) 289124211Sdes options->use_dns = 1; 29076262Sgreen if (options->client_alive_interval == -1) 29192559Sdes options->client_alive_interval = 0; 29276262Sgreen if (options->client_alive_count_max == -1) 29376262Sgreen options->client_alive_count_max = 3; 294226046Sdes if (options->num_authkeys_files == 0) { 295226046Sdes options->authorized_keys_files[options->num_authkeys_files++] = 296226046Sdes xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); 297226046Sdes options->authorized_keys_files[options->num_authkeys_files++] = 298226046Sdes xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2); 29992559Sdes } 300157019Sdes if (options->permit_tun == -1) 301157019Sdes options->permit_tun = SSH_TUNMODE_NO; 302192595Sdes if (options->zero_knowledge_password_authentication == -1) 303192595Sdes options->zero_knowledge_password_authentication = 0; 304221420Sdes if (options->ip_qos_interactive == -1) 305221420Sdes options->ip_qos_interactive = IPTOS_LOWDELAY; 306221420Sdes if (options->ip_qos_bulk == -1) 307221420Sdes options->ip_qos_bulk = IPTOS_THROUGHPUT; 308240075Sdes if (options->version_addendum == NULL) 309240075Sdes options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 310240075Sdes /* Turn privilege separation on by default */ 311240075Sdes if (use_privsep == -1) 312251088Sdes use_privsep = PRIVSEP_NOSANDBOX; 313240075Sdes 314240075Sdes#ifndef HAVE_MMAP 315240075Sdes if (use_privsep && options->compression == 1) { 316240075Sdes error("This platform does not support both privilege " 317240075Sdes "separation and compression"); 318240075Sdes error("Compression disabled"); 319240075Sdes options->compression = 0; 320240075Sdes } 321240075Sdes#endif 322240075Sdes 323231584Sed if (options->hpn_disabled == -1) 324224638Sbrooks options->hpn_disabled = 0; 325224638Sbrooks if (options->hpn_buffer_size == -1) { 326224638Sbrooks /* 327224638Sbrooks * HPN buffer size option not explicitly set. Try to figure 328224638Sbrooks * out what value to use or resort to default. 329224638Sbrooks */ 330224638Sbrooks options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; 331224638Sbrooks if (!options->hpn_disabled) { 332224638Sbrooks sock_get_rcvbuf(&options->hpn_buffer_size, 0); 333224638Sbrooks debug ("HPN Buffer Size: %d", options->hpn_buffer_size); 334224638Sbrooks } 335224638Sbrooks } else { 336224638Sbrooks /* 337224638Sbrooks * In the case that the user sets both values in a 338224638Sbrooks * contradictory manner hpn_disabled overrrides hpn_buffer_size. 339224638Sbrooks */ 340224638Sbrooks if (options->hpn_disabled <= 0) { 341224638Sbrooks u_int maxlen; 34298684Sdes 343224638Sbrooks maxlen = buffer_get_max_len(); 344224638Sbrooks if (options->hpn_buffer_size == 0) 345224638Sbrooks options->hpn_buffer_size = 1; 346224638Sbrooks /* Limit the maximum buffer to BUFFER_MAX_LEN. */ 347224638Sbrooks if (options->hpn_buffer_size > maxlen / 1024) 348224638Sbrooks options->hpn_buffer_size = maxlen; 349224638Sbrooks else 350224638Sbrooks options->hpn_buffer_size *= 1024; 351240075Sdes } else { 352224638Sbrooks options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; 353240075Sdes } 354224638Sbrooks } 35557429Smarkm} 35657429Smarkm 35757429Smarkm/* Keyword tokens. */ 35857429Smarkmtypedef enum { 35957429Smarkm sBadOption, /* == unknown option */ 36098941Sdes /* Portable-specific options */ 361124211Sdes sUsePAM, 36298941Sdes /* Standard Options */ 36357429Smarkm sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, 36457429Smarkm sPermitRootLogin, sLogFacility, sLogLevel, 365124211Sdes sRhostsRSAAuthentication, sRSAAuthentication, 36692559Sdes sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 367126277Sdes sKerberosGetAFSToken, 368124211Sdes sKerberosTgtPassing, sChallengeResponseAuthentication, 369147005Sdes sPasswordAuthentication, sKbdInteractiveAuthentication, 370147005Sdes sListenAddress, sAddressFamily, 37176262Sgreen sPrintMotd, sPrintLastLog, sIgnoreRhosts, 37292559Sdes sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 373126277Sdes sStrictModes, sEmptyPasswd, sTCPKeepAlive, 374106130Sdes sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, 375255767Sdes sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 37676262Sgreen sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 377137019Sdes sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, 378181111Sdes sMaxStartups, sMaxAuthTries, sMaxSessions, 379124211Sdes sBanner, sUseDNS, sHostbasedAuthentication, 38092559Sdes sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 381226046Sdes sClientAliveCountMax, sAuthorizedKeysFile, 382157019Sdes sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, 383181111Sdes sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 384181111Sdes sUsePrivilegeSeparation, sAllowAgentForwarding, 385204917Sdes sZeroKnowledgePasswordAuthentication, sHostCertificate, 386215116Sdes sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 387240075Sdes sKexAlgorithms, sIPQoS, sVersionAddendum, 388248619Sdes sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 389255767Sdes sAuthenticationMethods, sHostKeyAgent, 390224638Sbrooks sHPNDisabled, sHPNBufferSize, sTcpRcvBufPoll, 391224638Sbrooks#ifdef NONE_CIPHER_ENABLED 392224638Sbrooks sNoneEnabled, 393224638Sbrooks#endif 394124211Sdes sDeprecated, sUnsupported 39557429Smarkm} ServerOpCodes; 39657429Smarkm 397162856Sdes#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ 398162856Sdes#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 399162856Sdes#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 400162856Sdes 40157429Smarkm/* Textual representation of the tokens. */ 40257429Smarkmstatic struct { 40357429Smarkm const char *name; 40457429Smarkm ServerOpCodes opcode; 405162856Sdes u_int flags; 40657429Smarkm} keywords[] = { 40798941Sdes /* Portable-specific options */ 408124211Sdes#ifdef USE_PAM 409162856Sdes { "usepam", sUsePAM, SSHCFG_GLOBAL }, 410124211Sdes#else 411162856Sdes { "usepam", sUnsupported, SSHCFG_GLOBAL }, 41299048Sdes#endif 413162856Sdes { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, 41498941Sdes /* Standard Options */ 415162856Sdes { "port", sPort, SSHCFG_GLOBAL }, 416162856Sdes { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 417162856Sdes { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 418255767Sdes { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, 419162856Sdes { "pidfile", sPidFile, SSHCFG_GLOBAL }, 420162856Sdes { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, 421162856Sdes { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 422162856Sdes { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, 423181111Sdes { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, 424162856Sdes { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 425162856Sdes { "loglevel", sLogLevel, SSHCFG_GLOBAL }, 426162856Sdes { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, 427181111Sdes { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, 428181111Sdes { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, 429215116Sdes { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, 430181111Sdes { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, 431181111Sdes { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 432197679Sdes { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 433124211Sdes#ifdef KRB5 434181111Sdes { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 435162856Sdes { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 436162856Sdes { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 437126277Sdes#ifdef USE_AFS 438162856Sdes { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, 439124211Sdes#else 440162856Sdes { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 441126277Sdes#endif 442126277Sdes#else 443181111Sdes { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, 444162856Sdes { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, 445162856Sdes { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, 446162856Sdes { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 44773400Sassar#endif 448162856Sdes { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, 449162856Sdes { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, 450124211Sdes#ifdef GSSAPI 451181111Sdes { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 452162856Sdes { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 453124211Sdes#else 454181111Sdes { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, 455162856Sdes { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 45657429Smarkm#endif 457181111Sdes { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 458181111Sdes { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 459162856Sdes { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 460162856Sdes { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ 461192595Sdes#ifdef JPAKE 462192595Sdes { "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL }, 463192595Sdes#else 464192595Sdes { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL }, 465192595Sdes#endif 466162856Sdes { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 467162856Sdes { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 468162856Sdes { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, 469162856Sdes { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 470162856Sdes { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 471162856Sdes { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, 472162856Sdes { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 473162856Sdes { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 474162856Sdes { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 475162856Sdes { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 476162856Sdes { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 477162856Sdes { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 478192595Sdes { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, 479162856Sdes { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 480162856Sdes { "uselogin", sUseLogin, SSHCFG_GLOBAL }, 481162856Sdes { "compression", sCompression, SSHCFG_GLOBAL }, 482255767Sdes { "rekeylimit", sRekeyLimit, SSHCFG_ALL }, 483162856Sdes { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, 484162856Sdes { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ 485162856Sdes { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 486181111Sdes { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, 487240075Sdes { "allowusers", sAllowUsers, SSHCFG_ALL }, 488240075Sdes { "denyusers", sDenyUsers, SSHCFG_ALL }, 489240075Sdes { "allowgroups", sAllowGroups, SSHCFG_ALL }, 490240075Sdes { "denygroups", sDenyGroups, SSHCFG_ALL }, 491162856Sdes { "ciphers", sCiphers, SSHCFG_GLOBAL }, 492162856Sdes { "macs", sMacs, SSHCFG_GLOBAL }, 493162856Sdes { "protocol", sProtocol, SSHCFG_GLOBAL }, 494162856Sdes { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 495162856Sdes { "subsystem", sSubsystem, SSHCFG_GLOBAL }, 496162856Sdes { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 497181111Sdes { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, 498181111Sdes { "maxsessions", sMaxSessions, SSHCFG_ALL }, 499181111Sdes { "banner", sBanner, SSHCFG_ALL }, 500162856Sdes { "usedns", sUseDNS, SSHCFG_GLOBAL }, 501162856Sdes { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, 502162856Sdes { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, 503162856Sdes { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 504162856Sdes { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 505215116Sdes { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, 506226046Sdes { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, 507197679Sdes { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, 508240075Sdes { "acceptenv", sAcceptEnv, SSHCFG_ALL }, 509215116Sdes { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 510197679Sdes { "match", sMatch, SSHCFG_ALL }, 511162856Sdes { "permitopen", sPermitOpen, SSHCFG_ALL }, 512162856Sdes { "forcecommand", sForceCommand, SSHCFG_ALL }, 513181111Sdes { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 514204917Sdes { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, 515204917Sdes { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, 516204917Sdes { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, 517215116Sdes { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, 518221420Sdes { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, 519221420Sdes { "ipqos", sIPQoS, SSHCFG_ALL }, 520248619Sdes { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, 521248619Sdes { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 522240075Sdes { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 523248619Sdes { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 524224638Sbrooks { "hpndisabled", sHPNDisabled, SSHCFG_ALL }, 525224638Sbrooks { "hpnbuffersize", sHPNBufferSize, SSHCFG_ALL }, 526224638Sbrooks { "tcprcvbufpoll", sTcpRcvBufPoll, SSHCFG_ALL }, 527224638Sbrooks#ifdef NONE_CIPHER_ENABLED 528224638Sbrooks { "noneenabled", sNoneEnabled, SSHCFG_ALL }, 529224638Sbrooks#endif 530162856Sdes { NULL, sBadOption, 0 } 53157429Smarkm}; 53257429Smarkm 533181111Sdesstatic struct { 534181111Sdes int val; 535181111Sdes char *text; 536181111Sdes} tunmode_desc[] = { 537181111Sdes { SSH_TUNMODE_NO, "no" }, 538181111Sdes { SSH_TUNMODE_POINTOPOINT, "point-to-point" }, 539181111Sdes { SSH_TUNMODE_ETHERNET, "ethernet" }, 540181111Sdes { SSH_TUNMODE_YES, "yes" }, 541181111Sdes { -1, NULL } 542181111Sdes}; 543181111Sdes 54457429Smarkm/* 54576262Sgreen * Returns the number of the token pointed to by cp or sBadOption. 54657429Smarkm */ 54757429Smarkm 54860576Skrisstatic ServerOpCodes 54957429Smarkmparse_token(const char *cp, const char *filename, 550162856Sdes int linenum, u_int *flags) 55157429Smarkm{ 55276262Sgreen u_int i; 55357429Smarkm 55457429Smarkm for (i = 0; keywords[i].name; i++) 555162856Sdes if (strcasecmp(cp, keywords[i].name) == 0) { 556162856Sdes *flags = keywords[i].flags; 55757429Smarkm return keywords[i].opcode; 558162856Sdes } 55957429Smarkm 56076262Sgreen error("%s: line %d: Bad configuration option: %s", 56176262Sgreen filename, linenum, cp); 56257429Smarkm return sBadOption; 56357429Smarkm} 56457429Smarkm 565204917Sdeschar * 566204917Sdesderelativise_path(const char *path) 567204917Sdes{ 568207319Sdes char *expanded, *ret, cwd[MAXPATHLEN]; 569204917Sdes 570204917Sdes expanded = tilde_expand_filename(path, getuid()); 571204917Sdes if (*expanded == '/') 572204917Sdes return expanded; 573207319Sdes if (getcwd(cwd, sizeof(cwd)) == NULL) 574204917Sdes fatal("%s: getcwd: %s", __func__, strerror(errno)); 575204917Sdes xasprintf(&ret, "%s/%s", cwd, expanded); 576255767Sdes free(expanded); 577204917Sdes return ret; 578204917Sdes} 579204917Sdes 58092559Sdesstatic void 581192595Sdesadd_listen_addr(ServerOptions *options, char *addr, int port) 58257429Smarkm{ 583149753Sdes u_int i; 58457429Smarkm 58557429Smarkm if (options->num_ports == 0) 58657429Smarkm options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 587147005Sdes if (options->address_family == -1) 588147005Sdes options->address_family = AF_UNSPEC; 58976262Sgreen if (port == 0) 59076262Sgreen for (i = 0; i < options->num_ports; i++) 59176262Sgreen add_one_listen_addr(options, addr, options->ports[i]); 59276262Sgreen else 59376262Sgreen add_one_listen_addr(options, addr, port); 59457429Smarkm} 59557429Smarkm 59692559Sdesstatic void 597192595Sdesadd_one_listen_addr(ServerOptions *options, char *addr, int port) 59876262Sgreen{ 59976262Sgreen struct addrinfo hints, *ai, *aitop; 60076262Sgreen char strport[NI_MAXSERV]; 60176262Sgreen int gaierr; 60276262Sgreen 60376262Sgreen memset(&hints, 0, sizeof(hints)); 604147005Sdes hints.ai_family = options->address_family; 60576262Sgreen hints.ai_socktype = SOCK_STREAM; 60676262Sgreen hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 607192595Sdes snprintf(strport, sizeof strport, "%d", port); 60876262Sgreen if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 60976262Sgreen fatal("bad addr or host: %s (%s)", 61076262Sgreen addr ? addr : "<NULL>", 611181111Sdes ssh_gai_strerror(gaierr)); 61276262Sgreen for (ai = aitop; ai->ai_next; ai = ai->ai_next) 61376262Sgreen ; 61476262Sgreen ai->ai_next = options->listen_addrs; 61576262Sgreen options->listen_addrs = aitop; 61676262Sgreen} 61776262Sgreen 618240075Sdesstruct connection_info * 619240075Sdesget_connection_info(int populate, int use_dns) 620240075Sdes{ 621240075Sdes static struct connection_info ci; 622240075Sdes 623240075Sdes if (!populate) 624240075Sdes return &ci; 625240075Sdes ci.host = get_canonical_hostname(use_dns); 626240075Sdes ci.address = get_remote_ipaddr(); 627240075Sdes ci.laddress = get_local_ipaddr(packet_get_connection_in()); 628240075Sdes ci.lport = get_local_port(); 629240075Sdes return &ci; 630240075Sdes} 631240075Sdes 632162856Sdes/* 633162856Sdes * The strategy for the Match blocks is that the config file is parsed twice. 634162856Sdes * 635162856Sdes * The first time is at startup. activep is initialized to 1 and the 636162856Sdes * directives in the global context are processed and acted on. Hitting a 637162856Sdes * Match directive unsets activep and the directives inside the block are 638162856Sdes * checked for syntax only. 639162856Sdes * 640162856Sdes * The second time is after a connection has been established but before 641162856Sdes * authentication. activep is initialized to 2 and global config directives 642162856Sdes * are ignored since they have already been processed. If the criteria in a 643162856Sdes * Match block is met, activep is set and the subsequent directives 644162856Sdes * processed and actioned until EOF or another Match block unsets it. Any 645162856Sdes * options set are copied into the main server config. 646162856Sdes * 647162856Sdes * Potential additions/improvements: 648162856Sdes * - Add Match support for pre-kex directives, eg Protocol, Ciphers. 649162856Sdes * 650162856Sdes * - Add a Tag directive (idea from David Leonard) ala pf, eg: 651162856Sdes * Match Address 192.168.0.* 652162856Sdes * Tag trusted 653162856Sdes * Match Group wheel 654162856Sdes * Tag trusted 655162856Sdes * Match Tag trusted 656162856Sdes * AllowTcpForwarding yes 657162856Sdes * GatewayPorts clientspecified 658162856Sdes * [...] 659162856Sdes * 660162856Sdes * - Add a PermittedChannelRequests directive 661162856Sdes * Match Group shell 662162856Sdes * PermittedChannelRequests session,forwarded-tcpip 663162856Sdes */ 664162856Sdes 665162856Sdesstatic int 666162856Sdesmatch_cfg_line_group(const char *grps, int line, const char *user) 667162856Sdes{ 668162856Sdes int result = 0; 669162856Sdes struct passwd *pw; 670162856Sdes 671162856Sdes if (user == NULL) 672162856Sdes goto out; 673162856Sdes 674162856Sdes if ((pw = getpwnam(user)) == NULL) { 675162856Sdes debug("Can't match group at line %d because user %.100s does " 676162856Sdes "not exist", line, user); 677162856Sdes } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 678162856Sdes debug("Can't Match group because user %.100s not in any group " 679162856Sdes "at line %d", user, line); 680181111Sdes } else if (ga_match_pattern_list(grps) != 1) { 681181111Sdes debug("user %.100s does not match group list %.100s at line %d", 682181111Sdes user, grps, line); 683162856Sdes } else { 684181111Sdes debug("user %.100s matched group list %.100s at line %d", user, 685181111Sdes grps, line); 686162856Sdes result = 1; 687162856Sdes } 688162856Sdesout: 689162856Sdes ga_free(); 690162856Sdes return result; 691162856Sdes} 692162856Sdes 693240075Sdes/* 694248619Sdes * All of the attributes on a single Match line are ANDed together, so we need 695248619Sdes * to check every * attribute and set the result to zero if any attribute does 696248619Sdes * not match. 697240075Sdes */ 698162856Sdesstatic int 699240075Sdesmatch_cfg_line(char **condition, int line, struct connection_info *ci) 700162856Sdes{ 701240075Sdes int result = 1, port; 702162856Sdes char *arg, *attrib, *cp = *condition; 703162856Sdes size_t len; 704162856Sdes 705240075Sdes if (ci == NULL) 706162856Sdes debug3("checking syntax for 'Match %s'", cp); 707162856Sdes else 708240075Sdes debug3("checking match for '%s' user %s host %s addr %s " 709240075Sdes "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", 710240075Sdes ci->host ? ci->host : "(null)", 711240075Sdes ci->address ? ci->address : "(null)", 712240075Sdes ci->laddress ? ci->laddress : "(null)", ci->lport); 713162856Sdes 714162856Sdes while ((attrib = strdelim(&cp)) && *attrib != '\0') { 715162856Sdes if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 716162856Sdes error("Missing Match criteria for %s", attrib); 717162856Sdes return -1; 718162856Sdes } 719162856Sdes len = strlen(arg); 720162856Sdes if (strcasecmp(attrib, "user") == 0) { 721240075Sdes if (ci == NULL || ci->user == NULL) { 722162856Sdes result = 0; 723162856Sdes continue; 724162856Sdes } 725240075Sdes if (match_pattern_list(ci->user, arg, len, 0) != 1) 726162856Sdes result = 0; 727162856Sdes else 728162856Sdes debug("user %.100s matched 'User %.100s' at " 729240075Sdes "line %d", ci->user, arg, line); 730162856Sdes } else if (strcasecmp(attrib, "group") == 0) { 731240075Sdes if (ci == NULL || ci->user == NULL) { 732240075Sdes result = 0; 733240075Sdes continue; 734240075Sdes } 735240075Sdes switch (match_cfg_line_group(arg, line, ci->user)) { 736162856Sdes case -1: 737162856Sdes return -1; 738162856Sdes case 0: 739162856Sdes result = 0; 740162856Sdes } 741162856Sdes } else if (strcasecmp(attrib, "host") == 0) { 742240075Sdes if (ci == NULL || ci->host == NULL) { 743162856Sdes result = 0; 744162856Sdes continue; 745162856Sdes } 746240075Sdes if (match_hostname(ci->host, arg, len) != 1) 747162856Sdes result = 0; 748162856Sdes else 749162856Sdes debug("connection from %.100s matched 'Host " 750240075Sdes "%.100s' at line %d", ci->host, arg, line); 751162856Sdes } else if (strcasecmp(attrib, "address") == 0) { 752240075Sdes if (ci == NULL || ci->address == NULL) { 753240075Sdes result = 0; 754240075Sdes continue; 755240075Sdes } 756240075Sdes switch (addr_match_list(ci->address, arg)) { 757181111Sdes case 1: 758181111Sdes debug("connection from %.100s matched 'Address " 759240075Sdes "%.100s' at line %d", ci->address, arg, line); 760181111Sdes break; 761181111Sdes case 0: 762181111Sdes case -1: 763162856Sdes result = 0; 764181111Sdes break; 765181111Sdes case -2: 766181111Sdes return -1; 767162856Sdes } 768240075Sdes } else if (strcasecmp(attrib, "localaddress") == 0){ 769240075Sdes if (ci == NULL || ci->laddress == NULL) { 770240075Sdes result = 0; 771240075Sdes continue; 772240075Sdes } 773240075Sdes switch (addr_match_list(ci->laddress, arg)) { 774240075Sdes case 1: 775240075Sdes debug("connection from %.100s matched " 776240075Sdes "'LocalAddress %.100s' at line %d", 777240075Sdes ci->laddress, arg, line); 778240075Sdes break; 779240075Sdes case 0: 780240075Sdes case -1: 781240075Sdes result = 0; 782240075Sdes break; 783240075Sdes case -2: 784240075Sdes return -1; 785240075Sdes } 786240075Sdes } else if (strcasecmp(attrib, "localport") == 0) { 787240075Sdes if ((port = a2port(arg)) == -1) { 788240075Sdes error("Invalid LocalPort '%s' on Match line", 789240075Sdes arg); 790240075Sdes return -1; 791240075Sdes } 792240075Sdes if (ci == NULL || ci->lport == 0) { 793240075Sdes result = 0; 794240075Sdes continue; 795240075Sdes } 796240075Sdes /* TODO support port lists */ 797240075Sdes if (port == ci->lport) 798240075Sdes debug("connection from %.100s matched " 799240075Sdes "'LocalPort %d' at line %d", 800240075Sdes ci->laddress, port, line); 801240075Sdes else 802240075Sdes result = 0; 803162856Sdes } else { 804162856Sdes error("Unsupported Match attribute %s", attrib); 805162856Sdes return -1; 806162856Sdes } 807162856Sdes } 808240075Sdes if (ci != NULL) 809162856Sdes debug3("match %sfound", result ? "" : "not "); 810162856Sdes *condition = cp; 811162856Sdes return result; 812162856Sdes} 813162856Sdes 814162856Sdes#define WHITESPACE " \t\r\n" 815162856Sdes 816226046Sdes/* Multistate option parsing */ 817226046Sdesstruct multistate { 818226046Sdes char *key; 819226046Sdes int value; 820226046Sdes}; 821226046Sdesstatic const struct multistate multistate_addressfamily[] = { 822226046Sdes { "inet", AF_INET }, 823226046Sdes { "inet6", AF_INET6 }, 824226046Sdes { "any", AF_UNSPEC }, 825226046Sdes { NULL, -1 } 826226046Sdes}; 827226046Sdesstatic const struct multistate multistate_permitrootlogin[] = { 828226046Sdes { "without-password", PERMIT_NO_PASSWD }, 829226046Sdes { "forced-commands-only", PERMIT_FORCED_ONLY }, 830226046Sdes { "yes", PERMIT_YES }, 831226046Sdes { "no", PERMIT_NO }, 832226046Sdes { NULL, -1 } 833226046Sdes}; 834226046Sdesstatic const struct multistate multistate_compression[] = { 835226046Sdes { "delayed", COMP_DELAYED }, 836226046Sdes { "yes", COMP_ZLIB }, 837226046Sdes { "no", COMP_NONE }, 838226046Sdes { NULL, -1 } 839226046Sdes}; 840226046Sdesstatic const struct multistate multistate_gatewayports[] = { 841226046Sdes { "clientspecified", 2 }, 842226046Sdes { "yes", 1 }, 843226046Sdes { "no", 0 }, 844226046Sdes { NULL, -1 } 845226046Sdes}; 846226046Sdesstatic const struct multistate multistate_privsep[] = { 847240075Sdes { "yes", PRIVSEP_NOSANDBOX }, 848240075Sdes { "sandbox", PRIVSEP_ON }, 849240075Sdes { "nosandbox", PRIVSEP_NOSANDBOX }, 850226046Sdes { "no", PRIVSEP_OFF }, 851226046Sdes { NULL, -1 } 852226046Sdes}; 853248619Sdesstatic const struct multistate multistate_tcpfwd[] = { 854248619Sdes { "yes", FORWARD_ALLOW }, 855248619Sdes { "all", FORWARD_ALLOW }, 856248619Sdes { "no", FORWARD_DENY }, 857248619Sdes { "remote", FORWARD_REMOTE }, 858248619Sdes { "local", FORWARD_LOCAL }, 859248619Sdes { NULL, -1 } 860248619Sdes}; 861226046Sdes 86292559Sdesint 86392559Sdesprocess_server_config_line(ServerOptions *options, char *line, 864240075Sdes const char *filename, int linenum, int *activep, 865240075Sdes struct connection_info *connectinfo) 86657429Smarkm{ 86776262Sgreen char *cp, **charptr, *arg, *p; 868255767Sdes int cmdline = 0, *intptr, value, value2, n, port; 869181111Sdes SyslogFacility *log_facility_ptr; 870181111Sdes LogLevel *log_level_ptr; 87157429Smarkm ServerOpCodes opcode; 872162856Sdes u_int i, flags = 0; 873162856Sdes size_t len; 874255767Sdes long long val64; 875226046Sdes const struct multistate *multistate_ptr; 87657429Smarkm 87792559Sdes cp = line; 878162856Sdes if ((arg = strdelim(&cp)) == NULL) 879162856Sdes return 0; 88092559Sdes /* Ignore leading whitespace */ 88192559Sdes if (*arg == '\0') 88265674Skris arg = strdelim(&cp); 88392559Sdes if (!arg || !*arg || *arg == '#') 88492559Sdes return 0; 88592559Sdes intptr = NULL; 88692559Sdes charptr = NULL; 887162856Sdes opcode = parse_token(arg, filename, linenum, &flags); 888162856Sdes 889162856Sdes if (activep == NULL) { /* We are processing a command line directive */ 890162856Sdes cmdline = 1; 891162856Sdes activep = &cmdline; 892162856Sdes } 893162856Sdes if (*activep && opcode != sMatch) 894162856Sdes debug3("%s:%d setting %s %s", filename, linenum, arg, cp); 895162856Sdes if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 896240075Sdes if (connectinfo == NULL) { 897162856Sdes fatal("%s line %d: Directive '%s' is not allowed " 898162856Sdes "within a Match block", filename, linenum, arg); 899162856Sdes } else { /* this is a directive we have already processed */ 900162856Sdes while (arg) 901162856Sdes arg = strdelim(&cp); 902162856Sdes return 0; 903162856Sdes } 904162856Sdes } 905162856Sdes 90692559Sdes switch (opcode) { 90798941Sdes /* Portable-specific options */ 908124211Sdes case sUsePAM: 909124211Sdes intptr = &options->use_pam; 91098941Sdes goto parse_flag; 91198941Sdes 91298941Sdes /* Standard Options */ 91392559Sdes case sBadOption: 91492559Sdes return -1; 91592559Sdes case sPort: 91692559Sdes /* ignore ports from configfile if cmdline specifies ports */ 91792559Sdes if (options->ports_from_cmdline) 91892559Sdes return 0; 91992559Sdes if (options->listen_addrs != NULL) 92092559Sdes fatal("%s line %d: ports must be specified before " 92192559Sdes "ListenAddress.", filename, linenum); 92292559Sdes if (options->num_ports >= MAX_PORTS) 92392559Sdes fatal("%s line %d: too many ports.", 92492559Sdes filename, linenum); 92592559Sdes arg = strdelim(&cp); 92692559Sdes if (!arg || *arg == '\0') 92792559Sdes fatal("%s line %d: missing port number.", 92892559Sdes filename, linenum); 92992559Sdes options->ports[options->num_ports++] = a2port(arg); 930192595Sdes if (options->ports[options->num_ports-1] <= 0) 93192559Sdes fatal("%s line %d: Badly formatted port number.", 93292559Sdes filename, linenum); 93392559Sdes break; 93457429Smarkm 93592559Sdes case sServerKeyBits: 93692559Sdes intptr = &options->server_key_bits; 937181111Sdes parse_int: 93892559Sdes arg = strdelim(&cp); 93992559Sdes if (!arg || *arg == '\0') 94092559Sdes fatal("%s line %d: missing integer value.", 94192559Sdes filename, linenum); 94292559Sdes value = atoi(arg); 943162856Sdes if (*activep && *intptr == -1) 94492559Sdes *intptr = value; 94592559Sdes break; 94657429Smarkm 94792559Sdes case sLoginGraceTime: 94892559Sdes intptr = &options->login_grace_time; 949181111Sdes parse_time: 95092559Sdes arg = strdelim(&cp); 95192559Sdes if (!arg || *arg == '\0') 95292559Sdes fatal("%s line %d: missing time value.", 95392559Sdes filename, linenum); 95492559Sdes if ((value = convtime(arg)) == -1) 95592559Sdes fatal("%s line %d: invalid time value.", 95692559Sdes filename, linenum); 95792559Sdes if (*intptr == -1) 95892559Sdes *intptr = value; 95992559Sdes break; 96057429Smarkm 96192559Sdes case sKeyRegenerationTime: 96292559Sdes intptr = &options->key_regeneration_time; 96392559Sdes goto parse_time; 96457429Smarkm 96592559Sdes case sListenAddress: 96692559Sdes arg = strdelim(&cp); 967147005Sdes if (arg == NULL || *arg == '\0') 968147005Sdes fatal("%s line %d: missing address", 96992559Sdes filename, linenum); 970149753Sdes /* check for bare IPv6 address: no "[]" and 2 or more ":" */ 971149753Sdes if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL 972149753Sdes && strchr(p+1, ':') != NULL) { 973149753Sdes add_listen_addr(options, arg, 0); 974149753Sdes break; 975149753Sdes } 976147005Sdes p = hpdelim(&arg); 977147005Sdes if (p == NULL) 978147005Sdes fatal("%s line %d: bad address:port usage", 979147005Sdes filename, linenum); 980147005Sdes p = cleanhostname(p); 981147005Sdes if (arg == NULL) 982147005Sdes port = 0; 983192595Sdes else if ((port = a2port(arg)) <= 0) 984147005Sdes fatal("%s line %d: bad port number", filename, linenum); 98557429Smarkm 986147005Sdes add_listen_addr(options, p, port); 987147005Sdes 988147005Sdes break; 989147005Sdes 990147005Sdes case sAddressFamily: 991226046Sdes intptr = &options->address_family; 992226046Sdes multistate_ptr = multistate_addressfamily; 993226046Sdes if (options->listen_addrs != NULL) 994226046Sdes fatal("%s line %d: address family must be specified " 995226046Sdes "before ListenAddress.", filename, linenum); 996226046Sdes parse_multistate: 997147005Sdes arg = strdelim(&cp); 998149753Sdes if (!arg || *arg == '\0') 999226046Sdes fatal("%s line %d: missing argument.", 1000149753Sdes filename, linenum); 1001226046Sdes value = -1; 1002226046Sdes for (i = 0; multistate_ptr[i].key != NULL; i++) { 1003226046Sdes if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1004226046Sdes value = multistate_ptr[i].value; 1005226046Sdes break; 1006226046Sdes } 1007226046Sdes } 1008226046Sdes if (value == -1) 1009226046Sdes fatal("%s line %d: unsupported option \"%s\".", 1010147005Sdes filename, linenum, arg); 1011226046Sdes if (*activep && *intptr == -1) 1012147005Sdes *intptr = value; 101392559Sdes break; 101457429Smarkm 101592559Sdes case sHostKeyFile: 101692559Sdes intptr = &options->num_host_key_files; 101792559Sdes if (*intptr >= MAX_HOSTKEYS) 101892559Sdes fatal("%s line %d: too many host keys specified (max %d).", 101992559Sdes filename, linenum, MAX_HOSTKEYS); 102092559Sdes charptr = &options->host_key_files[*intptr]; 1021181111Sdes parse_filename: 102292559Sdes arg = strdelim(&cp); 102392559Sdes if (!arg || *arg == '\0') 102492559Sdes fatal("%s line %d: missing file name.", 102592559Sdes filename, linenum); 1026162856Sdes if (*activep && *charptr == NULL) { 1027204917Sdes *charptr = derelativise_path(arg); 102892559Sdes /* increase optional counter */ 102992559Sdes if (intptr != NULL) 103092559Sdes *intptr = *intptr + 1; 103192559Sdes } 103292559Sdes break; 103360576Skris 1034255767Sdes case sHostKeyAgent: 1035255767Sdes charptr = &options->host_key_agent; 1036255767Sdes arg = strdelim(&cp); 1037255767Sdes if (!arg || *arg == '\0') 1038255767Sdes fatal("%s line %d: missing socket name.", 1039255767Sdes filename, linenum); 1040255767Sdes if (*activep && *charptr == NULL) 1041255767Sdes *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? 1042255767Sdes xstrdup(arg) : derelativise_path(arg); 1043255767Sdes break; 1044255767Sdes 1045204917Sdes case sHostCertificate: 1046204917Sdes intptr = &options->num_host_cert_files; 1047204917Sdes if (*intptr >= MAX_HOSTKEYS) 1048204917Sdes fatal("%s line %d: too many host certificates " 1049204917Sdes "specified (max %d).", filename, linenum, 1050204917Sdes MAX_HOSTCERTS); 1051204917Sdes charptr = &options->host_cert_files[*intptr]; 1052204917Sdes goto parse_filename; 1053204917Sdes break; 1054204917Sdes 105592559Sdes case sPidFile: 105692559Sdes charptr = &options->pid_file; 105792559Sdes goto parse_filename; 105857429Smarkm 105992559Sdes case sPermitRootLogin: 106092559Sdes intptr = &options->permit_root_login; 1061226046Sdes multistate_ptr = multistate_permitrootlogin; 1062226046Sdes goto parse_multistate; 106392559Sdes 106492559Sdes case sIgnoreRhosts: 106592559Sdes intptr = &options->ignore_rhosts; 1066181111Sdes parse_flag: 106792559Sdes arg = strdelim(&cp); 106892559Sdes if (!arg || *arg == '\0') 106992559Sdes fatal("%s line %d: missing yes/no argument.", 107092559Sdes filename, linenum); 107192559Sdes value = 0; /* silence compiler */ 107292559Sdes if (strcmp(arg, "yes") == 0) 107392559Sdes value = 1; 107492559Sdes else if (strcmp(arg, "no") == 0) 107592559Sdes value = 0; 107692559Sdes else 107792559Sdes fatal("%s line %d: Bad yes/no argument: %s", 107892559Sdes filename, linenum, arg); 1079162856Sdes if (*activep && *intptr == -1) 108092559Sdes *intptr = value; 108192559Sdes break; 108257429Smarkm 108392559Sdes case sIgnoreUserKnownHosts: 108492559Sdes intptr = &options->ignore_user_known_hosts; 108592559Sdes goto parse_flag; 108657429Smarkm 108792559Sdes case sRhostsRSAAuthentication: 108892559Sdes intptr = &options->rhosts_rsa_authentication; 108992559Sdes goto parse_flag; 109057429Smarkm 109192559Sdes case sHostbasedAuthentication: 109292559Sdes intptr = &options->hostbased_authentication; 109392559Sdes goto parse_flag; 109476262Sgreen 109592559Sdes case sHostbasedUsesNameFromPacketOnly: 109692559Sdes intptr = &options->hostbased_uses_name_from_packet_only; 109792559Sdes goto parse_flag; 109876262Sgreen 109992559Sdes case sRSAAuthentication: 110092559Sdes intptr = &options->rsa_authentication; 110192559Sdes goto parse_flag; 110257429Smarkm 110392559Sdes case sPubkeyAuthentication: 110492559Sdes intptr = &options->pubkey_authentication; 110592559Sdes goto parse_flag; 1106124211Sdes 110792559Sdes case sKerberosAuthentication: 110892559Sdes intptr = &options->kerberos_authentication; 110992559Sdes goto parse_flag; 111057429Smarkm 111192559Sdes case sKerberosOrLocalPasswd: 111292559Sdes intptr = &options->kerberos_or_local_passwd; 111392559Sdes goto parse_flag; 111492559Sdes 111592559Sdes case sKerberosTicketCleanup: 111692559Sdes intptr = &options->kerberos_ticket_cleanup; 111792559Sdes goto parse_flag; 1118124211Sdes 1119126277Sdes case sKerberosGetAFSToken: 1120126277Sdes intptr = &options->kerberos_get_afs_token; 1121126277Sdes goto parse_flag; 1122126277Sdes 1123124211Sdes case sGssAuthentication: 1124124211Sdes intptr = &options->gss_authentication; 112592559Sdes goto parse_flag; 1126124211Sdes 1127124211Sdes case sGssCleanupCreds: 1128124211Sdes intptr = &options->gss_cleanup_creds; 112992559Sdes goto parse_flag; 113057429Smarkm 113192559Sdes case sPasswordAuthentication: 113292559Sdes intptr = &options->password_authentication; 113392559Sdes goto parse_flag; 113457565Smarkm 1135192595Sdes case sZeroKnowledgePasswordAuthentication: 1136192595Sdes intptr = &options->zero_knowledge_password_authentication; 1137192595Sdes goto parse_flag; 1138192595Sdes 113992559Sdes case sKbdInteractiveAuthentication: 114092559Sdes intptr = &options->kbd_interactive_authentication; 114192559Sdes goto parse_flag; 114257429Smarkm 114392559Sdes case sChallengeResponseAuthentication: 114492559Sdes intptr = &options->challenge_response_authentication; 114592559Sdes goto parse_flag; 114657429Smarkm 114792559Sdes case sPrintMotd: 114892559Sdes intptr = &options->print_motd; 114992559Sdes goto parse_flag; 115057429Smarkm 115192559Sdes case sPrintLastLog: 115292559Sdes intptr = &options->print_lastlog; 115392559Sdes goto parse_flag; 115469591Sgreen 115592559Sdes case sX11Forwarding: 115692559Sdes intptr = &options->x11_forwarding; 115792559Sdes goto parse_flag; 115857429Smarkm 115992559Sdes case sX11DisplayOffset: 116092559Sdes intptr = &options->x11_display_offset; 116192559Sdes goto parse_int; 116257429Smarkm 116392559Sdes case sX11UseLocalhost: 116492559Sdes intptr = &options->x11_use_localhost; 116592559Sdes goto parse_flag; 116657429Smarkm 116792559Sdes case sXAuthLocation: 116892559Sdes charptr = &options->xauth_location; 116992559Sdes goto parse_filename; 117076262Sgreen 117192559Sdes case sStrictModes: 117292559Sdes intptr = &options->strict_modes; 117392559Sdes goto parse_flag; 117457429Smarkm 1175126277Sdes case sTCPKeepAlive: 1176126277Sdes intptr = &options->tcp_keep_alive; 117792559Sdes goto parse_flag; 117857429Smarkm 117992559Sdes case sEmptyPasswd: 118092559Sdes intptr = &options->permit_empty_passwd; 118192559Sdes goto parse_flag; 118276262Sgreen 1183106130Sdes case sPermitUserEnvironment: 1184106130Sdes intptr = &options->permit_user_env; 1185106130Sdes goto parse_flag; 1186106130Sdes 118792559Sdes case sUseLogin: 118892559Sdes intptr = &options->use_login; 118992559Sdes goto parse_flag; 119057429Smarkm 119198684Sdes case sCompression: 119298684Sdes intptr = &options->compression; 1193226046Sdes multistate_ptr = multistate_compression; 1194226046Sdes goto parse_multistate; 119598684Sdes 1196255767Sdes case sRekeyLimit: 1197255767Sdes arg = strdelim(&cp); 1198255767Sdes if (!arg || *arg == '\0') 1199255767Sdes fatal("%.200s line %d: Missing argument.", filename, 1200255767Sdes linenum); 1201255767Sdes if (strcmp(arg, "default") == 0) { 1202255767Sdes val64 = 0; 1203255767Sdes } else { 1204255767Sdes if (scan_scaled(arg, &val64) == -1) 1205255767Sdes fatal("%.200s line %d: Bad number '%s': %s", 1206255767Sdes filename, linenum, arg, strerror(errno)); 1207255767Sdes /* check for too-large or too-small limits */ 1208255767Sdes if (val64 > UINT_MAX) 1209255767Sdes fatal("%.200s line %d: RekeyLimit too large", 1210255767Sdes filename, linenum); 1211255767Sdes if (val64 != 0 && val64 < 16) 1212255767Sdes fatal("%.200s line %d: RekeyLimit too small", 1213255767Sdes filename, linenum); 1214255767Sdes } 1215255767Sdes if (*activep && options->rekey_limit == -1) 1216255767Sdes options->rekey_limit = (u_int32_t)val64; 1217255767Sdes if (cp != NULL) { /* optional rekey interval present */ 1218255767Sdes if (strcmp(cp, "none") == 0) { 1219255767Sdes (void)strdelim(&cp); /* discard */ 1220255767Sdes break; 1221255767Sdes } 1222255767Sdes intptr = &options->rekey_interval; 1223255767Sdes goto parse_time; 1224255767Sdes } 1225255767Sdes break; 1226255767Sdes 122792559Sdes case sGatewayPorts: 122892559Sdes intptr = &options->gateway_ports; 1229226046Sdes multistate_ptr = multistate_gatewayports; 1230226046Sdes goto parse_multistate; 123157429Smarkm 1232124211Sdes case sUseDNS: 1233124211Sdes intptr = &options->use_dns; 123492559Sdes goto parse_flag; 123557429Smarkm 123692559Sdes case sLogFacility: 1237181111Sdes log_facility_ptr = &options->log_facility; 123892559Sdes arg = strdelim(&cp); 123992559Sdes value = log_facility_number(arg); 124092559Sdes if (value == SYSLOG_FACILITY_NOT_SET) 124192559Sdes fatal("%.200s line %d: unsupported log facility '%s'", 124292559Sdes filename, linenum, arg ? arg : "<NONE>"); 1243181111Sdes if (*log_facility_ptr == -1) 1244181111Sdes *log_facility_ptr = (SyslogFacility) value; 124592559Sdes break; 124657429Smarkm 124792559Sdes case sLogLevel: 1248181111Sdes log_level_ptr = &options->log_level; 124992559Sdes arg = strdelim(&cp); 125092559Sdes value = log_level_number(arg); 125192559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 125292559Sdes fatal("%.200s line %d: unsupported log level '%s'", 125392559Sdes filename, linenum, arg ? arg : "<NONE>"); 1254181111Sdes if (*log_level_ptr == -1) 1255181111Sdes *log_level_ptr = (LogLevel) value; 125692559Sdes break; 125760576Skris 125892559Sdes case sAllowTcpForwarding: 125992559Sdes intptr = &options->allow_tcp_forwarding; 1260248619Sdes multistate_ptr = multistate_tcpfwd; 1261248619Sdes goto parse_multistate; 126276262Sgreen 1263181111Sdes case sAllowAgentForwarding: 1264181111Sdes intptr = &options->allow_agent_forwarding; 1265181111Sdes goto parse_flag; 1266181111Sdes 126798684Sdes case sUsePrivilegeSeparation: 126898684Sdes intptr = &use_privsep; 1269226046Sdes multistate_ptr = multistate_privsep; 1270226046Sdes goto parse_multistate; 127198684Sdes 127292559Sdes case sAllowUsers: 127392559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 127492559Sdes if (options->num_allow_users >= MAX_ALLOW_USERS) 127592559Sdes fatal("%s line %d: too many allow users.", 127692559Sdes filename, linenum); 1277240075Sdes if (!*activep) 1278240075Sdes continue; 127999063Sdes options->allow_users[options->num_allow_users++] = 128099063Sdes xstrdup(arg); 128192559Sdes } 128292559Sdes break; 128357429Smarkm 128492559Sdes case sDenyUsers: 128592559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 128692559Sdes if (options->num_deny_users >= MAX_DENY_USERS) 1287162856Sdes fatal("%s line %d: too many deny users.", 128892559Sdes filename, linenum); 1289240075Sdes if (!*activep) 1290240075Sdes continue; 129199063Sdes options->deny_users[options->num_deny_users++] = 129299063Sdes xstrdup(arg); 129392559Sdes } 129492559Sdes break; 129557429Smarkm 129692559Sdes case sAllowGroups: 129792559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 129892559Sdes if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 129992559Sdes fatal("%s line %d: too many allow groups.", 130092559Sdes filename, linenum); 1301240075Sdes if (!*activep) 1302240075Sdes continue; 130399063Sdes options->allow_groups[options->num_allow_groups++] = 130499063Sdes xstrdup(arg); 130592559Sdes } 130692559Sdes break; 130769591Sgreen 130892559Sdes case sDenyGroups: 130992559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 131092559Sdes if (options->num_deny_groups >= MAX_DENY_GROUPS) 131192559Sdes fatal("%s line %d: too many deny groups.", 131292559Sdes filename, linenum); 1313240075Sdes if (!*activep) 1314240075Sdes continue; 1315240075Sdes options->deny_groups[options->num_deny_groups++] = 1316240075Sdes xstrdup(arg); 131792559Sdes } 131892559Sdes break; 131957429Smarkm 132092559Sdes case sCiphers: 132192559Sdes arg = strdelim(&cp); 132292559Sdes if (!arg || *arg == '\0') 132392559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 132492559Sdes if (!ciphers_valid(arg)) 132592559Sdes fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 132692559Sdes filename, linenum, arg ? arg : "<NONE>"); 132792559Sdes if (options->ciphers == NULL) 132892559Sdes options->ciphers = xstrdup(arg); 132992559Sdes break; 133057429Smarkm 133192559Sdes case sMacs: 133292559Sdes arg = strdelim(&cp); 133392559Sdes if (!arg || *arg == '\0') 133492559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 133592559Sdes if (!mac_valid(arg)) 133692559Sdes fatal("%s line %d: Bad SSH2 mac spec '%s'.", 133792559Sdes filename, linenum, arg ? arg : "<NONE>"); 133892559Sdes if (options->macs == NULL) 133992559Sdes options->macs = xstrdup(arg); 134092559Sdes break; 134157429Smarkm 1342221420Sdes case sKexAlgorithms: 1343221420Sdes arg = strdelim(&cp); 1344221420Sdes if (!arg || *arg == '\0') 1345221420Sdes fatal("%s line %d: Missing argument.", 1346221420Sdes filename, linenum); 1347221420Sdes if (!kex_names_valid(arg)) 1348221420Sdes fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", 1349221420Sdes filename, linenum, arg ? arg : "<NONE>"); 1350221420Sdes if (options->kex_algorithms == NULL) 1351221420Sdes options->kex_algorithms = xstrdup(arg); 1352221420Sdes break; 1353221420Sdes 135492559Sdes case sProtocol: 135592559Sdes intptr = &options->protocol; 135692559Sdes arg = strdelim(&cp); 135792559Sdes if (!arg || *arg == '\0') 135892559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 135992559Sdes value = proto_spec(arg); 136092559Sdes if (value == SSH_PROTO_UNKNOWN) 136192559Sdes fatal("%s line %d: Bad protocol spec '%s'.", 136292559Sdes filename, linenum, arg ? arg : "<NONE>"); 136392559Sdes if (*intptr == SSH_PROTO_UNKNOWN) 136492559Sdes *intptr = value; 136592559Sdes break; 136657429Smarkm 136792559Sdes case sSubsystem: 136892559Sdes if (options->num_subsystems >= MAX_SUBSYSTEMS) { 136992559Sdes fatal("%s line %d: too many subsystems defined.", 137092559Sdes filename, linenum); 137192559Sdes } 137292559Sdes arg = strdelim(&cp); 137392559Sdes if (!arg || *arg == '\0') 137492559Sdes fatal("%s line %d: Missing subsystem name.", 137592559Sdes filename, linenum); 1376162856Sdes if (!*activep) { 1377162856Sdes arg = strdelim(&cp); 1378162856Sdes break; 1379162856Sdes } 138092559Sdes for (i = 0; i < options->num_subsystems; i++) 138192559Sdes if (strcmp(arg, options->subsystem_name[i]) == 0) 138292559Sdes fatal("%s line %d: Subsystem '%s' already defined.", 138392559Sdes filename, linenum, arg); 138492559Sdes options->subsystem_name[options->num_subsystems] = xstrdup(arg); 138592559Sdes arg = strdelim(&cp); 138692559Sdes if (!arg || *arg == '\0') 138792559Sdes fatal("%s line %d: Missing subsystem command.", 138892559Sdes filename, linenum); 138992559Sdes options->subsystem_command[options->num_subsystems] = xstrdup(arg); 1390162856Sdes 1391162856Sdes /* Collect arguments (separate to executable) */ 1392162856Sdes p = xstrdup(arg); 1393162856Sdes len = strlen(p) + 1; 1394162856Sdes while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { 1395162856Sdes len += 1 + strlen(arg); 1396162856Sdes p = xrealloc(p, 1, len); 1397162856Sdes strlcat(p, " ", len); 1398162856Sdes strlcat(p, arg, len); 1399162856Sdes } 1400162856Sdes options->subsystem_args[options->num_subsystems] = p; 140192559Sdes options->num_subsystems++; 140292559Sdes break; 140360576Skris 140492559Sdes case sMaxStartups: 140592559Sdes arg = strdelim(&cp); 140692559Sdes if (!arg || *arg == '\0') 140792559Sdes fatal("%s line %d: Missing MaxStartups spec.", 140892559Sdes filename, linenum); 140992559Sdes if ((n = sscanf(arg, "%d:%d:%d", 141092559Sdes &options->max_startups_begin, 141192559Sdes &options->max_startups_rate, 141292559Sdes &options->max_startups)) == 3) { 141392559Sdes if (options->max_startups_begin > 141492559Sdes options->max_startups || 141592559Sdes options->max_startups_rate > 100 || 141692559Sdes options->max_startups_rate < 1) 141792559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 141892559Sdes filename, linenum); 141992559Sdes } else if (n != 1) 142092559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 142192559Sdes filename, linenum); 142292559Sdes else 142392559Sdes options->max_startups = options->max_startups_begin; 142492559Sdes break; 142576262Sgreen 1426137019Sdes case sMaxAuthTries: 1427137019Sdes intptr = &options->max_authtries; 1428137019Sdes goto parse_int; 1429137019Sdes 1430181111Sdes case sMaxSessions: 1431181111Sdes intptr = &options->max_sessions; 1432181111Sdes goto parse_int; 1433181111Sdes 143492559Sdes case sBanner: 143592559Sdes charptr = &options->banner; 143692559Sdes goto parse_filename; 1437181111Sdes 143892559Sdes /* 143992559Sdes * These options can contain %X options expanded at 144092559Sdes * connect time, so that you can specify paths like: 144192559Sdes * 144292559Sdes * AuthorizedKeysFile /etc/ssh_keys/%u 144392559Sdes */ 144492559Sdes case sAuthorizedKeysFile: 1445226046Sdes if (*activep && options->num_authkeys_files == 0) { 1446226046Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1447226046Sdes if (options->num_authkeys_files >= 1448226046Sdes MAX_AUTHKEYS_FILES) 1449226046Sdes fatal("%s line %d: " 1450226046Sdes "too many authorized keys files.", 1451226046Sdes filename, linenum); 1452226046Sdes options->authorized_keys_files[ 1453226046Sdes options->num_authkeys_files++] = 1454226046Sdes tilde_expand_filename(arg, getuid()); 1455226046Sdes } 1456226046Sdes } 1457226046Sdes return 0; 1458226046Sdes 1459215116Sdes case sAuthorizedPrincipalsFile: 1460215116Sdes charptr = &options->authorized_principals_file; 1461207319Sdes arg = strdelim(&cp); 1462207319Sdes if (!arg || *arg == '\0') 1463207319Sdes fatal("%s line %d: missing file name.", 1464207319Sdes filename, linenum); 1465207319Sdes if (*activep && *charptr == NULL) { 1466207319Sdes *charptr = tilde_expand_filename(arg, getuid()); 1467207319Sdes /* increase optional counter */ 1468207319Sdes if (intptr != NULL) 1469207319Sdes *intptr = *intptr + 1; 1470207319Sdes } 1471207319Sdes break; 147260576Skris 147392559Sdes case sClientAliveInterval: 147492559Sdes intptr = &options->client_alive_interval; 147592559Sdes goto parse_time; 147657432Smarkm 147792559Sdes case sClientAliveCountMax: 147892559Sdes intptr = &options->client_alive_count_max; 147992559Sdes goto parse_int; 148065674Skris 1481137019Sdes case sAcceptEnv: 1482137019Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1483137019Sdes if (strchr(arg, '=') != NULL) 1484137019Sdes fatal("%s line %d: Invalid environment name.", 1485137019Sdes filename, linenum); 1486137019Sdes if (options->num_accept_env >= MAX_ACCEPT_ENV) 1487137019Sdes fatal("%s line %d: too many allow env.", 1488137019Sdes filename, linenum); 1489162856Sdes if (!*activep) 1490240075Sdes continue; 1491137019Sdes options->accept_env[options->num_accept_env++] = 1492137019Sdes xstrdup(arg); 1493137019Sdes } 1494137019Sdes break; 1495137019Sdes 1496157019Sdes case sPermitTunnel: 1497157019Sdes intptr = &options->permit_tun; 1498157019Sdes arg = strdelim(&cp); 1499157019Sdes if (!arg || *arg == '\0') 1500157019Sdes fatal("%s line %d: Missing yes/point-to-point/" 1501157019Sdes "ethernet/no argument.", filename, linenum); 1502181111Sdes value = -1; 1503181111Sdes for (i = 0; tunmode_desc[i].val != -1; i++) 1504181111Sdes if (strcmp(tunmode_desc[i].text, arg) == 0) { 1505181111Sdes value = tunmode_desc[i].val; 1506181111Sdes break; 1507181111Sdes } 1508181111Sdes if (value == -1) 1509157019Sdes fatal("%s line %d: Bad yes/point-to-point/ethernet/" 1510157019Sdes "no argument: %s", filename, linenum, arg); 1511157019Sdes if (*intptr == -1) 1512157019Sdes *intptr = value; 1513157019Sdes break; 1514157019Sdes 1515162856Sdes case sMatch: 1516162856Sdes if (cmdline) 1517162856Sdes fatal("Match directive not supported as a command-line " 1518162856Sdes "option"); 1519240075Sdes value = match_cfg_line(&cp, linenum, connectinfo); 1520162856Sdes if (value < 0) 1521162856Sdes fatal("%s line %d: Bad Match condition", filename, 1522162856Sdes linenum); 1523162856Sdes *activep = value; 1524162856Sdes break; 1525162856Sdes 1526162856Sdes case sPermitOpen: 1527162856Sdes arg = strdelim(&cp); 1528162856Sdes if (!arg || *arg == '\0') 1529162856Sdes fatal("%s line %d: missing PermitOpen specification", 1530162856Sdes filename, linenum); 1531181111Sdes n = options->num_permitted_opens; /* modified later */ 1532162856Sdes if (strcmp(arg, "any") == 0) { 1533181111Sdes if (*activep && n == -1) { 1534162856Sdes channel_clear_adm_permitted_opens(); 1535162856Sdes options->num_permitted_opens = 0; 1536162856Sdes } 1537162856Sdes break; 1538162856Sdes } 1539240075Sdes if (strcmp(arg, "none") == 0) { 1540240075Sdes if (*activep && n == -1) { 1541240075Sdes options->num_permitted_opens = 1; 1542240075Sdes channel_disable_adm_local_opens(); 1543240075Sdes } 1544240075Sdes break; 1545240075Sdes } 1546181111Sdes if (*activep && n == -1) 1547181111Sdes channel_clear_adm_permitted_opens(); 1548162856Sdes for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { 1549162856Sdes p = hpdelim(&arg); 1550162856Sdes if (p == NULL) 1551162856Sdes fatal("%s line %d: missing host in PermitOpen", 1552162856Sdes filename, linenum); 1553162856Sdes p = cleanhostname(p); 1554240075Sdes if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 1555162856Sdes fatal("%s line %d: bad port number in " 1556162856Sdes "PermitOpen", filename, linenum); 1557181111Sdes if (*activep && n == -1) 1558162856Sdes options->num_permitted_opens = 1559162856Sdes channel_add_adm_permitted_opens(p, port); 1560162856Sdes } 1561162856Sdes break; 1562162856Sdes 1563162856Sdes case sForceCommand: 1564162856Sdes if (cp == NULL) 1565162856Sdes fatal("%.200s line %d: Missing argument.", filename, 1566162856Sdes linenum); 1567162856Sdes len = strspn(cp, WHITESPACE); 1568162856Sdes if (*activep && options->adm_forced_command == NULL) 1569162856Sdes options->adm_forced_command = xstrdup(cp + len); 1570162856Sdes return 0; 1571162856Sdes 1572181111Sdes case sChrootDirectory: 1573181111Sdes charptr = &options->chroot_directory; 1574181111Sdes 1575181111Sdes arg = strdelim(&cp); 1576181111Sdes if (!arg || *arg == '\0') 1577181111Sdes fatal("%s line %d: missing file name.", 1578181111Sdes filename, linenum); 1579181111Sdes if (*activep && *charptr == NULL) 1580181111Sdes *charptr = xstrdup(arg); 1581181111Sdes break; 1582181111Sdes 1583204917Sdes case sTrustedUserCAKeys: 1584204917Sdes charptr = &options->trusted_user_ca_keys; 1585204917Sdes goto parse_filename; 1586204917Sdes 1587204917Sdes case sRevokedKeys: 1588204917Sdes charptr = &options->revoked_keys_file; 1589204917Sdes goto parse_filename; 1590204917Sdes 1591221420Sdes case sIPQoS: 1592221420Sdes arg = strdelim(&cp); 1593221420Sdes if ((value = parse_ipqos(arg)) == -1) 1594221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1595221420Sdes filename, linenum, arg); 1596221420Sdes arg = strdelim(&cp); 1597221420Sdes if (arg == NULL) 1598221420Sdes value2 = value; 1599221420Sdes else if ((value2 = parse_ipqos(arg)) == -1) 1600221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1601221420Sdes filename, linenum, arg); 1602221420Sdes if (*activep) { 1603221420Sdes options->ip_qos_interactive = value; 1604221420Sdes options->ip_qos_bulk = value2; 1605221420Sdes } 1606221420Sdes break; 1607221420Sdes 160899047Sdes case sVersionAddendum: 1609240075Sdes if (cp == NULL) 1610240075Sdes fatal("%.200s line %d: Missing argument.", filename, 1611240075Sdes linenum); 1612240075Sdes len = strspn(cp, WHITESPACE); 1613240075Sdes if (*activep && options->version_addendum == NULL) { 1614240075Sdes if (strcasecmp(cp + len, "none") == 0) 1615240075Sdes options->version_addendum = xstrdup(""); 1616240075Sdes else if (strchr(cp + len, '\r') != NULL) 1617240075Sdes fatal("%.200s line %d: Invalid argument", 1618240075Sdes filename, linenum); 1619240075Sdes else 1620240075Sdes options->version_addendum = xstrdup(cp + len); 1621240075Sdes } 1622240075Sdes return 0; 162399047Sdes 1624248619Sdes case sAuthorizedKeysCommand: 1625248619Sdes len = strspn(cp, WHITESPACE); 1626248619Sdes if (*activep && options->authorized_keys_command == NULL) { 1627248619Sdes if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) 1628248619Sdes fatal("%.200s line %d: AuthorizedKeysCommand " 1629248619Sdes "must be an absolute path", 1630248619Sdes filename, linenum); 1631248619Sdes options->authorized_keys_command = xstrdup(cp + len); 1632248619Sdes } 1633248619Sdes return 0; 1634248619Sdes 1635248619Sdes case sAuthorizedKeysCommandUser: 1636248619Sdes charptr = &options->authorized_keys_command_user; 1637248619Sdes 1638248619Sdes arg = strdelim(&cp); 1639248619Sdes if (*activep && *charptr == NULL) 1640248619Sdes *charptr = xstrdup(arg); 1641248619Sdes break; 1642248619Sdes 1643248619Sdes case sAuthenticationMethods: 1644248619Sdes if (*activep && options->num_auth_methods == 0) { 1645248619Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 1646248619Sdes if (options->num_auth_methods >= 1647248619Sdes MAX_AUTH_METHODS) 1648248619Sdes fatal("%s line %d: " 1649248619Sdes "too many authentication methods.", 1650248619Sdes filename, linenum); 1651248619Sdes if (auth2_methods_valid(arg, 0) != 0) 1652248619Sdes fatal("%s line %d: invalid " 1653248619Sdes "authentication method list.", 1654248619Sdes filename, linenum); 1655248619Sdes options->auth_methods[ 1656248619Sdes options->num_auth_methods++] = xstrdup(arg); 1657248619Sdes } 1658248619Sdes } 1659248619Sdes return 0; 1660248619Sdes 1661224638Sbrooks case sHPNDisabled: 1662224638Sbrooks intptr = &options->hpn_disabled; 1663224638Sbrooks goto parse_flag; 1664224638Sbrooks 1665224638Sbrooks case sHPNBufferSize: 1666224638Sbrooks intptr = &options->hpn_buffer_size; 1667224638Sbrooks goto parse_int; 1668224638Sbrooks 1669224638Sbrooks case sTcpRcvBufPoll: 1670224638Sbrooks intptr = &options->tcp_rcv_buf_poll; 1671224638Sbrooks goto parse_flag; 1672224638Sbrooks 1673224638Sbrooks#ifdef NONE_CIPHER_ENABLED 1674224638Sbrooks case sNoneEnabled: 1675224638Sbrooks intptr = &options->none_enabled; 1676224638Sbrooks goto parse_flag; 1677224638Sbrooks#endif 1678224638Sbrooks 167992559Sdes case sDeprecated: 1680124211Sdes logit("%s line %d: Deprecated option %s", 168192559Sdes filename, linenum, arg); 168292559Sdes while (arg) 168392559Sdes arg = strdelim(&cp); 168492559Sdes break; 168592559Sdes 1686124211Sdes case sUnsupported: 1687124211Sdes logit("%s line %d: Unsupported option %s", 1688124211Sdes filename, linenum, arg); 1689124211Sdes while (arg) 1690124211Sdes arg = strdelim(&cp); 1691124211Sdes break; 1692124211Sdes 169392559Sdes default: 169492559Sdes fatal("%s line %d: Missing handler for opcode %s (%d)", 169592559Sdes filename, linenum, arg, opcode); 169692559Sdes } 169792559Sdes if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 169892559Sdes fatal("%s line %d: garbage at end of line; \"%.200s\".", 169992559Sdes filename, linenum, arg); 170092559Sdes return 0; 170192559Sdes} 170276227Sgreen 170392559Sdes/* Reads the server configuration file. */ 170492559Sdes 170592559Sdesvoid 1706137019Sdesload_server_config(const char *filename, Buffer *conf) 170792559Sdes{ 1708240075Sdes char line[4096], *cp; 170992559Sdes FILE *f; 1710240075Sdes int lineno = 0; 171192559Sdes 1712137019Sdes debug2("%s: filename %s", __func__, filename); 1713137019Sdes if ((f = fopen(filename, "r")) == NULL) { 171492559Sdes perror(filename); 171592559Sdes exit(1); 171657429Smarkm } 1717137019Sdes buffer_clear(conf); 171892559Sdes while (fgets(line, sizeof(line), f)) { 1719240075Sdes lineno++; 1720240075Sdes if (strlen(line) == sizeof(line) - 1) 1721240075Sdes fatal("%s line %d too long", filename, lineno); 1722137019Sdes /* 1723137019Sdes * Trim out comments and strip whitespace 1724137019Sdes * NB - preserve newlines, they are needed to reproduce 1725137019Sdes * line numbers later for error messages 1726137019Sdes */ 1727137019Sdes if ((cp = strchr(line, '#')) != NULL) 1728137019Sdes memcpy(cp, "\n", 2); 1729137019Sdes cp = line + strspn(line, " \t\r"); 1730137019Sdes 1731137019Sdes buffer_append(conf, cp, strlen(cp)); 1732137019Sdes } 1733137019Sdes buffer_append(conf, "\0", 1); 1734137019Sdes fclose(f); 1735137019Sdes debug2("%s: done config len = %d", __func__, buffer_len(conf)); 1736137019Sdes} 1737137019Sdes 1738137019Sdesvoid 1739240075Sdesparse_server_match_config(ServerOptions *options, 1740240075Sdes struct connection_info *connectinfo) 1741137019Sdes{ 1742162856Sdes ServerOptions mo; 1743162856Sdes 1744162856Sdes initialize_server_options(&mo); 1745240075Sdes parse_server_config(&mo, "reprocess config", &cfg, connectinfo); 1746181111Sdes copy_set_server_options(options, &mo, 0); 1747162856Sdes} 1748162856Sdes 1749240075Sdesint parse_server_match_testspec(struct connection_info *ci, char *spec) 1750240075Sdes{ 1751240075Sdes char *p; 1752240075Sdes 1753240075Sdes while ((p = strsep(&spec, ",")) && *p != '\0') { 1754240075Sdes if (strncmp(p, "addr=", 5) == 0) { 1755240075Sdes ci->address = xstrdup(p + 5); 1756240075Sdes } else if (strncmp(p, "host=", 5) == 0) { 1757240075Sdes ci->host = xstrdup(p + 5); 1758240075Sdes } else if (strncmp(p, "user=", 5) == 0) { 1759240075Sdes ci->user = xstrdup(p + 5); 1760240075Sdes } else if (strncmp(p, "laddr=", 6) == 0) { 1761240075Sdes ci->laddress = xstrdup(p + 6); 1762240075Sdes } else if (strncmp(p, "lport=", 6) == 0) { 1763240075Sdes ci->lport = a2port(p + 6); 1764240075Sdes if (ci->lport == -1) { 1765240075Sdes fprintf(stderr, "Invalid port '%s' in test mode" 1766240075Sdes " specification %s\n", p+6, p); 1767240075Sdes return -1; 1768240075Sdes } 1769240075Sdes } else { 1770240075Sdes fprintf(stderr, "Invalid test mode specification %s\n", 1771240075Sdes p); 1772240075Sdes return -1; 1773240075Sdes } 1774240075Sdes } 1775240075Sdes return 0; 1776240075Sdes} 1777240075Sdes 1778240075Sdes/* 1779240075Sdes * returns 1 for a complete spec, 0 for partial spec and -1 for an 1780240075Sdes * empty spec. 1781240075Sdes */ 1782240075Sdesint server_match_spec_complete(struct connection_info *ci) 1783240075Sdes{ 1784240075Sdes if (ci->user && ci->host && ci->address) 1785240075Sdes return 1; /* complete */ 1786240075Sdes if (!ci->user && !ci->host && !ci->address) 1787240075Sdes return -1; /* empty */ 1788240075Sdes return 0; /* partial */ 1789240075Sdes} 1790240075Sdes 1791181111Sdes/* Helper macros */ 1792181111Sdes#define M_CP_INTOPT(n) do {\ 1793181111Sdes if (src->n != -1) \ 1794181111Sdes dst->n = src->n; \ 1795181111Sdes} while (0) 1796181111Sdes#define M_CP_STROPT(n) do {\ 1797181111Sdes if (src->n != NULL) { \ 1798255767Sdes free(dst->n); \ 1799181111Sdes dst->n = src->n; \ 1800181111Sdes } \ 1801181111Sdes} while(0) 1802226046Sdes#define M_CP_STRARRAYOPT(n, num_n) do {\ 1803226046Sdes if (src->num_n != 0) { \ 1804226046Sdes for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \ 1805226046Sdes dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ 1806226046Sdes } \ 1807226046Sdes} while(0) 1808181111Sdes 1809181111Sdes/* 1810181111Sdes * Copy any supported values that are set. 1811181111Sdes * 1812197679Sdes * If the preauth flag is set, we do not bother copying the string or 1813181111Sdes * array values that are not used pre-authentication, because any that we 1814181111Sdes * do use must be explictly sent in mm_getpwnamallow(). 1815181111Sdes */ 1816162856Sdesvoid 1817181111Sdescopy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) 1818162856Sdes{ 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); 1827192595Sdes M_CP_INTOPT(zero_knowledge_password_authentication); 1828248619Sdes M_CP_STROPT(authorized_keys_command); 1829248619Sdes M_CP_STROPT(authorized_keys_command_user); 1830181111Sdes M_CP_INTOPT(permit_root_login); 1831192595Sdes M_CP_INTOPT(permit_empty_passwd); 1832181111Sdes 1833181111Sdes M_CP_INTOPT(allow_tcp_forwarding); 1834181111Sdes M_CP_INTOPT(allow_agent_forwarding); 1835215116Sdes M_CP_INTOPT(permit_tun); 1836181111Sdes M_CP_INTOPT(gateway_ports); 1837181111Sdes M_CP_INTOPT(x11_display_offset); 1838181111Sdes M_CP_INTOPT(x11_forwarding); 1839181111Sdes M_CP_INTOPT(x11_use_localhost); 1840181111Sdes M_CP_INTOPT(max_sessions); 1841181111Sdes M_CP_INTOPT(max_authtries); 1842221420Sdes M_CP_INTOPT(ip_qos_interactive); 1843221420Sdes M_CP_INTOPT(ip_qos_bulk); 1844255767Sdes M_CP_INTOPT(rekey_limit); 1845255767Sdes M_CP_INTOPT(rekey_interval); 1846181111Sdes 1847226046Sdes /* See comment in servconf.h */ 1848226046Sdes COPY_MATCH_STRING_OPTS(); 1849226046Sdes 1850226046Sdes /* 1851226046Sdes * The only things that should be below this point are string options 1852226046Sdes * which are only used after authentication. 1853226046Sdes */ 1854181111Sdes if (preauth) 1855181111Sdes return; 1856226046Sdes 1857181111Sdes M_CP_STROPT(adm_forced_command); 1858181111Sdes M_CP_STROPT(chroot_directory); 1859162856Sdes} 1860162856Sdes 1861181111Sdes#undef M_CP_INTOPT 1862181111Sdes#undef M_CP_STROPT 1863226046Sdes#undef M_CP_STRARRAYOPT 1864181111Sdes 1865162856Sdesvoid 1866162856Sdesparse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1867240075Sdes struct connection_info *connectinfo) 1868162856Sdes{ 1869162856Sdes int active, linenum, bad_options = 0; 1870137019Sdes char *cp, *obuf, *cbuf; 1871137019Sdes 1872137019Sdes debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); 1873137019Sdes 1874137019Sdes obuf = cbuf = xstrdup(buffer_ptr(conf)); 1875240075Sdes active = connectinfo ? 0 : 1; 1876137019Sdes linenum = 1; 1877147005Sdes while ((cp = strsep(&cbuf, "\n")) != NULL) { 1878137019Sdes if (process_server_config_line(options, cp, filename, 1879240075Sdes linenum++, &active, connectinfo) != 0) 188092559Sdes bad_options++; 188192559Sdes } 1882255767Sdes free(obuf); 188376262Sgreen if (bad_options > 0) 188492559Sdes fatal("%s: terminating, %d bad configuration options", 188576262Sgreen filename, bad_options); 188657429Smarkm} 1887181111Sdes 1888181111Sdesstatic const char * 1889226046Sdesfmt_multistate_int(int val, const struct multistate *m) 1890226046Sdes{ 1891226046Sdes u_int i; 1892226046Sdes 1893226046Sdes for (i = 0; m[i].key != NULL; i++) { 1894226046Sdes if (m[i].value == val) 1895226046Sdes return m[i].key; 1896226046Sdes } 1897226046Sdes return "UNKNOWN"; 1898226046Sdes} 1899226046Sdes 1900226046Sdesstatic const char * 1901181111Sdesfmt_intarg(ServerOpCodes code, int val) 1902181111Sdes{ 1903226046Sdes if (val == -1) 1904226046Sdes return "unset"; 1905226046Sdes switch (code) { 1906226046Sdes case sAddressFamily: 1907226046Sdes return fmt_multistate_int(val, multistate_addressfamily); 1908226046Sdes case sPermitRootLogin: 1909226046Sdes return fmt_multistate_int(val, multistate_permitrootlogin); 1910226046Sdes case sGatewayPorts: 1911226046Sdes return fmt_multistate_int(val, multistate_gatewayports); 1912226046Sdes case sCompression: 1913226046Sdes return fmt_multistate_int(val, multistate_compression); 1914226046Sdes case sUsePrivilegeSeparation: 1915226046Sdes return fmt_multistate_int(val, multistate_privsep); 1916248619Sdes case sAllowTcpForwarding: 1917248619Sdes return fmt_multistate_int(val, multistate_tcpfwd); 1918226046Sdes case sProtocol: 1919181111Sdes switch (val) { 1920181111Sdes case SSH_PROTO_1: 1921181111Sdes return "1"; 1922181111Sdes case SSH_PROTO_2: 1923181111Sdes return "2"; 1924181111Sdes case (SSH_PROTO_1|SSH_PROTO_2): 1925181111Sdes return "2,1"; 1926181111Sdes default: 1927181111Sdes return "UNKNOWN"; 1928181111Sdes } 1929226046Sdes default: 1930226046Sdes switch (val) { 1931226046Sdes case 0: 1932226046Sdes return "no"; 1933226046Sdes case 1: 1934226046Sdes return "yes"; 1935226046Sdes default: 1936226046Sdes return "UNKNOWN"; 1937226046Sdes } 1938181111Sdes } 1939181111Sdes} 1940181111Sdes 1941181111Sdesstatic const char * 1942181111Sdeslookup_opcode_name(ServerOpCodes code) 1943181111Sdes{ 1944181111Sdes u_int i; 1945181111Sdes 1946181111Sdes for (i = 0; keywords[i].name != NULL; i++) 1947181111Sdes if (keywords[i].opcode == code) 1948181111Sdes return(keywords[i].name); 1949181111Sdes return "UNKNOWN"; 1950181111Sdes} 1951181111Sdes 1952181111Sdesstatic void 1953181111Sdesdump_cfg_int(ServerOpCodes code, int val) 1954181111Sdes{ 1955181111Sdes printf("%s %d\n", lookup_opcode_name(code), val); 1956181111Sdes} 1957181111Sdes 1958181111Sdesstatic void 1959181111Sdesdump_cfg_fmtint(ServerOpCodes code, int val) 1960181111Sdes{ 1961181111Sdes printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 1962181111Sdes} 1963181111Sdes 1964181111Sdesstatic void 1965181111Sdesdump_cfg_string(ServerOpCodes code, const char *val) 1966181111Sdes{ 1967181111Sdes if (val == NULL) 1968181111Sdes return; 1969181111Sdes printf("%s %s\n", lookup_opcode_name(code), val); 1970181111Sdes} 1971181111Sdes 1972181111Sdesstatic void 1973181111Sdesdump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) 1974181111Sdes{ 1975181111Sdes u_int i; 1976181111Sdes 1977181111Sdes for (i = 0; i < count; i++) 1978226046Sdes printf("%s %s\n", lookup_opcode_name(code), vals[i]); 1979181111Sdes} 1980181111Sdes 1981226046Sdesstatic void 1982226046Sdesdump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) 1983226046Sdes{ 1984226046Sdes u_int i; 1985226046Sdes 1986226046Sdes printf("%s", lookup_opcode_name(code)); 1987226046Sdes for (i = 0; i < count; i++) 1988226046Sdes printf(" %s", vals[i]); 1989226046Sdes printf("\n"); 1990226046Sdes} 1991226046Sdes 1992181111Sdesvoid 1993181111Sdesdump_config(ServerOptions *o) 1994181111Sdes{ 1995181111Sdes u_int i; 1996181111Sdes int ret; 1997181111Sdes struct addrinfo *ai; 1998181111Sdes char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL; 1999181111Sdes 2000181111Sdes /* these are usually at the top of the config */ 2001181111Sdes for (i = 0; i < o->num_ports; i++) 2002181111Sdes printf("port %d\n", o->ports[i]); 2003181111Sdes dump_cfg_fmtint(sProtocol, o->protocol); 2004181111Sdes dump_cfg_fmtint(sAddressFamily, o->address_family); 2005181111Sdes 2006181111Sdes /* ListenAddress must be after Port */ 2007181111Sdes for (ai = o->listen_addrs; ai; ai = ai->ai_next) { 2008181111Sdes if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, 2009181111Sdes sizeof(addr), port, sizeof(port), 2010181111Sdes NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { 2011181111Sdes error("getnameinfo failed: %.100s", 2012181111Sdes (ret != EAI_SYSTEM) ? gai_strerror(ret) : 2013181111Sdes strerror(errno)); 2014181111Sdes } else { 2015181111Sdes if (ai->ai_family == AF_INET6) 2016181111Sdes printf("listenaddress [%s]:%s\n", addr, port); 2017181111Sdes else 2018181111Sdes printf("listenaddress %s:%s\n", addr, port); 2019181111Sdes } 2020181111Sdes } 2021181111Sdes 2022181111Sdes /* integer arguments */ 2023192595Sdes#ifdef USE_PAM 2024192595Sdes dump_cfg_int(sUsePAM, o->use_pam); 2025192595Sdes#endif 2026181111Sdes dump_cfg_int(sServerKeyBits, o->server_key_bits); 2027181111Sdes dump_cfg_int(sLoginGraceTime, o->login_grace_time); 2028181111Sdes dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time); 2029181111Sdes dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); 2030181111Sdes dump_cfg_int(sMaxAuthTries, o->max_authtries); 2031192595Sdes dump_cfg_int(sMaxSessions, o->max_sessions); 2032181111Sdes dump_cfg_int(sClientAliveInterval, o->client_alive_interval); 2033181111Sdes dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); 2034181111Sdes 2035181111Sdes /* formatted integer arguments */ 2036181111Sdes dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); 2037181111Sdes dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); 2038181111Sdes dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); 2039181111Sdes dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication); 2040181111Sdes dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); 2041181111Sdes dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, 2042181111Sdes o->hostbased_uses_name_from_packet_only); 2043181111Sdes dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication); 2044181111Sdes dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); 2045192595Sdes#ifdef KRB5 2046181111Sdes dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); 2047181111Sdes dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); 2048181111Sdes dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); 2049192595Sdes# ifdef USE_AFS 2050181111Sdes dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); 2051192595Sdes# endif 2052192595Sdes#endif 2053192595Sdes#ifdef GSSAPI 2054181111Sdes dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 2055181111Sdes dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 2056192595Sdes#endif 2057192595Sdes#ifdef JPAKE 2058192595Sdes dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, 2059192595Sdes o->zero_knowledge_password_authentication); 2060192595Sdes#endif 2061181111Sdes dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 2062181111Sdes dump_cfg_fmtint(sKbdInteractiveAuthentication, 2063181111Sdes o->kbd_interactive_authentication); 2064181111Sdes dump_cfg_fmtint(sChallengeResponseAuthentication, 2065181111Sdes o->challenge_response_authentication); 2066181111Sdes dump_cfg_fmtint(sPrintMotd, o->print_motd); 2067181111Sdes dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); 2068181111Sdes dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); 2069181111Sdes dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); 2070181111Sdes dump_cfg_fmtint(sStrictModes, o->strict_modes); 2071181111Sdes dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); 2072181111Sdes dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); 2073181111Sdes dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 2074181111Sdes dump_cfg_fmtint(sUseLogin, o->use_login); 2075181111Sdes dump_cfg_fmtint(sCompression, o->compression); 2076181111Sdes dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); 2077181111Sdes dump_cfg_fmtint(sUseDNS, o->use_dns); 2078181111Sdes dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 2079181111Sdes dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); 2080181111Sdes 2081181111Sdes /* string arguments */ 2082181111Sdes dump_cfg_string(sPidFile, o->pid_file); 2083181111Sdes dump_cfg_string(sXAuthLocation, o->xauth_location); 2084181111Sdes dump_cfg_string(sCiphers, o->ciphers); 2085181111Sdes dump_cfg_string(sMacs, o->macs); 2086181111Sdes dump_cfg_string(sBanner, o->banner); 2087181111Sdes dump_cfg_string(sForceCommand, o->adm_forced_command); 2088204917Sdes dump_cfg_string(sChrootDirectory, o->chroot_directory); 2089204917Sdes dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); 2090204917Sdes dump_cfg_string(sRevokedKeys, o->revoked_keys_file); 2091215116Sdes dump_cfg_string(sAuthorizedPrincipalsFile, 2092215116Sdes o->authorized_principals_file); 2093240075Sdes dump_cfg_string(sVersionAddendum, o->version_addendum); 2094248619Sdes dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); 2095248619Sdes dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); 2096255767Sdes dump_cfg_string(sHostKeyAgent, o->host_key_agent); 2097181111Sdes 2098181111Sdes /* string arguments requiring a lookup */ 2099181111Sdes dump_cfg_string(sLogLevel, log_level_name(o->log_level)); 2100181111Sdes dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); 2101181111Sdes 2102181111Sdes /* string array arguments */ 2103226046Sdes dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, 2104226046Sdes o->authorized_keys_files); 2105181111Sdes dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, 2106181111Sdes o->host_key_files); 2107204917Sdes dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files, 2108204917Sdes o->host_cert_files); 2109181111Sdes dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); 2110181111Sdes dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); 2111181111Sdes dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); 2112181111Sdes dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); 2113181111Sdes dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); 2114248619Sdes dump_cfg_strarray_oneline(sAuthenticationMethods, 2115248619Sdes o->num_auth_methods, o->auth_methods); 2116181111Sdes 2117181111Sdes /* other arguments */ 2118181111Sdes for (i = 0; i < o->num_subsystems; i++) 2119181111Sdes printf("subsystem %s %s\n", o->subsystem_name[i], 2120181111Sdes o->subsystem_args[i]); 2121181111Sdes 2122181111Sdes printf("maxstartups %d:%d:%d\n", o->max_startups_begin, 2123181111Sdes o->max_startups_rate, o->max_startups); 2124181111Sdes 2125181111Sdes for (i = 0; tunmode_desc[i].val != -1; i++) 2126181111Sdes if (tunmode_desc[i].val == o->permit_tun) { 2127181111Sdes s = tunmode_desc[i].text; 2128181111Sdes break; 2129181111Sdes } 2130181111Sdes dump_cfg_string(sPermitTunnel, s); 2131181111Sdes 2132226046Sdes printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2133226046Sdes printf("%s\n", iptos2str(o->ip_qos_bulk)); 2134221420Sdes 2135255767Sdes printf("rekeylimit %lld %d\n", (long long)o->rekey_limit, 2136255767Sdes o->rekey_interval); 2137255767Sdes 2138181111Sdes channel_print_adm_permitted_opens(); 2139181111Sdes} 2140