jcs's openbsd hax
openbsd
1/* $OpenBSD: servconf.c,v 1.445 2026/02/17 21:45:07 djm Exp $ */
2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 *
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 */
12
13#include <sys/types.h>
14#include <sys/socket.h>
15#include <sys/queue.h>
16#include <sys/sysctl.h>
17#include <sys/stat.h>
18
19#include <netinet/in.h>
20#include <netinet/ip.h>
21#include <net/route.h>
22
23#include <ctype.h>
24#include <glob.h>
25#include <netdb.h>
26#include <pwd.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <signal.h>
31#include <unistd.h>
32#include <limits.h>
33#include <stdarg.h>
34#include <errno.h>
35#include <util.h>
36
37#include "xmalloc.h"
38#include "ssh.h"
39#include "log.h"
40#include "sshbuf.h"
41#include "misc.h"
42#include "servconf.h"
43#include "pathnames.h"
44#include "cipher.h"
45#include "sshkey.h"
46#include "kex.h"
47#include "mac.h"
48#include "match.h"
49#include "channels.h"
50#include "groupaccess.h"
51#include "canohost.h"
52#include "packet.h"
53#include "ssherr.h"
54#include "hostfile.h"
55#include "auth.h"
56#include "myproposal.h"
57#include "digest.h"
58#include "version.h"
59
60static void add_listen_addr(ServerOptions *, const char *,
61 const char *, int);
62static void add_one_listen_addr(ServerOptions *, const char *,
63 const char *, int);
64static void parse_server_config_depth(ServerOptions *options,
65 const char *filename, struct sshbuf *conf, struct include_list *includes,
66 struct connection_info *connectinfo, int flags, int *activep, int depth);
67
68extern struct sshbuf *cfg;
69
70/* Initializes the server options to their default values. */
71
72void
73initialize_server_options(ServerOptions *options)
74{
75 memset(options, 0, sizeof(*options));
76 options->num_ports = 0;
77 options->ports_from_cmdline = 0;
78 options->queued_listen_addrs = NULL;
79 options->num_queued_listens = 0;
80 options->listen_addrs = NULL;
81 options->num_listen_addrs = 0;
82 options->address_family = -1;
83 options->routing_domain = NULL;
84 options->num_host_key_files = 0;
85 options->num_host_cert_files = 0;
86 options->host_key_agent = NULL;
87 options->pid_file = NULL;
88 options->login_grace_time = -1;
89 options->permit_root_login = PERMIT_NOT_SET;
90 options->ignore_rhosts = -1;
91 options->ignore_user_known_hosts = -1;
92 options->print_motd = -1;
93 options->print_lastlog = -1;
94 options->x11_forwarding = -1;
95 options->x11_display_offset = -1;
96 options->x11_use_localhost = -1;
97 options->permit_tty = -1;
98 options->permit_user_rc = -1;
99 options->xauth_location = NULL;
100 options->strict_modes = -1;
101 options->tcp_keep_alive = -1;
102 options->log_facility = SYSLOG_FACILITY_NOT_SET;
103 options->log_level = SYSLOG_LEVEL_NOT_SET;
104 options->num_log_verbose = 0;
105 options->log_verbose = NULL;
106 options->hostbased_authentication = -1;
107 options->hostbased_uses_name_from_packet_only = -1;
108 options->hostbased_accepted_algos = NULL;
109 options->hostkeyalgorithms = NULL;
110 options->pubkey_authentication = -1;
111 options->pubkey_auth_options = -1;
112 options->pubkey_accepted_algos = NULL;
113 options->kerberos_authentication = -1;
114 options->kerberos_or_local_passwd = -1;
115 options->kerberos_ticket_cleanup = -1;
116 options->kerberos_get_afs_token = -1;
117 options->gss_authentication=-1;
118 options->gss_cleanup_creds = -1;
119 options->gss_deleg_creds = -1;
120 options->gss_strict_acceptor = -1;
121 options->password_authentication = -1;
122 options->kbd_interactive_authentication = -1;
123 options->permit_empty_passwd = -1;
124 options->permit_user_env = -1;
125 options->permit_user_env_allowlist = NULL;
126 options->compression = -1;
127 options->rekey_limit = -1;
128 options->rekey_interval = -1;
129 options->allow_tcp_forwarding = -1;
130 options->allow_streamlocal_forwarding = -1;
131 options->allow_agent_forwarding = -1;
132 options->num_allow_users = 0;
133 options->num_deny_users = 0;
134 options->num_allow_groups = 0;
135 options->num_deny_groups = 0;
136 options->ciphers = NULL;
137 options->macs = NULL;
138 options->kex_algorithms = NULL;
139 options->ca_sign_algorithms = NULL;
140 options->fwd_opts.gateway_ports = -1;
141 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
142 options->fwd_opts.streamlocal_bind_unlink = -1;
143 options->num_subsystems = 0;
144 options->max_startups_begin = -1;
145 options->max_startups_rate = -1;
146 options->max_startups = -1;
147 options->per_source_max_startups = -1;
148 options->per_source_masklen_ipv4 = -1;
149 options->per_source_masklen_ipv6 = -1;
150 options->per_source_penalty_exempt = NULL;
151 options->per_source_penalty.enabled = -1;
152 options->per_source_penalty.max_sources4 = -1;
153 options->per_source_penalty.max_sources6 = -1;
154 options->per_source_penalty.overflow_mode = -1;
155 options->per_source_penalty.overflow_mode6 = -1;
156 options->per_source_penalty.penalty_crash = -1.0;
157 options->per_source_penalty.penalty_authfail = -1.0;
158 options->per_source_penalty.penalty_invaliduser = -1.0;
159 options->per_source_penalty.penalty_noauth = -1.0;
160 options->per_source_penalty.penalty_grace = -1.0;
161 options->per_source_penalty.penalty_refuseconnection = -1.0;
162 options->per_source_penalty.penalty_max = -1.0;
163 options->per_source_penalty.penalty_min = -1.0;
164 options->max_authtries = -1;
165 options->max_sessions = -1;
166 options->banner = NULL;
167 options->use_dns = -1;
168 options->client_alive_interval = -1;
169 options->client_alive_count_max = -1;
170 options->num_authkeys_files = 0;
171 options->num_accept_env = 0;
172 options->num_setenv = 0;
173 options->permit_tun = -1;
174 options->permitted_opens = NULL;
175 options->permitted_listens = NULL;
176 options->adm_forced_command = NULL;
177 options->chroot_directory = NULL;
178 options->authorized_keys_command = NULL;
179 options->authorized_keys_command_user = NULL;
180 options->revoked_keys_files = NULL;
181 options->num_revoked_keys_files = 0;
182 options->sk_provider = NULL;
183 options->trusted_user_ca_keys = NULL;
184 options->authorized_principals_file = NULL;
185 options->authorized_principals_command = NULL;
186 options->authorized_principals_command_user = NULL;
187 options->ip_qos_interactive = -1;
188 options->ip_qos_bulk = -1;
189 options->version_addendum = NULL;
190 options->fingerprint_hash = -1;
191 options->disable_forwarding = -1;
192 options->expose_userauth_info = -1;
193 options->required_rsa_size = -1;
194 options->channel_timeouts = NULL;
195 options->num_channel_timeouts = 0;
196 options->unused_connection_timeout = -1;
197 options->sshd_session_path = NULL;
198 options->sshd_auth_path = NULL;
199 options->refuse_connection = -1;
200}
201
202/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
203static int
204option_clear_or_none(const char *o)
205{
206 return o == NULL || strcasecmp(o, "none") == 0;
207}
208
209static void
210assemble_algorithms(ServerOptions *o)
211{
212 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
213 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
214 int r;
215
216 all_cipher = cipher_alg_list(',', 0);
217 all_mac = mac_alg_list(',');
218 all_kex = kex_alg_list(',');
219 all_key = sshkey_alg_list(0, 0, 1, ',');
220 all_sig = sshkey_alg_list(0, 1, 1, ',');
221 /* remove unsupported algos from default lists */
222 def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
223 def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
224 def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
225 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
226 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
227#define ASSEMBLE(what, defaults, all) \
228 do { \
229 if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
230 fatal_fr(r, "%s", #what); \
231 } while (0)
232 ASSEMBLE(ciphers, def_cipher, all_cipher);
233 ASSEMBLE(macs, def_mac, all_mac);
234 ASSEMBLE(kex_algorithms, def_kex, all_kex);
235 ASSEMBLE(hostkeyalgorithms, def_key, all_key);
236 ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
237 ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
238 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
239#undef ASSEMBLE
240 free(all_cipher);
241 free(all_mac);
242 free(all_kex);
243 free(all_key);
244 free(all_sig);
245 free(def_cipher);
246 free(def_mac);
247 free(def_kex);
248 free(def_key);
249 free(def_sig);
250}
251
252void
253servconf_add_hostkey(const char *file, const int line,
254 ServerOptions *options, const char *path, int userprovided)
255{
256 char *apath = derelativise_path(path);
257
258 opt_array_append2(file, line, "HostKey",
259 &options->host_key_files, &options->host_key_file_userprovided,
260 &options->num_host_key_files, apath, userprovided);
261 free(apath);
262}
263
264void
265servconf_add_hostcert(const char *file, const int line,
266 ServerOptions *options, const char *path)
267{
268 char *apath = derelativise_path(path);
269
270 opt_array_append(file, line, "HostCertificate",
271 &options->host_cert_files, &options->num_host_cert_files, apath);
272 free(apath);
273}
274
275void
276fill_default_server_options(ServerOptions *options)
277{
278 u_int i;
279
280 if (options->num_host_key_files == 0) {
281 /* fill default hostkeys */
282 servconf_add_hostkey("[default]", 0, options,
283 _PATH_HOST_RSA_KEY_FILE, 0);
284 servconf_add_hostkey("[default]", 0, options,
285 _PATH_HOST_ECDSA_KEY_FILE, 0);
286 servconf_add_hostkey("[default]", 0, options,
287 _PATH_HOST_ED25519_KEY_FILE, 0);
288 }
289 /* No certificates by default */
290 if (options->num_ports == 0)
291 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
292 if (options->address_family == -1)
293 options->address_family = AF_UNSPEC;
294 if (options->listen_addrs == NULL)
295 add_listen_addr(options, NULL, NULL, 0);
296 if (options->pid_file == NULL)
297 options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
298 if (options->moduli_file == NULL)
299 options->moduli_file = xstrdup(_PATH_DH_MODULI);
300 if (options->login_grace_time == -1)
301 options->login_grace_time = 120;
302 if (options->permit_root_login == PERMIT_NOT_SET)
303 options->permit_root_login = PERMIT_NO_PASSWD;
304 if (options->ignore_rhosts == -1)
305 options->ignore_rhosts = 1;
306 if (options->ignore_user_known_hosts == -1)
307 options->ignore_user_known_hosts = 0;
308 if (options->print_motd == -1)
309 options->print_motd = 1;
310 if (options->print_lastlog == -1)
311 options->print_lastlog = 1;
312 if (options->x11_forwarding == -1)
313 options->x11_forwarding = 0;
314 if (options->x11_display_offset == -1)
315 options->x11_display_offset = 10;
316 if (options->x11_use_localhost == -1)
317 options->x11_use_localhost = 1;
318 if (options->xauth_location == NULL)
319 options->xauth_location = xstrdup(_PATH_XAUTH);
320 if (options->permit_tty == -1)
321 options->permit_tty = 1;
322 if (options->permit_user_rc == -1)
323 options->permit_user_rc = 1;
324 if (options->strict_modes == -1)
325 options->strict_modes = 1;
326 if (options->tcp_keep_alive == -1)
327 options->tcp_keep_alive = 1;
328 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
329 options->log_facility = SYSLOG_FACILITY_AUTH;
330 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
331 options->log_level = SYSLOG_LEVEL_INFO;
332 if (options->hostbased_authentication == -1)
333 options->hostbased_authentication = 0;
334 if (options->hostbased_uses_name_from_packet_only == -1)
335 options->hostbased_uses_name_from_packet_only = 0;
336 if (options->pubkey_authentication == -1)
337 options->pubkey_authentication = 1;
338 if (options->pubkey_auth_options == -1)
339 options->pubkey_auth_options = 0;
340 if (options->kerberos_authentication == -1)
341 options->kerberos_authentication = 0;
342 if (options->kerberos_or_local_passwd == -1)
343 options->kerberos_or_local_passwd = 1;
344 if (options->kerberos_ticket_cleanup == -1)
345 options->kerberos_ticket_cleanup = 1;
346 if (options->kerberos_get_afs_token == -1)
347 options->kerberos_get_afs_token = 0;
348 if (options->gss_authentication == -1)
349 options->gss_authentication = 0;
350 if (options->gss_cleanup_creds == -1)
351 options->gss_cleanup_creds = 1;
352 if (options->gss_deleg_creds == -1)
353 options->gss_deleg_creds = 1;
354 if (options->gss_strict_acceptor == -1)
355 options->gss_strict_acceptor = 1;
356 if (options->password_authentication == -1)
357 options->password_authentication = 1;
358 if (options->kbd_interactive_authentication == -1)
359 options->kbd_interactive_authentication = 1;
360 if (options->permit_empty_passwd == -1)
361 options->permit_empty_passwd = 0;
362 if (options->permit_user_env == -1) {
363 options->permit_user_env = 0;
364 options->permit_user_env_allowlist = NULL;
365 }
366 if (options->compression == -1)
367#ifdef WITH_ZLIB
368 options->compression = COMP_DELAYED;
369#else
370 options->compression = COMP_NONE;
371#endif
372
373 if (options->rekey_limit == -1)
374 options->rekey_limit = 0;
375 if (options->rekey_interval == -1)
376 options->rekey_interval = 0;
377 if (options->allow_tcp_forwarding == -1)
378 options->allow_tcp_forwarding = FORWARD_ALLOW;
379 if (options->allow_streamlocal_forwarding == -1)
380 options->allow_streamlocal_forwarding = FORWARD_ALLOW;
381 if (options->allow_agent_forwarding == -1)
382 options->allow_agent_forwarding = 1;
383 if (options->fwd_opts.gateway_ports == -1)
384 options->fwd_opts.gateway_ports = 0;
385 if (options->max_startups == -1)
386 options->max_startups = 100;
387 if (options->max_startups_rate == -1)
388 options->max_startups_rate = 30; /* 30% */
389 if (options->max_startups_begin == -1)
390 options->max_startups_begin = 10;
391 if (options->per_source_max_startups == -1)
392 options->per_source_max_startups = INT_MAX;
393 if (options->per_source_masklen_ipv4 == -1)
394 options->per_source_masklen_ipv4 = 32;
395 if (options->per_source_masklen_ipv6 == -1)
396 options->per_source_masklen_ipv6 = 128;
397 if (options->per_source_penalty.enabled == -1)
398 options->per_source_penalty.enabled = 1;
399 if (options->per_source_penalty.max_sources4 == -1)
400 options->per_source_penalty.max_sources4 = 65536;
401 if (options->per_source_penalty.max_sources6 == -1)
402 options->per_source_penalty.max_sources6 = 65536;
403 if (options->per_source_penalty.overflow_mode == -1)
404 options->per_source_penalty.overflow_mode = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
405 if (options->per_source_penalty.overflow_mode6 == -1)
406 options->per_source_penalty.overflow_mode6 = options->per_source_penalty.overflow_mode;
407 if (options->per_source_penalty.penalty_crash < 0.0)
408 options->per_source_penalty.penalty_crash = 90.0;
409 if (options->per_source_penalty.penalty_grace < 0.0)
410 options->per_source_penalty.penalty_grace = 10.0;
411 if (options->per_source_penalty.penalty_authfail < 0.0)
412 options->per_source_penalty.penalty_authfail = 5.0;
413 if (options->per_source_penalty.penalty_invaliduser < 0.0)
414 options->per_source_penalty.penalty_invaliduser = 5.0;
415 if (options->per_source_penalty.penalty_noauth < 0.0)
416 options->per_source_penalty.penalty_noauth = 1.0;
417 if (options->per_source_penalty.penalty_refuseconnection < 0.0)
418 options->per_source_penalty.penalty_refuseconnection = 10.0;
419 if (options->per_source_penalty.penalty_min < 0.0)
420 options->per_source_penalty.penalty_min = 15.0;
421 if (options->per_source_penalty.penalty_max < 0.0)
422 options->per_source_penalty.penalty_max = 600.0;
423 if (options->max_authtries == -1)
424 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
425 if (options->max_sessions == -1)
426 options->max_sessions = DEFAULT_SESSIONS_MAX;
427 if (options->use_dns == -1)
428 options->use_dns = 0;
429 if (options->client_alive_interval == -1)
430 options->client_alive_interval = 0;
431 if (options->client_alive_count_max == -1)
432 options->client_alive_count_max = 3;
433 if (options->num_authkeys_files == 0) {
434 opt_array_append("[default]", 0, "AuthorizedKeysFiles",
435 &options->authorized_keys_files,
436 &options->num_authkeys_files,
437 _PATH_SSH_USER_PERMITTED_KEYS);
438 opt_array_append("[default]", 0, "AuthorizedKeysFiles",
439 &options->authorized_keys_files,
440 &options->num_authkeys_files,
441 _PATH_SSH_USER_PERMITTED_KEYS2);
442 }
443 if (options->permit_tun == -1)
444 options->permit_tun = SSH_TUNMODE_NO;
445 if (options->ip_qos_interactive == -1)
446 options->ip_qos_interactive = IPTOS_DSCP_EF;
447 if (options->ip_qos_bulk == -1)
448 options->ip_qos_bulk = IPTOS_DSCP_CS0;
449 if (options->version_addendum == NULL)
450 options->version_addendum = xstrdup("");
451 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
452 options->fwd_opts.streamlocal_bind_mask = 0177;
453 if (options->fwd_opts.streamlocal_bind_unlink == -1)
454 options->fwd_opts.streamlocal_bind_unlink = 0;
455 if (options->fingerprint_hash == -1)
456 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
457 if (options->disable_forwarding == -1)
458 options->disable_forwarding = 0;
459 if (options->expose_userauth_info == -1)
460 options->expose_userauth_info = 0;
461 if (options->sk_provider == NULL)
462 options->sk_provider = xstrdup("internal");
463 if (options->required_rsa_size == -1)
464 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
465 if (options->unused_connection_timeout == -1)
466 options->unused_connection_timeout = 0;
467 if (options->sshd_session_path == NULL)
468 options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION);
469 if (options->sshd_auth_path == NULL)
470 options->sshd_auth_path = xstrdup(_PATH_SSHD_AUTH);
471 if (options->refuse_connection == -1)
472 options->refuse_connection = 0;
473
474 assemble_algorithms(options);
475
476#define CLEAR_ON_NONE(v) \
477 do { \
478 if (option_clear_or_none(v)) { \
479 free(v); \
480 v = NULL; \
481 } \
482 } while(0)
483#define CLEAR_ON_NONE_ARRAY(v, nv, none) \
484 do { \
485 if (options->nv == 1 && \
486 strcasecmp(options->v[0], none) == 0) { \
487 free(options->v[0]); \
488 free(options->v); \
489 options->v = NULL; \
490 options->nv = 0; \
491 } \
492 } while (0)
493 CLEAR_ON_NONE(options->pid_file);
494 CLEAR_ON_NONE(options->xauth_location);
495 CLEAR_ON_NONE(options->banner);
496 CLEAR_ON_NONE(options->trusted_user_ca_keys);
497 CLEAR_ON_NONE(options->sk_provider);
498 CLEAR_ON_NONE(options->authorized_principals_file);
499 CLEAR_ON_NONE(options->adm_forced_command);
500 CLEAR_ON_NONE(options->chroot_directory);
501 CLEAR_ON_NONE(options->routing_domain);
502 CLEAR_ON_NONE(options->host_key_agent);
503 CLEAR_ON_NONE(options->per_source_penalty_exempt);
504
505 for (i = 0; i < options->num_host_key_files; i++)
506 CLEAR_ON_NONE(options->host_key_files[i]);
507 for (i = 0; i < options->num_host_cert_files; i++)
508 CLEAR_ON_NONE(options->host_cert_files[i]);
509
510 CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
511 CLEAR_ON_NONE_ARRAY(auth_methods, num_auth_methods, "any");
512 CLEAR_ON_NONE_ARRAY(revoked_keys_files, num_revoked_keys_files, "none");
513 CLEAR_ON_NONE_ARRAY(authorized_keys_files, num_authkeys_files, "none");
514#undef CLEAR_ON_NONE
515#undef CLEAR_ON_NONE_ARRAY
516}
517
518/* Keyword tokens. */
519typedef enum {
520 sBadOption, /* == unknown option */
521 sPort, sHostKeyFile, sLoginGraceTime,
522 sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
523 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
524 sKerberosGetAFSToken, sPasswordAuthentication,
525 sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
526 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
527 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
528 sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
529 sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
530 sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
531 sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sModuliFile,
532 sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms,
533 sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
534 sBanner, sUseDNS, sHostbasedAuthentication,
535 sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms,
536 sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize,
537 sPerSourcePenalties, sPerSourcePenaltyExemptList,
538 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
539 sGssAuthentication, sGssCleanupCreds, sGssDelegateCreds, sGssStrictAcceptor,
540 sAcceptEnv, sSetEnv, sPermitTunnel,
541 sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
542 sUsePrivilegeSeparation, sAllowAgentForwarding,
543 sHostCertificate, sInclude,
544 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
545 sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
546 sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
547 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
548 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
549 sStreamLocalBindMask, sStreamLocalBindUnlink,
550 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
551 sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
552 sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout,
553 sSshdSessionPath, sSshdAuthPath, sRefuseConnection,
554 sDeprecated, sIgnore, sUnsupported
555} ServerOpCodes;
556
557#define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */
558#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
559#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
560#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */
561#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */
562
563/* Textual representation of the tokens. */
564static struct {
565 const char *name;
566 ServerOpCodes opcode;
567 u_int flags;
568} keywords[] = {
569 { "port", sPort, SSHCFG_GLOBAL },
570 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
571 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
572 { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
573 { "pidfile", sPidFile, SSHCFG_GLOBAL },
574 { "modulifile", sModuliFile, SSHCFG_GLOBAL },
575 { "serverkeybits", sDeprecated, SSHCFG_GLOBAL },
576 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
577 { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL },
578 { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
579 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
580 { "loglevel", sLogLevel, SSHCFG_ALL },
581 { "logverbose", sLogVerbose, SSHCFG_ALL },
582 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
583 { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL },
584 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
585 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
586 { "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL },
587 { "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */
588 { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL },
589 { "rsaauthentication", sDeprecated, SSHCFG_ALL },
590 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
591 { "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL },
592 { "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */
593 { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL },
594 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
595#ifdef KRB5
596 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
597 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
598 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
599 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
600#else
601 { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
602 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
603 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
604 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
605#endif
606 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
607 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
608#ifdef GSSAPI
609 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
610 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
611 { "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_GLOBAL },
612 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
613#else
614 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
615 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
616 { "gssapidelegatecredentials", sUnsupported, SSHCFG_GLOBAL },
617 { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
618#endif
619 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
620 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
621 { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */
622 { "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */
623 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
624 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
625 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
626 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
627 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
628 { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL },
629 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
630 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
631 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
632 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
633 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
634 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
635 { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
636 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
637 { "uselogin", sDeprecated, SSHCFG_GLOBAL },
638 { "compression", sCompression, SSHCFG_GLOBAL },
639 { "rekeylimit", sRekeyLimit, SSHCFG_ALL },
640 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
641 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
642 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
643 { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
644 { "allowusers", sAllowUsers, SSHCFG_ALL },
645 { "denyusers", sDenyUsers, SSHCFG_ALL },
646 { "allowgroups", sAllowGroups, SSHCFG_ALL },
647 { "denygroups", sDenyGroups, SSHCFG_ALL },
648 { "ciphers", sCiphers, SSHCFG_GLOBAL },
649 { "macs", sMacs, SSHCFG_GLOBAL },
650 { "protocol", sIgnore, SSHCFG_GLOBAL },
651 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
652 { "subsystem", sSubsystem, SSHCFG_ALL },
653 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
654 { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL },
655 { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL },
656 { "persourcepenalties", sPerSourcePenalties, SSHCFG_GLOBAL },
657 { "persourcepenaltyexemptlist", sPerSourcePenaltyExemptList, SSHCFG_GLOBAL },
658 { "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
659 { "maxsessions", sMaxSessions, SSHCFG_ALL },
660 { "banner", sBanner, SSHCFG_ALL },
661 { "usedns", sUseDNS, SSHCFG_GLOBAL },
662 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
663 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
664 { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
665 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
666 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
667 { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
668 { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL},
669 { "acceptenv", sAcceptEnv, SSHCFG_ALL },
670 { "setenv", sSetEnv, SSHCFG_ALL },
671 { "permittunnel", sPermitTunnel, SSHCFG_ALL },
672 { "permittty", sPermitTTY, SSHCFG_ALL },
673 { "permituserrc", sPermitUserRC, SSHCFG_ALL },
674 { "match", sMatch, SSHCFG_ALL },
675 { "permitopen", sPermitOpen, SSHCFG_ALL },
676 { "permitlisten", sPermitListen, SSHCFG_ALL },
677 { "forcecommand", sForceCommand, SSHCFG_ALL },
678 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
679 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
680 { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
681 { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
682 { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
683 { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
684 { "include", sInclude, SSHCFG_ALL },
685 { "ipqos", sIPQoS, SSHCFG_ALL },
686 { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
687 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
688 { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL },
689 { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL },
690 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
691 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
692 { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
693 { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
694 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
695 { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
696 { "disableforwarding", sDisableForwarding, SSHCFG_ALL },
697 { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
698 { "rdomain", sRDomain, SSHCFG_ALL },
699 { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
700 { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
701 { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
702 { "channeltimeout", sChannelTimeout, SSHCFG_ALL },
703 { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
704 { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
705 { "sshdauthpath", sSshdAuthPath, SSHCFG_GLOBAL },
706 { "refuseconnection", sRefuseConnection, SSHCFG_ALL },
707 { NULL, sBadOption, 0 }
708};
709
710static struct {
711 int val;
712 char *text;
713} tunmode_desc[] = {
714 { SSH_TUNMODE_NO, "no" },
715 { SSH_TUNMODE_POINTOPOINT, "point-to-point" },
716 { SSH_TUNMODE_ETHERNET, "ethernet" },
717 { SSH_TUNMODE_YES, "yes" },
718 { -1, NULL }
719};
720
721/* Returns an opcode name from its number */
722
723static const char *
724lookup_opcode_name(ServerOpCodes code)
725{
726 u_int i;
727
728 for (i = 0; keywords[i].name != NULL; i++)
729 if (keywords[i].opcode == code)
730 return(keywords[i].name);
731 return "UNKNOWN";
732}
733
734
735/*
736 * Returns the number of the token pointed to by cp or sBadOption.
737 */
738
739static ServerOpCodes
740parse_token(const char *cp, const char *filename,
741 int linenum, u_int *flags)
742{
743 u_int i;
744
745 for (i = 0; keywords[i].name; i++)
746 if (strcasecmp(cp, keywords[i].name) == 0) {
747 *flags = keywords[i].flags;
748 return keywords[i].opcode;
749 }
750
751 error("%s: line %d: Bad configuration option: %s",
752 filename, linenum, cp);
753 return sBadOption;
754}
755
756char *
757derelativise_path(const char *path)
758{
759 char *expanded, *ret, cwd[PATH_MAX];
760
761 if (strcasecmp(path, "none") == 0)
762 return xstrdup("none");
763 expanded = tilde_expand_filename(path, getuid());
764 if (path_absolute(expanded))
765 return expanded;
766 if (getcwd(cwd, sizeof(cwd)) == NULL)
767 fatal_f("getcwd: %s", strerror(errno));
768 xasprintf(&ret, "%s/%s", cwd, expanded);
769 free(expanded);
770 return ret;
771}
772
773static void
774add_listen_addr(ServerOptions *options, const char *addr,
775 const char *rdomain, int port)
776{
777 u_int i;
778
779 if (port > 0)
780 add_one_listen_addr(options, addr, rdomain, port);
781 else {
782 for (i = 0; i < options->num_ports; i++) {
783 add_one_listen_addr(options, addr, rdomain,
784 options->ports[i]);
785 }
786 }
787}
788
789static void
790add_one_listen_addr(ServerOptions *options, const char *addr,
791 const char *rdomain, int port)
792{
793 struct addrinfo hints, *ai, *aitop;
794 char strport[NI_MAXSERV];
795 int gaierr;
796 u_int i;
797
798 /* Find listen_addrs entry for this rdomain */
799 for (i = 0; i < options->num_listen_addrs; i++) {
800 if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL)
801 break;
802 if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL)
803 continue;
804 if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0)
805 break;
806 }
807 if (i >= options->num_listen_addrs) {
808 /* No entry for this rdomain; allocate one */
809 if (i >= INT_MAX)
810 fatal_f("too many listen addresses");
811 options->listen_addrs = xrecallocarray(options->listen_addrs,
812 options->num_listen_addrs, options->num_listen_addrs + 1,
813 sizeof(*options->listen_addrs));
814 i = options->num_listen_addrs++;
815 if (rdomain != NULL)
816 options->listen_addrs[i].rdomain = xstrdup(rdomain);
817 }
818 /* options->listen_addrs[i] points to the addresses for this rdomain */
819
820 memset(&hints, 0, sizeof(hints));
821 hints.ai_family = options->address_family;
822 hints.ai_socktype = SOCK_STREAM;
823 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
824 snprintf(strport, sizeof strport, "%d", port);
825 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
826 fatal("bad addr or host: %s (%s)",
827 addr ? addr : "<NULL>",
828 ssh_gai_strerror(gaierr));
829 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
830 ;
831 ai->ai_next = options->listen_addrs[i].addrs;
832 options->listen_addrs[i].addrs = aitop;
833}
834
835/* Returns nonzero if the routing domain name is valid */
836static int
837valid_rdomain(const char *name)
838{
839 const char *errstr;
840 long long num;
841 struct rt_tableinfo info;
842 int mib[6];
843 size_t miblen = sizeof(mib);
844
845 if (name == NULL)
846 return 1;
847
848 num = strtonum(name, 0, 255, &errstr);
849 if (errstr != NULL)
850 return 0;
851
852 /* Check whether the table actually exists */
853 memset(mib, 0, sizeof(mib));
854 mib[0] = CTL_NET;
855 mib[1] = PF_ROUTE;
856 mib[4] = NET_RT_TABLE;
857 mib[5] = (int)num;
858 if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1)
859 return 0;
860
861 return 1;
862}
863
864/*
865 * Queue a ListenAddress to be processed once we have all of the Ports
866 * and AddressFamily options.
867 */
868static void
869queue_listen_addr(ServerOptions *options, const char *addr,
870 const char *rdomain, int port)
871{
872 struct queued_listenaddr *qla;
873
874 options->queued_listen_addrs = xrecallocarray(
875 options->queued_listen_addrs,
876 options->num_queued_listens, options->num_queued_listens + 1,
877 sizeof(*options->queued_listen_addrs));
878 qla = &options->queued_listen_addrs[options->num_queued_listens++];
879 qla->addr = xstrdup(addr);
880 qla->port = port;
881 qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain);
882}
883
884/*
885 * Process queued (text) ListenAddress entries.
886 */
887static void
888process_queued_listen_addrs(ServerOptions *options)
889{
890 u_int i;
891 struct queued_listenaddr *qla;
892
893 if (options->num_ports == 0)
894 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
895 if (options->address_family == -1)
896 options->address_family = AF_UNSPEC;
897
898 for (i = 0; i < options->num_queued_listens; i++) {
899 qla = &options->queued_listen_addrs[i];
900 add_listen_addr(options, qla->addr, qla->rdomain, qla->port);
901 free(qla->addr);
902 free(qla->rdomain);
903 }
904 free(options->queued_listen_addrs);
905 options->queued_listen_addrs = NULL;
906 options->num_queued_listens = 0;
907}
908
909/*
910 * The strategy for the Match blocks is that the config file is parsed twice.
911 *
912 * The first time is at startup. activep is initialized to 1 and the
913 * directives in the global context are processed and acted on. Hitting a
914 * Match directive unsets activep and the directives inside the block are
915 * checked for syntax only.
916 *
917 * The second time is after a connection has been established but before
918 * authentication. activep is initialized to 2 and global config directives
919 * are ignored since they have already been processed. If the criteria in a
920 * Match block is met, activep is set and the subsequent directives
921 * processed and actioned until EOF or another Match block unsets it. Any
922 * options set are copied into the main server config.
923 *
924 * Potential additions/improvements:
925 * - Add Match support for pre-kex directives, eg. Ciphers.
926 *
927 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
928 * Match Address 192.168.0.*
929 * Tag trusted
930 * Match Group wheel
931 * Tag trusted
932 * Match Tag trusted
933 * AllowTcpForwarding yes
934 * GatewayPorts clientspecified
935 * [...]
936 *
937 * - Add a PermittedChannelRequests directive
938 * Match Group shell
939 * PermittedChannelRequests session,forwarded-tcpip
940 */
941
942static int
943match_cfg_line_group(const char *grps, int line, const char *user)
944{
945 int result = 0;
946 struct passwd *pw;
947
948 if (user == NULL)
949 goto out;
950
951 if ((pw = getpwnam(user)) == NULL) {
952 debug("Can't match group at line %d because user %.100s does "
953 "not exist", line, user);
954 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
955 debug("Can't Match group because user %.100s not in any group "
956 "at line %d", user, line);
957 } else if (ga_match_pattern_list(grps) != 1) {
958 debug("user %.100s does not match group list %.100s at line %d",
959 user, grps, line);
960 } else {
961 debug("user %.100s matched group list %.100s at line %d", user,
962 grps, line);
963 result = 1;
964 }
965out:
966 ga_free();
967 return result;
968}
969
970static void
971match_test_missing_fatal(const char *criteria, const char *attrib)
972{
973 fatal("'Match %s' in configuration but '%s' not in connection "
974 "test specification.", criteria, attrib);
975}
976
977/*
978 * All of the attributes on a single Match line are ANDed together, so we need
979 * to check every attribute and set the result to zero if any attribute does
980 * not match.
981 */
982static int
983match_cfg_line(const char *full_line, int *acp, char ***avp,
984 int line, struct connection_info *ci)
985{
986 int result = 1, attributes = 0, port;
987 char *arg, *attrib = NULL, *oattrib;
988
989 if (ci == NULL) {
990 debug3("checking syntax for 'Match %s' on line %d",
991 full_line, line);
992 } else {
993 debug3("checking match for '%s' user %s%s host %s addr %s "
994 "laddr %s lport %d on line %d", full_line,
995 ci->user ? ci->user : "(null)",
996 ci->user_invalid ? " (invalid)" : "",
997 ci->host ? ci->host : "(null)",
998 ci->address ? ci->address : "(null)",
999 ci->laddress ? ci->laddress : "(null)", ci->lport, line);
1000 }
1001
1002 while ((oattrib = argv_next(acp, avp)) != NULL) {
1003 /* Terminate on comment */
1004 if (*oattrib == '#') {
1005 argv_consume(acp); /* mark all arguments consumed */
1006 break;
1007 }
1008 attrib = xstrdup(oattrib);
1009 arg = NULL;
1010 attributes++;
1011 /* Criterion "all" has no argument and must appear alone */
1012 if (strcasecmp(attrib, "all") == 0) {
1013 if (attributes > 1 ||
1014 ((arg = argv_next(acp, avp)) != NULL &&
1015 *arg != '\0' && *arg != '#')) {
1016 error("'all' cannot be combined with other "
1017 "Match attributes");
1018 result = -1;
1019 goto out;
1020 }
1021 if (arg != NULL && *arg == '#')
1022 argv_consume(acp); /* consume remaining args */
1023 result = 1;
1024 goto out;
1025 }
1026 /* Criterion "invalid-user" also has no argument */
1027 if (strcasecmp(attrib, "invalid-user") == 0) {
1028 if (ci == NULL) {
1029 result = 0;
1030 goto next;
1031 }
1032 if (ci->user_invalid == 0)
1033 result = 0;
1034 else
1035 debug("matched invalid-user at line %d", line);
1036 goto next;
1037 }
1038
1039 /* Keep this list in sync with below */
1040 if (strprefix(attrib, "user=", 1) != NULL ||
1041 strprefix(attrib, "group=", 1) != NULL ||
1042 strprefix(attrib, "host=", 1) != NULL ||
1043 strprefix(attrib, "address=", 1) != NULL ||
1044 strprefix(attrib, "localaddress=", 1) != NULL ||
1045 strprefix(attrib, "localport=", 1) != NULL ||
1046 strprefix(attrib, "rdomain=", 1) != NULL ||
1047 strprefix(attrib, "version=", 1) != NULL) {
1048 arg = strchr(attrib, '=');
1049 *(arg++) = '\0';
1050 } else {
1051 arg = argv_next(acp, avp);
1052 }
1053
1054 /* All other criteria require an argument */
1055 if (arg == NULL || *arg == '\0' || *arg == '#') {
1056 error("Missing Match criteria for %s", attrib);
1057 result = -1;
1058 goto out;
1059 }
1060 if (strcasecmp(attrib, "user") == 0) {
1061 if (ci == NULL || (ci->test && ci->user == NULL)) {
1062 result = 0;
1063 goto next;
1064 }
1065 if (ci->user == NULL)
1066 match_test_missing_fatal("User", "user");
1067 if (match_usergroup_pattern_list(ci->user, arg) != 1)
1068 result = 0;
1069 else
1070 debug("user %.100s matched 'User %.100s' at "
1071 "line %d", ci->user, arg, line);
1072 } else if (strcasecmp(attrib, "group") == 0) {
1073 if (ci == NULL || (ci->test && ci->user == NULL)) {
1074 result = 0;
1075 goto next;
1076 }
1077 if (ci->user == NULL)
1078 match_test_missing_fatal("Group", "user");
1079 switch (match_cfg_line_group(arg, line, ci->user)) {
1080 case -1:
1081 result = -1;
1082 goto out;
1083 case 0:
1084 result = 0;
1085 }
1086 } else if (strcasecmp(attrib, "host") == 0) {
1087 if (ci == NULL || (ci->test && ci->host == NULL)) {
1088 result = 0;
1089 goto next;
1090 }
1091 if (ci->host == NULL)
1092 match_test_missing_fatal("Host", "host");
1093 if (match_hostname(ci->host, arg) != 1)
1094 result = 0;
1095 else
1096 debug("connection from %.100s matched 'Host "
1097 "%.100s' at line %d", ci->host, arg, line);
1098 } else if (strcasecmp(attrib, "address") == 0) {
1099 if (ci == NULL || (ci->test && ci->address == NULL)) {
1100 if (addr_match_list(NULL, arg) != 0)
1101 fatal("Invalid Match address argument "
1102 "'%s' at line %d", arg, line);
1103 result = 0;
1104 goto next;
1105 }
1106 if (ci->address == NULL)
1107 match_test_missing_fatal("Address", "addr");
1108 switch (addr_match_list(ci->address, arg)) {
1109 case 1:
1110 debug("connection from %.100s matched 'Address "
1111 "%.100s' at line %d", ci->address, arg, line);
1112 break;
1113 case 0:
1114 case -1:
1115 result = 0;
1116 break;
1117 case -2:
1118 result = -1;
1119 goto out;
1120 }
1121 } else if (strcasecmp(attrib, "localaddress") == 0){
1122 if (ci == NULL || (ci->test && ci->laddress == NULL)) {
1123 if (addr_match_list(NULL, arg) != 0)
1124 fatal("Invalid Match localaddress "
1125 "argument '%s' at line %d", arg,
1126 line);
1127 result = 0;
1128 goto next;
1129 }
1130 if (ci->laddress == NULL)
1131 match_test_missing_fatal("LocalAddress",
1132 "laddr");
1133 switch (addr_match_list(ci->laddress, arg)) {
1134 case 1:
1135 debug("connection from %.100s matched "
1136 "'LocalAddress %.100s' at line %d",
1137 ci->laddress, arg, line);
1138 break;
1139 case 0:
1140 case -1:
1141 result = 0;
1142 break;
1143 case -2:
1144 result = -1;
1145 goto out;
1146 }
1147 } else if (strcasecmp(attrib, "localport") == 0) {
1148 if ((port = a2port(arg)) == -1) {
1149 error("Invalid LocalPort '%s' on Match line",
1150 arg);
1151 result = -1;
1152 goto out;
1153 }
1154 if (ci == NULL || (ci->test && ci->lport == -1)) {
1155 result = 0;
1156 goto next;
1157 }
1158 if (ci->lport == 0)
1159 match_test_missing_fatal("LocalPort", "lport");
1160 /* TODO support port lists */
1161 if (port == ci->lport)
1162 debug("connection from %.100s matched "
1163 "'LocalPort %d' at line %d",
1164 ci->laddress, port, line);
1165 else
1166 result = 0;
1167 } else if (strcasecmp(attrib, "rdomain") == 0) {
1168 if (ci == NULL || (ci->test && ci->rdomain == NULL)) {
1169 result = 0;
1170 goto next;
1171 }
1172 if (ci->rdomain == NULL)
1173 match_test_missing_fatal("RDomain", "rdomain");
1174 if (match_pattern_list(ci->rdomain, arg, 0) != 1)
1175 result = 0;
1176 else
1177 debug("connection RDomain %.100s matched "
1178 "'RDomain %.100s' at line %d",
1179 ci->rdomain, arg, line);
1180 } else if (strcasecmp(attrib, "version") == 0) {
1181 if (match_pattern_list(SSH_RELEASE, arg, 0) != 1)
1182 result = 0;
1183 else
1184 debug("version %.100s matched "
1185 "'version %.100s' at line %d",
1186 SSH_RELEASE, arg, line);
1187 } else {
1188 error("Unsupported Match attribute %s", oattrib);
1189 result = -1;
1190 goto out;
1191 }
1192 next:
1193 free(attrib);
1194 attrib = NULL;
1195 }
1196 if (attributes == 0) {
1197 error("One or more attributes required for Match");
1198 return -1;
1199 }
1200 out:
1201 if (ci != NULL && result != -1)
1202 debug3("match %sfound on line %d", result ? "" : "not ", line);
1203 free(attrib);
1204 return result;
1205}
1206
1207#define WHITESPACE " \t\r\n"
1208
1209/* Multistate option parsing */
1210struct multistate {
1211 char *key;
1212 int value;
1213};
1214static const struct multistate multistate_flag[] = {
1215 { "yes", 1 },
1216 { "no", 0 },
1217 { NULL, -1 }
1218};
1219static const struct multistate multistate_ignore_rhosts[] = {
1220 { "yes", IGNORE_RHOSTS_YES },
1221 { "no", IGNORE_RHOSTS_NO },
1222 { "shosts-only", IGNORE_RHOSTS_SHOSTS },
1223 { NULL, -1 }
1224};
1225static const struct multistate multistate_addressfamily[] = {
1226 { "inet", AF_INET },
1227 { "inet6", AF_INET6 },
1228 { "any", AF_UNSPEC },
1229 { NULL, -1 }
1230};
1231static const struct multistate multistate_permitrootlogin[] = {
1232 { "prohibit-password", PERMIT_NO_PASSWD },
1233 { "without-password", PERMIT_NO_PASSWD },
1234 { "forced-commands-only", PERMIT_FORCED_ONLY },
1235 { "yes", PERMIT_YES },
1236 { "no", PERMIT_NO },
1237 { NULL, -1 }
1238};
1239static const struct multistate multistate_compression[] = {
1240#ifdef WITH_ZLIB
1241 { "yes", COMP_DELAYED },
1242 { "delayed", COMP_DELAYED },
1243#endif
1244 { "no", COMP_NONE },
1245 { NULL, -1 }
1246};
1247static const struct multistate multistate_gatewayports[] = {
1248 { "clientspecified", 2 },
1249 { "yes", 1 },
1250 { "no", 0 },
1251 { NULL, -1 }
1252};
1253static const struct multistate multistate_tcpfwd[] = {
1254 { "yes", FORWARD_ALLOW },
1255 { "all", FORWARD_ALLOW },
1256 { "no", FORWARD_DENY },
1257 { "remote", FORWARD_REMOTE },
1258 { "local", FORWARD_LOCAL },
1259 { NULL, -1 }
1260};
1261
1262static int
1263process_server_config_line_depth(ServerOptions *options, char *line,
1264 const char *filename, int linenum, int *activep,
1265 struct connection_info *connectinfo, int *inc_flags, int depth,
1266 struct include_list *includes)
1267{
1268 char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword;
1269 int cmdline = 0, *intptr, value, value2, value3, n, port, oactive, r;
1270 double dvalue, *doubleptr = NULL;
1271 int ca_only = 0, found = 0;
1272 SyslogFacility *log_facility_ptr;
1273 LogLevel *log_level_ptr;
1274 ServerOpCodes opcode;
1275 u_int i, *uintptr, flags = 0;
1276 size_t len;
1277 long long val64;
1278 const struct multistate *multistate_ptr;
1279 const char *errstr;
1280 struct include_item *item;
1281 glob_t gbuf;
1282 char **oav = NULL, **av;
1283 int oac = 0, ac;
1284 int ret = -1;
1285 char **strs = NULL; /* string array arguments; freed implicitly */
1286 u_int nstrs = 0;
1287
1288 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1289 if ((len = strlen(line)) == 0)
1290 return 0;
1291 for (len--; len > 0; len--) {
1292 if (strchr(WHITESPACE "\f", line[len]) == NULL)
1293 break;
1294 line[len] = '\0';
1295 }
1296
1297 str = line;
1298 if ((keyword = strdelim(&str)) == NULL)
1299 return 0;
1300 /* Ignore leading whitespace */
1301 if (*keyword == '\0')
1302 keyword = strdelim(&str);
1303 if (!keyword || !*keyword || *keyword == '#')
1304 return 0;
1305 if (str == NULL || *str == '\0') {
1306 error("%s line %d: no argument after keyword \"%s\"",
1307 filename, linenum, keyword);
1308 return -1;
1309 }
1310 intptr = NULL;
1311 charptr = NULL;
1312 opcode = parse_token(keyword, filename, linenum, &flags);
1313
1314 if (argv_split(str, &oac, &oav, 1) != 0) {
1315 error("%s line %d: invalid quotes", filename, linenum);
1316 return -1;
1317 }
1318 ac = oac;
1319 av = oav;
1320
1321 if (activep == NULL) { /* We are processing a command line directive */
1322 cmdline = 1;
1323 activep = &cmdline;
1324 }
1325 if (*activep && opcode != sMatch && opcode != sInclude)
1326 debug3("%s:%d setting %s %s", filename, linenum, keyword, str);
1327 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
1328 if (connectinfo == NULL) {
1329 fatal("%s line %d: Directive '%s' is not allowed "
1330 "within a Match block", filename, linenum, keyword);
1331 } else { /* this is a directive we have already processed */
1332 ret = 0;
1333 goto out;
1334 }
1335 }
1336
1337 switch (opcode) {
1338 case sBadOption:
1339 goto out;
1340 case sPort:
1341 /* ignore ports from configfile if cmdline specifies ports */
1342 if (options->ports_from_cmdline) {
1343 argv_consume(&ac);
1344 break;
1345 }
1346 if (options->num_ports >= MAX_PORTS)
1347 fatal("%s line %d: too many ports.",
1348 filename, linenum);
1349 arg = argv_next(&ac, &av);
1350 if (!arg || *arg == '\0')
1351 fatal("%s line %d: missing port number.",
1352 filename, linenum);
1353 options->ports[options->num_ports++] = a2port(arg);
1354 if (options->ports[options->num_ports-1] <= 0)
1355 fatal("%s line %d: Badly formatted port number.",
1356 filename, linenum);
1357 break;
1358
1359 case sLoginGraceTime:
1360 intptr = &options->login_grace_time;
1361 parse_time:
1362 arg = argv_next(&ac, &av);
1363 if (!arg || *arg == '\0')
1364 fatal("%s line %d: missing time value.",
1365 filename, linenum);
1366 if ((value = convtime(arg)) == -1)
1367 fatal("%s line %d: invalid time value.",
1368 filename, linenum);
1369 if (*activep && *intptr == -1)
1370 *intptr = value;
1371 break;
1372
1373 case sListenAddress:
1374 arg = argv_next(&ac, &av);
1375 if (arg == NULL || *arg == '\0')
1376 fatal("%s line %d: missing address",
1377 filename, linenum);
1378 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
1379 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
1380 && strchr(p+1, ':') != NULL) {
1381 port = 0;
1382 p = arg;
1383 } else {
1384 arg2 = NULL;
1385 p = hpdelim(&arg);
1386 if (p == NULL)
1387 fatal("%s line %d: bad address:port usage",
1388 filename, linenum);
1389 p = cleanhostname(p);
1390 if (arg == NULL)
1391 port = 0;
1392 else if ((port = a2port(arg)) <= 0)
1393 fatal("%s line %d: bad port number",
1394 filename, linenum);
1395 }
1396 /* Optional routing table */
1397 arg2 = NULL;
1398 if ((arg = argv_next(&ac, &av)) != NULL) {
1399 if (strcmp(arg, "rdomain") != 0 ||
1400 (arg2 = argv_next(&ac, &av)) == NULL)
1401 fatal("%s line %d: bad ListenAddress syntax",
1402 filename, linenum);
1403 if (!valid_rdomain(arg2))
1404 fatal("%s line %d: bad routing domain",
1405 filename, linenum);
1406 }
1407 queue_listen_addr(options, p, arg2, port);
1408
1409 break;
1410
1411 case sAddressFamily:
1412 intptr = &options->address_family;
1413 multistate_ptr = multistate_addressfamily;
1414 parse_multistate:
1415 arg = argv_next(&ac, &av);
1416 if (!arg || *arg == '\0')
1417 fatal("%s line %d: missing argument.",
1418 filename, linenum);
1419 value = -1;
1420 for (i = 0; multistate_ptr[i].key != NULL; i++) {
1421 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1422 value = multistate_ptr[i].value;
1423 break;
1424 }
1425 }
1426 if (value == -1)
1427 fatal("%s line %d: unsupported option \"%s\".",
1428 filename, linenum, arg);
1429 if (*activep && *intptr == -1)
1430 *intptr = value;
1431 break;
1432
1433 case sHostKeyFile:
1434 arg = argv_next(&ac, &av);
1435 if (!arg || *arg == '\0')
1436 fatal("%s line %d: missing file name.",
1437 filename, linenum);
1438 if (*activep) {
1439 servconf_add_hostkey(filename, linenum,
1440 options, arg, 1);
1441 }
1442 break;
1443
1444 case sHostKeyAgent:
1445 charptr = &options->host_key_agent;
1446 arg = argv_next(&ac, &av);
1447 if (!arg || *arg == '\0')
1448 fatal("%s line %d: missing socket name.",
1449 filename, linenum);
1450 if (*activep && *charptr == NULL)
1451 *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ?
1452 xstrdup(arg) : derelativise_path(arg);
1453 break;
1454
1455 case sHostCertificate:
1456 arg = argv_next(&ac, &av);
1457 if (!arg || *arg == '\0')
1458 fatal("%s line %d: missing file name.",
1459 filename, linenum);
1460 if (*activep)
1461 servconf_add_hostcert(filename, linenum, options, arg);
1462 break;
1463
1464 case sPidFile:
1465 charptr = &options->pid_file;
1466 parse_filename:
1467 arg = argv_next(&ac, &av);
1468 if (!arg || *arg == '\0')
1469 fatal("%s line %d: missing file name.",
1470 filename, linenum);
1471 if (*activep && *charptr == NULL) {
1472 *charptr = derelativise_path(arg);
1473 /* increase optional counter */
1474 if (intptr != NULL)
1475 *intptr = *intptr + 1;
1476 }
1477 break;
1478
1479 case sModuliFile:
1480 charptr = &options->moduli_file;
1481 goto parse_filename;
1482
1483 case sPermitRootLogin:
1484 intptr = &options->permit_root_login;
1485 multistate_ptr = multistate_permitrootlogin;
1486 goto parse_multistate;
1487
1488 case sIgnoreRhosts:
1489 intptr = &options->ignore_rhosts;
1490 multistate_ptr = multistate_ignore_rhosts;
1491 goto parse_multistate;
1492
1493 case sIgnoreUserKnownHosts:
1494 intptr = &options->ignore_user_known_hosts;
1495 parse_flag:
1496 multistate_ptr = multistate_flag;
1497 goto parse_multistate;
1498
1499 case sHostbasedAuthentication:
1500 intptr = &options->hostbased_authentication;
1501 goto parse_flag;
1502
1503 case sHostbasedUsesNameFromPacketOnly:
1504 intptr = &options->hostbased_uses_name_from_packet_only;
1505 goto parse_flag;
1506
1507 case sHostbasedAcceptedAlgorithms:
1508 charptr = &options->hostbased_accepted_algos;
1509 ca_only = 0;
1510 parse_pubkey_algos:
1511 arg = argv_next(&ac, &av);
1512 if (!arg || *arg == '\0')
1513 fatal("%s line %d: Missing argument.",
1514 filename, linenum);
1515 if (*arg != '-' &&
1516 !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1517 arg + 1 : arg, 1, ca_only))
1518 fatal("%s line %d: Bad key types '%s'.",
1519 filename, linenum, arg ? arg : "<NONE>");
1520 if (*activep && *charptr == NULL)
1521 *charptr = xstrdup(arg);
1522 break;
1523
1524 case sHostKeyAlgorithms:
1525 charptr = &options->hostkeyalgorithms;
1526 ca_only = 0;
1527 goto parse_pubkey_algos;
1528
1529 case sCASignatureAlgorithms:
1530 charptr = &options->ca_sign_algorithms;
1531 ca_only = 1;
1532 goto parse_pubkey_algos;
1533
1534 case sPubkeyAuthentication:
1535 intptr = &options->pubkey_authentication;
1536 ca_only = 0;
1537 goto parse_flag;
1538
1539 case sPubkeyAcceptedAlgorithms:
1540 charptr = &options->pubkey_accepted_algos;
1541 ca_only = 0;
1542 goto parse_pubkey_algos;
1543
1544 case sPubkeyAuthOptions:
1545 intptr = &options->pubkey_auth_options;
1546 value = 0;
1547 while ((arg = argv_next(&ac, &av)) != NULL) {
1548 if (strcasecmp(arg, "none") == 0)
1549 continue;
1550 if (strcasecmp(arg, "touch-required") == 0)
1551 value |= PUBKEYAUTH_TOUCH_REQUIRED;
1552 else if (strcasecmp(arg, "verify-required") == 0)
1553 value |= PUBKEYAUTH_VERIFY_REQUIRED;
1554 else {
1555 error("%s line %d: unsupported %s option %s",
1556 filename, linenum, keyword, arg);
1557 goto out;
1558 }
1559 }
1560 if (*activep && *intptr == -1)
1561 *intptr = value;
1562 break;
1563
1564 case sKerberosAuthentication:
1565 intptr = &options->kerberos_authentication;
1566 goto parse_flag;
1567
1568 case sKerberosOrLocalPasswd:
1569 intptr = &options->kerberos_or_local_passwd;
1570 goto parse_flag;
1571
1572 case sKerberosTicketCleanup:
1573 intptr = &options->kerberos_ticket_cleanup;
1574 goto parse_flag;
1575
1576 case sKerberosGetAFSToken:
1577 intptr = &options->kerberos_get_afs_token;
1578 goto parse_flag;
1579
1580 case sGssAuthentication:
1581 intptr = &options->gss_authentication;
1582 goto parse_flag;
1583
1584 case sGssCleanupCreds:
1585 intptr = &options->gss_cleanup_creds;
1586 goto parse_flag;
1587
1588 case sGssDelegateCreds:
1589 intptr = &options->gss_deleg_creds;
1590 goto parse_flag;
1591
1592 case sGssStrictAcceptor:
1593 intptr = &options->gss_strict_acceptor;
1594 goto parse_flag;
1595
1596 case sPasswordAuthentication:
1597 intptr = &options->password_authentication;
1598 goto parse_flag;
1599
1600 case sKbdInteractiveAuthentication:
1601 intptr = &options->kbd_interactive_authentication;
1602 goto parse_flag;
1603
1604 case sPrintMotd:
1605 intptr = &options->print_motd;
1606 goto parse_flag;
1607
1608 case sPrintLastLog:
1609 intptr = &options->print_lastlog;
1610 goto parse_flag;
1611
1612 case sX11Forwarding:
1613 intptr = &options->x11_forwarding;
1614 goto parse_flag;
1615
1616 case sX11DisplayOffset:
1617 intptr = &options->x11_display_offset;
1618 parse_int:
1619 arg = argv_next(&ac, &av);
1620 if ((errstr = atoi_err(arg, &value)) != NULL)
1621 fatal("%s line %d: %s integer value %s.",
1622 filename, linenum, keyword, errstr);
1623 if (*activep && *intptr == -1)
1624 *intptr = value;
1625 break;
1626
1627 case sX11UseLocalhost:
1628 intptr = &options->x11_use_localhost;
1629 goto parse_flag;
1630
1631 case sXAuthLocation:
1632 charptr = &options->xauth_location;
1633 goto parse_filename;
1634
1635 case sPermitTTY:
1636 intptr = &options->permit_tty;
1637 goto parse_flag;
1638
1639 case sPermitUserRC:
1640 intptr = &options->permit_user_rc;
1641 goto parse_flag;
1642
1643 case sStrictModes:
1644 intptr = &options->strict_modes;
1645 goto parse_flag;
1646
1647 case sTCPKeepAlive:
1648 intptr = &options->tcp_keep_alive;
1649 goto parse_flag;
1650
1651 case sEmptyPasswd:
1652 intptr = &options->permit_empty_passwd;
1653 goto parse_flag;
1654
1655 case sPermitUserEnvironment:
1656 intptr = &options->permit_user_env;
1657 charptr = &options->permit_user_env_allowlist;
1658 arg = argv_next(&ac, &av);
1659 if (!arg || *arg == '\0')
1660 fatal("%s line %d: %s missing argument.",
1661 filename, linenum, keyword);
1662 value = 0;
1663 p = NULL;
1664 if (strcmp(arg, "yes") == 0)
1665 value = 1;
1666 else if (strcmp(arg, "no") == 0)
1667 value = 0;
1668 else {
1669 /* Pattern-list specified */
1670 value = 1;
1671 p = xstrdup(arg);
1672 }
1673 if (*activep && *intptr == -1) {
1674 *intptr = value;
1675 *charptr = p;
1676 p = NULL;
1677 }
1678 free(p);
1679 break;
1680
1681 case sCompression:
1682 intptr = &options->compression;
1683 multistate_ptr = multistate_compression;
1684 goto parse_multistate;
1685
1686 case sRekeyLimit:
1687 arg = argv_next(&ac, &av);
1688 if (!arg || *arg == '\0')
1689 fatal("%s line %d: %s missing argument.",
1690 filename, linenum, keyword);
1691 if (strcmp(arg, "default") == 0) {
1692 val64 = 0;
1693 } else {
1694 if (scan_scaled(arg, &val64) == -1)
1695 fatal("%.200s line %d: Bad %s number '%s': %s",
1696 filename, linenum, keyword,
1697 arg, strerror(errno));
1698 if (val64 != 0 && val64 < 16)
1699 fatal("%.200s line %d: %s too small",
1700 filename, linenum, keyword);
1701 }
1702 if (*activep && options->rekey_limit == -1)
1703 options->rekey_limit = val64;
1704 if (ac != 0) { /* optional rekey interval present */
1705 if (strcmp(av[0], "none") == 0) {
1706 (void)argv_next(&ac, &av); /* discard */
1707 break;
1708 }
1709 intptr = &options->rekey_interval;
1710 goto parse_time;
1711 }
1712 break;
1713
1714 case sGatewayPorts:
1715 intptr = &options->fwd_opts.gateway_ports;
1716 multistate_ptr = multistate_gatewayports;
1717 goto parse_multistate;
1718
1719 case sUseDNS:
1720 intptr = &options->use_dns;
1721 goto parse_flag;
1722
1723 case sLogFacility:
1724 log_facility_ptr = &options->log_facility;
1725 arg = argv_next(&ac, &av);
1726 value = log_facility_number(arg);
1727 if (value == SYSLOG_FACILITY_NOT_SET)
1728 fatal("%.200s line %d: unsupported log facility '%s'",
1729 filename, linenum, arg ? arg : "<NONE>");
1730 if (*log_facility_ptr == -1)
1731 *log_facility_ptr = (SyslogFacility) value;
1732 break;
1733
1734 case sLogLevel:
1735 log_level_ptr = &options->log_level;
1736 arg = argv_next(&ac, &av);
1737 value = log_level_number(arg);
1738 if (value == SYSLOG_LEVEL_NOT_SET)
1739 fatal("%.200s line %d: unsupported log level '%s'",
1740 filename, linenum, arg ? arg : "<NONE>");
1741 if (*activep && *log_level_ptr == -1)
1742 *log_level_ptr = (LogLevel) value;
1743 break;
1744
1745 case sLogVerbose:
1746 found = options->num_log_verbose == 0;
1747 while ((arg = argv_next(&ac, &av)) != NULL) {
1748 if (*arg == '\0') {
1749 error("%s line %d: keyword %s empty argument",
1750 filename, linenum, keyword);
1751 goto out;
1752 }
1753 /* Allow "none" only in first position */
1754 if (strcasecmp(arg, "none") == 0) {
1755 if (nstrs > 0 || ac > 0) {
1756 error("%s line %d: keyword %s \"none\" "
1757 "argument must appear alone.",
1758 filename, linenum, keyword);
1759 goto out;
1760 }
1761 }
1762 opt_array_append(filename, linenum, keyword,
1763 &strs, &nstrs, arg);
1764 }
1765 if (nstrs == 0) {
1766 fatal("%s line %d: no %s specified",
1767 filename, linenum, keyword);
1768 }
1769 if (found && *activep) {
1770 options->log_verbose = strs;
1771 options->num_log_verbose = nstrs;
1772 strs = NULL; /* transferred */
1773 nstrs = 0;
1774 }
1775 break;
1776
1777 case sAllowTcpForwarding:
1778 intptr = &options->allow_tcp_forwarding;
1779 multistate_ptr = multistate_tcpfwd;
1780 goto parse_multistate;
1781
1782 case sAllowStreamLocalForwarding:
1783 intptr = &options->allow_streamlocal_forwarding;
1784 multistate_ptr = multistate_tcpfwd;
1785 goto parse_multistate;
1786
1787 case sAllowAgentForwarding:
1788 intptr = &options->allow_agent_forwarding;
1789 goto parse_flag;
1790
1791 case sDisableForwarding:
1792 intptr = &options->disable_forwarding;
1793 goto parse_flag;
1794
1795 case sAllowUsers:
1796 chararrayptr = &options->allow_users;
1797 uintptr = &options->num_allow_users;
1798 parse_allowdenyusers:
1799 /* XXX appends to list; doesn't respect first-match-wins */
1800 while ((arg = argv_next(&ac, &av)) != NULL) {
1801 if (*arg == '\0' ||
1802 match_user(NULL, NULL, NULL, arg) == -1)
1803 fatal("%s line %d: invalid %s pattern: \"%s\"",
1804 filename, linenum, keyword, arg);
1805 found = 1;
1806 if (!*activep)
1807 continue;
1808 opt_array_append(filename, linenum, keyword,
1809 chararrayptr, uintptr, arg);
1810 }
1811 if (!found) {
1812 fatal("%s line %d: no %s specified",
1813 filename, linenum, keyword);
1814 }
1815 break;
1816
1817 case sDenyUsers:
1818 chararrayptr = &options->deny_users;
1819 uintptr = &options->num_deny_users;
1820 goto parse_allowdenyusers;
1821
1822 case sAllowGroups:
1823 chararrayptr = &options->allow_groups;
1824 uintptr = &options->num_allow_groups;
1825 /* XXX appends to list; doesn't respect first-match-wins */
1826 parse_allowdenygroups:
1827 while ((arg = argv_next(&ac, &av)) != NULL) {
1828 if (*arg == '\0')
1829 fatal("%s line %d: empty %s pattern",
1830 filename, linenum, keyword);
1831 found = 1;
1832 if (!*activep)
1833 continue;
1834 opt_array_append(filename, linenum, keyword,
1835 chararrayptr, uintptr, arg);
1836 }
1837 if (!found) {
1838 fatal("%s line %d: no %s specified",
1839 filename, linenum, keyword);
1840 }
1841 break;
1842
1843 case sDenyGroups:
1844 chararrayptr = &options->deny_groups;
1845 uintptr = &options->num_deny_groups;
1846 goto parse_allowdenygroups;
1847
1848 case sCiphers:
1849 arg = argv_next(&ac, &av);
1850 if (!arg || *arg == '\0')
1851 fatal("%s line %d: %s missing argument.",
1852 filename, linenum, keyword);
1853 if (*arg != '-' &&
1854 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
1855 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1856 filename, linenum, arg ? arg : "<NONE>");
1857 if (options->ciphers == NULL)
1858 options->ciphers = xstrdup(arg);
1859 break;
1860
1861 case sMacs:
1862 arg = argv_next(&ac, &av);
1863 if (!arg || *arg == '\0')
1864 fatal("%s line %d: %s missing argument.",
1865 filename, linenum, keyword);
1866 if (*arg != '-' &&
1867 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
1868 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1869 filename, linenum, arg ? arg : "<NONE>");
1870 if (options->macs == NULL)
1871 options->macs = xstrdup(arg);
1872 break;
1873
1874 case sKexAlgorithms:
1875 arg = argv_next(&ac, &av);
1876 if (!arg || *arg == '\0')
1877 fatal("%s line %d: %s missing argument.",
1878 filename, linenum, keyword);
1879 if (*arg != '-' &&
1880 !kex_names_valid(*arg == '+' || *arg == '^' ?
1881 arg + 1 : arg))
1882 fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
1883 filename, linenum, arg ? arg : "<NONE>");
1884 if (options->kex_algorithms == NULL)
1885 options->kex_algorithms = xstrdup(arg);
1886 break;
1887
1888 case sSubsystem:
1889 if ((arg = argv_next(&ac, &av)) == NULL || *arg == '\0' ||
1890 ((arg2 = argv_next(&ac, &av)) == NULL || *arg2 == '\0'))
1891 fatal("%s line %d: %s missing argument.",
1892 filename, linenum, keyword);
1893 if (!*activep) {
1894 argv_consume(&ac);
1895 break;
1896 }
1897 found = 0;
1898 for (i = 0; i < options->num_subsystems; i++) {
1899 if (strcmp(arg, options->subsystem_name[i]) == 0) {
1900 found = 1;
1901 break;
1902 }
1903 }
1904 if (found) {
1905 debug("%s line %d: Subsystem '%s' already defined.",
1906 filename, linenum, arg);
1907 argv_consume(&ac);
1908 break;
1909 }
1910 options->subsystem_name = xrecallocarray(
1911 options->subsystem_name, options->num_subsystems,
1912 options->num_subsystems + 1,
1913 sizeof(*options->subsystem_name));
1914 options->subsystem_command = xrecallocarray(
1915 options->subsystem_command, options->num_subsystems,
1916 options->num_subsystems + 1,
1917 sizeof(*options->subsystem_command));
1918 options->subsystem_args = xrecallocarray(
1919 options->subsystem_args, options->num_subsystems,
1920 options->num_subsystems + 1,
1921 sizeof(*options->subsystem_args));
1922 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1923 options->subsystem_command[options->num_subsystems] =
1924 xstrdup(arg2);
1925 /* Collect arguments (separate to executable) */
1926 arg = argv_assemble(1, &arg2); /* quote command correctly */
1927 arg2 = argv_assemble(ac, av); /* rest of command */
1928 xasprintf(&options->subsystem_args[options->num_subsystems],
1929 "%s%s%s", arg, *arg2 == '\0' ? "" : " ", arg2);
1930 free(arg2);
1931 free(arg);
1932 argv_consume(&ac);
1933 options->num_subsystems++;
1934 break;
1935
1936 case sMaxStartups:
1937 arg = argv_next(&ac, &av);
1938 if (!arg || *arg == '\0')
1939 fatal("%s line %d: %s missing argument.",
1940 filename, linenum, keyword);
1941 /* begin:rate:max */
1942 if ((n = sscanf(arg, "%d:%d:%d",
1943 &value, &value2, &value3)) == 3) {
1944 if (value > value3 || value2 > 100 || value2 < 1)
1945 fatal("%s line %d: Invalid %s spec.",
1946 filename, linenum, keyword);
1947 } else if (n == 1) {
1948 value3 = value;
1949 value = value2 = -1;
1950 } else {
1951 fatal("%s line %d: Invalid %s spec.",
1952 filename, linenum, keyword);
1953 }
1954 if (value3 <= 0 || (value2 != -1 && value <= 0))
1955 fatal("%s line %d: Invalid %s spec.",
1956 filename, linenum, keyword);
1957 if (*activep && options->max_startups == -1) {
1958 options->max_startups_begin = value;
1959 options->max_startups_rate = value2;
1960 options->max_startups = value3;
1961 }
1962 break;
1963
1964 case sPerSourceNetBlockSize:
1965 arg = argv_next(&ac, &av);
1966 if (!arg || *arg == '\0')
1967 fatal("%s line %d: %s missing argument.",
1968 filename, linenum, keyword);
1969 switch (n = sscanf(arg, "%d:%d", &value, &value2)) {
1970 case 2:
1971 if (value2 < 0 || value2 > 128)
1972 n = -1;
1973 /* FALLTHROUGH */
1974 case 1:
1975 if (value < 0 || value > 32)
1976 n = -1;
1977 }
1978 if (n != 1 && n != 2)
1979 fatal("%s line %d: Invalid %s spec.",
1980 filename, linenum, keyword);
1981 if (*activep && options->per_source_masklen_ipv4 == -1) {
1982 options->per_source_masklen_ipv4 = value;
1983 if (n == 2)
1984 options->per_source_masklen_ipv6 = value2;
1985 }
1986 break;
1987
1988 case sPerSourceMaxStartups:
1989 arg = argv_next(&ac, &av);
1990 if (!arg || *arg == '\0')
1991 fatal("%s line %d: %s missing argument.",
1992 filename, linenum, keyword);
1993 if (strcmp(arg, "none") == 0) { /* no limit */
1994 value = INT_MAX;
1995 } else {
1996 if ((errstr = atoi_err(arg, &value)) != NULL)
1997 fatal("%s line %d: %s integer value %s.",
1998 filename, linenum, keyword, errstr);
1999 }
2000 if (*activep && options->per_source_max_startups == -1)
2001 options->per_source_max_startups = value;
2002 break;
2003
2004 case sPerSourcePenaltyExemptList:
2005 charptr = &options->per_source_penalty_exempt;
2006 arg = argv_next(&ac, &av);
2007 if (!arg || *arg == '\0')
2008 fatal("%s line %d: missing argument.",
2009 filename, linenum);
2010 if (addr_match_list(NULL, arg) != 0) {
2011 fatal("%s line %d: keyword %s "
2012 "invalid address argument.",
2013 filename, linenum, keyword);
2014 }
2015 if (*activep && *charptr == NULL)
2016 *charptr = xstrdup(arg);
2017 break;
2018
2019 case sPerSourcePenalties:
2020 while ((arg = argv_next(&ac, &av)) != NULL) {
2021 const char *q = NULL;
2022
2023 found = 1;
2024 intptr = NULL;
2025 doubleptr = NULL;
2026 value = -1;
2027 value2 = 0;
2028 /* Allow no/yes only in first position */
2029 if (strcasecmp(arg, "no") == 0 ||
2030 (value2 = (strcasecmp(arg, "yes") == 0))) {
2031 if (ac > 0) {
2032 fatal("%s line %d: keyword %s \"%s\" "
2033 "argument must appear alone.",
2034 filename, linenum, keyword, arg);
2035 }
2036 if (*activep &&
2037 options->per_source_penalty.enabled == -1)
2038 options->per_source_penalty.enabled = value2;
2039 continue;
2040 } else if ((q = strprefix(arg, "crash:", 0)) != NULL) {
2041 doubleptr = &options->per_source_penalty.penalty_crash;
2042 } else if ((q = strprefix(arg, "authfail:", 0)) != NULL) {
2043 doubleptr = &options->per_source_penalty.penalty_authfail;
2044 } else if ((q = strprefix(arg, "invaliduser:", 0)) != NULL) {
2045 doubleptr = &options->per_source_penalty.penalty_invaliduser;
2046 } else if ((q = strprefix(arg, "noauth:", 0)) != NULL) {
2047 doubleptr = &options->per_source_penalty.penalty_noauth;
2048 } else if ((q = strprefix(arg, "grace-exceeded:", 0)) != NULL) {
2049 doubleptr = &options->per_source_penalty.penalty_grace;
2050 } else if ((q = strprefix(arg, "refuseconnection:", 0)) != NULL) {
2051 doubleptr = &options->per_source_penalty.penalty_refuseconnection;
2052 } else if ((q = strprefix(arg, "max:", 0)) != NULL) {
2053 doubleptr = &options->per_source_penalty.penalty_max;
2054 } else if ((q = strprefix(arg, "min:", 0)) != NULL) {
2055 doubleptr = &options->per_source_penalty.penalty_min;
2056 } else if ((q = strprefix(arg, "max-sources4:", 0)) != NULL) {
2057 intptr = &options->per_source_penalty.max_sources4;
2058 if ((errstr = atoi_err(q, &value)) != NULL)
2059 fatal("%s line %d: %s value %s.",
2060 filename, linenum, keyword, errstr);
2061 } else if ((q = strprefix(arg, "max-sources6:", 0)) != NULL) {
2062 intptr = &options->per_source_penalty.max_sources6;
2063 if ((errstr = atoi_err(q, &value)) != NULL)
2064 fatal("%s line %d: %s value %s.",
2065 filename, linenum, keyword, errstr);
2066 } else if (strcmp(arg, "overflow:deny-all") == 0) {
2067 intptr = &options->per_source_penalty.overflow_mode;
2068 value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL;
2069 } else if (strcmp(arg, "overflow:permissive") == 0) {
2070 intptr = &options->per_source_penalty.overflow_mode;
2071 value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
2072 } else if (strcmp(arg, "overflow6:deny-all") == 0) {
2073 intptr = &options->per_source_penalty.overflow_mode6;
2074 value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL;
2075 } else if (strcmp(arg, "overflow6:permissive") == 0) {
2076 intptr = &options->per_source_penalty.overflow_mode6;
2077 value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
2078 } else {
2079 fatal("%s line %d: unsupported %s keyword %s",
2080 filename, linenum, keyword, arg);
2081 }
2082
2083 if (doubleptr != NULL) {
2084 if ((dvalue = convtime_double(q)) < 0) {
2085 fatal("%s line %d: invalid %s time value.",
2086 filename, linenum, keyword);
2087 }
2088 if (*activep && *doubleptr < 0.0) {
2089 *doubleptr = dvalue;
2090 options->per_source_penalty.enabled = 1;
2091 }
2092 } else if (intptr != NULL) {
2093 if (*activep && *intptr == -1) {
2094 *intptr = value;
2095 options->per_source_penalty.enabled = 1;
2096 }
2097 } else {
2098 fatal_f("%s line %d: internal error",
2099 filename, linenum);
2100 }
2101 }
2102 if (!found) {
2103 fatal("%s line %d: no %s specified",
2104 filename, linenum, keyword);
2105 }
2106 break;
2107
2108 case sMaxAuthTries:
2109 intptr = &options->max_authtries;
2110 goto parse_int;
2111
2112 case sMaxSessions:
2113 intptr = &options->max_sessions;
2114 goto parse_int;
2115
2116 case sBanner:
2117 charptr = &options->banner;
2118 goto parse_filename;
2119
2120 /*
2121 * These options can contain %X options expanded at
2122 * connect time, so that you can specify paths like:
2123 *
2124 * AuthorizedKeysFile /etc/ssh_keys/%u
2125 */
2126 case sAuthorizedKeysFile:
2127 uintptr = &options->num_authkeys_files;
2128 chararrayptr = &options->authorized_keys_files;
2129 parse_filenames:
2130 found = *uintptr == 0;
2131 while ((arg = argv_next(&ac, &av)) != NULL) {
2132 if (*arg == '\0') {
2133 error("%s line %d: keyword %s empty argument",
2134 filename, linenum, keyword);
2135 goto out;
2136 }
2137 /* Allow "none" only in first position */
2138 if (strcasecmp(arg, "none") == 0) {
2139 if (nstrs > 0 || ac > 0) {
2140 error("%s line %d: keyword %s \"none\" "
2141 "argument must appear alone.",
2142 filename, linenum, keyword);
2143 goto out;
2144 }
2145 }
2146 arg2 = tilde_expand_filename(arg, getuid());
2147 opt_array_append(filename, linenum, keyword,
2148 &strs, &nstrs, arg2);
2149 free(arg2);
2150 }
2151 if (nstrs == 0) {
2152 fatal("%s line %d: no %s specified",
2153 filename, linenum, keyword);
2154 }
2155 if (found && *activep) {
2156 *chararrayptr = strs;
2157 *uintptr = nstrs;
2158 strs = NULL; /* transferred */
2159 nstrs = 0;
2160 }
2161 break;
2162
2163 case sAuthorizedPrincipalsFile:
2164 charptr = &options->authorized_principals_file;
2165 arg = argv_next(&ac, &av);
2166 if (!arg || *arg == '\0')
2167 fatal("%s line %d: %s missing argument.",
2168 filename, linenum, keyword);
2169 if (*activep && *charptr == NULL) {
2170 *charptr = tilde_expand_filename(arg, getuid());
2171 /* increase optional counter */
2172 if (intptr != NULL)
2173 *intptr = *intptr + 1;
2174 }
2175 break;
2176
2177 case sClientAliveInterval:
2178 intptr = &options->client_alive_interval;
2179 goto parse_time;
2180
2181 case sClientAliveCountMax:
2182 intptr = &options->client_alive_count_max;
2183 goto parse_int;
2184
2185 case sAcceptEnv:
2186 /* XXX appends to list; doesn't respect first-match-wins */
2187 while ((arg = argv_next(&ac, &av)) != NULL) {
2188 if (*arg == '\0' || strchr(arg, '=') != NULL)
2189 fatal("%s line %d: Invalid environment name.",
2190 filename, linenum);
2191 found = 1;
2192 if (!*activep)
2193 continue;
2194 opt_array_append(filename, linenum, keyword,
2195 &options->accept_env, &options->num_accept_env,
2196 arg);
2197 }
2198 if (!found) {
2199 fatal("%s line %d: no %s specified",
2200 filename, linenum, keyword);
2201 }
2202 break;
2203
2204 case sSetEnv:
2205 found = options->num_setenv == 0;
2206 while ((arg = argv_next(&ac, &av)) != NULL) {
2207 if (*arg == '\0' || strchr(arg, '=') == NULL)
2208 fatal("%s line %d: Invalid environment.",
2209 filename, linenum);
2210 if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) {
2211 debug2("%s line %d: ignoring duplicate env "
2212 "name \"%.64s\"", filename, linenum, arg);
2213 continue;
2214 }
2215 opt_array_append(filename, linenum, keyword,
2216 &strs, &nstrs, arg);
2217 }
2218 if (nstrs == 0) {
2219 fatal("%s line %d: no %s specified",
2220 filename, linenum, keyword);
2221 }
2222 if (found && *activep) {
2223 options->setenv = strs;
2224 options->num_setenv = nstrs;
2225 strs = NULL; /* transferred */
2226 nstrs = 0;
2227 }
2228 break;
2229
2230 case sPermitTunnel:
2231 intptr = &options->permit_tun;
2232 arg = argv_next(&ac, &av);
2233 if (!arg || *arg == '\0')
2234 fatal("%s line %d: %s missing argument.",
2235 filename, linenum, keyword);
2236 value = -1;
2237 for (i = 0; tunmode_desc[i].val != -1; i++)
2238 if (strcmp(tunmode_desc[i].text, arg) == 0) {
2239 value = tunmode_desc[i].val;
2240 break;
2241 }
2242 if (value == -1)
2243 fatal("%s line %d: bad %s argument %s",
2244 filename, linenum, keyword, arg);
2245 if (*activep && *intptr == -1)
2246 *intptr = value;
2247 break;
2248
2249 case sInclude:
2250 if (cmdline) {
2251 fatal("Include directive not supported as a "
2252 "command-line option");
2253 }
2254 value = 0;
2255 while ((arg2 = argv_next(&ac, &av)) != NULL) {
2256 if (*arg2 == '\0') {
2257 error("%s line %d: keyword %s empty argument",
2258 filename, linenum, keyword);
2259 goto out;
2260 }
2261 value++;
2262 found = 0;
2263 if (*arg2 != '/' && *arg2 != '~') {
2264 xasprintf(&arg, "%s/%s", SSHDIR, arg2);
2265 } else
2266 arg = xstrdup(arg2);
2267
2268 /*
2269 * Don't let included files clobber the containing
2270 * file's Match state.
2271 */
2272 oactive = *activep;
2273
2274 /* consult cache of include files */
2275 TAILQ_FOREACH(item, includes, entry) {
2276 if (strcmp(item->selector, arg) != 0)
2277 continue;
2278 if (item->filename != NULL) {
2279 parse_server_config_depth(options,
2280 item->filename, item->contents,
2281 includes, connectinfo,
2282 (*inc_flags & SSHCFG_MATCH_ONLY
2283 ? SSHCFG_MATCH_ONLY : (oactive
2284 ? 0 : SSHCFG_NEVERMATCH)),
2285 activep, depth + 1);
2286 }
2287 found = 1;
2288 *activep = oactive;
2289 }
2290 if (found != 0) {
2291 free(arg);
2292 continue;
2293 }
2294
2295 /* requested glob was not in cache */
2296 debug2("%s line %d: new include %s",
2297 filename, linenum, arg);
2298 if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {
2299 if (r != GLOB_NOMATCH) {
2300 fatal("%s line %d: include \"%s\" glob "
2301 "failed", filename, linenum, arg);
2302 }
2303 /*
2304 * If no entry matched then record a
2305 * placeholder to skip later glob calls.
2306 */
2307 debug2("%s line %d: no match for %s",
2308 filename, linenum, arg);
2309 item = xcalloc(1, sizeof(*item));
2310 item->selector = strdup(arg);
2311 TAILQ_INSERT_TAIL(includes,
2312 item, entry);
2313 }
2314 if (gbuf.gl_pathc > INT_MAX)
2315 fatal_f("too many glob results");
2316 for (n = 0; n < (int)gbuf.gl_pathc; n++) {
2317 debug2("%s line %d: including %s",
2318 filename, linenum, gbuf.gl_pathv[n]);
2319 item = xcalloc(1, sizeof(*item));
2320 item->selector = strdup(arg);
2321 item->filename = strdup(gbuf.gl_pathv[n]);
2322 if ((item->contents = sshbuf_new()) == NULL)
2323 fatal_f("sshbuf_new failed");
2324 load_server_config(item->filename,
2325 item->contents);
2326 parse_server_config_depth(options,
2327 item->filename, item->contents,
2328 includes, connectinfo,
2329 (*inc_flags & SSHCFG_MATCH_ONLY
2330 ? SSHCFG_MATCH_ONLY : (oactive
2331 ? 0 : SSHCFG_NEVERMATCH)),
2332 activep, depth + 1);
2333 *activep = oactive;
2334 TAILQ_INSERT_TAIL(includes, item, entry);
2335 }
2336 globfree(&gbuf);
2337 free(arg);
2338 }
2339 if (value == 0) {
2340 fatal("%s line %d: %s missing filename argument",
2341 filename, linenum, keyword);
2342 }
2343 break;
2344
2345 case sMatch:
2346 if (cmdline)
2347 fatal("Match directive not supported as a command-line "
2348 "option");
2349 value = match_cfg_line(str, &ac, &av, linenum,
2350 (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
2351 if (value < 0)
2352 fatal("%s line %d: Bad Match condition", filename,
2353 linenum);
2354 *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
2355 /*
2356 * The MATCH_ONLY flag is applicable only until the first
2357 * match block.
2358 */
2359 *inc_flags &= ~SSHCFG_MATCH_ONLY;
2360 break;
2361
2362 case sPermitListen:
2363 case sPermitOpen:
2364 if (opcode == sPermitListen) {
2365 uintptr = &options->num_permitted_listens;
2366 chararrayptr = &options->permitted_listens;
2367 } else {
2368 uintptr = &options->num_permitted_opens;
2369 chararrayptr = &options->permitted_opens;
2370 }
2371 found = *uintptr == 0;
2372 while ((arg = argv_next(&ac, &av)) != NULL) {
2373 if (strcmp(arg, "any") == 0 ||
2374 strcmp(arg, "none") == 0) {
2375 if (nstrs != 0) {
2376 fatal("%s line %d: %s must appear "
2377 "alone on a %s line.",
2378 filename, linenum, arg, keyword);
2379 }
2380 opt_array_append(filename, linenum, keyword,
2381 &strs, &nstrs, arg);
2382 continue;
2383 }
2384
2385 if (opcode == sPermitListen &&
2386 strchr(arg, ':') == NULL) {
2387 /*
2388 * Allow bare port number for PermitListen
2389 * to indicate a wildcard listen host.
2390 */
2391 xasprintf(&arg2, "*:%s", arg);
2392 } else {
2393 arg2 = xstrdup(arg);
2394 p = hpdelim(&arg);
2395 if (p == NULL) {
2396 fatal("%s line %d: %s missing host",
2397 filename, linenum, keyword);
2398 }
2399 p = cleanhostname(p);
2400 }
2401 if (arg == NULL ||
2402 ((port = permitopen_port(arg)) < 0)) {
2403 fatal("%s line %d: %s bad port number",
2404 filename, linenum, keyword);
2405 }
2406 opt_array_append(filename, linenum, keyword,
2407 &strs, &nstrs, arg2);
2408 free(arg2);
2409 }
2410 if (nstrs == 0) {
2411 fatal("%s line %d: %s missing argument.",
2412 filename, linenum, keyword);
2413 }
2414 if (found && *activep) {
2415 *chararrayptr = strs;
2416 *uintptr = nstrs;
2417 strs = NULL; /* transferred */
2418 nstrs = 0;
2419 }
2420 break;
2421
2422 case sForceCommand:
2423 if (str == NULL || *str == '\0')
2424 fatal("%s line %d: %s missing argument.",
2425 filename, linenum, keyword);
2426 len = strspn(str, WHITESPACE);
2427 if (*activep && options->adm_forced_command == NULL)
2428 options->adm_forced_command = xstrdup(str + len);
2429 argv_consume(&ac);
2430 break;
2431
2432 case sChrootDirectory:
2433 charptr = &options->chroot_directory;
2434
2435 arg = argv_next(&ac, &av);
2436 if (!arg || *arg == '\0')
2437 fatal("%s line %d: %s missing argument.",
2438 filename, linenum, keyword);
2439 if (*activep && *charptr == NULL)
2440 *charptr = xstrdup(arg);
2441 break;
2442
2443 case sTrustedUserCAKeys:
2444 charptr = &options->trusted_user_ca_keys;
2445 goto parse_filename;
2446
2447 case sRevokedKeys:
2448 uintptr = &options->num_revoked_keys_files;
2449 chararrayptr = &options->revoked_keys_files;
2450 goto parse_filenames;
2451
2452 case sSecurityKeyProvider:
2453 charptr = &options->sk_provider;
2454 arg = argv_next(&ac, &av);
2455 if (!arg || *arg == '\0')
2456 fatal("%s line %d: %s missing argument.",
2457 filename, linenum, keyword);
2458 if (*activep && *charptr == NULL) {
2459 *charptr = strcasecmp(arg, "internal") == 0 ?
2460 xstrdup(arg) : derelativise_path(arg);
2461 /* increase optional counter */
2462 if (intptr != NULL)
2463 *intptr = *intptr + 1;
2464 }
2465 break;
2466
2467 case sIPQoS:
2468 arg = argv_next(&ac, &av);
2469 if (!arg || *arg == '\0')
2470 fatal("%s line %d: %s missing argument.",
2471 filename, linenum, keyword);
2472 if ((value = parse_ipqos(arg)) == -1)
2473 fatal("%s line %d: Bad %s value: %s",
2474 filename, linenum, keyword, arg);
2475 if (value == INT_MIN) {
2476 debug("%s line %d: Deprecated IPQoS value \"%s\" "
2477 "ignored - using system default instead. Consider"
2478 " using DSCP values.", filename, linenum, arg);
2479 value = INT_MAX;
2480 }
2481 arg = argv_next(&ac, &av);
2482 if (arg == NULL)
2483 value2 = value;
2484 else if ((value2 = parse_ipqos(arg)) == -1)
2485 fatal("%s line %d: Bad %s value: %s",
2486 filename, linenum, keyword, arg);
2487 if (value2 == INT_MIN) {
2488 debug("%s line %d: Deprecated IPQoS value \"%s\" "
2489 "ignored - using system default instead. Consider"
2490 " using DSCP values.", filename, linenum, arg);
2491 value2 = INT_MAX;
2492 }
2493 if (*activep && options->ip_qos_interactive == -1) {
2494 options->ip_qos_interactive = value;
2495 options->ip_qos_bulk = value2;
2496 }
2497 break;
2498
2499 case sVersionAddendum:
2500 if (str == NULL || *str == '\0')
2501 fatal("%s line %d: %s missing argument.",
2502 filename, linenum, keyword);
2503 len = strspn(str, WHITESPACE);
2504 if (strchr(str + len, '\r') != NULL) {
2505 fatal("%.200s line %d: Invalid %s argument",
2506 filename, linenum, keyword);
2507 }
2508 if ((arg = strchr(line, '#')) != NULL) {
2509 *arg = '\0';
2510 rtrim(line);
2511 }
2512 if (*activep && options->version_addendum == NULL) {
2513 if (strcasecmp(str + len, "none") == 0)
2514 options->version_addendum = xstrdup("");
2515 else
2516 options->version_addendum = xstrdup(str + len);
2517 }
2518 argv_consume(&ac);
2519 break;
2520
2521 case sAuthorizedKeysCommand:
2522 charptr = &options->authorized_keys_command;
2523 parse_command:
2524 len = strspn(str, WHITESPACE);
2525 if (str[len] != '/' && strcasecmp(str + len, "none") != 0) {
2526 fatal("%.200s line %d: %s must be an absolute path",
2527 filename, linenum, keyword);
2528 }
2529 if (*activep && *charptr == NULL)
2530 *charptr = xstrdup(str + len);
2531 argv_consume(&ac);
2532 break;
2533
2534 case sAuthorizedKeysCommandUser:
2535 charptr = &options->authorized_keys_command_user;
2536 parse_localuser:
2537 arg = argv_next(&ac, &av);
2538 if (!arg || *arg == '\0') {
2539 fatal("%s line %d: missing %s argument.",
2540 filename, linenum, keyword);
2541 }
2542 if (*activep && *charptr == NULL)
2543 *charptr = xstrdup(arg);
2544 break;
2545
2546 case sAuthorizedPrincipalsCommand:
2547 charptr = &options->authorized_principals_command;
2548 goto parse_command;
2549
2550 case sAuthorizedPrincipalsCommandUser:
2551 charptr = &options->authorized_principals_command_user;
2552 goto parse_localuser;
2553
2554 case sAuthenticationMethods:
2555 found = options->num_auth_methods == 0;
2556 value = 0; /* seen "any" pseudo-method */
2557 while ((arg = argv_next(&ac, &av)) != NULL) {
2558 if (strcmp(arg, "any") == 0) {
2559 if (nstrs > 0) {
2560 fatal("%s line %d: \"any\" must "
2561 "appear alone in %s",
2562 filename, linenum, keyword);
2563 }
2564 value = 1;
2565 } else if (value) {
2566 fatal("%s line %d: \"any\" must appear "
2567 "alone in %s", filename, linenum, keyword);
2568 } else if (auth2_methods_valid(arg, 0) != 0) {
2569 fatal("%s line %d: invalid %s method list.",
2570 filename, linenum, keyword);
2571 }
2572 opt_array_append(filename, linenum, keyword,
2573 &strs, &nstrs, arg);
2574 }
2575 if (nstrs == 0) {
2576 fatal("%s line %d: no %s specified",
2577 filename, linenum, keyword);
2578 }
2579 if (found && *activep) {
2580 options->auth_methods = strs;
2581 options->num_auth_methods = nstrs;
2582 strs = NULL; /* transferred */
2583 nstrs = 0;
2584 }
2585 break;
2586
2587 case sStreamLocalBindMask:
2588 arg = argv_next(&ac, &av);
2589 if (!arg || *arg == '\0')
2590 fatal("%s line %d: %s missing argument.",
2591 filename, linenum, keyword);
2592 /* Parse mode in octal format */
2593 value = strtol(arg, &p, 8);
2594 if (arg == p || value < 0 || value > 0777)
2595 fatal("%s line %d: Invalid %s.",
2596 filename, linenum, keyword);
2597 if (*activep)
2598 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2599 break;
2600
2601 case sStreamLocalBindUnlink:
2602 intptr = &options->fwd_opts.streamlocal_bind_unlink;
2603 goto parse_flag;
2604
2605 case sFingerprintHash:
2606 arg = argv_next(&ac, &av);
2607 if (!arg || *arg == '\0')
2608 fatal("%s line %d: %s missing argument.",
2609 filename, linenum, keyword);
2610 if ((value = ssh_digest_alg_by_name(arg)) == -1)
2611 fatal("%.200s line %d: Invalid %s algorithm \"%s\".",
2612 filename, linenum, keyword, arg);
2613 if (*activep)
2614 options->fingerprint_hash = value;
2615 break;
2616
2617 case sExposeAuthInfo:
2618 intptr = &options->expose_userauth_info;
2619 goto parse_flag;
2620
2621 case sRDomain:
2622 charptr = &options->routing_domain;
2623 arg = argv_next(&ac, &av);
2624 if (!arg || *arg == '\0')
2625 fatal("%s line %d: %s missing argument.",
2626 filename, linenum, keyword);
2627 if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
2628 !valid_rdomain(arg))
2629 fatal("%s line %d: invalid routing domain",
2630 filename, linenum);
2631 if (*activep && *charptr == NULL)
2632 *charptr = xstrdup(arg);
2633 break;
2634
2635 case sRequiredRSASize:
2636 intptr = &options->required_rsa_size;
2637 goto parse_int;
2638
2639 case sChannelTimeout:
2640 found = options->num_channel_timeouts == 0;
2641 while ((arg = argv_next(&ac, &av)) != NULL) {
2642 /* Allow "none" only in first position */
2643 if (strcasecmp(arg, "none") == 0) {
2644 if (nstrs > 0 || ac > 0) {
2645 error("%s line %d: keyword %s \"none\" "
2646 "argument must appear alone.",
2647 filename, linenum, keyword);
2648 goto out;
2649 }
2650 } else if (parse_pattern_interval(arg,
2651 NULL, NULL) != 0) {
2652 fatal("%s line %d: invalid channel timeout %s",
2653 filename, linenum, arg);
2654 }
2655 opt_array_append(filename, linenum, keyword,
2656 &strs, &nstrs, arg);
2657 }
2658 if (nstrs == 0) {
2659 fatal("%s line %d: no %s specified",
2660 filename, linenum, keyword);
2661 }
2662 if (found && *activep) {
2663 options->channel_timeouts = strs;
2664 options->num_channel_timeouts = nstrs;
2665 strs = NULL; /* transferred */
2666 nstrs = 0;
2667 }
2668 break;
2669
2670 case sUnusedConnectionTimeout:
2671 intptr = &options->unused_connection_timeout;
2672 /* peek at first arg for "none" so we can reuse parse_time */
2673 if (av[0] != NULL && strcasecmp(av[0], "none") == 0) {
2674 (void)argv_next(&ac, &av); /* consume arg */
2675 if (*activep)
2676 *intptr = 0;
2677 break;
2678 }
2679 goto parse_time;
2680
2681 case sSshdSessionPath:
2682 charptr = &options->sshd_session_path;
2683 goto parse_filename;
2684
2685 case sSshdAuthPath:
2686 charptr = &options->sshd_auth_path;
2687 goto parse_filename;
2688
2689 case sRefuseConnection:
2690 intptr = &options->refuse_connection;
2691 multistate_ptr = multistate_flag;
2692 goto parse_multistate;
2693
2694 case sDeprecated:
2695 case sIgnore:
2696 case sUnsupported:
2697 do_log2(opcode == sIgnore ?
2698 SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
2699 "%s line %d: %s option %s", filename, linenum,
2700 opcode == sUnsupported ? "Unsupported" : "Deprecated",
2701 keyword);
2702 argv_consume(&ac);
2703 break;
2704
2705 default:
2706 fatal("%s line %d: Missing handler for opcode %s (%d)",
2707 filename, linenum, keyword, opcode);
2708 }
2709 /* Check that there is no garbage at end of line. */
2710 if (ac > 0) {
2711 error("%.200s line %d: keyword %s extra arguments "
2712 "at end of line", filename, linenum, keyword);
2713 goto out;
2714 }
2715
2716 /* success */
2717 ret = 0;
2718 out:
2719 opt_array_free2(strs, NULL, nstrs);
2720 argv_free(oav, oac);
2721 return ret;
2722}
2723
2724int
2725process_server_config_line(ServerOptions *options, char *line,
2726 const char *filename, int linenum, int *activep,
2727 struct connection_info *connectinfo, struct include_list *includes)
2728{
2729 int inc_flags = 0;
2730
2731 return process_server_config_line_depth(options, line, filename,
2732 linenum, activep, connectinfo, &inc_flags, 0, includes);
2733}
2734
2735
2736/* Reads the server configuration file. */
2737
2738void
2739load_server_config(const char *filename, struct sshbuf *conf)
2740{
2741 struct stat st;
2742 char *line = NULL, *cp;
2743 size_t linesize = 0;
2744 FILE *f;
2745 int r;
2746
2747 debug2_f("filename %s", filename);
2748 if ((f = fopen(filename, "r")) == NULL) {
2749 perror(filename);
2750 exit(1);
2751 }
2752 sshbuf_reset(conf);
2753 /* grow buffer, so realloc is avoided for large config files */
2754 if (fstat(fileno(f), &st) == 0 && st.st_size > 0 &&
2755 (r = sshbuf_allocate(conf, st.st_size)) != 0)
2756 fatal_fr(r, "allocate");
2757 while (getline(&line, &linesize, f) != -1) {
2758 /*
2759 * Strip whitespace
2760 * NB - preserve newlines, they are needed to reproduce
2761 * line numbers later for error messages
2762 */
2763 cp = line + strspn(line, " \t\r");
2764 if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)
2765 fatal_fr(r, "sshbuf_put");
2766 }
2767 free(line);
2768 if ((r = sshbuf_put_u8(conf, 0)) != 0)
2769 fatal_fr(r, "sshbuf_put_u8");
2770 fclose(f);
2771 debug2_f("done config len = %zu", sshbuf_len(conf));
2772}
2773
2774void
2775parse_server_match_config(ServerOptions *options,
2776 struct include_list *includes, struct connection_info *connectinfo)
2777{
2778 ServerOptions mo;
2779
2780 initialize_server_options(&mo);
2781 parse_server_config(&mo, "reprocess config", cfg, includes,
2782 connectinfo, 0);
2783 copy_set_server_options(options, &mo, 0);
2784}
2785
2786int
2787parse_server_match_testspec(struct connection_info *ci, char *spec)
2788{
2789 char *p;
2790 const char *val;
2791
2792 while ((p = strsep(&spec, ",")) && *p != '\0') {
2793 if ((val = strprefix(p, "addr=", 0)) != NULL) {
2794 ci->address = xstrdup(val);
2795 } else if ((val = strprefix(p, "host=", 0)) != NULL) {
2796 ci->host = xstrdup(val);
2797 } else if ((val = strprefix(p, "user=", 0)) != NULL) {
2798 ci->user = xstrdup(val);
2799 } else if ((val = strprefix(p, "laddr=", 0)) != NULL) {
2800 ci->laddress = xstrdup(val);
2801 } else if ((val = strprefix(p, "rdomain=", 0)) != NULL) {
2802 ci->rdomain = xstrdup(val);
2803 } else if ((val = strprefix(p, "lport=", 0)) != NULL) {
2804 ci->lport = a2port(val);
2805 if (ci->lport == -1) {
2806 fprintf(stderr, "Invalid port '%s' in test mode"
2807 " specification %s\n", p+6, p);
2808 return -1;
2809 }
2810 } else if (strcmp(p, "invalid-user") == 0) {
2811 ci->user_invalid = 1;
2812 } else {
2813 fprintf(stderr, "Invalid test mode specification %s\n",
2814 p);
2815 return -1;
2816 }
2817 }
2818 return 0;
2819}
2820
2821void
2822servconf_merge_subsystems(ServerOptions *dst, ServerOptions *src)
2823{
2824 u_int i, j, found;
2825
2826 for (i = 0; i < src->num_subsystems; i++) {
2827 found = 0;
2828 for (j = 0; j < dst->num_subsystems; j++) {
2829 if (strcmp(src->subsystem_name[i],
2830 dst->subsystem_name[j]) == 0) {
2831 found = 1;
2832 break;
2833 }
2834 }
2835 if (found) {
2836 debug_f("override \"%s\"", dst->subsystem_name[j]);
2837 free(dst->subsystem_command[j]);
2838 free(dst->subsystem_args[j]);
2839 dst->subsystem_command[j] =
2840 xstrdup(src->subsystem_command[i]);
2841 dst->subsystem_args[j] =
2842 xstrdup(src->subsystem_args[i]);
2843 continue;
2844 }
2845 debug_f("add \"%s\"", src->subsystem_name[i]);
2846 dst->subsystem_name = xrecallocarray(
2847 dst->subsystem_name, dst->num_subsystems,
2848 dst->num_subsystems + 1, sizeof(*dst->subsystem_name));
2849 dst->subsystem_command = xrecallocarray(
2850 dst->subsystem_command, dst->num_subsystems,
2851 dst->num_subsystems + 1, sizeof(*dst->subsystem_command));
2852 dst->subsystem_args = xrecallocarray(
2853 dst->subsystem_args, dst->num_subsystems,
2854 dst->num_subsystems + 1, sizeof(*dst->subsystem_args));
2855 j = dst->num_subsystems++;
2856 dst->subsystem_name[j] = xstrdup(src->subsystem_name[i]);
2857 dst->subsystem_command[j] = xstrdup(src->subsystem_command[i]);
2858 dst->subsystem_args[j] = xstrdup(src->subsystem_args[i]);
2859 }
2860}
2861
2862/*
2863 * Copy any supported values that are set.
2864 *
2865 * If the preauth flag is set, we do not bother copying the string or
2866 * array values that are not used pre-authentication, because any that we
2867 * do use must be explicitly sent in mm_getpwnamallow().
2868 */
2869void
2870copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
2871{
2872#define M_CP_INTOPT(n) do {\
2873 if (src->n != -1) \
2874 dst->n = src->n; \
2875} while (0)
2876
2877 M_CP_INTOPT(password_authentication);
2878 M_CP_INTOPT(gss_authentication);
2879 M_CP_INTOPT(pubkey_authentication);
2880 M_CP_INTOPT(pubkey_auth_options);
2881 M_CP_INTOPT(kerberos_authentication);
2882 M_CP_INTOPT(hostbased_authentication);
2883 M_CP_INTOPT(hostbased_uses_name_from_packet_only);
2884 M_CP_INTOPT(kbd_interactive_authentication);
2885 M_CP_INTOPT(permit_root_login);
2886 M_CP_INTOPT(permit_empty_passwd);
2887 M_CP_INTOPT(ignore_rhosts);
2888
2889 M_CP_INTOPT(allow_tcp_forwarding);
2890 M_CP_INTOPT(allow_streamlocal_forwarding);
2891 M_CP_INTOPT(allow_agent_forwarding);
2892 M_CP_INTOPT(disable_forwarding);
2893 M_CP_INTOPT(expose_userauth_info);
2894 M_CP_INTOPT(permit_tun);
2895 M_CP_INTOPT(fwd_opts.gateway_ports);
2896 M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
2897 M_CP_INTOPT(x11_display_offset);
2898 M_CP_INTOPT(x11_forwarding);
2899 M_CP_INTOPT(x11_use_localhost);
2900 M_CP_INTOPT(permit_tty);
2901 M_CP_INTOPT(permit_user_rc);
2902 M_CP_INTOPT(max_sessions);
2903 M_CP_INTOPT(max_authtries);
2904 M_CP_INTOPT(client_alive_count_max);
2905 M_CP_INTOPT(client_alive_interval);
2906 M_CP_INTOPT(ip_qos_interactive);
2907 M_CP_INTOPT(ip_qos_bulk);
2908 M_CP_INTOPT(rekey_limit);
2909 M_CP_INTOPT(rekey_interval);
2910 M_CP_INTOPT(log_level);
2911 M_CP_INTOPT(required_rsa_size);
2912 M_CP_INTOPT(unused_connection_timeout);
2913 M_CP_INTOPT(refuse_connection);
2914
2915 /*
2916 * The bind_mask is a mode_t that may be unsigned, so we can't use
2917 * M_CP_INTOPT - it does a signed comparison that causes compiler
2918 * warnings.
2919 */
2920 if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) {
2921 dst->fwd_opts.streamlocal_bind_mask =
2922 src->fwd_opts.streamlocal_bind_mask;
2923 }
2924
2925 /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
2926#define M_CP_STROPT(n) do {\
2927 if (src->n != NULL && dst->n != src->n) { \
2928 free(dst->n); \
2929 dst->n = xstrdup(src->n); \
2930 } \
2931} while(0)
2932#define M_CP_STRARRAYOPT(s, num_s, clobber) do {\
2933 u_int i; \
2934 if (src->num_s != 0) { \
2935 for (i = 0; i < dst->num_s; i++) \
2936 free(dst->s[i]); \
2937 free(dst->s); \
2938 dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \
2939 for (i = 0; i < src->num_s; i++) \
2940 dst->s[i] = xstrdup(src->s[i]); \
2941 if (clobber) \
2942 dst->num_s = src->num_s; \
2943 } \
2944} while(0)
2945
2946 /* See comment in servconf.h */
2947 COPY_MATCH_STRING_OPTS();
2948
2949 /* Arguments that accept '+...' need to be expanded */
2950 assemble_algorithms(dst);
2951
2952 /*
2953 * The only things that should be below this point are string options
2954 * which are only used after authentication.
2955 */
2956 if (preauth)
2957 return;
2958
2959 /* These options may be "none" to clear a global setting */
2960 M_CP_STROPT(adm_forced_command);
2961 if (option_clear_or_none(dst->adm_forced_command)) {
2962 free(dst->adm_forced_command);
2963 dst->adm_forced_command = NULL;
2964 }
2965 M_CP_STROPT(chroot_directory);
2966 if (option_clear_or_none(dst->chroot_directory)) {
2967 free(dst->chroot_directory);
2968 dst->chroot_directory = NULL;
2969 }
2970
2971 /* Subsystems require merging. */
2972 servconf_merge_subsystems(dst, src);
2973}
2974
2975#undef M_CP_INTOPT
2976#undef M_CP_STROPT
2977#undef M_CP_STRARRAYOPT
2978
2979#define SERVCONF_MAX_DEPTH 16
2980static void
2981parse_server_config_depth(ServerOptions *options, const char *filename,
2982 struct sshbuf *conf, struct include_list *includes,
2983 struct connection_info *connectinfo, int flags, int *activep, int depth)
2984{
2985 int linenum, bad_options = 0;
2986 char *cp, *obuf, *cbuf;
2987
2988 if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
2989 fatal("Too many recursive configuration includes");
2990
2991 debug2_f("config %s len %zu%s", filename, sshbuf_len(conf),
2992 (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : ""));
2993
2994 if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
2995 fatal_f("sshbuf_dup_string failed");
2996 linenum = 1;
2997 while ((cp = strsep(&cbuf, "\n")) != NULL) {
2998 if (process_server_config_line_depth(options, cp,
2999 filename, linenum++, activep, connectinfo, &flags,
3000 depth, includes) != 0)
3001 bad_options++;
3002 }
3003 free(obuf);
3004 if (bad_options > 0)
3005 fatal("%s: terminating, %d bad configuration options",
3006 filename, bad_options);
3007}
3008
3009void
3010parse_server_config(ServerOptions *options, const char *filename,
3011 struct sshbuf *conf, struct include_list *includes,
3012 struct connection_info *connectinfo, int reexec)
3013{
3014 int active = connectinfo ? 0 : 1;
3015 parse_server_config_depth(options, filename, conf, includes,
3016 connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0);
3017 if (!reexec)
3018 process_queued_listen_addrs(options);
3019}
3020
3021static const char *
3022fmt_multistate_int(int val, const struct multistate *m)
3023{
3024 u_int i;
3025
3026 for (i = 0; m[i].key != NULL; i++) {
3027 if (m[i].value == val)
3028 return m[i].key;
3029 }
3030 return "UNKNOWN";
3031}
3032
3033static const char *
3034fmt_intarg(ServerOpCodes code, int val)
3035{
3036 if (val == -1)
3037 return "unset";
3038 switch (code) {
3039 case sAddressFamily:
3040 return fmt_multistate_int(val, multistate_addressfamily);
3041 case sPermitRootLogin:
3042 return fmt_multistate_int(val, multistate_permitrootlogin);
3043 case sGatewayPorts:
3044 return fmt_multistate_int(val, multistate_gatewayports);
3045 case sCompression:
3046 return fmt_multistate_int(val, multistate_compression);
3047 case sAllowTcpForwarding:
3048 return fmt_multistate_int(val, multistate_tcpfwd);
3049 case sAllowStreamLocalForwarding:
3050 return fmt_multistate_int(val, multistate_tcpfwd);
3051 case sIgnoreRhosts:
3052 return fmt_multistate_int(val, multistate_ignore_rhosts);
3053 case sFingerprintHash:
3054 return ssh_digest_alg_name(val);
3055 default:
3056 switch (val) {
3057 case 0:
3058 return "no";
3059 case 1:
3060 return "yes";
3061 default:
3062 return "UNKNOWN";
3063 }
3064 }
3065}
3066
3067static void
3068dump_cfg_int(ServerOpCodes code, int val)
3069{
3070 if (code == sUnusedConnectionTimeout && val == 0) {
3071 printf("%s none\n", lookup_opcode_name(code));
3072 return;
3073 }
3074 printf("%s %d\n", lookup_opcode_name(code), val);
3075}
3076
3077static void
3078dump_cfg_oct(ServerOpCodes code, int val)
3079{
3080 printf("%s 0%o\n", lookup_opcode_name(code), val);
3081}
3082
3083static void
3084dump_cfg_fmtint(ServerOpCodes code, int val)
3085{
3086 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3087}
3088
3089static void
3090dump_cfg_string(ServerOpCodes code, const char *val)
3091{
3092 printf("%s %s\n", lookup_opcode_name(code),
3093 val == NULL ? "none" : val);
3094}
3095
3096static void
3097dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
3098{
3099 u_int i;
3100
3101 for (i = 0; i < count; i++)
3102 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3103}
3104
3105static void
3106dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
3107{
3108 u_int i;
3109
3110 switch (code) {
3111 case sAuthenticationMethods:
3112 case sChannelTimeout:
3113 break;
3114 default:
3115 if (count <= 0)
3116 return;
3117 break;
3118 }
3119
3120 printf("%s", lookup_opcode_name(code));
3121 for (i = 0; i < count; i++)
3122 printf(" %s", vals[i]);
3123 if (code == sAuthenticationMethods && count == 0)
3124 printf(" any");
3125 else if (code == sChannelTimeout && count == 0)
3126 printf(" none");
3127 printf("\n");
3128}
3129
3130static char *
3131format_listen_addrs(struct listenaddr *la)
3132{
3133 int r;
3134 struct addrinfo *ai;
3135 char addr[NI_MAXHOST], port[NI_MAXSERV];
3136 char *laddr1 = xstrdup(""), *laddr2 = NULL;
3137
3138 /*
3139 * ListenAddress must be after Port. add_one_listen_addr pushes
3140 * addresses onto a stack, so to maintain ordering we need to
3141 * print these in reverse order.
3142 */
3143 for (ai = la->addrs; ai; ai = ai->ai_next) {
3144 if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
3145 sizeof(addr), port, sizeof(port),
3146 NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
3147 error("getnameinfo: %.100s", ssh_gai_strerror(r));
3148 continue;
3149 }
3150 laddr2 = laddr1;
3151 if (ai->ai_family == AF_INET6) {
3152 xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s",
3153 addr, port,
3154 la->rdomain == NULL ? "" : " rdomain ",
3155 la->rdomain == NULL ? "" : la->rdomain,
3156 laddr2);
3157 } else {
3158 xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s",
3159 addr, port,
3160 la->rdomain == NULL ? "" : " rdomain ",
3161 la->rdomain == NULL ? "" : la->rdomain,
3162 laddr2);
3163 }
3164 free(laddr2);
3165 }
3166 return laddr1;
3167}
3168
3169void
3170dump_config(ServerOptions *o)
3171{
3172 char *s;
3173 u_int i;
3174
3175 /* these are usually at the top of the config */
3176 for (i = 0; i < o->num_ports; i++)
3177 printf("port %d\n", o->ports[i]);
3178 dump_cfg_fmtint(sAddressFamily, o->address_family);
3179
3180 for (i = 0; i < o->num_listen_addrs; i++) {
3181 s = format_listen_addrs(&o->listen_addrs[i]);
3182 printf("%s", s);
3183 free(s);
3184 }
3185
3186 /* integer arguments */
3187 dump_cfg_int(sLoginGraceTime, o->login_grace_time);
3188 dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
3189 dump_cfg_int(sMaxAuthTries, o->max_authtries);
3190 dump_cfg_int(sMaxSessions, o->max_sessions);
3191 dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
3192 dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
3193 dump_cfg_int(sRequiredRSASize, o->required_rsa_size);
3194 dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
3195 dump_cfg_int(sUnusedConnectionTimeout, o->unused_connection_timeout);
3196
3197 /* formatted integer arguments */
3198 dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
3199 dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
3200 dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
3201 dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
3202 dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
3203 o->hostbased_uses_name_from_packet_only);
3204 dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
3205#ifdef KRB5
3206 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
3207 dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
3208 dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
3209 dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
3210#endif
3211#ifdef GSSAPI
3212 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
3213 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
3214 dump_cfg_fmtint(sGssDelegateCreds, o->gss_deleg_creds);
3215 dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
3216#endif
3217 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
3218 dump_cfg_fmtint(sKbdInteractiveAuthentication,
3219 o->kbd_interactive_authentication);
3220 dump_cfg_fmtint(sPrintMotd, o->print_motd);
3221 dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
3222 dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
3223 dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
3224 dump_cfg_fmtint(sPermitTTY, o->permit_tty);
3225 dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc);
3226 dump_cfg_fmtint(sStrictModes, o->strict_modes);
3227 dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
3228 dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
3229 dump_cfg_fmtint(sCompression, o->compression);
3230 dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
3231 dump_cfg_fmtint(sUseDNS, o->use_dns);
3232 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
3233 dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
3234 dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding);
3235 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
3236 dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3237 dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
3238 dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
3239 dump_cfg_fmtint(sRefuseConnection, o->refuse_connection);
3240
3241 /* string arguments */
3242 dump_cfg_string(sPidFile, o->pid_file);
3243 dump_cfg_string(sModuliFile, o->moduli_file);
3244 dump_cfg_string(sXAuthLocation, o->xauth_location);
3245 dump_cfg_string(sCiphers, o->ciphers);
3246 dump_cfg_string(sMacs, o->macs);
3247 dump_cfg_string(sBanner, o->banner);
3248 dump_cfg_string(sForceCommand, o->adm_forced_command);
3249 dump_cfg_string(sChrootDirectory, o->chroot_directory);
3250 dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
3251 dump_cfg_string(sSecurityKeyProvider, o->sk_provider);
3252 dump_cfg_string(sAuthorizedPrincipalsFile,
3253 o->authorized_principals_file);
3254 dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0'
3255 ? "none" : o->version_addendum);
3256 dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
3257 dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
3258 dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command);
3259 dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user);
3260 dump_cfg_string(sHostKeyAgent, o->host_key_agent);
3261 dump_cfg_string(sKexAlgorithms, o->kex_algorithms);
3262 dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms);
3263 dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3264 dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms);
3265 dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3266 dump_cfg_string(sRDomain, o->routing_domain);
3267 dump_cfg_string(sSshdSessionPath, o->sshd_session_path);
3268 dump_cfg_string(sSshdAuthPath, o->sshd_auth_path);
3269 dump_cfg_string(sPerSourcePenaltyExemptList, o->per_source_penalty_exempt);
3270
3271 /* string arguments requiring a lookup */
3272 dump_cfg_string(sLogLevel, log_level_name(o->log_level));
3273 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
3274
3275 /* string array arguments */
3276 dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
3277 o->authorized_keys_files);
3278 dump_cfg_strarray_oneline(sRevokedKeys, o->num_revoked_keys_files,
3279 o->revoked_keys_files);
3280 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
3281 o->host_key_files);
3282 dump_cfg_strarray(sHostCertificate, o->num_host_cert_files,
3283 o->host_cert_files);
3284 dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
3285 dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
3286 dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
3287 dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
3288 dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
3289 dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv);
3290 dump_cfg_strarray_oneline(sAuthenticationMethods,
3291 o->num_auth_methods, o->auth_methods);
3292 dump_cfg_strarray_oneline(sLogVerbose,
3293 o->num_log_verbose, o->log_verbose);
3294 dump_cfg_strarray_oneline(sChannelTimeout,
3295 o->num_channel_timeouts, o->channel_timeouts);
3296
3297 /* other arguments */
3298 for (i = 0; i < o->num_subsystems; i++)
3299 printf("subsystem %s %s\n", o->subsystem_name[i],
3300 o->subsystem_args[i]);
3301
3302 printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
3303 o->max_startups_rate, o->max_startups);
3304 printf("persourcemaxstartups ");
3305 if (o->per_source_max_startups == INT_MAX)
3306 printf("none\n");
3307 else
3308 printf("%d\n", o->per_source_max_startups);
3309 printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4,
3310 o->per_source_masklen_ipv6);
3311
3312 s = NULL;
3313 for (i = 0; tunmode_desc[i].val != -1; i++) {
3314 if (tunmode_desc[i].val == o->permit_tun) {
3315 s = tunmode_desc[i].text;
3316 break;
3317 }
3318 }
3319 dump_cfg_string(sPermitTunnel, s);
3320
3321 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3322 printf("%s\n", iptos2str(o->ip_qos_bulk));
3323
3324 printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit,
3325 o->rekey_interval);
3326
3327 printf("permitopen");
3328 if (o->num_permitted_opens == 0)
3329 printf(" any");
3330 else {
3331 for (i = 0; i < o->num_permitted_opens; i++)
3332 printf(" %s", o->permitted_opens[i]);
3333 }
3334 printf("\n");
3335 printf("permitlisten");
3336 if (o->num_permitted_listens == 0)
3337 printf(" any");
3338 else {
3339 for (i = 0; i < o->num_permitted_listens; i++)
3340 printf(" %s", o->permitted_listens[i]);
3341 }
3342 printf("\n");
3343
3344 if (o->permit_user_env_allowlist == NULL) {
3345 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
3346 } else {
3347 printf("permituserenvironment %s\n",
3348 o->permit_user_env_allowlist);
3349 }
3350
3351 printf("pubkeyauthoptions");
3352 if (o->pubkey_auth_options == 0)
3353 printf(" none");
3354 if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
3355 printf(" touch-required");
3356 if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED)
3357 printf(" verify-required");
3358 printf("\n");
3359
3360 if (o->per_source_penalty.enabled) {
3361 printf("persourcepenalties crash:%f authfail:%f noauth:%f "
3362 "invaliduser:%f "
3363 "grace-exceeded:%f refuseconnection:%f max:%f min:%f "
3364 "max-sources4:%d max-sources6:%d "
3365 "overflow:%s overflow6:%s\n",
3366 o->per_source_penalty.penalty_crash,
3367 o->per_source_penalty.penalty_authfail,
3368 o->per_source_penalty.penalty_noauth,
3369 o->per_source_penalty.penalty_invaliduser,
3370 o->per_source_penalty.penalty_grace,
3371 o->per_source_penalty.penalty_refuseconnection,
3372 o->per_source_penalty.penalty_max,
3373 o->per_source_penalty.penalty_min,
3374 o->per_source_penalty.max_sources4,
3375 o->per_source_penalty.max_sources6,
3376 o->per_source_penalty.overflow_mode ==
3377 PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ?
3378 "deny-all" : "permissive",
3379 o->per_source_penalty.overflow_mode6 ==
3380 PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ?
3381 "deny-all" : "permissive");
3382 } else
3383 printf("persourcepenalties no\n");
3384}