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