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