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