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