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