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