sshd - Change options defaults to be more secure
[dragonfly.git] / crypto / openssh / servconf.c
CommitLineData
99e85e0d 1
664f4763 2/* $OpenBSD: servconf.c,v 1.350 2019/03/25 22:33:44 djm Exp $ */
16c343f1
PA
3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose. Any derived versions of this
9 * software must be clearly marked as such, and if the derived work is
10 * incompatible with the protocol description in the RFC file, it must be
11 * called by a name other than "ssh" or "Secure Shell".
12 */
13
14#include "includes.h"
15
16#include <sys/types.h>
17#include <sys/socket.h>
664f4763 18#ifdef HAVE_SYS_SYSCTL_H
19#include <sys/sysctl.h>
20#endif
16c343f1 21
9f304aaf
PA
22#include <netinet/in.h>
23#include <netinet/in_systm.h>
24#include <netinet/ip.h>
664f4763 25#ifdef HAVE_NET_ROUTE_H
26#include <net/route.h>
27#endif
9f304aaf 28
36e94dc5 29#include <ctype.h>
16c343f1
PA
30#include <netdb.h>
31#include <pwd.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <signal.h>
36#include <unistd.h>
e9778795 37#include <limits.h>
16c343f1 38#include <stdarg.h>
3b69e377 39#include <errno.h>
36e94dc5
PA
40#ifdef HAVE_UTIL_H
41#include <util.h>
42#endif
16c343f1 43
3b69e377 44#include "openbsd-compat/sys-queue.h"
16c343f1
PA
45#include "xmalloc.h"
46#include "ssh.h"
47#include "log.h"
664f4763 48#include "sshbuf.h"
36e94dc5 49#include "misc.h"
16c343f1
PA
50#include "servconf.h"
51#include "compat.h"
52#include "pathnames.h"
16c343f1 53#include "cipher.h"
664f4763 54#include "sshkey.h"
16c343f1
PA
55#include "kex.h"
56#include "mac.h"
57#include "match.h"
58#include "channels.h"
59#include "groupaccess.h"
99e85e0d
PA
60#include "canohost.h"
61#include "packet.h"
664f4763 62#include "ssherr.h"
36e94dc5
PA
63#include "hostfile.h"
64#include "auth.h"
e9778795
PA
65#include "myproposal.h"
66#include "digest.h"
16c343f1 67
664f4763 68static void add_listen_addr(ServerOptions *, const char *,
69 const char *, int);
70static void add_one_listen_addr(ServerOptions *, const char *,
71 const char *, int);
16c343f1
PA
72
73/* Use of privilege separation or not */
74extern int use_privsep;
664f4763 75extern struct sshbuf *cfg;
16c343f1
PA
76
77/* Initializes the server options to their default values. */
78
79void
80initialize_server_options(ServerOptions *options)
81{
82 memset(options, 0, sizeof(*options));
83
84 /* Portable-specific options */
85 options->use_pam = -1;
86
87 /* Standard Options */
88 options->num_ports = 0;
89 options->ports_from_cmdline = 0;
e9778795
PA
90 options->queued_listen_addrs = NULL;
91 options->num_queued_listens = 0;
16c343f1 92 options->listen_addrs = NULL;
664f4763 93 options->num_listen_addrs = 0;
16c343f1 94 options->address_family = -1;
664f4763 95 options->routing_domain = NULL;
16c343f1 96 options->num_host_key_files = 0;
856ea928 97 options->num_host_cert_files = 0;
36e94dc5 98 options->host_key_agent = NULL;
16c343f1 99 options->pid_file = NULL;
16c343f1 100 options->login_grace_time = -1;
16c343f1
PA
101 options->permit_root_login = PERMIT_NOT_SET;
102 options->ignore_rhosts = -1;
103 options->ignore_user_known_hosts = -1;
104 options->print_motd = -1;
105 options->print_lastlog = -1;
106 options->x11_forwarding = -1;
107 options->x11_display_offset = -1;
108 options->x11_use_localhost = -1;
36e94dc5
PA
109 options->permit_tty = -1;
110 options->permit_user_rc = -1;
16c343f1
PA
111 options->xauth_location = NULL;
112 options->strict_modes = -1;
113 options->tcp_keep_alive = -1;
114 options->log_facility = SYSLOG_FACILITY_NOT_SET;
115 options->log_level = SYSLOG_LEVEL_NOT_SET;
16c343f1
PA
116 options->hostbased_authentication = -1;
117 options->hostbased_uses_name_from_packet_only = -1;
e9778795
PA
118 options->hostbased_key_types = NULL;
119 options->hostkeyalgorithms = NULL;
16c343f1 120 options->pubkey_authentication = -1;
e9778795 121 options->pubkey_key_types = NULL;
16c343f1
PA
122 options->kerberos_authentication = -1;
123 options->kerberos_or_local_passwd = -1;
124 options->kerberos_ticket_cleanup = -1;
125 options->kerberos_get_afs_token = -1;
126 options->gss_authentication=-1;
127 options->gss_cleanup_creds = -1;
e9778795 128 options->gss_strict_acceptor = -1;
16c343f1
PA
129 options->password_authentication = -1;
130 options->kbd_interactive_authentication = -1;
131 options->challenge_response_authentication = -1;
132 options->permit_empty_passwd = -1;
133 options->permit_user_env = -1;
664f4763 134 options->permit_user_env_whitelist = NULL;
16c343f1 135 options->compression = -1;
36e94dc5
PA
136 options->rekey_limit = -1;
137 options->rekey_interval = -1;
16c343f1 138 options->allow_tcp_forwarding = -1;
36e94dc5 139 options->allow_streamlocal_forwarding = -1;
3b69e377 140 options->allow_agent_forwarding = -1;
16c343f1
PA
141 options->num_allow_users = 0;
142 options->num_deny_users = 0;
143 options->num_allow_groups = 0;
144 options->num_deny_groups = 0;
145 options->ciphers = NULL;
146 options->macs = NULL;
9f304aaf 147 options->kex_algorithms = NULL;
664f4763 148 options->ca_sign_algorithms = NULL;
36e94dc5
PA
149 options->fwd_opts.gateway_ports = -1;
150 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
151 options->fwd_opts.streamlocal_bind_unlink = -1;
16c343f1
PA
152 options->num_subsystems = 0;
153 options->max_startups_begin = -1;
154 options->max_startups_rate = -1;
155 options->max_startups = -1;
156 options->max_authtries = -1;
3b69e377 157 options->max_sessions = -1;
16c343f1
PA
158 options->banner = NULL;
159 options->use_dns = -1;
160 options->client_alive_interval = -1;
161 options->client_alive_count_max = -1;
1c188a7f 162 options->num_authkeys_files = 0;
16c343f1 163 options->num_accept_env = 0;
664f4763 164 options->num_setenv = 0;
16c343f1 165 options->permit_tun = -1;
ce74baca 166 options->permitted_opens = NULL;
664f4763 167 options->permitted_listens = NULL;
16c343f1
PA
168 options->adm_forced_command = NULL;
169 options->chroot_directory = NULL;
36e94dc5
PA
170 options->authorized_keys_command = NULL;
171 options->authorized_keys_command_user = NULL;
856ea928
PA
172 options->revoked_keys_file = NULL;
173 options->trusted_user_ca_keys = NULL;
174 options->authorized_principals_file = NULL;
e9778795
PA
175 options->authorized_principals_command = NULL;
176 options->authorized_principals_command_user = NULL;
9f304aaf
PA
177 options->ip_qos_interactive = -1;
178 options->ip_qos_bulk = -1;
99e85e0d 179 options->version_addendum = NULL;
e9778795 180 options->fingerprint_hash = -1;
ce74baca
MD
181 options->disable_forwarding = -1;
182 options->expose_userauth_info = -1;
e9778795
PA
183}
184
185/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
186static int
187option_clear_or_none(const char *o)
188{
189 return o == NULL || strcasecmp(o, "none") == 0;
190}
191
192static void
193assemble_algorithms(ServerOptions *o)
194{
664f4763 195 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
196 int r;
197
198 all_cipher = cipher_alg_list(',', 0);
199 all_mac = mac_alg_list(',');
200 all_kex = kex_alg_list(',');
201 all_key = sshkey_alg_list(0, 0, 1, ',');
202 all_sig = sshkey_alg_list(0, 1, 1, ',');
203#define ASSEMBLE(what, defaults, all) \
204 do { \
205 if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
206 fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
207 } while (0)
208 ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);
209 ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);
210 ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
211 ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, all_key);
212 ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
213 ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
214 ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
215#undef ASSEMBLE
216 free(all_cipher);
217 free(all_mac);
218 free(all_kex);
219 free(all_key);
220 free(all_sig);
221}
222
223static void
224array_append2(const char *file, const int line, const char *directive,
225 char ***array, int **iarray, u_int *lp, const char *s, int i)
226{
227
228 if (*lp >= INT_MAX)
229 fatal("%s line %d: Too many %s entries", file, line, directive);
230
231 if (iarray != NULL) {
232 *iarray = xrecallocarray(*iarray, *lp, *lp + 1,
233 sizeof(**iarray));
234 (*iarray)[*lp] = i;
235 }
236
237 *array = xrecallocarray(*array, *lp, *lp + 1, sizeof(**array));
238 (*array)[*lp] = xstrdup(s);
239 (*lp)++;
240}
241
242static void
243array_append(const char *file, const int line, const char *directive,
244 char ***array, u_int *lp, const char *s)
245{
246 array_append2(file, line, directive, array, NULL, lp, s, 0);
247}
248
249void
250servconf_add_hostkey(const char *file, const int line,
251 ServerOptions *options, const char *path, int userprovided)
252{
253 char *apath = derelativise_path(path);
254
255 array_append2(file, line, "HostKey",
256 &options->host_key_files, &options->host_key_file_userprovided,
257 &options->num_host_key_files, apath, userprovided);
258 free(apath);
259}
260
261void
262servconf_add_hostcert(const char *file, const int line,
263 ServerOptions *options, const char *path)
264{
265 char *apath = derelativise_path(path);
266
267 array_append(file, line, "HostCertificate",
268 &options->host_cert_files, &options->num_host_cert_files, apath);
269 free(apath);
16c343f1
PA
270}
271
272void
273fill_default_server_options(ServerOptions *options)
274{
664f4763 275 u_int i;
e9778795 276
61aab03f
MD
277 /*
278 * Portable-specific options.
279 *
280 * Please do NOT under any circumstances change the default to 1,
281 * for any reason. The use of PAM is not considered to be secure
282 * by default.
283 */
16c343f1
PA
284 if (options->use_pam == -1)
285 options->use_pam = 0;
286
287 /* Standard Options */
16c343f1
PA
288 if (options->num_host_key_files == 0) {
289 /* fill default hostkeys for protocols */
664f4763 290 servconf_add_hostkey("[default]", 0, options,
291 _PATH_HOST_RSA_KEY_FILE, 0);
9f304aaf 292#ifdef OPENSSL_HAS_ECC
664f4763 293 servconf_add_hostkey("[default]", 0, options,
294 _PATH_HOST_ECDSA_KEY_FILE, 0);
9f304aaf 295#endif
664f4763 296 servconf_add_hostkey("[default]", 0, options,
297 _PATH_HOST_ED25519_KEY_FILE, 0);
298#ifdef WITH_XMSS
299 servconf_add_hostkey("[default]", 0, options,
300 _PATH_HOST_XMSS_KEY_FILE, 0);
301#endif /* WITH_XMSS */
16c343f1 302 }
856ea928 303 /* No certificates by default */
16c343f1
PA
304 if (options->num_ports == 0)
305 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
e9778795
PA
306 if (options->address_family == -1)
307 options->address_family = AF_UNSPEC;
16c343f1 308 if (options->listen_addrs == NULL)
664f4763 309 add_listen_addr(options, NULL, NULL, 0);
16c343f1 310 if (options->pid_file == NULL)
e9778795 311 options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
16c343f1
PA
312 if (options->login_grace_time == -1)
313 options->login_grace_time = 120;
16c343f1 314 if (options->permit_root_login == PERMIT_NOT_SET)
e9778795 315 options->permit_root_login = PERMIT_NO_PASSWD;
16c343f1
PA
316 if (options->ignore_rhosts == -1)
317 options->ignore_rhosts = 1;
318 if (options->ignore_user_known_hosts == -1)
319 options->ignore_user_known_hosts = 0;
320 if (options->print_motd == -1)
321 options->print_motd = 1;
322 if (options->print_lastlog == -1)
323 options->print_lastlog = 1;
324 if (options->x11_forwarding == -1)
325 options->x11_forwarding = 0;
326 if (options->x11_display_offset == -1)
327 options->x11_display_offset = 10;
328 if (options->x11_use_localhost == -1)
329 options->x11_use_localhost = 1;
330 if (options->xauth_location == NULL)
e9778795 331 options->xauth_location = xstrdup(_PATH_XAUTH);
36e94dc5
PA
332 if (options->permit_tty == -1)
333 options->permit_tty = 1;
334 if (options->permit_user_rc == -1)
335 options->permit_user_rc = 1;
16c343f1
PA
336 if (options->strict_modes == -1)
337 options->strict_modes = 1;
338 if (options->tcp_keep_alive == -1)
339 options->tcp_keep_alive = 1;
340 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
341 options->log_facility = SYSLOG_FACILITY_AUTH;
342 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
343 options->log_level = SYSLOG_LEVEL_INFO;
16c343f1
PA
344 if (options->hostbased_authentication == -1)
345 options->hostbased_authentication = 0;
346 if (options->hostbased_uses_name_from_packet_only == -1)
347 options->hostbased_uses_name_from_packet_only = 0;
16c343f1
PA
348 if (options->pubkey_authentication == -1)
349 options->pubkey_authentication = 1;
350 if (options->kerberos_authentication == -1)
351 options->kerberos_authentication = 0;
352 if (options->kerberos_or_local_passwd == -1)
353 options->kerberos_or_local_passwd = 1;
354 if (options->kerberos_ticket_cleanup == -1)
355 options->kerberos_ticket_cleanup = 1;
356 if (options->kerberos_get_afs_token == -1)
357 options->kerberos_get_afs_token = 0;
358 if (options->gss_authentication == -1)
359 options->gss_authentication = 0;
360 if (options->gss_cleanup_creds == -1)
361 options->gss_cleanup_creds = 1;
e9778795 362 if (options->gss_strict_acceptor == -1)
ce74baca 363 options->gss_strict_acceptor = 1;
61aab03f
MD
364 /*
365 * Please do NOT under any circumstances change the default to 1,
366 * for any reason. The use of plaintext passwords are not considered
367 * secure by default.
368 */
16c343f1 369 if (options->password_authentication == -1)
61aab03f 370 options->password_authentication = 0;
16c343f1
PA
371 if (options->kbd_interactive_authentication == -1)
372 options->kbd_interactive_authentication = 0;
373 if (options->challenge_response_authentication == -1)
374 options->challenge_response_authentication = 1;
375 if (options->permit_empty_passwd == -1)
376 options->permit_empty_passwd = 0;
664f4763 377 if (options->permit_user_env == -1) {
16c343f1 378 options->permit_user_env = 0;
664f4763 379 options->permit_user_env_whitelist = NULL;
380 }
16c343f1
PA
381 if (options->compression == -1)
382 options->compression = COMP_DELAYED;
36e94dc5
PA
383 if (options->rekey_limit == -1)
384 options->rekey_limit = 0;
385 if (options->rekey_interval == -1)
386 options->rekey_interval = 0;
16c343f1 387 if (options->allow_tcp_forwarding == -1)
36e94dc5
PA
388 options->allow_tcp_forwarding = FORWARD_ALLOW;
389 if (options->allow_streamlocal_forwarding == -1)
390 options->allow_streamlocal_forwarding = FORWARD_ALLOW;
3b69e377
PA
391 if (options->allow_agent_forwarding == -1)
392 options->allow_agent_forwarding = 1;
36e94dc5
PA
393 if (options->fwd_opts.gateway_ports == -1)
394 options->fwd_opts.gateway_ports = 0;
16c343f1 395 if (options->max_startups == -1)
36e94dc5 396 options->max_startups = 100;
16c343f1 397 if (options->max_startups_rate == -1)
36e94dc5 398 options->max_startups_rate = 30; /* 30% */
16c343f1 399 if (options->max_startups_begin == -1)
36e94dc5 400 options->max_startups_begin = 10;
16c343f1
PA
401 if (options->max_authtries == -1)
402 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
3b69e377
PA
403 if (options->max_sessions == -1)
404 options->max_sessions = DEFAULT_SESSIONS_MAX;
16c343f1 405 if (options->use_dns == -1)
e9778795 406 options->use_dns = 0;
16c343f1
PA
407 if (options->client_alive_interval == -1)
408 options->client_alive_interval = 0;
409 if (options->client_alive_count_max == -1)
410 options->client_alive_count_max = 3;
1c188a7f 411 if (options->num_authkeys_files == 0) {
664f4763 412 array_append("[default]", 0, "AuthorizedKeysFiles",
413 &options->authorized_keys_files,
414 &options->num_authkeys_files,
415 _PATH_SSH_USER_PERMITTED_KEYS);
416 array_append("[default]", 0, "AuthorizedKeysFiles",
417 &options->authorized_keys_files,
418 &options->num_authkeys_files,
419 _PATH_SSH_USER_PERMITTED_KEYS2);
16c343f1 420 }
16c343f1
PA
421 if (options->permit_tun == -1)
422 options->permit_tun = SSH_TUNMODE_NO;
9f304aaf 423 if (options->ip_qos_interactive == -1)
664f4763 424 options->ip_qos_interactive = IPTOS_DSCP_AF21;
9f304aaf 425 if (options->ip_qos_bulk == -1)
664f4763 426 options->ip_qos_bulk = IPTOS_DSCP_CS1;
99e85e0d
PA
427 if (options->version_addendum == NULL)
428 options->version_addendum = xstrdup("");
36e94dc5
PA
429 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
430 options->fwd_opts.streamlocal_bind_mask = 0177;
431 if (options->fwd_opts.streamlocal_bind_unlink == -1)
432 options->fwd_opts.streamlocal_bind_unlink = 0;
e9778795
PA
433 if (options->fingerprint_hash == -1)
434 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
ce74baca
MD
435 if (options->disable_forwarding == -1)
436 options->disable_forwarding = 0;
437 if (options->expose_userauth_info == -1)
438 options->expose_userauth_info = 0;
e9778795
PA
439
440 assemble_algorithms(options);
441
442 /* Turn privilege separation and sandboxing on by default */
16c343f1 443 if (use_privsep == -1)
e9778795
PA
444 use_privsep = PRIVSEP_ON;
445
446#define CLEAR_ON_NONE(v) \
447 do { \
448 if (option_clear_or_none(v)) { \
449 free(v); \
450 v = NULL; \
451 } \
452 } while(0)
453 CLEAR_ON_NONE(options->pid_file);
454 CLEAR_ON_NONE(options->xauth_location);
455 CLEAR_ON_NONE(options->banner);
456 CLEAR_ON_NONE(options->trusted_user_ca_keys);
457 CLEAR_ON_NONE(options->revoked_keys_file);
458 CLEAR_ON_NONE(options->authorized_principals_file);
459 CLEAR_ON_NONE(options->adm_forced_command);
460 CLEAR_ON_NONE(options->chroot_directory);
664f4763 461 CLEAR_ON_NONE(options->routing_domain);
e9778795
PA
462 for (i = 0; i < options->num_host_key_files; i++)
463 CLEAR_ON_NONE(options->host_key_files[i]);
464 for (i = 0; i < options->num_host_cert_files; i++)
465 CLEAR_ON_NONE(options->host_cert_files[i]);
466#undef CLEAR_ON_NONE
467
468 /* Similar handling for AuthenticationMethods=any */
469 if (options->num_auth_methods == 1 &&
470 strcmp(options->auth_methods[0], "any") == 0) {
471 free(options->auth_methods[0]);
472 options->auth_methods[0] = NULL;
473 options->num_auth_methods = 0;
474 }
16c343f1
PA
475
476#ifndef HAVE_MMAP
477 if (use_privsep && options->compression == 1) {
478 error("This platform does not support both privilege "
479 "separation and compression");
480 error("Compression disabled");
481 options->compression = 0;
482 }
483#endif
16c343f1
PA
484}
485
486/* Keyword tokens. */
487typedef enum {
488 sBadOption, /* == unknown option */
489 /* Portable-specific options */
490 sUsePAM,
491 /* Standard Options */
ce74baca
MD
492 sPort, sHostKeyFile, sLoginGraceTime,
493 sPermitRootLogin, sLogFacility, sLogLevel,
16c343f1
PA
494 sRhostsRSAAuthentication, sRSAAuthentication,
495 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
664f4763 496 sKerberosGetAFSToken, sChallengeResponseAuthentication,
16c343f1
PA
497 sPasswordAuthentication, sKbdInteractiveAuthentication,
498 sListenAddress, sAddressFamily,
499 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
500 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
36e94dc5 501 sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
ce74baca 502 sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
36e94dc5 503 sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
ce74baca 504 sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
e9778795
PA
505 sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
506 sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
16c343f1 507 sBanner, sUseDNS, sHostbasedAuthentication,
e9778795
PA
508 sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
509 sHostKeyAlgorithms,
510 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
511 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
664f4763 512 sAcceptEnv, sSetEnv, sPermitTunnel,
513 sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
3b69e377 514 sUsePrivilegeSeparation, sAllowAgentForwarding,
36e94dc5 515 sHostCertificate,
856ea928 516 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
e9778795 517 sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
664f4763 518 sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
36e94dc5
PA
519 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
520 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
521 sStreamLocalBindMask, sStreamLocalBindUnlink,
ce74baca 522 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
664f4763 523 sExposeAuthInfo, sRDomain,
ce74baca 524 sDeprecated, sIgnore, sUnsupported
16c343f1
PA
525} ServerOpCodes;
526
527#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
528#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
529#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
530
531/* Textual representation of the tokens. */
532static struct {
533 const char *name;
534 ServerOpCodes opcode;
535 u_int flags;
536} keywords[] = {
537 /* Portable-specific options */
538#ifdef USE_PAM
539 { "usepam", sUsePAM, SSHCFG_GLOBAL },
540#else
541 { "usepam", sUnsupported, SSHCFG_GLOBAL },
542#endif
543 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
544 /* Standard Options */
545 { "port", sPort, SSHCFG_GLOBAL },
546 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
547 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
36e94dc5 548 { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
16c343f1 549 { "pidfile", sPidFile, SSHCFG_GLOBAL },
ce74baca 550 { "serverkeybits", sDeprecated, SSHCFG_GLOBAL },
16c343f1 551 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
ce74baca 552 { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL },
16c343f1
PA
553 { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
554 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
ce74baca 555 { "loglevel", sLogLevel, SSHCFG_ALL },
16c343f1 556 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
ce74baca 557 { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL },
16c343f1 558 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
856ea928 559 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
e9778795
PA
560 { "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL },
561 { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL },
ce74baca 562 { "rsaauthentication", sDeprecated, SSHCFG_ALL },
16c343f1 563 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
e9778795 564 { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
40c002af 565 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
16c343f1
PA
566#ifdef KRB5
567 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
568 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
569 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
570#ifdef USE_AFS
571 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
572#else
573 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
574#endif
575#else
576 { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
577 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
578 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
579 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
580#endif
581 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
582 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
583#ifdef GSSAPI
584 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
585 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
e9778795 586 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
16c343f1
PA
587#else
588 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
589 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
e9778795 590 { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
16c343f1
PA
591#endif
592 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
593 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
594 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
664f4763 595 { "skeyauthentication", sDeprecated, SSHCFG_GLOBAL },
16c343f1
PA
596 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
597 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
598 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
599 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
e9778795
PA
600#ifdef DISABLE_LASTLOG
601 { "printlastlog", sUnsupported, SSHCFG_GLOBAL },
602#else
16c343f1 603 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
e9778795 604#endif
16c343f1
PA
605 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
606 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
607 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
608 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
609 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
610 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
611 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
cb5eb4f1 612 { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
16c343f1 613 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
ce74baca 614 { "uselogin", sDeprecated, SSHCFG_GLOBAL },
16c343f1 615 { "compression", sCompression, SSHCFG_GLOBAL },
36e94dc5 616 { "rekeylimit", sRekeyLimit, SSHCFG_ALL },
16c343f1
PA
617 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
618 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
619 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
3b69e377 620 { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
99e85e0d
PA
621 { "allowusers", sAllowUsers, SSHCFG_ALL },
622 { "denyusers", sDenyUsers, SSHCFG_ALL },
623 { "allowgroups", sAllowGroups, SSHCFG_ALL },
624 { "denygroups", sDenyGroups, SSHCFG_ALL },
16c343f1
PA
625 { "ciphers", sCiphers, SSHCFG_GLOBAL },
626 { "macs", sMacs, SSHCFG_GLOBAL },
ce74baca 627 { "protocol", sIgnore, SSHCFG_GLOBAL },
16c343f1
PA
628 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
629 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
630 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
3b69e377
PA
631 { "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
632 { "maxsessions", sMaxSessions, SSHCFG_ALL },
16c343f1
PA
633 { "banner", sBanner, SSHCFG_ALL },
634 { "usedns", sUseDNS, SSHCFG_GLOBAL },
635 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
636 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
ce74baca
MD
637 { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
638 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
856ea928 639 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
1c188a7f 640 { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
ce74baca 641 { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL},
99e85e0d 642 { "acceptenv", sAcceptEnv, SSHCFG_ALL },
664f4763 643 { "setenv", sSetEnv, SSHCFG_ALL },
856ea928 644 { "permittunnel", sPermitTunnel, SSHCFG_ALL },
36e94dc5
PA
645 { "permittty", sPermitTTY, SSHCFG_ALL },
646 { "permituserrc", sPermitUserRC, SSHCFG_ALL },
40c002af 647 { "match", sMatch, SSHCFG_ALL },
16c343f1 648 { "permitopen", sPermitOpen, SSHCFG_ALL },
664f4763 649 { "permitlisten", sPermitListen, SSHCFG_ALL },
16c343f1
PA
650 { "forcecommand", sForceCommand, SSHCFG_ALL },
651 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
856ea928
PA
652 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
653 { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
654 { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
655 { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
9f304aaf
PA
656 { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
657 { "ipqos", sIPQoS, SSHCFG_ALL },
36e94dc5
PA
658 { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
659 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
e9778795
PA
660 { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL },
661 { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL },
99e85e0d 662 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
36e94dc5
PA
663 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
664 { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
665 { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
666 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
e9778795 667 { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
ce74baca
MD
668 { "disableforwarding", sDisableForwarding, SSHCFG_ALL },
669 { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
664f4763 670 { "rdomain", sRDomain, SSHCFG_ALL },
671 { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
16c343f1
PA
672 { NULL, sBadOption, 0 }
673};
674
3b69e377
PA
675static struct {
676 int val;
677 char *text;
678} tunmode_desc[] = {
679 { SSH_TUNMODE_NO, "no" },
680 { SSH_TUNMODE_POINTOPOINT, "point-to-point" },
681 { SSH_TUNMODE_ETHERNET, "ethernet" },
682 { SSH_TUNMODE_YES, "yes" },
683 { -1, NULL }
684};
685
664f4763 686/* Returns an opcode name from its number */
687
688static const char *
689lookup_opcode_name(ServerOpCodes code)
690{
691 u_int i;
692
693 for (i = 0; keywords[i].name != NULL; i++)
694 if (keywords[i].opcode == code)
695 return(keywords[i].name);
696 return "UNKNOWN";
697}
698
699
16c343f1
PA
700/*
701 * Returns the number of the token pointed to by cp or sBadOption.
702 */
703
704static ServerOpCodes
705parse_token(const char *cp, const char *filename,
706 int linenum, u_int *flags)
707{
708 u_int i;
709
710 for (i = 0; keywords[i].name; i++)
711 if (strcasecmp(cp, keywords[i].name) == 0) {
712 *flags = keywords[i].flags;
713 return keywords[i].opcode;
714 }
715
716 error("%s: line %d: Bad configuration option: %s",
717 filename, linenum, cp);
718 return sBadOption;
719}
720
856ea928
PA
721char *
722derelativise_path(const char *path)
723{
e9778795 724 char *expanded, *ret, cwd[PATH_MAX];
856ea928 725
e9778795
PA
726 if (strcasecmp(path, "none") == 0)
727 return xstrdup("none");
856ea928 728 expanded = tilde_expand_filename(path, getuid());
664f4763 729 if (path_absolute(expanded))
856ea928
PA
730 return expanded;
731 if (getcwd(cwd, sizeof(cwd)) == NULL)
732 fatal("%s: getcwd: %s", __func__, strerror(errno));
733 xasprintf(&ret, "%s/%s", cwd, expanded);
36e94dc5 734 free(expanded);
856ea928
PA
735 return ret;
736}
737
16c343f1 738static void
664f4763 739add_listen_addr(ServerOptions *options, const char *addr,
740 const char *rdomain, int port)
16c343f1
PA
741{
742 u_int i;
743
664f4763 744 if (port > 0)
745 add_one_listen_addr(options, addr, rdomain, port);
746 else {
747 for (i = 0; i < options->num_ports; i++) {
748 add_one_listen_addr(options, addr, rdomain,
749 options->ports[i]);
750 }
751 }
16c343f1
PA
752}
753
754static void
664f4763 755add_one_listen_addr(ServerOptions *options, const char *addr,
756 const char *rdomain, int port)
16c343f1
PA
757{
758 struct addrinfo hints, *ai, *aitop;
759 char strport[NI_MAXSERV];
760 int gaierr;
664f4763 761 u_int i;
762
763 /* Find listen_addrs entry for this rdomain */
764 for (i = 0; i < options->num_listen_addrs; i++) {
765 if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL)
766 break;
767 if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL)
768 continue;
769 if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0)
770 break;
771 }
772 if (i >= options->num_listen_addrs) {
773 /* No entry for this rdomain; allocate one */
774 if (i >= INT_MAX)
775 fatal("%s: too many listen addresses", __func__);
776 options->listen_addrs = xrecallocarray(options->listen_addrs,
777 options->num_listen_addrs, options->num_listen_addrs + 1,
778 sizeof(*options->listen_addrs));
779 i = options->num_listen_addrs++;
780 if (rdomain != NULL)
781 options->listen_addrs[i].rdomain = xstrdup(rdomain);
782 }
783 /* options->listen_addrs[i] points to the addresses for this rdomain */
16c343f1
PA
784
785 memset(&hints, 0, sizeof(hints));
786 hints.ai_family = options->address_family;
787 hints.ai_socktype = SOCK_STREAM;
788 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
cb5eb4f1 789 snprintf(strport, sizeof strport, "%d", port);
16c343f1
PA
790 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
791 fatal("bad addr or host: %s (%s)",
792 addr ? addr : "<NULL>",
793 ssh_gai_strerror(gaierr));
794 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
795 ;
664f4763 796 ai->ai_next = options->listen_addrs[i].addrs;
797 options->listen_addrs[i].addrs = aitop;
798}
799
800/* Returns nonzero if the routing domain name is valid */
801static int
802valid_rdomain(const char *name)
803{
804#if defined(HAVE_SYS_VALID_RDOMAIN)
805 return sys_valid_rdomain(name);
806#elif defined(__OpenBSD__)
807 const char *errstr;
808 long long num;
809 struct rt_tableinfo info;
810 int mib[6];
811 size_t miblen = sizeof(mib);
812
813 if (name == NULL)
814 return 1;
815
816 num = strtonum(name, 0, 255, &errstr);
817 if (errstr != NULL)
818 return 0;
819
820 /* Check whether the table actually exists */
821 memset(mib, 0, sizeof(mib));
822 mib[0] = CTL_NET;
823 mib[1] = PF_ROUTE;
824 mib[4] = NET_RT_TABLE;
825 mib[5] = (int)num;
826 if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1)
827 return 0;
828
829 return 1;
830#else /* defined(__OpenBSD__) */
831 error("Routing domains are not supported on this platform");
832 return 0;
833#endif
16c343f1
PA
834}
835
e9778795
PA
836/*
837 * Queue a ListenAddress to be processed once we have all of the Ports
838 * and AddressFamily options.
839 */
840static void
664f4763 841queue_listen_addr(ServerOptions *options, const char *addr,
842 const char *rdomain, int port)
e9778795 843{
664f4763 844 struct queued_listenaddr *qla;
845
846 options->queued_listen_addrs = xrecallocarray(
847 options->queued_listen_addrs,
848 options->num_queued_listens, options->num_queued_listens + 1,
849 sizeof(*options->queued_listen_addrs));
850 qla = &options->queued_listen_addrs[options->num_queued_listens++];
851 qla->addr = xstrdup(addr);
852 qla->port = port;
853 qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain);
e9778795
PA
854}
855
856/*
857 * Process queued (text) ListenAddress entries.
858 */
859static void
860process_queued_listen_addrs(ServerOptions *options)
861{
862 u_int i;
664f4763 863 struct queued_listenaddr *qla;
e9778795
PA
864
865 if (options->num_ports == 0)
866 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
867 if (options->address_family == -1)
868 options->address_family = AF_UNSPEC;
869
870 for (i = 0; i < options->num_queued_listens; i++) {
664f4763 871 qla = &options->queued_listen_addrs[i];
872 add_listen_addr(options, qla->addr, qla->rdomain, qla->port);
873 free(qla->addr);
874 free(qla->rdomain);
e9778795
PA
875 }
876 free(options->queued_listen_addrs);
877 options->queued_listen_addrs = NULL;
e9778795
PA
878 options->num_queued_listens = 0;
879}
880
ce74baca 881/*
664f4763 882 * Inform channels layer of permitopen options for a single forwarding
883 * direction (local/remote).
ce74baca 884 */
664f4763 885static void
886process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode,
887 char **opens, u_int num_opens)
ce74baca
MD
888{
889 u_int i;
890 int port;
664f4763 891 char *host, *arg, *oarg, ch;
892 int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;
893 const char *what = lookup_opcode_name(opcode);
ce74baca 894
664f4763 895 channel_clear_permission(ssh, FORWARD_ADM, where);
896 if (num_opens == 0)
ce74baca
MD
897 return; /* permit any */
898
899 /* handle keywords: "any" / "none" */
664f4763 900 if (num_opens == 1 && strcmp(opens[0], "any") == 0)
ce74baca 901 return;
664f4763 902 if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
903 channel_disable_admin(ssh, where);
ce74baca
MD
904 return;
905 }
906 /* Otherwise treat it as a list of permitted host:port */
664f4763 907 for (i = 0; i < num_opens; i++) {
908 oarg = arg = xstrdup(opens[i]);
909 ch = '\0';
910 host = hpdelim2(&arg, &ch);
911 if (host == NULL || ch == '/')
912 fatal("%s: missing host in %s", __func__, what);
ce74baca
MD
913 host = cleanhostname(host);
914 if (arg == NULL || ((port = permitopen_port(arg)) < 0))
664f4763 915 fatal("%s: bad port number in %s", __func__, what);
ce74baca 916 /* Send it to channels layer */
664f4763 917 channel_add_permission(ssh, FORWARD_ADM,
918 where, host, port);
ce74baca
MD
919 free(oarg);
920 }
921}
922
664f4763 923/*
924 * Inform channels layer of permitopen options from configuration.
925 */
926void
927process_permitopen(struct ssh *ssh, ServerOptions *options)
928{
929 process_permitopen_list(ssh, sPermitOpen,
930 options->permitted_opens, options->num_permitted_opens);
931 process_permitopen_list(ssh, sPermitListen,
932 options->permitted_listens,
933 options->num_permitted_listens);
934}
935
99e85e0d 936struct connection_info *
664f4763 937get_connection_info(struct ssh *ssh, int populate, int use_dns)
99e85e0d
PA
938{
939 static struct connection_info ci;
940
664f4763 941 if (ssh == NULL || !populate)
99e85e0d 942 return &ci;
e9778795
PA
943 ci.host = auth_get_canonical_hostname(ssh, use_dns);
944 ci.address = ssh_remote_ipaddr(ssh);
945 ci.laddress = ssh_local_ipaddr(ssh);
946 ci.lport = ssh_local_port(ssh);
664f4763 947 ci.rdomain = ssh_packet_rdomain_in(ssh);
99e85e0d
PA
948 return &ci;
949}
950
16c343f1
PA
951/*
952 * The strategy for the Match blocks is that the config file is parsed twice.
953 *
954 * The first time is at startup. activep is initialized to 1 and the
955 * directives in the global context are processed and acted on. Hitting a
956 * Match directive unsets activep and the directives inside the block are
957 * checked for syntax only.
958 *
959 * The second time is after a connection has been established but before
960 * authentication. activep is initialized to 2 and global config directives
961 * are ignored since they have already been processed. If the criteria in a
962 * Match block is met, activep is set and the subsequent directives
963 * processed and actioned until EOF or another Match block unsets it. Any
964 * options set are copied into the main server config.
965 *
966 * Potential additions/improvements:
ce74baca 967 * - Add Match support for pre-kex directives, eg. Ciphers.
16c343f1
PA
968 *
969 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
970 * Match Address 192.168.0.*
971 * Tag trusted
972 * Match Group wheel
973 * Tag trusted
974 * Match Tag trusted
975 * AllowTcpForwarding yes
976 * GatewayPorts clientspecified
977 * [...]
978 *
979 * - Add a PermittedChannelRequests directive
980 * Match Group shell
981 * PermittedChannelRequests session,forwarded-tcpip
982 */
983
984static int
985match_cfg_line_group(const char *grps, int line, const char *user)
986{
987 int result = 0;
16c343f1
PA
988 struct passwd *pw;
989
16c343f1
PA
990 if (user == NULL)
991 goto out;
992
993 if ((pw = getpwnam(user)) == NULL) {
994 debug("Can't match group at line %d because user %.100s does "
995 "not exist", line, user);
996 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
997 debug("Can't Match group because user %.100s not in any group "
998 "at line %d", user, line);
3b69e377
PA
999 } else if (ga_match_pattern_list(grps) != 1) {
1000 debug("user %.100s does not match group list %.100s at line %d",
1001 user, grps, line);
16c343f1 1002 } else {
3b69e377
PA
1003 debug("user %.100s matched group list %.100s at line %d", user,
1004 grps, line);
16c343f1
PA
1005 result = 1;
1006 }
1007out:
1008 ga_free();
16c343f1
PA
1009 return result;
1010}
1011
664f4763 1012static void
1013match_test_missing_fatal(const char *criteria, const char *attrib)
1014{
1015 fatal("'Match %s' in configuration but '%s' not in connection "
1016 "test specification.", criteria, attrib);
1017}
1018
99e85e0d 1019/*
36e94dc5
PA
1020 * All of the attributes on a single Match line are ANDed together, so we need
1021 * to check every attribute and set the result to zero if any attribute does
1022 * not match.
99e85e0d 1023 */
16c343f1 1024static int
99e85e0d 1025match_cfg_line(char **condition, int line, struct connection_info *ci)
16c343f1 1026{
36e94dc5 1027 int result = 1, attributes = 0, port;
16c343f1 1028 char *arg, *attrib, *cp = *condition;
16c343f1 1029
99e85e0d 1030 if (ci == NULL)
16c343f1
PA
1031 debug3("checking syntax for 'Match %s'", cp);
1032 else
99e85e0d
PA
1033 debug3("checking match for '%s' user %s host %s addr %s "
1034 "laddr %s lport %d", cp, ci->user ? ci->user : "(null)",
1035 ci->host ? ci->host : "(null)",
1036 ci->address ? ci->address : "(null)",
1037 ci->laddress ? ci->laddress : "(null)", ci->lport);
16c343f1
PA
1038
1039 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
36e94dc5
PA
1040 attributes++;
1041 if (strcasecmp(attrib, "all") == 0) {
1042 if (attributes != 1 ||
1043 ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
1044 error("'all' cannot be combined with other "
1045 "Match attributes");
1046 return -1;
1047 }
1048 *condition = cp;
1049 return 1;
1050 }
16c343f1
PA
1051 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
1052 error("Missing Match criteria for %s", attrib);
1053 return -1;
1054 }
16c343f1 1055 if (strcasecmp(attrib, "user") == 0) {
664f4763 1056 if (ci == NULL) {
16c343f1
PA
1057 result = 0;
1058 continue;
1059 }
664f4763 1060 if (ci->user == NULL)
1061 match_test_missing_fatal("User", "user");
1062 if (match_usergroup_pattern_list(ci->user, arg) != 1)
16c343f1
PA
1063 result = 0;
1064 else
1065 debug("user %.100s matched 'User %.100s' at "
99e85e0d 1066 "line %d", ci->user, arg, line);
16c343f1 1067 } else if (strcasecmp(attrib, "group") == 0) {
664f4763 1068 if (ci == NULL) {
99e85e0d
PA
1069 result = 0;
1070 continue;
1071 }
664f4763 1072 if (ci->user == NULL)
1073 match_test_missing_fatal("Group", "user");
99e85e0d 1074 switch (match_cfg_line_group(arg, line, ci->user)) {
16c343f1
PA
1075 case -1:
1076 return -1;
1077 case 0:
1078 result = 0;
1079 }
1080 } else if (strcasecmp(attrib, "host") == 0) {
664f4763 1081 if (ci == NULL) {
16c343f1
PA
1082 result = 0;
1083 continue;
1084 }
664f4763 1085 if (ci->host == NULL)
1086 match_test_missing_fatal("Host", "host");
e9778795 1087 if (match_hostname(ci->host, arg) != 1)
16c343f1
PA
1088 result = 0;
1089 else
1090 debug("connection from %.100s matched 'Host "
99e85e0d 1091 "%.100s' at line %d", ci->host, arg, line);
16c343f1 1092 } else if (strcasecmp(attrib, "address") == 0) {
664f4763 1093 if (ci == NULL) {
99e85e0d
PA
1094 result = 0;
1095 continue;
1096 }
664f4763 1097 if (ci->address == NULL)
1098 match_test_missing_fatal("Address", "addr");
99e85e0d 1099 switch (addr_match_list(ci->address, arg)) {
3b69e377 1100 case 1:
16c343f1 1101 debug("connection from %.100s matched 'Address "
99e85e0d 1102 "%.100s' at line %d", ci->address, arg, line);
3b69e377
PA
1103 break;
1104 case 0:
1105 case -1:
1106 result = 0;
1107 break;
1108 case -2:
1109 return -1;
1110 }
99e85e0d 1111 } else if (strcasecmp(attrib, "localaddress") == 0){
664f4763 1112 if (ci == NULL) {
99e85e0d
PA
1113 result = 0;
1114 continue;
1115 }
664f4763 1116 if (ci->laddress == NULL)
1117 match_test_missing_fatal("LocalAddress",
1118 "laddr");
99e85e0d
PA
1119 switch (addr_match_list(ci->laddress, arg)) {
1120 case 1:
1121 debug("connection from %.100s matched "
1122 "'LocalAddress %.100s' at line %d",
1123 ci->laddress, arg, line);
1124 break;
1125 case 0:
1126 case -1:
1127 result = 0;
1128 break;
1129 case -2:
1130 return -1;
1131 }
1132 } else if (strcasecmp(attrib, "localport") == 0) {
1133 if ((port = a2port(arg)) == -1) {
1134 error("Invalid LocalPort '%s' on Match line",
1135 arg);
1136 return -1;
1137 }
664f4763 1138 if (ci == NULL) {
99e85e0d
PA
1139 result = 0;
1140 continue;
1141 }
664f4763 1142 if (ci->lport == 0)
1143 match_test_missing_fatal("LocalPort", "lport");
99e85e0d
PA
1144 /* TODO support port lists */
1145 if (port == ci->lport)
1146 debug("connection from %.100s matched "
1147 "'LocalPort %d' at line %d",
1148 ci->laddress, port, line);
1149 else
1150 result = 0;
664f4763 1151 } else if (strcasecmp(attrib, "rdomain") == 0) {
1152 if (ci == NULL || ci->rdomain == NULL) {
1153 result = 0;
1154 continue;
1155 }
1156 if (match_pattern_list(ci->rdomain, arg, 0) != 1)
1157 result = 0;
1158 else
1159 debug("user %.100s matched 'RDomain %.100s' at "
1160 "line %d", ci->rdomain, arg, line);
16c343f1
PA
1161 } else {
1162 error("Unsupported Match attribute %s", attrib);
1163 return -1;
1164 }
1165 }
36e94dc5
PA
1166 if (attributes == 0) {
1167 error("One or more attributes required for Match");
1168 return -1;
1169 }
99e85e0d 1170 if (ci != NULL)
16c343f1
PA
1171 debug3("match %sfound", result ? "" : "not ");
1172 *condition = cp;
1173 return result;
1174}
1175
1176#define WHITESPACE " \t\r\n"
1177
1c188a7f
PA
1178/* Multistate option parsing */
1179struct multistate {
1180 char *key;
1181 int value;
1182};
664f4763 1183static const struct multistate multistate_flag[] = {
1184 { "yes", 1 },
1185 { "no", 0 },
1186 { NULL, -1 }
1187};
1c188a7f
PA
1188static const struct multistate multistate_addressfamily[] = {
1189 { "inet", AF_INET },
1190 { "inet6", AF_INET6 },
1191 { "any", AF_UNSPEC },
1192 { NULL, -1 }
1193};
1194static const struct multistate multistate_permitrootlogin[] = {
1195 { "without-password", PERMIT_NO_PASSWD },
e9778795 1196 { "prohibit-password", PERMIT_NO_PASSWD },
1c188a7f
PA
1197 { "forced-commands-only", PERMIT_FORCED_ONLY },
1198 { "yes", PERMIT_YES },
1199 { "no", PERMIT_NO },
1200 { NULL, -1 }
1201};
1202static const struct multistate multistate_compression[] = {
ce74baca 1203 { "yes", COMP_DELAYED },
1c188a7f 1204 { "delayed", COMP_DELAYED },
1c188a7f
PA
1205 { "no", COMP_NONE },
1206 { NULL, -1 }
1207};
1208static const struct multistate multistate_gatewayports[] = {
1209 { "clientspecified", 2 },
1210 { "yes", 1 },
1211 { "no", 0 },
1212 { NULL, -1 }
1213};
36e94dc5
PA
1214static const struct multistate multistate_tcpfwd[] = {
1215 { "yes", FORWARD_ALLOW },
1216 { "all", FORWARD_ALLOW },
1217 { "no", FORWARD_DENY },
1218 { "remote", FORWARD_REMOTE },
1219 { "local", FORWARD_LOCAL },
1220 { NULL, -1 }
1221};
1c188a7f 1222
16c343f1
PA
1223int
1224process_server_config_line(ServerOptions *options, char *line,
99e85e0d
PA
1225 const char *filename, int linenum, int *activep,
1226 struct connection_info *connectinfo)
16c343f1 1227{
664f4763 1228 char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
36e94dc5 1229 int cmdline = 0, *intptr, value, value2, n, port;
16c343f1
PA
1230 SyslogFacility *log_facility_ptr;
1231 LogLevel *log_level_ptr;
1232 ServerOpCodes opcode;
664f4763 1233 u_int i, *uintptr, uvalue, flags = 0;
16c343f1 1234 size_t len;
36e94dc5 1235 long long val64;
1c188a7f 1236 const struct multistate *multistate_ptr;
664f4763 1237 const char *errstr;
16c343f1 1238
ce74baca
MD
1239 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1240 if ((len = strlen(line)) == 0)
1241 return 0;
1242 for (len--; len > 0; len--) {
1243 if (strchr(WHITESPACE "\f", line[len]) == NULL)
1244 break;
1245 line[len] = '\0';
1246 }
1247
16c343f1
PA
1248 cp = line;
1249 if ((arg = strdelim(&cp)) == NULL)
1250 return 0;
1251 /* Ignore leading whitespace */
1252 if (*arg == '\0')
1253 arg = strdelim(&cp);
1254 if (!arg || !*arg || *arg == '#')
1255 return 0;
1256 intptr = NULL;
1257 charptr = NULL;
1258 opcode = parse_token(arg, filename, linenum, &flags);
1259
1260 if (activep == NULL) { /* We are processing a command line directive */
1261 cmdline = 1;
1262 activep = &cmdline;
1263 }
1264 if (*activep && opcode != sMatch)
1265 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
1266 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
99e85e0d 1267 if (connectinfo == NULL) {
16c343f1
PA
1268 fatal("%s line %d: Directive '%s' is not allowed "
1269 "within a Match block", filename, linenum, arg);
1270 } else { /* this is a directive we have already processed */
1271 while (arg)
1272 arg = strdelim(&cp);
1273 return 0;
1274 }
1275 }
1276
1277 switch (opcode) {
1278 /* Portable-specific options */
1279 case sUsePAM:
1280 intptr = &options->use_pam;
1281 goto parse_flag;
1282
1283 /* Standard Options */
1284 case sBadOption:
1285 return -1;
1286 case sPort:
1287 /* ignore ports from configfile if cmdline specifies ports */
1288 if (options->ports_from_cmdline)
1289 return 0;
16c343f1
PA
1290 if (options->num_ports >= MAX_PORTS)
1291 fatal("%s line %d: too many ports.",
1292 filename, linenum);
1293 arg = strdelim(&cp);
1294 if (!arg || *arg == '\0')
1295 fatal("%s line %d: missing port number.",
1296 filename, linenum);
1297 options->ports[options->num_ports++] = a2port(arg);
cb5eb4f1 1298 if (options->ports[options->num_ports-1] <= 0)
16c343f1
PA
1299 fatal("%s line %d: Badly formatted port number.",
1300 filename, linenum);
1301 break;
1302
16c343f1
PA
1303 case sLoginGraceTime:
1304 intptr = &options->login_grace_time;
3b69e377 1305 parse_time:
16c343f1
PA
1306 arg = strdelim(&cp);
1307 if (!arg || *arg == '\0')
1308 fatal("%s line %d: missing time value.",
1309 filename, linenum);
1310 if ((value = convtime(arg)) == -1)
1311 fatal("%s line %d: invalid time value.",
1312 filename, linenum);
e9778795 1313 if (*activep && *intptr == -1)
16c343f1
PA
1314 *intptr = value;
1315 break;
1316
16c343f1
PA
1317 case sListenAddress:
1318 arg = strdelim(&cp);
1319 if (arg == NULL || *arg == '\0')
1320 fatal("%s line %d: missing address",
1321 filename, linenum);
1322 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
1323 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
1324 && strchr(p+1, ':') != NULL) {
16c343f1 1325 port = 0;
664f4763 1326 p = arg;
1327 } else {
1328 arg2 = NULL;
1329 ch = '\0';
1330 p = hpdelim2(&arg, &ch);
1331 if (p == NULL || ch == '/')
1332 fatal("%s line %d: bad address:port usage",
1333 filename, linenum);
1334 p = cleanhostname(p);
1335 if (arg == NULL)
1336 port = 0;
1337 else if ((port = a2port(arg)) <= 0)
1338 fatal("%s line %d: bad port number",
1339 filename, linenum);
1340 }
1341 /* Optional routing table */
1342 arg2 = NULL;
1343 if ((arg = strdelim(&cp)) != NULL) {
1344 if (strcmp(arg, "rdomain") != 0 ||
1345 (arg2 = strdelim(&cp)) == NULL)
1346 fatal("%s line %d: bad ListenAddress syntax",
1347 filename, linenum);
1348 if (!valid_rdomain(arg2))
1349 fatal("%s line %d: bad routing domain",
1350 filename, linenum);
1351 }
16c343f1 1352
664f4763 1353 queue_listen_addr(options, p, arg2, port);
16c343f1
PA
1354
1355 break;
1356
1357 case sAddressFamily:
1c188a7f
PA
1358 intptr = &options->address_family;
1359 multistate_ptr = multistate_addressfamily;
1c188a7f 1360 parse_multistate:
16c343f1
PA
1361 arg = strdelim(&cp);
1362 if (!arg || *arg == '\0')
1c188a7f 1363 fatal("%s line %d: missing argument.",
16c343f1 1364 filename, linenum);
1c188a7f
PA
1365 value = -1;
1366 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1367 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1368 value = multistate_ptr[i].value;
1369 break;
1370 }
1371 }
1372 if (value == -1)
1373 fatal("%s line %d: unsupported option \"%s\".",
16c343f1 1374 filename, linenum, arg);
1c188a7f 1375 if (*activep && *intptr == -1)
16c343f1
PA
1376 *intptr = value;
1377 break;
1378
1379 case sHostKeyFile:
16c343f1
PA
1380 arg = strdelim(&cp);
1381 if (!arg || *arg == '\0')
1382 fatal("%s line %d: missing file name.",
1383 filename, linenum);
664f4763 1384 if (*activep) {
1385 servconf_add_hostkey(filename, linenum,
1386 options, arg, 1);
16c343f1
PA
1387 }
1388 break;
1389
36e94dc5
PA
1390 case sHostKeyAgent:
1391 charptr = &options->host_key_agent;
1392 arg = strdelim(&cp);
1393 if (!arg || *arg == '\0')
1394 fatal("%s line %d: missing socket name.",
1395 filename, linenum);
1396 if (*activep && *charptr == NULL)
1397 *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ?
1398 xstrdup(arg) : derelativise_path(arg);
1399 break;
1400
856ea928 1401 case sHostCertificate:
664f4763 1402 arg = strdelim(&cp);
1403 if (!arg || *arg == '\0')
1404 fatal("%s line %d: missing file name.",
1405 filename, linenum);
1406 if (*activep)
1407 servconf_add_hostcert(filename, linenum, options, arg);
1408 break;
856ea928 1409
16c343f1
PA
1410 case sPidFile:
1411 charptr = &options->pid_file;
664f4763 1412 parse_filename:
1413 arg = strdelim(&cp);
1414 if (!arg || *arg == '\0')
1415 fatal("%s line %d: missing file name.",
1416 filename, linenum);
1417 if (*activep && *charptr == NULL) {
1418 *charptr = derelativise_path(arg);
1419 /* increase optional counter */
1420 if (intptr != NULL)
1421 *intptr = *intptr + 1;
1422 }
1423 break;
16c343f1
PA
1424
1425 case sPermitRootLogin:
1426 intptr = &options->permit_root_login;
1c188a7f
PA
1427 multistate_ptr = multistate_permitrootlogin;
1428 goto parse_multistate;
16c343f1
PA
1429
1430 case sIgnoreRhosts:
1431 intptr = &options->ignore_rhosts;
3b69e377 1432 parse_flag:
664f4763 1433 multistate_ptr = multistate_flag;
1434 goto parse_multistate;
16c343f1
PA
1435
1436 case sIgnoreUserKnownHosts:
1437 intptr = &options->ignore_user_known_hosts;
1438 goto parse_flag;
1439
16c343f1
PA
1440 case sHostbasedAuthentication:
1441 intptr = &options->hostbased_authentication;
1442 goto parse_flag;
1443
1444 case sHostbasedUsesNameFromPacketOnly:
1445 intptr = &options->hostbased_uses_name_from_packet_only;
1446 goto parse_flag;
1447
e9778795
PA
1448 case sHostbasedAcceptedKeyTypes:
1449 charptr = &options->hostbased_key_types;
1450 parse_keytypes:
1451 arg = strdelim(&cp);
1452 if (!arg || *arg == '\0')
1453 fatal("%s line %d: Missing argument.",
1454 filename, linenum);
ce74baca
MD
1455 if (*arg != '-' &&
1456 !sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
e9778795
PA
1457 fatal("%s line %d: Bad key types '%s'.",
1458 filename, linenum, arg ? arg : "<NONE>");
1459 if (*activep && *charptr == NULL)
1460 *charptr = xstrdup(arg);
1461 break;
1462
1463 case sHostKeyAlgorithms:
1464 charptr = &options->hostkeyalgorithms;
1465 goto parse_keytypes;
1466
664f4763 1467 case sCASignatureAlgorithms:
1468 charptr = &options->ca_sign_algorithms;
1469 goto parse_keytypes;
1470
16c343f1
PA
1471 case sPubkeyAuthentication:
1472 intptr = &options->pubkey_authentication;
1473 goto parse_flag;
1474
e9778795
PA
1475 case sPubkeyAcceptedKeyTypes:
1476 charptr = &options->pubkey_key_types;
1477 goto parse_keytypes;
1478
16c343f1
PA
1479 case sKerberosAuthentication:
1480 intptr = &options->kerberos_authentication;
1481 goto parse_flag;
1482
1483 case sKerberosOrLocalPasswd:
1484 intptr = &options->kerberos_or_local_passwd;
1485 goto parse_flag;
1486
1487 case sKerberosTicketCleanup:
1488 intptr = &options->kerberos_ticket_cleanup;
1489 goto parse_flag;
1490
1491 case sKerberosGetAFSToken:
1492 intptr = &options->kerberos_get_afs_token;
1493 goto parse_flag;
1494
1495 case sGssAuthentication:
1496 intptr = &options->gss_authentication;
1497 goto parse_flag;
1498
1499 case sGssCleanupCreds:
1500 intptr = &options->gss_cleanup_creds;
1501 goto parse_flag;
1502
e9778795
PA
1503 case sGssStrictAcceptor:
1504 intptr = &options->gss_strict_acceptor;
1505 goto parse_flag;
1506
16c343f1
PA
1507 case sPasswordAuthentication:
1508 intptr = &options->password_authentication;
1509 goto parse_flag;
1510
1511 case sKbdInteractiveAuthentication:
1512 intptr = &options->kbd_interactive_authentication;
1513 goto parse_flag;
1514
1515 case sChallengeResponseAuthentication:
1516 intptr = &options->challenge_response_authentication;
1517 goto parse_flag;
1518
1519 case sPrintMotd:
1520 intptr = &options->print_motd;
1521 goto parse_flag;
1522
1523 case sPrintLastLog:
1524 intptr = &options->print_lastlog;
1525 goto parse_flag;
1526
1527 case sX11Forwarding:
1528 intptr = &options->x11_forwarding;
1529 goto parse_flag;
1530
1531 case sX11DisplayOffset:
1532 intptr = &options->x11_display_offset;
ce74baca
MD
1533 parse_int:
1534 arg = strdelim(&cp);
664f4763 1535 if ((errstr = atoi_err(arg, &value)) != NULL)
1536 fatal("%s line %d: integer value %s.",
1537 filename, linenum, errstr);
ce74baca
MD
1538 if (*activep && *intptr == -1)
1539 *intptr = value;
1540 break;
16c343f1
PA
1541
1542 case sX11UseLocalhost:
1543 intptr = &options->x11_use_localhost;
1544 goto parse_flag;
1545
1546 case sXAuthLocation:
1547 charptr = &options->xauth_location;
1548 goto parse_filename;
1549
36e94dc5
PA
1550 case sPermitTTY:
1551 intptr = &options->permit_tty;
1552 goto parse_flag;
1553
1554 case sPermitUserRC:
1555 intptr = &options->permit_user_rc;
1556 goto parse_flag;
1557
16c343f1
PA
1558 case sStrictModes:
1559 intptr = &options->strict_modes;
1560 goto parse_flag;
1561
1562 case sTCPKeepAlive:
1563 intptr = &options->tcp_keep_alive;
1564 goto parse_flag;
1565
1566 case sEmptyPasswd:
1567 intptr = &options->permit_empty_passwd;
1568 goto parse_flag;
1569
1570 case sPermitUserEnvironment:
1571 intptr = &options->permit_user_env;
664f4763 1572 charptr = &options->permit_user_env_whitelist;
1573 arg = strdelim(&cp);
1574 if (!arg || *arg == '\0')
1575 fatal("%s line %d: missing argument.",
1576 filename, linenum);
1577 value = 0;
1578 p = NULL;
1579 if (strcmp(arg, "yes") == 0)
1580 value = 1;
1581 else if (strcmp(arg, "no") == 0)
1582 value = 0;
1583 else {
1584 /* Pattern-list specified */
1585 value = 1;
1586 p = xstrdup(arg);
1587 }
1588 if (*activep && *intptr == -1) {
1589 *intptr = value;
1590 *charptr = p;
1591 p = NULL;
1592 }
1593 free(p);
1594 break;
16c343f1 1595
16c343f1
PA
1596 case sCompression:
1597 intptr = &options->compression;
1c188a7f
PA
1598 multistate_ptr = multistate_compression;
1599 goto parse_multistate;
16c343f1 1600
36e94dc5
PA
1601 case sRekeyLimit:
1602 arg = strdelim(&cp);
1603 if (!arg || *arg == '\0')
1604 fatal("%.200s line %d: Missing argument.", filename,
1605 linenum);
1606 if (strcmp(arg, "default") == 0) {
1607 val64 = 0;
1608 } else {
1609 if (scan_scaled(arg, &val64) == -1)
1610 fatal("%.200s line %d: Bad number '%s': %s",
1611 filename, linenum, arg, strerror(errno));
36e94dc5
PA
1612 if (val64 != 0 && val64 < 16)
1613 fatal("%.200s line %d: RekeyLimit too small",
1614 filename, linenum);
1615 }
1616 if (*activep && options->rekey_limit == -1)
e9778795 1617 options->rekey_limit = val64;
36e94dc5
PA
1618 if (cp != NULL) { /* optional rekey interval present */
1619 if (strcmp(cp, "none") == 0) {
1620 (void)strdelim(&cp); /* discard */
1621 break;
1622 }
1623 intptr = &options->rekey_interval;
1624 goto parse_time;
1625 }
1626 break;
1627
16c343f1 1628 case sGatewayPorts:
36e94dc5 1629 intptr = &options->fwd_opts.gateway_ports;
1c188a7f
PA
1630 multistate_ptr = multistate_gatewayports;
1631 goto parse_multistate;
16c343f1
PA
1632
1633 case sUseDNS:
1634 intptr = &options->use_dns;
1635 goto parse_flag;
1636
1637 case sLogFacility:
1638 log_facility_ptr = &options->log_facility;
1639 arg = strdelim(&cp);
1640 value = log_facility_number(arg);
1641 if (value == SYSLOG_FACILITY_NOT_SET)
1642 fatal("%.200s line %d: unsupported log facility '%s'",
1643 filename, linenum, arg ? arg : "<NONE>");
1644 if (*log_facility_ptr == -1)
1645 *log_facility_ptr = (SyslogFacility) value;
1646 break;
1647
1648 case sLogLevel:
1649 log_level_ptr = &options->log_level;
1650 arg = strdelim(&cp);
1651 value = log_level_number(arg);
1652 if (value == SYSLOG_LEVEL_NOT_SET)
1653 fatal("%.200s line %d: unsupported log level '%s'",
1654 filename, linenum, arg ? arg : "<NONE>");
ce74baca 1655 if (*activep && *log_level_ptr == -1)
16c343f1
PA
1656 *log_level_ptr = (LogLevel) value;
1657 break;
1658
1659 case sAllowTcpForwarding:
1660 intptr = &options->allow_tcp_forwarding;
36e94dc5
PA
1661 multistate_ptr = multistate_tcpfwd;
1662 goto parse_multistate;
1663
1664 case sAllowStreamLocalForwarding:
1665 intptr = &options->allow_streamlocal_forwarding;
1666 multistate_ptr = multistate_tcpfwd;
1667 goto parse_multistate;
16c343f1 1668
3b69e377
PA
1669 case sAllowAgentForwarding:
1670 intptr = &options->allow_agent_forwarding;
1671 goto parse_flag;
1672
ce74baca
MD
1673 case sDisableForwarding:
1674 intptr = &options->disable_forwarding;
1675 goto parse_flag;
16c343f1
PA
1676
1677 case sAllowUsers:
1678 while ((arg = strdelim(&cp)) && *arg != '\0') {
ce74baca
MD
1679 if (match_user(NULL, NULL, NULL, arg) == -1)
1680 fatal("%s line %d: invalid AllowUsers pattern: "
1681 "\"%.100s\"", filename, linenum, arg);
99e85e0d
PA
1682 if (!*activep)
1683 continue;
664f4763 1684 array_append(filename, linenum, "AllowUsers",
1685 &options->allow_users, &options->num_allow_users,
1686 arg);
16c343f1
PA
1687 }
1688 break;
1689
1690 case sDenyUsers:
1691 while ((arg = strdelim(&cp)) && *arg != '\0') {
ce74baca
MD
1692 if (match_user(NULL, NULL, NULL, arg) == -1)
1693 fatal("%s line %d: invalid DenyUsers pattern: "
1694 "\"%.100s\"", filename, linenum, arg);
99e85e0d
PA
1695 if (!*activep)
1696 continue;
664f4763 1697 array_append(filename, linenum, "DenyUsers",
1698 &options->deny_users, &options->num_deny_users,
1699 arg);
16c343f1
PA
1700 }
1701 break;
1702
1703 case sAllowGroups:
1704 while ((arg = strdelim(&cp)) && *arg != '\0') {
99e85e0d
PA
1705 if (!*activep)
1706 continue;
664f4763 1707 array_append(filename, linenum, "AllowGroups",
1708 &options->allow_groups, &options->num_allow_groups,
1709 arg);
16c343f1
PA
1710 }
1711 break;
1712
1713 case sDenyGroups:
1714 while ((arg = strdelim(&cp)) && *arg != '\0') {
99e85e0d
PA
1715 if (!*activep)
1716 continue;
664f4763 1717 array_append(filename, linenum, "DenyGroups",
1718 &options->deny_groups, &options->num_deny_groups,
1719 arg);
16c343f1
PA
1720 }
1721 break;
1722
1723 case sCiphers:
1724 arg = strdelim(&cp);
1725 if (!arg || *arg == '\0')
1726 fatal("%s line %d: Missing argument.", filename, linenum);
ce74baca 1727 if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
16c343f1
PA
1728 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1729 filename, linenum, arg ? arg : "<NONE>");
1730 if (options->ciphers == NULL)
1731 options->ciphers = xstrdup(arg);
1732 break;
1733
1734 case sMacs:
1735 arg = strdelim(&cp);
1736 if (!arg || *arg == '\0')
1737 fatal("%s line %d: Missing argument.", filename, linenum);
ce74baca 1738 if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
16c343f1
PA
1739 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1740 filename, linenum, arg ? arg : "<NONE>");
1741 if (options->macs == NULL)
1742 options->macs = xstrdup(arg);
1743 break;
1744
9f304aaf
PA
1745 case sKexAlgorithms:
1746 arg = strdelim(&cp);
1747 if (!arg || *arg == '\0')
1748 fatal("%s line %d: Missing argument.",
1749 filename, linenum);
ce74baca
MD
1750 if (*arg != '-' &&
1751 !kex_names_valid(*arg == '+' ? arg + 1 : arg))
9f304aaf
PA
1752 fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
1753 filename, linenum, arg ? arg : "<NONE>");
1754 if (options->kex_algorithms == NULL)
1755 options->kex_algorithms = xstrdup(arg);
1756 break;
1757
16c343f1
PA
1758 case sSubsystem:
1759 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1760 fatal("%s line %d: too many subsystems defined.",
1761 filename, linenum);
1762 }
1763 arg = strdelim(&cp);
1764 if (!arg || *arg == '\0')
1765 fatal("%s line %d: Missing subsystem name.",
1766 filename, linenum);
1767 if (!*activep) {
1768 arg = strdelim(&cp);
1769 break;
1770 }
1771 for (i = 0; i < options->num_subsystems; i++)
1772 if (strcmp(arg, options->subsystem_name[i]) == 0)
1773 fatal("%s line %d: Subsystem '%s' already defined.",
1774 filename, linenum, arg);
1775 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1776 arg = strdelim(&cp);
1777 if (!arg || *arg == '\0')
1778 fatal("%s line %d: Missing subsystem command.",
1779 filename, linenum);
1780 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
1781
1782 /* Collect arguments (separate to executable) */
1783 p = xstrdup(arg);
1784 len = strlen(p) + 1;
1785 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1786 len += 1 + strlen(arg);
e9778795 1787 p = xreallocarray(p, 1, len);
16c343f1
PA
1788 strlcat(p, " ", len);
1789 strlcat(p, arg, len);
1790 }
1791 options->subsystem_args[options->num_subsystems] = p;
1792 options->num_subsystems++;
1793 break;
1794
1795 case sMaxStartups:
1796 arg = strdelim(&cp);
1797 if (!arg || *arg == '\0')
1798 fatal("%s line %d: Missing MaxStartups spec.",
1799 filename, linenum);
1800 if ((n = sscanf(arg, "%d:%d:%d",
1801 &options->max_startups_begin,
1802 &options->max_startups_rate,
1803 &options->max_startups)) == 3) {
1804 if (options->max_startups_begin >
1805 options->max_startups ||
1806 options->max_startups_rate > 100 ||
1807 options->max_startups_rate < 1)
1808 fatal("%s line %d: Illegal MaxStartups spec.",
1809 filename, linenum);
1810 } else if (n != 1)
1811 fatal("%s line %d: Illegal MaxStartups spec.",
1812 filename, linenum);
1813 else
1814 options->max_startups = options->max_startups_begin;
1815 break;
1816
1817 case sMaxAuthTries:
1818 intptr = &options->max_authtries;
1819 goto parse_int;
1820
3b69e377
PA
1821 case sMaxSessions:
1822 intptr = &options->max_sessions;
1823 goto parse_int;
1824
16c343f1
PA
1825 case sBanner:
1826 charptr = &options->banner;
1827 goto parse_filename;
1828
1829 /*
1830 * These options can contain %X options expanded at
1831 * connect time, so that you can specify paths like:
1832 *
1833 * AuthorizedKeysFile /etc/ssh_keys/%u
1834 */
1835 case sAuthorizedKeysFile:
1c188a7f
PA
1836 if (*activep && options->num_authkeys_files == 0) {
1837 while ((arg = strdelim(&cp)) && *arg != '\0') {
664f4763 1838 arg = tilde_expand_filename(arg, getuid());
1839 array_append(filename, linenum,
1840 "AuthorizedKeysFile",
1841 &options->authorized_keys_files,
1842 &options->num_authkeys_files, arg);
1843 free(arg);
1c188a7f
PA
1844 }
1845 }
1846 return 0;
1847
856ea928
PA
1848 case sAuthorizedPrincipalsFile:
1849 charptr = &options->authorized_principals_file;
856ea928
PA
1850 arg = strdelim(&cp);
1851 if (!arg || *arg == '\0')
1852 fatal("%s line %d: missing file name.",
1853 filename, linenum);
1854 if (*activep && *charptr == NULL) {
1855 *charptr = tilde_expand_filename(arg, getuid());
1856 /* increase optional counter */
1857 if (intptr != NULL)
1858 *intptr = *intptr + 1;
1859 }
1860 break;
16c343f1
PA
1861
1862 case sClientAliveInterval:
1863 intptr = &options->client_alive_interval;
1864 goto parse_time;
1865
1866 case sClientAliveCountMax:
1867 intptr = &options->client_alive_count_max;
1868 goto parse_int;
1869
1870 case sAcceptEnv:
1871 while ((arg = strdelim(&cp)) && *arg != '\0') {
1872 if (strchr(arg, '=') != NULL)
1873 fatal("%s line %d: Invalid environment name.",
1874 filename, linenum);
16c343f1 1875 if (!*activep)
99e85e0d 1876 continue;
664f4763 1877 array_append(filename, linenum, "AcceptEnv",
1878 &options->accept_env, &options->num_accept_env,
1879 arg);
1880 }
1881 break;
1882
1883 case sSetEnv:
1884 uvalue = options->num_setenv;
1885 while ((arg = strdelimw(&cp)) && *arg != '\0') {
1886 if (strchr(arg, '=') == NULL)
1887 fatal("%s line %d: Invalid environment.",
1888 filename, linenum);
1889 if (!*activep || uvalue != 0)
1890 continue;
1891 array_append(filename, linenum, "SetEnv",
1892 &options->setenv, &options->num_setenv, arg);
16c343f1
PA
1893 }
1894 break;
1895
1896 case sPermitTunnel:
1897 intptr = &options->permit_tun;
1898 arg = strdelim(&cp);
1899 if (!arg || *arg == '\0')
1900 fatal("%s line %d: Missing yes/point-to-point/"
1901 "ethernet/no argument.", filename, linenum);
3b69e377
PA
1902 value = -1;
1903 for (i = 0; tunmode_desc[i].val != -1; i++)
1904 if (strcmp(tunmode_desc[i].text, arg) == 0) {
1905 value = tunmode_desc[i].val;
1906 break;
1907 }
1908 if (value == -1)
16c343f1
PA
1909 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1910 "no argument: %s", filename, linenum, arg);
e9778795 1911 if (*activep && *intptr == -1)
16c343f1
PA
1912 *intptr = value;
1913 break;
1914
1915 case sMatch:
1916 if (cmdline)
1917 fatal("Match directive not supported as a command-line "
1918 "option");
99e85e0d 1919 value = match_cfg_line(&cp, linenum, connectinfo);
16c343f1
PA
1920 if (value < 0)
1921 fatal("%s line %d: Bad Match condition", filename,
1922 linenum);
1923 *activep = value;
1924 break;
1925
664f4763 1926 case sPermitListen:
16c343f1 1927 case sPermitOpen:
664f4763 1928 if (opcode == sPermitListen) {
1929 uintptr = &options->num_permitted_listens;
1930 chararrayptr = &options->permitted_listens;
1931 } else {
1932 uintptr = &options->num_permitted_opens;
1933 chararrayptr = &options->permitted_opens;
1934 }
16c343f1
PA
1935 arg = strdelim(&cp);
1936 if (!arg || *arg == '\0')
664f4763 1937 fatal("%s line %d: missing %s specification",
1938 filename, linenum, lookup_opcode_name(opcode));
1939 uvalue = *uintptr; /* modified later */
ce74baca 1940 if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
664f4763 1941 if (*activep && uvalue == 0) {
1942 *uintptr = 1;
1943 *chararrayptr = xcalloc(1,
1944 sizeof(**chararrayptr));
1945 (*chararrayptr)[0] = xstrdup(arg);
99e85e0d
PA
1946 }
1947 break;
1948 }
16c343f1 1949 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
664f4763 1950 if (opcode == sPermitListen &&
1951 strchr(arg, ':') == NULL) {
1952 /*
1953 * Allow bare port number for PermitListen
1954 * to indicate a wildcard listen host.
1955 */
1956 xasprintf(&arg2, "*:%s", arg);
1957 } else {
1958 arg2 = xstrdup(arg);
1959 ch = '\0';
1960 p = hpdelim2(&arg, &ch);
1961 if (p == NULL || ch == '/') {
1962 fatal("%s line %d: missing host in %s",
1963 filename, linenum,
1964 lookup_opcode_name(opcode));
1965 }
1966 p = cleanhostname(p);
1967 }
1968 if (arg == NULL ||
1969 ((port = permitopen_port(arg)) < 0)) {
1970 fatal("%s line %d: bad port number in %s",
1971 filename, linenum,
1972 lookup_opcode_name(opcode));
1973 }
1974 if (*activep && uvalue == 0) {
1975 array_append(filename, linenum,
1976 lookup_opcode_name(opcode),
1977 chararrayptr, uintptr, arg2);
1978 }
1979 free(arg2);
16c343f1
PA
1980 }
1981 break;
1982
1983 case sForceCommand:
e9778795 1984 if (cp == NULL || *cp == '\0')
16c343f1
PA
1985 fatal("%.200s line %d: Missing argument.", filename,
1986 linenum);
1987 len = strspn(cp, WHITESPACE);
1988 if (*activep && options->adm_forced_command == NULL)
1989 options->adm_forced_command = xstrdup(cp + len);
1990 return 0;
1991
1992 case sChrootDirectory:
1993 charptr = &options->chroot_directory;
1994
1995 arg = strdelim(&cp);
1996 if (!arg || *arg == '\0')
1997 fatal("%s line %d: missing file name.",
1998 filename, linenum);
1999 if (*activep && *charptr == NULL)
2000 *charptr = xstrdup(arg);
2001 break;
2002
856ea928
PA
2003 case sTrustedUserCAKeys:
2004 charptr = &options->trusted_user_ca_keys;
2005 goto parse_filename;
2006
2007 case sRevokedKeys:
2008 charptr = &options->revoked_keys_file;
2009 goto parse_filename;
2010
9f304aaf
PA
2011 case sIPQoS:
2012 arg = strdelim(&cp);
2013 if ((value = parse_ipqos(arg)) == -1)
2014 fatal("%s line %d: Bad IPQoS value: %s",
2015 filename, linenum, arg);
2016 arg = strdelim(&cp);
2017 if (arg == NULL)
2018 value2 = value;
2019 else if ((value2 = parse_ipqos(arg)) == -1)
2020 fatal("%s line %d: Bad IPQoS value: %s",
2021 filename, linenum, arg);
2022 if (*activep) {
2023 options->ip_qos_interactive = value;
2024 options->ip_qos_bulk = value2;
2025 }
2026 break;
2027
99e85e0d 2028 case sVersionAddendum:
e9778795 2029 if (cp == NULL || *cp == '\0')
99e85e0d
PA
2030 fatal("%.200s line %d: Missing argument.", filename,
2031 linenum);
2032 len = strspn(cp, WHITESPACE);
2033 if (*activep && options->version_addendum == NULL) {
2034 if (strcasecmp(cp + len, "none") == 0)
2035 options->version_addendum = xstrdup("");
2036 else if (strchr(cp + len, '\r') != NULL)
2037 fatal("%.200s line %d: Invalid argument",
2038 filename, linenum);
2039 else
2040 options->version_addendum = xstrdup(cp + len);
2041 }
2042 return 0;
2043
36e94dc5 2044 case sAuthorizedKeysCommand:
e9778795
PA
2045 if (cp == NULL)
2046 fatal("%.200s line %d: Missing argument.", filename,
2047 linenum);
36e94dc5
PA
2048 len = strspn(cp, WHITESPACE);
2049 if (*activep && options->authorized_keys_command == NULL) {
2050 if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
2051 fatal("%.200s line %d: AuthorizedKeysCommand "
2052 "must be an absolute path",
2053 filename, linenum);
2054 options->authorized_keys_command = xstrdup(cp + len);
2055 }
2056 return 0;
2057
2058 case sAuthorizedKeysCommandUser:
2059 charptr = &options->authorized_keys_command_user;
2060
2061 arg = strdelim(&cp);
e9778795
PA
2062 if (!arg || *arg == '\0')
2063 fatal("%s line %d: missing AuthorizedKeysCommandUser "
2064 "argument.", filename, linenum);
2065 if (*activep && *charptr == NULL)
2066 *charptr = xstrdup(arg);
2067 break;
2068
2069 case sAuthorizedPrincipalsCommand:
2070 if (cp == NULL)
2071 fatal("%.200s line %d: Missing argument.", filename,
2072 linenum);
2073 len = strspn(cp, WHITESPACE);
2074 if (*activep &&
2075 options->authorized_principals_command == NULL) {
2076 if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
2077 fatal("%.200s line %d: "
2078 "AuthorizedPrincipalsCommand must be "
2079 "an absolute path", filename, linenum);
2080 options->authorized_principals_command =
2081 xstrdup(cp + len);
2082 }
2083 return 0;
2084
2085 case sAuthorizedPrincipalsCommandUser:
2086 charptr = &options->authorized_principals_command_user;
2087
2088 arg = strdelim(&cp);
2089 if (!arg || *arg == '\0')
2090 fatal("%s line %d: missing "
2091 "AuthorizedPrincipalsCommandUser argument.",
2092 filename, linenum);
36e94dc5
PA
2093 if (*activep && *charptr == NULL)
2094 *charptr = xstrdup(arg);
2095 break;
2096
2097 case sAuthenticationMethods:
e9778795
PA
2098 if (options->num_auth_methods == 0) {
2099 value = 0; /* seen "any" pseudo-method */
664f4763 2100 value2 = 0; /* successfully parsed any method */
36e94dc5 2101 while ((arg = strdelim(&cp)) && *arg != '\0') {
e9778795
PA
2102 if (strcmp(arg, "any") == 0) {
2103 if (options->num_auth_methods > 0) {
2104 fatal("%s line %d: \"any\" "
2105 "must appear alone in "
2106 "AuthenticationMethods",
2107 filename, linenum);
2108 }
2109 value = 1;
2110 } else if (value) {
2111 fatal("%s line %d: \"any\" must appear "
2112 "alone in AuthenticationMethods",
2113 filename, linenum);
2114 } else if (auth2_methods_valid(arg, 0) != 0) {
36e94dc5
PA
2115 fatal("%s line %d: invalid "
2116 "authentication method list.",
2117 filename, linenum);
e9778795
PA
2118 }
2119 value2 = 1;
2120 if (!*activep)
2121 continue;
664f4763 2122 array_append(filename, linenum,
2123 "AuthenticationMethods",
2124 &options->auth_methods,
2125 &options->num_auth_methods, arg);
36e94dc5 2126 }
e9778795
PA
2127 if (value2 == 0) {
2128 fatal("%s line %d: no AuthenticationMethods "
2129 "specified", filename, linenum);
2130 }
36e94dc5
PA
2131 }
2132 return 0;
2133
2134 case sStreamLocalBindMask:
2135 arg = strdelim(&cp);
2136 if (!arg || *arg == '\0')
e9778795
PA
2137 fatal("%s line %d: missing StreamLocalBindMask "
2138 "argument.", filename, linenum);
36e94dc5
PA
2139 /* Parse mode in octal format */
2140 value = strtol(arg, &p, 8);
2141 if (arg == p || value < 0 || value > 0777)
2142 fatal("%s line %d: Bad mask.", filename, linenum);
e9778795
PA
2143 if (*activep)
2144 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
36e94dc5
PA
2145 break;
2146
2147 case sStreamLocalBindUnlink:
2148 intptr = &options->fwd_opts.streamlocal_bind_unlink;
2149 goto parse_flag;
2150
e9778795
PA
2151 case sFingerprintHash:
2152 arg = strdelim(&cp);
2153 if (!arg || *arg == '\0')
2154 fatal("%.200s line %d: Missing argument.",
2155 filename, linenum);
2156 if ((value = ssh_digest_alg_by_name(arg)) == -1)
2157 fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
2158 filename, linenum, arg);
2159 if (*activep)
2160 options->fingerprint_hash = value;
2161 break;
2162
ce74baca
MD
2163 case sExposeAuthInfo:
2164 intptr = &options->expose_userauth_info;
2165 goto parse_flag;
16c343f1 2166
664f4763 2167 case sRDomain:
2168 charptr = &options->routing_domain;
2169 arg = strdelim(&cp);
2170 if (!arg || *arg == '\0')
2171 fatal("%.200s line %d: Missing argument.",
2172 filename, linenum);
2173 if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
2174 !valid_rdomain(arg))
2175 fatal("%s line %d: bad routing domain",
2176 filename, linenum);
2177 if (*activep && *charptr == NULL)
2178 *charptr = xstrdup(arg);
2179 break;
2180
ce74baca
MD
2181 case sDeprecated:
2182 case sIgnore:
16c343f1 2183 case sUnsupported:
ce74baca
MD
2184 do_log2(opcode == sIgnore ?
2185 SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
2186 "%s line %d: %s option %s", filename, linenum,
2187 opcode == sUnsupported ? "Unsupported" : "Deprecated", arg);
16c343f1
PA
2188 while (arg)
2189 arg = strdelim(&cp);
2190 break;
2191
2192 default:
2193 fatal("%s line %d: Missing handler for opcode %s (%d)",
2194 filename, linenum, arg, opcode);
2195 }
2196 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
2197 fatal("%s line %d: garbage at end of line; \"%.200s\".",
2198 filename, linenum, arg);
2199 return 0;
2200}
2201
2202/* Reads the server configuration file. */
2203
2204void
664f4763 2205load_server_config(const char *filename, struct sshbuf *conf)
16c343f1 2206{
664f4763 2207 char *line = NULL, *cp;
2208 size_t linesize = 0;
16c343f1 2209 FILE *f;
664f4763 2210 int r, lineno = 0;
16c343f1
PA
2211
2212 debug2("%s: filename %s", __func__, filename);
2213 if ((f = fopen(filename, "r")) == NULL) {
2214 perror(filename);
2215 exit(1);
2216 }
664f4763 2217 sshbuf_reset(conf);
2218 while (getline(&line, &linesize, f) != -1) {
99e85e0d 2219 lineno++;
16c343f1
PA
2220 /*
2221 * Trim out comments and strip whitespace
2222 * NB - preserve newlines, they are needed to reproduce
2223 * line numbers later for error messages
2224 */
2225 if ((cp = strchr(line, '#')) != NULL)
2226 memcpy(cp, "\n", 2);
2227 cp = line + strspn(line, " \t\r");
664f4763 2228 if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)
2229 fatal("%s: buffer error: %s", __func__, ssh_err(r));
16c343f1 2230 }
664f4763 2231 free(line);
2232 if ((r = sshbuf_put_u8(conf, 0)) != 0)
2233 fatal("%s: buffer error: %s", __func__, ssh_err(r));
16c343f1 2234 fclose(f);
664f4763 2235 debug2("%s: done config len = %zu", __func__, sshbuf_len(conf));
16c343f1
PA
2236}
2237
2238void
99e85e0d
PA
2239parse_server_match_config(ServerOptions *options,
2240 struct connection_info *connectinfo)
16c343f1
PA
2241{
2242 ServerOptions mo;
2243
2244 initialize_server_options(&mo);
664f4763 2245 parse_server_config(&mo, "reprocess config", cfg, connectinfo);
16c343f1
PA
2246 copy_set_server_options(options, &mo, 0);
2247}
2248
99e85e0d
PA
2249int parse_server_match_testspec(struct connection_info *ci, char *spec)
2250{
2251 char *p;
2252
2253 while ((p = strsep(&spec, ",")) && *p != '\0') {
2254 if (strncmp(p, "addr=", 5) == 0) {
2255 ci->address = xstrdup(p + 5);
2256 } else if (strncmp(p, "host=", 5) == 0) {
2257 ci->host = xstrdup(p + 5);
2258 } else if (strncmp(p, "user=", 5) == 0) {
2259 ci->user = xstrdup(p + 5);
2260 } else if (strncmp(p, "laddr=", 6) == 0) {
2261 ci->laddress = xstrdup(p + 6);
664f4763 2262 } else if (strncmp(p, "rdomain=", 8) == 0) {
2263 ci->rdomain = xstrdup(p + 8);
99e85e0d
PA
2264 } else if (strncmp(p, "lport=", 6) == 0) {
2265 ci->lport = a2port(p + 6);
2266 if (ci->lport == -1) {
2267 fprintf(stderr, "Invalid port '%s' in test mode"
2268 " specification %s\n", p+6, p);
2269 return -1;
2270 }
2271 } else {
2272 fprintf(stderr, "Invalid test mode specification %s\n",
2273 p);
2274 return -1;
2275 }
2276 }
2277 return 0;
2278}
2279
16c343f1
PA
2280/*
2281 * Copy any supported values that are set.
2282 *
40c002af 2283 * If the preauth flag is set, we do not bother copying the string or
16c343f1 2284 * array values that are not used pre-authentication, because any that we
664f4763 2285 * do use must be explicitly sent in mm_getpwnamallow().
16c343f1
PA
2286 */
2287void
2288copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
2289{
36e94dc5
PA
2290#define M_CP_INTOPT(n) do {\
2291 if (src->n != -1) \
2292 dst->n = src->n; \
2293} while (0)
2294
16c343f1
PA
2295 M_CP_INTOPT(password_authentication);
2296 M_CP_INTOPT(gss_authentication);
16c343f1
PA
2297 M_CP_INTOPT(pubkey_authentication);
2298 M_CP_INTOPT(kerberos_authentication);
2299 M_CP_INTOPT(hostbased_authentication);
856ea928 2300 M_CP_INTOPT(hostbased_uses_name_from_packet_only);
16c343f1
PA
2301 M_CP_INTOPT(kbd_interactive_authentication);
2302 M_CP_INTOPT(permit_root_login);
cb5eb4f1 2303 M_CP_INTOPT(permit_empty_passwd);
16c343f1
PA
2304
2305 M_CP_INTOPT(allow_tcp_forwarding);
36e94dc5 2306 M_CP_INTOPT(allow_streamlocal_forwarding);
3b69e377 2307 M_CP_INTOPT(allow_agent_forwarding);
ce74baca
MD
2308 M_CP_INTOPT(disable_forwarding);
2309 M_CP_INTOPT(expose_userauth_info);
856ea928 2310 M_CP_INTOPT(permit_tun);
36e94dc5 2311 M_CP_INTOPT(fwd_opts.gateway_ports);
e9778795 2312 M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
16c343f1
PA
2313 M_CP_INTOPT(x11_display_offset);
2314 M_CP_INTOPT(x11_forwarding);
2315 M_CP_INTOPT(x11_use_localhost);
36e94dc5
PA
2316 M_CP_INTOPT(permit_tty);
2317 M_CP_INTOPT(permit_user_rc);
3b69e377
PA
2318 M_CP_INTOPT(max_sessions);
2319 M_CP_INTOPT(max_authtries);
ce74baca
MD
2320 M_CP_INTOPT(client_alive_count_max);
2321 M_CP_INTOPT(client_alive_interval);
9f304aaf
PA
2322 M_CP_INTOPT(ip_qos_interactive);
2323 M_CP_INTOPT(ip_qos_bulk);
36e94dc5
PA
2324 M_CP_INTOPT(rekey_limit);
2325 M_CP_INTOPT(rekey_interval);
ce74baca 2326 M_CP_INTOPT(log_level);
36e94dc5 2327
e9778795
PA
2328 /*
2329 * The bind_mask is a mode_t that may be unsigned, so we can't use
2330 * M_CP_INTOPT - it does a signed comparison that causes compiler
2331 * warnings.
2332 */
2333 if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) {
2334 dst->fwd_opts.streamlocal_bind_mask =
2335 src->fwd_opts.streamlocal_bind_mask;
2336 }
2337
36e94dc5
PA
2338 /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
2339#define M_CP_STROPT(n) do {\
2340 if (src->n != NULL && dst->n != src->n) { \
2341 free(dst->n); \
2342 dst->n = src->n; \
2343 } \
2344} while(0)
664f4763 2345#define M_CP_STRARRAYOPT(s, num_s) do {\
2346 u_int i; \
2347 if (src->num_s != 0) { \
2348 for (i = 0; i < dst->num_s; i++) \
2349 free(dst->s[i]); \
2350 free(dst->s); \
2351 dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \
2352 for (i = 0; i < src->num_s; i++) \
2353 dst->s[i] = xstrdup(src->s[i]); \
2354 dst->num_s = src->num_s; \
ce74baca
MD
2355 } \
2356} while(0)
16c343f1 2357
1c188a7f
PA
2358 /* See comment in servconf.h */
2359 COPY_MATCH_STRING_OPTS();
2360
e9778795
PA
2361 /* Arguments that accept '+...' need to be expanded */
2362 assemble_algorithms(dst);
2363
1c188a7f
PA
2364 /*
2365 * The only things that should be below this point are string options
2366 * which are only used after authentication.
2367 */
16c343f1
PA
2368 if (preauth)
2369 return;
1c188a7f 2370
e9778795 2371 /* These options may be "none" to clear a global setting */
16c343f1 2372 M_CP_STROPT(adm_forced_command);
e9778795
PA
2373 if (option_clear_or_none(dst->adm_forced_command)) {
2374 free(dst->adm_forced_command);
2375 dst->adm_forced_command = NULL;
2376 }
16c343f1 2377 M_CP_STROPT(chroot_directory);
e9778795
PA
2378 if (option_clear_or_none(dst->chroot_directory)) {
2379 free(dst->chroot_directory);
2380 dst->chroot_directory = NULL;
2381 }
16c343f1
PA
2382}
2383
2384#undef M_CP_INTOPT
2385#undef M_CP_STROPT
1c188a7f 2386#undef M_CP_STRARRAYOPT
16c343f1
PA
2387
2388void
664f4763 2389parse_server_config(ServerOptions *options, const char *filename,
2390 struct sshbuf *conf, struct connection_info *connectinfo)
16c343f1
PA
2391{
2392 int active, linenum, bad_options = 0;
2393 char *cp, *obuf, *cbuf;
2394
664f4763 2395 debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf));
16c343f1 2396
e9778795
PA
2397 if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
2398 fatal("%s: sshbuf_dup_string failed", __func__);
99e85e0d 2399 active = connectinfo ? 0 : 1;
16c343f1
PA
2400 linenum = 1;
2401 while ((cp = strsep(&cbuf, "\n")) != NULL) {
2402 if (process_server_config_line(options, cp, filename,
99e85e0d 2403 linenum++, &active, connectinfo) != 0)
16c343f1
PA
2404 bad_options++;
2405 }
36e94dc5 2406 free(obuf);
16c343f1
PA
2407 if (bad_options > 0)
2408 fatal("%s: terminating, %d bad configuration options",
2409 filename, bad_options);
e9778795 2410 process_queued_listen_addrs(options);
16c343f1 2411}
3b69e377
PA
2412
2413static const char *
1c188a7f 2414fmt_multistate_int(int val, const struct multistate *m)
3b69e377 2415{
1c188a7f
PA
2416 u_int i;
2417
2418 for (i = 0; m[i].key != NULL; i++) {
2419 if (m[i].value == val)
2420 return m[i].key;
3b69e377 2421 }
1c188a7f
PA
2422 return "UNKNOWN";
2423}
2424
2425static const char *
2426fmt_intarg(ServerOpCodes code, int val)
2427{
2428 if (val == -1)
2429 return "unset";
2430 switch (code) {
2431 case sAddressFamily:
2432 return fmt_multistate_int(val, multistate_addressfamily);
2433 case sPermitRootLogin:
2434 return fmt_multistate_int(val, multistate_permitrootlogin);
2435 case sGatewayPorts:
2436 return fmt_multistate_int(val, multistate_gatewayports);
2437 case sCompression:
2438 return fmt_multistate_int(val, multistate_compression);
36e94dc5
PA
2439 case sAllowTcpForwarding:
2440 return fmt_multistate_int(val, multistate_tcpfwd);
2441 case sAllowStreamLocalForwarding:
2442 return fmt_multistate_int(val, multistate_tcpfwd);
e9778795
PA
2443 case sFingerprintHash:
2444 return ssh_digest_alg_name(val);
1c188a7f
PA
2445 default:
2446 switch (val) {
2447 case 0:
2448 return "no";
2449 case 1:
2450 return "yes";
2451 default:
2452 return "UNKNOWN";
2453 }
3b69e377 2454 }
3b69e377
PA
2455}
2456
3b69e377
PA
2457static void
2458dump_cfg_int(ServerOpCodes code, int val)
2459{
2460 printf("%s %d\n", lookup_opcode_name(code), val);
2461}
2462
e9778795
PA
2463static void
2464dump_cfg_oct(ServerOpCodes code, int val)
2465{
2466 printf("%s 0%o\n", lookup_opcode_name(code), val);
2467}
2468
3b69e377
PA
2469static void
2470dump_cfg_fmtint(ServerOpCodes code, int val)
2471{
2472 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2473}
2474
2475static void
2476dump_cfg_string(ServerOpCodes code, const char *val)
2477{
e9778795
PA
2478 printf("%s %s\n", lookup_opcode_name(code),
2479 val == NULL ? "none" : val);
3b69e377
PA
2480}
2481
2482static void
2483dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
2484{
2485 u_int i;
2486
2487 for (i = 0; i < count; i++)
1c188a7f
PA
2488 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2489}
2490
2491static void
2492dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
2493{
2494 u_int i;
2495
e9778795
PA
2496 if (count <= 0 && code != sAuthenticationMethods)
2497 return;
1c188a7f
PA
2498 printf("%s", lookup_opcode_name(code));
2499 for (i = 0; i < count; i++)
2500 printf(" %s", vals[i]);
e9778795
PA
2501 if (code == sAuthenticationMethods && count == 0)
2502 printf(" any");
1c188a7f 2503 printf("\n");
3b69e377
PA
2504}
2505
664f4763 2506static char *
2507format_listen_addrs(struct listenaddr *la)
3b69e377 2508{
664f4763 2509 int r;
3b69e377 2510 struct addrinfo *ai;
664f4763 2511 char addr[NI_MAXHOST], port[NI_MAXSERV];
e9778795 2512 char *laddr1 = xstrdup(""), *laddr2 = NULL;
3b69e377 2513
e9778795
PA
2514 /*
2515 * ListenAddress must be after Port. add_one_listen_addr pushes
2516 * addresses onto a stack, so to maintain ordering we need to
2517 * print these in reverse order.
2518 */
664f4763 2519 for (ai = la->addrs; ai; ai = ai->ai_next) {
2520 if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
3b69e377
PA
2521 sizeof(addr), port, sizeof(port),
2522 NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
664f4763 2523 error("getnameinfo: %.100s", ssh_gai_strerror(r));
2524 continue;
2525 }
2526 laddr2 = laddr1;
2527 if (ai->ai_family == AF_INET6) {
2528 xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s",
2529 addr, port,
2530 la->rdomain == NULL ? "" : " rdomain ",
2531 la->rdomain == NULL ? "" : la->rdomain,
2532 laddr2);
3b69e377 2533 } else {
664f4763 2534 xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s",
2535 addr, port,
2536 la->rdomain == NULL ? "" : " rdomain ",
2537 la->rdomain == NULL ? "" : la->rdomain,
2538 laddr2);
3b69e377 2539 }
664f4763 2540 free(laddr2);
2541 }
2542 return laddr1;
2543}
2544
2545void
2546dump_config(ServerOptions *o)
2547{
2548 char *s;
2549 u_int i;
2550
2551 /* these are usually at the top of the config */
2552 for (i = 0; i < o->num_ports; i++)
2553 printf("port %d\n", o->ports[i]);
2554 dump_cfg_fmtint(sAddressFamily, o->address_family);
2555
2556 for (i = 0; i < o->num_listen_addrs; i++) {
2557 s = format_listen_addrs(&o->listen_addrs[i]);
2558 printf("%s", s);
2559 free(s);
3b69e377
PA
2560 }
2561
2562 /* integer arguments */
cb5eb4f1 2563#ifdef USE_PAM
e9778795 2564 dump_cfg_fmtint(sUsePAM, o->use_pam);
cb5eb4f1 2565#endif
3b69e377 2566 dump_cfg_int(sLoginGraceTime, o->login_grace_time);
3b69e377
PA
2567 dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
2568 dump_cfg_int(sMaxAuthTries, o->max_authtries);
cb5eb4f1 2569 dump_cfg_int(sMaxSessions, o->max_sessions);
3b69e377
PA
2570 dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
2571 dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
e9778795 2572 dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
3b69e377
PA
2573
2574 /* formatted integer arguments */
2575 dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
2576 dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
2577 dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
3b69e377
PA
2578 dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
2579 dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
2580 o->hostbased_uses_name_from_packet_only);
3b69e377 2581 dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
cb5eb4f1 2582#ifdef KRB5
3b69e377
PA
2583 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
2584 dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
2585 dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
cb5eb4f1 2586# ifdef USE_AFS
3b69e377 2587 dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
cb5eb4f1
PA
2588# endif
2589#endif
2590#ifdef GSSAPI
3b69e377
PA
2591 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
2592 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
cb5eb4f1 2593#endif
3b69e377
PA
2594 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2595 dump_cfg_fmtint(sKbdInteractiveAuthentication,
2596 o->kbd_interactive_authentication);
2597 dump_cfg_fmtint(sChallengeResponseAuthentication,
2598 o->challenge_response_authentication);
2599 dump_cfg_fmtint(sPrintMotd, o->print_motd);
e9778795 2600#ifndef DISABLE_LASTLOG
3b69e377 2601 dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
e9778795 2602#endif
3b69e377
PA
2603 dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
2604 dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
36e94dc5
PA
2605 dump_cfg_fmtint(sPermitTTY, o->permit_tty);
2606 dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc);
3b69e377
PA
2607 dump_cfg_fmtint(sStrictModes, o->strict_modes);
2608 dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
2609 dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
3b69e377 2610 dump_cfg_fmtint(sCompression, o->compression);
36e94dc5 2611 dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
3b69e377
PA
2612 dump_cfg_fmtint(sUseDNS, o->use_dns);
2613 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
e9778795 2614 dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
ce74baca 2615 dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding);
36e94dc5 2616 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
e9778795 2617 dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
e9778795 2618 dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
ce74baca 2619 dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
3b69e377
PA
2620
2621 /* string arguments */
2622 dump_cfg_string(sPidFile, o->pid_file);
2623 dump_cfg_string(sXAuthLocation, o->xauth_location);
e9778795
PA
2624 dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT);
2625 dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC);
3b69e377 2626 dump_cfg_string(sBanner, o->banner);
3b69e377 2627 dump_cfg_string(sForceCommand, o->adm_forced_command);
856ea928
PA
2628 dump_cfg_string(sChrootDirectory, o->chroot_directory);
2629 dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
2630 dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
2631 dump_cfg_string(sAuthorizedPrincipalsFile,
2632 o->authorized_principals_file);
e9778795
PA
2633 dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0'
2634 ? "none" : o->version_addendum);
36e94dc5
PA
2635 dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
2636 dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
e9778795
PA
2637 dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command);
2638 dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user);
36e94dc5 2639 dump_cfg_string(sHostKeyAgent, o->host_key_agent);
e9778795
PA
2640 dump_cfg_string(sKexAlgorithms,
2641 o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX);
664f4763 2642 dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms ?
2643 o->ca_sign_algorithms : SSH_ALLOWED_CA_SIGALGS);
e9778795
PA
2644 dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ?
2645 o->hostbased_key_types : KEX_DEFAULT_PK_ALG);
2646 dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ?
2647 o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
2648 dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ?
2649 o->pubkey_key_types : KEX_DEFAULT_PK_ALG);
664f4763 2650 dump_cfg_string(sRDomain, o->routing_domain);
3b69e377
PA
2651
2652 /* string arguments requiring a lookup */
2653 dump_cfg_string(sLogLevel, log_level_name(o->log_level));
2654 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
2655
2656 /* string array arguments */
1c188a7f
PA
2657 dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
2658 o->authorized_keys_files);
3b69e377
PA
2659 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
2660 o->host_key_files);
e9778795 2661 dump_cfg_strarray(sHostCertificate, o->num_host_cert_files,
856ea928 2662 o->host_cert_files);
3b69e377
PA
2663 dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
2664 dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
2665 dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
2666 dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
2667 dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
664f4763 2668 dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv);
36e94dc5
PA
2669 dump_cfg_strarray_oneline(sAuthenticationMethods,
2670 o->num_auth_methods, o->auth_methods);
3b69e377
PA
2671
2672 /* other arguments */
2673 for (i = 0; i < o->num_subsystems; i++)
2674 printf("subsystem %s %s\n", o->subsystem_name[i],
2675 o->subsystem_args[i]);
2676
2677 printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
2678 o->max_startups_rate, o->max_startups);
2679
664f4763 2680 s = NULL;
2681 for (i = 0; tunmode_desc[i].val != -1; i++) {
3b69e377
PA
2682 if (tunmode_desc[i].val == o->permit_tun) {
2683 s = tunmode_desc[i].text;
2684 break;
2685 }
664f4763 2686 }
3b69e377
PA
2687 dump_cfg_string(sPermitTunnel, s);
2688
1c188a7f
PA
2689 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2690 printf("%s\n", iptos2str(o->ip_qos_bulk));
9f304aaf 2691
e9778795 2692 printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit,
36e94dc5
PA
2693 o->rekey_interval);
2694
ce74baca
MD
2695 printf("permitopen");
2696 if (o->num_permitted_opens == 0)
2697 printf(" any");
2698 else {
2699 for (i = 0; i < o->num_permitted_opens; i++)
2700 printf(" %s", o->permitted_opens[i]);
2701 }
2702 printf("\n");
664f4763 2703 printf("permitlisten");
2704 if (o->num_permitted_listens == 0)
2705 printf(" any");
2706 else {
2707 for (i = 0; i < o->num_permitted_listens; i++)
2708 printf(" %s", o->permitted_listens[i]);
2709 }
2710 printf("\n");
2711
2712 if (o->permit_user_env_whitelist == NULL) {
2713 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
2714 } else {
2715 printf("permituserenvironment %s\n",
2716 o->permit_user_env_whitelist);
2717 }
2718
3b69e377 2719}