servconf.c revision 99063
157429Smarkm/* 257429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 357429Smarkm * All rights reserved 460576Skris * 565674Skris * As far as I am concerned, the code I have written for this software 665674Skris * can be used freely for any purpose. Any derived versions of this 765674Skris * software must be clearly marked as such, and if the derived work is 865674Skris * incompatible with the protocol description in the RFC file, it must be 965674Skris * called by a name other than "ssh" or "Secure Shell". 1057429Smarkm */ 1157429Smarkm 1257429Smarkm#include "includes.h" 1399063SdesRCSID("$OpenBSD: servconf.c,v 1.112 2002/06/23 09:46:51 deraadt Exp $"); 1499048SdesRCSID("$FreeBSD: head/crypto/openssh/servconf.c 99063 2002-06-29 11:48:59Z des $"); 1557429Smarkm 1692708Sdes#if defined(KRB4) 1776262Sgreen#include <krb.h> 1876262Sgreen#endif 1992708Sdes#if defined(KRB5) 2098941Sdes#ifdef HEIMDAL 2199048Sdes#include <krb5.h> 2298941Sdes#else 2398941Sdes/* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V 2498941Sdes * keytab */ 2598941Sdes#define KEYFILE "/etc/krb5.keytab" 2692708Sdes#endif 2798941Sdes#endif 2876262Sgreen#ifdef AFS 2976262Sgreen#include <kafs.h> 3076262Sgreen#endif 3176262Sgreen 3257429Smarkm#include "ssh.h" 3376262Sgreen#include "log.h" 3457429Smarkm#include "servconf.h" 3557429Smarkm#include "xmalloc.h" 3660576Skris#include "compat.h" 3776262Sgreen#include "pathnames.h" 3876262Sgreen#include "tildexpand.h" 3976262Sgreen#include "misc.h" 4076262Sgreen#include "cipher.h" 4176262Sgreen#include "kex.h" 4276262Sgreen#include "mac.h" 4357429Smarkm 4492559Sdesstatic void add_listen_addr(ServerOptions *, char *, u_short); 4592559Sdesstatic void add_one_listen_addr(ServerOptions *, char *, u_short); 4657429Smarkm 4776262Sgreen/* AF_UNSPEC or AF_INET or AF_INET6 */ 4876262Sgreenextern int IPv4or6; 4998684Sdes/* Use of privilege separation or not */ 5098684Sdesextern int use_privsep; 5176262Sgreen 5257429Smarkm/* Initializes the server options to their default values. */ 5357429Smarkm 5460576Skrisvoid 5557429Smarkminitialize_server_options(ServerOptions *options) 5657429Smarkm{ 5757429Smarkm memset(options, 0, sizeof(*options)); 5898941Sdes 5998941Sdes /* Portable-specific options */ 6098941Sdes options->pam_authentication_via_kbd_int = -1; 6198941Sdes 6298941Sdes /* Standard Options */ 6357429Smarkm options->num_ports = 0; 6457429Smarkm options->ports_from_cmdline = 0; 6557429Smarkm options->listen_addrs = NULL; 6676262Sgreen options->num_host_key_files = 0; 6760576Skris options->pid_file = NULL; 6857429Smarkm options->server_key_bits = -1; 6957429Smarkm options->login_grace_time = -1; 7057429Smarkm options->key_regeneration_time = -1; 7176262Sgreen options->permit_root_login = PERMIT_NOT_SET; 7257429Smarkm options->ignore_rhosts = -1; 7357429Smarkm options->ignore_user_known_hosts = -1; 7457429Smarkm options->print_motd = -1; 7576262Sgreen options->print_lastlog = -1; 7657429Smarkm options->x11_forwarding = -1; 7757429Smarkm options->x11_display_offset = -1; 7892559Sdes options->x11_use_localhost = -1; 7965674Skris options->xauth_location = NULL; 8057429Smarkm options->strict_modes = -1; 8157429Smarkm options->keepalives = -1; 8292559Sdes options->log_facility = SYSLOG_FACILITY_NOT_SET; 8392559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 8457429Smarkm options->rhosts_authentication = -1; 8557429Smarkm options->rhosts_rsa_authentication = -1; 8676262Sgreen options->hostbased_authentication = -1; 8776262Sgreen options->hostbased_uses_name_from_packet_only = -1; 8857429Smarkm options->rsa_authentication = -1; 8976262Sgreen options->pubkey_authentication = -1; 9073400Sassar#if defined(KRB4) || defined(KRB5) 9173400Sassar options->kerberos_authentication = -1; 9292559Sdes options->kerberos_or_local_passwd = -1; 9392559Sdes options->kerberos_ticket_cleanup = -1; 9473400Sassar#endif 9592559Sdes#if defined(AFS) || defined(KRB5) 9692559Sdes options->kerberos_tgt_passing = -1; 9757429Smarkm#endif 9857429Smarkm#ifdef AFS 9957429Smarkm options->afs_token_passing = -1; 10057429Smarkm#endif 10157429Smarkm options->password_authentication = -1; 10269591Sgreen options->kbd_interactive_authentication = -1; 10392559Sdes options->challenge_response_authentication = -1; 10457429Smarkm options->permit_empty_passwd = -1; 10557429Smarkm options->use_login = -1; 10698684Sdes options->compression = -1; 10769591Sgreen options->allow_tcp_forwarding = -1; 10857429Smarkm options->num_allow_users = 0; 10957429Smarkm options->num_deny_users = 0; 11057429Smarkm options->num_allow_groups = 0; 11157429Smarkm options->num_deny_groups = 0; 11260576Skris options->ciphers = NULL; 11376262Sgreen options->macs = NULL; 11460576Skris options->protocol = SSH_PROTO_UNKNOWN; 11560576Skris options->gateway_ports = -1; 11665674Skris options->num_subsystems = 0; 11765674Skris options->max_startups_begin = -1; 11865674Skris options->max_startups_rate = -1; 11965674Skris options->max_startups = -1; 12076262Sgreen options->banner = NULL; 12192559Sdes options->verify_reverse_mapping = -1; 12276262Sgreen options->client_alive_interval = -1; 12376262Sgreen options->client_alive_count_max = -1; 12492559Sdes options->authorized_keys_file = NULL; 12592559Sdes options->authorized_keys_file2 = NULL; 12698684Sdes 12798684Sdes /* Needs to be accessable in many places */ 12898684Sdes use_privsep = -1; 12957429Smarkm} 13057429Smarkm 13160576Skrisvoid 13257429Smarkmfill_default_server_options(ServerOptions *options) 13357429Smarkm{ 13498941Sdes /* Portable-specific options */ 13598941Sdes if (options->pam_authentication_via_kbd_int == -1) 13698941Sdes options->pam_authentication_via_kbd_int = 0; 13798941Sdes 13898941Sdes /* Standard Options */ 13976262Sgreen if (options->protocol == SSH_PROTO_UNKNOWN) 14076262Sgreen options->protocol = SSH_PROTO_1|SSH_PROTO_2; 14176262Sgreen if (options->num_host_key_files == 0) { 14276262Sgreen /* fill default hostkeys for protocols */ 14376262Sgreen if (options->protocol & SSH_PROTO_1) 14492559Sdes options->host_key_files[options->num_host_key_files++] = 14592559Sdes _PATH_HOST_KEY_FILE; 14692559Sdes if (options->protocol & SSH_PROTO_2) { 14792559Sdes options->host_key_files[options->num_host_key_files++] = 14892559Sdes _PATH_HOST_DSA_KEY_FILE; 14992559Sdes } 15076262Sgreen } 15157429Smarkm if (options->num_ports == 0) 15257429Smarkm options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 15357429Smarkm if (options->listen_addrs == NULL) 15476262Sgreen add_listen_addr(options, NULL, 0); 15560576Skris if (options->pid_file == NULL) 15676262Sgreen options->pid_file = _PATH_SSH_DAEMON_PID_FILE; 15757429Smarkm if (options->server_key_bits == -1) 15857429Smarkm options->server_key_bits = 768; 15957429Smarkm if (options->login_grace_time == -1) 16099048Sdes options->login_grace_time = 120; 16157429Smarkm if (options->key_regeneration_time == -1) 16257429Smarkm options->key_regeneration_time = 3600; 16376262Sgreen if (options->permit_root_login == PERMIT_NOT_SET) 16499048Sdes options->permit_root_login = PERMIT_NO; 16557429Smarkm if (options->ignore_rhosts == -1) 16657565Smarkm options->ignore_rhosts = 1; 16757429Smarkm if (options->ignore_user_known_hosts == -1) 16857429Smarkm options->ignore_user_known_hosts = 0; 16957429Smarkm if (options->print_motd == -1) 17057429Smarkm options->print_motd = 1; 17176262Sgreen if (options->print_lastlog == -1) 17276262Sgreen options->print_lastlog = 1; 17357429Smarkm if (options->x11_forwarding == -1) 17499048Sdes options->x11_forwarding = 1; 17557429Smarkm if (options->x11_display_offset == -1) 17657565Smarkm options->x11_display_offset = 10; 17792559Sdes if (options->x11_use_localhost == -1) 17892559Sdes options->x11_use_localhost = 1; 17965674Skris if (options->xauth_location == NULL) 18092559Sdes options->xauth_location = _PATH_XAUTH; 18157429Smarkm if (options->strict_modes == -1) 18257429Smarkm options->strict_modes = 1; 18357429Smarkm if (options->keepalives == -1) 18457429Smarkm options->keepalives = 1; 18592559Sdes if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 18657429Smarkm options->log_facility = SYSLOG_FACILITY_AUTH; 18792559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 18857429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 18957429Smarkm if (options->rhosts_authentication == -1) 19057429Smarkm options->rhosts_authentication = 0; 19157429Smarkm if (options->rhosts_rsa_authentication == -1) 19257565Smarkm options->rhosts_rsa_authentication = 0; 19376262Sgreen if (options->hostbased_authentication == -1) 19476262Sgreen options->hostbased_authentication = 0; 19576262Sgreen if (options->hostbased_uses_name_from_packet_only == -1) 19676262Sgreen options->hostbased_uses_name_from_packet_only = 0; 19757429Smarkm if (options->rsa_authentication == -1) 19857429Smarkm options->rsa_authentication = 1; 19976262Sgreen if (options->pubkey_authentication == -1) 20076262Sgreen options->pubkey_authentication = 1; 20199048Sdes#if defined(KRB4) && defined(KRB5) 20299048Sdes if (options->kerberos_authentication == -1) 20399048Sdes options->kerberos_authentication = 20499048Sdes (access(KEYFILE, R_OK) == 0 || 20599048Sdes access(krb5_defkeyname, R_OK) == 0); 20699048Sdes#elif defined(KRB4) 20799048Sdes if (options->kerberos_authentication == -1) 20899048Sdes options->kerberos_authentication = 20999048Sdes (access(KEYFILE, R_OK) == 0); 21099048Sdes#elif defined(KRB5) 21199048Sdes if (options->kerberos_authentication == -1) 21299048Sdes options->kerberos_authentication = 21399048Sdes (access(krb5_defkeyname, R_OK) == 0); 21499048Sdes#endif 21598941Sdes#if defined(KRB4) || defined(KRB5) 21692559Sdes if (options->kerberos_or_local_passwd == -1) 21792559Sdes options->kerberos_or_local_passwd = 1; 21892559Sdes if (options->kerberos_ticket_cleanup == -1) 21992559Sdes options->kerberos_ticket_cleanup = 1; 22073400Sassar#endif 22192559Sdes#if defined(AFS) || defined(KRB5) 22292559Sdes if (options->kerberos_tgt_passing == -1) 22392559Sdes options->kerberos_tgt_passing = 0; 22492559Sdes#endif 22557429Smarkm#ifdef AFS 22657429Smarkm if (options->afs_token_passing == -1) 22798684Sdes options->afs_token_passing = 0; 22892559Sdes#endif 22957429Smarkm if (options->password_authentication == -1) 23057429Smarkm options->password_authentication = 1; 23169591Sgreen if (options->kbd_interactive_authentication == -1) 23269591Sgreen options->kbd_interactive_authentication = 0; 23392559Sdes if (options->challenge_response_authentication == -1) 23495456Sdes options->challenge_response_authentication = 1; 23557429Smarkm if (options->permit_empty_passwd == -1) 23657565Smarkm options->permit_empty_passwd = 0; 23757429Smarkm if (options->use_login == -1) 23857429Smarkm options->use_login = 0; 23998684Sdes if (options->compression == -1) 24098684Sdes options->compression = 1; 24169591Sgreen if (options->allow_tcp_forwarding == -1) 24269591Sgreen options->allow_tcp_forwarding = 1; 24360576Skris if (options->gateway_ports == -1) 24460576Skris options->gateway_ports = 0; 24565674Skris if (options->max_startups == -1) 24665674Skris options->max_startups = 10; 24765674Skris if (options->max_startups_rate == -1) 24865674Skris options->max_startups_rate = 100; /* 100% */ 24965674Skris if (options->max_startups_begin == -1) 25065674Skris options->max_startups_begin = options->max_startups; 25192559Sdes if (options->verify_reverse_mapping == -1) 25292559Sdes options->verify_reverse_mapping = 0; 25376262Sgreen if (options->client_alive_interval == -1) 25492559Sdes options->client_alive_interval = 0; 25576262Sgreen if (options->client_alive_count_max == -1) 25676262Sgreen options->client_alive_count_max = 3; 25792559Sdes if (options->authorized_keys_file2 == NULL) { 25892559Sdes /* authorized_keys_file2 falls back to authorized_keys_file */ 25992559Sdes if (options->authorized_keys_file != NULL) 26092559Sdes options->authorized_keys_file2 = options->authorized_keys_file; 26192559Sdes else 26292559Sdes options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; 26392559Sdes } 26492559Sdes if (options->authorized_keys_file == NULL) 26592559Sdes options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; 26698684Sdes 26798941Sdes /* Turn privilege separation on by default */ 26898684Sdes if (use_privsep == -1) 26998941Sdes use_privsep = 1; 27098941Sdes 27199063Sdes#if !defined(HAVE_MMAP_ANON_SHARED) 27298941Sdes if (use_privsep && options->compression == 1) { 27398941Sdes error("This platform does not support both privilege " 27498941Sdes "separation and compression"); 27598941Sdes error("Compression disabled"); 27698941Sdes options->compression = 0; 27798941Sdes } 27898941Sdes#endif 27998941Sdes 28057429Smarkm} 28157429Smarkm 28257429Smarkm/* Keyword tokens. */ 28357429Smarkmtypedef enum { 28457429Smarkm sBadOption, /* == unknown option */ 28598941Sdes /* Portable-specific options */ 28698941Sdes sPAMAuthenticationViaKbdInt, 28798941Sdes /* Standard Options */ 28857429Smarkm sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, 28957429Smarkm sPermitRootLogin, sLogFacility, sLogLevel, 29057429Smarkm sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication, 29173400Sassar#if defined(KRB4) || defined(KRB5) 29292559Sdes sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 29373400Sassar#endif 29492559Sdes#if defined(AFS) || defined(KRB5) 29592559Sdes sKerberosTgtPassing, 29657429Smarkm#endif 29757429Smarkm#ifdef AFS 29892559Sdes sAFSTokenPassing, 29957429Smarkm#endif 30076262Sgreen sChallengeResponseAuthentication, 30169591Sgreen sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, 30276262Sgreen sPrintMotd, sPrintLastLog, sIgnoreRhosts, 30392559Sdes sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 30492559Sdes sStrictModes, sEmptyPasswd, sKeepAlives, 30598684Sdes sUseLogin, sAllowTcpForwarding, sCompression, 30669591Sgreen sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 30776262Sgreen sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 30876262Sgreen sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, 30992559Sdes sBanner, sVerifyReverseMapping, sHostbasedAuthentication, 31092559Sdes sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 31192559Sdes sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 31298684Sdes sUsePrivilegeSeparation, 31399047Sdes sVersionAddendum, 31492559Sdes sDeprecated 31557429Smarkm} ServerOpCodes; 31657429Smarkm 31757429Smarkm/* Textual representation of the tokens. */ 31857429Smarkmstatic struct { 31957429Smarkm const char *name; 32057429Smarkm ServerOpCodes opcode; 32157429Smarkm} keywords[] = { 32298941Sdes /* Portable-specific options */ 32399048Sdes#if 0 32498941Sdes { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt }, 32599048Sdes#endif 32698941Sdes /* Standard Options */ 32757429Smarkm { "port", sPort }, 32857429Smarkm { "hostkey", sHostKeyFile }, 32976262Sgreen { "hostdsakey", sHostKeyFile }, /* alias */ 33076262Sgreen { "pidfile", sPidFile }, 33157429Smarkm { "serverkeybits", sServerKeyBits }, 33257429Smarkm { "logingracetime", sLoginGraceTime }, 33357429Smarkm { "keyregenerationinterval", sKeyRegenerationTime }, 33457429Smarkm { "permitrootlogin", sPermitRootLogin }, 33557429Smarkm { "syslogfacility", sLogFacility }, 33657429Smarkm { "loglevel", sLogLevel }, 33757429Smarkm { "rhostsauthentication", sRhostsAuthentication }, 33857429Smarkm { "rhostsrsaauthentication", sRhostsRSAAuthentication }, 33976262Sgreen { "hostbasedauthentication", sHostbasedAuthentication }, 34076262Sgreen { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, 34192559Sdes { "rsaauthentication", sRSAAuthentication }, 34276262Sgreen { "pubkeyauthentication", sPubkeyAuthentication }, 34376262Sgreen { "dsaauthentication", sPubkeyAuthentication }, /* alias */ 34473400Sassar#if defined(KRB4) || defined(KRB5) 34573400Sassar { "kerberosauthentication", sKerberosAuthentication }, 34692559Sdes { "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, 34792559Sdes { "kerberosticketcleanup", sKerberosTicketCleanup }, 34873400Sassar#endif 34992559Sdes#if defined(AFS) || defined(KRB5) 35092559Sdes { "kerberostgtpassing", sKerberosTgtPassing }, 35157429Smarkm#endif 35257429Smarkm#ifdef AFS 35357429Smarkm { "afstokenpassing", sAFSTokenPassing }, 35457429Smarkm#endif 35557429Smarkm { "passwordauthentication", sPasswordAuthentication }, 35669591Sgreen { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, 35776262Sgreen { "challengeresponseauthentication", sChallengeResponseAuthentication }, 35876262Sgreen { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */ 35998941Sdes { "checkmail", sDeprecated }, 36057429Smarkm { "listenaddress", sListenAddress }, 36157429Smarkm { "printmotd", sPrintMotd }, 36276262Sgreen { "printlastlog", sPrintLastLog }, 36357429Smarkm { "ignorerhosts", sIgnoreRhosts }, 36457429Smarkm { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, 36557429Smarkm { "x11forwarding", sX11Forwarding }, 36657429Smarkm { "x11displayoffset", sX11DisplayOffset }, 36792559Sdes { "x11uselocalhost", sX11UseLocalhost }, 36865674Skris { "xauthlocation", sXAuthLocation }, 36957429Smarkm { "strictmodes", sStrictModes }, 37057429Smarkm { "permitemptypasswords", sEmptyPasswd }, 37157429Smarkm { "uselogin", sUseLogin }, 37298684Sdes { "compression", sCompression }, 37357429Smarkm { "keepalive", sKeepAlives }, 37469591Sgreen { "allowtcpforwarding", sAllowTcpForwarding }, 37557429Smarkm { "allowusers", sAllowUsers }, 37657429Smarkm { "denyusers", sDenyUsers }, 37757429Smarkm { "allowgroups", sAllowGroups }, 37857429Smarkm { "denygroups", sDenyGroups }, 37960576Skris { "ciphers", sCiphers }, 38076262Sgreen { "macs", sMacs }, 38160576Skris { "protocol", sProtocol }, 38260576Skris { "gatewayports", sGatewayPorts }, 38365674Skris { "subsystem", sSubsystem }, 38465674Skris { "maxstartups", sMaxStartups }, 38576262Sgreen { "banner", sBanner }, 38692559Sdes { "verifyreversemapping", sVerifyReverseMapping }, 38792559Sdes { "reversemappingcheck", sVerifyReverseMapping }, 38876262Sgreen { "clientaliveinterval", sClientAliveInterval }, 38976262Sgreen { "clientalivecountmax", sClientAliveCountMax }, 39092559Sdes { "authorizedkeysfile", sAuthorizedKeysFile }, 39192559Sdes { "authorizedkeysfile2", sAuthorizedKeysFile2 }, 39298684Sdes { "useprivilegeseparation", sUsePrivilegeSeparation}, 39399047Sdes { "versionaddendum", sVersionAddendum }, 39492559Sdes { NULL, sBadOption } 39557429Smarkm}; 39657429Smarkm 39757429Smarkm/* 39876262Sgreen * Returns the number of the token pointed to by cp or sBadOption. 39957429Smarkm */ 40057429Smarkm 40160576Skrisstatic ServerOpCodes 40257429Smarkmparse_token(const char *cp, const char *filename, 40357429Smarkm int linenum) 40457429Smarkm{ 40576262Sgreen u_int i; 40657429Smarkm 40757429Smarkm for (i = 0; keywords[i].name; i++) 40857429Smarkm if (strcasecmp(cp, keywords[i].name) == 0) 40957429Smarkm return keywords[i].opcode; 41057429Smarkm 41176262Sgreen error("%s: line %d: Bad configuration option: %s", 41276262Sgreen filename, linenum, cp); 41357429Smarkm return sBadOption; 41457429Smarkm} 41557429Smarkm 41692559Sdesstatic void 41776262Sgreenadd_listen_addr(ServerOptions *options, char *addr, u_short port) 41857429Smarkm{ 41957429Smarkm int i; 42057429Smarkm 42157429Smarkm if (options->num_ports == 0) 42257429Smarkm options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 42376262Sgreen if (port == 0) 42476262Sgreen for (i = 0; i < options->num_ports; i++) 42576262Sgreen add_one_listen_addr(options, addr, options->ports[i]); 42676262Sgreen else 42776262Sgreen add_one_listen_addr(options, addr, port); 42857429Smarkm} 42957429Smarkm 43092559Sdesstatic void 43176262Sgreenadd_one_listen_addr(ServerOptions *options, char *addr, u_short port) 43276262Sgreen{ 43376262Sgreen struct addrinfo hints, *ai, *aitop; 43476262Sgreen char strport[NI_MAXSERV]; 43576262Sgreen int gaierr; 43676262Sgreen 43776262Sgreen memset(&hints, 0, sizeof(hints)); 43876262Sgreen hints.ai_family = IPv4or6; 43976262Sgreen hints.ai_socktype = SOCK_STREAM; 44076262Sgreen hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 44199063Sdes snprintf(strport, sizeof strport, "%u", port); 44276262Sgreen if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 44376262Sgreen fatal("bad addr or host: %s (%s)", 44476262Sgreen addr ? addr : "<NULL>", 44576262Sgreen gai_strerror(gaierr)); 44676262Sgreen for (ai = aitop; ai->ai_next; ai = ai->ai_next) 44776262Sgreen ; 44876262Sgreen ai->ai_next = options->listen_addrs; 44976262Sgreen options->listen_addrs = aitop; 45076262Sgreen} 45176262Sgreen 45292559Sdesint 45392559Sdesprocess_server_config_line(ServerOptions *options, char *line, 45492559Sdes const char *filename, int linenum) 45557429Smarkm{ 45676262Sgreen char *cp, **charptr, *arg, *p; 45799063Sdes int *intptr, value, i, n; 45857429Smarkm ServerOpCodes opcode; 45957429Smarkm 46092559Sdes cp = line; 46192559Sdes arg = strdelim(&cp); 46292559Sdes /* Ignore leading whitespace */ 46392559Sdes if (*arg == '\0') 46465674Skris arg = strdelim(&cp); 46592559Sdes if (!arg || !*arg || *arg == '#') 46692559Sdes return 0; 46792559Sdes intptr = NULL; 46892559Sdes charptr = NULL; 46992559Sdes opcode = parse_token(arg, filename, linenum); 47092559Sdes switch (opcode) { 47198941Sdes /* Portable-specific options */ 47298941Sdes case sPAMAuthenticationViaKbdInt: 47398941Sdes intptr = &options->pam_authentication_via_kbd_int; 47498941Sdes goto parse_flag; 47598941Sdes 47698941Sdes /* Standard Options */ 47792559Sdes case sBadOption: 47892559Sdes return -1; 47992559Sdes case sPort: 48092559Sdes /* ignore ports from configfile if cmdline specifies ports */ 48192559Sdes if (options->ports_from_cmdline) 48292559Sdes return 0; 48392559Sdes if (options->listen_addrs != NULL) 48492559Sdes fatal("%s line %d: ports must be specified before " 48592559Sdes "ListenAddress.", filename, linenum); 48692559Sdes if (options->num_ports >= MAX_PORTS) 48792559Sdes fatal("%s line %d: too many ports.", 48892559Sdes filename, linenum); 48992559Sdes arg = strdelim(&cp); 49092559Sdes if (!arg || *arg == '\0') 49192559Sdes fatal("%s line %d: missing port number.", 49292559Sdes filename, linenum); 49392559Sdes options->ports[options->num_ports++] = a2port(arg); 49492559Sdes if (options->ports[options->num_ports-1] == 0) 49592559Sdes fatal("%s line %d: Badly formatted port number.", 49692559Sdes filename, linenum); 49792559Sdes break; 49857429Smarkm 49992559Sdes case sServerKeyBits: 50092559Sdes intptr = &options->server_key_bits; 50157429Smarkmparse_int: 50292559Sdes arg = strdelim(&cp); 50392559Sdes if (!arg || *arg == '\0') 50492559Sdes fatal("%s line %d: missing integer value.", 50592559Sdes filename, linenum); 50692559Sdes value = atoi(arg); 50792559Sdes if (*intptr == -1) 50892559Sdes *intptr = value; 50992559Sdes break; 51057429Smarkm 51192559Sdes case sLoginGraceTime: 51292559Sdes intptr = &options->login_grace_time; 51392559Sdesparse_time: 51492559Sdes arg = strdelim(&cp); 51592559Sdes if (!arg || *arg == '\0') 51692559Sdes fatal("%s line %d: missing time value.", 51792559Sdes filename, linenum); 51892559Sdes if ((value = convtime(arg)) == -1) 51992559Sdes fatal("%s line %d: invalid time value.", 52092559Sdes filename, linenum); 52192559Sdes if (*intptr == -1) 52292559Sdes *intptr = value; 52392559Sdes break; 52457429Smarkm 52592559Sdes case sKeyRegenerationTime: 52692559Sdes intptr = &options->key_regeneration_time; 52792559Sdes goto parse_time; 52857429Smarkm 52992559Sdes case sListenAddress: 53092559Sdes arg = strdelim(&cp); 53192559Sdes if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) 53292559Sdes fatal("%s line %d: missing inet addr.", 53392559Sdes filename, linenum); 53492559Sdes if (*arg == '[') { 53592559Sdes if ((p = strchr(arg, ']')) == NULL) 53692559Sdes fatal("%s line %d: bad ipv6 inet addr usage.", 53757429Smarkm filename, linenum); 53892559Sdes arg++; 53992559Sdes memmove(p, p+1, strlen(p+1)+1); 54092559Sdes } else if (((p = strchr(arg, ':')) == NULL) || 54192559Sdes (strchr(p+1, ':') != NULL)) { 54292559Sdes add_listen_addr(options, arg, 0); 54357429Smarkm break; 54492559Sdes } 54592559Sdes if (*p == ':') { 54692559Sdes u_short port; 54757429Smarkm 54892559Sdes p++; 54992559Sdes if (*p == '\0') 55092559Sdes fatal("%s line %d: bad inet addr:port usage.", 55160576Skris filename, linenum); 55292559Sdes else { 55392559Sdes *(p-1) = '\0'; 55492559Sdes if ((port = a2port(p)) == 0) 55592559Sdes fatal("%s line %d: bad port number.", 55692559Sdes filename, linenum); 55792559Sdes add_listen_addr(options, arg, port); 55857429Smarkm } 55992559Sdes } else if (*p == '\0') 56092559Sdes add_listen_addr(options, arg, 0); 56192559Sdes else 56292559Sdes fatal("%s line %d: bad inet addr usage.", 56392559Sdes filename, linenum); 56492559Sdes break; 56557429Smarkm 56692559Sdes case sHostKeyFile: 56792559Sdes intptr = &options->num_host_key_files; 56892559Sdes if (*intptr >= MAX_HOSTKEYS) 56992559Sdes fatal("%s line %d: too many host keys specified (max %d).", 57092559Sdes filename, linenum, MAX_HOSTKEYS); 57192559Sdes charptr = &options->host_key_files[*intptr]; 57292559Sdesparse_filename: 57392559Sdes arg = strdelim(&cp); 57492559Sdes if (!arg || *arg == '\0') 57592559Sdes fatal("%s line %d: missing file name.", 57692559Sdes filename, linenum); 57792559Sdes if (*charptr == NULL) { 57892559Sdes *charptr = tilde_expand_filename(arg, getuid()); 57992559Sdes /* increase optional counter */ 58092559Sdes if (intptr != NULL) 58192559Sdes *intptr = *intptr + 1; 58292559Sdes } 58392559Sdes break; 58460576Skris 58592559Sdes case sPidFile: 58692559Sdes charptr = &options->pid_file; 58792559Sdes goto parse_filename; 58857429Smarkm 58992559Sdes case sPermitRootLogin: 59092559Sdes intptr = &options->permit_root_login; 59192559Sdes arg = strdelim(&cp); 59292559Sdes if (!arg || *arg == '\0') 59392559Sdes fatal("%s line %d: missing yes/" 59492559Sdes "without-password/forced-commands-only/no " 59592559Sdes "argument.", filename, linenum); 59692559Sdes value = 0; /* silence compiler */ 59792559Sdes if (strcmp(arg, "without-password") == 0) 59892559Sdes value = PERMIT_NO_PASSWD; 59992559Sdes else if (strcmp(arg, "forced-commands-only") == 0) 60092559Sdes value = PERMIT_FORCED_ONLY; 60192559Sdes else if (strcmp(arg, "yes") == 0) 60292559Sdes value = PERMIT_YES; 60392559Sdes else if (strcmp(arg, "no") == 0) 60492559Sdes value = PERMIT_NO; 60592559Sdes else 60692559Sdes fatal("%s line %d: Bad yes/" 60792559Sdes "without-password/forced-commands-only/no " 60892559Sdes "argument: %s", filename, linenum, arg); 60992559Sdes if (*intptr == -1) 61092559Sdes *intptr = value; 61192559Sdes break; 61292559Sdes 61392559Sdes case sIgnoreRhosts: 61492559Sdes intptr = &options->ignore_rhosts; 61557429Smarkmparse_flag: 61692559Sdes arg = strdelim(&cp); 61792559Sdes if (!arg || *arg == '\0') 61892559Sdes fatal("%s line %d: missing yes/no argument.", 61992559Sdes filename, linenum); 62092559Sdes value = 0; /* silence compiler */ 62192559Sdes if (strcmp(arg, "yes") == 0) 62292559Sdes value = 1; 62392559Sdes else if (strcmp(arg, "no") == 0) 62492559Sdes value = 0; 62592559Sdes else 62692559Sdes fatal("%s line %d: Bad yes/no argument: %s", 62792559Sdes filename, linenum, arg); 62892559Sdes if (*intptr == -1) 62992559Sdes *intptr = value; 63092559Sdes break; 63157429Smarkm 63292559Sdes case sIgnoreUserKnownHosts: 63392559Sdes intptr = &options->ignore_user_known_hosts; 63492559Sdes goto parse_flag; 63557429Smarkm 63692559Sdes case sRhostsAuthentication: 63792559Sdes intptr = &options->rhosts_authentication; 63892559Sdes goto parse_flag; 63957429Smarkm 64092559Sdes case sRhostsRSAAuthentication: 64192559Sdes intptr = &options->rhosts_rsa_authentication; 64292559Sdes goto parse_flag; 64357429Smarkm 64492559Sdes case sHostbasedAuthentication: 64592559Sdes intptr = &options->hostbased_authentication; 64692559Sdes goto parse_flag; 64776262Sgreen 64892559Sdes case sHostbasedUsesNameFromPacketOnly: 64992559Sdes intptr = &options->hostbased_uses_name_from_packet_only; 65092559Sdes goto parse_flag; 65176262Sgreen 65292559Sdes case sRSAAuthentication: 65392559Sdes intptr = &options->rsa_authentication; 65492559Sdes goto parse_flag; 65557429Smarkm 65692559Sdes case sPubkeyAuthentication: 65792559Sdes intptr = &options->pubkey_authentication; 65892559Sdes goto parse_flag; 65973400Sassar#if defined(KRB4) || defined(KRB5) 66092559Sdes case sKerberosAuthentication: 66192559Sdes intptr = &options->kerberos_authentication; 66292559Sdes goto parse_flag; 66357429Smarkm 66492559Sdes case sKerberosOrLocalPasswd: 66592559Sdes intptr = &options->kerberos_or_local_passwd; 66692559Sdes goto parse_flag; 66792559Sdes 66892559Sdes case sKerberosTicketCleanup: 66992559Sdes intptr = &options->kerberos_ticket_cleanup; 67092559Sdes goto parse_flag; 67157429Smarkm#endif 67292559Sdes#if defined(AFS) || defined(KRB5) 67392559Sdes case sKerberosTgtPassing: 67492559Sdes intptr = &options->kerberos_tgt_passing; 67592559Sdes goto parse_flag; 67692559Sdes#endif 67792559Sdes#ifdef AFS 67892559Sdes case sAFSTokenPassing: 67992559Sdes intptr = &options->afs_token_passing; 68092559Sdes goto parse_flag; 68192559Sdes#endif 68257429Smarkm 68392559Sdes case sPasswordAuthentication: 68492559Sdes intptr = &options->password_authentication; 68592559Sdes goto parse_flag; 68657565Smarkm 68792559Sdes case sKbdInteractiveAuthentication: 68892559Sdes intptr = &options->kbd_interactive_authentication; 68992559Sdes goto parse_flag; 69057429Smarkm 69192559Sdes case sChallengeResponseAuthentication: 69292559Sdes intptr = &options->challenge_response_authentication; 69392559Sdes goto parse_flag; 69457429Smarkm 69592559Sdes case sPrintMotd: 69692559Sdes intptr = &options->print_motd; 69792559Sdes goto parse_flag; 69857429Smarkm 69992559Sdes case sPrintLastLog: 70092559Sdes intptr = &options->print_lastlog; 70192559Sdes goto parse_flag; 70269591Sgreen 70392559Sdes case sX11Forwarding: 70492559Sdes intptr = &options->x11_forwarding; 70592559Sdes goto parse_flag; 70657429Smarkm 70792559Sdes case sX11DisplayOffset: 70892559Sdes intptr = &options->x11_display_offset; 70992559Sdes goto parse_int; 71057429Smarkm 71192559Sdes case sX11UseLocalhost: 71292559Sdes intptr = &options->x11_use_localhost; 71392559Sdes goto parse_flag; 71457429Smarkm 71592559Sdes case sXAuthLocation: 71692559Sdes charptr = &options->xauth_location; 71792559Sdes goto parse_filename; 71876262Sgreen 71992559Sdes case sStrictModes: 72092559Sdes intptr = &options->strict_modes; 72192559Sdes goto parse_flag; 72257429Smarkm 72392559Sdes case sKeepAlives: 72492559Sdes intptr = &options->keepalives; 72592559Sdes goto parse_flag; 72657429Smarkm 72792559Sdes case sEmptyPasswd: 72892559Sdes intptr = &options->permit_empty_passwd; 72992559Sdes goto parse_flag; 73076262Sgreen 73192559Sdes case sUseLogin: 73292559Sdes intptr = &options->use_login; 73392559Sdes goto parse_flag; 73457429Smarkm 73598684Sdes case sCompression: 73698684Sdes intptr = &options->compression; 73798684Sdes goto parse_flag; 73898684Sdes 73992559Sdes case sGatewayPorts: 74092559Sdes intptr = &options->gateway_ports; 74192559Sdes goto parse_flag; 74257429Smarkm 74392559Sdes case sVerifyReverseMapping: 74492559Sdes intptr = &options->verify_reverse_mapping; 74592559Sdes goto parse_flag; 74657429Smarkm 74792559Sdes case sLogFacility: 74892559Sdes intptr = (int *) &options->log_facility; 74992559Sdes arg = strdelim(&cp); 75092559Sdes value = log_facility_number(arg); 75192559Sdes if (value == SYSLOG_FACILITY_NOT_SET) 75292559Sdes fatal("%.200s line %d: unsupported log facility '%s'", 75392559Sdes filename, linenum, arg ? arg : "<NONE>"); 75492559Sdes if (*intptr == -1) 75592559Sdes *intptr = (SyslogFacility) value; 75692559Sdes break; 75757429Smarkm 75892559Sdes case sLogLevel: 75992559Sdes intptr = (int *) &options->log_level; 76092559Sdes arg = strdelim(&cp); 76192559Sdes value = log_level_number(arg); 76292559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 76392559Sdes fatal("%.200s line %d: unsupported log level '%s'", 76492559Sdes filename, linenum, arg ? arg : "<NONE>"); 76592559Sdes if (*intptr == -1) 76692559Sdes *intptr = (LogLevel) value; 76792559Sdes break; 76860576Skris 76992559Sdes case sAllowTcpForwarding: 77092559Sdes intptr = &options->allow_tcp_forwarding; 77192559Sdes goto parse_flag; 77276262Sgreen 77398684Sdes case sUsePrivilegeSeparation: 77498684Sdes intptr = &use_privsep; 77598684Sdes goto parse_flag; 77698684Sdes 77792559Sdes case sAllowUsers: 77892559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 77992559Sdes if (options->num_allow_users >= MAX_ALLOW_USERS) 78092559Sdes fatal("%s line %d: too many allow users.", 78192559Sdes filename, linenum); 78299063Sdes options->allow_users[options->num_allow_users++] = 78399063Sdes xstrdup(arg); 78492559Sdes } 78592559Sdes break; 78657429Smarkm 78792559Sdes case sDenyUsers: 78892559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 78992559Sdes if (options->num_deny_users >= MAX_DENY_USERS) 79092559Sdes fatal( "%s line %d: too many deny users.", 79192559Sdes filename, linenum); 79299063Sdes options->deny_users[options->num_deny_users++] = 79399063Sdes xstrdup(arg); 79492559Sdes } 79592559Sdes break; 79657429Smarkm 79792559Sdes case sAllowGroups: 79892559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 79992559Sdes if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 80092559Sdes fatal("%s line %d: too many allow groups.", 80192559Sdes filename, linenum); 80299063Sdes options->allow_groups[options->num_allow_groups++] = 80399063Sdes xstrdup(arg); 80492559Sdes } 80592559Sdes break; 80669591Sgreen 80792559Sdes case sDenyGroups: 80892559Sdes while ((arg = strdelim(&cp)) && *arg != '\0') { 80992559Sdes if (options->num_deny_groups >= MAX_DENY_GROUPS) 81092559Sdes fatal("%s line %d: too many deny groups.", 81192559Sdes filename, linenum); 81292559Sdes options->deny_groups[options->num_deny_groups++] = xstrdup(arg); 81392559Sdes } 81492559Sdes break; 81557429Smarkm 81692559Sdes case sCiphers: 81792559Sdes arg = strdelim(&cp); 81892559Sdes if (!arg || *arg == '\0') 81992559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 82092559Sdes if (!ciphers_valid(arg)) 82192559Sdes fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 82292559Sdes filename, linenum, arg ? arg : "<NONE>"); 82392559Sdes if (options->ciphers == NULL) 82492559Sdes options->ciphers = xstrdup(arg); 82592559Sdes break; 82657429Smarkm 82792559Sdes case sMacs: 82892559Sdes arg = strdelim(&cp); 82992559Sdes if (!arg || *arg == '\0') 83092559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 83192559Sdes if (!mac_valid(arg)) 83292559Sdes fatal("%s line %d: Bad SSH2 mac spec '%s'.", 83392559Sdes filename, linenum, arg ? arg : "<NONE>"); 83492559Sdes if (options->macs == NULL) 83592559Sdes options->macs = xstrdup(arg); 83692559Sdes break; 83757429Smarkm 83892559Sdes case sProtocol: 83992559Sdes intptr = &options->protocol; 84092559Sdes arg = strdelim(&cp); 84192559Sdes if (!arg || *arg == '\0') 84292559Sdes fatal("%s line %d: Missing argument.", filename, linenum); 84392559Sdes value = proto_spec(arg); 84492559Sdes if (value == SSH_PROTO_UNKNOWN) 84592559Sdes fatal("%s line %d: Bad protocol spec '%s'.", 84692559Sdes filename, linenum, arg ? arg : "<NONE>"); 84792559Sdes if (*intptr == SSH_PROTO_UNKNOWN) 84892559Sdes *intptr = value; 84992559Sdes break; 85057429Smarkm 85192559Sdes case sSubsystem: 85292559Sdes if (options->num_subsystems >= MAX_SUBSYSTEMS) { 85392559Sdes fatal("%s line %d: too many subsystems defined.", 85492559Sdes filename, linenum); 85592559Sdes } 85692559Sdes arg = strdelim(&cp); 85792559Sdes if (!arg || *arg == '\0') 85892559Sdes fatal("%s line %d: Missing subsystem name.", 85992559Sdes filename, linenum); 86092559Sdes for (i = 0; i < options->num_subsystems; i++) 86192559Sdes if (strcmp(arg, options->subsystem_name[i]) == 0) 86292559Sdes fatal("%s line %d: Subsystem '%s' already defined.", 86392559Sdes filename, linenum, arg); 86492559Sdes options->subsystem_name[options->num_subsystems] = xstrdup(arg); 86592559Sdes arg = strdelim(&cp); 86692559Sdes if (!arg || *arg == '\0') 86792559Sdes fatal("%s line %d: Missing subsystem command.", 86892559Sdes filename, linenum); 86992559Sdes options->subsystem_command[options->num_subsystems] = xstrdup(arg); 87092559Sdes options->num_subsystems++; 87192559Sdes break; 87260576Skris 87392559Sdes case sMaxStartups: 87492559Sdes arg = strdelim(&cp); 87592559Sdes if (!arg || *arg == '\0') 87692559Sdes fatal("%s line %d: Missing MaxStartups spec.", 87792559Sdes filename, linenum); 87892559Sdes if ((n = sscanf(arg, "%d:%d:%d", 87992559Sdes &options->max_startups_begin, 88092559Sdes &options->max_startups_rate, 88192559Sdes &options->max_startups)) == 3) { 88292559Sdes if (options->max_startups_begin > 88392559Sdes options->max_startups || 88492559Sdes options->max_startups_rate > 100 || 88592559Sdes options->max_startups_rate < 1) 88692559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 88792559Sdes filename, linenum); 88892559Sdes } else if (n != 1) 88992559Sdes fatal("%s line %d: Illegal MaxStartups spec.", 89092559Sdes filename, linenum); 89192559Sdes else 89292559Sdes options->max_startups = options->max_startups_begin; 89392559Sdes break; 89476262Sgreen 89592559Sdes case sBanner: 89692559Sdes charptr = &options->banner; 89792559Sdes goto parse_filename; 89892559Sdes /* 89992559Sdes * These options can contain %X options expanded at 90092559Sdes * connect time, so that you can specify paths like: 90192559Sdes * 90292559Sdes * AuthorizedKeysFile /etc/ssh_keys/%u 90392559Sdes */ 90492559Sdes case sAuthorizedKeysFile: 90592559Sdes case sAuthorizedKeysFile2: 90692559Sdes charptr = (opcode == sAuthorizedKeysFile ) ? 90792559Sdes &options->authorized_keys_file : 90892559Sdes &options->authorized_keys_file2; 90992559Sdes goto parse_filename; 91060576Skris 91192559Sdes case sClientAliveInterval: 91292559Sdes intptr = &options->client_alive_interval; 91392559Sdes goto parse_time; 91457432Smarkm 91592559Sdes case sClientAliveCountMax: 91692559Sdes intptr = &options->client_alive_count_max; 91792559Sdes goto parse_int; 91865674Skris 91999047Sdes case sVersionAddendum: 92099047Sdes ssh_version_set_addendum(strtok(cp, "\n")); 92199047Sdes do { 92299047Sdes arg = strdelim(&cp); 92399047Sdes } while (arg != NULL && *arg != '\0'); 92499047Sdes break; 92599047Sdes 92692559Sdes case sDeprecated: 92792559Sdes log("%s line %d: Deprecated option %s", 92892559Sdes filename, linenum, arg); 92992559Sdes while (arg) 93092559Sdes arg = strdelim(&cp); 93192559Sdes break; 93292559Sdes 93392559Sdes default: 93492559Sdes fatal("%s line %d: Missing handler for opcode %s (%d)", 93592559Sdes filename, linenum, arg, opcode); 93692559Sdes } 93792559Sdes if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 93892559Sdes fatal("%s line %d: garbage at end of line; \"%.200s\".", 93992559Sdes filename, linenum, arg); 94092559Sdes return 0; 94192559Sdes} 94276227Sgreen 94392559Sdes/* Reads the server configuration file. */ 94492559Sdes 94592559Sdesvoid 94692559Sdesread_server_config(ServerOptions *options, const char *filename) 94792559Sdes{ 94899063Sdes int linenum, bad_options = 0; 94999063Sdes char line[1024]; 95092559Sdes FILE *f; 95192559Sdes 95292559Sdes f = fopen(filename, "r"); 95392559Sdes if (!f) { 95492559Sdes perror(filename); 95592559Sdes exit(1); 95657429Smarkm } 95792559Sdes linenum = 0; 95892559Sdes while (fgets(line, sizeof(line), f)) { 95992559Sdes /* Update line number counter. */ 96092559Sdes linenum++; 96192559Sdes if (process_server_config_line(options, line, filename, linenum) != 0) 96292559Sdes bad_options++; 96392559Sdes } 96457429Smarkm fclose(f); 96576262Sgreen if (bad_options > 0) 96692559Sdes fatal("%s: terminating, %d bad configuration options", 96776262Sgreen filename, bad_options); 96857429Smarkm} 969