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