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