]> andersk Git - openssh.git/blame - servconf.c
- jmc@cvs.openbsd.org 2006/07/12 13:39:55
[openssh.git] / servconf.c
CommitLineData
d231781a 1/* $OpenBSD: servconf.c,v 1.153 2006/07/12 11:34:58 dtucker Exp $ */
8efc0c15 2/*
5260325f 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
6ae2364d 5 *
bcbf86ec 6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
5260325f 11 */
8efc0c15 12
13#include "includes.h"
8efc0c15 14
5b04a8bf 15#include <sys/types.h>
16#include <sys/socket.h>
17
8efc0c15 18#include "ssh.h"
42f11eb2 19#include "log.h"
8efc0c15 20#include "servconf.h"
21#include "xmalloc.h"
a8be9f80 22#include "compat.h"
42f11eb2 23#include "pathnames.h"
42f11eb2 24#include "misc.h"
25#include "cipher.h"
b2552997 26#include "kex.h"
27#include "mac.h"
d231781a 28#include "match.h"
42f11eb2 29
396c147e 30static void add_listen_addr(ServerOptions *, char *, u_short);
31static void add_one_listen_addr(ServerOptions *, char *, u_short);
48e671d5 32
1853d1ef 33/* Use of privilege separation or not */
34extern int use_privsep;
d231781a 35extern Buffer cfg;
42f11eb2 36
8efc0c15 37/* Initializes the server options to their default values. */
38
6ae2364d 39void
5260325f 40initialize_server_options(ServerOptions *options)
8efc0c15 41{
5260325f 42 memset(options, 0, sizeof(*options));
e15895cd 43
44 /* Portable-specific options */
7fceb20d 45 options->use_pam = -1;
e15895cd 46
47 /* Standard Options */
48e671d5 48 options->num_ports = 0;
49 options->ports_from_cmdline = 0;
50 options->listen_addrs = NULL;
31b41ceb 51 options->address_family = -1;
fa08c86b 52 options->num_host_key_files = 0;
0fbe8c74 53 options->pid_file = NULL;
5260325f 54 options->server_key_bits = -1;
55 options->login_grace_time = -1;
56 options->key_regeneration_time = -1;
15853e93 57 options->permit_root_login = PERMIT_NOT_SET;
5260325f 58 options->ignore_rhosts = -1;
59 options->ignore_user_known_hosts = -1;
60 options->print_motd = -1;
4f4648f9 61 options->print_lastlog = -1;
5260325f 62 options->x11_forwarding = -1;
63 options->x11_display_offset = -1;
e6e573bd 64 options->x11_use_localhost = -1;
fa649821 65 options->xauth_location = NULL;
5260325f 66 options->strict_modes = -1;
fd573618 67 options->tcp_keep_alive = -1;
5eaf8578 68 options->log_facility = SYSLOG_FACILITY_NOT_SET;
69 options->log_level = SYSLOG_LEVEL_NOT_SET;
5260325f 70 options->rhosts_rsa_authentication = -1;
8002af61 71 options->hostbased_authentication = -1;
72 options->hostbased_uses_name_from_packet_only = -1;
5260325f 73 options->rsa_authentication = -1;
fa08c86b 74 options->pubkey_authentication = -1;
5260325f 75 options->kerberos_authentication = -1;
76 options->kerberos_or_local_passwd = -1;
77 options->kerberos_ticket_cleanup = -1;
a1e30b47 78 options->kerberos_get_afs_token = -1;
7364bd04 79 options->gss_authentication=-1;
80 options->gss_cleanup_creds = -1;
5260325f 81 options->password_authentication = -1;
94ec8c6b 82 options->kbd_interactive_authentication = -1;
5ba55ada 83 options->challenge_response_authentication = -1;
5260325f 84 options->permit_empty_passwd = -1;
f00bab84 85 options->permit_user_env = -1;
5260325f 86 options->use_login = -1;
636f76ca 87 options->compression = -1;
33de75a3 88 options->allow_tcp_forwarding = -1;
5260325f 89 options->num_allow_users = 0;
90 options->num_deny_users = 0;
91 options->num_allow_groups = 0;
92 options->num_deny_groups = 0;
a8be9f80 93 options->ciphers = NULL;
b2552997 94 options->macs = NULL;
a8be9f80 95 options->protocol = SSH_PROTO_UNKNOWN;
1d1ffb87 96 options->gateway_ports = -1;
38c295d6 97 options->num_subsystems = 0;
c345cf9d 98 options->max_startups_begin = -1;
99 options->max_startups_rate = -1;
089fbbd2 100 options->max_startups = -1;
af4bd935 101 options->max_authtries = -1;
eea39c02 102 options->banner = NULL;
c5a7d788 103 options->use_dns = -1;
3ffc6336 104 options->client_alive_interval = -1;
105 options->client_alive_count_max = -1;
c8445989 106 options->authorized_keys_file = NULL;
107 options->authorized_keys_file2 = NULL;
61a2c1da 108 options->num_accept_env = 0;
d20f3c9e 109 options->permit_tun = -1;
8efc0c15 110}
111
6ae2364d 112void
5260325f 113fill_default_server_options(ServerOptions *options)
8efc0c15 114{
e15895cd 115 /* Portable-specific options */
7fceb20d 116 if (options->use_pam == -1)
0a23d79f 117 options->use_pam = 0;
e15895cd 118
119 /* Standard Options */
fa08c86b 120 if (options->protocol == SSH_PROTO_UNKNOWN)
121 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
122 if (options->num_host_key_files == 0) {
123 /* fill default hostkeys for protocols */
124 if (options->protocol & SSH_PROTO_1)
0f84fe37 125 options->host_key_files[options->num_host_key_files++] =
126 _PATH_HOST_KEY_FILE;
127 if (options->protocol & SSH_PROTO_2) {
128 options->host_key_files[options->num_host_key_files++] =
129 _PATH_HOST_RSA_KEY_FILE;
130 options->host_key_files[options->num_host_key_files++] =
131 _PATH_HOST_DSA_KEY_FILE;
132 }
fa08c86b 133 }
48e671d5 134 if (options->num_ports == 0)
135 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
136 if (options->listen_addrs == NULL)
2d2a2c65 137 add_listen_addr(options, NULL, 0);
0fbe8c74 138 if (options->pid_file == NULL)
42f11eb2 139 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
5260325f 140 if (options->server_key_bits == -1)
141 options->server_key_bits = 768;
142 if (options->login_grace_time == -1)
3445ca02 143 options->login_grace_time = 120;
5260325f 144 if (options->key_regeneration_time == -1)
145 options->key_regeneration_time = 3600;
15853e93 146 if (options->permit_root_login == PERMIT_NOT_SET)
147 options->permit_root_login = PERMIT_YES;
5260325f 148 if (options->ignore_rhosts == -1)
c8d54615 149 options->ignore_rhosts = 1;
5260325f 150 if (options->ignore_user_known_hosts == -1)
151 options->ignore_user_known_hosts = 0;
5260325f 152 if (options->print_motd == -1)
153 options->print_motd = 1;
4f4648f9 154 if (options->print_lastlog == -1)
155 options->print_lastlog = 1;
5260325f 156 if (options->x11_forwarding == -1)
c8d54615 157 options->x11_forwarding = 0;
5260325f 158 if (options->x11_display_offset == -1)
c8d54615 159 options->x11_display_offset = 10;
e6e573bd 160 if (options->x11_use_localhost == -1)
161 options->x11_use_localhost = 1;
fa649821 162 if (options->xauth_location == NULL)
fd9ede94 163 options->xauth_location = _PATH_XAUTH;
5260325f 164 if (options->strict_modes == -1)
165 options->strict_modes = 1;
fd573618 166 if (options->tcp_keep_alive == -1)
167 options->tcp_keep_alive = 1;
5eaf8578 168 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
5260325f 169 options->log_facility = SYSLOG_FACILITY_AUTH;
5eaf8578 170 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
59c97189 171 options->log_level = SYSLOG_LEVEL_INFO;
5260325f 172 if (options->rhosts_rsa_authentication == -1)
c8d54615 173 options->rhosts_rsa_authentication = 0;
8002af61 174 if (options->hostbased_authentication == -1)
175 options->hostbased_authentication = 0;
176 if (options->hostbased_uses_name_from_packet_only == -1)
177 options->hostbased_uses_name_from_packet_only = 0;
5260325f 178 if (options->rsa_authentication == -1)
179 options->rsa_authentication = 1;
fa08c86b 180 if (options->pubkey_authentication == -1)
181 options->pubkey_authentication = 1;
5260325f 182 if (options->kerberos_authentication == -1)
eadc806d 183 options->kerberos_authentication = 0;
5260325f 184 if (options->kerberos_or_local_passwd == -1)
185 options->kerberos_or_local_passwd = 1;
186 if (options->kerberos_ticket_cleanup == -1)
187 options->kerberos_ticket_cleanup = 1;
a1e30b47 188 if (options->kerberos_get_afs_token == -1)
189 options->kerberos_get_afs_token = 0;
7364bd04 190 if (options->gss_authentication == -1)
191 options->gss_authentication = 0;
192 if (options->gss_cleanup_creds == -1)
193 options->gss_cleanup_creds = 1;
5260325f 194 if (options->password_authentication == -1)
195 options->password_authentication = 1;
94ec8c6b 196 if (options->kbd_interactive_authentication == -1)
197 options->kbd_interactive_authentication = 0;
5ba55ada 198 if (options->challenge_response_authentication == -1)
199 options->challenge_response_authentication = 1;
5260325f 200 if (options->permit_empty_passwd == -1)
c8d54615 201 options->permit_empty_passwd = 0;
f00bab84 202 if (options->permit_user_env == -1)
203 options->permit_user_env = 0;
5260325f 204 if (options->use_login == -1)
205 options->use_login = 0;
636f76ca 206 if (options->compression == -1)
07200973 207 options->compression = COMP_DELAYED;
33de75a3 208 if (options->allow_tcp_forwarding == -1)
209 options->allow_tcp_forwarding = 1;
1d1ffb87 210 if (options->gateway_ports == -1)
211 options->gateway_ports = 0;
089fbbd2 212 if (options->max_startups == -1)
213 options->max_startups = 10;
c345cf9d 214 if (options->max_startups_rate == -1)
215 options->max_startups_rate = 100; /* 100% */
216 if (options->max_startups_begin == -1)
217 options->max_startups_begin = options->max_startups;
af4bd935 218 if (options->max_authtries == -1)
219 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
c5a7d788 220 if (options->use_dns == -1)
221 options->use_dns = 1;
3ffc6336 222 if (options->client_alive_interval == -1)
184eed6a 223 options->client_alive_interval = 0;
3ffc6336 224 if (options->client_alive_count_max == -1)
225 options->client_alive_count_max = 3;
5df83e07 226 if (options->authorized_keys_file2 == NULL) {
227 /* authorized_keys_file2 falls back to authorized_keys_file */
228 if (options->authorized_keys_file != NULL)
229 options->authorized_keys_file2 = options->authorized_keys_file;
230 else
231 options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
232 }
233 if (options->authorized_keys_file == NULL)
234 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
d20f3c9e 235 if (options->permit_tun == -1)
a4f24bf8 236 options->permit_tun = SSH_TUNMODE_NO;
1853d1ef 237
2ee1b704 238 /* Turn privilege separation on by default */
1853d1ef 239 if (use_privsep == -1)
2ee1b704 240 use_privsep = 1;
e299a298 241
4165b82e 242#ifndef HAVE_MMAP
e299a298 243 if (use_privsep && options->compression == 1) {
244 error("This platform does not support both privilege "
245 "separation and compression");
246 error("Compression disabled");
247 options->compression = 0;
248 }
249#endif
250
8efc0c15 251}
252
8efc0c15 253/* Keyword tokens. */
5260325f 254typedef enum {
255 sBadOption, /* == unknown option */
e15895cd 256 /* Portable-specific options */
7fceb20d 257 sUsePAM,
e15895cd 258 /* Standard Options */
5260325f 259 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
260 sPermitRootLogin, sLogFacility, sLogLevel,
0598d99d 261 sRhostsRSAAuthentication, sRSAAuthentication,
5260325f 262 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
a1e30b47 263 sKerberosGetAFSToken,
1c590258 264 sKerberosTgtPassing, sChallengeResponseAuthentication,
31b41ceb 265 sPasswordAuthentication, sKbdInteractiveAuthentication,
266 sListenAddress, sAddressFamily,
4f4648f9 267 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
e6e573bd 268 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
fd573618 269 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
f00bab84 270 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
33de75a3 271 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
b2552997 272 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
af4bd935 273 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
274 sMaxStartups, sMaxAuthTries,
c5a7d788 275 sBanner, sUseDNS, sHostbasedAuthentication,
184eed6a 276 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
c8445989 277 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
d20f3c9e 278 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
d231781a 279 sMatch,
2ea6de2b 280 sUsePrivilegeSeparation,
a2144546 281 sDeprecated, sUnsupported
8efc0c15 282} ServerOpCodes;
283
d231781a 284#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
285#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
286#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
287
8efc0c15 288/* Textual representation of the tokens. */
5260325f 289static struct {
290 const char *name;
291 ServerOpCodes opcode;
d231781a 292 u_int flags;
5260325f 293} keywords[] = {
e15895cd 294 /* Portable-specific options */
b06b11ad 295#ifdef USE_PAM
d231781a 296 { "usepam", sUsePAM, SSHCFG_GLOBAL },
b06b11ad 297#else
d231781a 298 { "usepam", sUnsupported, SSHCFG_GLOBAL },
b06b11ad 299#endif
d231781a 300 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
e15895cd 301 /* Standard Options */
d231781a 302 { "port", sPort, SSHCFG_GLOBAL },
303 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
304 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
305 { "pidfile", sPidFile, SSHCFG_GLOBAL },
306 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
307 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
308 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
309 { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL },
310 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
311 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
312 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
313 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL },
314 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL },
315 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
316 { "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL },
317 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },
318 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
1c590258 319#ifdef KRB5
d231781a 320 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL },
321 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
322 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
bcfcc5f9 323#ifdef USE_AFS
d231781a 324 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
309af4e5 325#else
d231781a 326 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
309af4e5 327#endif
a2144546 328#else
d231781a 329 { "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL },
330 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
331 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
332 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
a2144546 333#endif
d231781a 334 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
335 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
7364bd04 336#ifdef GSSAPI
d231781a 337 { "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
338 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
7364bd04 339#else
d231781a 340 { "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
341 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
7364bd04 342#endif
d231781a 343 { "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
344 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL },
345 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
346 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
347 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
348 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
349 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
350 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
351 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
352 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
353 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
354 { "x11forwarding", sX11Forwarding, SSHCFG_GLOBAL },
355 { "x11displayoffset", sX11DisplayOffset, SSHCFG_GLOBAL },
356 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_GLOBAL },
357 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
358 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
359 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
360 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
361 { "uselogin", sUseLogin, SSHCFG_GLOBAL },
362 { "compression", sCompression, SSHCFG_GLOBAL },
363 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
364 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
365 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
366 { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
367 { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
368 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
369 { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
370 { "ciphers", sCiphers, SSHCFG_GLOBAL },
371 { "macs", sMacs, SSHCFG_GLOBAL },
372 { "protocol", sProtocol, SSHCFG_GLOBAL },
373 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
374 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
375 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
376 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
377 { "banner", sBanner, SSHCFG_GLOBAL },
378 { "usedns", sUseDNS, SSHCFG_GLOBAL },
379 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
380 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
381 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
382 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
383 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
384 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
385 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
386 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
387 { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
388 { NULL, sBadOption, 0 }
8efc0c15 389};
390
aa3378df 391/*
6be9a5e8 392 * Returns the number of the token pointed to by cp or sBadOption.
aa3378df 393 */
8efc0c15 394
6ae2364d 395static ServerOpCodes
5260325f 396parse_token(const char *cp, const char *filename,
d231781a 397 int linenum, u_int *flags)
8efc0c15 398{
1e3b8b07 399 u_int i;
8efc0c15 400
5260325f 401 for (i = 0; keywords[i].name; i++)
d231781a 402 if (strcasecmp(cp, keywords[i].name) == 0) {
403 *flags = keywords[i].flags;
5260325f 404 return keywords[i].opcode;
d231781a 405 }
8efc0c15 406
b7c70970 407 error("%s: line %d: Bad configuration option: %s",
408 filename, linenum, cp);
5260325f 409 return sBadOption;
8efc0c15 410}
411
396c147e 412static void
2d2a2c65 413add_listen_addr(ServerOptions *options, char *addr, u_short port)
48e671d5 414{
2ceb8101 415 u_int i;
48e671d5 416
417 if (options->num_ports == 0)
418 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
31b41ceb 419 if (options->address_family == -1)
420 options->address_family = AF_UNSPEC;
2d2a2c65 421 if (port == 0)
d11c1288 422 for (i = 0; i < options->num_ports; i++)
423 add_one_listen_addr(options, addr, options->ports[i]);
424 else
2d2a2c65 425 add_one_listen_addr(options, addr, port);
d11c1288 426}
427
396c147e 428static void
d11c1288 429add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
430{
431 struct addrinfo hints, *ai, *aitop;
432 char strport[NI_MAXSERV];
433 int gaierr;
434
435 memset(&hints, 0, sizeof(hints));
31b41ceb 436 hints.ai_family = options->address_family;
d11c1288 437 hints.ai_socktype = SOCK_STREAM;
438 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
7528d467 439 snprintf(strport, sizeof strport, "%u", port);
d11c1288 440 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
441 fatal("bad addr or host: %s (%s)",
442 addr ? addr : "<NULL>",
443 gai_strerror(gaierr));
444 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
445 ;
446 ai->ai_next = options->listen_addrs;
447 options->listen_addrs = aitop;
48e671d5 448}
449
d231781a 450/*
451 * The strategy for the Match blocks is that the config file is parsed twice.
452 *
453 * The first time is at startup. activep is initialized to 1 and the
454 * directives in the global context are processed and acted on. Hitting a
455 * Match directive unsets activep and the directives inside the block are
456 * checked for syntax only.
457 *
458 * The second time is after a connection has been established but before
459 * authentication. activep is initialized to 2 and global config directives
460 * are ignored since they have already been processed. If the criteria in a
461 * Match block is met, activep is set and the subsequent directives
462 * processed and actioned until EOF or another Match block unsets it. Any
463 * options set are copied into the main server config.
464 *
465 * Potential additions/improvements:
466 * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
467 *
468 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
469 * Match Address 192.168.0.*
470 * Tag trusted
471 * Match Group wheel
472 * Tag trusted
473 * Match Tag trusted
474 * AllowTcpForwarding yes
475 * GatewayPorts clientspecified
476 * [...]
477 *
478 * - Add a PermittedChannelRequests directive
479 * Match Group shell
480 * PermittedChannelRequests session,forwarded-tcpip
481 */
482
483static int
484match_cfg_line(char **condition, int line, const char *user, const char *host,
485 const char *address)
486{
487 int result = 1;
488 char *arg, *attrib, *cp = *condition;
489 size_t len;
490
491 if (user == NULL)
492 debug3("checking syntax for 'Match %s'", cp);
493 else
494 debug3("checking match for '%s' user %s host %s addr %s", cp,
495 user ? user : "(null)", host ? host : "(null)",
496 address ? address : "(null)");
497
498 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
499 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
500 error("Missing Match criteria for %s", attrib);
501 return -1;
502 }
503 len = strlen(arg);
504 if (strcasecmp(attrib, "user") == 0) {
505 if (!user) {
506 result = 0;
507 continue;
508 }
509 if (match_pattern_list(user, arg, len, 0) != 1)
510 result = 0;
511 else
512 debug("user %.100s matched 'User %.100s' at "
513 "line %d", user, arg, line);
514 } else if (strcasecmp(attrib, "host") == 0) {
515 if (!host) {
516 result = 0;
517 continue;
518 }
519 if (match_hostname(host, arg, len) != 1)
520 result = 0;
521 else
522 debug("connection from %.100s matched 'Host "
523 "%.100s' at line %d", host, arg, line);
524 } else if (strcasecmp(attrib, "address") == 0) {
525 debug("address '%s' arg '%s'", address, arg);
526 if (!address) {
527 result = 0;
528 continue;
529 }
530 if (match_hostname(address, arg, len) != 1)
531 result = 0;
532 else
533 debug("connection from %.100s matched 'Address "
534 "%.100s' at line %d", address, arg, line);
535 } else {
536 error("Unsupported Match attribute %s", attrib);
537 return -1;
538 }
539 }
540 if (user != NULL)
541 debug3("match %sfound", result ? "" : "not ");
542 *condition = cp;
543 return result;
544}
545
2717fa0f 546int
547process_server_config_line(ServerOptions *options, char *line,
d231781a 548 const char *filename, int linenum, int *activep, const char *user,
549 const char *host, const char *address)
8efc0c15 550{
d11c1288 551 char *cp, **charptr, *arg, *p;
d231781a 552 int cmdline = 0, *intptr, value, n;
5260325f 553 ServerOpCodes opcode;
3867aa0a 554 u_short port;
d231781a 555 u_int i, flags = 0;
d66ce1a1 556 size_t len;
5260325f 557
2717fa0f 558 cp = line;
0f8cd5a6 559 if ((arg = strdelim(&cp)) == NULL)
88299971 560 return 0;
2717fa0f 561 /* Ignore leading whitespace */
562 if (*arg == '\0')
704b1659 563 arg = strdelim(&cp);
2717fa0f 564 if (!arg || !*arg || *arg == '#')
565 return 0;
566 intptr = NULL;
567 charptr = NULL;
d231781a 568 opcode = parse_token(arg, filename, linenum, &flags);
569
570 if (activep == NULL) { /* We are processing a command line directive */
571 cmdline = 1;
572 activep = &cmdline;
573 }
574 if (*activep && opcode != sMatch)
575 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
576 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
577 if (user == NULL) {
578 fatal("%s line %d: Directive '%s' is not allowed "
579 "within a Match block", filename, linenum, arg);
580 } else { /* this is a directive we have already processed */
581 while (arg)
582 arg = strdelim(&cp);
583 return 0;
584 }
585 }
586
2717fa0f 587 switch (opcode) {
588 /* Portable-specific options */
7fceb20d 589 case sUsePAM:
590 intptr = &options->use_pam;
2717fa0f 591 goto parse_flag;
48e671d5 592
2717fa0f 593 /* Standard Options */
594 case sBadOption:
595 return -1;
596 case sPort:
597 /* ignore ports from configfile if cmdline specifies ports */
598 if (options->ports_from_cmdline)
599 return 0;
600 if (options->listen_addrs != NULL)
601 fatal("%s line %d: ports must be specified before "
3a454b6a 602 "ListenAddress.", filename, linenum);
2717fa0f 603 if (options->num_ports >= MAX_PORTS)
604 fatal("%s line %d: too many ports.",
605 filename, linenum);
606 arg = strdelim(&cp);
607 if (!arg || *arg == '\0')
608 fatal("%s line %d: missing port number.",
609 filename, linenum);
610 options->ports[options->num_ports++] = a2port(arg);
611 if (options->ports[options->num_ports-1] == 0)
612 fatal("%s line %d: Badly formatted port number.",
613 filename, linenum);
614 break;
615
616 case sServerKeyBits:
617 intptr = &options->server_key_bits;
5260325f 618parse_int:
2717fa0f 619 arg = strdelim(&cp);
620 if (!arg || *arg == '\0')
621 fatal("%s line %d: missing integer value.",
622 filename, linenum);
623 value = atoi(arg);
d231781a 624 if (*activep && *intptr == -1)
2717fa0f 625 *intptr = value;
626 break;
627
628 case sLoginGraceTime:
629 intptr = &options->login_grace_time;
e2b1fb42 630parse_time:
2717fa0f 631 arg = strdelim(&cp);
632 if (!arg || *arg == '\0')
633 fatal("%s line %d: missing time value.",
634 filename, linenum);
635 if ((value = convtime(arg)) == -1)
636 fatal("%s line %d: invalid time value.",
637 filename, linenum);
638 if (*intptr == -1)
639 *intptr = value;
640 break;
641
642 case sKeyRegenerationTime:
643 intptr = &options->key_regeneration_time;
644 goto parse_time;
645
646 case sListenAddress:
647 arg = strdelim(&cp);
3867aa0a 648 if (arg == NULL || *arg == '\0')
649 fatal("%s line %d: missing address",
2717fa0f 650 filename, linenum);
91135a0e 651 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
652 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
653 && strchr(p+1, ':') != NULL) {
654 add_listen_addr(options, arg, 0);
655 break;
656 }
3867aa0a 657 p = hpdelim(&arg);
658 if (p == NULL)
659 fatal("%s line %d: bad address:port usage",
2717fa0f 660 filename, linenum);
3867aa0a 661 p = cleanhostname(p);
662 if (arg == NULL)
663 port = 0;
664 else if ((port = a2port(arg)) == 0)
665 fatal("%s line %d: bad port number", filename, linenum);
666
667 add_listen_addr(options, p, port);
668
2717fa0f 669 break;
670
31b41ceb 671 case sAddressFamily:
672 arg = strdelim(&cp);
38634ff6 673 if (!arg || *arg == '\0')
674 fatal("%s line %d: missing address family.",
675 filename, linenum);
31b41ceb 676 intptr = &options->address_family;
677 if (options->listen_addrs != NULL)
678 fatal("%s line %d: address family must be specified before "
679 "ListenAddress.", filename, linenum);
680 if (strcasecmp(arg, "inet") == 0)
681 value = AF_INET;
682 else if (strcasecmp(arg, "inet6") == 0)
683 value = AF_INET6;
684 else if (strcasecmp(arg, "any") == 0)
685 value = AF_UNSPEC;
686 else
687 fatal("%s line %d: unsupported address family \"%s\".",
688 filename, linenum, arg);
689 if (*intptr == -1)
690 *intptr = value;
691 break;
692
2717fa0f 693 case sHostKeyFile:
694 intptr = &options->num_host_key_files;
695 if (*intptr >= MAX_HOSTKEYS)
696 fatal("%s line %d: too many host keys specified (max %d).",
697 filename, linenum, MAX_HOSTKEYS);
698 charptr = &options->host_key_files[*intptr];
fa649821 699parse_filename:
2717fa0f 700 arg = strdelim(&cp);
701 if (!arg || *arg == '\0')
702 fatal("%s line %d: missing file name.",
703 filename, linenum);
d231781a 704 if (*activep && *charptr == NULL) {
2717fa0f 705 *charptr = tilde_expand_filename(arg, getuid());
706 /* increase optional counter */
707 if (intptr != NULL)
708 *intptr = *intptr + 1;
709 }
710 break;
0fbe8c74 711
2717fa0f 712 case sPidFile:
713 charptr = &options->pid_file;
714 goto parse_filename;
5260325f 715
2717fa0f 716 case sPermitRootLogin:
717 intptr = &options->permit_root_login;
718 arg = strdelim(&cp);
719 if (!arg || *arg == '\0')
720 fatal("%s line %d: missing yes/"
721 "without-password/forced-commands-only/no "
722 "argument.", filename, linenum);
723 value = 0; /* silence compiler */
724 if (strcmp(arg, "without-password") == 0)
725 value = PERMIT_NO_PASSWD;
726 else if (strcmp(arg, "forced-commands-only") == 0)
727 value = PERMIT_FORCED_ONLY;
728 else if (strcmp(arg, "yes") == 0)
729 value = PERMIT_YES;
730 else if (strcmp(arg, "no") == 0)
731 value = PERMIT_NO;
732 else
733 fatal("%s line %d: Bad yes/"
734 "without-password/forced-commands-only/no "
735 "argument: %s", filename, linenum, arg);
736 if (*intptr == -1)
737 *intptr = value;
738 break;
739
740 case sIgnoreRhosts:
741 intptr = &options->ignore_rhosts;
5260325f 742parse_flag:
2717fa0f 743 arg = strdelim(&cp);
744 if (!arg || *arg == '\0')
745 fatal("%s line %d: missing yes/no argument.",
746 filename, linenum);
747 value = 0; /* silence compiler */
748 if (strcmp(arg, "yes") == 0)
749 value = 1;
750 else if (strcmp(arg, "no") == 0)
751 value = 0;
752 else
753 fatal("%s line %d: Bad yes/no argument: %s",
754 filename, linenum, arg);
d231781a 755 if (*activep && *intptr == -1)
2717fa0f 756 *intptr = value;
757 break;
758
759 case sIgnoreUserKnownHosts:
760 intptr = &options->ignore_user_known_hosts;
761 goto parse_flag;
762
2717fa0f 763 case sRhostsRSAAuthentication:
764 intptr = &options->rhosts_rsa_authentication;
765 goto parse_flag;
766
767 case sHostbasedAuthentication:
768 intptr = &options->hostbased_authentication;
769 goto parse_flag;
770
771 case sHostbasedUsesNameFromPacketOnly:
772 intptr = &options->hostbased_uses_name_from_packet_only;
773 goto parse_flag;
774
775 case sRSAAuthentication:
776 intptr = &options->rsa_authentication;
777 goto parse_flag;
778
779 case sPubkeyAuthentication:
780 intptr = &options->pubkey_authentication;
781 goto parse_flag;
d0ec7f42 782
2717fa0f 783 case sKerberosAuthentication:
784 intptr = &options->kerberos_authentication;
785 goto parse_flag;
5260325f 786
2717fa0f 787 case sKerberosOrLocalPasswd:
788 intptr = &options->kerberos_or_local_passwd;
789 goto parse_flag;
5260325f 790
2717fa0f 791 case sKerberosTicketCleanup:
792 intptr = &options->kerberos_ticket_cleanup;
793 goto parse_flag;
d0ec7f42 794
a1e30b47 795 case sKerberosGetAFSToken:
796 intptr = &options->kerberos_get_afs_token;
797 goto parse_flag;
798
7364bd04 799 case sGssAuthentication:
800 intptr = &options->gss_authentication;
801 goto parse_flag;
802
803 case sGssCleanupCreds:
804 intptr = &options->gss_cleanup_creds;
805 goto parse_flag;
806
2717fa0f 807 case sPasswordAuthentication:
808 intptr = &options->password_authentication;
809 goto parse_flag;
5260325f 810
2717fa0f 811 case sKbdInteractiveAuthentication:
812 intptr = &options->kbd_interactive_authentication;
813 goto parse_flag;
8002af61 814
2717fa0f 815 case sChallengeResponseAuthentication:
816 intptr = &options->challenge_response_authentication;
817 goto parse_flag;
8002af61 818
2717fa0f 819 case sPrintMotd:
820 intptr = &options->print_motd;
821 goto parse_flag;
5260325f 822
2717fa0f 823 case sPrintLastLog:
824 intptr = &options->print_lastlog;
825 goto parse_flag;
5260325f 826
2717fa0f 827 case sX11Forwarding:
828 intptr = &options->x11_forwarding;
829 goto parse_flag;
5260325f 830
2717fa0f 831 case sX11DisplayOffset:
832 intptr = &options->x11_display_offset;
833 goto parse_int;
8efc0c15 834
e6e573bd 835 case sX11UseLocalhost:
836 intptr = &options->x11_use_localhost;
837 goto parse_flag;
838
2717fa0f 839 case sXAuthLocation:
840 charptr = &options->xauth_location;
841 goto parse_filename;
5260325f 842
2717fa0f 843 case sStrictModes:
844 intptr = &options->strict_modes;
845 goto parse_flag;
5260325f 846
fd573618 847 case sTCPKeepAlive:
848 intptr = &options->tcp_keep_alive;
2717fa0f 849 goto parse_flag;
33de75a3 850
2717fa0f 851 case sEmptyPasswd:
852 intptr = &options->permit_empty_passwd;
853 goto parse_flag;
5260325f 854
f00bab84 855 case sPermitUserEnvironment:
856 intptr = &options->permit_user_env;
857 goto parse_flag;
858
2717fa0f 859 case sUseLogin:
860 intptr = &options->use_login;
861 goto parse_flag;
5260325f 862
636f76ca 863 case sCompression:
864 intptr = &options->compression;
07200973 865 arg = strdelim(&cp);
866 if (!arg || *arg == '\0')
867 fatal("%s line %d: missing yes/no/delayed "
868 "argument.", filename, linenum);
869 value = 0; /* silence compiler */
870 if (strcmp(arg, "delayed") == 0)
871 value = COMP_DELAYED;
872 else if (strcmp(arg, "yes") == 0)
873 value = COMP_ZLIB;
874 else if (strcmp(arg, "no") == 0)
875 value = COMP_NONE;
876 else
877 fatal("%s line %d: Bad yes/no/delayed "
878 "argument: %s", filename, linenum, arg);
879 if (*intptr == -1)
880 *intptr = value;
881 break;
636f76ca 882
2717fa0f 883 case sGatewayPorts:
884 intptr = &options->gateway_ports;
3867aa0a 885 arg = strdelim(&cp);
886 if (!arg || *arg == '\0')
887 fatal("%s line %d: missing yes/no/clientspecified "
888 "argument.", filename, linenum);
889 value = 0; /* silence compiler */
890 if (strcmp(arg, "clientspecified") == 0)
891 value = 2;
892 else if (strcmp(arg, "yes") == 0)
893 value = 1;
894 else if (strcmp(arg, "no") == 0)
895 value = 0;
896 else
897 fatal("%s line %d: Bad yes/no/clientspecified "
898 "argument: %s", filename, linenum, arg);
899 if (*intptr == -1)
900 *intptr = value;
901 break;
5260325f 902
c5a7d788 903 case sUseDNS:
904 intptr = &options->use_dns;
2717fa0f 905 goto parse_flag;
5260325f 906
2717fa0f 907 case sLogFacility:
908 intptr = (int *) &options->log_facility;
909 arg = strdelim(&cp);
910 value = log_facility_number(arg);
5eaf8578 911 if (value == SYSLOG_FACILITY_NOT_SET)
2717fa0f 912 fatal("%.200s line %d: unsupported log facility '%s'",
913 filename, linenum, arg ? arg : "<NONE>");
914 if (*intptr == -1)
915 *intptr = (SyslogFacility) value;
916 break;
917
918 case sLogLevel:
919 intptr = (int *) &options->log_level;
920 arg = strdelim(&cp);
921 value = log_level_number(arg);
5eaf8578 922 if (value == SYSLOG_LEVEL_NOT_SET)
2717fa0f 923 fatal("%.200s line %d: unsupported log level '%s'",
924 filename, linenum, arg ? arg : "<NONE>");
925 if (*intptr == -1)
926 *intptr = (LogLevel) value;
927 break;
928
929 case sAllowTcpForwarding:
930 intptr = &options->allow_tcp_forwarding;
931 goto parse_flag;
932
1853d1ef 933 case sUsePrivilegeSeparation:
934 intptr = &use_privsep;
935 goto parse_flag;
936
2717fa0f 937 case sAllowUsers:
938 while ((arg = strdelim(&cp)) && *arg != '\0') {
939 if (options->num_allow_users >= MAX_ALLOW_USERS)
940 fatal("%s line %d: too many allow users.",
941 filename, linenum);
7528d467 942 options->allow_users[options->num_allow_users++] =
943 xstrdup(arg);
2717fa0f 944 }
945 break;
a8be9f80 946
2717fa0f 947 case sDenyUsers:
948 while ((arg = strdelim(&cp)) && *arg != '\0') {
949 if (options->num_deny_users >= MAX_DENY_USERS)
950 fatal( "%s line %d: too many deny users.",
951 filename, linenum);
7528d467 952 options->deny_users[options->num_deny_users++] =
953 xstrdup(arg);
2717fa0f 954 }
955 break;
b2552997 956
2717fa0f 957 case sAllowGroups:
958 while ((arg = strdelim(&cp)) && *arg != '\0') {
959 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
960 fatal("%s line %d: too many allow groups.",
961 filename, linenum);
7528d467 962 options->allow_groups[options->num_allow_groups++] =
963 xstrdup(arg);
2717fa0f 964 }
965 break;
a8be9f80 966
2717fa0f 967 case sDenyGroups:
968 while ((arg = strdelim(&cp)) && *arg != '\0') {
969 if (options->num_deny_groups >= MAX_DENY_GROUPS)
970 fatal("%s line %d: too many deny groups.",
971 filename, linenum);
972 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
973 }
974 break;
38c295d6 975
2717fa0f 976 case sCiphers:
977 arg = strdelim(&cp);
978 if (!arg || *arg == '\0')
979 fatal("%s line %d: Missing argument.", filename, linenum);
980 if (!ciphers_valid(arg))
981 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
982 filename, linenum, arg ? arg : "<NONE>");
983 if (options->ciphers == NULL)
984 options->ciphers = xstrdup(arg);
985 break;
986
987 case sMacs:
988 arg = strdelim(&cp);
989 if (!arg || *arg == '\0')
990 fatal("%s line %d: Missing argument.", filename, linenum);
991 if (!mac_valid(arg))
992 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
993 filename, linenum, arg ? arg : "<NONE>");
994 if (options->macs == NULL)
995 options->macs = xstrdup(arg);
996 break;
997
998 case sProtocol:
999 intptr = &options->protocol;
1000 arg = strdelim(&cp);
1001 if (!arg || *arg == '\0')
1002 fatal("%s line %d: Missing argument.", filename, linenum);
1003 value = proto_spec(arg);
1004 if (value == SSH_PROTO_UNKNOWN)
1005 fatal("%s line %d: Bad protocol spec '%s'.",
184eed6a 1006 filename, linenum, arg ? arg : "<NONE>");
2717fa0f 1007 if (*intptr == SSH_PROTO_UNKNOWN)
1008 *intptr = value;
1009 break;
1010
1011 case sSubsystem:
1012 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1013 fatal("%s line %d: too many subsystems defined.",
184eed6a 1014 filename, linenum);
2717fa0f 1015 }
1016 arg = strdelim(&cp);
1017 if (!arg || *arg == '\0')
1018 fatal("%s line %d: Missing subsystem name.",
184eed6a 1019 filename, linenum);
d231781a 1020 if (!*activep) {
1021 arg = strdelim(&cp);
1022 break;
1023 }
2717fa0f 1024 for (i = 0; i < options->num_subsystems; i++)
1025 if (strcmp(arg, options->subsystem_name[i]) == 0)
1026 fatal("%s line %d: Subsystem '%s' already defined.",
184eed6a 1027 filename, linenum, arg);
2717fa0f 1028 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1029 arg = strdelim(&cp);
1030 if (!arg || *arg == '\0')
1031 fatal("%s line %d: Missing subsystem command.",
184eed6a 1032 filename, linenum);
2717fa0f 1033 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
d66ce1a1 1034
1035 /* Collect arguments (separate to executable) */
1036 p = xstrdup(arg);
1037 len = strlen(p) + 1;
1038 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1039 len += 1 + strlen(arg);
1040 p = xrealloc(p, 1, len);
1041 strlcat(p, " ", len);
1042 strlcat(p, arg, len);
1043 }
1044 options->subsystem_args[options->num_subsystems] = p;
2717fa0f 1045 options->num_subsystems++;
1046 break;
1047
1048 case sMaxStartups:
1049 arg = strdelim(&cp);
1050 if (!arg || *arg == '\0')
1051 fatal("%s line %d: Missing MaxStartups spec.",
184eed6a 1052 filename, linenum);
2717fa0f 1053 if ((n = sscanf(arg, "%d:%d:%d",
1054 &options->max_startups_begin,
1055 &options->max_startups_rate,
1056 &options->max_startups)) == 3) {
1057 if (options->max_startups_begin >
1058 options->max_startups ||
1059 options->max_startups_rate > 100 ||
1060 options->max_startups_rate < 1)
c345cf9d 1061 fatal("%s line %d: Illegal MaxStartups spec.",
97de229c 1062 filename, linenum);
2717fa0f 1063 } else if (n != 1)
1064 fatal("%s line %d: Illegal MaxStartups spec.",
1065 filename, linenum);
1066 else
1067 options->max_startups = options->max_startups_begin;
1068 break;
1069
af4bd935 1070 case sMaxAuthTries:
1071 intptr = &options->max_authtries;
1072 goto parse_int;
1073
2717fa0f 1074 case sBanner:
1075 charptr = &options->banner;
1076 goto parse_filename;
1077 /*
1078 * These options can contain %X options expanded at
1079 * connect time, so that you can specify paths like:
1080 *
1081 * AuthorizedKeysFile /etc/ssh_keys/%u
1082 */
1083 case sAuthorizedKeysFile:
1084 case sAuthorizedKeysFile2:
1085 charptr = (opcode == sAuthorizedKeysFile ) ?
1086 &options->authorized_keys_file :
1087 &options->authorized_keys_file2;
1088 goto parse_filename;
1089
1090 case sClientAliveInterval:
1091 intptr = &options->client_alive_interval;
1092 goto parse_time;
1093
1094 case sClientAliveCountMax:
1095 intptr = &options->client_alive_count_max;
1096 goto parse_int;
1097
61a2c1da 1098 case sAcceptEnv:
1099 while ((arg = strdelim(&cp)) && *arg != '\0') {
1100 if (strchr(arg, '=') != NULL)
1101 fatal("%s line %d: Invalid environment name.",
1102 filename, linenum);
1103 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1104 fatal("%s line %d: too many allow env.",
1105 filename, linenum);
d231781a 1106 if (!*activep)
1107 break;
61a2c1da 1108 options->accept_env[options->num_accept_env++] =
1109 xstrdup(arg);
1110 }
1111 break;
1112
d20f3c9e 1113 case sPermitTunnel:
1114 intptr = &options->permit_tun;
a4f24bf8 1115 arg = strdelim(&cp);
1116 if (!arg || *arg == '\0')
1117 fatal("%s line %d: Missing yes/point-to-point/"
1118 "ethernet/no argument.", filename, linenum);
1119 value = 0; /* silence compiler */
1120 if (strcasecmp(arg, "ethernet") == 0)
1121 value = SSH_TUNMODE_ETHERNET;
1122 else if (strcasecmp(arg, "point-to-point") == 0)
1123 value = SSH_TUNMODE_POINTOPOINT;
1124 else if (strcasecmp(arg, "yes") == 0)
1125 value = SSH_TUNMODE_YES;
1126 else if (strcasecmp(arg, "no") == 0)
1127 value = SSH_TUNMODE_NO;
1128 else
1129 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1130 "no argument: %s", filename, linenum, arg);
1131 if (*intptr == -1)
1132 *intptr = value;
1133 break;
d20f3c9e 1134
d231781a 1135 case sMatch:
1136 if (cmdline)
1137 fatal("Match directive not supported as a command-line "
1138 "option");
1139 value = match_cfg_line(&cp, linenum, user, host, address);
1140 if (value < 0)
1141 fatal("%s line %d: Bad Match condition", filename,
1142 linenum);
1143 *activep = value;
1144 break;
1145
2717fa0f 1146 case sDeprecated:
bbe88b6d 1147 logit("%s line %d: Deprecated option %s",
2717fa0f 1148 filename, linenum, arg);
1149 while (arg)
1150 arg = strdelim(&cp);
1151 break;
1152
a2144546 1153 case sUnsupported:
1154 logit("%s line %d: Unsupported option %s",
1155 filename, linenum, arg);
1156 while (arg)
1157 arg = strdelim(&cp);
1158 break;
1159
2717fa0f 1160 default:
1161 fatal("%s line %d: Missing handler for opcode %s (%d)",
1162 filename, linenum, arg, opcode);
1163 }
1164 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1165 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1166 filename, linenum, arg);
1167 return 0;
1168}
089fbbd2 1169
2717fa0f 1170/* Reads the server configuration file. */
5c53a31e 1171
2717fa0f 1172void
b9a549d7 1173load_server_config(const char *filename, Buffer *conf)
2717fa0f 1174{
b9a549d7 1175 char line[1024], *cp;
7528d467 1176 FILE *f;
2717fa0f 1177
b9a549d7 1178 debug2("%s: filename %s", __func__, filename);
1179 if ((f = fopen(filename, "r")) == NULL) {
2717fa0f 1180 perror(filename);
1181 exit(1);
1182 }
b9a549d7 1183 buffer_clear(conf);
2717fa0f 1184 while (fgets(line, sizeof(line), f)) {
b9a549d7 1185 /*
1186 * Trim out comments and strip whitespace
f2107e97 1187 * NB - preserve newlines, they are needed to reproduce
b9a549d7 1188 * line numbers later for error messages
1189 */
1190 if ((cp = strchr(line, '#')) != NULL)
1191 memcpy(cp, "\n", 2);
1192 cp = line + strspn(line, " \t\r");
1193
1194 buffer_append(conf, cp, strlen(cp));
8efc0c15 1195 }
b9a549d7 1196 buffer_append(conf, "\0", 1);
5260325f 1197 fclose(f);
b9a549d7 1198 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1199}
1200
1201void
d231781a 1202parse_server_match_config(ServerOptions *options, const char *user,
1203 const char *host, const char *address)
1204{
1205 ServerOptions mo;
1206
1207 initialize_server_options(&mo);
1208 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1209 copy_set_server_options(options, &mo);
1210}
1211
1212/* Copy any (supported) values that are set */
1213void
1214copy_set_server_options(ServerOptions *dst, ServerOptions *src)
1215{
1216 if (src->allow_tcp_forwarding != -1)
1217 dst->allow_tcp_forwarding = src->allow_tcp_forwarding;
1218 if (src->gateway_ports != -1)
1219 dst->gateway_ports = src->gateway_ports;
1220}
1221
1222void
1223parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1224 const char *user, const char *host, const char *address)
b9a549d7 1225{
d231781a 1226 int active, linenum, bad_options = 0;
16acb158 1227 char *cp, *obuf, *cbuf;
b9a549d7 1228
1229 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1230
16acb158 1231 obuf = cbuf = xstrdup(buffer_ptr(conf));
d231781a 1232 active = user ? 0 : 1;
861cc543 1233 linenum = 1;
f8cc7664 1234 while ((cp = strsep(&cbuf, "\n")) != NULL) {
b9a549d7 1235 if (process_server_config_line(options, cp, filename,
d231781a 1236 linenum++, &active, user, host, address) != 0)
b9a549d7 1237 bad_options++;
1238 }
16acb158 1239 xfree(obuf);
b7c70970 1240 if (bad_options > 0)
1241 fatal("%s: terminating, %d bad configuration options",
1242 filename, bad_options);
8efc0c15 1243}
This page took 0.48001 seconds and 5 git commands to generate.