1eccfee6eSDag-Erling Smørgrav 2*1323ec57SEd Maste /* $OpenBSD: servconf.c,v 1.383 2022/02/08 08:59:12 dtucker Exp $ */ 3511b41d2SMark Murray /* 4511b41d2SMark Murray * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5511b41d2SMark Murray * All rights reserved 6511b41d2SMark Murray * 7c2d3a559SKris Kennaway * As far as I am concerned, the code I have written for this software 8c2d3a559SKris Kennaway * can be used freely for any purpose. Any derived versions of this 9c2d3a559SKris Kennaway * software must be clearly marked as such, and if the derived work is 10c2d3a559SKris Kennaway * incompatible with the protocol description in the RFC file, it must be 11c2d3a559SKris Kennaway * called by a name other than "ssh" or "Secure Shell". 12511b41d2SMark Murray */ 13511b41d2SMark Murray 14511b41d2SMark Murray #include "includes.h" 15333ee039SDag-Erling Smørgrav __RCSID("$FreeBSD$"); 16511b41d2SMark Murray 17333ee039SDag-Erling Smørgrav #include <sys/types.h> 18333ee039SDag-Erling Smørgrav #include <sys/socket.h> 1919261079SEd Maste #include <sys/stat.h> 2019261079SEd Maste #ifdef __OpenBSD__ 2147dd1d1bSDag-Erling Smørgrav #include <sys/sysctl.h> 2247dd1d1bSDag-Erling Smørgrav #endif 23333ee039SDag-Erling Smørgrav 244a421b63SDag-Erling Smørgrav #include <netinet/in.h> 254a421b63SDag-Erling Smørgrav #include <netinet/in_systm.h> 264a421b63SDag-Erling Smørgrav #include <netinet/ip.h> 2747dd1d1bSDag-Erling Smørgrav #ifdef HAVE_NET_ROUTE_H 2847dd1d1bSDag-Erling Smørgrav #include <net/route.h> 2947dd1d1bSDag-Erling Smørgrav #endif 304a421b63SDag-Erling Smørgrav 31e4a9863fSDag-Erling Smørgrav #include <ctype.h> 32333ee039SDag-Erling Smørgrav #include <netdb.h> 33333ee039SDag-Erling Smørgrav #include <pwd.h> 34333ee039SDag-Erling Smørgrav #include <stdio.h> 35333ee039SDag-Erling Smørgrav #include <stdlib.h> 36333ee039SDag-Erling Smørgrav #include <string.h> 37333ee039SDag-Erling Smørgrav #include <signal.h> 38333ee039SDag-Erling Smørgrav #include <unistd.h> 39bc5531deSDag-Erling Smørgrav #include <limits.h> 40333ee039SDag-Erling Smørgrav #include <stdarg.h> 41d4af9e69SDag-Erling Smørgrav #include <errno.h> 42e4a9863fSDag-Erling Smørgrav #ifdef HAVE_UTIL_H 43e4a9863fSDag-Erling Smørgrav #include <util.h> 44e4a9863fSDag-Erling Smørgrav #endif 4519261079SEd Maste #ifdef USE_SYSTEM_GLOB 4619261079SEd Maste # include <glob.h> 4719261079SEd Maste #else 4819261079SEd Maste # include "openbsd-compat/glob.h" 4919261079SEd Maste #endif 50333ee039SDag-Erling Smørgrav 51d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h" 52333ee039SDag-Erling Smørgrav #include "xmalloc.h" 53511b41d2SMark Murray #include "ssh.h" 54ca3176e7SBrian Feldman #include "log.h" 55190cef3dSDag-Erling Smørgrav #include "sshbuf.h" 56a0ee8cc6SDag-Erling Smørgrav #include "misc.h" 57511b41d2SMark Murray #include "servconf.h" 58e8aafc91SKris Kennaway #include "compat.h" 59ca3176e7SBrian Feldman #include "pathnames.h" 60ca3176e7SBrian Feldman #include "cipher.h" 61190cef3dSDag-Erling Smørgrav #include "sshkey.h" 62ca3176e7SBrian Feldman #include "kex.h" 63ca3176e7SBrian Feldman #include "mac.h" 64333ee039SDag-Erling Smørgrav #include "match.h" 65333ee039SDag-Erling Smørgrav #include "channels.h" 66333ee039SDag-Erling Smørgrav #include "groupaccess.h" 67462c32cbSDag-Erling Smørgrav #include "canohost.h" 68462c32cbSDag-Erling Smørgrav #include "packet.h" 69190cef3dSDag-Erling Smørgrav #include "ssherr.h" 706888a9beSDag-Erling Smørgrav #include "hostfile.h" 716888a9beSDag-Erling Smørgrav #include "auth.h" 72bc5531deSDag-Erling Smørgrav #include "myproposal.h" 73bc5531deSDag-Erling Smørgrav #include "digest.h" 74b15c8340SDag-Erling Smørgrav #include "version.h" 75511b41d2SMark Murray 7647dd1d1bSDag-Erling Smørgrav static void add_listen_addr(ServerOptions *, const char *, 7747dd1d1bSDag-Erling Smørgrav const char *, int); 7847dd1d1bSDag-Erling Smørgrav static void add_one_listen_addr(ServerOptions *, const char *, 7947dd1d1bSDag-Erling Smørgrav const char *, int); 8019261079SEd Maste static void parse_server_config_depth(ServerOptions *options, 8119261079SEd Maste const char *filename, struct sshbuf *conf, struct include_list *includes, 8219261079SEd Maste struct connection_info *connectinfo, int flags, int *activep, int depth); 83ca3176e7SBrian Feldman 8480628bacSDag-Erling Smørgrav /* Use of privilege separation or not */ 8580628bacSDag-Erling Smørgrav extern int use_privsep; 86190cef3dSDag-Erling Smørgrav extern struct sshbuf *cfg; 87511b41d2SMark Murray 88511b41d2SMark Murray /* Initializes the server options to their default values. */ 89511b41d2SMark Murray 90511b41d2SMark Murray void 91511b41d2SMark Murray initialize_server_options(ServerOptions *options) 92511b41d2SMark Murray { 93511b41d2SMark Murray memset(options, 0, sizeof(*options)); 94989dd127SDag-Erling Smørgrav 95989dd127SDag-Erling Smørgrav /* Portable-specific options */ 96cf2b5f3bSDag-Erling Smørgrav options->use_pam = -1; 97989dd127SDag-Erling Smørgrav 98989dd127SDag-Erling Smørgrav /* Standard Options */ 99511b41d2SMark Murray options->num_ports = 0; 100511b41d2SMark Murray options->ports_from_cmdline = 0; 101557f75e5SDag-Erling Smørgrav options->queued_listen_addrs = NULL; 102557f75e5SDag-Erling Smørgrav options->num_queued_listens = 0; 103511b41d2SMark Murray options->listen_addrs = NULL; 10447dd1d1bSDag-Erling Smørgrav options->num_listen_addrs = 0; 105aa49c926SDag-Erling Smørgrav options->address_family = -1; 10647dd1d1bSDag-Erling Smørgrav options->routing_domain = NULL; 107ca3176e7SBrian Feldman options->num_host_key_files = 0; 108b15c8340SDag-Erling Smørgrav options->num_host_cert_files = 0; 109e4a9863fSDag-Erling Smørgrav options->host_key_agent = NULL; 110e8aafc91SKris Kennaway options->pid_file = NULL; 111511b41d2SMark Murray options->login_grace_time = -1; 112ca3176e7SBrian Feldman options->permit_root_login = PERMIT_NOT_SET; 113511b41d2SMark Murray options->ignore_rhosts = -1; 114511b41d2SMark Murray options->ignore_user_known_hosts = -1; 115511b41d2SMark Murray options->print_motd = -1; 116ca3176e7SBrian Feldman options->print_lastlog = -1; 117511b41d2SMark Murray options->x11_forwarding = -1; 118511b41d2SMark Murray options->x11_display_offset = -1; 119af12a3e7SDag-Erling Smørgrav options->x11_use_localhost = -1; 120f7167e0eSDag-Erling Smørgrav options->permit_tty = -1; 121a0ee8cc6SDag-Erling Smørgrav options->permit_user_rc = -1; 122c2d3a559SKris Kennaway options->xauth_location = NULL; 123511b41d2SMark Murray options->strict_modes = -1; 1241ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = -1; 125af12a3e7SDag-Erling Smørgrav options->log_facility = SYSLOG_FACILITY_NOT_SET; 126af12a3e7SDag-Erling Smørgrav options->log_level = SYSLOG_LEVEL_NOT_SET; 12719261079SEd Maste options->num_log_verbose = 0; 12819261079SEd Maste options->log_verbose = NULL; 129ca3176e7SBrian Feldman options->hostbased_authentication = -1; 130ca3176e7SBrian Feldman options->hostbased_uses_name_from_packet_only = -1; 13119261079SEd Maste options->hostbased_accepted_algos = NULL; 132eccfee6eSDag-Erling Smørgrav options->hostkeyalgorithms = NULL; 133ca3176e7SBrian Feldman options->pubkey_authentication = -1; 13419261079SEd Maste options->pubkey_auth_options = -1; 13519261079SEd Maste options->pubkey_accepted_algos = NULL; 136cb96ab36SAssar Westerlund options->kerberos_authentication = -1; 137af12a3e7SDag-Erling Smørgrav options->kerberos_or_local_passwd = -1; 138af12a3e7SDag-Erling Smørgrav options->kerberos_ticket_cleanup = -1; 1391ec0d754SDag-Erling Smørgrav options->kerberos_get_afs_token = -1; 140cf2b5f3bSDag-Erling Smørgrav options->gss_authentication=-1; 141cf2b5f3bSDag-Erling Smørgrav options->gss_cleanup_creds = -1; 142557f75e5SDag-Erling Smørgrav options->gss_strict_acceptor = -1; 143511b41d2SMark Murray options->password_authentication = -1; 14409958426SBrian Feldman options->kbd_interactive_authentication = -1; 145511b41d2SMark Murray options->permit_empty_passwd = -1; 146f388f5efSDag-Erling Smørgrav options->permit_user_env = -1; 14719261079SEd Maste options->permit_user_env_allowlist = NULL; 14880628bacSDag-Erling Smørgrav options->compression = -1; 149e4a9863fSDag-Erling Smørgrav options->rekey_limit = -1; 150e4a9863fSDag-Erling Smørgrav options->rekey_interval = -1; 15109958426SBrian Feldman options->allow_tcp_forwarding = -1; 152a0ee8cc6SDag-Erling Smørgrav options->allow_streamlocal_forwarding = -1; 153d4af9e69SDag-Erling Smørgrav options->allow_agent_forwarding = -1; 154511b41d2SMark Murray options->num_allow_users = 0; 155511b41d2SMark Murray options->num_deny_users = 0; 156511b41d2SMark Murray options->num_allow_groups = 0; 157511b41d2SMark Murray options->num_deny_groups = 0; 158e8aafc91SKris Kennaway options->ciphers = NULL; 159ca3176e7SBrian Feldman options->macs = NULL; 1604a421b63SDag-Erling Smørgrav options->kex_algorithms = NULL; 1612f513db7SEd Maste options->ca_sign_algorithms = NULL; 162a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.gateway_ports = -1; 163a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 164a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_unlink = -1; 165c2d3a559SKris Kennaway options->num_subsystems = 0; 166c2d3a559SKris Kennaway options->max_startups_begin = -1; 167c2d3a559SKris Kennaway options->max_startups_rate = -1; 168c2d3a559SKris Kennaway options->max_startups = -1; 16919261079SEd Maste options->per_source_max_startups = -1; 17019261079SEd Maste options->per_source_masklen_ipv4 = -1; 17119261079SEd Maste options->per_source_masklen_ipv6 = -1; 17221e764dfSDag-Erling Smørgrav options->max_authtries = -1; 173d4af9e69SDag-Erling Smørgrav options->max_sessions = -1; 174ca3176e7SBrian Feldman options->banner = NULL; 175cf2b5f3bSDag-Erling Smørgrav options->use_dns = -1; 176ca3176e7SBrian Feldman options->client_alive_interval = -1; 177ca3176e7SBrian Feldman options->client_alive_count_max = -1; 178e146993eSDag-Erling Smørgrav options->num_authkeys_files = 0; 17921e764dfSDag-Erling Smørgrav options->num_accept_env = 0; 180190cef3dSDag-Erling Smørgrav options->num_setenv = 0; 181b74df5b2SDag-Erling Smørgrav options->permit_tun = -1; 1824f52dfbbSDag-Erling Smørgrav options->permitted_opens = NULL; 183190cef3dSDag-Erling Smørgrav options->permitted_listens = NULL; 184333ee039SDag-Erling Smørgrav options->adm_forced_command = NULL; 185d4af9e69SDag-Erling Smørgrav options->chroot_directory = NULL; 1866888a9beSDag-Erling Smørgrav options->authorized_keys_command = NULL; 1876888a9beSDag-Erling Smørgrav options->authorized_keys_command_user = NULL; 188b15c8340SDag-Erling Smørgrav options->revoked_keys_file = NULL; 18919261079SEd Maste options->sk_provider = NULL; 190b15c8340SDag-Erling Smørgrav options->trusted_user_ca_keys = NULL; 191e2f6069cSDag-Erling Smørgrav options->authorized_principals_file = NULL; 192557f75e5SDag-Erling Smørgrav options->authorized_principals_command = NULL; 193557f75e5SDag-Erling Smørgrav options->authorized_principals_command_user = NULL; 1944a421b63SDag-Erling Smørgrav options->ip_qos_interactive = -1; 1954a421b63SDag-Erling Smørgrav options->ip_qos_bulk = -1; 196462c32cbSDag-Erling Smørgrav options->version_addendum = NULL; 197bc5531deSDag-Erling Smørgrav options->fingerprint_hash = -1; 198ca86bcf2SDag-Erling Smørgrav options->disable_forwarding = -1; 1994f52dfbbSDag-Erling Smørgrav options->expose_userauth_info = -1; 200b2af61ecSKurt Lidl options->use_blacklist = -1; 201bc5531deSDag-Erling Smørgrav } 202bc5531deSDag-Erling Smørgrav 203bc5531deSDag-Erling Smørgrav /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 204bc5531deSDag-Erling Smørgrav static int 205bc5531deSDag-Erling Smørgrav option_clear_or_none(const char *o) 206bc5531deSDag-Erling Smørgrav { 207bc5531deSDag-Erling Smørgrav return o == NULL || strcasecmp(o, "none") == 0; 208511b41d2SMark Murray } 209511b41d2SMark Murray 210acc1a9efSDag-Erling Smørgrav static void 211acc1a9efSDag-Erling Smørgrav assemble_algorithms(ServerOptions *o) 212acc1a9efSDag-Erling Smørgrav { 2132f513db7SEd Maste char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 21419261079SEd Maste char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 215190cef3dSDag-Erling Smørgrav int r; 216190cef3dSDag-Erling Smørgrav 217190cef3dSDag-Erling Smørgrav all_cipher = cipher_alg_list(',', 0); 218190cef3dSDag-Erling Smørgrav all_mac = mac_alg_list(','); 219190cef3dSDag-Erling Smørgrav all_kex = kex_alg_list(','); 220190cef3dSDag-Erling Smørgrav all_key = sshkey_alg_list(0, 0, 1, ','); 2212f513db7SEd Maste all_sig = sshkey_alg_list(0, 1, 1, ','); 22219261079SEd Maste /* remove unsupported algos from default lists */ 22319261079SEd Maste def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher); 22419261079SEd Maste def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac); 22519261079SEd Maste def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex); 22619261079SEd Maste def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 22719261079SEd Maste def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 228190cef3dSDag-Erling Smørgrav #define ASSEMBLE(what, defaults, all) \ 229190cef3dSDag-Erling Smørgrav do { \ 230190cef3dSDag-Erling Smørgrav if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ 23119261079SEd Maste fatal_fr(r, "%s", #what); \ 232190cef3dSDag-Erling Smørgrav } while (0) 23319261079SEd Maste ASSEMBLE(ciphers, def_cipher, all_cipher); 23419261079SEd Maste ASSEMBLE(macs, def_mac, all_mac); 23519261079SEd Maste ASSEMBLE(kex_algorithms, def_kex, all_kex); 23619261079SEd Maste ASSEMBLE(hostkeyalgorithms, def_key, all_key); 23719261079SEd Maste ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 23819261079SEd Maste ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 23919261079SEd Maste ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 240190cef3dSDag-Erling Smørgrav #undef ASSEMBLE 241190cef3dSDag-Erling Smørgrav free(all_cipher); 242190cef3dSDag-Erling Smørgrav free(all_mac); 243190cef3dSDag-Erling Smørgrav free(all_kex); 244190cef3dSDag-Erling Smørgrav free(all_key); 2452f513db7SEd Maste free(all_sig); 24619261079SEd Maste free(def_cipher); 24719261079SEd Maste free(def_mac); 24819261079SEd Maste free(def_kex); 24919261079SEd Maste free(def_key); 25019261079SEd Maste free(def_sig); 25147dd1d1bSDag-Erling Smørgrav } 25247dd1d1bSDag-Erling Smørgrav 25347dd1d1bSDag-Erling Smørgrav static const char *defaultkey = "[default]"; 25447dd1d1bSDag-Erling Smørgrav 25547dd1d1bSDag-Erling Smørgrav void 25647dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(const char *file, const int line, 25719261079SEd Maste ServerOptions *options, const char *path, int userprovided) 25847dd1d1bSDag-Erling Smørgrav { 25947dd1d1bSDag-Erling Smørgrav char *apath = derelativise_path(path); 26047dd1d1bSDag-Erling Smørgrav 26147dd1d1bSDag-Erling Smørgrav if (file == defaultkey && access(path, R_OK) != 0) 26247dd1d1bSDag-Erling Smørgrav return; 26319261079SEd Maste opt_array_append2(file, line, "HostKey", 26419261079SEd Maste &options->host_key_files, &options->host_key_file_userprovided, 26519261079SEd Maste &options->num_host_key_files, apath, userprovided); 26647dd1d1bSDag-Erling Smørgrav free(apath); 26747dd1d1bSDag-Erling Smørgrav } 26847dd1d1bSDag-Erling Smørgrav 26947dd1d1bSDag-Erling Smørgrav void 27047dd1d1bSDag-Erling Smørgrav servconf_add_hostcert(const char *file, const int line, 27147dd1d1bSDag-Erling Smørgrav ServerOptions *options, const char *path) 27247dd1d1bSDag-Erling Smørgrav { 27347dd1d1bSDag-Erling Smørgrav char *apath = derelativise_path(path); 27447dd1d1bSDag-Erling Smørgrav 27519261079SEd Maste opt_array_append(file, line, "HostCertificate", 27647dd1d1bSDag-Erling Smørgrav &options->host_cert_files, &options->num_host_cert_files, apath); 27747dd1d1bSDag-Erling Smørgrav free(apath); 27847dd1d1bSDag-Erling Smørgrav } 27947dd1d1bSDag-Erling Smørgrav 280511b41d2SMark Murray void 281511b41d2SMark Murray fill_default_server_options(ServerOptions *options) 282511b41d2SMark Murray { 28347dd1d1bSDag-Erling Smørgrav u_int i; 284bc5531deSDag-Erling Smørgrav 285989dd127SDag-Erling Smørgrav /* Portable-specific options */ 286cf2b5f3bSDag-Erling Smørgrav if (options->use_pam == -1) 287f0477b26SDag-Erling Smørgrav options->use_pam = 1; 288989dd127SDag-Erling Smørgrav 289989dd127SDag-Erling Smørgrav /* Standard Options */ 290ca3176e7SBrian Feldman if (options->num_host_key_files == 0) { 291ca3176e7SBrian Feldman /* fill default hostkeys for protocols */ 29247dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 29319261079SEd Maste _PATH_HOST_RSA_KEY_FILE, 0); 2944a421b63SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC 29547dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 29619261079SEd Maste _PATH_HOST_ECDSA_KEY_FILE, 0); 2974a421b63SDag-Erling Smørgrav #endif 29847dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 29919261079SEd Maste _PATH_HOST_ED25519_KEY_FILE, 0); 30047dd1d1bSDag-Erling Smørgrav #ifdef WITH_XMSS 30147dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 30219261079SEd Maste _PATH_HOST_XMSS_KEY_FILE, 0); 30347dd1d1bSDag-Erling Smørgrav #endif /* WITH_XMSS */ 304af12a3e7SDag-Erling Smørgrav } 305144a80bdSDag-Erling Smørgrav if (options->num_host_key_files == 0) 306144a80bdSDag-Erling Smørgrav fatal("No host key files found"); 307b15c8340SDag-Erling Smørgrav /* No certificates by default */ 308511b41d2SMark Murray if (options->num_ports == 0) 309511b41d2SMark Murray options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 310557f75e5SDag-Erling Smørgrav if (options->address_family == -1) 311557f75e5SDag-Erling Smørgrav options->address_family = AF_UNSPEC; 312511b41d2SMark Murray if (options->listen_addrs == NULL) 31347dd1d1bSDag-Erling Smørgrav add_listen_addr(options, NULL, NULL, 0); 314e8aafc91SKris Kennaway if (options->pid_file == NULL) 315bc5531deSDag-Erling Smørgrav options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); 31619261079SEd Maste if (options->moduli_file == NULL) 31719261079SEd Maste options->moduli_file = xstrdup(_PATH_DH_MODULI); 318511b41d2SMark Murray if (options->login_grace_time == -1) 319975616f0SDag-Erling Smørgrav options->login_grace_time = 120; 320ca3176e7SBrian Feldman if (options->permit_root_login == PERMIT_NOT_SET) 321975616f0SDag-Erling Smørgrav options->permit_root_login = PERMIT_NO; 322511b41d2SMark Murray if (options->ignore_rhosts == -1) 323fe5fd017SMark Murray options->ignore_rhosts = 1; 324511b41d2SMark Murray if (options->ignore_user_known_hosts == -1) 325511b41d2SMark Murray options->ignore_user_known_hosts = 0; 326511b41d2SMark Murray if (options->print_motd == -1) 327511b41d2SMark Murray options->print_motd = 1; 328ca3176e7SBrian Feldman if (options->print_lastlog == -1) 329ca3176e7SBrian Feldman options->print_lastlog = 1; 330511b41d2SMark Murray if (options->x11_forwarding == -1) 331975616f0SDag-Erling Smørgrav options->x11_forwarding = 1; 332511b41d2SMark Murray if (options->x11_display_offset == -1) 333fe5fd017SMark Murray options->x11_display_offset = 10; 334af12a3e7SDag-Erling Smørgrav if (options->x11_use_localhost == -1) 335af12a3e7SDag-Erling Smørgrav options->x11_use_localhost = 1; 336c2d3a559SKris Kennaway if (options->xauth_location == NULL) 337bc5531deSDag-Erling Smørgrav options->xauth_location = xstrdup(_PATH_XAUTH); 338f7167e0eSDag-Erling Smørgrav if (options->permit_tty == -1) 339f7167e0eSDag-Erling Smørgrav options->permit_tty = 1; 340a0ee8cc6SDag-Erling Smørgrav if (options->permit_user_rc == -1) 341a0ee8cc6SDag-Erling Smørgrav options->permit_user_rc = 1; 342511b41d2SMark Murray if (options->strict_modes == -1) 343511b41d2SMark Murray options->strict_modes = 1; 3441ec0d754SDag-Erling Smørgrav if (options->tcp_keep_alive == -1) 3451ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = 1; 346af12a3e7SDag-Erling Smørgrav if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 347511b41d2SMark Murray options->log_facility = SYSLOG_FACILITY_AUTH; 348af12a3e7SDag-Erling Smørgrav if (options->log_level == SYSLOG_LEVEL_NOT_SET) 349511b41d2SMark Murray options->log_level = SYSLOG_LEVEL_INFO; 350ca3176e7SBrian Feldman if (options->hostbased_authentication == -1) 351ca3176e7SBrian Feldman options->hostbased_authentication = 0; 352ca3176e7SBrian Feldman if (options->hostbased_uses_name_from_packet_only == -1) 353ca3176e7SBrian Feldman options->hostbased_uses_name_from_packet_only = 0; 354ca3176e7SBrian Feldman if (options->pubkey_authentication == -1) 355ca3176e7SBrian Feldman options->pubkey_authentication = 1; 35619261079SEd Maste if (options->pubkey_auth_options == -1) 35719261079SEd Maste options->pubkey_auth_options = 0; 358989dd127SDag-Erling Smørgrav if (options->kerberos_authentication == -1) 359cf2b5f3bSDag-Erling Smørgrav options->kerberos_authentication = 0; 360af12a3e7SDag-Erling Smørgrav if (options->kerberos_or_local_passwd == -1) 361af12a3e7SDag-Erling Smørgrav options->kerberos_or_local_passwd = 1; 362af12a3e7SDag-Erling Smørgrav if (options->kerberos_ticket_cleanup == -1) 363af12a3e7SDag-Erling Smørgrav options->kerberos_ticket_cleanup = 1; 3641ec0d754SDag-Erling Smørgrav if (options->kerberos_get_afs_token == -1) 3651ec0d754SDag-Erling Smørgrav options->kerberos_get_afs_token = 0; 366cf2b5f3bSDag-Erling Smørgrav if (options->gss_authentication == -1) 367cf2b5f3bSDag-Erling Smørgrav options->gss_authentication = 0; 368cf2b5f3bSDag-Erling Smørgrav if (options->gss_cleanup_creds == -1) 369cf2b5f3bSDag-Erling Smørgrav options->gss_cleanup_creds = 1; 370557f75e5SDag-Erling Smørgrav if (options->gss_strict_acceptor == -1) 371d93a896eSDag-Erling Smørgrav options->gss_strict_acceptor = 1; 372511b41d2SMark Murray if (options->password_authentication == -1) 373b909c84bSDag-Erling Smørgrav options->password_authentication = 0; 37409958426SBrian Feldman if (options->kbd_interactive_authentication == -1) 37519261079SEd Maste options->kbd_interactive_authentication = 1; 376511b41d2SMark Murray if (options->permit_empty_passwd == -1) 377fe5fd017SMark Murray options->permit_empty_passwd = 0; 378190cef3dSDag-Erling Smørgrav if (options->permit_user_env == -1) { 379f388f5efSDag-Erling Smørgrav options->permit_user_env = 0; 38019261079SEd Maste options->permit_user_env_allowlist = NULL; 381190cef3dSDag-Erling Smørgrav } 38280628bacSDag-Erling Smørgrav if (options->compression == -1) 38319261079SEd Maste #ifdef WITH_ZLIB 384d4ecd108SDag-Erling Smørgrav options->compression = COMP_DELAYED; 38519261079SEd Maste #else 38619261079SEd Maste options->compression = COMP_NONE; 38719261079SEd Maste #endif 38819261079SEd Maste 389e4a9863fSDag-Erling Smørgrav if (options->rekey_limit == -1) 390e4a9863fSDag-Erling Smørgrav options->rekey_limit = 0; 391e4a9863fSDag-Erling Smørgrav if (options->rekey_interval == -1) 392e4a9863fSDag-Erling Smørgrav options->rekey_interval = 0; 39309958426SBrian Feldman if (options->allow_tcp_forwarding == -1) 3946888a9beSDag-Erling Smørgrav options->allow_tcp_forwarding = FORWARD_ALLOW; 395a0ee8cc6SDag-Erling Smørgrav if (options->allow_streamlocal_forwarding == -1) 396a0ee8cc6SDag-Erling Smørgrav options->allow_streamlocal_forwarding = FORWARD_ALLOW; 397d4af9e69SDag-Erling Smørgrav if (options->allow_agent_forwarding == -1) 398d4af9e69SDag-Erling Smørgrav options->allow_agent_forwarding = 1; 399a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.gateway_ports == -1) 400a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.gateway_ports = 0; 401c2d3a559SKris Kennaway if (options->max_startups == -1) 4026888a9beSDag-Erling Smørgrav options->max_startups = 100; 403c2d3a559SKris Kennaway if (options->max_startups_rate == -1) 4046888a9beSDag-Erling Smørgrav options->max_startups_rate = 30; /* 30% */ 405c2d3a559SKris Kennaway if (options->max_startups_begin == -1) 4066888a9beSDag-Erling Smørgrav options->max_startups_begin = 10; 40719261079SEd Maste if (options->per_source_max_startups == -1) 40819261079SEd Maste options->per_source_max_startups = INT_MAX; 40919261079SEd Maste if (options->per_source_masklen_ipv4 == -1) 41019261079SEd Maste options->per_source_masklen_ipv4 = 32; 41119261079SEd Maste if (options->per_source_masklen_ipv6 == -1) 41219261079SEd Maste options->per_source_masklen_ipv6 = 128; 41321e764dfSDag-Erling Smørgrav if (options->max_authtries == -1) 41421e764dfSDag-Erling Smørgrav options->max_authtries = DEFAULT_AUTH_FAIL_MAX; 415d4af9e69SDag-Erling Smørgrav if (options->max_sessions == -1) 416d4af9e69SDag-Erling Smørgrav options->max_sessions = DEFAULT_SESSIONS_MAX; 417cf2b5f3bSDag-Erling Smørgrav if (options->use_dns == -1) 418c4cd1fa4SDag-Erling Smørgrav options->use_dns = 1; 419ca3176e7SBrian Feldman if (options->client_alive_interval == -1) 420ca3176e7SBrian Feldman options->client_alive_interval = 0; 421ca3176e7SBrian Feldman if (options->client_alive_count_max == -1) 422ca3176e7SBrian Feldman options->client_alive_count_max = 3; 423e146993eSDag-Erling Smørgrav if (options->num_authkeys_files == 0) { 42419261079SEd Maste opt_array_append(defaultkey, 0, "AuthorizedKeysFiles", 42547dd1d1bSDag-Erling Smørgrav &options->authorized_keys_files, 42647dd1d1bSDag-Erling Smørgrav &options->num_authkeys_files, 42747dd1d1bSDag-Erling Smørgrav _PATH_SSH_USER_PERMITTED_KEYS); 42819261079SEd Maste opt_array_append(defaultkey, 0, "AuthorizedKeysFiles", 42947dd1d1bSDag-Erling Smørgrav &options->authorized_keys_files, 43047dd1d1bSDag-Erling Smørgrav &options->num_authkeys_files, 43147dd1d1bSDag-Erling Smørgrav _PATH_SSH_USER_PERMITTED_KEYS2); 432af12a3e7SDag-Erling Smørgrav } 433b74df5b2SDag-Erling Smørgrav if (options->permit_tun == -1) 434b74df5b2SDag-Erling Smørgrav options->permit_tun = SSH_TUNMODE_NO; 4354a421b63SDag-Erling Smørgrav if (options->ip_qos_interactive == -1) 436190cef3dSDag-Erling Smørgrav options->ip_qos_interactive = IPTOS_DSCP_AF21; 4374a421b63SDag-Erling Smørgrav if (options->ip_qos_bulk == -1) 438190cef3dSDag-Erling Smørgrav options->ip_qos_bulk = IPTOS_DSCP_CS1; 439462c32cbSDag-Erling Smørgrav if (options->version_addendum == NULL) 440462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 441a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 442a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = 0177; 443a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.streamlocal_bind_unlink == -1) 444a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_unlink = 0; 445bc5531deSDag-Erling Smørgrav if (options->fingerprint_hash == -1) 446bc5531deSDag-Erling Smørgrav options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 447ca86bcf2SDag-Erling Smørgrav if (options->disable_forwarding == -1) 448ca86bcf2SDag-Erling Smørgrav options->disable_forwarding = 0; 4494f52dfbbSDag-Erling Smørgrav if (options->expose_userauth_info == -1) 4504f52dfbbSDag-Erling Smørgrav options->expose_userauth_info = 0; 45119261079SEd Maste if (options->sk_provider == NULL) 45219261079SEd Maste options->sk_provider = xstrdup("internal"); 453b2af61ecSKurt Lidl if (options->use_blacklist == -1) 454b2af61ecSKurt Lidl options->use_blacklist = 0; 455eccfee6eSDag-Erling Smørgrav 456acc1a9efSDag-Erling Smørgrav assemble_algorithms(options); 457eccfee6eSDag-Erling Smørgrav 458acc1a9efSDag-Erling Smørgrav /* Turn privilege separation and sandboxing on by default */ 459462c32cbSDag-Erling Smørgrav if (use_privsep == -1) 4602b1970f3SDag-Erling Smørgrav use_privsep = PRIVSEP_ON; 461462c32cbSDag-Erling Smørgrav 462bc5531deSDag-Erling Smørgrav #define CLEAR_ON_NONE(v) \ 463bc5531deSDag-Erling Smørgrav do { \ 464bc5531deSDag-Erling Smørgrav if (option_clear_or_none(v)) { \ 465bc5531deSDag-Erling Smørgrav free(v); \ 466bc5531deSDag-Erling Smørgrav v = NULL; \ 467bc5531deSDag-Erling Smørgrav } \ 468bc5531deSDag-Erling Smørgrav } while(0) 469bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->pid_file); 470bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->xauth_location); 471bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->banner); 472bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->trusted_user_ca_keys); 473bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->revoked_keys_file); 47419261079SEd Maste CLEAR_ON_NONE(options->sk_provider); 475557f75e5SDag-Erling Smørgrav CLEAR_ON_NONE(options->authorized_principals_file); 476acc1a9efSDag-Erling Smørgrav CLEAR_ON_NONE(options->adm_forced_command); 477acc1a9efSDag-Erling Smørgrav CLEAR_ON_NONE(options->chroot_directory); 47847dd1d1bSDag-Erling Smørgrav CLEAR_ON_NONE(options->routing_domain); 47919261079SEd Maste CLEAR_ON_NONE(options->host_key_agent); 480bc5531deSDag-Erling Smørgrav for (i = 0; i < options->num_host_key_files; i++) 481bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->host_key_files[i]); 482bc5531deSDag-Erling Smørgrav for (i = 0; i < options->num_host_cert_files; i++) 483bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->host_cert_files[i]); 484bc5531deSDag-Erling Smørgrav #undef CLEAR_ON_NONE 485bc5531deSDag-Erling Smørgrav 486076ad2f8SDag-Erling Smørgrav /* Similar handling for AuthenticationMethods=any */ 487076ad2f8SDag-Erling Smørgrav if (options->num_auth_methods == 1 && 488076ad2f8SDag-Erling Smørgrav strcmp(options->auth_methods[0], "any") == 0) { 489076ad2f8SDag-Erling Smørgrav free(options->auth_methods[0]); 490076ad2f8SDag-Erling Smørgrav options->auth_methods[0] = NULL; 491076ad2f8SDag-Erling Smørgrav options->num_auth_methods = 0; 492076ad2f8SDag-Erling Smørgrav } 493511b41d2SMark Murray } 494511b41d2SMark Murray 495511b41d2SMark Murray /* Keyword tokens. */ 496511b41d2SMark Murray typedef enum { 497511b41d2SMark Murray sBadOption, /* == unknown option */ 498989dd127SDag-Erling Smørgrav /* Portable-specific options */ 499cf2b5f3bSDag-Erling Smørgrav sUsePAM, 500989dd127SDag-Erling Smørgrav /* Standard Options */ 501ca86bcf2SDag-Erling Smørgrav sPort, sHostKeyFile, sLoginGraceTime, 50219261079SEd Maste sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, 503af12a3e7SDag-Erling Smørgrav sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 504e9e8876aSEd Maste sKerberosGetAFSToken, sPasswordAuthentication, 505e9e8876aSEd Maste sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, 506ca3176e7SBrian Feldman sPrintMotd, sPrintLastLog, sIgnoreRhosts, 507af12a3e7SDag-Erling Smørgrav sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 508f7167e0eSDag-Erling Smørgrav sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, 509ca86bcf2SDag-Erling Smørgrav sPermitUserEnvironment, sAllowTcpForwarding, sCompression, 510e4a9863fSDag-Erling Smørgrav sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 51119261079SEd Maste sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sModuliFile, 51219261079SEd Maste sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms, 513bc5531deSDag-Erling Smørgrav sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, 514cf2b5f3bSDag-Erling Smørgrav sBanner, sUseDNS, sHostbasedAuthentication, 51519261079SEd Maste sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms, 51619261079SEd Maste sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, 517bc5531deSDag-Erling Smørgrav sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, 518557f75e5SDag-Erling Smørgrav sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 519190cef3dSDag-Erling Smørgrav sAcceptEnv, sSetEnv, sPermitTunnel, 520190cef3dSDag-Erling Smørgrav sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, 521d4af9e69SDag-Erling Smørgrav sUsePrivilegeSeparation, sAllowAgentForwarding, 52219261079SEd Maste sHostCertificate, sInclude, 523e2f6069cSDag-Erling Smørgrav sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 524557f75e5SDag-Erling Smørgrav sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, 5252f513db7SEd Maste sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, 5266888a9beSDag-Erling Smørgrav sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 527a0ee8cc6SDag-Erling Smørgrav sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, 528a0ee8cc6SDag-Erling Smørgrav sStreamLocalBindMask, sStreamLocalBindUnlink, 529ca86bcf2SDag-Erling Smørgrav sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, 53019261079SEd Maste sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, 531b2af61ecSKurt Lidl sUseBlacklist, 532ca86bcf2SDag-Erling Smørgrav sDeprecated, sIgnore, sUnsupported 533511b41d2SMark Murray } ServerOpCodes; 534511b41d2SMark Murray 53519261079SEd Maste #define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */ 536333ee039SDag-Erling Smørgrav #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 537333ee039SDag-Erling Smørgrav #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 53819261079SEd Maste #define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ 53919261079SEd Maste #define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */ 540333ee039SDag-Erling Smørgrav 541511b41d2SMark Murray /* Textual representation of the tokens. */ 542511b41d2SMark Murray static struct { 543511b41d2SMark Murray const char *name; 544511b41d2SMark Murray ServerOpCodes opcode; 545333ee039SDag-Erling Smørgrav u_int flags; 546511b41d2SMark Murray } keywords[] = { 547989dd127SDag-Erling Smørgrav /* Portable-specific options */ 548cf2b5f3bSDag-Erling Smørgrav #ifdef USE_PAM 549333ee039SDag-Erling Smørgrav { "usepam", sUsePAM, SSHCFG_GLOBAL }, 550cf2b5f3bSDag-Erling Smørgrav #else 551333ee039SDag-Erling Smørgrav { "usepam", sUnsupported, SSHCFG_GLOBAL }, 552975616f0SDag-Erling Smørgrav #endif 553333ee039SDag-Erling Smørgrav { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, 554989dd127SDag-Erling Smørgrav /* Standard Options */ 555333ee039SDag-Erling Smørgrav { "port", sPort, SSHCFG_GLOBAL }, 556333ee039SDag-Erling Smørgrav { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 557333ee039SDag-Erling Smørgrav { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 558e4a9863fSDag-Erling Smørgrav { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, 559333ee039SDag-Erling Smørgrav { "pidfile", sPidFile, SSHCFG_GLOBAL }, 56019261079SEd Maste { "modulifile", sModuliFile, SSHCFG_GLOBAL }, 561ca86bcf2SDag-Erling Smørgrav { "serverkeybits", sDeprecated, SSHCFG_GLOBAL }, 562333ee039SDag-Erling Smørgrav { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 563ca86bcf2SDag-Erling Smørgrav { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL }, 564d4af9e69SDag-Erling Smørgrav { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, 565333ee039SDag-Erling Smørgrav { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 5664f52dfbbSDag-Erling Smørgrav { "loglevel", sLogLevel, SSHCFG_ALL }, 56719261079SEd Maste { "logverbose", sLogVerbose, SSHCFG_ALL }, 568333ee039SDag-Erling Smørgrav { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, 569ca86bcf2SDag-Erling Smørgrav { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL }, 570d4af9e69SDag-Erling Smørgrav { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, 571e2f6069cSDag-Erling Smørgrav { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, 57219261079SEd Maste { "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, 57319261079SEd Maste { "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ 574eccfee6eSDag-Erling Smørgrav { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, 575ca86bcf2SDag-Erling Smørgrav { "rsaauthentication", sDeprecated, SSHCFG_ALL }, 576d4af9e69SDag-Erling Smørgrav { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 57719261079SEd Maste { "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, 57819261079SEd Maste { "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ 57919261079SEd Maste { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL }, 580333ee039SDag-Erling Smørgrav { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 581cf2b5f3bSDag-Erling Smørgrav #ifdef KRB5 582d4af9e69SDag-Erling Smørgrav { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 583333ee039SDag-Erling Smørgrav { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 584333ee039SDag-Erling Smørgrav { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 5851ec0d754SDag-Erling Smørgrav #ifdef USE_AFS 586333ee039SDag-Erling Smørgrav { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, 5871ec0d754SDag-Erling Smørgrav #else 588333ee039SDag-Erling Smørgrav { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 5891ec0d754SDag-Erling Smørgrav #endif 590cf2b5f3bSDag-Erling Smørgrav #else 591d4af9e69SDag-Erling Smørgrav { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, 592333ee039SDag-Erling Smørgrav { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, 593333ee039SDag-Erling Smørgrav { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, 594333ee039SDag-Erling Smørgrav { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 595cb96ab36SAssar Westerlund #endif 596333ee039SDag-Erling Smørgrav { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, 597333ee039SDag-Erling Smørgrav { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, 598cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 599d4af9e69SDag-Erling Smørgrav { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 600333ee039SDag-Erling Smørgrav { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 601557f75e5SDag-Erling Smørgrav { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, 602cf2b5f3bSDag-Erling Smørgrav #else 603d4af9e69SDag-Erling Smørgrav { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, 604333ee039SDag-Erling Smørgrav { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 605557f75e5SDag-Erling Smørgrav { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, 606511b41d2SMark Murray #endif 607d4af9e69SDag-Erling Smørgrav { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 608d4af9e69SDag-Erling Smørgrav { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 60919261079SEd Maste { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ 61019261079SEd Maste { "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ 611333ee039SDag-Erling Smørgrav { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 612333ee039SDag-Erling Smørgrav { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 613333ee039SDag-Erling Smørgrav { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, 614333ee039SDag-Erling Smørgrav { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 615acc1a9efSDag-Erling Smørgrav #ifdef DISABLE_LASTLOG 616acc1a9efSDag-Erling Smørgrav { "printlastlog", sUnsupported, SSHCFG_GLOBAL }, 617acc1a9efSDag-Erling Smørgrav #else 618333ee039SDag-Erling Smørgrav { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 619acc1a9efSDag-Erling Smørgrav #endif 62019261079SEd Maste { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL }, 621333ee039SDag-Erling Smørgrav { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 622333ee039SDag-Erling Smørgrav { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 623333ee039SDag-Erling Smørgrav { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 624333ee039SDag-Erling Smørgrav { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 625333ee039SDag-Erling Smørgrav { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 626333ee039SDag-Erling Smørgrav { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 627cce7d346SDag-Erling Smørgrav { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, 628333ee039SDag-Erling Smørgrav { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 629ca86bcf2SDag-Erling Smørgrav { "uselogin", sDeprecated, SSHCFG_GLOBAL }, 630333ee039SDag-Erling Smørgrav { "compression", sCompression, SSHCFG_GLOBAL }, 631e4a9863fSDag-Erling Smørgrav { "rekeylimit", sRekeyLimit, SSHCFG_ALL }, 632333ee039SDag-Erling Smørgrav { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, 633333ee039SDag-Erling Smørgrav { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ 634333ee039SDag-Erling Smørgrav { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 635d4af9e69SDag-Erling Smørgrav { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, 636462c32cbSDag-Erling Smørgrav { "allowusers", sAllowUsers, SSHCFG_ALL }, 637462c32cbSDag-Erling Smørgrav { "denyusers", sDenyUsers, SSHCFG_ALL }, 638462c32cbSDag-Erling Smørgrav { "allowgroups", sAllowGroups, SSHCFG_ALL }, 639462c32cbSDag-Erling Smørgrav { "denygroups", sDenyGroups, SSHCFG_ALL }, 640333ee039SDag-Erling Smørgrav { "ciphers", sCiphers, SSHCFG_GLOBAL }, 641333ee039SDag-Erling Smørgrav { "macs", sMacs, SSHCFG_GLOBAL }, 642ca86bcf2SDag-Erling Smørgrav { "protocol", sIgnore, SSHCFG_GLOBAL }, 643333ee039SDag-Erling Smørgrav { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 644333ee039SDag-Erling Smørgrav { "subsystem", sSubsystem, SSHCFG_GLOBAL }, 645333ee039SDag-Erling Smørgrav { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 64619261079SEd Maste { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL }, 64719261079SEd Maste { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL }, 648d4af9e69SDag-Erling Smørgrav { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, 649d4af9e69SDag-Erling Smørgrav { "maxsessions", sMaxSessions, SSHCFG_ALL }, 650d4af9e69SDag-Erling Smørgrav { "banner", sBanner, SSHCFG_ALL }, 651333ee039SDag-Erling Smørgrav { "usedns", sUseDNS, SSHCFG_GLOBAL }, 652333ee039SDag-Erling Smørgrav { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, 653333ee039SDag-Erling Smørgrav { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, 654ca86bcf2SDag-Erling Smørgrav { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL }, 655ca86bcf2SDag-Erling Smørgrav { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL }, 656e2f6069cSDag-Erling Smørgrav { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, 657e146993eSDag-Erling Smørgrav { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, 658d93a896eSDag-Erling Smørgrav { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL}, 659462c32cbSDag-Erling Smørgrav { "acceptenv", sAcceptEnv, SSHCFG_ALL }, 660190cef3dSDag-Erling Smørgrav { "setenv", sSetEnv, SSHCFG_ALL }, 661e2f6069cSDag-Erling Smørgrav { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 662f7167e0eSDag-Erling Smørgrav { "permittty", sPermitTTY, SSHCFG_ALL }, 663a0ee8cc6SDag-Erling Smørgrav { "permituserrc", sPermitUserRC, SSHCFG_ALL }, 664333ee039SDag-Erling Smørgrav { "match", sMatch, SSHCFG_ALL }, 665333ee039SDag-Erling Smørgrav { "permitopen", sPermitOpen, SSHCFG_ALL }, 666190cef3dSDag-Erling Smørgrav { "permitlisten", sPermitListen, SSHCFG_ALL }, 667333ee039SDag-Erling Smørgrav { "forcecommand", sForceCommand, SSHCFG_ALL }, 668d4af9e69SDag-Erling Smørgrav { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 669b15c8340SDag-Erling Smørgrav { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, 670b15c8340SDag-Erling Smørgrav { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, 671b15c8340SDag-Erling Smørgrav { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, 672e2f6069cSDag-Erling Smørgrav { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, 6734a421b63SDag-Erling Smørgrav { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, 67419261079SEd Maste { "include", sInclude, SSHCFG_ALL }, 6754a421b63SDag-Erling Smørgrav { "ipqos", sIPQoS, SSHCFG_ALL }, 6766888a9beSDag-Erling Smørgrav { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, 6776888a9beSDag-Erling Smørgrav { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 678557f75e5SDag-Erling Smørgrav { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL }, 679557f75e5SDag-Erling Smørgrav { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL }, 680462c32cbSDag-Erling Smørgrav { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 6816888a9beSDag-Erling Smørgrav { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 682a0ee8cc6SDag-Erling Smørgrav { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, 683a0ee8cc6SDag-Erling Smørgrav { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, 684a0ee8cc6SDag-Erling Smørgrav { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, 685bc5531deSDag-Erling Smørgrav { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, 686ca86bcf2SDag-Erling Smørgrav { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, 6874f52dfbbSDag-Erling Smørgrav { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, 68847dd1d1bSDag-Erling Smørgrav { "rdomain", sRDomain, SSHCFG_ALL }, 6892f513db7SEd Maste { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, 69019261079SEd Maste { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, 691b2af61ecSKurt Lidl { "useblacklist", sUseBlacklist, SSHCFG_GLOBAL }, 692e426c743SEd Maste { "useblocklist", sUseBlacklist, SSHCFG_GLOBAL }, /* alias */ 6936f351346SDag-Erling Smørgrav { "noneenabled", sUnsupported, SSHCFG_ALL }, 6949860d96eSDag-Erling Smørgrav { "hpndisabled", sDeprecated, SSHCFG_ALL }, 6959860d96eSDag-Erling Smørgrav { "hpnbuffersize", sDeprecated, SSHCFG_ALL }, 6969860d96eSDag-Erling Smørgrav { "tcprcvbufpoll", sDeprecated, SSHCFG_ALL }, 697333ee039SDag-Erling Smørgrav { NULL, sBadOption, 0 } 698511b41d2SMark Murray }; 699511b41d2SMark Murray 700d4af9e69SDag-Erling Smørgrav static struct { 701d4af9e69SDag-Erling Smørgrav int val; 702d4af9e69SDag-Erling Smørgrav char *text; 703d4af9e69SDag-Erling Smørgrav } tunmode_desc[] = { 704d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_NO, "no" }, 705d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_POINTOPOINT, "point-to-point" }, 706d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_ETHERNET, "ethernet" }, 707d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_YES, "yes" }, 708d4af9e69SDag-Erling Smørgrav { -1, NULL } 709d4af9e69SDag-Erling Smørgrav }; 710d4af9e69SDag-Erling Smørgrav 711190cef3dSDag-Erling Smørgrav /* Returns an opcode name from its number */ 712190cef3dSDag-Erling Smørgrav 713190cef3dSDag-Erling Smørgrav static const char * 714190cef3dSDag-Erling Smørgrav lookup_opcode_name(ServerOpCodes code) 715190cef3dSDag-Erling Smørgrav { 716190cef3dSDag-Erling Smørgrav u_int i; 717190cef3dSDag-Erling Smørgrav 718190cef3dSDag-Erling Smørgrav for (i = 0; keywords[i].name != NULL; i++) 719190cef3dSDag-Erling Smørgrav if (keywords[i].opcode == code) 720190cef3dSDag-Erling Smørgrav return(keywords[i].name); 721190cef3dSDag-Erling Smørgrav return "UNKNOWN"; 722190cef3dSDag-Erling Smørgrav } 723190cef3dSDag-Erling Smørgrav 724190cef3dSDag-Erling Smørgrav 725511b41d2SMark Murray /* 726ca3176e7SBrian Feldman * Returns the number of the token pointed to by cp or sBadOption. 727511b41d2SMark Murray */ 728511b41d2SMark Murray 729511b41d2SMark Murray static ServerOpCodes 730511b41d2SMark Murray parse_token(const char *cp, const char *filename, 731333ee039SDag-Erling Smørgrav int linenum, u_int *flags) 732511b41d2SMark Murray { 733ca3176e7SBrian Feldman u_int i; 734511b41d2SMark Murray 735511b41d2SMark Murray for (i = 0; keywords[i].name; i++) 736333ee039SDag-Erling Smørgrav if (strcasecmp(cp, keywords[i].name) == 0) { 737333ee039SDag-Erling Smørgrav *flags = keywords[i].flags; 738511b41d2SMark Murray return keywords[i].opcode; 739333ee039SDag-Erling Smørgrav } 740511b41d2SMark Murray 741ca3176e7SBrian Feldman error("%s: line %d: Bad configuration option: %s", 742511b41d2SMark Murray filename, linenum, cp); 743511b41d2SMark Murray return sBadOption; 744511b41d2SMark Murray } 745511b41d2SMark Murray 746b15c8340SDag-Erling Smørgrav char * 747b15c8340SDag-Erling Smørgrav derelativise_path(const char *path) 748b15c8340SDag-Erling Smørgrav { 749bc5531deSDag-Erling Smørgrav char *expanded, *ret, cwd[PATH_MAX]; 750b15c8340SDag-Erling Smørgrav 751bc5531deSDag-Erling Smørgrav if (strcasecmp(path, "none") == 0) 752bc5531deSDag-Erling Smørgrav return xstrdup("none"); 753b15c8340SDag-Erling Smørgrav expanded = tilde_expand_filename(path, getuid()); 75419261079SEd Maste if (path_absolute(expanded)) 755b15c8340SDag-Erling Smørgrav return expanded; 7568ad9b54aSDag-Erling Smørgrav if (getcwd(cwd, sizeof(cwd)) == NULL) 75719261079SEd Maste fatal_f("getcwd: %s", strerror(errno)); 758b15c8340SDag-Erling Smørgrav xasprintf(&ret, "%s/%s", cwd, expanded); 759e4a9863fSDag-Erling Smørgrav free(expanded); 760b15c8340SDag-Erling Smørgrav return ret; 761b15c8340SDag-Erling Smørgrav } 762b15c8340SDag-Erling Smørgrav 763af12a3e7SDag-Erling Smørgrav static void 76447dd1d1bSDag-Erling Smørgrav add_listen_addr(ServerOptions *options, const char *addr, 76547dd1d1bSDag-Erling Smørgrav const char *rdomain, int port) 766511b41d2SMark Murray { 767d4ecd108SDag-Erling Smørgrav u_int i; 768511b41d2SMark Murray 76947dd1d1bSDag-Erling Smørgrav if (port > 0) 77047dd1d1bSDag-Erling Smørgrav add_one_listen_addr(options, addr, rdomain, port); 77147dd1d1bSDag-Erling Smørgrav else { 77247dd1d1bSDag-Erling Smørgrav for (i = 0; i < options->num_ports; i++) { 77347dd1d1bSDag-Erling Smørgrav add_one_listen_addr(options, addr, rdomain, 77447dd1d1bSDag-Erling Smørgrav options->ports[i]); 77547dd1d1bSDag-Erling Smørgrav } 77647dd1d1bSDag-Erling Smørgrav } 777ca3176e7SBrian Feldman } 778ca3176e7SBrian Feldman 779af12a3e7SDag-Erling Smørgrav static void 78047dd1d1bSDag-Erling Smørgrav add_one_listen_addr(ServerOptions *options, const char *addr, 78147dd1d1bSDag-Erling Smørgrav const char *rdomain, int port) 782ca3176e7SBrian Feldman { 783ca3176e7SBrian Feldman struct addrinfo hints, *ai, *aitop; 784ca3176e7SBrian Feldman char strport[NI_MAXSERV]; 785ca3176e7SBrian Feldman int gaierr; 78647dd1d1bSDag-Erling Smørgrav u_int i; 78747dd1d1bSDag-Erling Smørgrav 78847dd1d1bSDag-Erling Smørgrav /* Find listen_addrs entry for this rdomain */ 78947dd1d1bSDag-Erling Smørgrav for (i = 0; i < options->num_listen_addrs; i++) { 79047dd1d1bSDag-Erling Smørgrav if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL) 79147dd1d1bSDag-Erling Smørgrav break; 79247dd1d1bSDag-Erling Smørgrav if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL) 79347dd1d1bSDag-Erling Smørgrav continue; 79447dd1d1bSDag-Erling Smørgrav if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0) 79547dd1d1bSDag-Erling Smørgrav break; 79647dd1d1bSDag-Erling Smørgrav } 79747dd1d1bSDag-Erling Smørgrav if (i >= options->num_listen_addrs) { 79847dd1d1bSDag-Erling Smørgrav /* No entry for this rdomain; allocate one */ 79947dd1d1bSDag-Erling Smørgrav if (i >= INT_MAX) 80019261079SEd Maste fatal_f("too many listen addresses"); 80147dd1d1bSDag-Erling Smørgrav options->listen_addrs = xrecallocarray(options->listen_addrs, 80247dd1d1bSDag-Erling Smørgrav options->num_listen_addrs, options->num_listen_addrs + 1, 80347dd1d1bSDag-Erling Smørgrav sizeof(*options->listen_addrs)); 80447dd1d1bSDag-Erling Smørgrav i = options->num_listen_addrs++; 80547dd1d1bSDag-Erling Smørgrav if (rdomain != NULL) 80647dd1d1bSDag-Erling Smørgrav options->listen_addrs[i].rdomain = xstrdup(rdomain); 80747dd1d1bSDag-Erling Smørgrav } 80847dd1d1bSDag-Erling Smørgrav /* options->listen_addrs[i] points to the addresses for this rdomain */ 809ca3176e7SBrian Feldman 810511b41d2SMark Murray memset(&hints, 0, sizeof(hints)); 811aa49c926SDag-Erling Smørgrav hints.ai_family = options->address_family; 812511b41d2SMark Murray hints.ai_socktype = SOCK_STREAM; 813511b41d2SMark Murray hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 814cce7d346SDag-Erling Smørgrav snprintf(strport, sizeof strport, "%d", port); 815511b41d2SMark Murray if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 816ca3176e7SBrian Feldman fatal("bad addr or host: %s (%s)", 817511b41d2SMark Murray addr ? addr : "<NULL>", 818d4af9e69SDag-Erling Smørgrav ssh_gai_strerror(gaierr)); 819511b41d2SMark Murray for (ai = aitop; ai->ai_next; ai = ai->ai_next) 820511b41d2SMark Murray ; 82147dd1d1bSDag-Erling Smørgrav ai->ai_next = options->listen_addrs[i].addrs; 82247dd1d1bSDag-Erling Smørgrav options->listen_addrs[i].addrs = aitop; 82347dd1d1bSDag-Erling Smørgrav } 82447dd1d1bSDag-Erling Smørgrav 82547dd1d1bSDag-Erling Smørgrav /* Returns nonzero if the routing domain name is valid */ 82647dd1d1bSDag-Erling Smørgrav static int 82747dd1d1bSDag-Erling Smørgrav valid_rdomain(const char *name) 82847dd1d1bSDag-Erling Smørgrav { 82947dd1d1bSDag-Erling Smørgrav #if defined(HAVE_SYS_VALID_RDOMAIN) 83047dd1d1bSDag-Erling Smørgrav return sys_valid_rdomain(name); 83147dd1d1bSDag-Erling Smørgrav #elif defined(__OpenBSD__) 83247dd1d1bSDag-Erling Smørgrav const char *errstr; 83347dd1d1bSDag-Erling Smørgrav long long num; 83447dd1d1bSDag-Erling Smørgrav struct rt_tableinfo info; 83547dd1d1bSDag-Erling Smørgrav int mib[6]; 83647dd1d1bSDag-Erling Smørgrav size_t miblen = sizeof(mib); 83747dd1d1bSDag-Erling Smørgrav 83847dd1d1bSDag-Erling Smørgrav if (name == NULL) 83947dd1d1bSDag-Erling Smørgrav return 1; 84047dd1d1bSDag-Erling Smørgrav 84147dd1d1bSDag-Erling Smørgrav num = strtonum(name, 0, 255, &errstr); 84247dd1d1bSDag-Erling Smørgrav if (errstr != NULL) 84347dd1d1bSDag-Erling Smørgrav return 0; 84447dd1d1bSDag-Erling Smørgrav 84547dd1d1bSDag-Erling Smørgrav /* Check whether the table actually exists */ 84647dd1d1bSDag-Erling Smørgrav memset(mib, 0, sizeof(mib)); 84747dd1d1bSDag-Erling Smørgrav mib[0] = CTL_NET; 84847dd1d1bSDag-Erling Smørgrav mib[1] = PF_ROUTE; 84947dd1d1bSDag-Erling Smørgrav mib[4] = NET_RT_TABLE; 85047dd1d1bSDag-Erling Smørgrav mib[5] = (int)num; 85147dd1d1bSDag-Erling Smørgrav if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1) 85247dd1d1bSDag-Erling Smørgrav return 0; 85347dd1d1bSDag-Erling Smørgrav 85447dd1d1bSDag-Erling Smørgrav return 1; 85547dd1d1bSDag-Erling Smørgrav #else /* defined(__OpenBSD__) */ 85647dd1d1bSDag-Erling Smørgrav error("Routing domains are not supported on this platform"); 85747dd1d1bSDag-Erling Smørgrav return 0; 85847dd1d1bSDag-Erling Smørgrav #endif 859511b41d2SMark Murray } 860511b41d2SMark Murray 861557f75e5SDag-Erling Smørgrav /* 862557f75e5SDag-Erling Smørgrav * Queue a ListenAddress to be processed once we have all of the Ports 863557f75e5SDag-Erling Smørgrav * and AddressFamily options. 864557f75e5SDag-Erling Smørgrav */ 865557f75e5SDag-Erling Smørgrav static void 86647dd1d1bSDag-Erling Smørgrav queue_listen_addr(ServerOptions *options, const char *addr, 86747dd1d1bSDag-Erling Smørgrav const char *rdomain, int port) 868557f75e5SDag-Erling Smørgrav { 86947dd1d1bSDag-Erling Smørgrav struct queued_listenaddr *qla; 87047dd1d1bSDag-Erling Smørgrav 87147dd1d1bSDag-Erling Smørgrav options->queued_listen_addrs = xrecallocarray( 87247dd1d1bSDag-Erling Smørgrav options->queued_listen_addrs, 87347dd1d1bSDag-Erling Smørgrav options->num_queued_listens, options->num_queued_listens + 1, 87447dd1d1bSDag-Erling Smørgrav sizeof(*options->queued_listen_addrs)); 87547dd1d1bSDag-Erling Smørgrav qla = &options->queued_listen_addrs[options->num_queued_listens++]; 87647dd1d1bSDag-Erling Smørgrav qla->addr = xstrdup(addr); 87747dd1d1bSDag-Erling Smørgrav qla->port = port; 87847dd1d1bSDag-Erling Smørgrav qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain); 879557f75e5SDag-Erling Smørgrav } 880557f75e5SDag-Erling Smørgrav 881557f75e5SDag-Erling Smørgrav /* 882557f75e5SDag-Erling Smørgrav * Process queued (text) ListenAddress entries. 883557f75e5SDag-Erling Smørgrav */ 884557f75e5SDag-Erling Smørgrav static void 885557f75e5SDag-Erling Smørgrav process_queued_listen_addrs(ServerOptions *options) 886557f75e5SDag-Erling Smørgrav { 887557f75e5SDag-Erling Smørgrav u_int i; 88847dd1d1bSDag-Erling Smørgrav struct queued_listenaddr *qla; 889557f75e5SDag-Erling Smørgrav 890557f75e5SDag-Erling Smørgrav if (options->num_ports == 0) 891557f75e5SDag-Erling Smørgrav options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 892557f75e5SDag-Erling Smørgrav if (options->address_family == -1) 893557f75e5SDag-Erling Smørgrav options->address_family = AF_UNSPEC; 894557f75e5SDag-Erling Smørgrav 895557f75e5SDag-Erling Smørgrav for (i = 0; i < options->num_queued_listens; i++) { 89647dd1d1bSDag-Erling Smørgrav qla = &options->queued_listen_addrs[i]; 89747dd1d1bSDag-Erling Smørgrav add_listen_addr(options, qla->addr, qla->rdomain, qla->port); 89847dd1d1bSDag-Erling Smørgrav free(qla->addr); 89947dd1d1bSDag-Erling Smørgrav free(qla->rdomain); 900557f75e5SDag-Erling Smørgrav } 901557f75e5SDag-Erling Smørgrav free(options->queued_listen_addrs); 902557f75e5SDag-Erling Smørgrav options->queued_listen_addrs = NULL; 903557f75e5SDag-Erling Smørgrav options->num_queued_listens = 0; 904557f75e5SDag-Erling Smørgrav } 905557f75e5SDag-Erling Smørgrav 9064f52dfbbSDag-Erling Smørgrav /* 907190cef3dSDag-Erling Smørgrav * Inform channels layer of permitopen options for a single forwarding 908190cef3dSDag-Erling Smørgrav * direction (local/remote). 909190cef3dSDag-Erling Smørgrav */ 910190cef3dSDag-Erling Smørgrav static void 911190cef3dSDag-Erling Smørgrav process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode, 912190cef3dSDag-Erling Smørgrav char **opens, u_int num_opens) 913190cef3dSDag-Erling Smørgrav { 914190cef3dSDag-Erling Smørgrav u_int i; 915190cef3dSDag-Erling Smørgrav int port; 916*1323ec57SEd Maste char *host, *arg, *oarg; 917190cef3dSDag-Erling Smørgrav int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE; 918190cef3dSDag-Erling Smørgrav const char *what = lookup_opcode_name(opcode); 919190cef3dSDag-Erling Smørgrav 920190cef3dSDag-Erling Smørgrav channel_clear_permission(ssh, FORWARD_ADM, where); 921190cef3dSDag-Erling Smørgrav if (num_opens == 0) 922190cef3dSDag-Erling Smørgrav return; /* permit any */ 923190cef3dSDag-Erling Smørgrav 924190cef3dSDag-Erling Smørgrav /* handle keywords: "any" / "none" */ 925190cef3dSDag-Erling Smørgrav if (num_opens == 1 && strcmp(opens[0], "any") == 0) 926190cef3dSDag-Erling Smørgrav return; 927190cef3dSDag-Erling Smørgrav if (num_opens == 1 && strcmp(opens[0], "none") == 0) { 928190cef3dSDag-Erling Smørgrav channel_disable_admin(ssh, where); 929190cef3dSDag-Erling Smørgrav return; 930190cef3dSDag-Erling Smørgrav } 931190cef3dSDag-Erling Smørgrav /* Otherwise treat it as a list of permitted host:port */ 932190cef3dSDag-Erling Smørgrav for (i = 0; i < num_opens; i++) { 933190cef3dSDag-Erling Smørgrav oarg = arg = xstrdup(opens[i]); 934*1323ec57SEd Maste host = hpdelim(&arg); 935*1323ec57SEd Maste if (host == NULL) 93619261079SEd Maste fatal_f("missing host in %s", what); 937190cef3dSDag-Erling Smørgrav host = cleanhostname(host); 938190cef3dSDag-Erling Smørgrav if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 93919261079SEd Maste fatal_f("bad port number in %s", what); 940190cef3dSDag-Erling Smørgrav /* Send it to channels layer */ 941190cef3dSDag-Erling Smørgrav channel_add_permission(ssh, FORWARD_ADM, 942190cef3dSDag-Erling Smørgrav where, host, port); 943190cef3dSDag-Erling Smørgrav free(oarg); 944190cef3dSDag-Erling Smørgrav } 945190cef3dSDag-Erling Smørgrav } 946190cef3dSDag-Erling Smørgrav 947190cef3dSDag-Erling Smørgrav /* 9484f52dfbbSDag-Erling Smørgrav * Inform channels layer of permitopen options from configuration. 9494f52dfbbSDag-Erling Smørgrav */ 9504f52dfbbSDag-Erling Smørgrav void 9514f52dfbbSDag-Erling Smørgrav process_permitopen(struct ssh *ssh, ServerOptions *options) 9524f52dfbbSDag-Erling Smørgrav { 953190cef3dSDag-Erling Smørgrav process_permitopen_list(ssh, sPermitOpen, 954190cef3dSDag-Erling Smørgrav options->permitted_opens, options->num_permitted_opens); 955190cef3dSDag-Erling Smørgrav process_permitopen_list(ssh, sPermitListen, 956190cef3dSDag-Erling Smørgrav options->permitted_listens, 957190cef3dSDag-Erling Smørgrav options->num_permitted_listens); 9584f52dfbbSDag-Erling Smørgrav } 9594f52dfbbSDag-Erling Smørgrav 960462c32cbSDag-Erling Smørgrav struct connection_info * 96119261079SEd Maste get_connection_info(struct ssh *ssh, int populate, int use_dns) 962462c32cbSDag-Erling Smørgrav { 963462c32cbSDag-Erling Smørgrav static struct connection_info ci; 964462c32cbSDag-Erling Smørgrav 96519261079SEd Maste if (ssh == NULL || !populate) 966462c32cbSDag-Erling Smørgrav return &ci; 967076ad2f8SDag-Erling Smørgrav ci.host = auth_get_canonical_hostname(ssh, use_dns); 968076ad2f8SDag-Erling Smørgrav ci.address = ssh_remote_ipaddr(ssh); 969076ad2f8SDag-Erling Smørgrav ci.laddress = ssh_local_ipaddr(ssh); 970076ad2f8SDag-Erling Smørgrav ci.lport = ssh_local_port(ssh); 97147dd1d1bSDag-Erling Smørgrav ci.rdomain = ssh_packet_rdomain_in(ssh); 972462c32cbSDag-Erling Smørgrav return &ci; 973462c32cbSDag-Erling Smørgrav } 974462c32cbSDag-Erling Smørgrav 975333ee039SDag-Erling Smørgrav /* 976333ee039SDag-Erling Smørgrav * The strategy for the Match blocks is that the config file is parsed twice. 977333ee039SDag-Erling Smørgrav * 978333ee039SDag-Erling Smørgrav * The first time is at startup. activep is initialized to 1 and the 979333ee039SDag-Erling Smørgrav * directives in the global context are processed and acted on. Hitting a 980333ee039SDag-Erling Smørgrav * Match directive unsets activep and the directives inside the block are 981333ee039SDag-Erling Smørgrav * checked for syntax only. 982333ee039SDag-Erling Smørgrav * 983333ee039SDag-Erling Smørgrav * The second time is after a connection has been established but before 984333ee039SDag-Erling Smørgrav * authentication. activep is initialized to 2 and global config directives 985333ee039SDag-Erling Smørgrav * are ignored since they have already been processed. If the criteria in a 986333ee039SDag-Erling Smørgrav * Match block is met, activep is set and the subsequent directives 987333ee039SDag-Erling Smørgrav * processed and actioned until EOF or another Match block unsets it. Any 988333ee039SDag-Erling Smørgrav * options set are copied into the main server config. 989333ee039SDag-Erling Smørgrav * 990333ee039SDag-Erling Smørgrav * Potential additions/improvements: 991ca86bcf2SDag-Erling Smørgrav * - Add Match support for pre-kex directives, eg. Ciphers. 992333ee039SDag-Erling Smørgrav * 993333ee039SDag-Erling Smørgrav * - Add a Tag directive (idea from David Leonard) ala pf, eg: 994333ee039SDag-Erling Smørgrav * Match Address 192.168.0.* 995333ee039SDag-Erling Smørgrav * Tag trusted 996333ee039SDag-Erling Smørgrav * Match Group wheel 997333ee039SDag-Erling Smørgrav * Tag trusted 998333ee039SDag-Erling Smørgrav * Match Tag trusted 999333ee039SDag-Erling Smørgrav * AllowTcpForwarding yes 1000333ee039SDag-Erling Smørgrav * GatewayPorts clientspecified 1001333ee039SDag-Erling Smørgrav * [...] 1002333ee039SDag-Erling Smørgrav * 1003333ee039SDag-Erling Smørgrav * - Add a PermittedChannelRequests directive 1004333ee039SDag-Erling Smørgrav * Match Group shell 1005333ee039SDag-Erling Smørgrav * PermittedChannelRequests session,forwarded-tcpip 1006333ee039SDag-Erling Smørgrav */ 1007333ee039SDag-Erling Smørgrav 1008333ee039SDag-Erling Smørgrav static int 1009333ee039SDag-Erling Smørgrav match_cfg_line_group(const char *grps, int line, const char *user) 1010333ee039SDag-Erling Smørgrav { 1011333ee039SDag-Erling Smørgrav int result = 0; 1012333ee039SDag-Erling Smørgrav struct passwd *pw; 1013333ee039SDag-Erling Smørgrav 1014333ee039SDag-Erling Smørgrav if (user == NULL) 1015333ee039SDag-Erling Smørgrav goto out; 1016333ee039SDag-Erling Smørgrav 1017333ee039SDag-Erling Smørgrav if ((pw = getpwnam(user)) == NULL) { 1018333ee039SDag-Erling Smørgrav debug("Can't match group at line %d because user %.100s does " 1019333ee039SDag-Erling Smørgrav "not exist", line, user); 1020333ee039SDag-Erling Smørgrav } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 1021333ee039SDag-Erling Smørgrav debug("Can't Match group because user %.100s not in any group " 1022333ee039SDag-Erling Smørgrav "at line %d", user, line); 1023d4af9e69SDag-Erling Smørgrav } else if (ga_match_pattern_list(grps) != 1) { 1024d4af9e69SDag-Erling Smørgrav debug("user %.100s does not match group list %.100s at line %d", 1025d4af9e69SDag-Erling Smørgrav user, grps, line); 1026333ee039SDag-Erling Smørgrav } else { 1027d4af9e69SDag-Erling Smørgrav debug("user %.100s matched group list %.100s at line %d", user, 1028d4af9e69SDag-Erling Smørgrav grps, line); 1029333ee039SDag-Erling Smørgrav result = 1; 1030333ee039SDag-Erling Smørgrav } 1031333ee039SDag-Erling Smørgrav out: 1032333ee039SDag-Erling Smørgrav ga_free(); 1033333ee039SDag-Erling Smørgrav return result; 1034333ee039SDag-Erling Smørgrav } 1035333ee039SDag-Erling Smørgrav 103647dd1d1bSDag-Erling Smørgrav static void 103747dd1d1bSDag-Erling Smørgrav match_test_missing_fatal(const char *criteria, const char *attrib) 103847dd1d1bSDag-Erling Smørgrav { 103947dd1d1bSDag-Erling Smørgrav fatal("'Match %s' in configuration but '%s' not in connection " 104047dd1d1bSDag-Erling Smørgrav "test specification.", criteria, attrib); 104147dd1d1bSDag-Erling Smørgrav } 104247dd1d1bSDag-Erling Smørgrav 1043462c32cbSDag-Erling Smørgrav /* 10446888a9beSDag-Erling Smørgrav * All of the attributes on a single Match line are ANDed together, so we need 1045f7167e0eSDag-Erling Smørgrav * to check every attribute and set the result to zero if any attribute does 10466888a9beSDag-Erling Smørgrav * not match. 1047462c32cbSDag-Erling Smørgrav */ 1048333ee039SDag-Erling Smørgrav static int 1049462c32cbSDag-Erling Smørgrav match_cfg_line(char **condition, int line, struct connection_info *ci) 1050333ee039SDag-Erling Smørgrav { 1051f7167e0eSDag-Erling Smørgrav int result = 1, attributes = 0, port; 1052333ee039SDag-Erling Smørgrav char *arg, *attrib, *cp = *condition; 1053333ee039SDag-Erling Smørgrav 1054462c32cbSDag-Erling Smørgrav if (ci == NULL) 1055333ee039SDag-Erling Smørgrav debug3("checking syntax for 'Match %s'", cp); 1056333ee039SDag-Erling Smørgrav else 1057462c32cbSDag-Erling Smørgrav debug3("checking match for '%s' user %s host %s addr %s " 1058462c32cbSDag-Erling Smørgrav "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", 1059462c32cbSDag-Erling Smørgrav ci->host ? ci->host : "(null)", 1060462c32cbSDag-Erling Smørgrav ci->address ? ci->address : "(null)", 1061462c32cbSDag-Erling Smørgrav ci->laddress ? ci->laddress : "(null)", ci->lport); 1062333ee039SDag-Erling Smørgrav 1063333ee039SDag-Erling Smørgrav while ((attrib = strdelim(&cp)) && *attrib != '\0') { 106419261079SEd Maste /* Terminate on comment */ 106519261079SEd Maste if (*attrib == '#') { 106619261079SEd Maste cp = NULL; /* mark all arguments consumed */ 106719261079SEd Maste break; 106819261079SEd Maste } 106919261079SEd Maste arg = NULL; 1070f7167e0eSDag-Erling Smørgrav attributes++; 107119261079SEd Maste /* Criterion "all" has no argument and must appear alone */ 1072f7167e0eSDag-Erling Smørgrav if (strcasecmp(attrib, "all") == 0) { 107319261079SEd Maste if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && 107419261079SEd Maste *arg != '\0' && *arg != '#')) { 1075f7167e0eSDag-Erling Smørgrav error("'all' cannot be combined with other " 1076f7167e0eSDag-Erling Smørgrav "Match attributes"); 1077f7167e0eSDag-Erling Smørgrav return -1; 1078f7167e0eSDag-Erling Smørgrav } 107919261079SEd Maste if (arg != NULL && *arg == '#') 108019261079SEd Maste cp = NULL; /* mark all arguments consumed */ 1081f7167e0eSDag-Erling Smørgrav *condition = cp; 1082f7167e0eSDag-Erling Smørgrav return 1; 1083f7167e0eSDag-Erling Smørgrav } 108419261079SEd Maste /* All other criteria require an argument */ 108519261079SEd Maste if ((arg = strdelim(&cp)) == NULL || 108619261079SEd Maste *arg == '\0' || *arg == '#') { 1087333ee039SDag-Erling Smørgrav error("Missing Match criteria for %s", attrib); 1088333ee039SDag-Erling Smørgrav return -1; 1089333ee039SDag-Erling Smørgrav } 1090333ee039SDag-Erling Smørgrav if (strcasecmp(attrib, "user") == 0) { 109119261079SEd Maste if (ci == NULL || (ci->test && ci->user == NULL)) { 1092333ee039SDag-Erling Smørgrav result = 0; 1093333ee039SDag-Erling Smørgrav continue; 1094333ee039SDag-Erling Smørgrav } 109547dd1d1bSDag-Erling Smørgrav if (ci->user == NULL) 109647dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("User", "user"); 109719261079SEd Maste if (match_usergroup_pattern_list(ci->user, arg) != 1) 1098333ee039SDag-Erling Smørgrav result = 0; 1099333ee039SDag-Erling Smørgrav else 1100333ee039SDag-Erling Smørgrav debug("user %.100s matched 'User %.100s' at " 1101462c32cbSDag-Erling Smørgrav "line %d", ci->user, arg, line); 1102333ee039SDag-Erling Smørgrav } else if (strcasecmp(attrib, "group") == 0) { 110319261079SEd Maste if (ci == NULL || (ci->test && ci->user == NULL)) { 1104462c32cbSDag-Erling Smørgrav result = 0; 1105462c32cbSDag-Erling Smørgrav continue; 1106462c32cbSDag-Erling Smørgrav } 110747dd1d1bSDag-Erling Smørgrav if (ci->user == NULL) 110847dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("Group", "user"); 1109462c32cbSDag-Erling Smørgrav switch (match_cfg_line_group(arg, line, ci->user)) { 1110333ee039SDag-Erling Smørgrav case -1: 1111333ee039SDag-Erling Smørgrav return -1; 1112333ee039SDag-Erling Smørgrav case 0: 1113333ee039SDag-Erling Smørgrav result = 0; 1114333ee039SDag-Erling Smørgrav } 1115333ee039SDag-Erling Smørgrav } else if (strcasecmp(attrib, "host") == 0) { 111619261079SEd Maste if (ci == NULL || (ci->test && ci->host == NULL)) { 1117333ee039SDag-Erling Smørgrav result = 0; 1118333ee039SDag-Erling Smørgrav continue; 1119333ee039SDag-Erling Smørgrav } 112047dd1d1bSDag-Erling Smørgrav if (ci->host == NULL) 112147dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("Host", "host"); 1122557f75e5SDag-Erling Smørgrav if (match_hostname(ci->host, arg) != 1) 1123333ee039SDag-Erling Smørgrav result = 0; 1124333ee039SDag-Erling Smørgrav else 1125333ee039SDag-Erling Smørgrav debug("connection from %.100s matched 'Host " 1126462c32cbSDag-Erling Smørgrav "%.100s' at line %d", ci->host, arg, line); 1127333ee039SDag-Erling Smørgrav } else if (strcasecmp(attrib, "address") == 0) { 112819261079SEd Maste if (ci == NULL || (ci->test && ci->address == NULL)) { 112919261079SEd Maste if (addr_match_list(NULL, arg) != 0) 113019261079SEd Maste fatal("Invalid Match address argument " 113119261079SEd Maste "'%s' at line %d", arg, line); 1132462c32cbSDag-Erling Smørgrav result = 0; 1133462c32cbSDag-Erling Smørgrav continue; 1134462c32cbSDag-Erling Smørgrav } 113547dd1d1bSDag-Erling Smørgrav if (ci->address == NULL) 113647dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("Address", "addr"); 1137462c32cbSDag-Erling Smørgrav switch (addr_match_list(ci->address, arg)) { 1138d4af9e69SDag-Erling Smørgrav case 1: 1139333ee039SDag-Erling Smørgrav debug("connection from %.100s matched 'Address " 1140462c32cbSDag-Erling Smørgrav "%.100s' at line %d", ci->address, arg, line); 1141d4af9e69SDag-Erling Smørgrav break; 1142d4af9e69SDag-Erling Smørgrav case 0: 1143d4af9e69SDag-Erling Smørgrav case -1: 1144d4af9e69SDag-Erling Smørgrav result = 0; 1145d4af9e69SDag-Erling Smørgrav break; 1146d4af9e69SDag-Erling Smørgrav case -2: 1147d4af9e69SDag-Erling Smørgrav return -1; 1148d4af9e69SDag-Erling Smørgrav } 1149462c32cbSDag-Erling Smørgrav } else if (strcasecmp(attrib, "localaddress") == 0){ 115019261079SEd Maste if (ci == NULL || (ci->test && ci->laddress == NULL)) { 115119261079SEd Maste if (addr_match_list(NULL, arg) != 0) 115219261079SEd Maste fatal("Invalid Match localaddress " 115319261079SEd Maste "argument '%s' at line %d", arg, 115419261079SEd Maste line); 1155462c32cbSDag-Erling Smørgrav result = 0; 1156462c32cbSDag-Erling Smørgrav continue; 1157462c32cbSDag-Erling Smørgrav } 115847dd1d1bSDag-Erling Smørgrav if (ci->laddress == NULL) 115947dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("LocalAddress", 116047dd1d1bSDag-Erling Smørgrav "laddr"); 1161462c32cbSDag-Erling Smørgrav switch (addr_match_list(ci->laddress, arg)) { 1162462c32cbSDag-Erling Smørgrav case 1: 1163462c32cbSDag-Erling Smørgrav debug("connection from %.100s matched " 1164462c32cbSDag-Erling Smørgrav "'LocalAddress %.100s' at line %d", 1165462c32cbSDag-Erling Smørgrav ci->laddress, arg, line); 1166462c32cbSDag-Erling Smørgrav break; 1167462c32cbSDag-Erling Smørgrav case 0: 1168462c32cbSDag-Erling Smørgrav case -1: 1169462c32cbSDag-Erling Smørgrav result = 0; 1170462c32cbSDag-Erling Smørgrav break; 1171462c32cbSDag-Erling Smørgrav case -2: 1172462c32cbSDag-Erling Smørgrav return -1; 1173462c32cbSDag-Erling Smørgrav } 1174462c32cbSDag-Erling Smørgrav } else if (strcasecmp(attrib, "localport") == 0) { 1175462c32cbSDag-Erling Smørgrav if ((port = a2port(arg)) == -1) { 1176462c32cbSDag-Erling Smørgrav error("Invalid LocalPort '%s' on Match line", 1177462c32cbSDag-Erling Smørgrav arg); 1178462c32cbSDag-Erling Smørgrav return -1; 1179462c32cbSDag-Erling Smørgrav } 118019261079SEd Maste if (ci == NULL || (ci->test && ci->lport == -1)) { 1181462c32cbSDag-Erling Smørgrav result = 0; 1182462c32cbSDag-Erling Smørgrav continue; 1183462c32cbSDag-Erling Smørgrav } 118447dd1d1bSDag-Erling Smørgrav if (ci->lport == 0) 118547dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("LocalPort", "lport"); 1186462c32cbSDag-Erling Smørgrav /* TODO support port lists */ 1187462c32cbSDag-Erling Smørgrav if (port == ci->lport) 1188462c32cbSDag-Erling Smørgrav debug("connection from %.100s matched " 1189462c32cbSDag-Erling Smørgrav "'LocalPort %d' at line %d", 1190462c32cbSDag-Erling Smørgrav ci->laddress, port, line); 1191462c32cbSDag-Erling Smørgrav else 1192462c32cbSDag-Erling Smørgrav result = 0; 119347dd1d1bSDag-Erling Smørgrav } else if (strcasecmp(attrib, "rdomain") == 0) { 119419261079SEd Maste if (ci == NULL || (ci->test && ci->rdomain == NULL)) { 119547dd1d1bSDag-Erling Smørgrav result = 0; 119647dd1d1bSDag-Erling Smørgrav continue; 119747dd1d1bSDag-Erling Smørgrav } 119819261079SEd Maste if (ci->rdomain == NULL) 119919261079SEd Maste match_test_missing_fatal("RDomain", "rdomain"); 120047dd1d1bSDag-Erling Smørgrav if (match_pattern_list(ci->rdomain, arg, 0) != 1) 120147dd1d1bSDag-Erling Smørgrav result = 0; 120247dd1d1bSDag-Erling Smørgrav else 120347dd1d1bSDag-Erling Smørgrav debug("user %.100s matched 'RDomain %.100s' at " 120447dd1d1bSDag-Erling Smørgrav "line %d", ci->rdomain, arg, line); 1205333ee039SDag-Erling Smørgrav } else { 1206333ee039SDag-Erling Smørgrav error("Unsupported Match attribute %s", attrib); 1207333ee039SDag-Erling Smørgrav return -1; 1208333ee039SDag-Erling Smørgrav } 1209333ee039SDag-Erling Smørgrav } 1210f7167e0eSDag-Erling Smørgrav if (attributes == 0) { 1211f7167e0eSDag-Erling Smørgrav error("One or more attributes required for Match"); 1212f7167e0eSDag-Erling Smørgrav return -1; 1213f7167e0eSDag-Erling Smørgrav } 1214462c32cbSDag-Erling Smørgrav if (ci != NULL) 1215333ee039SDag-Erling Smørgrav debug3("match %sfound", result ? "" : "not "); 1216333ee039SDag-Erling Smørgrav *condition = cp; 1217333ee039SDag-Erling Smørgrav return result; 1218333ee039SDag-Erling Smørgrav } 1219333ee039SDag-Erling Smørgrav 1220333ee039SDag-Erling Smørgrav #define WHITESPACE " \t\r\n" 1221333ee039SDag-Erling Smørgrav 1222e146993eSDag-Erling Smørgrav /* Multistate option parsing */ 1223e146993eSDag-Erling Smørgrav struct multistate { 1224e146993eSDag-Erling Smørgrav char *key; 1225e146993eSDag-Erling Smørgrav int value; 1226e146993eSDag-Erling Smørgrav }; 122747dd1d1bSDag-Erling Smørgrav static const struct multistate multistate_flag[] = { 122847dd1d1bSDag-Erling Smørgrav { "yes", 1 }, 122947dd1d1bSDag-Erling Smørgrav { "no", 0 }, 123047dd1d1bSDag-Erling Smørgrav { NULL, -1 } 123147dd1d1bSDag-Erling Smørgrav }; 123219261079SEd Maste static const struct multistate multistate_ignore_rhosts[] = { 123319261079SEd Maste { "yes", IGNORE_RHOSTS_YES }, 123419261079SEd Maste { "no", IGNORE_RHOSTS_NO }, 123519261079SEd Maste { "shosts-only", IGNORE_RHOSTS_SHOSTS }, 123619261079SEd Maste { NULL, -1 } 123719261079SEd Maste }; 1238e146993eSDag-Erling Smørgrav static const struct multistate multistate_addressfamily[] = { 1239e146993eSDag-Erling Smørgrav { "inet", AF_INET }, 1240e146993eSDag-Erling Smørgrav { "inet6", AF_INET6 }, 1241e146993eSDag-Erling Smørgrav { "any", AF_UNSPEC }, 1242e146993eSDag-Erling Smørgrav { NULL, -1 } 1243e146993eSDag-Erling Smørgrav }; 1244e146993eSDag-Erling Smørgrav static const struct multistate multistate_permitrootlogin[] = { 1245e146993eSDag-Erling Smørgrav { "without-password", PERMIT_NO_PASSWD }, 1246eccfee6eSDag-Erling Smørgrav { "prohibit-password", PERMIT_NO_PASSWD }, 1247e146993eSDag-Erling Smørgrav { "forced-commands-only", PERMIT_FORCED_ONLY }, 1248e146993eSDag-Erling Smørgrav { "yes", PERMIT_YES }, 1249e146993eSDag-Erling Smørgrav { "no", PERMIT_NO }, 1250e146993eSDag-Erling Smørgrav { NULL, -1 } 1251e146993eSDag-Erling Smørgrav }; 1252e146993eSDag-Erling Smørgrav static const struct multistate multistate_compression[] = { 125319261079SEd Maste #ifdef WITH_ZLIB 1254ca86bcf2SDag-Erling Smørgrav { "yes", COMP_DELAYED }, 1255e146993eSDag-Erling Smørgrav { "delayed", COMP_DELAYED }, 125619261079SEd Maste #endif 1257e146993eSDag-Erling Smørgrav { "no", COMP_NONE }, 1258e146993eSDag-Erling Smørgrav { NULL, -1 } 1259e146993eSDag-Erling Smørgrav }; 1260e146993eSDag-Erling Smørgrav static const struct multistate multistate_gatewayports[] = { 1261e146993eSDag-Erling Smørgrav { "clientspecified", 2 }, 1262e146993eSDag-Erling Smørgrav { "yes", 1 }, 1263e146993eSDag-Erling Smørgrav { "no", 0 }, 1264e146993eSDag-Erling Smørgrav { NULL, -1 } 1265e146993eSDag-Erling Smørgrav }; 12666888a9beSDag-Erling Smørgrav static const struct multistate multistate_tcpfwd[] = { 12676888a9beSDag-Erling Smørgrav { "yes", FORWARD_ALLOW }, 12686888a9beSDag-Erling Smørgrav { "all", FORWARD_ALLOW }, 12696888a9beSDag-Erling Smørgrav { "no", FORWARD_DENY }, 12706888a9beSDag-Erling Smørgrav { "remote", FORWARD_REMOTE }, 12716888a9beSDag-Erling Smørgrav { "local", FORWARD_LOCAL }, 12726888a9beSDag-Erling Smørgrav { NULL, -1 } 12736888a9beSDag-Erling Smørgrav }; 1274e146993eSDag-Erling Smørgrav 127519261079SEd Maste static int 127619261079SEd Maste process_server_config_line_depth(ServerOptions *options, char *line, 1277462c32cbSDag-Erling Smørgrav const char *filename, int linenum, int *activep, 127819261079SEd Maste struct connection_info *connectinfo, int *inc_flags, int depth, 127919261079SEd Maste struct include_list *includes) 1280511b41d2SMark Murray { 1281*1323ec57SEd Maste char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword; 128219261079SEd Maste int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found; 1283d4af9e69SDag-Erling Smørgrav SyslogFacility *log_facility_ptr; 1284d4af9e69SDag-Erling Smørgrav LogLevel *log_level_ptr; 1285511b41d2SMark Murray ServerOpCodes opcode; 1286190cef3dSDag-Erling Smørgrav u_int i, *uintptr, uvalue, flags = 0; 1287333ee039SDag-Erling Smørgrav size_t len; 1288e4a9863fSDag-Erling Smørgrav long long val64; 1289e146993eSDag-Erling Smørgrav const struct multistate *multistate_ptr; 129047dd1d1bSDag-Erling Smørgrav const char *errstr; 129119261079SEd Maste struct include_item *item; 129219261079SEd Maste glob_t gbuf; 129319261079SEd Maste char **oav = NULL, **av; 129419261079SEd Maste int oac = 0, ac; 129519261079SEd Maste int ret = -1; 1296511b41d2SMark Murray 1297d93a896eSDag-Erling Smørgrav /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ 1298d93a896eSDag-Erling Smørgrav if ((len = strlen(line)) == 0) 1299d93a896eSDag-Erling Smørgrav return 0; 1300d93a896eSDag-Erling Smørgrav for (len--; len > 0; len--) { 1301d93a896eSDag-Erling Smørgrav if (strchr(WHITESPACE "\f", line[len]) == NULL) 1302d93a896eSDag-Erling Smørgrav break; 1303d93a896eSDag-Erling Smørgrav line[len] = '\0'; 1304d93a896eSDag-Erling Smørgrav } 1305d93a896eSDag-Erling Smørgrav 130619261079SEd Maste str = line; 130719261079SEd Maste if ((keyword = strdelim(&str)) == NULL) 1308333ee039SDag-Erling Smørgrav return 0; 1309c2d3a559SKris Kennaway /* Ignore leading whitespace */ 131019261079SEd Maste if (*keyword == '\0') 131119261079SEd Maste keyword = strdelim(&str); 131219261079SEd Maste if (!keyword || !*keyword || *keyword == '#') 1313af12a3e7SDag-Erling Smørgrav return 0; 131419261079SEd Maste if (str == NULL || *str == '\0') { 131519261079SEd Maste error("%s line %d: no argument after keyword \"%s\"", 131619261079SEd Maste filename, linenum, keyword); 131719261079SEd Maste return -1; 131819261079SEd Maste } 1319ca3176e7SBrian Feldman intptr = NULL; 1320ca3176e7SBrian Feldman charptr = NULL; 132119261079SEd Maste opcode = parse_token(keyword, filename, linenum, &flags); 132219261079SEd Maste 132319261079SEd Maste if (argv_split(str, &oac, &oav, 1) != 0) { 132419261079SEd Maste error("%s line %d: invalid quotes", filename, linenum); 132519261079SEd Maste return -1; 132619261079SEd Maste } 132719261079SEd Maste ac = oac; 132819261079SEd Maste av = oav; 1329333ee039SDag-Erling Smørgrav 1330333ee039SDag-Erling Smørgrav if (activep == NULL) { /* We are processing a command line directive */ 1331333ee039SDag-Erling Smørgrav cmdline = 1; 1332333ee039SDag-Erling Smørgrav activep = &cmdline; 1333333ee039SDag-Erling Smørgrav } 133419261079SEd Maste if (*activep && opcode != sMatch && opcode != sInclude) 133519261079SEd Maste debug3("%s:%d setting %s %s", filename, linenum, keyword, str); 1336333ee039SDag-Erling Smørgrav if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 1337462c32cbSDag-Erling Smørgrav if (connectinfo == NULL) { 1338333ee039SDag-Erling Smørgrav fatal("%s line %d: Directive '%s' is not allowed " 133919261079SEd Maste "within a Match block", filename, linenum, keyword); 1340333ee039SDag-Erling Smørgrav } else { /* this is a directive we have already processed */ 134119261079SEd Maste ret = 0; 134219261079SEd Maste goto out; 1343333ee039SDag-Erling Smørgrav } 1344333ee039SDag-Erling Smørgrav } 1345333ee039SDag-Erling Smørgrav 1346511b41d2SMark Murray switch (opcode) { 1347989dd127SDag-Erling Smørgrav /* Portable-specific options */ 1348cf2b5f3bSDag-Erling Smørgrav case sUsePAM: 1349cf2b5f3bSDag-Erling Smørgrav intptr = &options->use_pam; 1350989dd127SDag-Erling Smørgrav goto parse_flag; 1351989dd127SDag-Erling Smørgrav 1352989dd127SDag-Erling Smørgrav /* Standard Options */ 1353511b41d2SMark Murray case sBadOption: 135419261079SEd Maste goto out; 1355511b41d2SMark Murray case sPort: 1356511b41d2SMark Murray /* ignore ports from configfile if cmdline specifies ports */ 135719261079SEd Maste if (options->ports_from_cmdline) { 135819261079SEd Maste argv_consume(&ac); 135919261079SEd Maste break; 136019261079SEd Maste } 1361511b41d2SMark Murray if (options->num_ports >= MAX_PORTS) 1362ca3176e7SBrian Feldman fatal("%s line %d: too many ports.", 1363511b41d2SMark Murray filename, linenum); 136419261079SEd Maste arg = argv_next(&ac, &av); 1365c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1366ca3176e7SBrian Feldman fatal("%s line %d: missing port number.", 1367511b41d2SMark Murray filename, linenum); 1368ca3176e7SBrian Feldman options->ports[options->num_ports++] = a2port(arg); 1369cce7d346SDag-Erling Smørgrav if (options->ports[options->num_ports-1] <= 0) 1370ca3176e7SBrian Feldman fatal("%s line %d: Badly formatted port number.", 1371ca3176e7SBrian Feldman filename, linenum); 1372511b41d2SMark Murray break; 1373511b41d2SMark Murray 1374511b41d2SMark Murray case sLoginGraceTime: 1375511b41d2SMark Murray intptr = &options->login_grace_time; 1376af12a3e7SDag-Erling Smørgrav parse_time: 137719261079SEd Maste arg = argv_next(&ac, &av); 1378af12a3e7SDag-Erling Smørgrav if (!arg || *arg == '\0') 1379af12a3e7SDag-Erling Smørgrav fatal("%s line %d: missing time value.", 1380af12a3e7SDag-Erling Smørgrav filename, linenum); 1381af12a3e7SDag-Erling Smørgrav if ((value = convtime(arg)) == -1) 1382af12a3e7SDag-Erling Smørgrav fatal("%s line %d: invalid time value.", 1383af12a3e7SDag-Erling Smørgrav filename, linenum); 1384557f75e5SDag-Erling Smørgrav if (*activep && *intptr == -1) 1385af12a3e7SDag-Erling Smørgrav *intptr = value; 1386af12a3e7SDag-Erling Smørgrav break; 1387511b41d2SMark Murray 1388511b41d2SMark Murray case sListenAddress: 138919261079SEd Maste arg = argv_next(&ac, &av); 1390aa49c926SDag-Erling Smørgrav if (arg == NULL || *arg == '\0') 1391aa49c926SDag-Erling Smørgrav fatal("%s line %d: missing address", 1392511b41d2SMark Murray filename, linenum); 1393d4ecd108SDag-Erling Smørgrav /* check for bare IPv6 address: no "[]" and 2 or more ":" */ 1394d4ecd108SDag-Erling Smørgrav if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL 1395d4ecd108SDag-Erling Smørgrav && strchr(p+1, ':') != NULL) { 139647dd1d1bSDag-Erling Smørgrav port = 0; 139747dd1d1bSDag-Erling Smørgrav p = arg; 139847dd1d1bSDag-Erling Smørgrav } else { 139919261079SEd Maste arg2 = NULL; 1400*1323ec57SEd Maste p = hpdelim(&arg); 1401*1323ec57SEd Maste if (p == NULL) 1402aa49c926SDag-Erling Smørgrav fatal("%s line %d: bad address:port usage", 1403ca3176e7SBrian Feldman filename, linenum); 1404aa49c926SDag-Erling Smørgrav p = cleanhostname(p); 1405aa49c926SDag-Erling Smørgrav if (arg == NULL) 1406aa49c926SDag-Erling Smørgrav port = 0; 1407cce7d346SDag-Erling Smørgrav else if ((port = a2port(arg)) <= 0) 140847dd1d1bSDag-Erling Smørgrav fatal("%s line %d: bad port number", 140947dd1d1bSDag-Erling Smørgrav filename, linenum); 141047dd1d1bSDag-Erling Smørgrav } 141147dd1d1bSDag-Erling Smørgrav /* Optional routing table */ 141247dd1d1bSDag-Erling Smørgrav arg2 = NULL; 141319261079SEd Maste if ((arg = argv_next(&ac, &av)) != NULL) { 141447dd1d1bSDag-Erling Smørgrav if (strcmp(arg, "rdomain") != 0 || 141519261079SEd Maste (arg2 = argv_next(&ac, &av)) == NULL) 141647dd1d1bSDag-Erling Smørgrav fatal("%s line %d: bad ListenAddress syntax", 141747dd1d1bSDag-Erling Smørgrav filename, linenum); 141847dd1d1bSDag-Erling Smørgrav if (!valid_rdomain(arg2)) 141947dd1d1bSDag-Erling Smørgrav fatal("%s line %d: bad routing domain", 142047dd1d1bSDag-Erling Smørgrav filename, linenum); 142147dd1d1bSDag-Erling Smørgrav } 142247dd1d1bSDag-Erling Smørgrav queue_listen_addr(options, p, arg2, port); 1423aa49c926SDag-Erling Smørgrav 1424aa49c926SDag-Erling Smørgrav break; 1425aa49c926SDag-Erling Smørgrav 1426aa49c926SDag-Erling Smørgrav case sAddressFamily: 1427e146993eSDag-Erling Smørgrav intptr = &options->address_family; 1428e146993eSDag-Erling Smørgrav multistate_ptr = multistate_addressfamily; 1429e146993eSDag-Erling Smørgrav parse_multistate: 143019261079SEd Maste arg = argv_next(&ac, &av); 1431d4ecd108SDag-Erling Smørgrav if (!arg || *arg == '\0') 1432e146993eSDag-Erling Smørgrav fatal("%s line %d: missing argument.", 1433d4ecd108SDag-Erling Smørgrav filename, linenum); 1434e146993eSDag-Erling Smørgrav value = -1; 1435e146993eSDag-Erling Smørgrav for (i = 0; multistate_ptr[i].key != NULL; i++) { 1436e146993eSDag-Erling Smørgrav if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1437e146993eSDag-Erling Smørgrav value = multistate_ptr[i].value; 1438e146993eSDag-Erling Smørgrav break; 1439e146993eSDag-Erling Smørgrav } 1440e146993eSDag-Erling Smørgrav } 1441e146993eSDag-Erling Smørgrav if (value == -1) 1442e146993eSDag-Erling Smørgrav fatal("%s line %d: unsupported option \"%s\".", 1443aa49c926SDag-Erling Smørgrav filename, linenum, arg); 1444e146993eSDag-Erling Smørgrav if (*activep && *intptr == -1) 1445aa49c926SDag-Erling Smørgrav *intptr = value; 1446511b41d2SMark Murray break; 1447511b41d2SMark Murray 1448511b41d2SMark Murray case sHostKeyFile: 144919261079SEd Maste arg = argv_next(&ac, &av); 1450ca3176e7SBrian Feldman if (!arg || *arg == '\0') 1451ca3176e7SBrian Feldman fatal("%s line %d: missing file name.", 1452e8aafc91SKris Kennaway filename, linenum); 145319261079SEd Maste if (*activep) { 145419261079SEd Maste servconf_add_hostkey(filename, linenum, 145519261079SEd Maste options, arg, 1); 145619261079SEd Maste } 1457e8aafc91SKris Kennaway break; 1458e8aafc91SKris Kennaway 1459e4a9863fSDag-Erling Smørgrav case sHostKeyAgent: 1460e4a9863fSDag-Erling Smørgrav charptr = &options->host_key_agent; 146119261079SEd Maste arg = argv_next(&ac, &av); 1462e4a9863fSDag-Erling Smørgrav if (!arg || *arg == '\0') 1463e4a9863fSDag-Erling Smørgrav fatal("%s line %d: missing socket name.", 1464e4a9863fSDag-Erling Smørgrav filename, linenum); 1465e4a9863fSDag-Erling Smørgrav if (*activep && *charptr == NULL) 1466e4a9863fSDag-Erling Smørgrav *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? 1467e4a9863fSDag-Erling Smørgrav xstrdup(arg) : derelativise_path(arg); 1468e4a9863fSDag-Erling Smørgrav break; 1469e4a9863fSDag-Erling Smørgrav 1470b15c8340SDag-Erling Smørgrav case sHostCertificate: 147119261079SEd Maste arg = argv_next(&ac, &av); 147247dd1d1bSDag-Erling Smørgrav if (!arg || *arg == '\0') 147347dd1d1bSDag-Erling Smørgrav fatal("%s line %d: missing file name.", 147447dd1d1bSDag-Erling Smørgrav filename, linenum); 147547dd1d1bSDag-Erling Smørgrav if (*activep) 147647dd1d1bSDag-Erling Smørgrav servconf_add_hostcert(filename, linenum, options, arg); 147747dd1d1bSDag-Erling Smørgrav break; 1478b15c8340SDag-Erling Smørgrav 1479e8aafc91SKris Kennaway case sPidFile: 1480e8aafc91SKris Kennaway charptr = &options->pid_file; 148147dd1d1bSDag-Erling Smørgrav parse_filename: 148219261079SEd Maste arg = argv_next(&ac, &av); 148347dd1d1bSDag-Erling Smørgrav if (!arg || *arg == '\0') 148447dd1d1bSDag-Erling Smørgrav fatal("%s line %d: missing file name.", 148547dd1d1bSDag-Erling Smørgrav filename, linenum); 148647dd1d1bSDag-Erling Smørgrav if (*activep && *charptr == NULL) { 148747dd1d1bSDag-Erling Smørgrav *charptr = derelativise_path(arg); 148847dd1d1bSDag-Erling Smørgrav /* increase optional counter */ 148947dd1d1bSDag-Erling Smørgrav if (intptr != NULL) 149047dd1d1bSDag-Erling Smørgrav *intptr = *intptr + 1; 149147dd1d1bSDag-Erling Smørgrav } 149247dd1d1bSDag-Erling Smørgrav break; 1493511b41d2SMark Murray 149419261079SEd Maste case sModuliFile: 149519261079SEd Maste charptr = &options->moduli_file; 149619261079SEd Maste goto parse_filename; 149719261079SEd Maste 1498511b41d2SMark Murray case sPermitRootLogin: 1499511b41d2SMark Murray intptr = &options->permit_root_login; 1500e146993eSDag-Erling Smørgrav multistate_ptr = multistate_permitrootlogin; 1501e146993eSDag-Erling Smørgrav goto parse_multistate; 1502511b41d2SMark Murray 1503511b41d2SMark Murray case sIgnoreRhosts: 1504511b41d2SMark Murray intptr = &options->ignore_rhosts; 150519261079SEd Maste multistate_ptr = multistate_ignore_rhosts; 150647dd1d1bSDag-Erling Smørgrav goto parse_multistate; 1507511b41d2SMark Murray 1508511b41d2SMark Murray case sIgnoreUserKnownHosts: 1509511b41d2SMark Murray intptr = &options->ignore_user_known_hosts; 151019261079SEd Maste parse_flag: 151119261079SEd Maste multistate_ptr = multistate_flag; 151219261079SEd Maste goto parse_multistate; 1513511b41d2SMark Murray 1514ca3176e7SBrian Feldman case sHostbasedAuthentication: 1515ca3176e7SBrian Feldman intptr = &options->hostbased_authentication; 1516ca3176e7SBrian Feldman goto parse_flag; 1517ca3176e7SBrian Feldman 1518ca3176e7SBrian Feldman case sHostbasedUsesNameFromPacketOnly: 1519ca3176e7SBrian Feldman intptr = &options->hostbased_uses_name_from_packet_only; 1520ca3176e7SBrian Feldman goto parse_flag; 1521ca3176e7SBrian Feldman 152219261079SEd Maste case sHostbasedAcceptedAlgorithms: 152319261079SEd Maste charptr = &options->hostbased_accepted_algos; 152419261079SEd Maste parse_pubkey_algos: 152519261079SEd Maste arg = argv_next(&ac, &av); 1526bc5531deSDag-Erling Smørgrav if (!arg || *arg == '\0') 1527bc5531deSDag-Erling Smørgrav fatal("%s line %d: Missing argument.", 1528bc5531deSDag-Erling Smørgrav filename, linenum); 1529d93a896eSDag-Erling Smørgrav if (*arg != '-' && 153019261079SEd Maste !sshkey_names_valid2(*arg == '+' || *arg == '^' ? 153119261079SEd Maste arg + 1 : arg, 1)) 1532bc5531deSDag-Erling Smørgrav fatal("%s line %d: Bad key types '%s'.", 1533bc5531deSDag-Erling Smørgrav filename, linenum, arg ? arg : "<NONE>"); 1534bc5531deSDag-Erling Smørgrav if (*activep && *charptr == NULL) 1535bc5531deSDag-Erling Smørgrav *charptr = xstrdup(arg); 1536bc5531deSDag-Erling Smørgrav break; 1537bc5531deSDag-Erling Smørgrav 1538eccfee6eSDag-Erling Smørgrav case sHostKeyAlgorithms: 1539eccfee6eSDag-Erling Smørgrav charptr = &options->hostkeyalgorithms; 154019261079SEd Maste goto parse_pubkey_algos; 1541eccfee6eSDag-Erling Smørgrav 15422f513db7SEd Maste case sCASignatureAlgorithms: 15432f513db7SEd Maste charptr = &options->ca_sign_algorithms; 154419261079SEd Maste goto parse_pubkey_algos; 15452f513db7SEd Maste 1546ca3176e7SBrian Feldman case sPubkeyAuthentication: 1547ca3176e7SBrian Feldman intptr = &options->pubkey_authentication; 1548e8aafc91SKris Kennaway goto parse_flag; 1549cf2b5f3bSDag-Erling Smørgrav 155019261079SEd Maste case sPubkeyAcceptedAlgorithms: 155119261079SEd Maste charptr = &options->pubkey_accepted_algos; 155219261079SEd Maste goto parse_pubkey_algos; 155319261079SEd Maste 155419261079SEd Maste case sPubkeyAuthOptions: 155519261079SEd Maste intptr = &options->pubkey_auth_options; 155619261079SEd Maste value = 0; 155719261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 155819261079SEd Maste if (strcasecmp(arg, "none") == 0) 155919261079SEd Maste continue; 156019261079SEd Maste if (strcasecmp(arg, "touch-required") == 0) 156119261079SEd Maste value |= PUBKEYAUTH_TOUCH_REQUIRED; 156219261079SEd Maste else if (strcasecmp(arg, "verify-required") == 0) 156319261079SEd Maste value |= PUBKEYAUTH_VERIFY_REQUIRED; 156419261079SEd Maste else { 156519261079SEd Maste error("%s line %d: unsupported %s option %s", 156619261079SEd Maste filename, linenum, keyword, arg); 156719261079SEd Maste goto out; 156819261079SEd Maste } 156919261079SEd Maste } 157019261079SEd Maste if (*activep && *intptr == -1) 157119261079SEd Maste *intptr = value; 157219261079SEd Maste break; 1573bc5531deSDag-Erling Smørgrav 1574cb96ab36SAssar Westerlund case sKerberosAuthentication: 1575cb96ab36SAssar Westerlund intptr = &options->kerberos_authentication; 1576511b41d2SMark Murray goto parse_flag; 1577511b41d2SMark Murray 1578af12a3e7SDag-Erling Smørgrav case sKerberosOrLocalPasswd: 1579af12a3e7SDag-Erling Smørgrav intptr = &options->kerberos_or_local_passwd; 1580511b41d2SMark Murray goto parse_flag; 1581511b41d2SMark Murray 1582af12a3e7SDag-Erling Smørgrav case sKerberosTicketCleanup: 1583af12a3e7SDag-Erling Smørgrav intptr = &options->kerberos_ticket_cleanup; 1584511b41d2SMark Murray goto parse_flag; 1585cf2b5f3bSDag-Erling Smørgrav 15861ec0d754SDag-Erling Smørgrav case sKerberosGetAFSToken: 15871ec0d754SDag-Erling Smørgrav intptr = &options->kerberos_get_afs_token; 15881ec0d754SDag-Erling Smørgrav goto parse_flag; 15891ec0d754SDag-Erling Smørgrav 1590cf2b5f3bSDag-Erling Smørgrav case sGssAuthentication: 1591cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_authentication; 1592fe5fd017SMark Murray goto parse_flag; 1593cf2b5f3bSDag-Erling Smørgrav 1594cf2b5f3bSDag-Erling Smørgrav case sGssCleanupCreds: 1595cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_cleanup_creds; 1596511b41d2SMark Murray goto parse_flag; 1597511b41d2SMark Murray 1598557f75e5SDag-Erling Smørgrav case sGssStrictAcceptor: 1599557f75e5SDag-Erling Smørgrav intptr = &options->gss_strict_acceptor; 1600557f75e5SDag-Erling Smørgrav goto parse_flag; 1601557f75e5SDag-Erling Smørgrav 1602511b41d2SMark Murray case sPasswordAuthentication: 1603511b41d2SMark Murray intptr = &options->password_authentication; 1604511b41d2SMark Murray goto parse_flag; 1605511b41d2SMark Murray 160609958426SBrian Feldman case sKbdInteractiveAuthentication: 160709958426SBrian Feldman intptr = &options->kbd_interactive_authentication; 160809958426SBrian Feldman goto parse_flag; 160909958426SBrian Feldman 1610511b41d2SMark Murray case sPrintMotd: 1611511b41d2SMark Murray intptr = &options->print_motd; 1612511b41d2SMark Murray goto parse_flag; 1613511b41d2SMark Murray 1614ca3176e7SBrian Feldman case sPrintLastLog: 1615ca3176e7SBrian Feldman intptr = &options->print_lastlog; 1616ca3176e7SBrian Feldman goto parse_flag; 1617ca3176e7SBrian Feldman 1618511b41d2SMark Murray case sX11Forwarding: 1619511b41d2SMark Murray intptr = &options->x11_forwarding; 1620511b41d2SMark Murray goto parse_flag; 1621511b41d2SMark Murray 1622511b41d2SMark Murray case sX11DisplayOffset: 1623511b41d2SMark Murray intptr = &options->x11_display_offset; 1624ca86bcf2SDag-Erling Smørgrav parse_int: 162519261079SEd Maste arg = argv_next(&ac, &av); 162647dd1d1bSDag-Erling Smørgrav if ((errstr = atoi_err(arg, &value)) != NULL) 162719261079SEd Maste fatal("%s line %d: %s integer value %s.", 162819261079SEd Maste filename, linenum, keyword, errstr); 1629ca86bcf2SDag-Erling Smørgrav if (*activep && *intptr == -1) 1630ca86bcf2SDag-Erling Smørgrav *intptr = value; 1631ca86bcf2SDag-Erling Smørgrav break; 1632511b41d2SMark Murray 1633af12a3e7SDag-Erling Smørgrav case sX11UseLocalhost: 1634af12a3e7SDag-Erling Smørgrav intptr = &options->x11_use_localhost; 1635af12a3e7SDag-Erling Smørgrav goto parse_flag; 1636af12a3e7SDag-Erling Smørgrav 1637c2d3a559SKris Kennaway case sXAuthLocation: 1638c2d3a559SKris Kennaway charptr = &options->xauth_location; 1639c2d3a559SKris Kennaway goto parse_filename; 1640c2d3a559SKris Kennaway 1641f7167e0eSDag-Erling Smørgrav case sPermitTTY: 1642f7167e0eSDag-Erling Smørgrav intptr = &options->permit_tty; 1643f7167e0eSDag-Erling Smørgrav goto parse_flag; 1644f7167e0eSDag-Erling Smørgrav 1645a0ee8cc6SDag-Erling Smørgrav case sPermitUserRC: 1646a0ee8cc6SDag-Erling Smørgrav intptr = &options->permit_user_rc; 1647a0ee8cc6SDag-Erling Smørgrav goto parse_flag; 1648a0ee8cc6SDag-Erling Smørgrav 1649511b41d2SMark Murray case sStrictModes: 1650511b41d2SMark Murray intptr = &options->strict_modes; 1651511b41d2SMark Murray goto parse_flag; 1652511b41d2SMark Murray 16531ec0d754SDag-Erling Smørgrav case sTCPKeepAlive: 16541ec0d754SDag-Erling Smørgrav intptr = &options->tcp_keep_alive; 1655511b41d2SMark Murray goto parse_flag; 1656511b41d2SMark Murray 1657511b41d2SMark Murray case sEmptyPasswd: 1658511b41d2SMark Murray intptr = &options->permit_empty_passwd; 1659511b41d2SMark Murray goto parse_flag; 1660511b41d2SMark Murray 1661f388f5efSDag-Erling Smørgrav case sPermitUserEnvironment: 1662f388f5efSDag-Erling Smørgrav intptr = &options->permit_user_env; 166319261079SEd Maste charptr = &options->permit_user_env_allowlist; 166419261079SEd Maste arg = argv_next(&ac, &av); 1665190cef3dSDag-Erling Smørgrav if (!arg || *arg == '\0') 166619261079SEd Maste fatal("%s line %d: %s missing argument.", 166719261079SEd Maste filename, linenum, keyword); 1668190cef3dSDag-Erling Smørgrav value = 0; 1669190cef3dSDag-Erling Smørgrav p = NULL; 1670190cef3dSDag-Erling Smørgrav if (strcmp(arg, "yes") == 0) 1671190cef3dSDag-Erling Smørgrav value = 1; 1672190cef3dSDag-Erling Smørgrav else if (strcmp(arg, "no") == 0) 1673190cef3dSDag-Erling Smørgrav value = 0; 1674190cef3dSDag-Erling Smørgrav else { 1675190cef3dSDag-Erling Smørgrav /* Pattern-list specified */ 1676190cef3dSDag-Erling Smørgrav value = 1; 1677190cef3dSDag-Erling Smørgrav p = xstrdup(arg); 1678190cef3dSDag-Erling Smørgrav } 1679190cef3dSDag-Erling Smørgrav if (*activep && *intptr == -1) { 1680190cef3dSDag-Erling Smørgrav *intptr = value; 1681190cef3dSDag-Erling Smørgrav *charptr = p; 1682190cef3dSDag-Erling Smørgrav p = NULL; 1683190cef3dSDag-Erling Smørgrav } 1684190cef3dSDag-Erling Smørgrav free(p); 1685190cef3dSDag-Erling Smørgrav break; 1686f388f5efSDag-Erling Smørgrav 168780628bacSDag-Erling Smørgrav case sCompression: 168880628bacSDag-Erling Smørgrav intptr = &options->compression; 1689e146993eSDag-Erling Smørgrav multistate_ptr = multistate_compression; 1690e146993eSDag-Erling Smørgrav goto parse_multistate; 169180628bacSDag-Erling Smørgrav 1692e4a9863fSDag-Erling Smørgrav case sRekeyLimit: 169319261079SEd Maste arg = argv_next(&ac, &av); 1694e4a9863fSDag-Erling Smørgrav if (!arg || *arg == '\0') 169519261079SEd Maste fatal("%s line %d: %s missing argument.", 169619261079SEd Maste filename, linenum, keyword); 1697e4a9863fSDag-Erling Smørgrav if (strcmp(arg, "default") == 0) { 1698e4a9863fSDag-Erling Smørgrav val64 = 0; 1699e4a9863fSDag-Erling Smørgrav } else { 1700e4a9863fSDag-Erling Smørgrav if (scan_scaled(arg, &val64) == -1) 170119261079SEd Maste fatal("%.200s line %d: Bad %s number '%s': %s", 170219261079SEd Maste filename, linenum, keyword, 170319261079SEd Maste arg, strerror(errno)); 1704e4a9863fSDag-Erling Smørgrav if (val64 != 0 && val64 < 16) 170519261079SEd Maste fatal("%.200s line %d: %s too small", 170619261079SEd Maste filename, linenum, keyword); 1707e4a9863fSDag-Erling Smørgrav } 1708e4a9863fSDag-Erling Smørgrav if (*activep && options->rekey_limit == -1) 1709acc1a9efSDag-Erling Smørgrav options->rekey_limit = val64; 171019261079SEd Maste if (ac != 0) { /* optional rekey interval present */ 171119261079SEd Maste if (strcmp(av[0], "none") == 0) { 171219261079SEd Maste (void)argv_next(&ac, &av); /* discard */ 1713e4a9863fSDag-Erling Smørgrav break; 1714e4a9863fSDag-Erling Smørgrav } 1715e4a9863fSDag-Erling Smørgrav intptr = &options->rekey_interval; 1716e4a9863fSDag-Erling Smørgrav goto parse_time; 1717e4a9863fSDag-Erling Smørgrav } 1718e4a9863fSDag-Erling Smørgrav break; 1719e4a9863fSDag-Erling Smørgrav 1720e8aafc91SKris Kennaway case sGatewayPorts: 1721a0ee8cc6SDag-Erling Smørgrav intptr = &options->fwd_opts.gateway_ports; 1722e146993eSDag-Erling Smørgrav multistate_ptr = multistate_gatewayports; 1723e146993eSDag-Erling Smørgrav goto parse_multistate; 1724e8aafc91SKris Kennaway 1725cf2b5f3bSDag-Erling Smørgrav case sUseDNS: 1726cf2b5f3bSDag-Erling Smørgrav intptr = &options->use_dns; 1727ca3176e7SBrian Feldman goto parse_flag; 1728ca3176e7SBrian Feldman 1729511b41d2SMark Murray case sLogFacility: 1730d4af9e69SDag-Erling Smørgrav log_facility_ptr = &options->log_facility; 173119261079SEd Maste arg = argv_next(&ac, &av); 1732c2d3a559SKris Kennaway value = log_facility_number(arg); 1733af12a3e7SDag-Erling Smørgrav if (value == SYSLOG_FACILITY_NOT_SET) 1734ca3176e7SBrian Feldman fatal("%.200s line %d: unsupported log facility '%s'", 1735c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1736d4af9e69SDag-Erling Smørgrav if (*log_facility_ptr == -1) 1737d4af9e69SDag-Erling Smørgrav *log_facility_ptr = (SyslogFacility) value; 1738511b41d2SMark Murray break; 1739511b41d2SMark Murray 1740511b41d2SMark Murray case sLogLevel: 1741d4af9e69SDag-Erling Smørgrav log_level_ptr = &options->log_level; 174219261079SEd Maste arg = argv_next(&ac, &av); 1743c2d3a559SKris Kennaway value = log_level_number(arg); 1744af12a3e7SDag-Erling Smørgrav if (value == SYSLOG_LEVEL_NOT_SET) 1745ca3176e7SBrian Feldman fatal("%.200s line %d: unsupported log level '%s'", 1746c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 17474f52dfbbSDag-Erling Smørgrav if (*activep && *log_level_ptr == -1) 1748d4af9e69SDag-Erling Smørgrav *log_level_ptr = (LogLevel) value; 1749511b41d2SMark Murray break; 1750511b41d2SMark Murray 175119261079SEd Maste case sLogVerbose: 175219261079SEd Maste found = options->num_log_verbose == 0; 175319261079SEd Maste i = 0; 175419261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 175519261079SEd Maste if (*arg == '\0') { 175619261079SEd Maste error("%s line %d: keyword %s empty argument", 175719261079SEd Maste filename, linenum, keyword); 175819261079SEd Maste goto out; 175919261079SEd Maste } 176019261079SEd Maste /* Allow "none" only in first position */ 176119261079SEd Maste if (strcasecmp(arg, "none") == 0) { 176219261079SEd Maste if (i > 0 || ac > 0) { 176319261079SEd Maste error("%s line %d: keyword %s \"none\" " 176419261079SEd Maste "argument must appear alone.", 176519261079SEd Maste filename, linenum, keyword); 176619261079SEd Maste goto out; 176719261079SEd Maste } 176819261079SEd Maste } 176919261079SEd Maste i++; 177019261079SEd Maste if (!found || !*activep) 177119261079SEd Maste continue; 177219261079SEd Maste opt_array_append(filename, linenum, keyword, 177319261079SEd Maste &options->log_verbose, &options->num_log_verbose, 177419261079SEd Maste arg); 177519261079SEd Maste } 177619261079SEd Maste break; 177719261079SEd Maste 177809958426SBrian Feldman case sAllowTcpForwarding: 177909958426SBrian Feldman intptr = &options->allow_tcp_forwarding; 17806888a9beSDag-Erling Smørgrav multistate_ptr = multistate_tcpfwd; 17816888a9beSDag-Erling Smørgrav goto parse_multistate; 178209958426SBrian Feldman 1783a0ee8cc6SDag-Erling Smørgrav case sAllowStreamLocalForwarding: 1784a0ee8cc6SDag-Erling Smørgrav intptr = &options->allow_streamlocal_forwarding; 1785a0ee8cc6SDag-Erling Smørgrav multistate_ptr = multistate_tcpfwd; 1786a0ee8cc6SDag-Erling Smørgrav goto parse_multistate; 1787a0ee8cc6SDag-Erling Smørgrav 1788d4af9e69SDag-Erling Smørgrav case sAllowAgentForwarding: 1789d4af9e69SDag-Erling Smørgrav intptr = &options->allow_agent_forwarding; 1790d4af9e69SDag-Erling Smørgrav goto parse_flag; 1791d4af9e69SDag-Erling Smørgrav 1792ca86bcf2SDag-Erling Smørgrav case sDisableForwarding: 1793ca86bcf2SDag-Erling Smørgrav intptr = &options->disable_forwarding; 1794ca86bcf2SDag-Erling Smørgrav goto parse_flag; 1795ca86bcf2SDag-Erling Smørgrav 1796511b41d2SMark Murray case sAllowUsers: 179719261079SEd Maste chararrayptr = &options->allow_users; 179819261079SEd Maste uintptr = &options->num_allow_users; 179919261079SEd Maste parse_allowdenyusers: 180019261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 180119261079SEd Maste if (*arg == '\0' || 180219261079SEd Maste match_user(NULL, NULL, NULL, arg) == -1) 180319261079SEd Maste fatal("%s line %d: invalid %s pattern: \"%s\"", 180419261079SEd Maste filename, linenum, keyword, arg); 1805462c32cbSDag-Erling Smørgrav if (!*activep) 1806462c32cbSDag-Erling Smørgrav continue; 180719261079SEd Maste opt_array_append(filename, linenum, keyword, 180819261079SEd Maste chararrayptr, uintptr, arg); 1809511b41d2SMark Murray } 1810511b41d2SMark Murray break; 1811511b41d2SMark Murray 1812511b41d2SMark Murray case sDenyUsers: 181319261079SEd Maste chararrayptr = &options->deny_users; 181419261079SEd Maste uintptr = &options->num_deny_users; 181519261079SEd Maste goto parse_allowdenyusers; 1816511b41d2SMark Murray 1817511b41d2SMark Murray case sAllowGroups: 181819261079SEd Maste chararrayptr = &options->allow_groups; 181919261079SEd Maste uintptr = &options->num_allow_groups; 182019261079SEd Maste parse_allowdenygroups: 182119261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 182219261079SEd Maste if (*arg == '\0') 182319261079SEd Maste fatal("%s line %d: empty %s pattern", 182419261079SEd Maste filename, linenum, keyword); 1825462c32cbSDag-Erling Smørgrav if (!*activep) 1826462c32cbSDag-Erling Smørgrav continue; 182719261079SEd Maste opt_array_append(filename, linenum, keyword, 182819261079SEd Maste chararrayptr, uintptr, arg); 1829511b41d2SMark Murray } 1830511b41d2SMark Murray break; 1831511b41d2SMark Murray 1832511b41d2SMark Murray case sDenyGroups: 183319261079SEd Maste chararrayptr = &options->deny_groups; 183419261079SEd Maste uintptr = &options->num_deny_groups; 183519261079SEd Maste goto parse_allowdenygroups; 1836511b41d2SMark Murray 1837e8aafc91SKris Kennaway case sCiphers: 183819261079SEd Maste arg = argv_next(&ac, &av); 1839c2d3a559SKris Kennaway if (!arg || *arg == '\0') 184019261079SEd Maste fatal("%s line %d: %s missing argument.", 184119261079SEd Maste filename, linenum, keyword); 184219261079SEd Maste if (*arg != '-' && 184319261079SEd Maste !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) 1844e8aafc91SKris Kennaway fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 1845c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1846e8aafc91SKris Kennaway if (options->ciphers == NULL) 1847c2d3a559SKris Kennaway options->ciphers = xstrdup(arg); 1848e8aafc91SKris Kennaway break; 1849e8aafc91SKris Kennaway 1850ca3176e7SBrian Feldman case sMacs: 185119261079SEd Maste arg = argv_next(&ac, &av); 1852ca3176e7SBrian Feldman if (!arg || *arg == '\0') 185319261079SEd Maste fatal("%s line %d: %s missing argument.", 185419261079SEd Maste filename, linenum, keyword); 185519261079SEd Maste if (*arg != '-' && 185619261079SEd Maste !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) 1857ca3176e7SBrian Feldman fatal("%s line %d: Bad SSH2 mac spec '%s'.", 1858ca3176e7SBrian Feldman filename, linenum, arg ? arg : "<NONE>"); 1859ca3176e7SBrian Feldman if (options->macs == NULL) 1860ca3176e7SBrian Feldman options->macs = xstrdup(arg); 1861ca3176e7SBrian Feldman break; 1862ca3176e7SBrian Feldman 18634a421b63SDag-Erling Smørgrav case sKexAlgorithms: 186419261079SEd Maste arg = argv_next(&ac, &av); 18654a421b63SDag-Erling Smørgrav if (!arg || *arg == '\0') 186619261079SEd Maste fatal("%s line %d: %s missing argument.", 186719261079SEd Maste filename, linenum, keyword); 1868d93a896eSDag-Erling Smørgrav if (*arg != '-' && 186919261079SEd Maste !kex_names_valid(*arg == '+' || *arg == '^' ? 187019261079SEd Maste arg + 1 : arg)) 18714a421b63SDag-Erling Smørgrav fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", 18724a421b63SDag-Erling Smørgrav filename, linenum, arg ? arg : "<NONE>"); 18734a421b63SDag-Erling Smørgrav if (options->kex_algorithms == NULL) 18744a421b63SDag-Erling Smørgrav options->kex_algorithms = xstrdup(arg); 18754a421b63SDag-Erling Smørgrav break; 18764a421b63SDag-Erling Smørgrav 1877c2d3a559SKris Kennaway case sSubsystem: 1878c2d3a559SKris Kennaway if (options->num_subsystems >= MAX_SUBSYSTEMS) { 1879c2d3a559SKris Kennaway fatal("%s line %d: too many subsystems defined.", 1880c2d3a559SKris Kennaway filename, linenum); 1881c2d3a559SKris Kennaway } 188219261079SEd Maste arg = argv_next(&ac, &av); 1883c2d3a559SKris Kennaway if (!arg || *arg == '\0') 188419261079SEd Maste fatal("%s line %d: %s missing argument.", 188519261079SEd Maste filename, linenum, keyword); 1886333ee039SDag-Erling Smørgrav if (!*activep) { 188719261079SEd Maste arg = argv_next(&ac, &av); 1888333ee039SDag-Erling Smørgrav break; 1889333ee039SDag-Erling Smørgrav } 1890c2d3a559SKris Kennaway for (i = 0; i < options->num_subsystems; i++) 1891c2d3a559SKris Kennaway if (strcmp(arg, options->subsystem_name[i]) == 0) 189219261079SEd Maste fatal("%s line %d: Subsystem '%s' " 189319261079SEd Maste "already defined.", filename, linenum, arg); 1894c2d3a559SKris Kennaway options->subsystem_name[options->num_subsystems] = xstrdup(arg); 189519261079SEd Maste arg = argv_next(&ac, &av); 1896c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1897c2d3a559SKris Kennaway fatal("%s line %d: Missing subsystem command.", 1898c2d3a559SKris Kennaway filename, linenum); 1899c2d3a559SKris Kennaway options->subsystem_command[options->num_subsystems] = xstrdup(arg); 1900333ee039SDag-Erling Smørgrav 1901333ee039SDag-Erling Smørgrav /* Collect arguments (separate to executable) */ 1902333ee039SDag-Erling Smørgrav p = xstrdup(arg); 1903333ee039SDag-Erling Smørgrav len = strlen(p) + 1; 190419261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 1905333ee039SDag-Erling Smørgrav len += 1 + strlen(arg); 1906557f75e5SDag-Erling Smørgrav p = xreallocarray(p, 1, len); 1907333ee039SDag-Erling Smørgrav strlcat(p, " ", len); 1908333ee039SDag-Erling Smørgrav strlcat(p, arg, len); 1909333ee039SDag-Erling Smørgrav } 1910333ee039SDag-Erling Smørgrav options->subsystem_args[options->num_subsystems] = p; 1911c2d3a559SKris Kennaway options->num_subsystems++; 1912c2d3a559SKris Kennaway break; 1913c2d3a559SKris Kennaway 1914c2d3a559SKris Kennaway case sMaxStartups: 191519261079SEd Maste arg = argv_next(&ac, &av); 1916c2d3a559SKris Kennaway if (!arg || *arg == '\0') 191719261079SEd Maste fatal("%s line %d: %s missing argument.", 191819261079SEd Maste filename, linenum, keyword); 1919af12a3e7SDag-Erling Smørgrav if ((n = sscanf(arg, "%d:%d:%d", 1920c2d3a559SKris Kennaway &options->max_startups_begin, 1921c2d3a559SKris Kennaway &options->max_startups_rate, 1922af12a3e7SDag-Erling Smørgrav &options->max_startups)) == 3) { 1923c2d3a559SKris Kennaway if (options->max_startups_begin > 1924c2d3a559SKris Kennaway options->max_startups || 1925c2d3a559SKris Kennaway options->max_startups_rate > 100 || 1926c2d3a559SKris Kennaway options->max_startups_rate < 1) 192719261079SEd Maste fatal("%s line %d: Invalid %s spec.", 192819261079SEd Maste filename, linenum, keyword); 1929af12a3e7SDag-Erling Smørgrav } else if (n != 1) 193019261079SEd Maste fatal("%s line %d: Invalid %s spec.", 193119261079SEd Maste filename, linenum, keyword); 1932af12a3e7SDag-Erling Smørgrav else 1933af12a3e7SDag-Erling Smørgrav options->max_startups = options->max_startups_begin; 1934933ca70fSBrian Feldman break; 1935933ca70fSBrian Feldman 193619261079SEd Maste case sPerSourceNetBlockSize: 193719261079SEd Maste arg = argv_next(&ac, &av); 193819261079SEd Maste if (!arg || *arg == '\0') 193919261079SEd Maste fatal("%s line %d: %s missing argument.", 194019261079SEd Maste filename, linenum, keyword); 194119261079SEd Maste switch (n = sscanf(arg, "%d:%d", &value, &value2)) { 194219261079SEd Maste case 2: 194319261079SEd Maste if (value2 < 0 || value2 > 128) 194419261079SEd Maste n = -1; 194519261079SEd Maste /* FALLTHROUGH */ 194619261079SEd Maste case 1: 194719261079SEd Maste if (value < 0 || value > 32) 194819261079SEd Maste n = -1; 194919261079SEd Maste } 195019261079SEd Maste if (n != 1 && n != 2) 195119261079SEd Maste fatal("%s line %d: Invalid %s spec.", 195219261079SEd Maste filename, linenum, keyword); 195319261079SEd Maste if (*activep) { 195419261079SEd Maste options->per_source_masklen_ipv4 = value; 195519261079SEd Maste options->per_source_masklen_ipv6 = value2; 195619261079SEd Maste } 195719261079SEd Maste break; 195819261079SEd Maste 195919261079SEd Maste case sPerSourceMaxStartups: 196019261079SEd Maste arg = argv_next(&ac, &av); 196119261079SEd Maste if (!arg || *arg == '\0') 196219261079SEd Maste fatal("%s line %d: %s missing argument.", 196319261079SEd Maste filename, linenum, keyword); 196419261079SEd Maste if (strcmp(arg, "none") == 0) { /* no limit */ 196519261079SEd Maste value = INT_MAX; 196619261079SEd Maste } else { 196719261079SEd Maste if ((errstr = atoi_err(arg, &value)) != NULL) 196819261079SEd Maste fatal("%s line %d: %s integer value %s.", 196919261079SEd Maste filename, linenum, keyword, errstr); 197019261079SEd Maste } 197119261079SEd Maste if (*activep) 197219261079SEd Maste options->per_source_max_startups = value; 197319261079SEd Maste break; 197419261079SEd Maste 197521e764dfSDag-Erling Smørgrav case sMaxAuthTries: 197621e764dfSDag-Erling Smørgrav intptr = &options->max_authtries; 197721e764dfSDag-Erling Smørgrav goto parse_int; 197821e764dfSDag-Erling Smørgrav 1979d4af9e69SDag-Erling Smørgrav case sMaxSessions: 1980d4af9e69SDag-Erling Smørgrav intptr = &options->max_sessions; 1981d4af9e69SDag-Erling Smørgrav goto parse_int; 1982d4af9e69SDag-Erling Smørgrav 1983ca3176e7SBrian Feldman case sBanner: 1984ca3176e7SBrian Feldman charptr = &options->banner; 1985ca3176e7SBrian Feldman goto parse_filename; 1986d4af9e69SDag-Erling Smørgrav 1987af12a3e7SDag-Erling Smørgrav /* 1988af12a3e7SDag-Erling Smørgrav * These options can contain %X options expanded at 1989af12a3e7SDag-Erling Smørgrav * connect time, so that you can specify paths like: 1990af12a3e7SDag-Erling Smørgrav * 1991af12a3e7SDag-Erling Smørgrav * AuthorizedKeysFile /etc/ssh_keys/%u 1992af12a3e7SDag-Erling Smørgrav */ 1993af12a3e7SDag-Erling Smørgrav case sAuthorizedKeysFile: 199419261079SEd Maste uvalue = options->num_authkeys_files; 199519261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 199619261079SEd Maste if (*arg == '\0') { 199719261079SEd Maste error("%s line %d: keyword %s empty argument", 199819261079SEd Maste filename, linenum, keyword); 199919261079SEd Maste goto out; 200019261079SEd Maste } 200119261079SEd Maste arg2 = tilde_expand_filename(arg, getuid()); 200219261079SEd Maste if (*activep && uvalue == 0) { 200319261079SEd Maste opt_array_append(filename, linenum, keyword, 200447dd1d1bSDag-Erling Smørgrav &options->authorized_keys_files, 200519261079SEd Maste &options->num_authkeys_files, arg2); 2006e146993eSDag-Erling Smørgrav } 200719261079SEd Maste free(arg2); 2008e146993eSDag-Erling Smørgrav } 200919261079SEd Maste break; 2010e146993eSDag-Erling Smørgrav 2011e2f6069cSDag-Erling Smørgrav case sAuthorizedPrincipalsFile: 2012e2f6069cSDag-Erling Smørgrav charptr = &options->authorized_principals_file; 201319261079SEd Maste arg = argv_next(&ac, &av); 20148ad9b54aSDag-Erling Smørgrav if (!arg || *arg == '\0') 201519261079SEd Maste fatal("%s line %d: %s missing argument.", 201619261079SEd Maste filename, linenum, keyword); 20178ad9b54aSDag-Erling Smørgrav if (*activep && *charptr == NULL) { 20188ad9b54aSDag-Erling Smørgrav *charptr = tilde_expand_filename(arg, getuid()); 20198ad9b54aSDag-Erling Smørgrav /* increase optional counter */ 20208ad9b54aSDag-Erling Smørgrav if (intptr != NULL) 20218ad9b54aSDag-Erling Smørgrav *intptr = *intptr + 1; 20228ad9b54aSDag-Erling Smørgrav } 20238ad9b54aSDag-Erling Smørgrav break; 2024af12a3e7SDag-Erling Smørgrav 2025ca3176e7SBrian Feldman case sClientAliveInterval: 2026ca3176e7SBrian Feldman intptr = &options->client_alive_interval; 2027af12a3e7SDag-Erling Smørgrav goto parse_time; 2028af12a3e7SDag-Erling Smørgrav 2029ca3176e7SBrian Feldman case sClientAliveCountMax: 2030ca3176e7SBrian Feldman intptr = &options->client_alive_count_max; 2031ca3176e7SBrian Feldman goto parse_int; 2032af12a3e7SDag-Erling Smørgrav 203321e764dfSDag-Erling Smørgrav case sAcceptEnv: 203419261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 203519261079SEd Maste if (*arg == '\0' || strchr(arg, '=') != NULL) 203621e764dfSDag-Erling Smørgrav fatal("%s line %d: Invalid environment name.", 203721e764dfSDag-Erling Smørgrav filename, linenum); 2038333ee039SDag-Erling Smørgrav if (!*activep) 2039462c32cbSDag-Erling Smørgrav continue; 204019261079SEd Maste opt_array_append(filename, linenum, keyword, 204147dd1d1bSDag-Erling Smørgrav &options->accept_env, &options->num_accept_env, 204247dd1d1bSDag-Erling Smørgrav arg); 204321e764dfSDag-Erling Smørgrav } 204421e764dfSDag-Erling Smørgrav break; 204521e764dfSDag-Erling Smørgrav 2046190cef3dSDag-Erling Smørgrav case sSetEnv: 2047190cef3dSDag-Erling Smørgrav uvalue = options->num_setenv; 204819261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 204919261079SEd Maste if (*arg == '\0' || strchr(arg, '=') == NULL) 2050190cef3dSDag-Erling Smørgrav fatal("%s line %d: Invalid environment.", 2051190cef3dSDag-Erling Smørgrav filename, linenum); 2052190cef3dSDag-Erling Smørgrav if (!*activep || uvalue != 0) 2053190cef3dSDag-Erling Smørgrav continue; 205419261079SEd Maste opt_array_append(filename, linenum, keyword, 2055190cef3dSDag-Erling Smørgrav &options->setenv, &options->num_setenv, arg); 2056190cef3dSDag-Erling Smørgrav } 2057190cef3dSDag-Erling Smørgrav break; 2058190cef3dSDag-Erling Smørgrav 2059b74df5b2SDag-Erling Smørgrav case sPermitTunnel: 2060b74df5b2SDag-Erling Smørgrav intptr = &options->permit_tun; 206119261079SEd Maste arg = argv_next(&ac, &av); 2062b74df5b2SDag-Erling Smørgrav if (!arg || *arg == '\0') 206319261079SEd Maste fatal("%s line %d: %s missing argument.", 206419261079SEd Maste filename, linenum, keyword); 2065d4af9e69SDag-Erling Smørgrav value = -1; 2066d4af9e69SDag-Erling Smørgrav for (i = 0; tunmode_desc[i].val != -1; i++) 2067d4af9e69SDag-Erling Smørgrav if (strcmp(tunmode_desc[i].text, arg) == 0) { 2068d4af9e69SDag-Erling Smørgrav value = tunmode_desc[i].val; 2069d4af9e69SDag-Erling Smørgrav break; 2070d4af9e69SDag-Erling Smørgrav } 2071d4af9e69SDag-Erling Smørgrav if (value == -1) 207219261079SEd Maste fatal("%s line %d: bad %s argument %s", 207319261079SEd Maste filename, linenum, keyword, arg); 2074557f75e5SDag-Erling Smørgrav if (*activep && *intptr == -1) 2075b74df5b2SDag-Erling Smørgrav *intptr = value; 2076b74df5b2SDag-Erling Smørgrav break; 2077b74df5b2SDag-Erling Smørgrav 207819261079SEd Maste case sInclude: 207919261079SEd Maste if (cmdline) { 208019261079SEd Maste fatal("Include directive not supported as a " 208119261079SEd Maste "command-line option"); 208219261079SEd Maste } 208319261079SEd Maste value = 0; 208419261079SEd Maste while ((arg2 = argv_next(&ac, &av)) != NULL) { 208519261079SEd Maste if (*arg2 == '\0') { 208619261079SEd Maste error("%s line %d: keyword %s empty argument", 208719261079SEd Maste filename, linenum, keyword); 208819261079SEd Maste goto out; 208919261079SEd Maste } 209019261079SEd Maste value++; 209119261079SEd Maste found = 0; 209219261079SEd Maste if (*arg2 != '/' && *arg2 != '~') { 209319261079SEd Maste xasprintf(&arg, "%s/%s", SSHDIR, arg2); 209419261079SEd Maste } else 209519261079SEd Maste arg = xstrdup(arg2); 209619261079SEd Maste 209719261079SEd Maste /* 209819261079SEd Maste * Don't let included files clobber the containing 209919261079SEd Maste * file's Match state. 210019261079SEd Maste */ 210119261079SEd Maste oactive = *activep; 210219261079SEd Maste 210319261079SEd Maste /* consult cache of include files */ 210419261079SEd Maste TAILQ_FOREACH(item, includes, entry) { 210519261079SEd Maste if (strcmp(item->selector, arg) != 0) 210619261079SEd Maste continue; 210719261079SEd Maste if (item->filename != NULL) { 210819261079SEd Maste parse_server_config_depth(options, 210919261079SEd Maste item->filename, item->contents, 211019261079SEd Maste includes, connectinfo, 211119261079SEd Maste (*inc_flags & SSHCFG_MATCH_ONLY 211219261079SEd Maste ? SSHCFG_MATCH_ONLY : (oactive 211319261079SEd Maste ? 0 : SSHCFG_NEVERMATCH)), 211419261079SEd Maste activep, depth + 1); 211519261079SEd Maste } 211619261079SEd Maste found = 1; 211719261079SEd Maste *activep = oactive; 211819261079SEd Maste } 211919261079SEd Maste if (found != 0) { 212019261079SEd Maste free(arg); 212119261079SEd Maste continue; 212219261079SEd Maste } 212319261079SEd Maste 212419261079SEd Maste /* requested glob was not in cache */ 212519261079SEd Maste debug2("%s line %d: new include %s", 212619261079SEd Maste filename, linenum, arg); 212719261079SEd Maste if ((r = glob(arg, 0, NULL, &gbuf)) != 0) { 212819261079SEd Maste if (r != GLOB_NOMATCH) { 212919261079SEd Maste fatal("%s line %d: include \"%s\" glob " 213019261079SEd Maste "failed", filename, linenum, arg); 213119261079SEd Maste } 213219261079SEd Maste /* 213319261079SEd Maste * If no entry matched then record a 213419261079SEd Maste * placeholder to skip later glob calls. 213519261079SEd Maste */ 213619261079SEd Maste debug2("%s line %d: no match for %s", 213719261079SEd Maste filename, linenum, arg); 213819261079SEd Maste item = xcalloc(1, sizeof(*item)); 213919261079SEd Maste item->selector = strdup(arg); 214019261079SEd Maste TAILQ_INSERT_TAIL(includes, 214119261079SEd Maste item, entry); 214219261079SEd Maste } 214319261079SEd Maste if (gbuf.gl_pathc > INT_MAX) 214419261079SEd Maste fatal_f("too many glob results"); 214519261079SEd Maste for (n = 0; n < (int)gbuf.gl_pathc; n++) { 214619261079SEd Maste debug2("%s line %d: including %s", 214719261079SEd Maste filename, linenum, gbuf.gl_pathv[n]); 214819261079SEd Maste item = xcalloc(1, sizeof(*item)); 214919261079SEd Maste item->selector = strdup(arg); 215019261079SEd Maste item->filename = strdup(gbuf.gl_pathv[n]); 215119261079SEd Maste if ((item->contents = sshbuf_new()) == NULL) 215219261079SEd Maste fatal_f("sshbuf_new failed"); 215319261079SEd Maste load_server_config(item->filename, 215419261079SEd Maste item->contents); 215519261079SEd Maste parse_server_config_depth(options, 215619261079SEd Maste item->filename, item->contents, 215719261079SEd Maste includes, connectinfo, 215819261079SEd Maste (*inc_flags & SSHCFG_MATCH_ONLY 215919261079SEd Maste ? SSHCFG_MATCH_ONLY : (oactive 216019261079SEd Maste ? 0 : SSHCFG_NEVERMATCH)), 216119261079SEd Maste activep, depth + 1); 216219261079SEd Maste *activep = oactive; 216319261079SEd Maste TAILQ_INSERT_TAIL(includes, item, entry); 216419261079SEd Maste } 216519261079SEd Maste globfree(&gbuf); 216619261079SEd Maste free(arg); 216719261079SEd Maste } 216819261079SEd Maste if (value == 0) { 216919261079SEd Maste fatal("%s line %d: %s missing filename argument", 217019261079SEd Maste filename, linenum, keyword); 217119261079SEd Maste } 217219261079SEd Maste break; 217319261079SEd Maste 2174333ee039SDag-Erling Smørgrav case sMatch: 2175333ee039SDag-Erling Smørgrav if (cmdline) 2176333ee039SDag-Erling Smørgrav fatal("Match directive not supported as a command-line " 2177333ee039SDag-Erling Smørgrav "option"); 217819261079SEd Maste value = match_cfg_line(&str, linenum, 217919261079SEd Maste (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo)); 2180333ee039SDag-Erling Smørgrav if (value < 0) 2181333ee039SDag-Erling Smørgrav fatal("%s line %d: Bad Match condition", filename, 2182333ee039SDag-Erling Smørgrav linenum); 218319261079SEd Maste *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; 218419261079SEd Maste /* 218519261079SEd Maste * The MATCH_ONLY flag is applicable only until the first 218619261079SEd Maste * match block. 218719261079SEd Maste */ 218819261079SEd Maste *inc_flags &= ~SSHCFG_MATCH_ONLY; 218919261079SEd Maste /* 219019261079SEd Maste * If match_cfg_line() didn't consume all its arguments then 219119261079SEd Maste * arrange for the extra arguments check below to fail. 219219261079SEd Maste */ 219319261079SEd Maste if (str == NULL || *str == '\0') 219419261079SEd Maste argv_consume(&ac); 2195333ee039SDag-Erling Smørgrav break; 2196333ee039SDag-Erling Smørgrav 2197190cef3dSDag-Erling Smørgrav case sPermitListen: 2198333ee039SDag-Erling Smørgrav case sPermitOpen: 2199190cef3dSDag-Erling Smørgrav if (opcode == sPermitListen) { 2200190cef3dSDag-Erling Smørgrav uintptr = &options->num_permitted_listens; 2201190cef3dSDag-Erling Smørgrav chararrayptr = &options->permitted_listens; 2202190cef3dSDag-Erling Smørgrav } else { 2203190cef3dSDag-Erling Smørgrav uintptr = &options->num_permitted_opens; 2204190cef3dSDag-Erling Smørgrav chararrayptr = &options->permitted_opens; 2205190cef3dSDag-Erling Smørgrav } 220619261079SEd Maste arg = argv_next(&ac, &av); 2207333ee039SDag-Erling Smørgrav if (!arg || *arg == '\0') 220819261079SEd Maste fatal("%s line %d: %s missing argument.", 220919261079SEd Maste filename, linenum, keyword); 2210190cef3dSDag-Erling Smørgrav uvalue = *uintptr; /* modified later */ 22114f52dfbbSDag-Erling Smørgrav if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { 2212190cef3dSDag-Erling Smørgrav if (*activep && uvalue == 0) { 2213190cef3dSDag-Erling Smørgrav *uintptr = 1; 2214190cef3dSDag-Erling Smørgrav *chararrayptr = xcalloc(1, 2215190cef3dSDag-Erling Smørgrav sizeof(**chararrayptr)); 2216190cef3dSDag-Erling Smørgrav (*chararrayptr)[0] = xstrdup(arg); 2217462c32cbSDag-Erling Smørgrav } 2218462c32cbSDag-Erling Smørgrav break; 2219462c32cbSDag-Erling Smørgrav } 222019261079SEd Maste for (; arg != NULL && *arg != '\0'; arg = argv_next(&ac, &av)) { 2221190cef3dSDag-Erling Smørgrav if (opcode == sPermitListen && 2222190cef3dSDag-Erling Smørgrav strchr(arg, ':') == NULL) { 2223190cef3dSDag-Erling Smørgrav /* 2224190cef3dSDag-Erling Smørgrav * Allow bare port number for PermitListen 2225190cef3dSDag-Erling Smørgrav * to indicate a wildcard listen host. 2226190cef3dSDag-Erling Smørgrav */ 2227190cef3dSDag-Erling Smørgrav xasprintf(&arg2, "*:%s", arg); 2228190cef3dSDag-Erling Smørgrav } else { 22294f52dfbbSDag-Erling Smørgrav arg2 = xstrdup(arg); 2230*1323ec57SEd Maste p = hpdelim(&arg); 2231*1323ec57SEd Maste if (p == NULL) { 223219261079SEd Maste fatal("%s line %d: %s missing host", 223319261079SEd Maste filename, linenum, keyword); 2234190cef3dSDag-Erling Smørgrav } 2235333ee039SDag-Erling Smørgrav p = cleanhostname(p); 2236190cef3dSDag-Erling Smørgrav } 2237190cef3dSDag-Erling Smørgrav if (arg == NULL || 2238190cef3dSDag-Erling Smørgrav ((port = permitopen_port(arg)) < 0)) { 223919261079SEd Maste fatal("%s line %d: %s bad port number", 224019261079SEd Maste filename, linenum, keyword); 2241190cef3dSDag-Erling Smørgrav } 2242190cef3dSDag-Erling Smørgrav if (*activep && uvalue == 0) { 224319261079SEd Maste opt_array_append(filename, linenum, keyword, 2244190cef3dSDag-Erling Smørgrav chararrayptr, uintptr, arg2); 224547dd1d1bSDag-Erling Smørgrav } 22464f52dfbbSDag-Erling Smørgrav free(arg2); 2247333ee039SDag-Erling Smørgrav } 2248333ee039SDag-Erling Smørgrav break; 2249333ee039SDag-Erling Smørgrav 2250333ee039SDag-Erling Smørgrav case sForceCommand: 225119261079SEd Maste if (str == NULL || *str == '\0') 225219261079SEd Maste fatal("%s line %d: %s missing argument.", 225319261079SEd Maste filename, linenum, keyword); 225419261079SEd Maste len = strspn(str, WHITESPACE); 2255333ee039SDag-Erling Smørgrav if (*activep && options->adm_forced_command == NULL) 225619261079SEd Maste options->adm_forced_command = xstrdup(str + len); 225719261079SEd Maste argv_consume(&ac); 225819261079SEd Maste break; 2259333ee039SDag-Erling Smørgrav 2260d4af9e69SDag-Erling Smørgrav case sChrootDirectory: 2261d4af9e69SDag-Erling Smørgrav charptr = &options->chroot_directory; 2262d4af9e69SDag-Erling Smørgrav 226319261079SEd Maste arg = argv_next(&ac, &av); 2264d4af9e69SDag-Erling Smørgrav if (!arg || *arg == '\0') 226519261079SEd Maste fatal("%s line %d: %s missing argument.", 226619261079SEd Maste filename, linenum, keyword); 2267d4af9e69SDag-Erling Smørgrav if (*activep && *charptr == NULL) 2268d4af9e69SDag-Erling Smørgrav *charptr = xstrdup(arg); 2269d4af9e69SDag-Erling Smørgrav break; 2270d4af9e69SDag-Erling Smørgrav 2271b15c8340SDag-Erling Smørgrav case sTrustedUserCAKeys: 2272b15c8340SDag-Erling Smørgrav charptr = &options->trusted_user_ca_keys; 2273b15c8340SDag-Erling Smørgrav goto parse_filename; 2274b15c8340SDag-Erling Smørgrav 2275b15c8340SDag-Erling Smørgrav case sRevokedKeys: 2276b15c8340SDag-Erling Smørgrav charptr = &options->revoked_keys_file; 2277b15c8340SDag-Erling Smørgrav goto parse_filename; 2278b15c8340SDag-Erling Smørgrav 227919261079SEd Maste case sSecurityKeyProvider: 228019261079SEd Maste charptr = &options->sk_provider; 228119261079SEd Maste arg = argv_next(&ac, &av); 228219261079SEd Maste if (!arg || *arg == '\0') 228319261079SEd Maste fatal("%s line %d: %s missing argument.", 228419261079SEd Maste filename, linenum, keyword); 228519261079SEd Maste if (*activep && *charptr == NULL) { 228619261079SEd Maste *charptr = strcasecmp(arg, "internal") == 0 ? 228719261079SEd Maste xstrdup(arg) : derelativise_path(arg); 228819261079SEd Maste /* increase optional counter */ 228919261079SEd Maste if (intptr != NULL) 229019261079SEd Maste *intptr = *intptr + 1; 229119261079SEd Maste } 229219261079SEd Maste break; 229319261079SEd Maste 22944a421b63SDag-Erling Smørgrav case sIPQoS: 229519261079SEd Maste arg = argv_next(&ac, &av); 229619261079SEd Maste if (!arg || *arg == '\0') 229719261079SEd Maste fatal("%s line %d: %s missing argument.", 229819261079SEd Maste filename, linenum, keyword); 22994a421b63SDag-Erling Smørgrav if ((value = parse_ipqos(arg)) == -1) 230019261079SEd Maste fatal("%s line %d: Bad %s value: %s", 230119261079SEd Maste filename, linenum, keyword, arg); 230219261079SEd Maste arg = argv_next(&ac, &av); 23034a421b63SDag-Erling Smørgrav if (arg == NULL) 23044a421b63SDag-Erling Smørgrav value2 = value; 23054a421b63SDag-Erling Smørgrav else if ((value2 = parse_ipqos(arg)) == -1) 230619261079SEd Maste fatal("%s line %d: Bad %s value: %s", 230719261079SEd Maste filename, linenum, keyword, arg); 23084a421b63SDag-Erling Smørgrav if (*activep) { 23094a421b63SDag-Erling Smørgrav options->ip_qos_interactive = value; 23104a421b63SDag-Erling Smørgrav options->ip_qos_bulk = value2; 23114a421b63SDag-Erling Smørgrav } 23124a421b63SDag-Erling Smørgrav break; 23134a421b63SDag-Erling Smørgrav 2314db58a8e4SDag-Erling Smørgrav case sVersionAddendum: 231519261079SEd Maste if (str == NULL || *str == '\0') 231619261079SEd Maste fatal("%s line %d: %s missing argument.", 231719261079SEd Maste filename, linenum, keyword); 231819261079SEd Maste len = strspn(str, WHITESPACE); 231919261079SEd Maste if (strchr(str + len, '\r') != NULL) { 232019261079SEd Maste fatal("%.200s line %d: Invalid %s argument", 232119261079SEd Maste filename, linenum, keyword); 2322462c32cbSDag-Erling Smørgrav } 232319261079SEd Maste if ((arg = strchr(line, '#')) != NULL) { 232419261079SEd Maste *arg = '\0'; 232519261079SEd Maste rtrim(line); 232619261079SEd Maste } 232719261079SEd Maste if (*activep && options->version_addendum == NULL) { 232819261079SEd Maste if (strcasecmp(str + len, "none") == 0) 232919261079SEd Maste options->version_addendum = xstrdup(""); 233019261079SEd Maste else 233119261079SEd Maste options->version_addendum = xstrdup(str + len); 233219261079SEd Maste } 233319261079SEd Maste argv_consume(&ac); 233419261079SEd Maste break; 2335db58a8e4SDag-Erling Smørgrav 23366888a9beSDag-Erling Smørgrav case sAuthorizedKeysCommand: 233719261079SEd Maste charptr = &options->authorized_keys_command; 233819261079SEd Maste parse_command: 233919261079SEd Maste len = strspn(str, WHITESPACE); 234019261079SEd Maste if (str[len] != '/' && strcasecmp(str + len, "none") != 0) { 234119261079SEd Maste fatal("%.200s line %d: %s must be an absolute path", 234219261079SEd Maste filename, linenum, keyword); 23436888a9beSDag-Erling Smørgrav } 234419261079SEd Maste if (*activep && options->authorized_keys_command == NULL) 234519261079SEd Maste *charptr = xstrdup(str + len); 234619261079SEd Maste argv_consume(&ac); 234719261079SEd Maste break; 23486888a9beSDag-Erling Smørgrav 23496888a9beSDag-Erling Smørgrav case sAuthorizedKeysCommandUser: 23506888a9beSDag-Erling Smørgrav charptr = &options->authorized_keys_command_user; 235119261079SEd Maste parse_localuser: 235219261079SEd Maste arg = argv_next(&ac, &av); 235319261079SEd Maste if (!arg || *arg == '\0') { 235419261079SEd Maste fatal("%s line %d: missing %s argument.", 235519261079SEd Maste filename, linenum, keyword); 235619261079SEd Maste } 23576888a9beSDag-Erling Smørgrav if (*activep && *charptr == NULL) 23586888a9beSDag-Erling Smørgrav *charptr = xstrdup(arg); 23596888a9beSDag-Erling Smørgrav break; 23606888a9beSDag-Erling Smørgrav 2361557f75e5SDag-Erling Smørgrav case sAuthorizedPrincipalsCommand: 236219261079SEd Maste charptr = &options->authorized_principals_command; 236319261079SEd Maste goto parse_command; 2364557f75e5SDag-Erling Smørgrav 2365557f75e5SDag-Erling Smørgrav case sAuthorizedPrincipalsCommandUser: 2366557f75e5SDag-Erling Smørgrav charptr = &options->authorized_principals_command_user; 236719261079SEd Maste goto parse_localuser; 2368557f75e5SDag-Erling Smørgrav 23696888a9beSDag-Erling Smørgrav case sAuthenticationMethods: 237019261079SEd Maste found = options->num_auth_methods == 0; 2371076ad2f8SDag-Erling Smørgrav value = 0; /* seen "any" pseudo-method */ 2372190cef3dSDag-Erling Smørgrav value2 = 0; /* successfully parsed any method */ 237319261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 2374076ad2f8SDag-Erling Smørgrav if (strcmp(arg, "any") == 0) { 2375076ad2f8SDag-Erling Smørgrav if (options->num_auth_methods > 0) { 237619261079SEd Maste fatal("%s line %d: \"any\" must " 237719261079SEd Maste "appear alone in %s", 237819261079SEd Maste filename, linenum, keyword); 2379076ad2f8SDag-Erling Smørgrav } 2380076ad2f8SDag-Erling Smørgrav value = 1; 2381076ad2f8SDag-Erling Smørgrav } else if (value) { 2382076ad2f8SDag-Erling Smørgrav fatal("%s line %d: \"any\" must appear " 238319261079SEd Maste "alone in %s", filename, linenum, keyword); 2384076ad2f8SDag-Erling Smørgrav } else if (auth2_methods_valid(arg, 0) != 0) { 238519261079SEd Maste fatal("%s line %d: invalid %s method list.", 238619261079SEd Maste filename, linenum, keyword); 2387076ad2f8SDag-Erling Smørgrav } 2388076ad2f8SDag-Erling Smørgrav value2 = 1; 238919261079SEd Maste if (!found || !*activep) 2390557f75e5SDag-Erling Smørgrav continue; 239119261079SEd Maste opt_array_append(filename, linenum, keyword, 239247dd1d1bSDag-Erling Smørgrav &options->auth_methods, 239347dd1d1bSDag-Erling Smørgrav &options->num_auth_methods, arg); 23946888a9beSDag-Erling Smørgrav } 2395076ad2f8SDag-Erling Smørgrav if (value2 == 0) { 239619261079SEd Maste fatal("%s line %d: no %s specified", 239719261079SEd Maste filename, linenum, keyword); 2398076ad2f8SDag-Erling Smørgrav } 239919261079SEd Maste break; 24006888a9beSDag-Erling Smørgrav 2401a0ee8cc6SDag-Erling Smørgrav case sStreamLocalBindMask: 240219261079SEd Maste arg = argv_next(&ac, &av); 2403a0ee8cc6SDag-Erling Smørgrav if (!arg || *arg == '\0') 240419261079SEd Maste fatal("%s line %d: %s missing argument.", 240519261079SEd Maste filename, linenum, keyword); 2406a0ee8cc6SDag-Erling Smørgrav /* Parse mode in octal format */ 2407a0ee8cc6SDag-Erling Smørgrav value = strtol(arg, &p, 8); 2408a0ee8cc6SDag-Erling Smørgrav if (arg == p || value < 0 || value > 0777) 240919261079SEd Maste fatal("%s line %d: Invalid %s.", 241019261079SEd Maste filename, linenum, keyword); 2411557f75e5SDag-Erling Smørgrav if (*activep) 2412a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 2413a0ee8cc6SDag-Erling Smørgrav break; 2414a0ee8cc6SDag-Erling Smørgrav 2415a0ee8cc6SDag-Erling Smørgrav case sStreamLocalBindUnlink: 2416a0ee8cc6SDag-Erling Smørgrav intptr = &options->fwd_opts.streamlocal_bind_unlink; 2417a0ee8cc6SDag-Erling Smørgrav goto parse_flag; 2418a0ee8cc6SDag-Erling Smørgrav 2419bc5531deSDag-Erling Smørgrav case sFingerprintHash: 242019261079SEd Maste arg = argv_next(&ac, &av); 2421bc5531deSDag-Erling Smørgrav if (!arg || *arg == '\0') 242219261079SEd Maste fatal("%s line %d: %s missing argument.", 242319261079SEd Maste filename, linenum, keyword); 2424bc5531deSDag-Erling Smørgrav if ((value = ssh_digest_alg_by_name(arg)) == -1) 242519261079SEd Maste fatal("%.200s line %d: Invalid %s algorithm \"%s\".", 242619261079SEd Maste filename, linenum, keyword, arg); 2427bc5531deSDag-Erling Smørgrav if (*activep) 2428bc5531deSDag-Erling Smørgrav options->fingerprint_hash = value; 2429bc5531deSDag-Erling Smørgrav break; 2430bc5531deSDag-Erling Smørgrav 24314f52dfbbSDag-Erling Smørgrav case sExposeAuthInfo: 24324f52dfbbSDag-Erling Smørgrav intptr = &options->expose_userauth_info; 24334f52dfbbSDag-Erling Smørgrav goto parse_flag; 24344f52dfbbSDag-Erling Smørgrav 243547dd1d1bSDag-Erling Smørgrav case sRDomain: 243619261079SEd Maste #if !defined(__OpenBSD__) && !defined(HAVE_SYS_SET_PROCESS_RDOMAIN) 243719261079SEd Maste fatal("%s line %d: setting RDomain not supported on this " 243819261079SEd Maste "platform.", filename, linenum); 243919261079SEd Maste #endif 244047dd1d1bSDag-Erling Smørgrav charptr = &options->routing_domain; 244119261079SEd Maste arg = argv_next(&ac, &av); 244247dd1d1bSDag-Erling Smørgrav if (!arg || *arg == '\0') 244319261079SEd Maste fatal("%s line %d: %s missing argument.", 244419261079SEd Maste filename, linenum, keyword); 244547dd1d1bSDag-Erling Smørgrav if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 && 244647dd1d1bSDag-Erling Smørgrav !valid_rdomain(arg)) 244719261079SEd Maste fatal("%s line %d: invalid routing domain", 244847dd1d1bSDag-Erling Smørgrav filename, linenum); 244947dd1d1bSDag-Erling Smørgrav if (*activep && *charptr == NULL) 245047dd1d1bSDag-Erling Smørgrav *charptr = xstrdup(arg); 245147dd1d1bSDag-Erling Smørgrav break; 245247dd1d1bSDag-Erling Smørgrav 2453b2af61ecSKurt Lidl case sUseBlacklist: 2454b2af61ecSKurt Lidl intptr = &options->use_blacklist; 2455b2af61ecSKurt Lidl goto parse_flag; 2456b2af61ecSKurt Lidl 2457af12a3e7SDag-Erling Smørgrav case sDeprecated: 2458ca86bcf2SDag-Erling Smørgrav case sIgnore: 2459cf2b5f3bSDag-Erling Smørgrav case sUnsupported: 2460ca86bcf2SDag-Erling Smørgrav do_log2(opcode == sIgnore ? 2461ca86bcf2SDag-Erling Smørgrav SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO, 2462ca86bcf2SDag-Erling Smørgrav "%s line %d: %s option %s", filename, linenum, 246319261079SEd Maste opcode == sUnsupported ? "Unsupported" : "Deprecated", 246419261079SEd Maste keyword); 246519261079SEd Maste argv_consume(&ac); 2466af12a3e7SDag-Erling Smørgrav break; 2467af12a3e7SDag-Erling Smørgrav 246842f71286SMark Murray default: 2469af12a3e7SDag-Erling Smørgrav fatal("%s line %d: Missing handler for opcode %s (%d)", 247019261079SEd Maste filename, linenum, keyword, opcode); 2471511b41d2SMark Murray } 247219261079SEd Maste /* Check that there is no garbage at end of line. */ 247319261079SEd Maste if (ac > 0) { 247419261079SEd Maste error("%.200s line %d: keyword %s extra arguments " 247519261079SEd Maste "at end of line", filename, linenum, keyword); 247619261079SEd Maste goto out; 2477af12a3e7SDag-Erling Smørgrav } 2478af12a3e7SDag-Erling Smørgrav 247919261079SEd Maste /* success */ 248019261079SEd Maste ret = 0; 248119261079SEd Maste out: 248219261079SEd Maste argv_free(oav, oac); 248319261079SEd Maste return ret; 248419261079SEd Maste } 248519261079SEd Maste 248619261079SEd Maste int 248719261079SEd Maste process_server_config_line(ServerOptions *options, char *line, 248819261079SEd Maste const char *filename, int linenum, int *activep, 248919261079SEd Maste struct connection_info *connectinfo, struct include_list *includes) 249019261079SEd Maste { 249119261079SEd Maste int inc_flags = 0; 249219261079SEd Maste 249319261079SEd Maste return process_server_config_line_depth(options, line, filename, 249419261079SEd Maste linenum, activep, connectinfo, &inc_flags, 0, includes); 249519261079SEd Maste } 249619261079SEd Maste 249719261079SEd Maste 2498af12a3e7SDag-Erling Smørgrav /* Reads the server configuration file. */ 2499af12a3e7SDag-Erling Smørgrav 2500af12a3e7SDag-Erling Smørgrav void 2501190cef3dSDag-Erling Smørgrav load_server_config(const char *filename, struct sshbuf *conf) 2502af12a3e7SDag-Erling Smørgrav { 250319261079SEd Maste struct stat st; 2504190cef3dSDag-Erling Smørgrav char *line = NULL, *cp; 2505190cef3dSDag-Erling Smørgrav size_t linesize = 0; 2506a82e551fSDag-Erling Smørgrav FILE *f; 2507190cef3dSDag-Erling Smørgrav int r, lineno = 0; 2508af12a3e7SDag-Erling Smørgrav 250919261079SEd Maste debug2_f("filename %s", filename); 251021e764dfSDag-Erling Smørgrav if ((f = fopen(filename, "r")) == NULL) { 2511af12a3e7SDag-Erling Smørgrav perror(filename); 2512af12a3e7SDag-Erling Smørgrav exit(1); 2513af12a3e7SDag-Erling Smørgrav } 2514190cef3dSDag-Erling Smørgrav sshbuf_reset(conf); 251519261079SEd Maste /* grow buffer, so realloc is avoided for large config files */ 251619261079SEd Maste if (fstat(fileno(f), &st) == 0 && st.st_size > 0 && 251719261079SEd Maste (r = sshbuf_allocate(conf, st.st_size)) != 0) 251819261079SEd Maste fatal_fr(r, "allocate"); 2519190cef3dSDag-Erling Smørgrav while (getline(&line, &linesize, f) != -1) { 2520462c32cbSDag-Erling Smørgrav lineno++; 252121e764dfSDag-Erling Smørgrav /* 252219261079SEd Maste * Strip whitespace 252321e764dfSDag-Erling Smørgrav * NB - preserve newlines, they are needed to reproduce 252421e764dfSDag-Erling Smørgrav * line numbers later for error messages 252521e764dfSDag-Erling Smørgrav */ 252621e764dfSDag-Erling Smørgrav cp = line + strspn(line, " \t\r"); 2527190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0) 252819261079SEd Maste fatal_fr(r, "sshbuf_put"); 252921e764dfSDag-Erling Smørgrav } 2530190cef3dSDag-Erling Smørgrav free(line); 2531190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(conf, 0)) != 0) 253219261079SEd Maste fatal_fr(r, "sshbuf_put_u8"); 253321e764dfSDag-Erling Smørgrav fclose(f); 253419261079SEd Maste debug2_f("done config len = %zu", sshbuf_len(conf)); 253521e764dfSDag-Erling Smørgrav } 253621e764dfSDag-Erling Smørgrav 253721e764dfSDag-Erling Smørgrav void 2538462c32cbSDag-Erling Smørgrav parse_server_match_config(ServerOptions *options, 253919261079SEd Maste struct include_list *includes, struct connection_info *connectinfo) 254021e764dfSDag-Erling Smørgrav { 2541333ee039SDag-Erling Smørgrav ServerOptions mo; 2542333ee039SDag-Erling Smørgrav 2543333ee039SDag-Erling Smørgrav initialize_server_options(&mo); 254419261079SEd Maste parse_server_config(&mo, "reprocess config", cfg, includes, 254519261079SEd Maste connectinfo); 2546d4af9e69SDag-Erling Smørgrav copy_set_server_options(options, &mo, 0); 2547333ee039SDag-Erling Smørgrav } 2548333ee039SDag-Erling Smørgrav 2549462c32cbSDag-Erling Smørgrav int parse_server_match_testspec(struct connection_info *ci, char *spec) 2550462c32cbSDag-Erling Smørgrav { 2551462c32cbSDag-Erling Smørgrav char *p; 2552462c32cbSDag-Erling Smørgrav 2553462c32cbSDag-Erling Smørgrav while ((p = strsep(&spec, ",")) && *p != '\0') { 2554462c32cbSDag-Erling Smørgrav if (strncmp(p, "addr=", 5) == 0) { 2555462c32cbSDag-Erling Smørgrav ci->address = xstrdup(p + 5); 2556462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "host=", 5) == 0) { 2557462c32cbSDag-Erling Smørgrav ci->host = xstrdup(p + 5); 2558462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "user=", 5) == 0) { 2559462c32cbSDag-Erling Smørgrav ci->user = xstrdup(p + 5); 2560462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "laddr=", 6) == 0) { 2561462c32cbSDag-Erling Smørgrav ci->laddress = xstrdup(p + 6); 256247dd1d1bSDag-Erling Smørgrav } else if (strncmp(p, "rdomain=", 8) == 0) { 256347dd1d1bSDag-Erling Smørgrav ci->rdomain = xstrdup(p + 8); 2564462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "lport=", 6) == 0) { 2565462c32cbSDag-Erling Smørgrav ci->lport = a2port(p + 6); 2566462c32cbSDag-Erling Smørgrav if (ci->lport == -1) { 2567462c32cbSDag-Erling Smørgrav fprintf(stderr, "Invalid port '%s' in test mode" 2568462c32cbSDag-Erling Smørgrav " specification %s\n", p+6, p); 2569462c32cbSDag-Erling Smørgrav return -1; 2570462c32cbSDag-Erling Smørgrav } 2571462c32cbSDag-Erling Smørgrav } else { 2572462c32cbSDag-Erling Smørgrav fprintf(stderr, "Invalid test mode specification %s\n", 2573462c32cbSDag-Erling Smørgrav p); 2574462c32cbSDag-Erling Smørgrav return -1; 2575462c32cbSDag-Erling Smørgrav } 2576462c32cbSDag-Erling Smørgrav } 2577462c32cbSDag-Erling Smørgrav return 0; 2578462c32cbSDag-Erling Smørgrav } 2579462c32cbSDag-Erling Smørgrav 2580462c32cbSDag-Erling Smørgrav /* 2581d4af9e69SDag-Erling Smørgrav * Copy any supported values that are set. 2582d4af9e69SDag-Erling Smørgrav * 25837aee6ffeSDag-Erling Smørgrav * If the preauth flag is set, we do not bother copying the string or 2584d4af9e69SDag-Erling Smørgrav * array values that are not used pre-authentication, because any that we 2585190cef3dSDag-Erling Smørgrav * do use must be explicitly sent in mm_getpwnamallow(). 2586d4af9e69SDag-Erling Smørgrav */ 2587333ee039SDag-Erling Smørgrav void 2588d4af9e69SDag-Erling Smørgrav copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) 2589333ee039SDag-Erling Smørgrav { 2590f7167e0eSDag-Erling Smørgrav #define M_CP_INTOPT(n) do {\ 2591f7167e0eSDag-Erling Smørgrav if (src->n != -1) \ 2592f7167e0eSDag-Erling Smørgrav dst->n = src->n; \ 2593f7167e0eSDag-Erling Smørgrav } while (0) 2594f7167e0eSDag-Erling Smørgrav 2595d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(password_authentication); 2596d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(gss_authentication); 2597d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(pubkey_authentication); 259819261079SEd Maste M_CP_INTOPT(pubkey_auth_options); 2599d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(kerberos_authentication); 2600d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(hostbased_authentication); 2601e2f6069cSDag-Erling Smørgrav M_CP_INTOPT(hostbased_uses_name_from_packet_only); 2602d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(kbd_interactive_authentication); 2603d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(permit_root_login); 2604cce7d346SDag-Erling Smørgrav M_CP_INTOPT(permit_empty_passwd); 260519261079SEd Maste M_CP_INTOPT(ignore_rhosts); 2606d4af9e69SDag-Erling Smørgrav 2607d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(allow_tcp_forwarding); 2608a0ee8cc6SDag-Erling Smørgrav M_CP_INTOPT(allow_streamlocal_forwarding); 2609d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(allow_agent_forwarding); 2610ca86bcf2SDag-Erling Smørgrav M_CP_INTOPT(disable_forwarding); 26114f52dfbbSDag-Erling Smørgrav M_CP_INTOPT(expose_userauth_info); 2612e2f6069cSDag-Erling Smørgrav M_CP_INTOPT(permit_tun); 2613a0ee8cc6SDag-Erling Smørgrav M_CP_INTOPT(fwd_opts.gateway_ports); 2614076ad2f8SDag-Erling Smørgrav M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); 2615d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(x11_display_offset); 2616d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(x11_forwarding); 2617d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(x11_use_localhost); 2618f7167e0eSDag-Erling Smørgrav M_CP_INTOPT(permit_tty); 2619a0ee8cc6SDag-Erling Smørgrav M_CP_INTOPT(permit_user_rc); 2620d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(max_sessions); 2621d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(max_authtries); 2622ca86bcf2SDag-Erling Smørgrav M_CP_INTOPT(client_alive_count_max); 2623ca86bcf2SDag-Erling Smørgrav M_CP_INTOPT(client_alive_interval); 26244a421b63SDag-Erling Smørgrav M_CP_INTOPT(ip_qos_interactive); 26254a421b63SDag-Erling Smørgrav M_CP_INTOPT(ip_qos_bulk); 2626e4a9863fSDag-Erling Smørgrav M_CP_INTOPT(rekey_limit); 2627e4a9863fSDag-Erling Smørgrav M_CP_INTOPT(rekey_interval); 26284f52dfbbSDag-Erling Smørgrav M_CP_INTOPT(log_level); 2629d4af9e69SDag-Erling Smørgrav 2630076ad2f8SDag-Erling Smørgrav /* 2631076ad2f8SDag-Erling Smørgrav * The bind_mask is a mode_t that may be unsigned, so we can't use 2632076ad2f8SDag-Erling Smørgrav * M_CP_INTOPT - it does a signed comparison that causes compiler 2633076ad2f8SDag-Erling Smørgrav * warnings. 2634076ad2f8SDag-Erling Smørgrav */ 2635076ad2f8SDag-Erling Smørgrav if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) { 2636076ad2f8SDag-Erling Smørgrav dst->fwd_opts.streamlocal_bind_mask = 2637076ad2f8SDag-Erling Smørgrav src->fwd_opts.streamlocal_bind_mask; 2638076ad2f8SDag-Erling Smørgrav } 2639076ad2f8SDag-Erling Smørgrav 2640f7167e0eSDag-Erling Smørgrav /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ 2641f7167e0eSDag-Erling Smørgrav #define M_CP_STROPT(n) do {\ 2642f7167e0eSDag-Erling Smørgrav if (src->n != NULL && dst->n != src->n) { \ 2643f7167e0eSDag-Erling Smørgrav free(dst->n); \ 2644f7167e0eSDag-Erling Smørgrav dst->n = src->n; \ 2645f7167e0eSDag-Erling Smørgrav } \ 2646f7167e0eSDag-Erling Smørgrav } while(0) 264747dd1d1bSDag-Erling Smørgrav #define M_CP_STRARRAYOPT(s, num_s) do {\ 264847dd1d1bSDag-Erling Smørgrav u_int i; \ 264947dd1d1bSDag-Erling Smørgrav if (src->num_s != 0) { \ 265047dd1d1bSDag-Erling Smørgrav for (i = 0; i < dst->num_s; i++) \ 265147dd1d1bSDag-Erling Smørgrav free(dst->s[i]); \ 265247dd1d1bSDag-Erling Smørgrav free(dst->s); \ 265347dd1d1bSDag-Erling Smørgrav dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \ 265447dd1d1bSDag-Erling Smørgrav for (i = 0; i < src->num_s; i++) \ 265547dd1d1bSDag-Erling Smørgrav dst->s[i] = xstrdup(src->s[i]); \ 265647dd1d1bSDag-Erling Smørgrav dst->num_s = src->num_s; \ 26574f52dfbbSDag-Erling Smørgrav } \ 26584f52dfbbSDag-Erling Smørgrav } while(0) 2659f7167e0eSDag-Erling Smørgrav 2660e146993eSDag-Erling Smørgrav /* See comment in servconf.h */ 2661e146993eSDag-Erling Smørgrav COPY_MATCH_STRING_OPTS(); 2662e146993eSDag-Erling Smørgrav 2663acc1a9efSDag-Erling Smørgrav /* Arguments that accept '+...' need to be expanded */ 2664acc1a9efSDag-Erling Smørgrav assemble_algorithms(dst); 2665acc1a9efSDag-Erling Smørgrav 2666e146993eSDag-Erling Smørgrav /* 2667e146993eSDag-Erling Smørgrav * The only things that should be below this point are string options 2668e146993eSDag-Erling Smørgrav * which are only used after authentication. 2669e146993eSDag-Erling Smørgrav */ 2670d4af9e69SDag-Erling Smørgrav if (preauth) 2671d4af9e69SDag-Erling Smørgrav return; 2672e146993eSDag-Erling Smørgrav 2673acc1a9efSDag-Erling Smørgrav /* These options may be "none" to clear a global setting */ 2674d4af9e69SDag-Erling Smørgrav M_CP_STROPT(adm_forced_command); 2675acc1a9efSDag-Erling Smørgrav if (option_clear_or_none(dst->adm_forced_command)) { 2676acc1a9efSDag-Erling Smørgrav free(dst->adm_forced_command); 2677acc1a9efSDag-Erling Smørgrav dst->adm_forced_command = NULL; 2678acc1a9efSDag-Erling Smørgrav } 2679d4af9e69SDag-Erling Smørgrav M_CP_STROPT(chroot_directory); 2680acc1a9efSDag-Erling Smørgrav if (option_clear_or_none(dst->chroot_directory)) { 2681acc1a9efSDag-Erling Smørgrav free(dst->chroot_directory); 2682acc1a9efSDag-Erling Smørgrav dst->chroot_directory = NULL; 2683acc1a9efSDag-Erling Smørgrav } 2684333ee039SDag-Erling Smørgrav } 2685d4af9e69SDag-Erling Smørgrav 2686d4af9e69SDag-Erling Smørgrav #undef M_CP_INTOPT 2687d4af9e69SDag-Erling Smørgrav #undef M_CP_STROPT 2688e146993eSDag-Erling Smørgrav #undef M_CP_STRARRAYOPT 2689333ee039SDag-Erling Smørgrav 269019261079SEd Maste #define SERVCONF_MAX_DEPTH 16 269119261079SEd Maste static void 269219261079SEd Maste parse_server_config_depth(ServerOptions *options, const char *filename, 269319261079SEd Maste struct sshbuf *conf, struct include_list *includes, 269419261079SEd Maste struct connection_info *connectinfo, int flags, int *activep, int depth) 2695333ee039SDag-Erling Smørgrav { 269619261079SEd Maste int linenum, bad_options = 0; 269721e764dfSDag-Erling Smørgrav char *cp, *obuf, *cbuf; 269821e764dfSDag-Erling Smørgrav 269919261079SEd Maste if (depth < 0 || depth > SERVCONF_MAX_DEPTH) 270019261079SEd Maste fatal("Too many recursive configuration includes"); 270119261079SEd Maste 270219261079SEd Maste debug2_f("config %s len %zu%s", filename, sshbuf_len(conf), 270319261079SEd Maste (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : "")); 270421e764dfSDag-Erling Smørgrav 2705076ad2f8SDag-Erling Smørgrav if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) 270619261079SEd Maste fatal_f("sshbuf_dup_string failed"); 270721e764dfSDag-Erling Smørgrav linenum = 1; 270821e764dfSDag-Erling Smørgrav while ((cp = strsep(&cbuf, "\n")) != NULL) { 270919261079SEd Maste if (process_server_config_line_depth(options, cp, 271019261079SEd Maste filename, linenum++, activep, connectinfo, &flags, 271119261079SEd Maste depth, includes) != 0) 2712af12a3e7SDag-Erling Smørgrav bad_options++; 2713511b41d2SMark Murray } 2714e4a9863fSDag-Erling Smørgrav free(obuf); 2715ca3176e7SBrian Feldman if (bad_options > 0) 2716af12a3e7SDag-Erling Smørgrav fatal("%s: terminating, %d bad configuration options", 2717511b41d2SMark Murray filename, bad_options); 271819261079SEd Maste } 271919261079SEd Maste 272019261079SEd Maste void 272119261079SEd Maste parse_server_config(ServerOptions *options, const char *filename, 272219261079SEd Maste struct sshbuf *conf, struct include_list *includes, 272319261079SEd Maste struct connection_info *connectinfo) 272419261079SEd Maste { 272519261079SEd Maste int active = connectinfo ? 0 : 1; 272619261079SEd Maste parse_server_config_depth(options, filename, conf, includes, 272719261079SEd Maste connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0); 2728557f75e5SDag-Erling Smørgrav process_queued_listen_addrs(options); 2729511b41d2SMark Murray } 2730d4af9e69SDag-Erling Smørgrav 2731d4af9e69SDag-Erling Smørgrav static const char * 2732e146993eSDag-Erling Smørgrav fmt_multistate_int(int val, const struct multistate *m) 2733d4af9e69SDag-Erling Smørgrav { 2734e146993eSDag-Erling Smørgrav u_int i; 2735e146993eSDag-Erling Smørgrav 2736e146993eSDag-Erling Smørgrav for (i = 0; m[i].key != NULL; i++) { 2737e146993eSDag-Erling Smørgrav if (m[i].value == val) 2738e146993eSDag-Erling Smørgrav return m[i].key; 2739e146993eSDag-Erling Smørgrav } 2740d4af9e69SDag-Erling Smørgrav return "UNKNOWN"; 2741d4af9e69SDag-Erling Smørgrav } 2742e146993eSDag-Erling Smørgrav 2743e146993eSDag-Erling Smørgrav static const char * 2744e146993eSDag-Erling Smørgrav fmt_intarg(ServerOpCodes code, int val) 2745e146993eSDag-Erling Smørgrav { 2746e146993eSDag-Erling Smørgrav if (val == -1) 2747e146993eSDag-Erling Smørgrav return "unset"; 2748e146993eSDag-Erling Smørgrav switch (code) { 2749e146993eSDag-Erling Smørgrav case sAddressFamily: 2750e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_addressfamily); 2751e146993eSDag-Erling Smørgrav case sPermitRootLogin: 2752e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_permitrootlogin); 2753e146993eSDag-Erling Smørgrav case sGatewayPorts: 2754e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_gatewayports); 2755e146993eSDag-Erling Smørgrav case sCompression: 2756e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_compression); 27576888a9beSDag-Erling Smørgrav case sAllowTcpForwarding: 27586888a9beSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_tcpfwd); 2759a0ee8cc6SDag-Erling Smørgrav case sAllowStreamLocalForwarding: 2760a0ee8cc6SDag-Erling Smørgrav return fmt_multistate_int(val, multistate_tcpfwd); 276119261079SEd Maste case sIgnoreRhosts: 276219261079SEd Maste return fmt_multistate_int(val, multistate_ignore_rhosts); 2763bc5531deSDag-Erling Smørgrav case sFingerprintHash: 2764bc5531deSDag-Erling Smørgrav return ssh_digest_alg_name(val); 2765e146993eSDag-Erling Smørgrav default: 2766d4af9e69SDag-Erling Smørgrav switch (val) { 2767d4af9e69SDag-Erling Smørgrav case 0: 2768d4af9e69SDag-Erling Smørgrav return "no"; 2769d4af9e69SDag-Erling Smørgrav case 1: 2770d4af9e69SDag-Erling Smørgrav return "yes"; 2771e146993eSDag-Erling Smørgrav default: 2772d4af9e69SDag-Erling Smørgrav return "UNKNOWN"; 2773d4af9e69SDag-Erling Smørgrav } 2774e146993eSDag-Erling Smørgrav } 2775e146993eSDag-Erling Smørgrav } 2776d4af9e69SDag-Erling Smørgrav 2777d4af9e69SDag-Erling Smørgrav static void 2778d4af9e69SDag-Erling Smørgrav dump_cfg_int(ServerOpCodes code, int val) 2779d4af9e69SDag-Erling Smørgrav { 2780d4af9e69SDag-Erling Smørgrav printf("%s %d\n", lookup_opcode_name(code), val); 2781d4af9e69SDag-Erling Smørgrav } 2782d4af9e69SDag-Erling Smørgrav 2783d4af9e69SDag-Erling Smørgrav static void 2784557f75e5SDag-Erling Smørgrav dump_cfg_oct(ServerOpCodes code, int val) 2785557f75e5SDag-Erling Smørgrav { 2786557f75e5SDag-Erling Smørgrav printf("%s 0%o\n", lookup_opcode_name(code), val); 2787557f75e5SDag-Erling Smørgrav } 2788557f75e5SDag-Erling Smørgrav 2789557f75e5SDag-Erling Smørgrav static void 2790d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(ServerOpCodes code, int val) 2791d4af9e69SDag-Erling Smørgrav { 2792d4af9e69SDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2793d4af9e69SDag-Erling Smørgrav } 2794d4af9e69SDag-Erling Smørgrav 2795d4af9e69SDag-Erling Smørgrav static void 2796d4af9e69SDag-Erling Smørgrav dump_cfg_string(ServerOpCodes code, const char *val) 2797d4af9e69SDag-Erling Smørgrav { 2798bc5531deSDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), 2799bc5531deSDag-Erling Smørgrav val == NULL ? "none" : val); 2800d4af9e69SDag-Erling Smørgrav } 2801d4af9e69SDag-Erling Smørgrav 2802d4af9e69SDag-Erling Smørgrav static void 2803d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) 2804d4af9e69SDag-Erling Smørgrav { 2805d4af9e69SDag-Erling Smørgrav u_int i; 2806d4af9e69SDag-Erling Smørgrav 2807d4af9e69SDag-Erling Smørgrav for (i = 0; i < count; i++) 2808d4af9e69SDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2809d4af9e69SDag-Erling Smørgrav } 2810d4af9e69SDag-Erling Smørgrav 2811e146993eSDag-Erling Smørgrav static void 2812e146993eSDag-Erling Smørgrav dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) 2813e146993eSDag-Erling Smørgrav { 2814e146993eSDag-Erling Smørgrav u_int i; 2815e146993eSDag-Erling Smørgrav 2816076ad2f8SDag-Erling Smørgrav if (count <= 0 && code != sAuthenticationMethods) 2817557f75e5SDag-Erling Smørgrav return; 2818e146993eSDag-Erling Smørgrav printf("%s", lookup_opcode_name(code)); 2819e146993eSDag-Erling Smørgrav for (i = 0; i < count; i++) 2820e146993eSDag-Erling Smørgrav printf(" %s", vals[i]); 2821076ad2f8SDag-Erling Smørgrav if (code == sAuthenticationMethods && count == 0) 2822076ad2f8SDag-Erling Smørgrav printf(" any"); 2823e146993eSDag-Erling Smørgrav printf("\n"); 2824e146993eSDag-Erling Smørgrav } 2825e146993eSDag-Erling Smørgrav 282647dd1d1bSDag-Erling Smørgrav static char * 282747dd1d1bSDag-Erling Smørgrav format_listen_addrs(struct listenaddr *la) 2828d4af9e69SDag-Erling Smørgrav { 282947dd1d1bSDag-Erling Smørgrav int r; 2830d4af9e69SDag-Erling Smørgrav struct addrinfo *ai; 283147dd1d1bSDag-Erling Smørgrav char addr[NI_MAXHOST], port[NI_MAXSERV]; 2832557f75e5SDag-Erling Smørgrav char *laddr1 = xstrdup(""), *laddr2 = NULL; 2833d4af9e69SDag-Erling Smørgrav 2834557f75e5SDag-Erling Smørgrav /* 2835557f75e5SDag-Erling Smørgrav * ListenAddress must be after Port. add_one_listen_addr pushes 2836557f75e5SDag-Erling Smørgrav * addresses onto a stack, so to maintain ordering we need to 2837557f75e5SDag-Erling Smørgrav * print these in reverse order. 2838557f75e5SDag-Erling Smørgrav */ 283947dd1d1bSDag-Erling Smørgrav for (ai = la->addrs; ai; ai = ai->ai_next) { 284047dd1d1bSDag-Erling Smørgrav if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, 2841d4af9e69SDag-Erling Smørgrav sizeof(addr), port, sizeof(port), 2842d4af9e69SDag-Erling Smørgrav NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { 284347dd1d1bSDag-Erling Smørgrav error("getnameinfo: %.100s", ssh_gai_strerror(r)); 284447dd1d1bSDag-Erling Smørgrav continue; 284547dd1d1bSDag-Erling Smørgrav } 2846557f75e5SDag-Erling Smørgrav laddr2 = laddr1; 284747dd1d1bSDag-Erling Smørgrav if (ai->ai_family == AF_INET6) { 284847dd1d1bSDag-Erling Smørgrav xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s", 284947dd1d1bSDag-Erling Smørgrav addr, port, 285047dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : " rdomain ", 285147dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : la->rdomain, 285247dd1d1bSDag-Erling Smørgrav laddr2); 285347dd1d1bSDag-Erling Smørgrav } else { 285447dd1d1bSDag-Erling Smørgrav xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s", 285547dd1d1bSDag-Erling Smørgrav addr, port, 285647dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : " rdomain ", 285747dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : la->rdomain, 285847dd1d1bSDag-Erling Smørgrav laddr2); 285947dd1d1bSDag-Erling Smørgrav } 2860557f75e5SDag-Erling Smørgrav free(laddr2); 2861d4af9e69SDag-Erling Smørgrav } 286247dd1d1bSDag-Erling Smørgrav return laddr1; 2863d4af9e69SDag-Erling Smørgrav } 286447dd1d1bSDag-Erling Smørgrav 286547dd1d1bSDag-Erling Smørgrav void 286647dd1d1bSDag-Erling Smørgrav dump_config(ServerOptions *o) 286747dd1d1bSDag-Erling Smørgrav { 286847dd1d1bSDag-Erling Smørgrav char *s; 286947dd1d1bSDag-Erling Smørgrav u_int i; 287047dd1d1bSDag-Erling Smørgrav 287147dd1d1bSDag-Erling Smørgrav /* these are usually at the top of the config */ 287247dd1d1bSDag-Erling Smørgrav for (i = 0; i < o->num_ports; i++) 287347dd1d1bSDag-Erling Smørgrav printf("port %d\n", o->ports[i]); 287447dd1d1bSDag-Erling Smørgrav dump_cfg_fmtint(sAddressFamily, o->address_family); 287547dd1d1bSDag-Erling Smørgrav 287647dd1d1bSDag-Erling Smørgrav for (i = 0; i < o->num_listen_addrs; i++) { 287747dd1d1bSDag-Erling Smørgrav s = format_listen_addrs(&o->listen_addrs[i]); 287847dd1d1bSDag-Erling Smørgrav printf("%s", s); 287947dd1d1bSDag-Erling Smørgrav free(s); 288047dd1d1bSDag-Erling Smørgrav } 2881d4af9e69SDag-Erling Smørgrav 2882d4af9e69SDag-Erling Smørgrav /* integer arguments */ 2883cce7d346SDag-Erling Smørgrav #ifdef USE_PAM 2884557f75e5SDag-Erling Smørgrav dump_cfg_fmtint(sUsePAM, o->use_pam); 2885cce7d346SDag-Erling Smørgrav #endif 2886d4af9e69SDag-Erling Smørgrav dump_cfg_int(sLoginGraceTime, o->login_grace_time); 2887d4af9e69SDag-Erling Smørgrav dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); 2888d4af9e69SDag-Erling Smørgrav dump_cfg_int(sMaxAuthTries, o->max_authtries); 2889cce7d346SDag-Erling Smørgrav dump_cfg_int(sMaxSessions, o->max_sessions); 2890d4af9e69SDag-Erling Smørgrav dump_cfg_int(sClientAliveInterval, o->client_alive_interval); 2891d4af9e69SDag-Erling Smørgrav dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); 2892557f75e5SDag-Erling Smørgrav dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); 2893d4af9e69SDag-Erling Smørgrav 2894d4af9e69SDag-Erling Smørgrav /* formatted integer arguments */ 2895d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); 2896d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); 2897d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); 2898d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); 2899d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, 2900d4af9e69SDag-Erling Smørgrav o->hostbased_uses_name_from_packet_only); 2901d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); 2902cce7d346SDag-Erling Smørgrav #ifdef KRB5 2903d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); 2904d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); 2905d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); 2906cce7d346SDag-Erling Smørgrav # ifdef USE_AFS 2907d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); 2908cce7d346SDag-Erling Smørgrav # endif 2909cce7d346SDag-Erling Smørgrav #endif 2910cce7d346SDag-Erling Smørgrav #ifdef GSSAPI 2911d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 2912d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 2913cce7d346SDag-Erling Smørgrav #endif 2914d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 2915d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKbdInteractiveAuthentication, 2916d4af9e69SDag-Erling Smørgrav o->kbd_interactive_authentication); 2917d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPrintMotd, o->print_motd); 2918acc1a9efSDag-Erling Smørgrav #ifndef DISABLE_LASTLOG 2919d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); 2920acc1a9efSDag-Erling Smørgrav #endif 2921d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); 2922d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); 2923f7167e0eSDag-Erling Smørgrav dump_cfg_fmtint(sPermitTTY, o->permit_tty); 2924a0ee8cc6SDag-Erling Smørgrav dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); 2925d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sStrictModes, o->strict_modes); 2926d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); 2927d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); 2928d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sCompression, o->compression); 2929a0ee8cc6SDag-Erling Smørgrav dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); 2930d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sUseDNS, o->use_dns); 2931d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 2932557f75e5SDag-Erling Smørgrav dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); 2933ca86bcf2SDag-Erling Smørgrav dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding); 2934a0ee8cc6SDag-Erling Smørgrav dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); 2935076ad2f8SDag-Erling Smørgrav dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2936bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); 29374f52dfbbSDag-Erling Smørgrav dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); 2938b2af61ecSKurt Lidl dump_cfg_fmtint(sUseBlacklist, o->use_blacklist); 2939d4af9e69SDag-Erling Smørgrav 2940d4af9e69SDag-Erling Smørgrav /* string arguments */ 2941d4af9e69SDag-Erling Smørgrav dump_cfg_string(sPidFile, o->pid_file); 294219261079SEd Maste dump_cfg_string(sModuliFile, o->moduli_file); 2943d4af9e69SDag-Erling Smørgrav dump_cfg_string(sXAuthLocation, o->xauth_location); 294419261079SEd Maste dump_cfg_string(sCiphers, o->ciphers); 294519261079SEd Maste dump_cfg_string(sMacs, o->macs); 2946d4af9e69SDag-Erling Smørgrav dump_cfg_string(sBanner, o->banner); 2947d4af9e69SDag-Erling Smørgrav dump_cfg_string(sForceCommand, o->adm_forced_command); 2948b15c8340SDag-Erling Smørgrav dump_cfg_string(sChrootDirectory, o->chroot_directory); 2949b15c8340SDag-Erling Smørgrav dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); 2950b15c8340SDag-Erling Smørgrav dump_cfg_string(sRevokedKeys, o->revoked_keys_file); 295119261079SEd Maste dump_cfg_string(sSecurityKeyProvider, o->sk_provider); 2952e2f6069cSDag-Erling Smørgrav dump_cfg_string(sAuthorizedPrincipalsFile, 2953e2f6069cSDag-Erling Smørgrav o->authorized_principals_file); 2954557f75e5SDag-Erling Smørgrav dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' 2955557f75e5SDag-Erling Smørgrav ? "none" : o->version_addendum); 29566888a9beSDag-Erling Smørgrav dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); 29576888a9beSDag-Erling Smørgrav dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); 2958557f75e5SDag-Erling Smørgrav dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); 2959557f75e5SDag-Erling Smørgrav dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); 2960e4a9863fSDag-Erling Smørgrav dump_cfg_string(sHostKeyAgent, o->host_key_agent); 296119261079SEd Maste dump_cfg_string(sKexAlgorithms, o->kex_algorithms); 296219261079SEd Maste dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms); 296319261079SEd Maste dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 296419261079SEd Maste dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms); 296519261079SEd Maste dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 296619261079SEd Maste #if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN) 296747dd1d1bSDag-Erling Smørgrav dump_cfg_string(sRDomain, o->routing_domain); 296819261079SEd Maste #endif 2969d4af9e69SDag-Erling Smørgrav 2970d4af9e69SDag-Erling Smørgrav /* string arguments requiring a lookup */ 2971d4af9e69SDag-Erling Smørgrav dump_cfg_string(sLogLevel, log_level_name(o->log_level)); 2972d4af9e69SDag-Erling Smørgrav dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); 2973d4af9e69SDag-Erling Smørgrav 2974d4af9e69SDag-Erling Smørgrav /* string array arguments */ 2975e146993eSDag-Erling Smørgrav dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, 2976e146993eSDag-Erling Smørgrav o->authorized_keys_files); 2977d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, 2978d4af9e69SDag-Erling Smørgrav o->host_key_files); 2979557f75e5SDag-Erling Smørgrav dump_cfg_strarray(sHostCertificate, o->num_host_cert_files, 2980b15c8340SDag-Erling Smørgrav o->host_cert_files); 2981d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); 2982d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); 2983d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); 2984d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); 2985d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); 2986190cef3dSDag-Erling Smørgrav dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv); 29876888a9beSDag-Erling Smørgrav dump_cfg_strarray_oneline(sAuthenticationMethods, 29886888a9beSDag-Erling Smørgrav o->num_auth_methods, o->auth_methods); 298919261079SEd Maste dump_cfg_strarray_oneline(sLogVerbose, 299019261079SEd Maste o->num_log_verbose, o->log_verbose); 2991d4af9e69SDag-Erling Smørgrav 2992d4af9e69SDag-Erling Smørgrav /* other arguments */ 2993d4af9e69SDag-Erling Smørgrav for (i = 0; i < o->num_subsystems; i++) 2994d4af9e69SDag-Erling Smørgrav printf("subsystem %s %s\n", o->subsystem_name[i], 2995d4af9e69SDag-Erling Smørgrav o->subsystem_args[i]); 2996d4af9e69SDag-Erling Smørgrav 2997d4af9e69SDag-Erling Smørgrav printf("maxstartups %d:%d:%d\n", o->max_startups_begin, 2998d4af9e69SDag-Erling Smørgrav o->max_startups_rate, o->max_startups); 299919261079SEd Maste printf("persourcemaxstartups "); 300019261079SEd Maste if (o->per_source_max_startups == INT_MAX) 300119261079SEd Maste printf("none\n"); 300219261079SEd Maste else 300319261079SEd Maste printf("%d\n", o->per_source_max_startups); 300419261079SEd Maste printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4, 300519261079SEd Maste o->per_source_masklen_ipv6); 3006d4af9e69SDag-Erling Smørgrav 300747dd1d1bSDag-Erling Smørgrav s = NULL; 300847dd1d1bSDag-Erling Smørgrav for (i = 0; tunmode_desc[i].val != -1; i++) { 3009d4af9e69SDag-Erling Smørgrav if (tunmode_desc[i].val == o->permit_tun) { 3010d4af9e69SDag-Erling Smørgrav s = tunmode_desc[i].text; 3011d4af9e69SDag-Erling Smørgrav break; 3012d4af9e69SDag-Erling Smørgrav } 301347dd1d1bSDag-Erling Smørgrav } 3014d4af9e69SDag-Erling Smørgrav dump_cfg_string(sPermitTunnel, s); 3015d4af9e69SDag-Erling Smørgrav 3016e146993eSDag-Erling Smørgrav printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3017e146993eSDag-Erling Smørgrav printf("%s\n", iptos2str(o->ip_qos_bulk)); 30184a421b63SDag-Erling Smørgrav 3019acc1a9efSDag-Erling Smørgrav printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, 3020e4a9863fSDag-Erling Smørgrav o->rekey_interval); 3021e4a9863fSDag-Erling Smørgrav 30224f52dfbbSDag-Erling Smørgrav printf("permitopen"); 30234f52dfbbSDag-Erling Smørgrav if (o->num_permitted_opens == 0) 30244f52dfbbSDag-Erling Smørgrav printf(" any"); 30254f52dfbbSDag-Erling Smørgrav else { 30264f52dfbbSDag-Erling Smørgrav for (i = 0; i < o->num_permitted_opens; i++) 30274f52dfbbSDag-Erling Smørgrav printf(" %s", o->permitted_opens[i]); 30284f52dfbbSDag-Erling Smørgrav } 30294f52dfbbSDag-Erling Smørgrav printf("\n"); 3030190cef3dSDag-Erling Smørgrav printf("permitlisten"); 3031190cef3dSDag-Erling Smørgrav if (o->num_permitted_listens == 0) 3032190cef3dSDag-Erling Smørgrav printf(" any"); 3033190cef3dSDag-Erling Smørgrav else { 3034190cef3dSDag-Erling Smørgrav for (i = 0; i < o->num_permitted_listens; i++) 3035190cef3dSDag-Erling Smørgrav printf(" %s", o->permitted_listens[i]); 3036190cef3dSDag-Erling Smørgrav } 3037190cef3dSDag-Erling Smørgrav printf("\n"); 3038190cef3dSDag-Erling Smørgrav 303919261079SEd Maste if (o->permit_user_env_allowlist == NULL) { 3040190cef3dSDag-Erling Smørgrav dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 3041190cef3dSDag-Erling Smørgrav } else { 3042190cef3dSDag-Erling Smørgrav printf("permituserenvironment %s\n", 304319261079SEd Maste o->permit_user_env_allowlist); 3044190cef3dSDag-Erling Smørgrav } 3045190cef3dSDag-Erling Smørgrav 304619261079SEd Maste printf("pubkeyauthoptions"); 304719261079SEd Maste if (o->pubkey_auth_options == 0) 304819261079SEd Maste printf(" none"); 304919261079SEd Maste if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) 305019261079SEd Maste printf(" touch-required"); 305119261079SEd Maste if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) 305219261079SEd Maste printf(" verify-required"); 305319261079SEd Maste printf("\n"); 3054d4af9e69SDag-Erling Smørgrav } 3055