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