]> andersk Git - gssapi-openssh.git/blame - openssh/servconf.c
Import of OpenSSH 4.4p1
[gssapi-openssh.git] / openssh / servconf.c
CommitLineData
9108f8d9 1/* $OpenBSD: servconf.c,v 1.165 2006/08/14 12:40:25 dtucker Exp $ */
3c0ef626 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 *
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".
11 */
12
13#include "includes.h"
3c0ef626 14
9108f8d9 15#include <sys/types.h>
16#include <sys/socket.h>
17
18#include <netdb.h>
19#include <pwd.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <signal.h>
24#include <unistd.h>
25#include <stdarg.h>
26
27#include "xmalloc.h"
3c0ef626 28#include "ssh.h"
29#include "log.h"
9108f8d9 30#include "buffer.h"
3c0ef626 31#include "servconf.h"
3c0ef626 32#include "compat.h"
33#include "pathnames.h"
3c0ef626 34#include "misc.h"
35#include "cipher.h"
9108f8d9 36#include "key.h"
3c0ef626 37#include "kex.h"
38#include "mac.h"
9108f8d9 39#include "match.h"
40#include "channels.h"
41#include "groupaccess.h"
3c0ef626 42
43static void add_listen_addr(ServerOptions *, char *, u_short);
44static void add_one_listen_addr(ServerOptions *, char *, u_short);
45
700318f3 46/* Use of privilege separation or not */
47extern int use_privsep;
9108f8d9 48extern Buffer cfg;
3c0ef626 49
50/* Initializes the server options to their default values. */
51
52void
53initialize_server_options(ServerOptions *options)
54{
55 memset(options, 0, sizeof(*options));
56
57 /* Portable-specific options */
0fff78ff 58 options->use_pam = -1;
3c0ef626 59
60 /* Standard Options */
61 options->num_ports = 0;
62 options->ports_from_cmdline = 0;
63 options->listen_addrs = NULL;
996d5e62 64 options->address_family = -1;
3c0ef626 65 options->num_host_key_files = 0;
66 options->pid_file = NULL;
67 options->server_key_bits = -1;
68 options->login_grace_time = -1;
69 options->key_regeneration_time = -1;
70 options->permit_root_login = PERMIT_NOT_SET;
71 options->ignore_rhosts = -1;
72 options->ignore_user_known_hosts = -1;
73 options->print_motd = -1;
74 options->print_lastlog = -1;
75 options->x11_forwarding = -1;
76 options->x11_display_offset = -1;
e9a17296 77 options->x11_use_localhost = -1;
3c0ef626 78 options->xauth_location = NULL;
79 options->strict_modes = -1;
cdd66111 80 options->tcp_keep_alive = -1;
e9a17296 81 options->log_facility = SYSLOG_FACILITY_NOT_SET;
82 options->log_level = SYSLOG_LEVEL_NOT_SET;
3c0ef626 83 options->rhosts_rsa_authentication = -1;
84 options->hostbased_authentication = -1;
85 options->hostbased_uses_name_from_packet_only = -1;
86 options->rsa_authentication = -1;
87 options->pubkey_authentication = -1;
3c0ef626 88 options->kerberos_authentication = -1;
89 options->kerberos_or_local_passwd = -1;
90 options->kerberos_ticket_cleanup = -1;
cdd66111 91 options->kerberos_get_afs_token = -1;
0fff78ff 92 options->gss_authentication=-1;
93 options->gss_cleanup_creds = -1;
3c0ef626 94 options->password_authentication = -1;
95 options->kbd_interactive_authentication = -1;
96 options->challenge_response_authentication = -1;
97 options->permit_empty_passwd = -1;
41b2f314 98 options->permit_user_env = -1;
3c0ef626 99 options->use_login = -1;
f5799ae1 100 options->compression = -1;
3c0ef626 101 options->allow_tcp_forwarding = -1;
102 options->num_allow_users = 0;
103 options->num_deny_users = 0;
104 options->num_allow_groups = 0;
105 options->num_deny_groups = 0;
106 options->ciphers = NULL;
107 options->macs = NULL;
108 options->protocol = SSH_PROTO_UNKNOWN;
109 options->gateway_ports = -1;
110 options->num_subsystems = 0;
111 options->max_startups_begin = -1;
112 options->max_startups_rate = -1;
113 options->max_startups = -1;
c9f39d2c 114 options->max_authtries = -1;
3c0ef626 115 options->banner = NULL;
0fff78ff 116 options->use_dns = -1;
3c0ef626 117 options->client_alive_interval = -1;
118 options->client_alive_count_max = -1;
119 options->authorized_keys_file = NULL;
120 options->authorized_keys_file2 = NULL;
c9f39d2c 121 options->num_accept_env = 0;
2c06c99b 122 options->permit_tun = -1;
9108f8d9 123 options->num_permitted_opens = -1;
124 options->adm_forced_command = NULL;
3c0ef626 125}
126
127void
128fill_default_server_options(ServerOptions *options)
129{
130 /* Portable-specific options */
0fff78ff 131 if (options->use_pam == -1)
acc3d05e 132 options->use_pam = 0;
3c0ef626 133
134 /* Standard Options */
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)
e9a17296 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 }
3c0ef626 148 }
149 if (options->num_ports == 0)
150 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
151 if (options->listen_addrs == NULL)
152 add_listen_addr(options, NULL, 0);
153 if (options->pid_file == NULL)
154 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
155 if (options->server_key_bits == -1)
156 options->server_key_bits = 768;
157 if (options->login_grace_time == -1)
41b2f314 158 options->login_grace_time = 120;
3c0ef626 159 if (options->key_regeneration_time == -1)
160 options->key_regeneration_time = 3600;
161 if (options->permit_root_login == PERMIT_NOT_SET)
162 options->permit_root_login = PERMIT_YES;
163 if (options->ignore_rhosts == -1)
164 options->ignore_rhosts = 1;
165 if (options->ignore_user_known_hosts == -1)
166 options->ignore_user_known_hosts = 0;
167 if (options->print_motd == -1)
168 options->print_motd = 1;
169 if (options->print_lastlog == -1)
170 options->print_lastlog = 1;
171 if (options->x11_forwarding == -1)
172 options->x11_forwarding = 0;
173 if (options->x11_display_offset == -1)
174 options->x11_display_offset = 10;
e9a17296 175 if (options->x11_use_localhost == -1)
176 options->x11_use_localhost = 1;
3c0ef626 177 if (options->xauth_location == NULL)
178 options->xauth_location = _PATH_XAUTH;
3c0ef626 179 if (options->strict_modes == -1)
180 options->strict_modes = 1;
cdd66111 181 if (options->tcp_keep_alive == -1)
182 options->tcp_keep_alive = 1;
e9a17296 183 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
3c0ef626 184 options->log_facility = SYSLOG_FACILITY_AUTH;
e9a17296 185 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
3c0ef626 186 options->log_level = SYSLOG_LEVEL_INFO;
3c0ef626 187 if (options->rhosts_rsa_authentication == -1)
188 options->rhosts_rsa_authentication = 0;
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;
193 if (options->rsa_authentication == -1)
194 options->rsa_authentication = 1;
195 if (options->pubkey_authentication == -1)
196 options->pubkey_authentication = 1;
3c0ef626 197 if (options->kerberos_authentication == -1)
700318f3 198 options->kerberos_authentication = 0;
3c0ef626 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;
cdd66111 203 if (options->kerberos_get_afs_token == -1)
204 options->kerberos_get_afs_token = 0;
0fff78ff 205 if (options->gss_authentication == -1)
206 options->gss_authentication = 0;
207 if (options->gss_cleanup_creds == -1)
208 options->gss_cleanup_creds = 1;
3c0ef626 209 if (options->password_authentication == -1)
210 options->password_authentication = 1;
211 if (options->kbd_interactive_authentication == -1)
212 options->kbd_interactive_authentication = 0;
213 if (options->challenge_response_authentication == -1)
214 options->challenge_response_authentication = 1;
215 if (options->permit_empty_passwd == -1)
216 options->permit_empty_passwd = 0;
41b2f314 217 if (options->permit_user_env == -1)
218 options->permit_user_env = 0;
3c0ef626 219 if (options->use_login == -1)
220 options->use_login = 0;
f5799ae1 221 if (options->compression == -1)
665a873d 222 options->compression = COMP_DELAYED;
3c0ef626 223 if (options->allow_tcp_forwarding == -1)
224 options->allow_tcp_forwarding = 1;
225 if (options->gateway_ports == -1)
226 options->gateway_ports = 0;
227 if (options->max_startups == -1)
228 options->max_startups = 10;
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;
c9f39d2c 233 if (options->max_authtries == -1)
234 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
0fff78ff 235 if (options->use_dns == -1)
236 options->use_dns = 1;
3c0ef626 237 if (options->client_alive_interval == -1)
e9a17296 238 options->client_alive_interval = 0;
3c0ef626 239 if (options->client_alive_count_max == -1)
240 options->client_alive_count_max = 3;
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;
2c06c99b 250 if (options->permit_tun == -1)
251 options->permit_tun = SSH_TUNMODE_NO;
700318f3 252
f5799ae1 253 /* Turn privilege separation on by default */
700318f3 254 if (use_privsep == -1)
f5799ae1 255 use_privsep = 1;
256
41b2f314 257#ifndef HAVE_MMAP
f5799ae1 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
3c0ef626 266}
267
268/* Keyword tokens. */
269typedef enum {
270 sBadOption, /* == unknown option */
271 /* Portable-specific options */
0fff78ff 272 sUsePAM,
3c0ef626 273 /* Standard Options */
274 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
275 sPermitRootLogin, sLogFacility, sLogLevel,
0fff78ff 276 sRhostsRSAAuthentication, sRSAAuthentication,
3c0ef626 277 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
cdd66111 278 sKerberosGetAFSToken,
0fff78ff 279 sKerberosTgtPassing, sChallengeResponseAuthentication,
996d5e62 280 sPasswordAuthentication, sKbdInteractiveAuthentication,
281 sListenAddress, sAddressFamily,
3c0ef626 282 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
e9a17296 283 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
cdd66111 284 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
41b2f314 285 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
3c0ef626 286 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
287 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
c9f39d2c 288 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
289 sMaxStartups, sMaxAuthTries,
0fff78ff 290 sBanner, sUseDNS, sHostbasedAuthentication,
e9a17296 291 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
3c0ef626 292 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
2c06c99b 293 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
9108f8d9 294 sMatch, sPermitOpen, sForceCommand,
700318f3 295 sUsePrivilegeSeparation,
0fff78ff 296 sDeprecated, sUnsupported
3c0ef626 297} ServerOpCodes;
298
9108f8d9 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
3c0ef626 303/* Textual representation of the tokens. */
304static struct {
305 const char *name;
306 ServerOpCodes opcode;
9108f8d9 307 u_int flags;
3c0ef626 308} keywords[] = {
309 /* Portable-specific options */
0fff78ff 310#ifdef USE_PAM
9108f8d9 311 { "usepam", sUsePAM, SSHCFG_GLOBAL },
0fff78ff 312#else
9108f8d9 313 { "usepam", sUnsupported, SSHCFG_GLOBAL },
0fff78ff 314#endif
9108f8d9 315 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
3c0ef626 316 /* Standard Options */
9108f8d9 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 */
0fff78ff 334#ifdef KRB5
9108f8d9 335 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL },
336 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
337 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
cdd66111 338#ifdef USE_AFS
9108f8d9 339 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
cdd66111 340#else
9108f8d9 341 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
cdd66111 342#endif
0fff78ff 343#else
9108f8d9 344 { "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL },
345 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
346 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
347 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
3c0ef626 348#endif
9108f8d9 349 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
350 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
0fff78ff 351#ifdef GSSAPI
9108f8d9 352 { "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
353 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
0fff78ff 354#else
9108f8d9 355 { "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
356 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
3c0ef626 357#endif
9108f8d9 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 },
369 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
370 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
371 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
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 },
403 { "match", sMatch, SSHCFG_ALL },
404 { "permitopen", sPermitOpen, SSHCFG_ALL },
405 { "forcecommand", sForceCommand, SSHCFG_ALL },
406 { NULL, sBadOption, 0 }
3c0ef626 407};
408
409/*
410 * Returns the number of the token pointed to by cp or sBadOption.
411 */
412
413static ServerOpCodes
414parse_token(const char *cp, const char *filename,
9108f8d9 415 int linenum, u_int *flags)
3c0ef626 416{
417 u_int i;
418
419 for (i = 0; keywords[i].name; i++)
9108f8d9 420 if (strcasecmp(cp, keywords[i].name) == 0) {
421 *flags = keywords[i].flags;
3c0ef626 422 return keywords[i].opcode;
9108f8d9 423 }
3c0ef626 424
425 error("%s: line %d: Bad configuration option: %s",
426 filename, linenum, cp);
427 return sBadOption;
428}
429
430static void
431add_listen_addr(ServerOptions *options, char *addr, u_short port)
432{
665a873d 433 u_int i;
3c0ef626 434
435 if (options->num_ports == 0)
436 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
996d5e62 437 if (options->address_family == -1)
438 options->address_family = AF_UNSPEC;
3c0ef626 439 if (port == 0)
440 for (i = 0; i < options->num_ports; i++)
441 add_one_listen_addr(options, addr, options->ports[i]);
442 else
443 add_one_listen_addr(options, addr, port);
444}
445
446static void
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));
996d5e62 454 hints.ai_family = options->address_family;
3c0ef626 455 hints.ai_socktype = SOCK_STREAM;
456 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
680cee3b 457 snprintf(strport, sizeof strport, "%u", port);
3c0ef626 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;
466}
467
9108f8d9 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
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
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);
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 }
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
616#define WHITESPACE " \t\r\n"
617
e9a17296 618int
619process_server_config_line(ServerOptions *options, char *line,
9108f8d9 620 const char *filename, int linenum, int *activep, const char *user,
621 const char *host, const char *address)
3c0ef626 622{
3c0ef626 623 char *cp, **charptr, *arg, *p;
9108f8d9 624 int cmdline = 0, *intptr, value, n;
3c0ef626 625 ServerOpCodes opcode;
996d5e62 626 u_short port;
9108f8d9 627 u_int i, flags = 0;
628 size_t len;
3c0ef626 629
e9a17296 630 cp = line;
9108f8d9 631 if ((arg = strdelim(&cp)) == NULL)
632 return 0;
e9a17296 633 /* Ignore leading whitespace */
634 if (*arg == '\0')
3c0ef626 635 arg = strdelim(&cp);
e9a17296 636 if (!arg || !*arg || *arg == '#')
637 return 0;
638 intptr = NULL;
639 charptr = NULL;
9108f8d9 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
e9a17296 659 switch (opcode) {
660 /* Portable-specific options */
0fff78ff 661 case sUsePAM:
662 intptr = &options->use_pam;
e9a17296 663 goto parse_flag;
3c0ef626 664
e9a17296 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 "
674 "ListenAddress.", filename, linenum);
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;
3c0ef626 690parse_int:
e9a17296 691 arg = strdelim(&cp);
692 if (!arg || *arg == '\0')
693 fatal("%s line %d: missing integer value.",
694 filename, linenum);
695 value = atoi(arg);
9108f8d9 696 if (*activep && *intptr == -1)
e9a17296 697 *intptr = value;
698 break;
699
700 case sLoginGraceTime:
701 intptr = &options->login_grace_time;
3c0ef626 702parse_time:
e9a17296 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);
996d5e62 720 if (arg == NULL || *arg == '\0')
721 fatal("%s line %d: missing address",
e9a17296 722 filename, linenum);
665a873d 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 }
996d5e62 729 p = hpdelim(&arg);
730 if (p == NULL)
731 fatal("%s line %d: bad address:port usage",
e9a17296 732 filename, linenum);
996d5e62 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
741 break;
742
743 case sAddressFamily:
744 arg = strdelim(&cp);
665a873d 745 if (!arg || *arg == '\0')
746 fatal("%s line %d: missing address family.",
747 filename, linenum);
996d5e62 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;
e9a17296 763 break;
764
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];
3c0ef626 771parse_filename:
e9a17296 772 arg = strdelim(&cp);
773 if (!arg || *arg == '\0')
774 fatal("%s line %d: missing file name.",
775 filename, linenum);
9108f8d9 776 if (*activep && *charptr == NULL) {
e9a17296 777 *charptr = tilde_expand_filename(arg, getuid());
778 /* increase optional counter */
779 if (intptr != NULL)
780 *intptr = *intptr + 1;
781 }
782 break;
3c0ef626 783
e9a17296 784 case sPidFile:
785 charptr = &options->pid_file;
786 goto parse_filename;
3c0ef626 787
e9a17296 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;
3c0ef626 814parse_flag:
e9a17296 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);
9108f8d9 827 if (*activep && *intptr == -1)
e9a17296 828 *intptr = value;
829 break;
830
831 case sIgnoreUserKnownHosts:
832 intptr = &options->ignore_user_known_hosts;
833 goto parse_flag;
834
e9a17296 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;
0fff78ff 854
e9a17296 855 case sKerberosAuthentication:
856 intptr = &options->kerberos_authentication;
857 goto parse_flag;
3c0ef626 858
e9a17296 859 case sKerberosOrLocalPasswd:
860 intptr = &options->kerberos_or_local_passwd;
861 goto parse_flag;
3c0ef626 862
e9a17296 863 case sKerberosTicketCleanup:
864 intptr = &options->kerberos_ticket_cleanup;
865 goto parse_flag;
0fff78ff 866
cdd66111 867 case sKerberosGetAFSToken:
868 intptr = &options->kerberos_get_afs_token;
869 goto parse_flag;
870
0fff78ff 871 case sGssAuthentication:
872 intptr = &options->gss_authentication;
e9a17296 873 goto parse_flag;
0fff78ff 874
875 case sGssCleanupCreds:
876 intptr = &options->gss_cleanup_creds;
e9a17296 877 goto parse_flag;
3c0ef626 878
e9a17296 879 case sPasswordAuthentication:
880 intptr = &options->password_authentication;
881 goto parse_flag;
3c0ef626 882
e9a17296 883 case sKbdInteractiveAuthentication:
884 intptr = &options->kbd_interactive_authentication;
885 goto parse_flag;
3c0ef626 886
e9a17296 887 case sChallengeResponseAuthentication:
888 intptr = &options->challenge_response_authentication;
889 goto parse_flag;
3c0ef626 890
e9a17296 891 case sPrintMotd:
892 intptr = &options->print_motd;
893 goto parse_flag;
3c0ef626 894
e9a17296 895 case sPrintLastLog:
896 intptr = &options->print_lastlog;
897 goto parse_flag;
3c0ef626 898
e9a17296 899 case sX11Forwarding:
900 intptr = &options->x11_forwarding;
901 goto parse_flag;
3c0ef626 902
e9a17296 903 case sX11DisplayOffset:
904 intptr = &options->x11_display_offset;
905 goto parse_int;
3c0ef626 906
e9a17296 907 case sX11UseLocalhost:
908 intptr = &options->x11_use_localhost;
909 goto parse_flag;
3c0ef626 910
e9a17296 911 case sXAuthLocation:
912 charptr = &options->xauth_location;
913 goto parse_filename;
3c0ef626 914
e9a17296 915 case sStrictModes:
916 intptr = &options->strict_modes;
917 goto parse_flag;
3c0ef626 918
cdd66111 919 case sTCPKeepAlive:
920 intptr = &options->tcp_keep_alive;
e9a17296 921 goto parse_flag;
3c0ef626 922
e9a17296 923 case sEmptyPasswd:
924 intptr = &options->permit_empty_passwd;
925 goto parse_flag;
3c0ef626 926
41b2f314 927 case sPermitUserEnvironment:
928 intptr = &options->permit_user_env;
929 goto parse_flag;
930
e9a17296 931 case sUseLogin:
932 intptr = &options->use_login;
933 goto parse_flag;
3c0ef626 934
f5799ae1 935 case sCompression:
936 intptr = &options->compression;
665a873d 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;
f5799ae1 954
e9a17296 955 case sGatewayPorts:
956 intptr = &options->gateway_ports;
996d5e62 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;
3c0ef626 974
0fff78ff 975 case sUseDNS:
976 intptr = &options->use_dns;
e9a17296 977 goto parse_flag;
3c0ef626 978
e9a17296 979 case sLogFacility:
980 intptr = (int *) &options->log_facility;
981 arg = strdelim(&cp);
982 value = log_facility_number(arg);
983 if (value == SYSLOG_FACILITY_NOT_SET)
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);
994 if (value == SYSLOG_LEVEL_NOT_SET)
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
700318f3 1005 case sUsePrivilegeSeparation:
1006 intptr = &use_privsep;
1007 goto parse_flag;
1008
e9a17296 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);
680cee3b 1014 options->allow_users[options->num_allow_users++] =
1015 xstrdup(arg);
e9a17296 1016 }
1017 break;
3c0ef626 1018
e9a17296 1019 case sDenyUsers:
1020 while ((arg = strdelim(&cp)) && *arg != '\0') {
1021 if (options->num_deny_users >= MAX_DENY_USERS)
9108f8d9 1022 fatal("%s line %d: too many deny users.",
e9a17296 1023 filename, linenum);
680cee3b 1024 options->deny_users[options->num_deny_users++] =
1025 xstrdup(arg);
e9a17296 1026 }
1027 break;
3c0ef626 1028
e9a17296 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);
680cee3b 1034 options->allow_groups[options->num_allow_groups++] =
1035 xstrdup(arg);
e9a17296 1036 }
1037 break;
3c0ef626 1038
e9a17296 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;
1047
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'.",
1078 filename, linenum, arg ? arg : "<NONE>");
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.",
1086 filename, linenum);
1087 }
1088 arg = strdelim(&cp);
1089 if (!arg || *arg == '\0')
1090 fatal("%s line %d: Missing subsystem name.",
1091 filename, linenum);
9108f8d9 1092 if (!*activep) {
1093 arg = strdelim(&cp);
1094 break;
1095 }
e9a17296 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.",
1099 filename, linenum, arg);
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.",
1104 filename, linenum);
1105 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
9108f8d9 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;
e9a17296 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.",
1124 filename, linenum);
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)
3c0ef626 1133 fatal("%s line %d: Illegal MaxStartups spec.",
1134 filename, linenum);
e9a17296 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
c9f39d2c 1142 case sMaxAuthTries:
1143 intptr = &options->max_authtries;
1144 goto parse_int;
1145
e9a17296 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:
9108f8d9 1157 charptr = (opcode == sAuthorizedKeysFile) ?
e9a17296 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
c9f39d2c 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);
9108f8d9 1178 if (!*activep)
1179 break;
c9f39d2c 1180 options->accept_env[options->num_accept_env++] =
1181 xstrdup(arg);
1182 }
1183 break;
1184
2c06c99b 1185 case sPermitTunnel:
1186 intptr = &options->permit_tun;
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;
1206
9108f8d9 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
1218 case sPermitOpen:
1219 arg = strdelim(&cp);
1220 if (!arg || *arg == '\0')
1221 fatal("%s line %d: missing PermitOpen specification",
1222 filename, linenum);
1223 if (strcmp(arg, "any") == 0) {
1224 if (*activep) {
1225 channel_clear_adm_permitted_opens();
1226 options->num_permitted_opens = 0;
1227 }
1228 break;
1229 }
1230 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1231 p = hpdelim(&arg);
1232 if (p == NULL)
1233 fatal("%s line %d: missing host in PermitOpen",
1234 filename, linenum);
1235 p = cleanhostname(p);
1236 if (arg == NULL || (port = a2port(arg)) == 0)
1237 fatal("%s line %d: bad port number in "
1238 "PermitOpen", filename, linenum);
1239 if (*activep && options->num_permitted_opens == -1) {
1240 channel_clear_adm_permitted_opens();
1241 options->num_permitted_opens =
1242 channel_add_adm_permitted_opens(p, port);
1243 }
1244 }
1245 break;
1246
1247 case sForceCommand:
1248 if (cp == NULL)
1249 fatal("%.200s line %d: Missing argument.", filename,
1250 linenum);
1251 len = strspn(cp, WHITESPACE);
1252 if (*activep && options->adm_forced_command == NULL)
1253 options->adm_forced_command = xstrdup(cp + len);
1254 return 0;
1255
e9a17296 1256 case sDeprecated:
0fff78ff 1257 logit("%s line %d: Deprecated option %s",
1258 filename, linenum, arg);
1259 while (arg)
1260 arg = strdelim(&cp);
1261 break;
1262
1263 case sUnsupported:
1264 logit("%s line %d: Unsupported option %s",
e9a17296 1265 filename, linenum, arg);
1266 while (arg)
1267 arg = strdelim(&cp);
1268 break;
1269
1270 default:
1271 fatal("%s line %d: Missing handler for opcode %s (%d)",
1272 filename, linenum, arg, opcode);
1273 }
1274 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1275 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1276 filename, linenum, arg);
1277 return 0;
1278}
3c0ef626 1279
e9a17296 1280/* Reads the server configuration file. */
3c0ef626 1281
e9a17296 1282void
c9f39d2c 1283load_server_config(const char *filename, Buffer *conf)
e9a17296 1284{
c9f39d2c 1285 char line[1024], *cp;
680cee3b 1286 FILE *f;
e9a17296 1287
c9f39d2c 1288 debug2("%s: filename %s", __func__, filename);
1289 if ((f = fopen(filename, "r")) == NULL) {
e9a17296 1290 perror(filename);
1291 exit(1);
1292 }
c9f39d2c 1293 buffer_clear(conf);
e9a17296 1294 while (fgets(line, sizeof(line), f)) {
c9f39d2c 1295 /*
1296 * Trim out comments and strip whitespace
1297 * NB - preserve newlines, they are needed to reproduce
1298 * line numbers later for error messages
1299 */
1300 if ((cp = strchr(line, '#')) != NULL)
1301 memcpy(cp, "\n", 2);
1302 cp = line + strspn(line, " \t\r");
1303
1304 buffer_append(conf, cp, strlen(cp));
3c0ef626 1305 }
c9f39d2c 1306 buffer_append(conf, "\0", 1);
3c0ef626 1307 fclose(f);
c9f39d2c 1308 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1309}
1310
1311void
9108f8d9 1312parse_server_match_config(ServerOptions *options, const char *user,
1313 const char *host, const char *address)
1314{
1315 ServerOptions mo;
1316
1317 initialize_server_options(&mo);
1318 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1319 copy_set_server_options(options, &mo);
1320}
1321
1322/* Copy any (supported) values that are set */
1323void
1324copy_set_server_options(ServerOptions *dst, ServerOptions *src)
1325{
1326 if (src->allow_tcp_forwarding != -1)
1327 dst->allow_tcp_forwarding = src->allow_tcp_forwarding;
1328 if (src->gateway_ports != -1)
1329 dst->gateway_ports = src->gateway_ports;
1330 if (src->adm_forced_command != NULL) {
1331 if (dst->adm_forced_command != NULL)
1332 xfree(dst->adm_forced_command);
1333 dst->adm_forced_command = src->adm_forced_command;
1334 }
1335 if (src->x11_display_offset != -1)
1336 dst->x11_display_offset = src->x11_display_offset;
1337 if (src->x11_forwarding != -1)
1338 dst->x11_forwarding = src->x11_forwarding;
1339 if (src->x11_use_localhost != -1)
1340 dst->x11_use_localhost = src->x11_use_localhost;
1341}
1342
1343void
1344parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1345 const char *user, const char *host, const char *address)
c9f39d2c 1346{
9108f8d9 1347 int active, linenum, bad_options = 0;
c9f39d2c 1348 char *cp, *obuf, *cbuf;
1349
1350 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1351
1352 obuf = cbuf = xstrdup(buffer_ptr(conf));
9108f8d9 1353 active = user ? 0 : 1;
c9f39d2c 1354 linenum = 1;
dec6d9fe 1355 while ((cp = strsep(&cbuf, "\n")) != NULL) {
c9f39d2c 1356 if (process_server_config_line(options, cp, filename,
9108f8d9 1357 linenum++, &active, user, host, address) != 0)
c9f39d2c 1358 bad_options++;
1359 }
1360 xfree(obuf);
3c0ef626 1361 if (bad_options > 0)
1362 fatal("%s: terminating, %d bad configuration options",
1363 filename, bad_options);
1364}
This page took 0.263513 seconds and 5 git commands to generate.