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