Bug Summary

File:src/usr.bin/ssh/sshd/../servconf.c
Warning:line 2166, column 10
Although the value stored to 'port' is used in the enclosing expression, the value is never actually read from 'port'

Annotated Source Code

Press '?' to see keyboard shortcuts

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