1eccfee6eSDag-Erling Smørgrav 2*f374ba41SEd Maste /* $OpenBSD: servconf.c,v 1.390 2023/01/17 09:44:48 djm 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" 15511b41d2SMark Murray 16333ee039SDag-Erling Smørgrav #include <sys/types.h> 17333ee039SDag-Erling Smørgrav #include <sys/socket.h> 1819261079SEd Maste #include <sys/stat.h> 1919261079SEd Maste #ifdef __OpenBSD__ 2047dd1d1bSDag-Erling Smørgrav #include <sys/sysctl.h> 2147dd1d1bSDag-Erling Smørgrav #endif 22333ee039SDag-Erling Smørgrav 234a421b63SDag-Erling Smørgrav #include <netinet/in.h> 244a421b63SDag-Erling Smørgrav #include <netinet/in_systm.h> 254a421b63SDag-Erling Smørgrav #include <netinet/ip.h> 2647dd1d1bSDag-Erling Smørgrav #ifdef HAVE_NET_ROUTE_H 2747dd1d1bSDag-Erling Smørgrav #include <net/route.h> 2847dd1d1bSDag-Erling Smørgrav #endif 294a421b63SDag-Erling Smørgrav 30e4a9863fSDag-Erling Smørgrav #include <ctype.h> 31333ee039SDag-Erling Smørgrav #include <netdb.h> 32333ee039SDag-Erling Smørgrav #include <pwd.h> 33333ee039SDag-Erling Smørgrav #include <stdio.h> 34333ee039SDag-Erling Smørgrav #include <stdlib.h> 35333ee039SDag-Erling Smørgrav #include <string.h> 36333ee039SDag-Erling Smørgrav #include <signal.h> 37333ee039SDag-Erling Smørgrav #include <unistd.h> 38bc5531deSDag-Erling Smørgrav #include <limits.h> 39333ee039SDag-Erling Smørgrav #include <stdarg.h> 40d4af9e69SDag-Erling Smørgrav #include <errno.h> 41e4a9863fSDag-Erling Smørgrav #ifdef HAVE_UTIL_H 42e4a9863fSDag-Erling Smørgrav #include <util.h> 43e4a9863fSDag-Erling Smørgrav #endif 4419261079SEd Maste #ifdef USE_SYSTEM_GLOB 4519261079SEd Maste # include <glob.h> 4619261079SEd Maste #else 4719261079SEd Maste # include "openbsd-compat/glob.h" 4819261079SEd Maste #endif 49333ee039SDag-Erling Smørgrav 50d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h" 51333ee039SDag-Erling Smørgrav #include "xmalloc.h" 52511b41d2SMark Murray #include "ssh.h" 53ca3176e7SBrian Feldman #include "log.h" 54190cef3dSDag-Erling Smørgrav #include "sshbuf.h" 55a0ee8cc6SDag-Erling Smørgrav #include "misc.h" 56511b41d2SMark Murray #include "servconf.h" 57e8aafc91SKris Kennaway #include "compat.h" 58ca3176e7SBrian Feldman #include "pathnames.h" 59ca3176e7SBrian Feldman #include "cipher.h" 60190cef3dSDag-Erling Smørgrav #include "sshkey.h" 61ca3176e7SBrian Feldman #include "kex.h" 62ca3176e7SBrian Feldman #include "mac.h" 63333ee039SDag-Erling Smørgrav #include "match.h" 64333ee039SDag-Erling Smørgrav #include "channels.h" 65333ee039SDag-Erling Smørgrav #include "groupaccess.h" 66462c32cbSDag-Erling Smørgrav #include "canohost.h" 67462c32cbSDag-Erling Smørgrav #include "packet.h" 68190cef3dSDag-Erling Smørgrav #include "ssherr.h" 696888a9beSDag-Erling Smørgrav #include "hostfile.h" 706888a9beSDag-Erling Smørgrav #include "auth.h" 71bc5531deSDag-Erling Smørgrav #include "myproposal.h" 72bc5531deSDag-Erling Smørgrav #include "digest.h" 73b15c8340SDag-Erling Smørgrav #include "version.h" 74511b41d2SMark Murray 7547dd1d1bSDag-Erling Smørgrav static void add_listen_addr(ServerOptions *, const char *, 7647dd1d1bSDag-Erling Smørgrav const char *, int); 7747dd1d1bSDag-Erling Smørgrav static void add_one_listen_addr(ServerOptions *, const char *, 7847dd1d1bSDag-Erling Smørgrav const char *, int); 7919261079SEd Maste static void parse_server_config_depth(ServerOptions *options, 8019261079SEd Maste const char *filename, struct sshbuf *conf, struct include_list *includes, 8119261079SEd Maste struct connection_info *connectinfo, int flags, int *activep, int depth); 82ca3176e7SBrian Feldman 8380628bacSDag-Erling Smørgrav /* Use of privilege separation or not */ 8480628bacSDag-Erling Smørgrav extern int use_privsep; 85190cef3dSDag-Erling Smørgrav extern struct sshbuf *cfg; 86511b41d2SMark Murray 87511b41d2SMark Murray /* Initializes the server options to their default values. */ 88511b41d2SMark Murray 89511b41d2SMark Murray void 90511b41d2SMark Murray initialize_server_options(ServerOptions *options) 91511b41d2SMark Murray { 92511b41d2SMark Murray memset(options, 0, sizeof(*options)); 93989dd127SDag-Erling Smørgrav 94989dd127SDag-Erling Smørgrav /* Portable-specific options */ 95cf2b5f3bSDag-Erling Smørgrav options->use_pam = -1; 96989dd127SDag-Erling Smørgrav 97989dd127SDag-Erling Smørgrav /* Standard Options */ 98511b41d2SMark Murray options->num_ports = 0; 99511b41d2SMark Murray options->ports_from_cmdline = 0; 100557f75e5SDag-Erling Smørgrav options->queued_listen_addrs = NULL; 101557f75e5SDag-Erling Smørgrav options->num_queued_listens = 0; 102511b41d2SMark Murray options->listen_addrs = NULL; 10347dd1d1bSDag-Erling Smørgrav options->num_listen_addrs = 0; 104aa49c926SDag-Erling Smørgrav options->address_family = -1; 10547dd1d1bSDag-Erling Smørgrav options->routing_domain = NULL; 106ca3176e7SBrian Feldman options->num_host_key_files = 0; 107b15c8340SDag-Erling Smørgrav options->num_host_cert_files = 0; 108e4a9863fSDag-Erling Smørgrav options->host_key_agent = NULL; 109e8aafc91SKris Kennaway options->pid_file = NULL; 110511b41d2SMark Murray options->login_grace_time = -1; 111ca3176e7SBrian Feldman options->permit_root_login = PERMIT_NOT_SET; 112511b41d2SMark Murray options->ignore_rhosts = -1; 113511b41d2SMark Murray options->ignore_user_known_hosts = -1; 114511b41d2SMark Murray options->print_motd = -1; 115ca3176e7SBrian Feldman options->print_lastlog = -1; 116511b41d2SMark Murray options->x11_forwarding = -1; 117511b41d2SMark Murray options->x11_display_offset = -1; 118af12a3e7SDag-Erling Smørgrav options->x11_use_localhost = -1; 119f7167e0eSDag-Erling Smørgrav options->permit_tty = -1; 120a0ee8cc6SDag-Erling Smørgrav options->permit_user_rc = -1; 121c2d3a559SKris Kennaway options->xauth_location = NULL; 122511b41d2SMark Murray options->strict_modes = -1; 1231ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = -1; 124af12a3e7SDag-Erling Smørgrav options->log_facility = SYSLOG_FACILITY_NOT_SET; 125af12a3e7SDag-Erling Smørgrav options->log_level = SYSLOG_LEVEL_NOT_SET; 12619261079SEd Maste options->num_log_verbose = 0; 12719261079SEd Maste options->log_verbose = NULL; 128ca3176e7SBrian Feldman options->hostbased_authentication = -1; 129ca3176e7SBrian Feldman options->hostbased_uses_name_from_packet_only = -1; 13019261079SEd Maste options->hostbased_accepted_algos = NULL; 131eccfee6eSDag-Erling Smørgrav options->hostkeyalgorithms = NULL; 132ca3176e7SBrian Feldman options->pubkey_authentication = -1; 13319261079SEd Maste options->pubkey_auth_options = -1; 13419261079SEd Maste options->pubkey_accepted_algos = NULL; 135cb96ab36SAssar Westerlund options->kerberos_authentication = -1; 136af12a3e7SDag-Erling Smørgrav options->kerberos_or_local_passwd = -1; 137af12a3e7SDag-Erling Smørgrav options->kerberos_ticket_cleanup = -1; 1381ec0d754SDag-Erling Smørgrav options->kerberos_get_afs_token = -1; 139cf2b5f3bSDag-Erling Smørgrav options->gss_authentication=-1; 140cf2b5f3bSDag-Erling Smørgrav options->gss_cleanup_creds = -1; 141557f75e5SDag-Erling Smørgrav options->gss_strict_acceptor = -1; 142511b41d2SMark Murray options->password_authentication = -1; 14309958426SBrian Feldman options->kbd_interactive_authentication = -1; 144511b41d2SMark Murray options->permit_empty_passwd = -1; 145f388f5efSDag-Erling Smørgrav options->permit_user_env = -1; 14619261079SEd Maste options->permit_user_env_allowlist = NULL; 14780628bacSDag-Erling Smørgrav options->compression = -1; 148e4a9863fSDag-Erling Smørgrav options->rekey_limit = -1; 149e4a9863fSDag-Erling Smørgrav options->rekey_interval = -1; 15009958426SBrian Feldman options->allow_tcp_forwarding = -1; 151a0ee8cc6SDag-Erling Smørgrav options->allow_streamlocal_forwarding = -1; 152d4af9e69SDag-Erling Smørgrav options->allow_agent_forwarding = -1; 153511b41d2SMark Murray options->num_allow_users = 0; 154511b41d2SMark Murray options->num_deny_users = 0; 155511b41d2SMark Murray options->num_allow_groups = 0; 156511b41d2SMark Murray options->num_deny_groups = 0; 157e8aafc91SKris Kennaway options->ciphers = NULL; 158ca3176e7SBrian Feldman options->macs = NULL; 1594a421b63SDag-Erling Smørgrav options->kex_algorithms = NULL; 1602f513db7SEd Maste options->ca_sign_algorithms = NULL; 161a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.gateway_ports = -1; 162a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 163a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_unlink = -1; 164c2d3a559SKris Kennaway options->num_subsystems = 0; 165c2d3a559SKris Kennaway options->max_startups_begin = -1; 166c2d3a559SKris Kennaway options->max_startups_rate = -1; 167c2d3a559SKris Kennaway options->max_startups = -1; 16819261079SEd Maste options->per_source_max_startups = -1; 16919261079SEd Maste options->per_source_masklen_ipv4 = -1; 17019261079SEd Maste options->per_source_masklen_ipv6 = -1; 17121e764dfSDag-Erling Smørgrav options->max_authtries = -1; 172d4af9e69SDag-Erling Smørgrav options->max_sessions = -1; 173ca3176e7SBrian Feldman options->banner = NULL; 174cf2b5f3bSDag-Erling Smørgrav options->use_dns = -1; 175ca3176e7SBrian Feldman options->client_alive_interval = -1; 176ca3176e7SBrian Feldman options->client_alive_count_max = -1; 177e146993eSDag-Erling Smørgrav options->num_authkeys_files = 0; 17821e764dfSDag-Erling Smørgrav options->num_accept_env = 0; 179190cef3dSDag-Erling Smørgrav options->num_setenv = 0; 180b74df5b2SDag-Erling Smørgrav options->permit_tun = -1; 1814f52dfbbSDag-Erling Smørgrav options->permitted_opens = NULL; 182190cef3dSDag-Erling Smørgrav options->permitted_listens = NULL; 183333ee039SDag-Erling Smørgrav options->adm_forced_command = NULL; 184d4af9e69SDag-Erling Smørgrav options->chroot_directory = NULL; 1856888a9beSDag-Erling Smørgrav options->authorized_keys_command = NULL; 1866888a9beSDag-Erling Smørgrav options->authorized_keys_command_user = NULL; 187b15c8340SDag-Erling Smørgrav options->revoked_keys_file = NULL; 18819261079SEd Maste options->sk_provider = NULL; 189b15c8340SDag-Erling Smørgrav options->trusted_user_ca_keys = NULL; 190e2f6069cSDag-Erling Smørgrav options->authorized_principals_file = NULL; 191557f75e5SDag-Erling Smørgrav options->authorized_principals_command = NULL; 192557f75e5SDag-Erling Smørgrav options->authorized_principals_command_user = NULL; 1934a421b63SDag-Erling Smørgrav options->ip_qos_interactive = -1; 1944a421b63SDag-Erling Smørgrav options->ip_qos_bulk = -1; 195462c32cbSDag-Erling Smørgrav options->version_addendum = NULL; 196bc5531deSDag-Erling Smørgrav options->fingerprint_hash = -1; 197ca86bcf2SDag-Erling Smørgrav options->disable_forwarding = -1; 1984f52dfbbSDag-Erling Smørgrav options->expose_userauth_info = -1; 19938a52bd3SEd Maste options->required_rsa_size = -1; 200*f374ba41SEd Maste options->channel_timeouts = NULL; 201*f374ba41SEd Maste options->num_channel_timeouts = 0; 202*f374ba41SEd Maste options->unused_connection_timeout = -1; 203b2af61ecSKurt Lidl options->use_blacklist = -1; 204bc5531deSDag-Erling Smørgrav } 205bc5531deSDag-Erling Smørgrav 206bc5531deSDag-Erling Smørgrav /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 207bc5531deSDag-Erling Smørgrav static int 208bc5531deSDag-Erling Smørgrav option_clear_or_none(const char *o) 209bc5531deSDag-Erling Smørgrav { 210bc5531deSDag-Erling Smørgrav return o == NULL || strcasecmp(o, "none") == 0; 211511b41d2SMark Murray } 212511b41d2SMark Murray 213acc1a9efSDag-Erling Smørgrav static void 214acc1a9efSDag-Erling Smørgrav assemble_algorithms(ServerOptions *o) 215acc1a9efSDag-Erling Smørgrav { 2162f513db7SEd Maste char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; 21719261079SEd Maste char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; 218190cef3dSDag-Erling Smørgrav int r; 219190cef3dSDag-Erling Smørgrav 220190cef3dSDag-Erling Smørgrav all_cipher = cipher_alg_list(',', 0); 221190cef3dSDag-Erling Smørgrav all_mac = mac_alg_list(','); 222190cef3dSDag-Erling Smørgrav all_kex = kex_alg_list(','); 223190cef3dSDag-Erling Smørgrav all_key = sshkey_alg_list(0, 0, 1, ','); 2242f513db7SEd Maste all_sig = sshkey_alg_list(0, 1, 1, ','); 22519261079SEd Maste /* remove unsupported algos from default lists */ 22619261079SEd Maste def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher); 22719261079SEd Maste def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac); 22819261079SEd Maste def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex); 22919261079SEd Maste def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); 23019261079SEd Maste def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); 231190cef3dSDag-Erling Smørgrav #define ASSEMBLE(what, defaults, all) \ 232190cef3dSDag-Erling Smørgrav do { \ 233190cef3dSDag-Erling Smørgrav if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ 23419261079SEd Maste fatal_fr(r, "%s", #what); \ 235190cef3dSDag-Erling Smørgrav } while (0) 23619261079SEd Maste ASSEMBLE(ciphers, def_cipher, all_cipher); 23719261079SEd Maste ASSEMBLE(macs, def_mac, all_mac); 23819261079SEd Maste ASSEMBLE(kex_algorithms, def_kex, all_kex); 23919261079SEd Maste ASSEMBLE(hostkeyalgorithms, def_key, all_key); 24019261079SEd Maste ASSEMBLE(hostbased_accepted_algos, def_key, all_key); 24119261079SEd Maste ASSEMBLE(pubkey_accepted_algos, def_key, all_key); 24219261079SEd Maste ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); 243190cef3dSDag-Erling Smørgrav #undef ASSEMBLE 244190cef3dSDag-Erling Smørgrav free(all_cipher); 245190cef3dSDag-Erling Smørgrav free(all_mac); 246190cef3dSDag-Erling Smørgrav free(all_kex); 247190cef3dSDag-Erling Smørgrav free(all_key); 2482f513db7SEd Maste free(all_sig); 24919261079SEd Maste free(def_cipher); 25019261079SEd Maste free(def_mac); 25119261079SEd Maste free(def_kex); 25219261079SEd Maste free(def_key); 25319261079SEd Maste free(def_sig); 25447dd1d1bSDag-Erling Smørgrav } 25547dd1d1bSDag-Erling Smørgrav 25647dd1d1bSDag-Erling Smørgrav static const char *defaultkey = "[default]"; 25747dd1d1bSDag-Erling Smørgrav 25847dd1d1bSDag-Erling Smørgrav void 25947dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(const char *file, const int line, 26019261079SEd Maste ServerOptions *options, const char *path, int userprovided) 26147dd1d1bSDag-Erling Smørgrav { 26247dd1d1bSDag-Erling Smørgrav char *apath = derelativise_path(path); 26347dd1d1bSDag-Erling Smørgrav 26447dd1d1bSDag-Erling Smørgrav if (file == defaultkey && access(path, R_OK) != 0) 26547dd1d1bSDag-Erling Smørgrav return; 26619261079SEd Maste opt_array_append2(file, line, "HostKey", 26719261079SEd Maste &options->host_key_files, &options->host_key_file_userprovided, 26819261079SEd Maste &options->num_host_key_files, apath, userprovided); 26947dd1d1bSDag-Erling Smørgrav free(apath); 27047dd1d1bSDag-Erling Smørgrav } 27147dd1d1bSDag-Erling Smørgrav 27247dd1d1bSDag-Erling Smørgrav void 27347dd1d1bSDag-Erling Smørgrav servconf_add_hostcert(const char *file, const int line, 27447dd1d1bSDag-Erling Smørgrav ServerOptions *options, const char *path) 27547dd1d1bSDag-Erling Smørgrav { 27647dd1d1bSDag-Erling Smørgrav char *apath = derelativise_path(path); 27747dd1d1bSDag-Erling Smørgrav 27819261079SEd Maste opt_array_append(file, line, "HostCertificate", 27947dd1d1bSDag-Erling Smørgrav &options->host_cert_files, &options->num_host_cert_files, apath); 28047dd1d1bSDag-Erling Smørgrav free(apath); 28147dd1d1bSDag-Erling Smørgrav } 28247dd1d1bSDag-Erling Smørgrav 283511b41d2SMark Murray void 284511b41d2SMark Murray fill_default_server_options(ServerOptions *options) 285511b41d2SMark Murray { 28647dd1d1bSDag-Erling Smørgrav u_int i; 287bc5531deSDag-Erling Smørgrav 288989dd127SDag-Erling Smørgrav /* Portable-specific options */ 289cf2b5f3bSDag-Erling Smørgrav if (options->use_pam == -1) 290f0477b26SDag-Erling Smørgrav options->use_pam = 1; 291989dd127SDag-Erling Smørgrav 292989dd127SDag-Erling Smørgrav /* Standard Options */ 293ca3176e7SBrian Feldman if (options->num_host_key_files == 0) { 294ca3176e7SBrian Feldman /* fill default hostkeys for protocols */ 29547dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 29619261079SEd Maste _PATH_HOST_RSA_KEY_FILE, 0); 2974a421b63SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC 29847dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 29919261079SEd Maste _PATH_HOST_ECDSA_KEY_FILE, 0); 3004a421b63SDag-Erling Smørgrav #endif 30147dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 30219261079SEd Maste _PATH_HOST_ED25519_KEY_FILE, 0); 30347dd1d1bSDag-Erling Smørgrav #ifdef WITH_XMSS 30447dd1d1bSDag-Erling Smørgrav servconf_add_hostkey(defaultkey, 0, options, 30519261079SEd Maste _PATH_HOST_XMSS_KEY_FILE, 0); 30647dd1d1bSDag-Erling Smørgrav #endif /* WITH_XMSS */ 307af12a3e7SDag-Erling Smørgrav } 308144a80bdSDag-Erling Smørgrav if (options->num_host_key_files == 0) 309144a80bdSDag-Erling Smørgrav fatal("No host key files found"); 310b15c8340SDag-Erling Smørgrav /* No certificates by default */ 311511b41d2SMark Murray if (options->num_ports == 0) 312511b41d2SMark Murray options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 313557f75e5SDag-Erling Smørgrav if (options->address_family == -1) 314557f75e5SDag-Erling Smørgrav options->address_family = AF_UNSPEC; 315511b41d2SMark Murray if (options->listen_addrs == NULL) 31647dd1d1bSDag-Erling Smørgrav add_listen_addr(options, NULL, NULL, 0); 317e8aafc91SKris Kennaway if (options->pid_file == NULL) 318bc5531deSDag-Erling Smørgrav options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); 31919261079SEd Maste if (options->moduli_file == NULL) 32019261079SEd Maste options->moduli_file = xstrdup(_PATH_DH_MODULI); 321511b41d2SMark Murray if (options->login_grace_time == -1) 322975616f0SDag-Erling Smørgrav options->login_grace_time = 120; 323ca3176e7SBrian Feldman if (options->permit_root_login == PERMIT_NOT_SET) 324975616f0SDag-Erling Smørgrav options->permit_root_login = PERMIT_NO; 325511b41d2SMark Murray if (options->ignore_rhosts == -1) 326fe5fd017SMark Murray options->ignore_rhosts = 1; 327511b41d2SMark Murray if (options->ignore_user_known_hosts == -1) 328511b41d2SMark Murray options->ignore_user_known_hosts = 0; 329511b41d2SMark Murray if (options->print_motd == -1) 330511b41d2SMark Murray options->print_motd = 1; 331ca3176e7SBrian Feldman if (options->print_lastlog == -1) 332ca3176e7SBrian Feldman options->print_lastlog = 1; 333511b41d2SMark Murray if (options->x11_forwarding == -1) 334975616f0SDag-Erling Smørgrav options->x11_forwarding = 1; 335511b41d2SMark Murray if (options->x11_display_offset == -1) 336fe5fd017SMark Murray options->x11_display_offset = 10; 337af12a3e7SDag-Erling Smørgrav if (options->x11_use_localhost == -1) 338af12a3e7SDag-Erling Smørgrav options->x11_use_localhost = 1; 339c2d3a559SKris Kennaway if (options->xauth_location == NULL) 340bc5531deSDag-Erling Smørgrav options->xauth_location = xstrdup(_PATH_XAUTH); 341f7167e0eSDag-Erling Smørgrav if (options->permit_tty == -1) 342f7167e0eSDag-Erling Smørgrav options->permit_tty = 1; 343a0ee8cc6SDag-Erling Smørgrav if (options->permit_user_rc == -1) 344a0ee8cc6SDag-Erling Smørgrav options->permit_user_rc = 1; 345511b41d2SMark Murray if (options->strict_modes == -1) 346511b41d2SMark Murray options->strict_modes = 1; 3471ec0d754SDag-Erling Smørgrav if (options->tcp_keep_alive == -1) 3481ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = 1; 349af12a3e7SDag-Erling Smørgrav if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 350511b41d2SMark Murray options->log_facility = SYSLOG_FACILITY_AUTH; 351af12a3e7SDag-Erling Smørgrav if (options->log_level == SYSLOG_LEVEL_NOT_SET) 352511b41d2SMark Murray options->log_level = SYSLOG_LEVEL_INFO; 353ca3176e7SBrian Feldman if (options->hostbased_authentication == -1) 354ca3176e7SBrian Feldman options->hostbased_authentication = 0; 355ca3176e7SBrian Feldman if (options->hostbased_uses_name_from_packet_only == -1) 356ca3176e7SBrian Feldman options->hostbased_uses_name_from_packet_only = 0; 357ca3176e7SBrian Feldman if (options->pubkey_authentication == -1) 358ca3176e7SBrian Feldman options->pubkey_authentication = 1; 35919261079SEd Maste if (options->pubkey_auth_options == -1) 36019261079SEd Maste options->pubkey_auth_options = 0; 361989dd127SDag-Erling Smørgrav if (options->kerberos_authentication == -1) 362cf2b5f3bSDag-Erling Smørgrav options->kerberos_authentication = 0; 363af12a3e7SDag-Erling Smørgrav if (options->kerberos_or_local_passwd == -1) 364af12a3e7SDag-Erling Smørgrav options->kerberos_or_local_passwd = 1; 365af12a3e7SDag-Erling Smørgrav if (options->kerberos_ticket_cleanup == -1) 366af12a3e7SDag-Erling Smørgrav options->kerberos_ticket_cleanup = 1; 3671ec0d754SDag-Erling Smørgrav if (options->kerberos_get_afs_token == -1) 3681ec0d754SDag-Erling Smørgrav options->kerberos_get_afs_token = 0; 369cf2b5f3bSDag-Erling Smørgrav if (options->gss_authentication == -1) 370cf2b5f3bSDag-Erling Smørgrav options->gss_authentication = 0; 371cf2b5f3bSDag-Erling Smørgrav if (options->gss_cleanup_creds == -1) 372cf2b5f3bSDag-Erling Smørgrav options->gss_cleanup_creds = 1; 373557f75e5SDag-Erling Smørgrav if (options->gss_strict_acceptor == -1) 374d93a896eSDag-Erling Smørgrav options->gss_strict_acceptor = 1; 375511b41d2SMark Murray if (options->password_authentication == -1) 376b909c84bSDag-Erling Smørgrav options->password_authentication = 0; 37709958426SBrian Feldman if (options->kbd_interactive_authentication == -1) 37819261079SEd Maste options->kbd_interactive_authentication = 1; 379511b41d2SMark Murray if (options->permit_empty_passwd == -1) 380fe5fd017SMark Murray options->permit_empty_passwd = 0; 381190cef3dSDag-Erling Smørgrav if (options->permit_user_env == -1) { 382f388f5efSDag-Erling Smørgrav options->permit_user_env = 0; 38319261079SEd Maste options->permit_user_env_allowlist = NULL; 384190cef3dSDag-Erling Smørgrav } 38580628bacSDag-Erling Smørgrav if (options->compression == -1) 38619261079SEd Maste #ifdef WITH_ZLIB 387d4ecd108SDag-Erling Smørgrav options->compression = COMP_DELAYED; 38819261079SEd Maste #else 38919261079SEd Maste options->compression = COMP_NONE; 39019261079SEd Maste #endif 39119261079SEd Maste 392e4a9863fSDag-Erling Smørgrav if (options->rekey_limit == -1) 393e4a9863fSDag-Erling Smørgrav options->rekey_limit = 0; 394e4a9863fSDag-Erling Smørgrav if (options->rekey_interval == -1) 395e4a9863fSDag-Erling Smørgrav options->rekey_interval = 0; 39609958426SBrian Feldman if (options->allow_tcp_forwarding == -1) 3976888a9beSDag-Erling Smørgrav options->allow_tcp_forwarding = FORWARD_ALLOW; 398a0ee8cc6SDag-Erling Smørgrav if (options->allow_streamlocal_forwarding == -1) 399a0ee8cc6SDag-Erling Smørgrav options->allow_streamlocal_forwarding = FORWARD_ALLOW; 400d4af9e69SDag-Erling Smørgrav if (options->allow_agent_forwarding == -1) 401d4af9e69SDag-Erling Smørgrav options->allow_agent_forwarding = 1; 402a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.gateway_ports == -1) 403a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.gateway_ports = 0; 404c2d3a559SKris Kennaway if (options->max_startups == -1) 4056888a9beSDag-Erling Smørgrav options->max_startups = 100; 406c2d3a559SKris Kennaway if (options->max_startups_rate == -1) 4076888a9beSDag-Erling Smørgrav options->max_startups_rate = 30; /* 30% */ 408c2d3a559SKris Kennaway if (options->max_startups_begin == -1) 4096888a9beSDag-Erling Smørgrav options->max_startups_begin = 10; 41019261079SEd Maste if (options->per_source_max_startups == -1) 41119261079SEd Maste options->per_source_max_startups = INT_MAX; 41219261079SEd Maste if (options->per_source_masklen_ipv4 == -1) 41319261079SEd Maste options->per_source_masklen_ipv4 = 32; 41419261079SEd Maste if (options->per_source_masklen_ipv6 == -1) 41519261079SEd Maste options->per_source_masklen_ipv6 = 128; 41621e764dfSDag-Erling Smørgrav if (options->max_authtries == -1) 41721e764dfSDag-Erling Smørgrav options->max_authtries = DEFAULT_AUTH_FAIL_MAX; 418d4af9e69SDag-Erling Smørgrav if (options->max_sessions == -1) 419d4af9e69SDag-Erling Smørgrav options->max_sessions = DEFAULT_SESSIONS_MAX; 420cf2b5f3bSDag-Erling Smørgrav if (options->use_dns == -1) 421c4cd1fa4SDag-Erling Smørgrav options->use_dns = 1; 422ca3176e7SBrian Feldman if (options->client_alive_interval == -1) 423ca3176e7SBrian Feldman options->client_alive_interval = 0; 424ca3176e7SBrian Feldman if (options->client_alive_count_max == -1) 425ca3176e7SBrian Feldman options->client_alive_count_max = 3; 426e146993eSDag-Erling Smørgrav if (options->num_authkeys_files == 0) { 42719261079SEd Maste opt_array_append(defaultkey, 0, "AuthorizedKeysFiles", 42847dd1d1bSDag-Erling Smørgrav &options->authorized_keys_files, 42947dd1d1bSDag-Erling Smørgrav &options->num_authkeys_files, 43047dd1d1bSDag-Erling Smørgrav _PATH_SSH_USER_PERMITTED_KEYS); 43119261079SEd Maste opt_array_append(defaultkey, 0, "AuthorizedKeysFiles", 43247dd1d1bSDag-Erling Smørgrav &options->authorized_keys_files, 43347dd1d1bSDag-Erling Smørgrav &options->num_authkeys_files, 43447dd1d1bSDag-Erling Smørgrav _PATH_SSH_USER_PERMITTED_KEYS2); 435af12a3e7SDag-Erling Smørgrav } 436b74df5b2SDag-Erling Smørgrav if (options->permit_tun == -1) 437b74df5b2SDag-Erling Smørgrav options->permit_tun = SSH_TUNMODE_NO; 4384a421b63SDag-Erling Smørgrav if (options->ip_qos_interactive == -1) 439190cef3dSDag-Erling Smørgrav options->ip_qos_interactive = IPTOS_DSCP_AF21; 4404a421b63SDag-Erling Smørgrav if (options->ip_qos_bulk == -1) 441190cef3dSDag-Erling Smørgrav options->ip_qos_bulk = IPTOS_DSCP_CS1; 442462c32cbSDag-Erling Smørgrav if (options->version_addendum == NULL) 443462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 444a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 445a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = 0177; 446a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.streamlocal_bind_unlink == -1) 447a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_unlink = 0; 448bc5531deSDag-Erling Smørgrav if (options->fingerprint_hash == -1) 449bc5531deSDag-Erling Smørgrav options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 450ca86bcf2SDag-Erling Smørgrav if (options->disable_forwarding == -1) 451ca86bcf2SDag-Erling Smørgrav options->disable_forwarding = 0; 4524f52dfbbSDag-Erling Smørgrav if (options->expose_userauth_info == -1) 4534f52dfbbSDag-Erling Smørgrav options->expose_userauth_info = 0; 45419261079SEd Maste if (options->sk_provider == NULL) 45519261079SEd Maste options->sk_provider = xstrdup("internal"); 45638a52bd3SEd Maste if (options->required_rsa_size == -1) 45738a52bd3SEd Maste options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; 458*f374ba41SEd Maste if (options->unused_connection_timeout == -1) 459*f374ba41SEd Maste options->unused_connection_timeout = 0; 460b2af61ecSKurt Lidl if (options->use_blacklist == -1) 461b2af61ecSKurt Lidl options->use_blacklist = 0; 462eccfee6eSDag-Erling Smørgrav 463acc1a9efSDag-Erling Smørgrav assemble_algorithms(options); 464eccfee6eSDag-Erling Smørgrav 465acc1a9efSDag-Erling Smørgrav /* Turn privilege separation and sandboxing on by default */ 466462c32cbSDag-Erling Smørgrav if (use_privsep == -1) 4672b1970f3SDag-Erling Smørgrav use_privsep = PRIVSEP_ON; 468462c32cbSDag-Erling Smørgrav 469bc5531deSDag-Erling Smørgrav #define CLEAR_ON_NONE(v) \ 470bc5531deSDag-Erling Smørgrav do { \ 471bc5531deSDag-Erling Smørgrav if (option_clear_or_none(v)) { \ 472bc5531deSDag-Erling Smørgrav free(v); \ 473bc5531deSDag-Erling Smørgrav v = NULL; \ 474bc5531deSDag-Erling Smørgrav } \ 475bc5531deSDag-Erling Smørgrav } while(0) 476*f374ba41SEd Maste #define CLEAR_ON_NONE_ARRAY(v, nv, none) \ 477*f374ba41SEd Maste do { \ 478*f374ba41SEd Maste if (options->nv == 1 && \ 479*f374ba41SEd Maste strcasecmp(options->v[0], none) == 0) { \ 480*f374ba41SEd Maste free(options->v[0]); \ 481*f374ba41SEd Maste free(options->v); \ 482*f374ba41SEd Maste options->v = NULL; \ 483*f374ba41SEd Maste options->nv = 0; \ 484*f374ba41SEd Maste } \ 485*f374ba41SEd Maste } while (0) 486bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->pid_file); 487bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->xauth_location); 488bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->banner); 489bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->trusted_user_ca_keys); 490bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->revoked_keys_file); 49119261079SEd Maste CLEAR_ON_NONE(options->sk_provider); 492557f75e5SDag-Erling Smørgrav CLEAR_ON_NONE(options->authorized_principals_file); 493acc1a9efSDag-Erling Smørgrav CLEAR_ON_NONE(options->adm_forced_command); 494acc1a9efSDag-Erling Smørgrav CLEAR_ON_NONE(options->chroot_directory); 49547dd1d1bSDag-Erling Smørgrav CLEAR_ON_NONE(options->routing_domain); 49619261079SEd Maste CLEAR_ON_NONE(options->host_key_agent); 497*f374ba41SEd Maste 498bc5531deSDag-Erling Smørgrav for (i = 0; i < options->num_host_key_files; i++) 499bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->host_key_files[i]); 500bc5531deSDag-Erling Smørgrav for (i = 0; i < options->num_host_cert_files; i++) 501bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->host_cert_files[i]); 502bc5531deSDag-Erling Smørgrav 503*f374ba41SEd Maste CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); 504*f374ba41SEd Maste CLEAR_ON_NONE_ARRAY(auth_methods, num_auth_methods, "any"); 505*f374ba41SEd Maste #undef CLEAR_ON_NONE 506*f374ba41SEd Maste #undef CLEAR_ON_NONE_ARRAY 507511b41d2SMark Murray } 508511b41d2SMark Murray 509511b41d2SMark Murray /* Keyword tokens. */ 510511b41d2SMark Murray typedef enum { 511511b41d2SMark Murray sBadOption, /* == unknown option */ 512989dd127SDag-Erling Smørgrav /* Portable-specific options */ 513cf2b5f3bSDag-Erling Smørgrav sUsePAM, 514989dd127SDag-Erling Smørgrav /* Standard Options */ 515ca86bcf2SDag-Erling Smørgrav sPort, sHostKeyFile, sLoginGraceTime, 51619261079SEd Maste sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, 517af12a3e7SDag-Erling Smørgrav sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 518e9e8876aSEd Maste sKerberosGetAFSToken, sPasswordAuthentication, 519e9e8876aSEd Maste sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, 520ca3176e7SBrian Feldman sPrintMotd, sPrintLastLog, sIgnoreRhosts, 521af12a3e7SDag-Erling Smørgrav sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 522f7167e0eSDag-Erling Smørgrav sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, 523ca86bcf2SDag-Erling Smørgrav sPermitUserEnvironment, sAllowTcpForwarding, sCompression, 524e4a9863fSDag-Erling Smørgrav sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 52519261079SEd Maste sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sModuliFile, 52619261079SEd Maste sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms, 527bc5531deSDag-Erling Smørgrav sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, 528cf2b5f3bSDag-Erling Smørgrav sBanner, sUseDNS, sHostbasedAuthentication, 52919261079SEd Maste sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms, 53019261079SEd Maste sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, 531bc5531deSDag-Erling Smørgrav sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, 532557f75e5SDag-Erling Smørgrav sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 533190cef3dSDag-Erling Smørgrav sAcceptEnv, sSetEnv, sPermitTunnel, 534190cef3dSDag-Erling Smørgrav sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, 535d4af9e69SDag-Erling Smørgrav sUsePrivilegeSeparation, sAllowAgentForwarding, 53619261079SEd Maste sHostCertificate, sInclude, 537e2f6069cSDag-Erling Smørgrav sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 538557f75e5SDag-Erling Smørgrav sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, 5392f513db7SEd Maste sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, 5406888a9beSDag-Erling Smørgrav sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 541a0ee8cc6SDag-Erling Smørgrav sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, 542a0ee8cc6SDag-Erling Smørgrav sStreamLocalBindMask, sStreamLocalBindUnlink, 543ca86bcf2SDag-Erling Smørgrav sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, 54419261079SEd Maste sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, 545*f374ba41SEd Maste sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, 546b2af61ecSKurt Lidl sUseBlacklist, 547ca86bcf2SDag-Erling Smørgrav sDeprecated, sIgnore, sUnsupported 548511b41d2SMark Murray } ServerOpCodes; 549511b41d2SMark Murray 55019261079SEd Maste #define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */ 551333ee039SDag-Erling Smørgrav #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 552333ee039SDag-Erling Smørgrav #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 55319261079SEd Maste #define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ 55419261079SEd Maste #define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */ 555333ee039SDag-Erling Smørgrav 556511b41d2SMark Murray /* Textual representation of the tokens. */ 557511b41d2SMark Murray static struct { 558511b41d2SMark Murray const char *name; 559511b41d2SMark Murray ServerOpCodes opcode; 560333ee039SDag-Erling Smørgrav u_int flags; 561511b41d2SMark Murray } keywords[] = { 562989dd127SDag-Erling Smørgrav /* Portable-specific options */ 563cf2b5f3bSDag-Erling Smørgrav #ifdef USE_PAM 564333ee039SDag-Erling Smørgrav { "usepam", sUsePAM, SSHCFG_GLOBAL }, 565cf2b5f3bSDag-Erling Smørgrav #else 566333ee039SDag-Erling Smørgrav { "usepam", sUnsupported, SSHCFG_GLOBAL }, 567975616f0SDag-Erling Smørgrav #endif 568333ee039SDag-Erling Smørgrav { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, 569989dd127SDag-Erling Smørgrav /* Standard Options */ 570333ee039SDag-Erling Smørgrav { "port", sPort, SSHCFG_GLOBAL }, 571333ee039SDag-Erling Smørgrav { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 572333ee039SDag-Erling Smørgrav { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 573e4a9863fSDag-Erling Smørgrav { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, 574333ee039SDag-Erling Smørgrav { "pidfile", sPidFile, SSHCFG_GLOBAL }, 57519261079SEd Maste { "modulifile", sModuliFile, SSHCFG_GLOBAL }, 576ca86bcf2SDag-Erling Smørgrav { "serverkeybits", sDeprecated, SSHCFG_GLOBAL }, 577333ee039SDag-Erling Smørgrav { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 578ca86bcf2SDag-Erling Smørgrav { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL }, 579d4af9e69SDag-Erling Smørgrav { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, 580333ee039SDag-Erling Smørgrav { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 5814f52dfbbSDag-Erling Smørgrav { "loglevel", sLogLevel, SSHCFG_ALL }, 58219261079SEd Maste { "logverbose", sLogVerbose, SSHCFG_ALL }, 583333ee039SDag-Erling Smørgrav { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, 584ca86bcf2SDag-Erling Smørgrav { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL }, 585d4af9e69SDag-Erling Smørgrav { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, 586e2f6069cSDag-Erling Smørgrav { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, 58719261079SEd Maste { "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, 58819261079SEd Maste { "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ 589eccfee6eSDag-Erling Smørgrav { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, 590ca86bcf2SDag-Erling Smørgrav { "rsaauthentication", sDeprecated, SSHCFG_ALL }, 591d4af9e69SDag-Erling Smørgrav { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 59219261079SEd Maste { "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, 59319261079SEd Maste { "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ 59419261079SEd Maste { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL }, 595333ee039SDag-Erling Smørgrav { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 596cf2b5f3bSDag-Erling Smørgrav #ifdef KRB5 597d4af9e69SDag-Erling Smørgrav { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 598333ee039SDag-Erling Smørgrav { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 599333ee039SDag-Erling Smørgrav { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 6001ec0d754SDag-Erling Smørgrav #ifdef USE_AFS 601333ee039SDag-Erling Smørgrav { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, 6021ec0d754SDag-Erling Smørgrav #else 603333ee039SDag-Erling Smørgrav { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 6041ec0d754SDag-Erling Smørgrav #endif 605cf2b5f3bSDag-Erling Smørgrav #else 606d4af9e69SDag-Erling Smørgrav { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, 607333ee039SDag-Erling Smørgrav { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, 608333ee039SDag-Erling Smørgrav { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, 609333ee039SDag-Erling Smørgrav { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, 610cb96ab36SAssar Westerlund #endif 611333ee039SDag-Erling Smørgrav { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, 612333ee039SDag-Erling Smørgrav { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, 613cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI 614d4af9e69SDag-Erling Smørgrav { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 615333ee039SDag-Erling Smørgrav { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 616557f75e5SDag-Erling Smørgrav { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, 617cf2b5f3bSDag-Erling Smørgrav #else 618d4af9e69SDag-Erling Smørgrav { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, 619333ee039SDag-Erling Smørgrav { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 620557f75e5SDag-Erling Smørgrav { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, 621511b41d2SMark Murray #endif 622d4af9e69SDag-Erling Smørgrav { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 623d4af9e69SDag-Erling Smørgrav { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 62419261079SEd Maste { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ 62519261079SEd Maste { "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ 626333ee039SDag-Erling Smørgrav { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 627333ee039SDag-Erling Smørgrav { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 628333ee039SDag-Erling Smørgrav { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, 629333ee039SDag-Erling Smørgrav { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 630acc1a9efSDag-Erling Smørgrav #ifdef DISABLE_LASTLOG 631acc1a9efSDag-Erling Smørgrav { "printlastlog", sUnsupported, SSHCFG_GLOBAL }, 632acc1a9efSDag-Erling Smørgrav #else 633333ee039SDag-Erling Smørgrav { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 634acc1a9efSDag-Erling Smørgrav #endif 63519261079SEd Maste { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL }, 636333ee039SDag-Erling Smørgrav { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 637333ee039SDag-Erling Smørgrav { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 638333ee039SDag-Erling Smørgrav { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 639333ee039SDag-Erling Smørgrav { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 640333ee039SDag-Erling Smørgrav { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 641333ee039SDag-Erling Smørgrav { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 642cce7d346SDag-Erling Smørgrav { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, 643333ee039SDag-Erling Smørgrav { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 644ca86bcf2SDag-Erling Smørgrav { "uselogin", sDeprecated, SSHCFG_GLOBAL }, 645333ee039SDag-Erling Smørgrav { "compression", sCompression, SSHCFG_GLOBAL }, 646e4a9863fSDag-Erling Smørgrav { "rekeylimit", sRekeyLimit, SSHCFG_ALL }, 647333ee039SDag-Erling Smørgrav { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, 648333ee039SDag-Erling Smørgrav { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ 649333ee039SDag-Erling Smørgrav { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 650d4af9e69SDag-Erling Smørgrav { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, 651462c32cbSDag-Erling Smørgrav { "allowusers", sAllowUsers, SSHCFG_ALL }, 652462c32cbSDag-Erling Smørgrav { "denyusers", sDenyUsers, SSHCFG_ALL }, 653462c32cbSDag-Erling Smørgrav { "allowgroups", sAllowGroups, SSHCFG_ALL }, 654462c32cbSDag-Erling Smørgrav { "denygroups", sDenyGroups, SSHCFG_ALL }, 655333ee039SDag-Erling Smørgrav { "ciphers", sCiphers, SSHCFG_GLOBAL }, 656333ee039SDag-Erling Smørgrav { "macs", sMacs, SSHCFG_GLOBAL }, 657ca86bcf2SDag-Erling Smørgrav { "protocol", sIgnore, SSHCFG_GLOBAL }, 658333ee039SDag-Erling Smørgrav { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 659333ee039SDag-Erling Smørgrav { "subsystem", sSubsystem, SSHCFG_GLOBAL }, 660333ee039SDag-Erling Smørgrav { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 66119261079SEd Maste { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL }, 66219261079SEd Maste { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL }, 663d4af9e69SDag-Erling Smørgrav { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, 664d4af9e69SDag-Erling Smørgrav { "maxsessions", sMaxSessions, SSHCFG_ALL }, 665d4af9e69SDag-Erling Smørgrav { "banner", sBanner, SSHCFG_ALL }, 666333ee039SDag-Erling Smørgrav { "usedns", sUseDNS, SSHCFG_GLOBAL }, 667333ee039SDag-Erling Smørgrav { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, 668333ee039SDag-Erling Smørgrav { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, 669ca86bcf2SDag-Erling Smørgrav { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL }, 670ca86bcf2SDag-Erling Smørgrav { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL }, 671e2f6069cSDag-Erling Smørgrav { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, 672e146993eSDag-Erling Smørgrav { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, 673d93a896eSDag-Erling Smørgrav { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL}, 674462c32cbSDag-Erling Smørgrav { "acceptenv", sAcceptEnv, SSHCFG_ALL }, 675190cef3dSDag-Erling Smørgrav { "setenv", sSetEnv, SSHCFG_ALL }, 676e2f6069cSDag-Erling Smørgrav { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 677f7167e0eSDag-Erling Smørgrav { "permittty", sPermitTTY, SSHCFG_ALL }, 678a0ee8cc6SDag-Erling Smørgrav { "permituserrc", sPermitUserRC, SSHCFG_ALL }, 679333ee039SDag-Erling Smørgrav { "match", sMatch, SSHCFG_ALL }, 680333ee039SDag-Erling Smørgrav { "permitopen", sPermitOpen, SSHCFG_ALL }, 681190cef3dSDag-Erling Smørgrav { "permitlisten", sPermitListen, SSHCFG_ALL }, 682333ee039SDag-Erling Smørgrav { "forcecommand", sForceCommand, SSHCFG_ALL }, 683d4af9e69SDag-Erling Smørgrav { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 684b15c8340SDag-Erling Smørgrav { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, 685b15c8340SDag-Erling Smørgrav { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, 686b15c8340SDag-Erling Smørgrav { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, 687e2f6069cSDag-Erling Smørgrav { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, 6884a421b63SDag-Erling Smørgrav { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, 68919261079SEd Maste { "include", sInclude, SSHCFG_ALL }, 6904a421b63SDag-Erling Smørgrav { "ipqos", sIPQoS, SSHCFG_ALL }, 6916888a9beSDag-Erling Smørgrav { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, 6926888a9beSDag-Erling Smørgrav { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 693557f75e5SDag-Erling Smørgrav { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL }, 694557f75e5SDag-Erling Smørgrav { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL }, 695462c32cbSDag-Erling Smørgrav { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 6966888a9beSDag-Erling Smørgrav { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 697a0ee8cc6SDag-Erling Smørgrav { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, 698a0ee8cc6SDag-Erling Smørgrav { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, 699a0ee8cc6SDag-Erling Smørgrav { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, 700bc5531deSDag-Erling Smørgrav { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, 701ca86bcf2SDag-Erling Smørgrav { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, 7024f52dfbbSDag-Erling Smørgrav { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, 70347dd1d1bSDag-Erling Smørgrav { "rdomain", sRDomain, SSHCFG_ALL }, 7042f513db7SEd Maste { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, 70519261079SEd Maste { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, 70638a52bd3SEd Maste { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, 707*f374ba41SEd Maste { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, 708*f374ba41SEd Maste { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, 709b2af61ecSKurt Lidl { "useblacklist", sUseBlacklist, SSHCFG_GLOBAL }, 710e426c743SEd Maste { "useblocklist", sUseBlacklist, SSHCFG_GLOBAL }, /* alias */ 7116f351346SDag-Erling Smørgrav { "noneenabled", sUnsupported, SSHCFG_ALL }, 7129860d96eSDag-Erling Smørgrav { "hpndisabled", sDeprecated, SSHCFG_ALL }, 7139860d96eSDag-Erling Smørgrav { "hpnbuffersize", sDeprecated, SSHCFG_ALL }, 7149860d96eSDag-Erling Smørgrav { "tcprcvbufpoll", sDeprecated, SSHCFG_ALL }, 715333ee039SDag-Erling Smørgrav { NULL, sBadOption, 0 } 716511b41d2SMark Murray }; 717511b41d2SMark Murray 718d4af9e69SDag-Erling Smørgrav static struct { 719d4af9e69SDag-Erling Smørgrav int val; 720d4af9e69SDag-Erling Smørgrav char *text; 721d4af9e69SDag-Erling Smørgrav } tunmode_desc[] = { 722d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_NO, "no" }, 723d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_POINTOPOINT, "point-to-point" }, 724d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_ETHERNET, "ethernet" }, 725d4af9e69SDag-Erling Smørgrav { SSH_TUNMODE_YES, "yes" }, 726d4af9e69SDag-Erling Smørgrav { -1, NULL } 727d4af9e69SDag-Erling Smørgrav }; 728d4af9e69SDag-Erling Smørgrav 729190cef3dSDag-Erling Smørgrav /* Returns an opcode name from its number */ 730190cef3dSDag-Erling Smørgrav 731190cef3dSDag-Erling Smørgrav static const char * 732190cef3dSDag-Erling Smørgrav lookup_opcode_name(ServerOpCodes code) 733190cef3dSDag-Erling Smørgrav { 734190cef3dSDag-Erling Smørgrav u_int i; 735190cef3dSDag-Erling Smørgrav 736190cef3dSDag-Erling Smørgrav for (i = 0; keywords[i].name != NULL; i++) 737190cef3dSDag-Erling Smørgrav if (keywords[i].opcode == code) 738190cef3dSDag-Erling Smørgrav return(keywords[i].name); 739190cef3dSDag-Erling Smørgrav return "UNKNOWN"; 740190cef3dSDag-Erling Smørgrav } 741190cef3dSDag-Erling Smørgrav 742190cef3dSDag-Erling Smørgrav 743511b41d2SMark Murray /* 744ca3176e7SBrian Feldman * Returns the number of the token pointed to by cp or sBadOption. 745511b41d2SMark Murray */ 746511b41d2SMark Murray 747511b41d2SMark Murray static ServerOpCodes 748511b41d2SMark Murray parse_token(const char *cp, const char *filename, 749333ee039SDag-Erling Smørgrav int linenum, u_int *flags) 750511b41d2SMark Murray { 751ca3176e7SBrian Feldman u_int i; 752511b41d2SMark Murray 753511b41d2SMark Murray for (i = 0; keywords[i].name; i++) 754333ee039SDag-Erling Smørgrav if (strcasecmp(cp, keywords[i].name) == 0) { 755333ee039SDag-Erling Smørgrav *flags = keywords[i].flags; 756511b41d2SMark Murray return keywords[i].opcode; 757333ee039SDag-Erling Smørgrav } 758511b41d2SMark Murray 759ca3176e7SBrian Feldman error("%s: line %d: Bad configuration option: %s", 760511b41d2SMark Murray filename, linenum, cp); 761511b41d2SMark Murray return sBadOption; 762511b41d2SMark Murray } 763511b41d2SMark Murray 764b15c8340SDag-Erling Smørgrav char * 765b15c8340SDag-Erling Smørgrav derelativise_path(const char *path) 766b15c8340SDag-Erling Smørgrav { 767bc5531deSDag-Erling Smørgrav char *expanded, *ret, cwd[PATH_MAX]; 768b15c8340SDag-Erling Smørgrav 769bc5531deSDag-Erling Smørgrav if (strcasecmp(path, "none") == 0) 770bc5531deSDag-Erling Smørgrav return xstrdup("none"); 771b15c8340SDag-Erling Smørgrav expanded = tilde_expand_filename(path, getuid()); 77219261079SEd Maste if (path_absolute(expanded)) 773b15c8340SDag-Erling Smørgrav return expanded; 7748ad9b54aSDag-Erling Smørgrav if (getcwd(cwd, sizeof(cwd)) == NULL) 77519261079SEd Maste fatal_f("getcwd: %s", strerror(errno)); 776b15c8340SDag-Erling Smørgrav xasprintf(&ret, "%s/%s", cwd, expanded); 777e4a9863fSDag-Erling Smørgrav free(expanded); 778b15c8340SDag-Erling Smørgrav return ret; 779b15c8340SDag-Erling Smørgrav } 780b15c8340SDag-Erling Smørgrav 781af12a3e7SDag-Erling Smørgrav static void 78247dd1d1bSDag-Erling Smørgrav add_listen_addr(ServerOptions *options, const char *addr, 78347dd1d1bSDag-Erling Smørgrav const char *rdomain, int port) 784511b41d2SMark Murray { 785d4ecd108SDag-Erling Smørgrav u_int i; 786511b41d2SMark Murray 78747dd1d1bSDag-Erling Smørgrav if (port > 0) 78847dd1d1bSDag-Erling Smørgrav add_one_listen_addr(options, addr, rdomain, port); 78947dd1d1bSDag-Erling Smørgrav else { 79047dd1d1bSDag-Erling Smørgrav for (i = 0; i < options->num_ports; i++) { 79147dd1d1bSDag-Erling Smørgrav add_one_listen_addr(options, addr, rdomain, 79247dd1d1bSDag-Erling Smørgrav options->ports[i]); 79347dd1d1bSDag-Erling Smørgrav } 79447dd1d1bSDag-Erling Smørgrav } 795ca3176e7SBrian Feldman } 796ca3176e7SBrian Feldman 797af12a3e7SDag-Erling Smørgrav static void 79847dd1d1bSDag-Erling Smørgrav add_one_listen_addr(ServerOptions *options, const char *addr, 79947dd1d1bSDag-Erling Smørgrav const char *rdomain, int port) 800ca3176e7SBrian Feldman { 801ca3176e7SBrian Feldman struct addrinfo hints, *ai, *aitop; 802ca3176e7SBrian Feldman char strport[NI_MAXSERV]; 803ca3176e7SBrian Feldman int gaierr; 80447dd1d1bSDag-Erling Smørgrav u_int i; 80547dd1d1bSDag-Erling Smørgrav 80647dd1d1bSDag-Erling Smørgrav /* Find listen_addrs entry for this rdomain */ 80747dd1d1bSDag-Erling Smørgrav for (i = 0; i < options->num_listen_addrs; i++) { 80847dd1d1bSDag-Erling Smørgrav if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL) 80947dd1d1bSDag-Erling Smørgrav break; 81047dd1d1bSDag-Erling Smørgrav if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL) 81147dd1d1bSDag-Erling Smørgrav continue; 81247dd1d1bSDag-Erling Smørgrav if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0) 81347dd1d1bSDag-Erling Smørgrav break; 81447dd1d1bSDag-Erling Smørgrav } 81547dd1d1bSDag-Erling Smørgrav if (i >= options->num_listen_addrs) { 81647dd1d1bSDag-Erling Smørgrav /* No entry for this rdomain; allocate one */ 81747dd1d1bSDag-Erling Smørgrav if (i >= INT_MAX) 81819261079SEd Maste fatal_f("too many listen addresses"); 81947dd1d1bSDag-Erling Smørgrav options->listen_addrs = xrecallocarray(options->listen_addrs, 82047dd1d1bSDag-Erling Smørgrav options->num_listen_addrs, options->num_listen_addrs + 1, 82147dd1d1bSDag-Erling Smørgrav sizeof(*options->listen_addrs)); 82247dd1d1bSDag-Erling Smørgrav i = options->num_listen_addrs++; 82347dd1d1bSDag-Erling Smørgrav if (rdomain != NULL) 82447dd1d1bSDag-Erling Smørgrav options->listen_addrs[i].rdomain = xstrdup(rdomain); 82547dd1d1bSDag-Erling Smørgrav } 82647dd1d1bSDag-Erling Smørgrav /* options->listen_addrs[i] points to the addresses for this rdomain */ 827ca3176e7SBrian Feldman 828511b41d2SMark Murray memset(&hints, 0, sizeof(hints)); 829aa49c926SDag-Erling Smørgrav hints.ai_family = options->address_family; 830511b41d2SMark Murray hints.ai_socktype = SOCK_STREAM; 831511b41d2SMark Murray hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 832cce7d346SDag-Erling Smørgrav snprintf(strport, sizeof strport, "%d", port); 833511b41d2SMark Murray if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 834ca3176e7SBrian Feldman fatal("bad addr or host: %s (%s)", 835511b41d2SMark Murray addr ? addr : "<NULL>", 836d4af9e69SDag-Erling Smørgrav ssh_gai_strerror(gaierr)); 837511b41d2SMark Murray for (ai = aitop; ai->ai_next; ai = ai->ai_next) 838511b41d2SMark Murray ; 83947dd1d1bSDag-Erling Smørgrav ai->ai_next = options->listen_addrs[i].addrs; 84047dd1d1bSDag-Erling Smørgrav options->listen_addrs[i].addrs = aitop; 84147dd1d1bSDag-Erling Smørgrav } 84247dd1d1bSDag-Erling Smørgrav 84347dd1d1bSDag-Erling Smørgrav /* Returns nonzero if the routing domain name is valid */ 84447dd1d1bSDag-Erling Smørgrav static int 84547dd1d1bSDag-Erling Smørgrav valid_rdomain(const char *name) 84647dd1d1bSDag-Erling Smørgrav { 84747dd1d1bSDag-Erling Smørgrav #if defined(HAVE_SYS_VALID_RDOMAIN) 84847dd1d1bSDag-Erling Smørgrav return sys_valid_rdomain(name); 84947dd1d1bSDag-Erling Smørgrav #elif defined(__OpenBSD__) 85047dd1d1bSDag-Erling Smørgrav const char *errstr; 85147dd1d1bSDag-Erling Smørgrav long long num; 85247dd1d1bSDag-Erling Smørgrav struct rt_tableinfo info; 85347dd1d1bSDag-Erling Smørgrav int mib[6]; 85447dd1d1bSDag-Erling Smørgrav size_t miblen = sizeof(mib); 85547dd1d1bSDag-Erling Smørgrav 85647dd1d1bSDag-Erling Smørgrav if (name == NULL) 85747dd1d1bSDag-Erling Smørgrav return 1; 85847dd1d1bSDag-Erling Smørgrav 85947dd1d1bSDag-Erling Smørgrav num = strtonum(name, 0, 255, &errstr); 86047dd1d1bSDag-Erling Smørgrav if (errstr != NULL) 86147dd1d1bSDag-Erling Smørgrav return 0; 86247dd1d1bSDag-Erling Smørgrav 86347dd1d1bSDag-Erling Smørgrav /* Check whether the table actually exists */ 86447dd1d1bSDag-Erling Smørgrav memset(mib, 0, sizeof(mib)); 86547dd1d1bSDag-Erling Smørgrav mib[0] = CTL_NET; 86647dd1d1bSDag-Erling Smørgrav mib[1] = PF_ROUTE; 86747dd1d1bSDag-Erling Smørgrav mib[4] = NET_RT_TABLE; 86847dd1d1bSDag-Erling Smørgrav mib[5] = (int)num; 86947dd1d1bSDag-Erling Smørgrav if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1) 87047dd1d1bSDag-Erling Smørgrav return 0; 87147dd1d1bSDag-Erling Smørgrav 87247dd1d1bSDag-Erling Smørgrav return 1; 87347dd1d1bSDag-Erling Smørgrav #else /* defined(__OpenBSD__) */ 87447dd1d1bSDag-Erling Smørgrav error("Routing domains are not supported on this platform"); 87547dd1d1bSDag-Erling Smørgrav return 0; 87647dd1d1bSDag-Erling Smørgrav #endif 877511b41d2SMark Murray } 878511b41d2SMark Murray 879557f75e5SDag-Erling Smørgrav /* 880557f75e5SDag-Erling Smørgrav * Queue a ListenAddress to be processed once we have all of the Ports 881557f75e5SDag-Erling Smørgrav * and AddressFamily options. 882557f75e5SDag-Erling Smørgrav */ 883557f75e5SDag-Erling Smørgrav static void 88447dd1d1bSDag-Erling Smørgrav queue_listen_addr(ServerOptions *options, const char *addr, 88547dd1d1bSDag-Erling Smørgrav const char *rdomain, int port) 886557f75e5SDag-Erling Smørgrav { 88747dd1d1bSDag-Erling Smørgrav struct queued_listenaddr *qla; 88847dd1d1bSDag-Erling Smørgrav 88947dd1d1bSDag-Erling Smørgrav options->queued_listen_addrs = xrecallocarray( 89047dd1d1bSDag-Erling Smørgrav options->queued_listen_addrs, 89147dd1d1bSDag-Erling Smørgrav options->num_queued_listens, options->num_queued_listens + 1, 89247dd1d1bSDag-Erling Smørgrav sizeof(*options->queued_listen_addrs)); 89347dd1d1bSDag-Erling Smørgrav qla = &options->queued_listen_addrs[options->num_queued_listens++]; 89447dd1d1bSDag-Erling Smørgrav qla->addr = xstrdup(addr); 89547dd1d1bSDag-Erling Smørgrav qla->port = port; 89647dd1d1bSDag-Erling Smørgrav qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain); 897557f75e5SDag-Erling Smørgrav } 898557f75e5SDag-Erling Smørgrav 899557f75e5SDag-Erling Smørgrav /* 900557f75e5SDag-Erling Smørgrav * Process queued (text) ListenAddress entries. 901557f75e5SDag-Erling Smørgrav */ 902557f75e5SDag-Erling Smørgrav static void 903557f75e5SDag-Erling Smørgrav process_queued_listen_addrs(ServerOptions *options) 904557f75e5SDag-Erling Smørgrav { 905557f75e5SDag-Erling Smørgrav u_int i; 90647dd1d1bSDag-Erling Smørgrav struct queued_listenaddr *qla; 907557f75e5SDag-Erling Smørgrav 908557f75e5SDag-Erling Smørgrav if (options->num_ports == 0) 909557f75e5SDag-Erling Smørgrav options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 910557f75e5SDag-Erling Smørgrav if (options->address_family == -1) 911557f75e5SDag-Erling Smørgrav options->address_family = AF_UNSPEC; 912557f75e5SDag-Erling Smørgrav 913557f75e5SDag-Erling Smørgrav for (i = 0; i < options->num_queued_listens; i++) { 91447dd1d1bSDag-Erling Smørgrav qla = &options->queued_listen_addrs[i]; 91547dd1d1bSDag-Erling Smørgrav add_listen_addr(options, qla->addr, qla->rdomain, qla->port); 91647dd1d1bSDag-Erling Smørgrav free(qla->addr); 91747dd1d1bSDag-Erling Smørgrav free(qla->rdomain); 918557f75e5SDag-Erling Smørgrav } 919557f75e5SDag-Erling Smørgrav free(options->queued_listen_addrs); 920557f75e5SDag-Erling Smørgrav options->queued_listen_addrs = NULL; 921557f75e5SDag-Erling Smørgrav options->num_queued_listens = 0; 922557f75e5SDag-Erling Smørgrav } 923557f75e5SDag-Erling Smørgrav 9244f52dfbbSDag-Erling Smørgrav /* 925190cef3dSDag-Erling Smørgrav * Inform channels layer of permitopen options for a single forwarding 926190cef3dSDag-Erling Smørgrav * direction (local/remote). 927190cef3dSDag-Erling Smørgrav */ 928190cef3dSDag-Erling Smørgrav static void 929190cef3dSDag-Erling Smørgrav process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode, 930190cef3dSDag-Erling Smørgrav char **opens, u_int num_opens) 931190cef3dSDag-Erling Smørgrav { 932190cef3dSDag-Erling Smørgrav u_int i; 933190cef3dSDag-Erling Smørgrav int port; 9341323ec57SEd Maste char *host, *arg, *oarg; 935190cef3dSDag-Erling Smørgrav int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE; 936190cef3dSDag-Erling Smørgrav const char *what = lookup_opcode_name(opcode); 937190cef3dSDag-Erling Smørgrav 938190cef3dSDag-Erling Smørgrav channel_clear_permission(ssh, FORWARD_ADM, where); 939190cef3dSDag-Erling Smørgrav if (num_opens == 0) 940190cef3dSDag-Erling Smørgrav return; /* permit any */ 941190cef3dSDag-Erling Smørgrav 942190cef3dSDag-Erling Smørgrav /* handle keywords: "any" / "none" */ 943190cef3dSDag-Erling Smørgrav if (num_opens == 1 && strcmp(opens[0], "any") == 0) 944190cef3dSDag-Erling Smørgrav return; 945190cef3dSDag-Erling Smørgrav if (num_opens == 1 && strcmp(opens[0], "none") == 0) { 946190cef3dSDag-Erling Smørgrav channel_disable_admin(ssh, where); 947190cef3dSDag-Erling Smørgrav return; 948190cef3dSDag-Erling Smørgrav } 949190cef3dSDag-Erling Smørgrav /* Otherwise treat it as a list of permitted host:port */ 950190cef3dSDag-Erling Smørgrav for (i = 0; i < num_opens; i++) { 951190cef3dSDag-Erling Smørgrav oarg = arg = xstrdup(opens[i]); 9521323ec57SEd Maste host = hpdelim(&arg); 9531323ec57SEd Maste if (host == NULL) 95419261079SEd Maste fatal_f("missing host in %s", what); 955190cef3dSDag-Erling Smørgrav host = cleanhostname(host); 956190cef3dSDag-Erling Smørgrav if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 95719261079SEd Maste fatal_f("bad port number in %s", what); 958190cef3dSDag-Erling Smørgrav /* Send it to channels layer */ 959190cef3dSDag-Erling Smørgrav channel_add_permission(ssh, FORWARD_ADM, 960190cef3dSDag-Erling Smørgrav where, host, port); 961190cef3dSDag-Erling Smørgrav free(oarg); 962190cef3dSDag-Erling Smørgrav } 963190cef3dSDag-Erling Smørgrav } 964190cef3dSDag-Erling Smørgrav 965190cef3dSDag-Erling Smørgrav /* 9664f52dfbbSDag-Erling Smørgrav * Inform channels layer of permitopen options from configuration. 9674f52dfbbSDag-Erling Smørgrav */ 9684f52dfbbSDag-Erling Smørgrav void 9694f52dfbbSDag-Erling Smørgrav process_permitopen(struct ssh *ssh, ServerOptions *options) 9704f52dfbbSDag-Erling Smørgrav { 971190cef3dSDag-Erling Smørgrav process_permitopen_list(ssh, sPermitOpen, 972190cef3dSDag-Erling Smørgrav options->permitted_opens, options->num_permitted_opens); 973190cef3dSDag-Erling Smørgrav process_permitopen_list(ssh, sPermitListen, 974190cef3dSDag-Erling Smørgrav options->permitted_listens, 975190cef3dSDag-Erling Smørgrav options->num_permitted_listens); 9764f52dfbbSDag-Erling Smørgrav } 9774f52dfbbSDag-Erling Smørgrav 978*f374ba41SEd Maste /* Parse a ChannelTimeout clause "pattern=interval" */ 979*f374ba41SEd Maste static int 980*f374ba41SEd Maste parse_timeout(const char *s, char **typep, u_int *secsp) 981*f374ba41SEd Maste { 982*f374ba41SEd Maste char *cp, *sdup; 983*f374ba41SEd Maste int secs; 984*f374ba41SEd Maste 985*f374ba41SEd Maste if (typep != NULL) 986*f374ba41SEd Maste *typep = NULL; 987*f374ba41SEd Maste if (secsp != NULL) 988*f374ba41SEd Maste *secsp = 0; 989*f374ba41SEd Maste if (s == NULL) 990*f374ba41SEd Maste return -1; 991*f374ba41SEd Maste sdup = xstrdup(s); 992*f374ba41SEd Maste 993*f374ba41SEd Maste if ((cp = strchr(sdup, '=')) == NULL || cp == sdup) { 994*f374ba41SEd Maste free(sdup); 995*f374ba41SEd Maste return -1; 996*f374ba41SEd Maste } 997*f374ba41SEd Maste *cp++ = '\0'; 998*f374ba41SEd Maste if ((secs = convtime(cp)) < 0) { 999*f374ba41SEd Maste free(sdup); 1000*f374ba41SEd Maste return -1; 1001*f374ba41SEd Maste } 1002*f374ba41SEd Maste /* success */ 1003*f374ba41SEd Maste if (typep != NULL) 1004*f374ba41SEd Maste *typep = xstrdup(sdup); 1005*f374ba41SEd Maste if (secsp != NULL) 1006*f374ba41SEd Maste *secsp = (u_int)secs; 1007*f374ba41SEd Maste free(sdup); 1008*f374ba41SEd Maste return 0; 1009*f374ba41SEd Maste } 1010*f374ba41SEd Maste 1011*f374ba41SEd Maste void 1012*f374ba41SEd Maste process_channel_timeouts(struct ssh *ssh, ServerOptions *options) 1013*f374ba41SEd Maste { 1014*f374ba41SEd Maste u_int i, secs; 1015*f374ba41SEd Maste char *type; 1016*f374ba41SEd Maste 1017*f374ba41SEd Maste debug3_f("setting %u timeouts", options->num_channel_timeouts); 1018*f374ba41SEd Maste channel_clear_timeouts(ssh); 1019*f374ba41SEd Maste for (i = 0; i < options->num_channel_timeouts; i++) { 1020*f374ba41SEd Maste if (parse_timeout(options->channel_timeouts[i], 1021*f374ba41SEd Maste &type, &secs) != 0) { 1022*f374ba41SEd Maste fatal_f("internal error: bad timeout %s", 1023*f374ba41SEd Maste options->channel_timeouts[i]); 1024*f374ba41SEd Maste } 1025*f374ba41SEd Maste channel_add_timeout(ssh, type, secs); 1026*f374ba41SEd Maste free(type); 1027*f374ba41SEd Maste } 1028*f374ba41SEd Maste } 1029*f374ba41SEd Maste 1030462c32cbSDag-Erling Smørgrav struct connection_info * 103119261079SEd Maste get_connection_info(struct ssh *ssh, int populate, int use_dns) 1032462c32cbSDag-Erling Smørgrav { 1033462c32cbSDag-Erling Smørgrav static struct connection_info ci; 1034462c32cbSDag-Erling Smørgrav 103519261079SEd Maste if (ssh == NULL || !populate) 1036462c32cbSDag-Erling Smørgrav return &ci; 1037076ad2f8SDag-Erling Smørgrav ci.host = auth_get_canonical_hostname(ssh, use_dns); 1038076ad2f8SDag-Erling Smørgrav ci.address = ssh_remote_ipaddr(ssh); 1039076ad2f8SDag-Erling Smørgrav ci.laddress = ssh_local_ipaddr(ssh); 1040076ad2f8SDag-Erling Smørgrav ci.lport = ssh_local_port(ssh); 104147dd1d1bSDag-Erling Smørgrav ci.rdomain = ssh_packet_rdomain_in(ssh); 1042462c32cbSDag-Erling Smørgrav return &ci; 1043462c32cbSDag-Erling Smørgrav } 1044462c32cbSDag-Erling Smørgrav 1045333ee039SDag-Erling Smørgrav /* 1046333ee039SDag-Erling Smørgrav * The strategy for the Match blocks is that the config file is parsed twice. 1047333ee039SDag-Erling Smørgrav * 1048333ee039SDag-Erling Smørgrav * The first time is at startup. activep is initialized to 1 and the 1049333ee039SDag-Erling Smørgrav * directives in the global context are processed and acted on. Hitting a 1050333ee039SDag-Erling Smørgrav * Match directive unsets activep and the directives inside the block are 1051333ee039SDag-Erling Smørgrav * checked for syntax only. 1052333ee039SDag-Erling Smørgrav * 1053333ee039SDag-Erling Smørgrav * The second time is after a connection has been established but before 1054333ee039SDag-Erling Smørgrav * authentication. activep is initialized to 2 and global config directives 1055333ee039SDag-Erling Smørgrav * are ignored since they have already been processed. If the criteria in a 1056333ee039SDag-Erling Smørgrav * Match block is met, activep is set and the subsequent directives 1057333ee039SDag-Erling Smørgrav * processed and actioned until EOF or another Match block unsets it. Any 1058333ee039SDag-Erling Smørgrav * options set are copied into the main server config. 1059333ee039SDag-Erling Smørgrav * 1060333ee039SDag-Erling Smørgrav * Potential additions/improvements: 1061ca86bcf2SDag-Erling Smørgrav * - Add Match support for pre-kex directives, eg. Ciphers. 1062333ee039SDag-Erling Smørgrav * 1063333ee039SDag-Erling Smørgrav * - Add a Tag directive (idea from David Leonard) ala pf, eg: 1064333ee039SDag-Erling Smørgrav * Match Address 192.168.0.* 1065333ee039SDag-Erling Smørgrav * Tag trusted 1066333ee039SDag-Erling Smørgrav * Match Group wheel 1067333ee039SDag-Erling Smørgrav * Tag trusted 1068333ee039SDag-Erling Smørgrav * Match Tag trusted 1069333ee039SDag-Erling Smørgrav * AllowTcpForwarding yes 1070333ee039SDag-Erling Smørgrav * GatewayPorts clientspecified 1071333ee039SDag-Erling Smørgrav * [...] 1072333ee039SDag-Erling Smørgrav * 1073333ee039SDag-Erling Smørgrav * - Add a PermittedChannelRequests directive 1074333ee039SDag-Erling Smørgrav * Match Group shell 1075333ee039SDag-Erling Smørgrav * PermittedChannelRequests session,forwarded-tcpip 1076333ee039SDag-Erling Smørgrav */ 1077333ee039SDag-Erling Smørgrav 1078333ee039SDag-Erling Smørgrav static int 1079333ee039SDag-Erling Smørgrav match_cfg_line_group(const char *grps, int line, const char *user) 1080333ee039SDag-Erling Smørgrav { 1081333ee039SDag-Erling Smørgrav int result = 0; 1082333ee039SDag-Erling Smørgrav struct passwd *pw; 1083333ee039SDag-Erling Smørgrav 1084333ee039SDag-Erling Smørgrav if (user == NULL) 1085333ee039SDag-Erling Smørgrav goto out; 1086333ee039SDag-Erling Smørgrav 1087333ee039SDag-Erling Smørgrav if ((pw = getpwnam(user)) == NULL) { 1088333ee039SDag-Erling Smørgrav debug("Can't match group at line %d because user %.100s does " 1089333ee039SDag-Erling Smørgrav "not exist", line, user); 1090333ee039SDag-Erling Smørgrav } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 1091333ee039SDag-Erling Smørgrav debug("Can't Match group because user %.100s not in any group " 1092333ee039SDag-Erling Smørgrav "at line %d", user, line); 1093d4af9e69SDag-Erling Smørgrav } else if (ga_match_pattern_list(grps) != 1) { 1094d4af9e69SDag-Erling Smørgrav debug("user %.100s does not match group list %.100s at line %d", 1095d4af9e69SDag-Erling Smørgrav user, grps, line); 1096333ee039SDag-Erling Smørgrav } else { 1097d4af9e69SDag-Erling Smørgrav debug("user %.100s matched group list %.100s at line %d", user, 1098d4af9e69SDag-Erling Smørgrav grps, line); 1099333ee039SDag-Erling Smørgrav result = 1; 1100333ee039SDag-Erling Smørgrav } 1101333ee039SDag-Erling Smørgrav out: 1102333ee039SDag-Erling Smørgrav ga_free(); 1103333ee039SDag-Erling Smørgrav return result; 1104333ee039SDag-Erling Smørgrav } 1105333ee039SDag-Erling Smørgrav 110647dd1d1bSDag-Erling Smørgrav static void 110747dd1d1bSDag-Erling Smørgrav match_test_missing_fatal(const char *criteria, const char *attrib) 110847dd1d1bSDag-Erling Smørgrav { 110947dd1d1bSDag-Erling Smørgrav fatal("'Match %s' in configuration but '%s' not in connection " 111047dd1d1bSDag-Erling Smørgrav "test specification.", criteria, attrib); 111147dd1d1bSDag-Erling Smørgrav } 111247dd1d1bSDag-Erling Smørgrav 1113462c32cbSDag-Erling Smørgrav /* 11146888a9beSDag-Erling Smørgrav * All of the attributes on a single Match line are ANDed together, so we need 1115f7167e0eSDag-Erling Smørgrav * to check every attribute and set the result to zero if any attribute does 11166888a9beSDag-Erling Smørgrav * not match. 1117462c32cbSDag-Erling Smørgrav */ 1118333ee039SDag-Erling Smørgrav static int 1119462c32cbSDag-Erling Smørgrav match_cfg_line(char **condition, int line, struct connection_info *ci) 1120333ee039SDag-Erling Smørgrav { 1121f7167e0eSDag-Erling Smørgrav int result = 1, attributes = 0, port; 1122333ee039SDag-Erling Smørgrav char *arg, *attrib, *cp = *condition; 1123333ee039SDag-Erling Smørgrav 1124462c32cbSDag-Erling Smørgrav if (ci == NULL) 1125333ee039SDag-Erling Smørgrav debug3("checking syntax for 'Match %s'", cp); 1126333ee039SDag-Erling Smørgrav else 1127462c32cbSDag-Erling Smørgrav debug3("checking match for '%s' user %s host %s addr %s " 1128462c32cbSDag-Erling Smørgrav "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", 1129462c32cbSDag-Erling Smørgrav ci->host ? ci->host : "(null)", 1130462c32cbSDag-Erling Smørgrav ci->address ? ci->address : "(null)", 1131462c32cbSDag-Erling Smørgrav ci->laddress ? ci->laddress : "(null)", ci->lport); 1132333ee039SDag-Erling Smørgrav 1133333ee039SDag-Erling Smørgrav while ((attrib = strdelim(&cp)) && *attrib != '\0') { 113419261079SEd Maste /* Terminate on comment */ 113519261079SEd Maste if (*attrib == '#') { 113619261079SEd Maste cp = NULL; /* mark all arguments consumed */ 113719261079SEd Maste break; 113819261079SEd Maste } 113919261079SEd Maste arg = NULL; 1140f7167e0eSDag-Erling Smørgrav attributes++; 114119261079SEd Maste /* Criterion "all" has no argument and must appear alone */ 1142f7167e0eSDag-Erling Smørgrav if (strcasecmp(attrib, "all") == 0) { 114319261079SEd Maste if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && 114419261079SEd Maste *arg != '\0' && *arg != '#')) { 1145f7167e0eSDag-Erling Smørgrav error("'all' cannot be combined with other " 1146f7167e0eSDag-Erling Smørgrav "Match attributes"); 1147f7167e0eSDag-Erling Smørgrav return -1; 1148f7167e0eSDag-Erling Smørgrav } 114919261079SEd Maste if (arg != NULL && *arg == '#') 115019261079SEd Maste cp = NULL; /* mark all arguments consumed */ 1151f7167e0eSDag-Erling Smørgrav *condition = cp; 1152f7167e0eSDag-Erling Smørgrav return 1; 1153f7167e0eSDag-Erling Smørgrav } 115419261079SEd Maste /* All other criteria require an argument */ 115519261079SEd Maste if ((arg = strdelim(&cp)) == NULL || 115619261079SEd Maste *arg == '\0' || *arg == '#') { 1157333ee039SDag-Erling Smørgrav error("Missing Match criteria for %s", attrib); 1158333ee039SDag-Erling Smørgrav return -1; 1159333ee039SDag-Erling Smørgrav } 1160333ee039SDag-Erling Smørgrav if (strcasecmp(attrib, "user") == 0) { 116119261079SEd Maste if (ci == NULL || (ci->test && ci->user == NULL)) { 1162333ee039SDag-Erling Smørgrav result = 0; 1163333ee039SDag-Erling Smørgrav continue; 1164333ee039SDag-Erling Smørgrav } 116547dd1d1bSDag-Erling Smørgrav if (ci->user == NULL) 116647dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("User", "user"); 116719261079SEd Maste if (match_usergroup_pattern_list(ci->user, arg) != 1) 1168333ee039SDag-Erling Smørgrav result = 0; 1169333ee039SDag-Erling Smørgrav else 1170333ee039SDag-Erling Smørgrav debug("user %.100s matched 'User %.100s' at " 1171462c32cbSDag-Erling Smørgrav "line %d", ci->user, arg, line); 1172333ee039SDag-Erling Smørgrav } else if (strcasecmp(attrib, "group") == 0) { 117319261079SEd Maste if (ci == NULL || (ci->test && ci->user == NULL)) { 1174462c32cbSDag-Erling Smørgrav result = 0; 1175462c32cbSDag-Erling Smørgrav continue; 1176462c32cbSDag-Erling Smørgrav } 117747dd1d1bSDag-Erling Smørgrav if (ci->user == NULL) 117847dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("Group", "user"); 1179462c32cbSDag-Erling Smørgrav switch (match_cfg_line_group(arg, line, ci->user)) { 1180333ee039SDag-Erling Smørgrav case -1: 1181333ee039SDag-Erling Smørgrav return -1; 1182333ee039SDag-Erling Smørgrav case 0: 1183333ee039SDag-Erling Smørgrav result = 0; 1184333ee039SDag-Erling Smørgrav } 1185333ee039SDag-Erling Smørgrav } else if (strcasecmp(attrib, "host") == 0) { 118619261079SEd Maste if (ci == NULL || (ci->test && ci->host == NULL)) { 1187333ee039SDag-Erling Smørgrav result = 0; 1188333ee039SDag-Erling Smørgrav continue; 1189333ee039SDag-Erling Smørgrav } 119047dd1d1bSDag-Erling Smørgrav if (ci->host == NULL) 119147dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("Host", "host"); 1192557f75e5SDag-Erling Smørgrav if (match_hostname(ci->host, arg) != 1) 1193333ee039SDag-Erling Smørgrav result = 0; 1194333ee039SDag-Erling Smørgrav else 1195333ee039SDag-Erling Smørgrav debug("connection from %.100s matched 'Host " 1196462c32cbSDag-Erling Smørgrav "%.100s' at line %d", ci->host, arg, line); 1197333ee039SDag-Erling Smørgrav } else if (strcasecmp(attrib, "address") == 0) { 119819261079SEd Maste if (ci == NULL || (ci->test && ci->address == NULL)) { 119919261079SEd Maste if (addr_match_list(NULL, arg) != 0) 120019261079SEd Maste fatal("Invalid Match address argument " 120119261079SEd Maste "'%s' at line %d", arg, line); 1202462c32cbSDag-Erling Smørgrav result = 0; 1203462c32cbSDag-Erling Smørgrav continue; 1204462c32cbSDag-Erling Smørgrav } 120547dd1d1bSDag-Erling Smørgrav if (ci->address == NULL) 120647dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("Address", "addr"); 1207462c32cbSDag-Erling Smørgrav switch (addr_match_list(ci->address, arg)) { 1208d4af9e69SDag-Erling Smørgrav case 1: 1209333ee039SDag-Erling Smørgrav debug("connection from %.100s matched 'Address " 1210462c32cbSDag-Erling Smørgrav "%.100s' at line %d", ci->address, arg, line); 1211d4af9e69SDag-Erling Smørgrav break; 1212d4af9e69SDag-Erling Smørgrav case 0: 1213d4af9e69SDag-Erling Smørgrav case -1: 1214d4af9e69SDag-Erling Smørgrav result = 0; 1215d4af9e69SDag-Erling Smørgrav break; 1216d4af9e69SDag-Erling Smørgrav case -2: 1217d4af9e69SDag-Erling Smørgrav return -1; 1218d4af9e69SDag-Erling Smørgrav } 1219462c32cbSDag-Erling Smørgrav } else if (strcasecmp(attrib, "localaddress") == 0){ 122019261079SEd Maste if (ci == NULL || (ci->test && ci->laddress == NULL)) { 122119261079SEd Maste if (addr_match_list(NULL, arg) != 0) 122219261079SEd Maste fatal("Invalid Match localaddress " 122319261079SEd Maste "argument '%s' at line %d", arg, 122419261079SEd Maste line); 1225462c32cbSDag-Erling Smørgrav result = 0; 1226462c32cbSDag-Erling Smørgrav continue; 1227462c32cbSDag-Erling Smørgrav } 122847dd1d1bSDag-Erling Smørgrav if (ci->laddress == NULL) 122947dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("LocalAddress", 123047dd1d1bSDag-Erling Smørgrav "laddr"); 1231462c32cbSDag-Erling Smørgrav switch (addr_match_list(ci->laddress, arg)) { 1232462c32cbSDag-Erling Smørgrav case 1: 1233462c32cbSDag-Erling Smørgrav debug("connection from %.100s matched " 1234462c32cbSDag-Erling Smørgrav "'LocalAddress %.100s' at line %d", 1235462c32cbSDag-Erling Smørgrav ci->laddress, arg, line); 1236462c32cbSDag-Erling Smørgrav break; 1237462c32cbSDag-Erling Smørgrav case 0: 1238462c32cbSDag-Erling Smørgrav case -1: 1239462c32cbSDag-Erling Smørgrav result = 0; 1240462c32cbSDag-Erling Smørgrav break; 1241462c32cbSDag-Erling Smørgrav case -2: 1242462c32cbSDag-Erling Smørgrav return -1; 1243462c32cbSDag-Erling Smørgrav } 1244462c32cbSDag-Erling Smørgrav } else if (strcasecmp(attrib, "localport") == 0) { 1245462c32cbSDag-Erling Smørgrav if ((port = a2port(arg)) == -1) { 1246462c32cbSDag-Erling Smørgrav error("Invalid LocalPort '%s' on Match line", 1247462c32cbSDag-Erling Smørgrav arg); 1248462c32cbSDag-Erling Smørgrav return -1; 1249462c32cbSDag-Erling Smørgrav } 125019261079SEd Maste if (ci == NULL || (ci->test && ci->lport == -1)) { 1251462c32cbSDag-Erling Smørgrav result = 0; 1252462c32cbSDag-Erling Smørgrav continue; 1253462c32cbSDag-Erling Smørgrav } 125447dd1d1bSDag-Erling Smørgrav if (ci->lport == 0) 125547dd1d1bSDag-Erling Smørgrav match_test_missing_fatal("LocalPort", "lport"); 1256462c32cbSDag-Erling Smørgrav /* TODO support port lists */ 1257462c32cbSDag-Erling Smørgrav if (port == ci->lport) 1258462c32cbSDag-Erling Smørgrav debug("connection from %.100s matched " 1259462c32cbSDag-Erling Smørgrav "'LocalPort %d' at line %d", 1260462c32cbSDag-Erling Smørgrav ci->laddress, port, line); 1261462c32cbSDag-Erling Smørgrav else 1262462c32cbSDag-Erling Smørgrav result = 0; 126347dd1d1bSDag-Erling Smørgrav } else if (strcasecmp(attrib, "rdomain") == 0) { 126419261079SEd Maste if (ci == NULL || (ci->test && ci->rdomain == NULL)) { 126547dd1d1bSDag-Erling Smørgrav result = 0; 126647dd1d1bSDag-Erling Smørgrav continue; 126747dd1d1bSDag-Erling Smørgrav } 126819261079SEd Maste if (ci->rdomain == NULL) 126919261079SEd Maste match_test_missing_fatal("RDomain", "rdomain"); 127047dd1d1bSDag-Erling Smørgrav if (match_pattern_list(ci->rdomain, arg, 0) != 1) 127147dd1d1bSDag-Erling Smørgrav result = 0; 127247dd1d1bSDag-Erling Smørgrav else 127347dd1d1bSDag-Erling Smørgrav debug("user %.100s matched 'RDomain %.100s' at " 127447dd1d1bSDag-Erling Smørgrav "line %d", ci->rdomain, arg, line); 1275333ee039SDag-Erling Smørgrav } else { 1276333ee039SDag-Erling Smørgrav error("Unsupported Match attribute %s", attrib); 1277333ee039SDag-Erling Smørgrav return -1; 1278333ee039SDag-Erling Smørgrav } 1279333ee039SDag-Erling Smørgrav } 1280f7167e0eSDag-Erling Smørgrav if (attributes == 0) { 1281f7167e0eSDag-Erling Smørgrav error("One or more attributes required for Match"); 1282f7167e0eSDag-Erling Smørgrav return -1; 1283f7167e0eSDag-Erling Smørgrav } 1284462c32cbSDag-Erling Smørgrav if (ci != NULL) 1285333ee039SDag-Erling Smørgrav debug3("match %sfound", result ? "" : "not "); 1286333ee039SDag-Erling Smørgrav *condition = cp; 1287333ee039SDag-Erling Smørgrav return result; 1288333ee039SDag-Erling Smørgrav } 1289333ee039SDag-Erling Smørgrav 1290333ee039SDag-Erling Smørgrav #define WHITESPACE " \t\r\n" 1291333ee039SDag-Erling Smørgrav 1292e146993eSDag-Erling Smørgrav /* Multistate option parsing */ 1293e146993eSDag-Erling Smørgrav struct multistate { 1294e146993eSDag-Erling Smørgrav char *key; 1295e146993eSDag-Erling Smørgrav int value; 1296e146993eSDag-Erling Smørgrav }; 129747dd1d1bSDag-Erling Smørgrav static const struct multistate multistate_flag[] = { 129847dd1d1bSDag-Erling Smørgrav { "yes", 1 }, 129947dd1d1bSDag-Erling Smørgrav { "no", 0 }, 130047dd1d1bSDag-Erling Smørgrav { NULL, -1 } 130147dd1d1bSDag-Erling Smørgrav }; 130219261079SEd Maste static const struct multistate multistate_ignore_rhosts[] = { 130319261079SEd Maste { "yes", IGNORE_RHOSTS_YES }, 130419261079SEd Maste { "no", IGNORE_RHOSTS_NO }, 130519261079SEd Maste { "shosts-only", IGNORE_RHOSTS_SHOSTS }, 130619261079SEd Maste { NULL, -1 } 130719261079SEd Maste }; 1308e146993eSDag-Erling Smørgrav static const struct multistate multistate_addressfamily[] = { 1309e146993eSDag-Erling Smørgrav { "inet", AF_INET }, 1310e146993eSDag-Erling Smørgrav { "inet6", AF_INET6 }, 1311e146993eSDag-Erling Smørgrav { "any", AF_UNSPEC }, 1312e146993eSDag-Erling Smørgrav { NULL, -1 } 1313e146993eSDag-Erling Smørgrav }; 1314e146993eSDag-Erling Smørgrav static const struct multistate multistate_permitrootlogin[] = { 1315e146993eSDag-Erling Smørgrav { "without-password", PERMIT_NO_PASSWD }, 1316eccfee6eSDag-Erling Smørgrav { "prohibit-password", PERMIT_NO_PASSWD }, 1317e146993eSDag-Erling Smørgrav { "forced-commands-only", PERMIT_FORCED_ONLY }, 1318e146993eSDag-Erling Smørgrav { "yes", PERMIT_YES }, 1319e146993eSDag-Erling Smørgrav { "no", PERMIT_NO }, 1320e146993eSDag-Erling Smørgrav { NULL, -1 } 1321e146993eSDag-Erling Smørgrav }; 1322e146993eSDag-Erling Smørgrav static const struct multistate multistate_compression[] = { 132319261079SEd Maste #ifdef WITH_ZLIB 1324ca86bcf2SDag-Erling Smørgrav { "yes", COMP_DELAYED }, 1325e146993eSDag-Erling Smørgrav { "delayed", COMP_DELAYED }, 132619261079SEd Maste #endif 1327e146993eSDag-Erling Smørgrav { "no", COMP_NONE }, 1328e146993eSDag-Erling Smørgrav { NULL, -1 } 1329e146993eSDag-Erling Smørgrav }; 1330e146993eSDag-Erling Smørgrav static const struct multistate multistate_gatewayports[] = { 1331e146993eSDag-Erling Smørgrav { "clientspecified", 2 }, 1332e146993eSDag-Erling Smørgrav { "yes", 1 }, 1333e146993eSDag-Erling Smørgrav { "no", 0 }, 1334e146993eSDag-Erling Smørgrav { NULL, -1 } 1335e146993eSDag-Erling Smørgrav }; 13366888a9beSDag-Erling Smørgrav static const struct multistate multistate_tcpfwd[] = { 13376888a9beSDag-Erling Smørgrav { "yes", FORWARD_ALLOW }, 13386888a9beSDag-Erling Smørgrav { "all", FORWARD_ALLOW }, 13396888a9beSDag-Erling Smørgrav { "no", FORWARD_DENY }, 13406888a9beSDag-Erling Smørgrav { "remote", FORWARD_REMOTE }, 13416888a9beSDag-Erling Smørgrav { "local", FORWARD_LOCAL }, 13426888a9beSDag-Erling Smørgrav { NULL, -1 } 13436888a9beSDag-Erling Smørgrav }; 1344e146993eSDag-Erling Smørgrav 134519261079SEd Maste static int 134619261079SEd Maste process_server_config_line_depth(ServerOptions *options, char *line, 1347462c32cbSDag-Erling Smørgrav const char *filename, int linenum, int *activep, 134819261079SEd Maste struct connection_info *connectinfo, int *inc_flags, int depth, 134919261079SEd Maste struct include_list *includes) 1350511b41d2SMark Murray { 13511323ec57SEd Maste char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword; 135219261079SEd Maste int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found; 1353d4af9e69SDag-Erling Smørgrav SyslogFacility *log_facility_ptr; 1354d4af9e69SDag-Erling Smørgrav LogLevel *log_level_ptr; 1355511b41d2SMark Murray ServerOpCodes opcode; 1356190cef3dSDag-Erling Smørgrav u_int i, *uintptr, uvalue, flags = 0; 1357333ee039SDag-Erling Smørgrav size_t len; 1358e4a9863fSDag-Erling Smørgrav long long val64; 1359e146993eSDag-Erling Smørgrav const struct multistate *multistate_ptr; 136047dd1d1bSDag-Erling Smørgrav const char *errstr; 136119261079SEd Maste struct include_item *item; 136219261079SEd Maste glob_t gbuf; 136319261079SEd Maste char **oav = NULL, **av; 136419261079SEd Maste int oac = 0, ac; 136519261079SEd Maste int ret = -1; 1366511b41d2SMark Murray 1367d93a896eSDag-Erling Smørgrav /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ 1368d93a896eSDag-Erling Smørgrav if ((len = strlen(line)) == 0) 1369d93a896eSDag-Erling Smørgrav return 0; 1370d93a896eSDag-Erling Smørgrav for (len--; len > 0; len--) { 1371d93a896eSDag-Erling Smørgrav if (strchr(WHITESPACE "\f", line[len]) == NULL) 1372d93a896eSDag-Erling Smørgrav break; 1373d93a896eSDag-Erling Smørgrav line[len] = '\0'; 1374d93a896eSDag-Erling Smørgrav } 1375d93a896eSDag-Erling Smørgrav 137619261079SEd Maste str = line; 137719261079SEd Maste if ((keyword = strdelim(&str)) == NULL) 1378333ee039SDag-Erling Smørgrav return 0; 1379c2d3a559SKris Kennaway /* Ignore leading whitespace */ 138019261079SEd Maste if (*keyword == '\0') 138119261079SEd Maste keyword = strdelim(&str); 138219261079SEd Maste if (!keyword || !*keyword || *keyword == '#') 1383af12a3e7SDag-Erling Smørgrav return 0; 138419261079SEd Maste if (str == NULL || *str == '\0') { 138519261079SEd Maste error("%s line %d: no argument after keyword \"%s\"", 138619261079SEd Maste filename, linenum, keyword); 138719261079SEd Maste return -1; 138819261079SEd Maste } 1389ca3176e7SBrian Feldman intptr = NULL; 1390ca3176e7SBrian Feldman charptr = NULL; 139119261079SEd Maste opcode = parse_token(keyword, filename, linenum, &flags); 139219261079SEd Maste 139319261079SEd Maste if (argv_split(str, &oac, &oav, 1) != 0) { 139419261079SEd Maste error("%s line %d: invalid quotes", filename, linenum); 139519261079SEd Maste return -1; 139619261079SEd Maste } 139719261079SEd Maste ac = oac; 139819261079SEd Maste av = oav; 1399333ee039SDag-Erling Smørgrav 1400333ee039SDag-Erling Smørgrav if (activep == NULL) { /* We are processing a command line directive */ 1401333ee039SDag-Erling Smørgrav cmdline = 1; 1402333ee039SDag-Erling Smørgrav activep = &cmdline; 1403333ee039SDag-Erling Smørgrav } 140419261079SEd Maste if (*activep && opcode != sMatch && opcode != sInclude) 140519261079SEd Maste debug3("%s:%d setting %s %s", filename, linenum, keyword, str); 1406333ee039SDag-Erling Smørgrav if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 1407462c32cbSDag-Erling Smørgrav if (connectinfo == NULL) { 1408333ee039SDag-Erling Smørgrav fatal("%s line %d: Directive '%s' is not allowed " 140919261079SEd Maste "within a Match block", filename, linenum, keyword); 1410333ee039SDag-Erling Smørgrav } else { /* this is a directive we have already processed */ 141119261079SEd Maste ret = 0; 141219261079SEd Maste goto out; 1413333ee039SDag-Erling Smørgrav } 1414333ee039SDag-Erling Smørgrav } 1415333ee039SDag-Erling Smørgrav 1416511b41d2SMark Murray switch (opcode) { 1417989dd127SDag-Erling Smørgrav /* Portable-specific options */ 1418cf2b5f3bSDag-Erling Smørgrav case sUsePAM: 1419cf2b5f3bSDag-Erling Smørgrav intptr = &options->use_pam; 1420989dd127SDag-Erling Smørgrav goto parse_flag; 1421989dd127SDag-Erling Smørgrav 1422989dd127SDag-Erling Smørgrav /* Standard Options */ 1423511b41d2SMark Murray case sBadOption: 142419261079SEd Maste goto out; 1425511b41d2SMark Murray case sPort: 1426511b41d2SMark Murray /* ignore ports from configfile if cmdline specifies ports */ 142719261079SEd Maste if (options->ports_from_cmdline) { 142819261079SEd Maste argv_consume(&ac); 142919261079SEd Maste break; 143019261079SEd Maste } 1431511b41d2SMark Murray if (options->num_ports >= MAX_PORTS) 1432ca3176e7SBrian Feldman fatal("%s line %d: too many ports.", 1433511b41d2SMark Murray filename, linenum); 143419261079SEd Maste arg = argv_next(&ac, &av); 1435c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1436ca3176e7SBrian Feldman fatal("%s line %d: missing port number.", 1437511b41d2SMark Murray filename, linenum); 1438ca3176e7SBrian Feldman options->ports[options->num_ports++] = a2port(arg); 1439cce7d346SDag-Erling Smørgrav if (options->ports[options->num_ports-1] <= 0) 1440ca3176e7SBrian Feldman fatal("%s line %d: Badly formatted port number.", 1441ca3176e7SBrian Feldman filename, linenum); 1442511b41d2SMark Murray break; 1443511b41d2SMark Murray 1444511b41d2SMark Murray case sLoginGraceTime: 1445511b41d2SMark Murray intptr = &options->login_grace_time; 1446af12a3e7SDag-Erling Smørgrav parse_time: 144719261079SEd Maste arg = argv_next(&ac, &av); 1448af12a3e7SDag-Erling Smørgrav if (!arg || *arg == '\0') 1449af12a3e7SDag-Erling Smørgrav fatal("%s line %d: missing time value.", 1450af12a3e7SDag-Erling Smørgrav filename, linenum); 1451af12a3e7SDag-Erling Smørgrav if ((value = convtime(arg)) == -1) 1452af12a3e7SDag-Erling Smørgrav fatal("%s line %d: invalid time value.", 1453af12a3e7SDag-Erling Smørgrav filename, linenum); 1454557f75e5SDag-Erling Smørgrav if (*activep && *intptr == -1) 1455af12a3e7SDag-Erling Smørgrav *intptr = value; 1456af12a3e7SDag-Erling Smørgrav break; 1457511b41d2SMark Murray 1458511b41d2SMark Murray case sListenAddress: 145919261079SEd Maste arg = argv_next(&ac, &av); 1460aa49c926SDag-Erling Smørgrav if (arg == NULL || *arg == '\0') 1461aa49c926SDag-Erling Smørgrav fatal("%s line %d: missing address", 1462511b41d2SMark Murray filename, linenum); 1463d4ecd108SDag-Erling Smørgrav /* check for bare IPv6 address: no "[]" and 2 or more ":" */ 1464d4ecd108SDag-Erling Smørgrav if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL 1465d4ecd108SDag-Erling Smørgrav && strchr(p+1, ':') != NULL) { 146647dd1d1bSDag-Erling Smørgrav port = 0; 146747dd1d1bSDag-Erling Smørgrav p = arg; 146847dd1d1bSDag-Erling Smørgrav } else { 146919261079SEd Maste arg2 = NULL; 14701323ec57SEd Maste p = hpdelim(&arg); 14711323ec57SEd Maste if (p == NULL) 1472aa49c926SDag-Erling Smørgrav fatal("%s line %d: bad address:port usage", 1473ca3176e7SBrian Feldman filename, linenum); 1474aa49c926SDag-Erling Smørgrav p = cleanhostname(p); 1475aa49c926SDag-Erling Smørgrav if (arg == NULL) 1476aa49c926SDag-Erling Smørgrav port = 0; 1477cce7d346SDag-Erling Smørgrav else if ((port = a2port(arg)) <= 0) 147847dd1d1bSDag-Erling Smørgrav fatal("%s line %d: bad port number", 147947dd1d1bSDag-Erling Smørgrav filename, linenum); 148047dd1d1bSDag-Erling Smørgrav } 148147dd1d1bSDag-Erling Smørgrav /* Optional routing table */ 148247dd1d1bSDag-Erling Smørgrav arg2 = NULL; 148319261079SEd Maste if ((arg = argv_next(&ac, &av)) != NULL) { 148447dd1d1bSDag-Erling Smørgrav if (strcmp(arg, "rdomain") != 0 || 148519261079SEd Maste (arg2 = argv_next(&ac, &av)) == NULL) 148647dd1d1bSDag-Erling Smørgrav fatal("%s line %d: bad ListenAddress syntax", 148747dd1d1bSDag-Erling Smørgrav filename, linenum); 148847dd1d1bSDag-Erling Smørgrav if (!valid_rdomain(arg2)) 148947dd1d1bSDag-Erling Smørgrav fatal("%s line %d: bad routing domain", 149047dd1d1bSDag-Erling Smørgrav filename, linenum); 149147dd1d1bSDag-Erling Smørgrav } 149247dd1d1bSDag-Erling Smørgrav queue_listen_addr(options, p, arg2, port); 1493aa49c926SDag-Erling Smørgrav 1494aa49c926SDag-Erling Smørgrav break; 1495aa49c926SDag-Erling Smørgrav 1496aa49c926SDag-Erling Smørgrav case sAddressFamily: 1497e146993eSDag-Erling Smørgrav intptr = &options->address_family; 1498e146993eSDag-Erling Smørgrav multistate_ptr = multistate_addressfamily; 1499e146993eSDag-Erling Smørgrav parse_multistate: 150019261079SEd Maste arg = argv_next(&ac, &av); 1501d4ecd108SDag-Erling Smørgrav if (!arg || *arg == '\0') 1502e146993eSDag-Erling Smørgrav fatal("%s line %d: missing argument.", 1503d4ecd108SDag-Erling Smørgrav filename, linenum); 1504e146993eSDag-Erling Smørgrav value = -1; 1505e146993eSDag-Erling Smørgrav for (i = 0; multistate_ptr[i].key != NULL; i++) { 1506e146993eSDag-Erling Smørgrav if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 1507e146993eSDag-Erling Smørgrav value = multistate_ptr[i].value; 1508e146993eSDag-Erling Smørgrav break; 1509e146993eSDag-Erling Smørgrav } 1510e146993eSDag-Erling Smørgrav } 1511e146993eSDag-Erling Smørgrav if (value == -1) 1512e146993eSDag-Erling Smørgrav fatal("%s line %d: unsupported option \"%s\".", 1513aa49c926SDag-Erling Smørgrav filename, linenum, arg); 1514e146993eSDag-Erling Smørgrav if (*activep && *intptr == -1) 1515aa49c926SDag-Erling Smørgrav *intptr = value; 1516511b41d2SMark Murray break; 1517511b41d2SMark Murray 1518511b41d2SMark Murray case sHostKeyFile: 151919261079SEd Maste arg = argv_next(&ac, &av); 1520ca3176e7SBrian Feldman if (!arg || *arg == '\0') 1521ca3176e7SBrian Feldman fatal("%s line %d: missing file name.", 1522e8aafc91SKris Kennaway filename, linenum); 152319261079SEd Maste if (*activep) { 152419261079SEd Maste servconf_add_hostkey(filename, linenum, 152519261079SEd Maste options, arg, 1); 152619261079SEd Maste } 1527e8aafc91SKris Kennaway break; 1528e8aafc91SKris Kennaway 1529e4a9863fSDag-Erling Smørgrav case sHostKeyAgent: 1530e4a9863fSDag-Erling Smørgrav charptr = &options->host_key_agent; 153119261079SEd Maste arg = argv_next(&ac, &av); 1532e4a9863fSDag-Erling Smørgrav if (!arg || *arg == '\0') 1533e4a9863fSDag-Erling Smørgrav fatal("%s line %d: missing socket name.", 1534e4a9863fSDag-Erling Smørgrav filename, linenum); 1535e4a9863fSDag-Erling Smørgrav if (*activep && *charptr == NULL) 1536e4a9863fSDag-Erling Smørgrav *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? 1537e4a9863fSDag-Erling Smørgrav xstrdup(arg) : derelativise_path(arg); 1538e4a9863fSDag-Erling Smørgrav break; 1539e4a9863fSDag-Erling Smørgrav 1540b15c8340SDag-Erling Smørgrav case sHostCertificate: 154119261079SEd Maste arg = argv_next(&ac, &av); 154247dd1d1bSDag-Erling Smørgrav if (!arg || *arg == '\0') 154347dd1d1bSDag-Erling Smørgrav fatal("%s line %d: missing file name.", 154447dd1d1bSDag-Erling Smørgrav filename, linenum); 154547dd1d1bSDag-Erling Smørgrav if (*activep) 154647dd1d1bSDag-Erling Smørgrav servconf_add_hostcert(filename, linenum, options, arg); 154747dd1d1bSDag-Erling Smørgrav break; 1548b15c8340SDag-Erling Smørgrav 1549e8aafc91SKris Kennaway case sPidFile: 1550e8aafc91SKris Kennaway charptr = &options->pid_file; 155147dd1d1bSDag-Erling Smørgrav parse_filename: 155219261079SEd Maste arg = argv_next(&ac, &av); 155347dd1d1bSDag-Erling Smørgrav if (!arg || *arg == '\0') 155447dd1d1bSDag-Erling Smørgrav fatal("%s line %d: missing file name.", 155547dd1d1bSDag-Erling Smørgrav filename, linenum); 155647dd1d1bSDag-Erling Smørgrav if (*activep && *charptr == NULL) { 155747dd1d1bSDag-Erling Smørgrav *charptr = derelativise_path(arg); 155847dd1d1bSDag-Erling Smørgrav /* increase optional counter */ 155947dd1d1bSDag-Erling Smørgrav if (intptr != NULL) 156047dd1d1bSDag-Erling Smørgrav *intptr = *intptr + 1; 156147dd1d1bSDag-Erling Smørgrav } 156247dd1d1bSDag-Erling Smørgrav break; 1563511b41d2SMark Murray 156419261079SEd Maste case sModuliFile: 156519261079SEd Maste charptr = &options->moduli_file; 156619261079SEd Maste goto parse_filename; 156719261079SEd Maste 1568511b41d2SMark Murray case sPermitRootLogin: 1569511b41d2SMark Murray intptr = &options->permit_root_login; 1570e146993eSDag-Erling Smørgrav multistate_ptr = multistate_permitrootlogin; 1571e146993eSDag-Erling Smørgrav goto parse_multistate; 1572511b41d2SMark Murray 1573511b41d2SMark Murray case sIgnoreRhosts: 1574511b41d2SMark Murray intptr = &options->ignore_rhosts; 157519261079SEd Maste multistate_ptr = multistate_ignore_rhosts; 157647dd1d1bSDag-Erling Smørgrav goto parse_multistate; 1577511b41d2SMark Murray 1578511b41d2SMark Murray case sIgnoreUserKnownHosts: 1579511b41d2SMark Murray intptr = &options->ignore_user_known_hosts; 158019261079SEd Maste parse_flag: 158119261079SEd Maste multistate_ptr = multistate_flag; 158219261079SEd Maste goto parse_multistate; 1583511b41d2SMark Murray 1584ca3176e7SBrian Feldman case sHostbasedAuthentication: 1585ca3176e7SBrian Feldman intptr = &options->hostbased_authentication; 1586ca3176e7SBrian Feldman goto parse_flag; 1587ca3176e7SBrian Feldman 1588ca3176e7SBrian Feldman case sHostbasedUsesNameFromPacketOnly: 1589ca3176e7SBrian Feldman intptr = &options->hostbased_uses_name_from_packet_only; 1590ca3176e7SBrian Feldman goto parse_flag; 1591ca3176e7SBrian Feldman 159219261079SEd Maste case sHostbasedAcceptedAlgorithms: 159319261079SEd Maste charptr = &options->hostbased_accepted_algos; 159419261079SEd Maste parse_pubkey_algos: 159519261079SEd Maste arg = argv_next(&ac, &av); 1596bc5531deSDag-Erling Smørgrav if (!arg || *arg == '\0') 1597bc5531deSDag-Erling Smørgrav fatal("%s line %d: Missing argument.", 1598bc5531deSDag-Erling Smørgrav filename, linenum); 1599d93a896eSDag-Erling Smørgrav if (*arg != '-' && 160019261079SEd Maste !sshkey_names_valid2(*arg == '+' || *arg == '^' ? 160119261079SEd Maste arg + 1 : arg, 1)) 1602bc5531deSDag-Erling Smørgrav fatal("%s line %d: Bad key types '%s'.", 1603bc5531deSDag-Erling Smørgrav filename, linenum, arg ? arg : "<NONE>"); 1604bc5531deSDag-Erling Smørgrav if (*activep && *charptr == NULL) 1605bc5531deSDag-Erling Smørgrav *charptr = xstrdup(arg); 1606bc5531deSDag-Erling Smørgrav break; 1607bc5531deSDag-Erling Smørgrav 1608eccfee6eSDag-Erling Smørgrav case sHostKeyAlgorithms: 1609eccfee6eSDag-Erling Smørgrav charptr = &options->hostkeyalgorithms; 161019261079SEd Maste goto parse_pubkey_algos; 1611eccfee6eSDag-Erling Smørgrav 16122f513db7SEd Maste case sCASignatureAlgorithms: 16132f513db7SEd Maste charptr = &options->ca_sign_algorithms; 161419261079SEd Maste goto parse_pubkey_algos; 16152f513db7SEd Maste 1616ca3176e7SBrian Feldman case sPubkeyAuthentication: 1617ca3176e7SBrian Feldman intptr = &options->pubkey_authentication; 1618e8aafc91SKris Kennaway goto parse_flag; 1619cf2b5f3bSDag-Erling Smørgrav 162019261079SEd Maste case sPubkeyAcceptedAlgorithms: 162119261079SEd Maste charptr = &options->pubkey_accepted_algos; 162219261079SEd Maste goto parse_pubkey_algos; 162319261079SEd Maste 162419261079SEd Maste case sPubkeyAuthOptions: 162519261079SEd Maste intptr = &options->pubkey_auth_options; 162619261079SEd Maste value = 0; 162719261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 162819261079SEd Maste if (strcasecmp(arg, "none") == 0) 162919261079SEd Maste continue; 163019261079SEd Maste if (strcasecmp(arg, "touch-required") == 0) 163119261079SEd Maste value |= PUBKEYAUTH_TOUCH_REQUIRED; 163219261079SEd Maste else if (strcasecmp(arg, "verify-required") == 0) 163319261079SEd Maste value |= PUBKEYAUTH_VERIFY_REQUIRED; 163419261079SEd Maste else { 163519261079SEd Maste error("%s line %d: unsupported %s option %s", 163619261079SEd Maste filename, linenum, keyword, arg); 163719261079SEd Maste goto out; 163819261079SEd Maste } 163919261079SEd Maste } 164019261079SEd Maste if (*activep && *intptr == -1) 164119261079SEd Maste *intptr = value; 164219261079SEd Maste break; 1643bc5531deSDag-Erling Smørgrav 1644cb96ab36SAssar Westerlund case sKerberosAuthentication: 1645cb96ab36SAssar Westerlund intptr = &options->kerberos_authentication; 1646511b41d2SMark Murray goto parse_flag; 1647511b41d2SMark Murray 1648af12a3e7SDag-Erling Smørgrav case sKerberosOrLocalPasswd: 1649af12a3e7SDag-Erling Smørgrav intptr = &options->kerberos_or_local_passwd; 1650511b41d2SMark Murray goto parse_flag; 1651511b41d2SMark Murray 1652af12a3e7SDag-Erling Smørgrav case sKerberosTicketCleanup: 1653af12a3e7SDag-Erling Smørgrav intptr = &options->kerberos_ticket_cleanup; 1654511b41d2SMark Murray goto parse_flag; 1655cf2b5f3bSDag-Erling Smørgrav 16561ec0d754SDag-Erling Smørgrav case sKerberosGetAFSToken: 16571ec0d754SDag-Erling Smørgrav intptr = &options->kerberos_get_afs_token; 16581ec0d754SDag-Erling Smørgrav goto parse_flag; 16591ec0d754SDag-Erling Smørgrav 1660cf2b5f3bSDag-Erling Smørgrav case sGssAuthentication: 1661cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_authentication; 1662fe5fd017SMark Murray goto parse_flag; 1663cf2b5f3bSDag-Erling Smørgrav 1664cf2b5f3bSDag-Erling Smørgrav case sGssCleanupCreds: 1665cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_cleanup_creds; 1666511b41d2SMark Murray goto parse_flag; 1667511b41d2SMark Murray 1668557f75e5SDag-Erling Smørgrav case sGssStrictAcceptor: 1669557f75e5SDag-Erling Smørgrav intptr = &options->gss_strict_acceptor; 1670557f75e5SDag-Erling Smørgrav goto parse_flag; 1671557f75e5SDag-Erling Smørgrav 1672511b41d2SMark Murray case sPasswordAuthentication: 1673511b41d2SMark Murray intptr = &options->password_authentication; 1674511b41d2SMark Murray goto parse_flag; 1675511b41d2SMark Murray 167609958426SBrian Feldman case sKbdInteractiveAuthentication: 167709958426SBrian Feldman intptr = &options->kbd_interactive_authentication; 167809958426SBrian Feldman goto parse_flag; 167909958426SBrian Feldman 1680511b41d2SMark Murray case sPrintMotd: 1681511b41d2SMark Murray intptr = &options->print_motd; 1682511b41d2SMark Murray goto parse_flag; 1683511b41d2SMark Murray 1684ca3176e7SBrian Feldman case sPrintLastLog: 1685ca3176e7SBrian Feldman intptr = &options->print_lastlog; 1686ca3176e7SBrian Feldman goto parse_flag; 1687ca3176e7SBrian Feldman 1688511b41d2SMark Murray case sX11Forwarding: 1689511b41d2SMark Murray intptr = &options->x11_forwarding; 1690511b41d2SMark Murray goto parse_flag; 1691511b41d2SMark Murray 1692511b41d2SMark Murray case sX11DisplayOffset: 1693511b41d2SMark Murray intptr = &options->x11_display_offset; 1694ca86bcf2SDag-Erling Smørgrav parse_int: 169519261079SEd Maste arg = argv_next(&ac, &av); 169647dd1d1bSDag-Erling Smørgrav if ((errstr = atoi_err(arg, &value)) != NULL) 169719261079SEd Maste fatal("%s line %d: %s integer value %s.", 169819261079SEd Maste filename, linenum, keyword, errstr); 1699ca86bcf2SDag-Erling Smørgrav if (*activep && *intptr == -1) 1700ca86bcf2SDag-Erling Smørgrav *intptr = value; 1701ca86bcf2SDag-Erling Smørgrav break; 1702511b41d2SMark Murray 1703af12a3e7SDag-Erling Smørgrav case sX11UseLocalhost: 1704af12a3e7SDag-Erling Smørgrav intptr = &options->x11_use_localhost; 1705af12a3e7SDag-Erling Smørgrav goto parse_flag; 1706af12a3e7SDag-Erling Smørgrav 1707c2d3a559SKris Kennaway case sXAuthLocation: 1708c2d3a559SKris Kennaway charptr = &options->xauth_location; 1709c2d3a559SKris Kennaway goto parse_filename; 1710c2d3a559SKris Kennaway 1711f7167e0eSDag-Erling Smørgrav case sPermitTTY: 1712f7167e0eSDag-Erling Smørgrav intptr = &options->permit_tty; 1713f7167e0eSDag-Erling Smørgrav goto parse_flag; 1714f7167e0eSDag-Erling Smørgrav 1715a0ee8cc6SDag-Erling Smørgrav case sPermitUserRC: 1716a0ee8cc6SDag-Erling Smørgrav intptr = &options->permit_user_rc; 1717a0ee8cc6SDag-Erling Smørgrav goto parse_flag; 1718a0ee8cc6SDag-Erling Smørgrav 1719511b41d2SMark Murray case sStrictModes: 1720511b41d2SMark Murray intptr = &options->strict_modes; 1721511b41d2SMark Murray goto parse_flag; 1722511b41d2SMark Murray 17231ec0d754SDag-Erling Smørgrav case sTCPKeepAlive: 17241ec0d754SDag-Erling Smørgrav intptr = &options->tcp_keep_alive; 1725511b41d2SMark Murray goto parse_flag; 1726511b41d2SMark Murray 1727511b41d2SMark Murray case sEmptyPasswd: 1728511b41d2SMark Murray intptr = &options->permit_empty_passwd; 1729511b41d2SMark Murray goto parse_flag; 1730511b41d2SMark Murray 1731f388f5efSDag-Erling Smørgrav case sPermitUserEnvironment: 1732f388f5efSDag-Erling Smørgrav intptr = &options->permit_user_env; 173319261079SEd Maste charptr = &options->permit_user_env_allowlist; 173419261079SEd Maste arg = argv_next(&ac, &av); 1735190cef3dSDag-Erling Smørgrav if (!arg || *arg == '\0') 173619261079SEd Maste fatal("%s line %d: %s missing argument.", 173719261079SEd Maste filename, linenum, keyword); 1738190cef3dSDag-Erling Smørgrav value = 0; 1739190cef3dSDag-Erling Smørgrav p = NULL; 1740190cef3dSDag-Erling Smørgrav if (strcmp(arg, "yes") == 0) 1741190cef3dSDag-Erling Smørgrav value = 1; 1742190cef3dSDag-Erling Smørgrav else if (strcmp(arg, "no") == 0) 1743190cef3dSDag-Erling Smørgrav value = 0; 1744190cef3dSDag-Erling Smørgrav else { 1745190cef3dSDag-Erling Smørgrav /* Pattern-list specified */ 1746190cef3dSDag-Erling Smørgrav value = 1; 1747190cef3dSDag-Erling Smørgrav p = xstrdup(arg); 1748190cef3dSDag-Erling Smørgrav } 1749190cef3dSDag-Erling Smørgrav if (*activep && *intptr == -1) { 1750190cef3dSDag-Erling Smørgrav *intptr = value; 1751190cef3dSDag-Erling Smørgrav *charptr = p; 1752190cef3dSDag-Erling Smørgrav p = NULL; 1753190cef3dSDag-Erling Smørgrav } 1754190cef3dSDag-Erling Smørgrav free(p); 1755190cef3dSDag-Erling Smørgrav break; 1756f388f5efSDag-Erling Smørgrav 175780628bacSDag-Erling Smørgrav case sCompression: 175880628bacSDag-Erling Smørgrav intptr = &options->compression; 1759e146993eSDag-Erling Smørgrav multistate_ptr = multistate_compression; 1760e146993eSDag-Erling Smørgrav goto parse_multistate; 176180628bacSDag-Erling Smørgrav 1762e4a9863fSDag-Erling Smørgrav case sRekeyLimit: 176319261079SEd Maste arg = argv_next(&ac, &av); 1764e4a9863fSDag-Erling Smørgrav if (!arg || *arg == '\0') 176519261079SEd Maste fatal("%s line %d: %s missing argument.", 176619261079SEd Maste filename, linenum, keyword); 1767e4a9863fSDag-Erling Smørgrav if (strcmp(arg, "default") == 0) { 1768e4a9863fSDag-Erling Smørgrav val64 = 0; 1769e4a9863fSDag-Erling Smørgrav } else { 1770e4a9863fSDag-Erling Smørgrav if (scan_scaled(arg, &val64) == -1) 177119261079SEd Maste fatal("%.200s line %d: Bad %s number '%s': %s", 177219261079SEd Maste filename, linenum, keyword, 177319261079SEd Maste arg, strerror(errno)); 1774e4a9863fSDag-Erling Smørgrav if (val64 != 0 && val64 < 16) 177519261079SEd Maste fatal("%.200s line %d: %s too small", 177619261079SEd Maste filename, linenum, keyword); 1777e4a9863fSDag-Erling Smørgrav } 1778e4a9863fSDag-Erling Smørgrav if (*activep && options->rekey_limit == -1) 1779acc1a9efSDag-Erling Smørgrav options->rekey_limit = val64; 178019261079SEd Maste if (ac != 0) { /* optional rekey interval present */ 178119261079SEd Maste if (strcmp(av[0], "none") == 0) { 178219261079SEd Maste (void)argv_next(&ac, &av); /* discard */ 1783e4a9863fSDag-Erling Smørgrav break; 1784e4a9863fSDag-Erling Smørgrav } 1785e4a9863fSDag-Erling Smørgrav intptr = &options->rekey_interval; 1786e4a9863fSDag-Erling Smørgrav goto parse_time; 1787e4a9863fSDag-Erling Smørgrav } 1788e4a9863fSDag-Erling Smørgrav break; 1789e4a9863fSDag-Erling Smørgrav 1790e8aafc91SKris Kennaway case sGatewayPorts: 1791a0ee8cc6SDag-Erling Smørgrav intptr = &options->fwd_opts.gateway_ports; 1792e146993eSDag-Erling Smørgrav multistate_ptr = multistate_gatewayports; 1793e146993eSDag-Erling Smørgrav goto parse_multistate; 1794e8aafc91SKris Kennaway 1795cf2b5f3bSDag-Erling Smørgrav case sUseDNS: 1796cf2b5f3bSDag-Erling Smørgrav intptr = &options->use_dns; 1797ca3176e7SBrian Feldman goto parse_flag; 1798ca3176e7SBrian Feldman 1799511b41d2SMark Murray case sLogFacility: 1800d4af9e69SDag-Erling Smørgrav log_facility_ptr = &options->log_facility; 180119261079SEd Maste arg = argv_next(&ac, &av); 1802c2d3a559SKris Kennaway value = log_facility_number(arg); 1803af12a3e7SDag-Erling Smørgrav if (value == SYSLOG_FACILITY_NOT_SET) 1804ca3176e7SBrian Feldman fatal("%.200s line %d: unsupported log facility '%s'", 1805c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1806d4af9e69SDag-Erling Smørgrav if (*log_facility_ptr == -1) 1807d4af9e69SDag-Erling Smørgrav *log_facility_ptr = (SyslogFacility) value; 1808511b41d2SMark Murray break; 1809511b41d2SMark Murray 1810511b41d2SMark Murray case sLogLevel: 1811d4af9e69SDag-Erling Smørgrav log_level_ptr = &options->log_level; 181219261079SEd Maste arg = argv_next(&ac, &av); 1813c2d3a559SKris Kennaway value = log_level_number(arg); 1814af12a3e7SDag-Erling Smørgrav if (value == SYSLOG_LEVEL_NOT_SET) 1815ca3176e7SBrian Feldman fatal("%.200s line %d: unsupported log level '%s'", 1816c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 18174f52dfbbSDag-Erling Smørgrav if (*activep && *log_level_ptr == -1) 1818d4af9e69SDag-Erling Smørgrav *log_level_ptr = (LogLevel) value; 1819511b41d2SMark Murray break; 1820511b41d2SMark Murray 182119261079SEd Maste case sLogVerbose: 182219261079SEd Maste found = options->num_log_verbose == 0; 182319261079SEd Maste i = 0; 182419261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 182519261079SEd Maste if (*arg == '\0') { 182619261079SEd Maste error("%s line %d: keyword %s empty argument", 182719261079SEd Maste filename, linenum, keyword); 182819261079SEd Maste goto out; 182919261079SEd Maste } 183019261079SEd Maste /* Allow "none" only in first position */ 183119261079SEd Maste if (strcasecmp(arg, "none") == 0) { 183219261079SEd Maste if (i > 0 || ac > 0) { 183319261079SEd Maste error("%s line %d: keyword %s \"none\" " 183419261079SEd Maste "argument must appear alone.", 183519261079SEd Maste filename, linenum, keyword); 183619261079SEd Maste goto out; 183719261079SEd Maste } 183819261079SEd Maste } 183919261079SEd Maste i++; 184019261079SEd Maste if (!found || !*activep) 184119261079SEd Maste continue; 184219261079SEd Maste opt_array_append(filename, linenum, keyword, 184319261079SEd Maste &options->log_verbose, &options->num_log_verbose, 184419261079SEd Maste arg); 184519261079SEd Maste } 184619261079SEd Maste break; 184719261079SEd Maste 184809958426SBrian Feldman case sAllowTcpForwarding: 184909958426SBrian Feldman intptr = &options->allow_tcp_forwarding; 18506888a9beSDag-Erling Smørgrav multistate_ptr = multistate_tcpfwd; 18516888a9beSDag-Erling Smørgrav goto parse_multistate; 185209958426SBrian Feldman 1853a0ee8cc6SDag-Erling Smørgrav case sAllowStreamLocalForwarding: 1854a0ee8cc6SDag-Erling Smørgrav intptr = &options->allow_streamlocal_forwarding; 1855a0ee8cc6SDag-Erling Smørgrav multistate_ptr = multistate_tcpfwd; 1856a0ee8cc6SDag-Erling Smørgrav goto parse_multistate; 1857a0ee8cc6SDag-Erling Smørgrav 1858d4af9e69SDag-Erling Smørgrav case sAllowAgentForwarding: 1859d4af9e69SDag-Erling Smørgrav intptr = &options->allow_agent_forwarding; 1860d4af9e69SDag-Erling Smørgrav goto parse_flag; 1861d4af9e69SDag-Erling Smørgrav 1862ca86bcf2SDag-Erling Smørgrav case sDisableForwarding: 1863ca86bcf2SDag-Erling Smørgrav intptr = &options->disable_forwarding; 1864ca86bcf2SDag-Erling Smørgrav goto parse_flag; 1865ca86bcf2SDag-Erling Smørgrav 1866511b41d2SMark Murray case sAllowUsers: 186719261079SEd Maste chararrayptr = &options->allow_users; 186819261079SEd Maste uintptr = &options->num_allow_users; 186919261079SEd Maste parse_allowdenyusers: 187019261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 187119261079SEd Maste if (*arg == '\0' || 187219261079SEd Maste match_user(NULL, NULL, NULL, arg) == -1) 187319261079SEd Maste fatal("%s line %d: invalid %s pattern: \"%s\"", 187419261079SEd Maste filename, linenum, keyword, arg); 1875462c32cbSDag-Erling Smørgrav if (!*activep) 1876462c32cbSDag-Erling Smørgrav continue; 187719261079SEd Maste opt_array_append(filename, linenum, keyword, 187819261079SEd Maste chararrayptr, uintptr, arg); 1879511b41d2SMark Murray } 1880511b41d2SMark Murray break; 1881511b41d2SMark Murray 1882511b41d2SMark Murray case sDenyUsers: 188319261079SEd Maste chararrayptr = &options->deny_users; 188419261079SEd Maste uintptr = &options->num_deny_users; 188519261079SEd Maste goto parse_allowdenyusers; 1886511b41d2SMark Murray 1887511b41d2SMark Murray case sAllowGroups: 188819261079SEd Maste chararrayptr = &options->allow_groups; 188919261079SEd Maste uintptr = &options->num_allow_groups; 189019261079SEd Maste parse_allowdenygroups: 189119261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 189219261079SEd Maste if (*arg == '\0') 189319261079SEd Maste fatal("%s line %d: empty %s pattern", 189419261079SEd Maste filename, linenum, keyword); 1895462c32cbSDag-Erling Smørgrav if (!*activep) 1896462c32cbSDag-Erling Smørgrav continue; 189719261079SEd Maste opt_array_append(filename, linenum, keyword, 189819261079SEd Maste chararrayptr, uintptr, arg); 1899511b41d2SMark Murray } 1900511b41d2SMark Murray break; 1901511b41d2SMark Murray 1902511b41d2SMark Murray case sDenyGroups: 190319261079SEd Maste chararrayptr = &options->deny_groups; 190419261079SEd Maste uintptr = &options->num_deny_groups; 190519261079SEd Maste goto parse_allowdenygroups; 1906511b41d2SMark Murray 1907e8aafc91SKris Kennaway case sCiphers: 190819261079SEd Maste arg = argv_next(&ac, &av); 1909c2d3a559SKris Kennaway if (!arg || *arg == '\0') 191019261079SEd Maste fatal("%s line %d: %s missing argument.", 191119261079SEd Maste filename, linenum, keyword); 191219261079SEd Maste if (*arg != '-' && 191319261079SEd Maste !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) 1914e8aafc91SKris Kennaway fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 1915c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1916e8aafc91SKris Kennaway if (options->ciphers == NULL) 1917c2d3a559SKris Kennaway options->ciphers = xstrdup(arg); 1918e8aafc91SKris Kennaway break; 1919e8aafc91SKris Kennaway 1920ca3176e7SBrian Feldman case sMacs: 192119261079SEd Maste arg = argv_next(&ac, &av); 1922ca3176e7SBrian Feldman if (!arg || *arg == '\0') 192319261079SEd Maste fatal("%s line %d: %s missing argument.", 192419261079SEd Maste filename, linenum, keyword); 192519261079SEd Maste if (*arg != '-' && 192619261079SEd Maste !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) 1927ca3176e7SBrian Feldman fatal("%s line %d: Bad SSH2 mac spec '%s'.", 1928ca3176e7SBrian Feldman filename, linenum, arg ? arg : "<NONE>"); 1929ca3176e7SBrian Feldman if (options->macs == NULL) 1930ca3176e7SBrian Feldman options->macs = xstrdup(arg); 1931ca3176e7SBrian Feldman break; 1932ca3176e7SBrian Feldman 19334a421b63SDag-Erling Smørgrav case sKexAlgorithms: 193419261079SEd Maste arg = argv_next(&ac, &av); 19354a421b63SDag-Erling Smørgrav if (!arg || *arg == '\0') 193619261079SEd Maste fatal("%s line %d: %s missing argument.", 193719261079SEd Maste filename, linenum, keyword); 1938d93a896eSDag-Erling Smørgrav if (*arg != '-' && 193919261079SEd Maste !kex_names_valid(*arg == '+' || *arg == '^' ? 194019261079SEd Maste arg + 1 : arg)) 19414a421b63SDag-Erling Smørgrav fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", 19424a421b63SDag-Erling Smørgrav filename, linenum, arg ? arg : "<NONE>"); 19434a421b63SDag-Erling Smørgrav if (options->kex_algorithms == NULL) 19444a421b63SDag-Erling Smørgrav options->kex_algorithms = xstrdup(arg); 19454a421b63SDag-Erling Smørgrav break; 19464a421b63SDag-Erling Smørgrav 1947c2d3a559SKris Kennaway case sSubsystem: 1948c2d3a559SKris Kennaway if (options->num_subsystems >= MAX_SUBSYSTEMS) { 1949c2d3a559SKris Kennaway fatal("%s line %d: too many subsystems defined.", 1950c2d3a559SKris Kennaway filename, linenum); 1951c2d3a559SKris Kennaway } 195219261079SEd Maste arg = argv_next(&ac, &av); 1953c2d3a559SKris Kennaway if (!arg || *arg == '\0') 195419261079SEd Maste fatal("%s line %d: %s missing argument.", 195519261079SEd Maste filename, linenum, keyword); 1956333ee039SDag-Erling Smørgrav if (!*activep) { 195719261079SEd Maste arg = argv_next(&ac, &av); 1958333ee039SDag-Erling Smørgrav break; 1959333ee039SDag-Erling Smørgrav } 1960c2d3a559SKris Kennaway for (i = 0; i < options->num_subsystems; i++) 1961c2d3a559SKris Kennaway if (strcmp(arg, options->subsystem_name[i]) == 0) 196219261079SEd Maste fatal("%s line %d: Subsystem '%s' " 196319261079SEd Maste "already defined.", filename, linenum, arg); 1964c2d3a559SKris Kennaway options->subsystem_name[options->num_subsystems] = xstrdup(arg); 196519261079SEd Maste arg = argv_next(&ac, &av); 1966c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1967c2d3a559SKris Kennaway fatal("%s line %d: Missing subsystem command.", 1968c2d3a559SKris Kennaway filename, linenum); 1969c2d3a559SKris Kennaway options->subsystem_command[options->num_subsystems] = xstrdup(arg); 1970333ee039SDag-Erling Smørgrav 1971333ee039SDag-Erling Smørgrav /* Collect arguments (separate to executable) */ 1972333ee039SDag-Erling Smørgrav p = xstrdup(arg); 1973333ee039SDag-Erling Smørgrav len = strlen(p) + 1; 197419261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 1975333ee039SDag-Erling Smørgrav len += 1 + strlen(arg); 1976557f75e5SDag-Erling Smørgrav p = xreallocarray(p, 1, len); 1977333ee039SDag-Erling Smørgrav strlcat(p, " ", len); 1978333ee039SDag-Erling Smørgrav strlcat(p, arg, len); 1979333ee039SDag-Erling Smørgrav } 1980333ee039SDag-Erling Smørgrav options->subsystem_args[options->num_subsystems] = p; 1981c2d3a559SKris Kennaway options->num_subsystems++; 1982c2d3a559SKris Kennaway break; 1983c2d3a559SKris Kennaway 1984c2d3a559SKris Kennaway case sMaxStartups: 198519261079SEd Maste arg = argv_next(&ac, &av); 1986c2d3a559SKris Kennaway if (!arg || *arg == '\0') 198719261079SEd Maste fatal("%s line %d: %s missing argument.", 198819261079SEd Maste filename, linenum, keyword); 1989af12a3e7SDag-Erling Smørgrav if ((n = sscanf(arg, "%d:%d:%d", 1990c2d3a559SKris Kennaway &options->max_startups_begin, 1991c2d3a559SKris Kennaway &options->max_startups_rate, 1992af12a3e7SDag-Erling Smørgrav &options->max_startups)) == 3) { 1993c2d3a559SKris Kennaway if (options->max_startups_begin > 1994c2d3a559SKris Kennaway options->max_startups || 1995c2d3a559SKris Kennaway options->max_startups_rate > 100 || 1996c2d3a559SKris Kennaway options->max_startups_rate < 1) 199719261079SEd Maste fatal("%s line %d: Invalid %s spec.", 199819261079SEd Maste filename, linenum, keyword); 1999af12a3e7SDag-Erling Smørgrav } else if (n != 1) 200019261079SEd Maste fatal("%s line %d: Invalid %s spec.", 200119261079SEd Maste filename, linenum, keyword); 2002af12a3e7SDag-Erling Smørgrav else 2003af12a3e7SDag-Erling Smørgrav options->max_startups = options->max_startups_begin; 2004*f374ba41SEd Maste if (options->max_startups <= 0 || 2005*f374ba41SEd Maste options->max_startups_begin <= 0) 2006*f374ba41SEd Maste fatal("%s line %d: Invalid %s spec.", 2007*f374ba41SEd Maste filename, linenum, keyword); 2008933ca70fSBrian Feldman break; 2009933ca70fSBrian Feldman 201019261079SEd Maste case sPerSourceNetBlockSize: 201119261079SEd Maste arg = argv_next(&ac, &av); 201219261079SEd Maste if (!arg || *arg == '\0') 201319261079SEd Maste fatal("%s line %d: %s missing argument.", 201419261079SEd Maste filename, linenum, keyword); 201519261079SEd Maste switch (n = sscanf(arg, "%d:%d", &value, &value2)) { 201619261079SEd Maste case 2: 201719261079SEd Maste if (value2 < 0 || value2 > 128) 201819261079SEd Maste n = -1; 201919261079SEd Maste /* FALLTHROUGH */ 202019261079SEd Maste case 1: 202119261079SEd Maste if (value < 0 || value > 32) 202219261079SEd Maste n = -1; 202319261079SEd Maste } 202419261079SEd Maste if (n != 1 && n != 2) 202519261079SEd Maste fatal("%s line %d: Invalid %s spec.", 202619261079SEd Maste filename, linenum, keyword); 202719261079SEd Maste if (*activep) { 202819261079SEd Maste options->per_source_masklen_ipv4 = value; 202919261079SEd Maste options->per_source_masklen_ipv6 = value2; 203019261079SEd Maste } 203119261079SEd Maste break; 203219261079SEd Maste 203319261079SEd Maste case sPerSourceMaxStartups: 203419261079SEd Maste arg = argv_next(&ac, &av); 203519261079SEd Maste if (!arg || *arg == '\0') 203619261079SEd Maste fatal("%s line %d: %s missing argument.", 203719261079SEd Maste filename, linenum, keyword); 203819261079SEd Maste if (strcmp(arg, "none") == 0) { /* no limit */ 203919261079SEd Maste value = INT_MAX; 204019261079SEd Maste } else { 204119261079SEd Maste if ((errstr = atoi_err(arg, &value)) != NULL) 204219261079SEd Maste fatal("%s line %d: %s integer value %s.", 204319261079SEd Maste filename, linenum, keyword, errstr); 204419261079SEd Maste } 204519261079SEd Maste if (*activep) 204619261079SEd Maste options->per_source_max_startups = value; 204719261079SEd Maste break; 204819261079SEd Maste 204921e764dfSDag-Erling Smørgrav case sMaxAuthTries: 205021e764dfSDag-Erling Smørgrav intptr = &options->max_authtries; 205121e764dfSDag-Erling Smørgrav goto parse_int; 205221e764dfSDag-Erling Smørgrav 2053d4af9e69SDag-Erling Smørgrav case sMaxSessions: 2054d4af9e69SDag-Erling Smørgrav intptr = &options->max_sessions; 2055d4af9e69SDag-Erling Smørgrav goto parse_int; 2056d4af9e69SDag-Erling Smørgrav 2057ca3176e7SBrian Feldman case sBanner: 2058ca3176e7SBrian Feldman charptr = &options->banner; 2059ca3176e7SBrian Feldman goto parse_filename; 2060d4af9e69SDag-Erling Smørgrav 2061af12a3e7SDag-Erling Smørgrav /* 2062af12a3e7SDag-Erling Smørgrav * These options can contain %X options expanded at 2063af12a3e7SDag-Erling Smørgrav * connect time, so that you can specify paths like: 2064af12a3e7SDag-Erling Smørgrav * 2065af12a3e7SDag-Erling Smørgrav * AuthorizedKeysFile /etc/ssh_keys/%u 2066af12a3e7SDag-Erling Smørgrav */ 2067af12a3e7SDag-Erling Smørgrav case sAuthorizedKeysFile: 206819261079SEd Maste uvalue = options->num_authkeys_files; 206919261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 207019261079SEd Maste if (*arg == '\0') { 207119261079SEd Maste error("%s line %d: keyword %s empty argument", 207219261079SEd Maste filename, linenum, keyword); 207319261079SEd Maste goto out; 207419261079SEd Maste } 207519261079SEd Maste arg2 = tilde_expand_filename(arg, getuid()); 207619261079SEd Maste if (*activep && uvalue == 0) { 207719261079SEd Maste opt_array_append(filename, linenum, keyword, 207847dd1d1bSDag-Erling Smørgrav &options->authorized_keys_files, 207919261079SEd Maste &options->num_authkeys_files, arg2); 2080e146993eSDag-Erling Smørgrav } 208119261079SEd Maste free(arg2); 2082e146993eSDag-Erling Smørgrav } 208319261079SEd Maste break; 2084e146993eSDag-Erling Smørgrav 2085e2f6069cSDag-Erling Smørgrav case sAuthorizedPrincipalsFile: 2086e2f6069cSDag-Erling Smørgrav charptr = &options->authorized_principals_file; 208719261079SEd Maste arg = argv_next(&ac, &av); 20888ad9b54aSDag-Erling Smørgrav if (!arg || *arg == '\0') 208919261079SEd Maste fatal("%s line %d: %s missing argument.", 209019261079SEd Maste filename, linenum, keyword); 20918ad9b54aSDag-Erling Smørgrav if (*activep && *charptr == NULL) { 20928ad9b54aSDag-Erling Smørgrav *charptr = tilde_expand_filename(arg, getuid()); 20938ad9b54aSDag-Erling Smørgrav /* increase optional counter */ 20948ad9b54aSDag-Erling Smørgrav if (intptr != NULL) 20958ad9b54aSDag-Erling Smørgrav *intptr = *intptr + 1; 20968ad9b54aSDag-Erling Smørgrav } 20978ad9b54aSDag-Erling Smørgrav break; 2098af12a3e7SDag-Erling Smørgrav 2099ca3176e7SBrian Feldman case sClientAliveInterval: 2100ca3176e7SBrian Feldman intptr = &options->client_alive_interval; 2101af12a3e7SDag-Erling Smørgrav goto parse_time; 2102af12a3e7SDag-Erling Smørgrav 2103ca3176e7SBrian Feldman case sClientAliveCountMax: 2104ca3176e7SBrian Feldman intptr = &options->client_alive_count_max; 2105ca3176e7SBrian Feldman goto parse_int; 2106af12a3e7SDag-Erling Smørgrav 210721e764dfSDag-Erling Smørgrav case sAcceptEnv: 210819261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 210919261079SEd Maste if (*arg == '\0' || strchr(arg, '=') != NULL) 211021e764dfSDag-Erling Smørgrav fatal("%s line %d: Invalid environment name.", 211121e764dfSDag-Erling Smørgrav filename, linenum); 2112333ee039SDag-Erling Smørgrav if (!*activep) 2113462c32cbSDag-Erling Smørgrav continue; 211419261079SEd Maste opt_array_append(filename, linenum, keyword, 211547dd1d1bSDag-Erling Smørgrav &options->accept_env, &options->num_accept_env, 211647dd1d1bSDag-Erling Smørgrav arg); 211721e764dfSDag-Erling Smørgrav } 211821e764dfSDag-Erling Smørgrav break; 211921e764dfSDag-Erling Smørgrav 2120190cef3dSDag-Erling Smørgrav case sSetEnv: 2121190cef3dSDag-Erling Smørgrav uvalue = options->num_setenv; 212219261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 212319261079SEd Maste if (*arg == '\0' || strchr(arg, '=') == NULL) 2124190cef3dSDag-Erling Smørgrav fatal("%s line %d: Invalid environment.", 2125190cef3dSDag-Erling Smørgrav filename, linenum); 2126190cef3dSDag-Erling Smørgrav if (!*activep || uvalue != 0) 2127190cef3dSDag-Erling Smørgrav continue; 212838a52bd3SEd Maste if (lookup_setenv_in_list(arg, options->setenv, 212938a52bd3SEd Maste options->num_setenv) != NULL) { 213038a52bd3SEd Maste debug2("%s line %d: ignoring duplicate env " 213138a52bd3SEd Maste "name \"%.64s\"", filename, linenum, arg); 213238a52bd3SEd Maste continue; 213338a52bd3SEd Maste } 213419261079SEd Maste opt_array_append(filename, linenum, keyword, 2135190cef3dSDag-Erling Smørgrav &options->setenv, &options->num_setenv, arg); 2136190cef3dSDag-Erling Smørgrav } 2137190cef3dSDag-Erling Smørgrav break; 2138190cef3dSDag-Erling Smørgrav 2139b74df5b2SDag-Erling Smørgrav case sPermitTunnel: 2140b74df5b2SDag-Erling Smørgrav intptr = &options->permit_tun; 214119261079SEd Maste arg = argv_next(&ac, &av); 2142b74df5b2SDag-Erling Smørgrav if (!arg || *arg == '\0') 214319261079SEd Maste fatal("%s line %d: %s missing argument.", 214419261079SEd Maste filename, linenum, keyword); 2145d4af9e69SDag-Erling Smørgrav value = -1; 2146d4af9e69SDag-Erling Smørgrav for (i = 0; tunmode_desc[i].val != -1; i++) 2147d4af9e69SDag-Erling Smørgrav if (strcmp(tunmode_desc[i].text, arg) == 0) { 2148d4af9e69SDag-Erling Smørgrav value = tunmode_desc[i].val; 2149d4af9e69SDag-Erling Smørgrav break; 2150d4af9e69SDag-Erling Smørgrav } 2151d4af9e69SDag-Erling Smørgrav if (value == -1) 215219261079SEd Maste fatal("%s line %d: bad %s argument %s", 215319261079SEd Maste filename, linenum, keyword, arg); 2154557f75e5SDag-Erling Smørgrav if (*activep && *intptr == -1) 2155b74df5b2SDag-Erling Smørgrav *intptr = value; 2156b74df5b2SDag-Erling Smørgrav break; 2157b74df5b2SDag-Erling Smørgrav 215819261079SEd Maste case sInclude: 215919261079SEd Maste if (cmdline) { 216019261079SEd Maste fatal("Include directive not supported as a " 216119261079SEd Maste "command-line option"); 216219261079SEd Maste } 216319261079SEd Maste value = 0; 216419261079SEd Maste while ((arg2 = argv_next(&ac, &av)) != NULL) { 216519261079SEd Maste if (*arg2 == '\0') { 216619261079SEd Maste error("%s line %d: keyword %s empty argument", 216719261079SEd Maste filename, linenum, keyword); 216819261079SEd Maste goto out; 216919261079SEd Maste } 217019261079SEd Maste value++; 217119261079SEd Maste found = 0; 217219261079SEd Maste if (*arg2 != '/' && *arg2 != '~') { 217319261079SEd Maste xasprintf(&arg, "%s/%s", SSHDIR, arg2); 217419261079SEd Maste } else 217519261079SEd Maste arg = xstrdup(arg2); 217619261079SEd Maste 217719261079SEd Maste /* 217819261079SEd Maste * Don't let included files clobber the containing 217919261079SEd Maste * file's Match state. 218019261079SEd Maste */ 218119261079SEd Maste oactive = *activep; 218219261079SEd Maste 218319261079SEd Maste /* consult cache of include files */ 218419261079SEd Maste TAILQ_FOREACH(item, includes, entry) { 218519261079SEd Maste if (strcmp(item->selector, arg) != 0) 218619261079SEd Maste continue; 218719261079SEd Maste if (item->filename != NULL) { 218819261079SEd Maste parse_server_config_depth(options, 218919261079SEd Maste item->filename, item->contents, 219019261079SEd Maste includes, connectinfo, 219119261079SEd Maste (*inc_flags & SSHCFG_MATCH_ONLY 219219261079SEd Maste ? SSHCFG_MATCH_ONLY : (oactive 219319261079SEd Maste ? 0 : SSHCFG_NEVERMATCH)), 219419261079SEd Maste activep, depth + 1); 219519261079SEd Maste } 219619261079SEd Maste found = 1; 219719261079SEd Maste *activep = oactive; 219819261079SEd Maste } 219919261079SEd Maste if (found != 0) { 220019261079SEd Maste free(arg); 220119261079SEd Maste continue; 220219261079SEd Maste } 220319261079SEd Maste 220419261079SEd Maste /* requested glob was not in cache */ 220519261079SEd Maste debug2("%s line %d: new include %s", 220619261079SEd Maste filename, linenum, arg); 220719261079SEd Maste if ((r = glob(arg, 0, NULL, &gbuf)) != 0) { 220819261079SEd Maste if (r != GLOB_NOMATCH) { 220919261079SEd Maste fatal("%s line %d: include \"%s\" glob " 221019261079SEd Maste "failed", filename, linenum, arg); 221119261079SEd Maste } 221219261079SEd Maste /* 221319261079SEd Maste * If no entry matched then record a 221419261079SEd Maste * placeholder to skip later glob calls. 221519261079SEd Maste */ 221619261079SEd Maste debug2("%s line %d: no match for %s", 221719261079SEd Maste filename, linenum, arg); 221819261079SEd Maste item = xcalloc(1, sizeof(*item)); 221919261079SEd Maste item->selector = strdup(arg); 222019261079SEd Maste TAILQ_INSERT_TAIL(includes, 222119261079SEd Maste item, entry); 222219261079SEd Maste } 222319261079SEd Maste if (gbuf.gl_pathc > INT_MAX) 222419261079SEd Maste fatal_f("too many glob results"); 222519261079SEd Maste for (n = 0; n < (int)gbuf.gl_pathc; n++) { 222619261079SEd Maste debug2("%s line %d: including %s", 222719261079SEd Maste filename, linenum, gbuf.gl_pathv[n]); 222819261079SEd Maste item = xcalloc(1, sizeof(*item)); 222919261079SEd Maste item->selector = strdup(arg); 223019261079SEd Maste item->filename = strdup(gbuf.gl_pathv[n]); 223119261079SEd Maste if ((item->contents = sshbuf_new()) == NULL) 223219261079SEd Maste fatal_f("sshbuf_new failed"); 223319261079SEd Maste load_server_config(item->filename, 223419261079SEd Maste item->contents); 223519261079SEd Maste parse_server_config_depth(options, 223619261079SEd Maste item->filename, item->contents, 223719261079SEd Maste includes, connectinfo, 223819261079SEd Maste (*inc_flags & SSHCFG_MATCH_ONLY 223919261079SEd Maste ? SSHCFG_MATCH_ONLY : (oactive 224019261079SEd Maste ? 0 : SSHCFG_NEVERMATCH)), 224119261079SEd Maste activep, depth + 1); 224219261079SEd Maste *activep = oactive; 224319261079SEd Maste TAILQ_INSERT_TAIL(includes, item, entry); 224419261079SEd Maste } 224519261079SEd Maste globfree(&gbuf); 224619261079SEd Maste free(arg); 224719261079SEd Maste } 224819261079SEd Maste if (value == 0) { 224919261079SEd Maste fatal("%s line %d: %s missing filename argument", 225019261079SEd Maste filename, linenum, keyword); 225119261079SEd Maste } 225219261079SEd Maste break; 225319261079SEd Maste 2254333ee039SDag-Erling Smørgrav case sMatch: 2255333ee039SDag-Erling Smørgrav if (cmdline) 2256333ee039SDag-Erling Smørgrav fatal("Match directive not supported as a command-line " 2257333ee039SDag-Erling Smørgrav "option"); 225819261079SEd Maste value = match_cfg_line(&str, linenum, 225919261079SEd Maste (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo)); 2260333ee039SDag-Erling Smørgrav if (value < 0) 2261333ee039SDag-Erling Smørgrav fatal("%s line %d: Bad Match condition", filename, 2262333ee039SDag-Erling Smørgrav linenum); 226319261079SEd Maste *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; 226419261079SEd Maste /* 226519261079SEd Maste * The MATCH_ONLY flag is applicable only until the first 226619261079SEd Maste * match block. 226719261079SEd Maste */ 226819261079SEd Maste *inc_flags &= ~SSHCFG_MATCH_ONLY; 226919261079SEd Maste /* 227019261079SEd Maste * If match_cfg_line() didn't consume all its arguments then 227119261079SEd Maste * arrange for the extra arguments check below to fail. 227219261079SEd Maste */ 227319261079SEd Maste if (str == NULL || *str == '\0') 227419261079SEd Maste argv_consume(&ac); 2275333ee039SDag-Erling Smørgrav break; 2276333ee039SDag-Erling Smørgrav 2277190cef3dSDag-Erling Smørgrav case sPermitListen: 2278333ee039SDag-Erling Smørgrav case sPermitOpen: 2279190cef3dSDag-Erling Smørgrav if (opcode == sPermitListen) { 2280190cef3dSDag-Erling Smørgrav uintptr = &options->num_permitted_listens; 2281190cef3dSDag-Erling Smørgrav chararrayptr = &options->permitted_listens; 2282190cef3dSDag-Erling Smørgrav } else { 2283190cef3dSDag-Erling Smørgrav uintptr = &options->num_permitted_opens; 2284190cef3dSDag-Erling Smørgrav chararrayptr = &options->permitted_opens; 2285190cef3dSDag-Erling Smørgrav } 228619261079SEd Maste arg = argv_next(&ac, &av); 2287333ee039SDag-Erling Smørgrav if (!arg || *arg == '\0') 228819261079SEd Maste fatal("%s line %d: %s missing argument.", 228919261079SEd Maste filename, linenum, keyword); 2290190cef3dSDag-Erling Smørgrav uvalue = *uintptr; /* modified later */ 22914f52dfbbSDag-Erling Smørgrav if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { 2292190cef3dSDag-Erling Smørgrav if (*activep && uvalue == 0) { 2293190cef3dSDag-Erling Smørgrav *uintptr = 1; 2294190cef3dSDag-Erling Smørgrav *chararrayptr = xcalloc(1, 2295190cef3dSDag-Erling Smørgrav sizeof(**chararrayptr)); 2296190cef3dSDag-Erling Smørgrav (*chararrayptr)[0] = xstrdup(arg); 2297462c32cbSDag-Erling Smørgrav } 2298462c32cbSDag-Erling Smørgrav break; 2299462c32cbSDag-Erling Smørgrav } 230019261079SEd Maste for (; arg != NULL && *arg != '\0'; arg = argv_next(&ac, &av)) { 2301190cef3dSDag-Erling Smørgrav if (opcode == sPermitListen && 2302190cef3dSDag-Erling Smørgrav strchr(arg, ':') == NULL) { 2303190cef3dSDag-Erling Smørgrav /* 2304190cef3dSDag-Erling Smørgrav * Allow bare port number for PermitListen 2305190cef3dSDag-Erling Smørgrav * to indicate a wildcard listen host. 2306190cef3dSDag-Erling Smørgrav */ 2307190cef3dSDag-Erling Smørgrav xasprintf(&arg2, "*:%s", arg); 2308190cef3dSDag-Erling Smørgrav } else { 23094f52dfbbSDag-Erling Smørgrav arg2 = xstrdup(arg); 23101323ec57SEd Maste p = hpdelim(&arg); 23111323ec57SEd Maste if (p == NULL) { 231219261079SEd Maste fatal("%s line %d: %s missing host", 231319261079SEd Maste filename, linenum, keyword); 2314190cef3dSDag-Erling Smørgrav } 2315333ee039SDag-Erling Smørgrav p = cleanhostname(p); 2316190cef3dSDag-Erling Smørgrav } 2317190cef3dSDag-Erling Smørgrav if (arg == NULL || 2318190cef3dSDag-Erling Smørgrav ((port = permitopen_port(arg)) < 0)) { 231919261079SEd Maste fatal("%s line %d: %s bad port number", 232019261079SEd Maste filename, linenum, keyword); 2321190cef3dSDag-Erling Smørgrav } 2322190cef3dSDag-Erling Smørgrav if (*activep && uvalue == 0) { 232319261079SEd Maste opt_array_append(filename, linenum, keyword, 2324190cef3dSDag-Erling Smørgrav chararrayptr, uintptr, arg2); 232547dd1d1bSDag-Erling Smørgrav } 23264f52dfbbSDag-Erling Smørgrav free(arg2); 2327333ee039SDag-Erling Smørgrav } 2328333ee039SDag-Erling Smørgrav break; 2329333ee039SDag-Erling Smørgrav 2330333ee039SDag-Erling Smørgrav case sForceCommand: 233119261079SEd Maste if (str == NULL || *str == '\0') 233219261079SEd Maste fatal("%s line %d: %s missing argument.", 233319261079SEd Maste filename, linenum, keyword); 233419261079SEd Maste len = strspn(str, WHITESPACE); 2335333ee039SDag-Erling Smørgrav if (*activep && options->adm_forced_command == NULL) 233619261079SEd Maste options->adm_forced_command = xstrdup(str + len); 233719261079SEd Maste argv_consume(&ac); 233819261079SEd Maste break; 2339333ee039SDag-Erling Smørgrav 2340d4af9e69SDag-Erling Smørgrav case sChrootDirectory: 2341d4af9e69SDag-Erling Smørgrav charptr = &options->chroot_directory; 2342d4af9e69SDag-Erling Smørgrav 234319261079SEd Maste arg = argv_next(&ac, &av); 2344d4af9e69SDag-Erling Smørgrav if (!arg || *arg == '\0') 234519261079SEd Maste fatal("%s line %d: %s missing argument.", 234619261079SEd Maste filename, linenum, keyword); 2347d4af9e69SDag-Erling Smørgrav if (*activep && *charptr == NULL) 2348d4af9e69SDag-Erling Smørgrav *charptr = xstrdup(arg); 2349d4af9e69SDag-Erling Smørgrav break; 2350d4af9e69SDag-Erling Smørgrav 2351b15c8340SDag-Erling Smørgrav case sTrustedUserCAKeys: 2352b15c8340SDag-Erling Smørgrav charptr = &options->trusted_user_ca_keys; 2353b15c8340SDag-Erling Smørgrav goto parse_filename; 2354b15c8340SDag-Erling Smørgrav 2355b15c8340SDag-Erling Smørgrav case sRevokedKeys: 2356b15c8340SDag-Erling Smørgrav charptr = &options->revoked_keys_file; 2357b15c8340SDag-Erling Smørgrav goto parse_filename; 2358b15c8340SDag-Erling Smørgrav 235919261079SEd Maste case sSecurityKeyProvider: 236019261079SEd Maste charptr = &options->sk_provider; 236119261079SEd Maste arg = argv_next(&ac, &av); 236219261079SEd Maste if (!arg || *arg == '\0') 236319261079SEd Maste fatal("%s line %d: %s missing argument.", 236419261079SEd Maste filename, linenum, keyword); 236519261079SEd Maste if (*activep && *charptr == NULL) { 236619261079SEd Maste *charptr = strcasecmp(arg, "internal") == 0 ? 236719261079SEd Maste xstrdup(arg) : derelativise_path(arg); 236819261079SEd Maste /* increase optional counter */ 236919261079SEd Maste if (intptr != NULL) 237019261079SEd Maste *intptr = *intptr + 1; 237119261079SEd Maste } 237219261079SEd Maste break; 237319261079SEd Maste 23744a421b63SDag-Erling Smørgrav case sIPQoS: 237519261079SEd Maste arg = argv_next(&ac, &av); 237619261079SEd Maste if (!arg || *arg == '\0') 237719261079SEd Maste fatal("%s line %d: %s missing argument.", 237819261079SEd Maste filename, linenum, keyword); 23794a421b63SDag-Erling Smørgrav if ((value = parse_ipqos(arg)) == -1) 238019261079SEd Maste fatal("%s line %d: Bad %s value: %s", 238119261079SEd Maste filename, linenum, keyword, arg); 238219261079SEd Maste arg = argv_next(&ac, &av); 23834a421b63SDag-Erling Smørgrav if (arg == NULL) 23844a421b63SDag-Erling Smørgrav value2 = value; 23854a421b63SDag-Erling Smørgrav else if ((value2 = parse_ipqos(arg)) == -1) 238619261079SEd Maste fatal("%s line %d: Bad %s value: %s", 238719261079SEd Maste filename, linenum, keyword, arg); 23884a421b63SDag-Erling Smørgrav if (*activep) { 23894a421b63SDag-Erling Smørgrav options->ip_qos_interactive = value; 23904a421b63SDag-Erling Smørgrav options->ip_qos_bulk = value2; 23914a421b63SDag-Erling Smørgrav } 23924a421b63SDag-Erling Smørgrav break; 23934a421b63SDag-Erling Smørgrav 2394db58a8e4SDag-Erling Smørgrav case sVersionAddendum: 239519261079SEd Maste if (str == NULL || *str == '\0') 239619261079SEd Maste fatal("%s line %d: %s missing argument.", 239719261079SEd Maste filename, linenum, keyword); 239819261079SEd Maste len = strspn(str, WHITESPACE); 239919261079SEd Maste if (strchr(str + len, '\r') != NULL) { 240019261079SEd Maste fatal("%.200s line %d: Invalid %s argument", 240119261079SEd Maste filename, linenum, keyword); 2402462c32cbSDag-Erling Smørgrav } 240319261079SEd Maste if ((arg = strchr(line, '#')) != NULL) { 240419261079SEd Maste *arg = '\0'; 240519261079SEd Maste rtrim(line); 240619261079SEd Maste } 240719261079SEd Maste if (*activep && options->version_addendum == NULL) { 240819261079SEd Maste if (strcasecmp(str + len, "none") == 0) 240919261079SEd Maste options->version_addendum = xstrdup(""); 241019261079SEd Maste else 241119261079SEd Maste options->version_addendum = xstrdup(str + len); 241219261079SEd Maste } 241319261079SEd Maste argv_consume(&ac); 241419261079SEd Maste break; 2415db58a8e4SDag-Erling Smørgrav 24166888a9beSDag-Erling Smørgrav case sAuthorizedKeysCommand: 241719261079SEd Maste charptr = &options->authorized_keys_command; 241819261079SEd Maste parse_command: 241919261079SEd Maste len = strspn(str, WHITESPACE); 242019261079SEd Maste if (str[len] != '/' && strcasecmp(str + len, "none") != 0) { 242119261079SEd Maste fatal("%.200s line %d: %s must be an absolute path", 242219261079SEd Maste filename, linenum, keyword); 24236888a9beSDag-Erling Smørgrav } 242419261079SEd Maste if (*activep && options->authorized_keys_command == NULL) 242519261079SEd Maste *charptr = xstrdup(str + len); 242619261079SEd Maste argv_consume(&ac); 242719261079SEd Maste break; 24286888a9beSDag-Erling Smørgrav 24296888a9beSDag-Erling Smørgrav case sAuthorizedKeysCommandUser: 24306888a9beSDag-Erling Smørgrav charptr = &options->authorized_keys_command_user; 243119261079SEd Maste parse_localuser: 243219261079SEd Maste arg = argv_next(&ac, &av); 243319261079SEd Maste if (!arg || *arg == '\0') { 243419261079SEd Maste fatal("%s line %d: missing %s argument.", 243519261079SEd Maste filename, linenum, keyword); 243619261079SEd Maste } 24376888a9beSDag-Erling Smørgrav if (*activep && *charptr == NULL) 24386888a9beSDag-Erling Smørgrav *charptr = xstrdup(arg); 24396888a9beSDag-Erling Smørgrav break; 24406888a9beSDag-Erling Smørgrav 2441557f75e5SDag-Erling Smørgrav case sAuthorizedPrincipalsCommand: 244219261079SEd Maste charptr = &options->authorized_principals_command; 244319261079SEd Maste goto parse_command; 2444557f75e5SDag-Erling Smørgrav 2445557f75e5SDag-Erling Smørgrav case sAuthorizedPrincipalsCommandUser: 2446557f75e5SDag-Erling Smørgrav charptr = &options->authorized_principals_command_user; 244719261079SEd Maste goto parse_localuser; 2448557f75e5SDag-Erling Smørgrav 24496888a9beSDag-Erling Smørgrav case sAuthenticationMethods: 245019261079SEd Maste found = options->num_auth_methods == 0; 2451076ad2f8SDag-Erling Smørgrav value = 0; /* seen "any" pseudo-method */ 2452190cef3dSDag-Erling Smørgrav value2 = 0; /* successfully parsed any method */ 245319261079SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 2454076ad2f8SDag-Erling Smørgrav if (strcmp(arg, "any") == 0) { 2455076ad2f8SDag-Erling Smørgrav if (options->num_auth_methods > 0) { 245619261079SEd Maste fatal("%s line %d: \"any\" must " 245719261079SEd Maste "appear alone in %s", 245819261079SEd Maste filename, linenum, keyword); 2459076ad2f8SDag-Erling Smørgrav } 2460076ad2f8SDag-Erling Smørgrav value = 1; 2461076ad2f8SDag-Erling Smørgrav } else if (value) { 2462076ad2f8SDag-Erling Smørgrav fatal("%s line %d: \"any\" must appear " 246319261079SEd Maste "alone in %s", filename, linenum, keyword); 2464076ad2f8SDag-Erling Smørgrav } else if (auth2_methods_valid(arg, 0) != 0) { 246519261079SEd Maste fatal("%s line %d: invalid %s method list.", 246619261079SEd Maste filename, linenum, keyword); 2467076ad2f8SDag-Erling Smørgrav } 2468076ad2f8SDag-Erling Smørgrav value2 = 1; 246919261079SEd Maste if (!found || !*activep) 2470557f75e5SDag-Erling Smørgrav continue; 247119261079SEd Maste opt_array_append(filename, linenum, keyword, 247247dd1d1bSDag-Erling Smørgrav &options->auth_methods, 247347dd1d1bSDag-Erling Smørgrav &options->num_auth_methods, arg); 24746888a9beSDag-Erling Smørgrav } 2475076ad2f8SDag-Erling Smørgrav if (value2 == 0) { 247619261079SEd Maste fatal("%s line %d: no %s specified", 247719261079SEd Maste filename, linenum, keyword); 2478076ad2f8SDag-Erling Smørgrav } 247919261079SEd Maste break; 24806888a9beSDag-Erling Smørgrav 2481a0ee8cc6SDag-Erling Smørgrav case sStreamLocalBindMask: 248219261079SEd Maste arg = argv_next(&ac, &av); 2483a0ee8cc6SDag-Erling Smørgrav if (!arg || *arg == '\0') 248419261079SEd Maste fatal("%s line %d: %s missing argument.", 248519261079SEd Maste filename, linenum, keyword); 2486a0ee8cc6SDag-Erling Smørgrav /* Parse mode in octal format */ 2487a0ee8cc6SDag-Erling Smørgrav value = strtol(arg, &p, 8); 2488a0ee8cc6SDag-Erling Smørgrav if (arg == p || value < 0 || value > 0777) 248919261079SEd Maste fatal("%s line %d: Invalid %s.", 249019261079SEd Maste filename, linenum, keyword); 2491557f75e5SDag-Erling Smørgrav if (*activep) 2492a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 2493a0ee8cc6SDag-Erling Smørgrav break; 2494a0ee8cc6SDag-Erling Smørgrav 2495a0ee8cc6SDag-Erling Smørgrav case sStreamLocalBindUnlink: 2496a0ee8cc6SDag-Erling Smørgrav intptr = &options->fwd_opts.streamlocal_bind_unlink; 2497a0ee8cc6SDag-Erling Smørgrav goto parse_flag; 2498a0ee8cc6SDag-Erling Smørgrav 2499bc5531deSDag-Erling Smørgrav case sFingerprintHash: 250019261079SEd Maste arg = argv_next(&ac, &av); 2501bc5531deSDag-Erling Smørgrav if (!arg || *arg == '\0') 250219261079SEd Maste fatal("%s line %d: %s missing argument.", 250319261079SEd Maste filename, linenum, keyword); 2504bc5531deSDag-Erling Smørgrav if ((value = ssh_digest_alg_by_name(arg)) == -1) 250519261079SEd Maste fatal("%.200s line %d: Invalid %s algorithm \"%s\".", 250619261079SEd Maste filename, linenum, keyword, arg); 2507bc5531deSDag-Erling Smørgrav if (*activep) 2508bc5531deSDag-Erling Smørgrav options->fingerprint_hash = value; 2509bc5531deSDag-Erling Smørgrav break; 2510bc5531deSDag-Erling Smørgrav 25114f52dfbbSDag-Erling Smørgrav case sExposeAuthInfo: 25124f52dfbbSDag-Erling Smørgrav intptr = &options->expose_userauth_info; 25134f52dfbbSDag-Erling Smørgrav goto parse_flag; 25144f52dfbbSDag-Erling Smørgrav 251547dd1d1bSDag-Erling Smørgrav case sRDomain: 251619261079SEd Maste #if !defined(__OpenBSD__) && !defined(HAVE_SYS_SET_PROCESS_RDOMAIN) 251719261079SEd Maste fatal("%s line %d: setting RDomain not supported on this " 251819261079SEd Maste "platform.", filename, linenum); 251919261079SEd Maste #endif 252047dd1d1bSDag-Erling Smørgrav charptr = &options->routing_domain; 252119261079SEd Maste arg = argv_next(&ac, &av); 252247dd1d1bSDag-Erling Smørgrav if (!arg || *arg == '\0') 252319261079SEd Maste fatal("%s line %d: %s missing argument.", 252419261079SEd Maste filename, linenum, keyword); 252547dd1d1bSDag-Erling Smørgrav if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 && 252647dd1d1bSDag-Erling Smørgrav !valid_rdomain(arg)) 252719261079SEd Maste fatal("%s line %d: invalid routing domain", 252847dd1d1bSDag-Erling Smørgrav filename, linenum); 252947dd1d1bSDag-Erling Smørgrav if (*activep && *charptr == NULL) 253047dd1d1bSDag-Erling Smørgrav *charptr = xstrdup(arg); 253147dd1d1bSDag-Erling Smørgrav break; 253247dd1d1bSDag-Erling Smørgrav 253338a52bd3SEd Maste case sRequiredRSASize: 253438a52bd3SEd Maste intptr = &options->required_rsa_size; 253538a52bd3SEd Maste goto parse_int; 253638a52bd3SEd Maste 2537*f374ba41SEd Maste case sChannelTimeout: 2538*f374ba41SEd Maste uvalue = options->num_channel_timeouts; 2539*f374ba41SEd Maste i = 0; 2540*f374ba41SEd Maste while ((arg = argv_next(&ac, &av)) != NULL) { 2541*f374ba41SEd Maste /* Allow "none" only in first position */ 2542*f374ba41SEd Maste if (strcasecmp(arg, "none") == 0) { 2543*f374ba41SEd Maste if (i > 0 || ac > 0) { 2544*f374ba41SEd Maste error("%s line %d: keyword %s \"none\" " 2545*f374ba41SEd Maste "argument must appear alone.", 2546*f374ba41SEd Maste filename, linenum, keyword); 2547*f374ba41SEd Maste goto out; 2548*f374ba41SEd Maste } 2549*f374ba41SEd Maste } else if (parse_timeout(arg, NULL, NULL) != 0) { 2550*f374ba41SEd Maste fatal("%s line %d: invalid channel timeout %s", 2551*f374ba41SEd Maste filename, linenum, arg); 2552*f374ba41SEd Maste } 2553*f374ba41SEd Maste if (!*activep || uvalue != 0) 2554*f374ba41SEd Maste continue; 2555*f374ba41SEd Maste opt_array_append(filename, linenum, keyword, 2556*f374ba41SEd Maste &options->channel_timeouts, 2557*f374ba41SEd Maste &options->num_channel_timeouts, arg); 2558*f374ba41SEd Maste } 2559*f374ba41SEd Maste break; 2560*f374ba41SEd Maste 2561*f374ba41SEd Maste case sUnusedConnectionTimeout: 2562*f374ba41SEd Maste intptr = &options->unused_connection_timeout; 2563*f374ba41SEd Maste /* peek at first arg for "none" so we can reuse parse_time */ 2564*f374ba41SEd Maste if (av[0] != NULL && strcasecmp(av[0], "none") == 0) { 2565*f374ba41SEd Maste (void)argv_next(&ac, &av); /* consume arg */ 2566*f374ba41SEd Maste if (*activep) 2567*f374ba41SEd Maste *intptr = 0; 2568*f374ba41SEd Maste break; 2569*f374ba41SEd Maste } 2570*f374ba41SEd Maste goto parse_time; 2571*f374ba41SEd Maste 2572b2af61ecSKurt Lidl case sUseBlacklist: 2573b2af61ecSKurt Lidl intptr = &options->use_blacklist; 2574b2af61ecSKurt Lidl goto parse_flag; 2575b2af61ecSKurt Lidl 2576af12a3e7SDag-Erling Smørgrav case sDeprecated: 2577ca86bcf2SDag-Erling Smørgrav case sIgnore: 2578cf2b5f3bSDag-Erling Smørgrav case sUnsupported: 2579ca86bcf2SDag-Erling Smørgrav do_log2(opcode == sIgnore ? 2580ca86bcf2SDag-Erling Smørgrav SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO, 2581ca86bcf2SDag-Erling Smørgrav "%s line %d: %s option %s", filename, linenum, 258219261079SEd Maste opcode == sUnsupported ? "Unsupported" : "Deprecated", 258319261079SEd Maste keyword); 258419261079SEd Maste argv_consume(&ac); 2585af12a3e7SDag-Erling Smørgrav break; 2586af12a3e7SDag-Erling Smørgrav 258742f71286SMark Murray default: 2588af12a3e7SDag-Erling Smørgrav fatal("%s line %d: Missing handler for opcode %s (%d)", 258919261079SEd Maste filename, linenum, keyword, opcode); 2590511b41d2SMark Murray } 259119261079SEd Maste /* Check that there is no garbage at end of line. */ 259219261079SEd Maste if (ac > 0) { 259319261079SEd Maste error("%.200s line %d: keyword %s extra arguments " 259419261079SEd Maste "at end of line", filename, linenum, keyword); 259519261079SEd Maste goto out; 2596af12a3e7SDag-Erling Smørgrav } 2597af12a3e7SDag-Erling Smørgrav 259819261079SEd Maste /* success */ 259919261079SEd Maste ret = 0; 260019261079SEd Maste out: 260119261079SEd Maste argv_free(oav, oac); 260219261079SEd Maste return ret; 260319261079SEd Maste } 260419261079SEd Maste 260519261079SEd Maste int 260619261079SEd Maste process_server_config_line(ServerOptions *options, char *line, 260719261079SEd Maste const char *filename, int linenum, int *activep, 260819261079SEd Maste struct connection_info *connectinfo, struct include_list *includes) 260919261079SEd Maste { 261019261079SEd Maste int inc_flags = 0; 261119261079SEd Maste 261219261079SEd Maste return process_server_config_line_depth(options, line, filename, 261319261079SEd Maste linenum, activep, connectinfo, &inc_flags, 0, includes); 261419261079SEd Maste } 261519261079SEd Maste 261619261079SEd Maste 2617af12a3e7SDag-Erling Smørgrav /* Reads the server configuration file. */ 2618af12a3e7SDag-Erling Smørgrav 2619af12a3e7SDag-Erling Smørgrav void 2620190cef3dSDag-Erling Smørgrav load_server_config(const char *filename, struct sshbuf *conf) 2621af12a3e7SDag-Erling Smørgrav { 262219261079SEd Maste struct stat st; 2623190cef3dSDag-Erling Smørgrav char *line = NULL, *cp; 2624190cef3dSDag-Erling Smørgrav size_t linesize = 0; 2625a82e551fSDag-Erling Smørgrav FILE *f; 2626*f374ba41SEd Maste int r; 2627af12a3e7SDag-Erling Smørgrav 262819261079SEd Maste debug2_f("filename %s", filename); 262921e764dfSDag-Erling Smørgrav if ((f = fopen(filename, "r")) == NULL) { 2630af12a3e7SDag-Erling Smørgrav perror(filename); 2631af12a3e7SDag-Erling Smørgrav exit(1); 2632af12a3e7SDag-Erling Smørgrav } 2633190cef3dSDag-Erling Smørgrav sshbuf_reset(conf); 263419261079SEd Maste /* grow buffer, so realloc is avoided for large config files */ 263519261079SEd Maste if (fstat(fileno(f), &st) == 0 && st.st_size > 0 && 263619261079SEd Maste (r = sshbuf_allocate(conf, st.st_size)) != 0) 263719261079SEd Maste fatal_fr(r, "allocate"); 2638190cef3dSDag-Erling Smørgrav while (getline(&line, &linesize, f) != -1) { 263921e764dfSDag-Erling Smørgrav /* 264019261079SEd Maste * Strip whitespace 264121e764dfSDag-Erling Smørgrav * NB - preserve newlines, they are needed to reproduce 264221e764dfSDag-Erling Smørgrav * line numbers later for error messages 264321e764dfSDag-Erling Smørgrav */ 264421e764dfSDag-Erling Smørgrav cp = line + strspn(line, " \t\r"); 2645190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0) 264619261079SEd Maste fatal_fr(r, "sshbuf_put"); 264721e764dfSDag-Erling Smørgrav } 2648190cef3dSDag-Erling Smørgrav free(line); 2649190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(conf, 0)) != 0) 265019261079SEd Maste fatal_fr(r, "sshbuf_put_u8"); 265121e764dfSDag-Erling Smørgrav fclose(f); 265219261079SEd Maste debug2_f("done config len = %zu", sshbuf_len(conf)); 265321e764dfSDag-Erling Smørgrav } 265421e764dfSDag-Erling Smørgrav 265521e764dfSDag-Erling Smørgrav void 2656462c32cbSDag-Erling Smørgrav parse_server_match_config(ServerOptions *options, 265719261079SEd Maste struct include_list *includes, struct connection_info *connectinfo) 265821e764dfSDag-Erling Smørgrav { 2659333ee039SDag-Erling Smørgrav ServerOptions mo; 2660333ee039SDag-Erling Smørgrav 2661333ee039SDag-Erling Smørgrav initialize_server_options(&mo); 266219261079SEd Maste parse_server_config(&mo, "reprocess config", cfg, includes, 266387c1498dSEd Maste connectinfo, 0); 2664d4af9e69SDag-Erling Smørgrav copy_set_server_options(options, &mo, 0); 2665333ee039SDag-Erling Smørgrav } 2666333ee039SDag-Erling Smørgrav 2667462c32cbSDag-Erling Smørgrav int parse_server_match_testspec(struct connection_info *ci, char *spec) 2668462c32cbSDag-Erling Smørgrav { 2669462c32cbSDag-Erling Smørgrav char *p; 2670462c32cbSDag-Erling Smørgrav 2671462c32cbSDag-Erling Smørgrav while ((p = strsep(&spec, ",")) && *p != '\0') { 2672462c32cbSDag-Erling Smørgrav if (strncmp(p, "addr=", 5) == 0) { 2673462c32cbSDag-Erling Smørgrav ci->address = xstrdup(p + 5); 2674462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "host=", 5) == 0) { 2675462c32cbSDag-Erling Smørgrav ci->host = xstrdup(p + 5); 2676462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "user=", 5) == 0) { 2677462c32cbSDag-Erling Smørgrav ci->user = xstrdup(p + 5); 2678462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "laddr=", 6) == 0) { 2679462c32cbSDag-Erling Smørgrav ci->laddress = xstrdup(p + 6); 268047dd1d1bSDag-Erling Smørgrav } else if (strncmp(p, "rdomain=", 8) == 0) { 268147dd1d1bSDag-Erling Smørgrav ci->rdomain = xstrdup(p + 8); 2682462c32cbSDag-Erling Smørgrav } else if (strncmp(p, "lport=", 6) == 0) { 2683462c32cbSDag-Erling Smørgrav ci->lport = a2port(p + 6); 2684462c32cbSDag-Erling Smørgrav if (ci->lport == -1) { 2685462c32cbSDag-Erling Smørgrav fprintf(stderr, "Invalid port '%s' in test mode" 2686462c32cbSDag-Erling Smørgrav " specification %s\n", p+6, p); 2687462c32cbSDag-Erling Smørgrav return -1; 2688462c32cbSDag-Erling Smørgrav } 2689462c32cbSDag-Erling Smørgrav } else { 2690462c32cbSDag-Erling Smørgrav fprintf(stderr, "Invalid test mode specification %s\n", 2691462c32cbSDag-Erling Smørgrav p); 2692462c32cbSDag-Erling Smørgrav return -1; 2693462c32cbSDag-Erling Smørgrav } 2694462c32cbSDag-Erling Smørgrav } 2695462c32cbSDag-Erling Smørgrav return 0; 2696462c32cbSDag-Erling Smørgrav } 2697462c32cbSDag-Erling Smørgrav 2698462c32cbSDag-Erling Smørgrav /* 2699d4af9e69SDag-Erling Smørgrav * Copy any supported values that are set. 2700d4af9e69SDag-Erling Smørgrav * 27017aee6ffeSDag-Erling Smørgrav * If the preauth flag is set, we do not bother copying the string or 2702d4af9e69SDag-Erling Smørgrav * array values that are not used pre-authentication, because any that we 2703190cef3dSDag-Erling Smørgrav * do use must be explicitly sent in mm_getpwnamallow(). 2704d4af9e69SDag-Erling Smørgrav */ 2705333ee039SDag-Erling Smørgrav void 2706d4af9e69SDag-Erling Smørgrav copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) 2707333ee039SDag-Erling Smørgrav { 2708f7167e0eSDag-Erling Smørgrav #define M_CP_INTOPT(n) do {\ 2709f7167e0eSDag-Erling Smørgrav if (src->n != -1) \ 2710f7167e0eSDag-Erling Smørgrav dst->n = src->n; \ 2711f7167e0eSDag-Erling Smørgrav } while (0) 2712f7167e0eSDag-Erling Smørgrav 2713d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(password_authentication); 2714d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(gss_authentication); 2715d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(pubkey_authentication); 271619261079SEd Maste M_CP_INTOPT(pubkey_auth_options); 2717d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(kerberos_authentication); 2718d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(hostbased_authentication); 2719e2f6069cSDag-Erling Smørgrav M_CP_INTOPT(hostbased_uses_name_from_packet_only); 2720d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(kbd_interactive_authentication); 2721d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(permit_root_login); 2722cce7d346SDag-Erling Smørgrav M_CP_INTOPT(permit_empty_passwd); 272319261079SEd Maste M_CP_INTOPT(ignore_rhosts); 2724d4af9e69SDag-Erling Smørgrav 2725d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(allow_tcp_forwarding); 2726a0ee8cc6SDag-Erling Smørgrav M_CP_INTOPT(allow_streamlocal_forwarding); 2727d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(allow_agent_forwarding); 2728ca86bcf2SDag-Erling Smørgrav M_CP_INTOPT(disable_forwarding); 27294f52dfbbSDag-Erling Smørgrav M_CP_INTOPT(expose_userauth_info); 2730e2f6069cSDag-Erling Smørgrav M_CP_INTOPT(permit_tun); 2731a0ee8cc6SDag-Erling Smørgrav M_CP_INTOPT(fwd_opts.gateway_ports); 2732076ad2f8SDag-Erling Smørgrav M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); 2733d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(x11_display_offset); 2734d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(x11_forwarding); 2735d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(x11_use_localhost); 2736f7167e0eSDag-Erling Smørgrav M_CP_INTOPT(permit_tty); 2737a0ee8cc6SDag-Erling Smørgrav M_CP_INTOPT(permit_user_rc); 2738d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(max_sessions); 2739d4af9e69SDag-Erling Smørgrav M_CP_INTOPT(max_authtries); 2740ca86bcf2SDag-Erling Smørgrav M_CP_INTOPT(client_alive_count_max); 2741ca86bcf2SDag-Erling Smørgrav M_CP_INTOPT(client_alive_interval); 27424a421b63SDag-Erling Smørgrav M_CP_INTOPT(ip_qos_interactive); 27434a421b63SDag-Erling Smørgrav M_CP_INTOPT(ip_qos_bulk); 2744e4a9863fSDag-Erling Smørgrav M_CP_INTOPT(rekey_limit); 2745e4a9863fSDag-Erling Smørgrav M_CP_INTOPT(rekey_interval); 27464f52dfbbSDag-Erling Smørgrav M_CP_INTOPT(log_level); 274738a52bd3SEd Maste M_CP_INTOPT(required_rsa_size); 2748*f374ba41SEd Maste M_CP_INTOPT(unused_connection_timeout); 2749d4af9e69SDag-Erling Smørgrav 2750076ad2f8SDag-Erling Smørgrav /* 2751076ad2f8SDag-Erling Smørgrav * The bind_mask is a mode_t that may be unsigned, so we can't use 2752076ad2f8SDag-Erling Smørgrav * M_CP_INTOPT - it does a signed comparison that causes compiler 2753076ad2f8SDag-Erling Smørgrav * warnings. 2754076ad2f8SDag-Erling Smørgrav */ 2755076ad2f8SDag-Erling Smørgrav if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) { 2756076ad2f8SDag-Erling Smørgrav dst->fwd_opts.streamlocal_bind_mask = 2757076ad2f8SDag-Erling Smørgrav src->fwd_opts.streamlocal_bind_mask; 2758076ad2f8SDag-Erling Smørgrav } 2759076ad2f8SDag-Erling Smørgrav 2760f7167e0eSDag-Erling Smørgrav /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ 2761f7167e0eSDag-Erling Smørgrav #define M_CP_STROPT(n) do {\ 2762f7167e0eSDag-Erling Smørgrav if (src->n != NULL && dst->n != src->n) { \ 2763f7167e0eSDag-Erling Smørgrav free(dst->n); \ 2764f7167e0eSDag-Erling Smørgrav dst->n = src->n; \ 2765f7167e0eSDag-Erling Smørgrav } \ 2766f7167e0eSDag-Erling Smørgrav } while(0) 276747dd1d1bSDag-Erling Smørgrav #define M_CP_STRARRAYOPT(s, num_s) do {\ 276847dd1d1bSDag-Erling Smørgrav u_int i; \ 276947dd1d1bSDag-Erling Smørgrav if (src->num_s != 0) { \ 277047dd1d1bSDag-Erling Smørgrav for (i = 0; i < dst->num_s; i++) \ 277147dd1d1bSDag-Erling Smørgrav free(dst->s[i]); \ 277247dd1d1bSDag-Erling Smørgrav free(dst->s); \ 277347dd1d1bSDag-Erling Smørgrav dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \ 277447dd1d1bSDag-Erling Smørgrav for (i = 0; i < src->num_s; i++) \ 277547dd1d1bSDag-Erling Smørgrav dst->s[i] = xstrdup(src->s[i]); \ 277647dd1d1bSDag-Erling Smørgrav dst->num_s = src->num_s; \ 27774f52dfbbSDag-Erling Smørgrav } \ 27784f52dfbbSDag-Erling Smørgrav } while(0) 2779f7167e0eSDag-Erling Smørgrav 2780e146993eSDag-Erling Smørgrav /* See comment in servconf.h */ 2781e146993eSDag-Erling Smørgrav COPY_MATCH_STRING_OPTS(); 2782e146993eSDag-Erling Smørgrav 2783acc1a9efSDag-Erling Smørgrav /* Arguments that accept '+...' need to be expanded */ 2784acc1a9efSDag-Erling Smørgrav assemble_algorithms(dst); 2785acc1a9efSDag-Erling Smørgrav 2786e146993eSDag-Erling Smørgrav /* 2787e146993eSDag-Erling Smørgrav * The only things that should be below this point are string options 2788e146993eSDag-Erling Smørgrav * which are only used after authentication. 2789e146993eSDag-Erling Smørgrav */ 2790d4af9e69SDag-Erling Smørgrav if (preauth) 2791d4af9e69SDag-Erling Smørgrav return; 2792e146993eSDag-Erling Smørgrav 2793acc1a9efSDag-Erling Smørgrav /* These options may be "none" to clear a global setting */ 2794d4af9e69SDag-Erling Smørgrav M_CP_STROPT(adm_forced_command); 2795acc1a9efSDag-Erling Smørgrav if (option_clear_or_none(dst->adm_forced_command)) { 2796acc1a9efSDag-Erling Smørgrav free(dst->adm_forced_command); 2797acc1a9efSDag-Erling Smørgrav dst->adm_forced_command = NULL; 2798acc1a9efSDag-Erling Smørgrav } 2799d4af9e69SDag-Erling Smørgrav M_CP_STROPT(chroot_directory); 2800acc1a9efSDag-Erling Smørgrav if (option_clear_or_none(dst->chroot_directory)) { 2801acc1a9efSDag-Erling Smørgrav free(dst->chroot_directory); 2802acc1a9efSDag-Erling Smørgrav dst->chroot_directory = NULL; 2803acc1a9efSDag-Erling Smørgrav } 2804333ee039SDag-Erling Smørgrav } 2805d4af9e69SDag-Erling Smørgrav 2806d4af9e69SDag-Erling Smørgrav #undef M_CP_INTOPT 2807d4af9e69SDag-Erling Smørgrav #undef M_CP_STROPT 2808e146993eSDag-Erling Smørgrav #undef M_CP_STRARRAYOPT 2809333ee039SDag-Erling Smørgrav 281019261079SEd Maste #define SERVCONF_MAX_DEPTH 16 281119261079SEd Maste static void 281219261079SEd Maste parse_server_config_depth(ServerOptions *options, const char *filename, 281319261079SEd Maste struct sshbuf *conf, struct include_list *includes, 281419261079SEd Maste struct connection_info *connectinfo, int flags, int *activep, int depth) 2815333ee039SDag-Erling Smørgrav { 281619261079SEd Maste int linenum, bad_options = 0; 281721e764dfSDag-Erling Smørgrav char *cp, *obuf, *cbuf; 281821e764dfSDag-Erling Smørgrav 281919261079SEd Maste if (depth < 0 || depth > SERVCONF_MAX_DEPTH) 282019261079SEd Maste fatal("Too many recursive configuration includes"); 282119261079SEd Maste 282219261079SEd Maste debug2_f("config %s len %zu%s", filename, sshbuf_len(conf), 282319261079SEd Maste (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : "")); 282421e764dfSDag-Erling Smørgrav 2825076ad2f8SDag-Erling Smørgrav if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) 282619261079SEd Maste fatal_f("sshbuf_dup_string failed"); 282721e764dfSDag-Erling Smørgrav linenum = 1; 282821e764dfSDag-Erling Smørgrav while ((cp = strsep(&cbuf, "\n")) != NULL) { 282919261079SEd Maste if (process_server_config_line_depth(options, cp, 283019261079SEd Maste filename, linenum++, activep, connectinfo, &flags, 283119261079SEd Maste depth, includes) != 0) 2832af12a3e7SDag-Erling Smørgrav bad_options++; 2833511b41d2SMark Murray } 2834e4a9863fSDag-Erling Smørgrav free(obuf); 2835ca3176e7SBrian Feldman if (bad_options > 0) 2836af12a3e7SDag-Erling Smørgrav fatal("%s: terminating, %d bad configuration options", 2837511b41d2SMark Murray filename, bad_options); 283819261079SEd Maste } 283919261079SEd Maste 284019261079SEd Maste void 284119261079SEd Maste parse_server_config(ServerOptions *options, const char *filename, 284219261079SEd Maste struct sshbuf *conf, struct include_list *includes, 284387c1498dSEd Maste struct connection_info *connectinfo, int reexec) 284419261079SEd Maste { 284519261079SEd Maste int active = connectinfo ? 0 : 1; 284619261079SEd Maste parse_server_config_depth(options, filename, conf, includes, 284719261079SEd Maste connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0); 284887c1498dSEd Maste if (!reexec) 2849557f75e5SDag-Erling Smørgrav process_queued_listen_addrs(options); 2850511b41d2SMark Murray } 2851d4af9e69SDag-Erling Smørgrav 2852d4af9e69SDag-Erling Smørgrav static const char * 2853e146993eSDag-Erling Smørgrav fmt_multistate_int(int val, const struct multistate *m) 2854d4af9e69SDag-Erling Smørgrav { 2855e146993eSDag-Erling Smørgrav u_int i; 2856e146993eSDag-Erling Smørgrav 2857e146993eSDag-Erling Smørgrav for (i = 0; m[i].key != NULL; i++) { 2858e146993eSDag-Erling Smørgrav if (m[i].value == val) 2859e146993eSDag-Erling Smørgrav return m[i].key; 2860e146993eSDag-Erling Smørgrav } 2861d4af9e69SDag-Erling Smørgrav return "UNKNOWN"; 2862d4af9e69SDag-Erling Smørgrav } 2863e146993eSDag-Erling Smørgrav 2864e146993eSDag-Erling Smørgrav static const char * 2865e146993eSDag-Erling Smørgrav fmt_intarg(ServerOpCodes code, int val) 2866e146993eSDag-Erling Smørgrav { 2867e146993eSDag-Erling Smørgrav if (val == -1) 2868e146993eSDag-Erling Smørgrav return "unset"; 2869e146993eSDag-Erling Smørgrav switch (code) { 2870e146993eSDag-Erling Smørgrav case sAddressFamily: 2871e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_addressfamily); 2872e146993eSDag-Erling Smørgrav case sPermitRootLogin: 2873e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_permitrootlogin); 2874e146993eSDag-Erling Smørgrav case sGatewayPorts: 2875e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_gatewayports); 2876e146993eSDag-Erling Smørgrav case sCompression: 2877e146993eSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_compression); 28786888a9beSDag-Erling Smørgrav case sAllowTcpForwarding: 28796888a9beSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_tcpfwd); 2880a0ee8cc6SDag-Erling Smørgrav case sAllowStreamLocalForwarding: 2881a0ee8cc6SDag-Erling Smørgrav return fmt_multistate_int(val, multistate_tcpfwd); 288219261079SEd Maste case sIgnoreRhosts: 288319261079SEd Maste return fmt_multistate_int(val, multistate_ignore_rhosts); 2884bc5531deSDag-Erling Smørgrav case sFingerprintHash: 2885bc5531deSDag-Erling Smørgrav return ssh_digest_alg_name(val); 2886e146993eSDag-Erling Smørgrav default: 2887d4af9e69SDag-Erling Smørgrav switch (val) { 2888d4af9e69SDag-Erling Smørgrav case 0: 2889d4af9e69SDag-Erling Smørgrav return "no"; 2890d4af9e69SDag-Erling Smørgrav case 1: 2891d4af9e69SDag-Erling Smørgrav return "yes"; 2892e146993eSDag-Erling Smørgrav default: 2893d4af9e69SDag-Erling Smørgrav return "UNKNOWN"; 2894d4af9e69SDag-Erling Smørgrav } 2895e146993eSDag-Erling Smørgrav } 2896e146993eSDag-Erling Smørgrav } 2897d4af9e69SDag-Erling Smørgrav 2898d4af9e69SDag-Erling Smørgrav static void 2899d4af9e69SDag-Erling Smørgrav dump_cfg_int(ServerOpCodes code, int val) 2900d4af9e69SDag-Erling Smørgrav { 2901*f374ba41SEd Maste if (code == sUnusedConnectionTimeout && val == 0) { 2902*f374ba41SEd Maste printf("%s none\n", lookup_opcode_name(code)); 2903*f374ba41SEd Maste return; 2904*f374ba41SEd Maste } 2905d4af9e69SDag-Erling Smørgrav printf("%s %d\n", lookup_opcode_name(code), val); 2906d4af9e69SDag-Erling Smørgrav } 2907d4af9e69SDag-Erling Smørgrav 2908d4af9e69SDag-Erling Smørgrav static void 2909557f75e5SDag-Erling Smørgrav dump_cfg_oct(ServerOpCodes code, int val) 2910557f75e5SDag-Erling Smørgrav { 2911557f75e5SDag-Erling Smørgrav printf("%s 0%o\n", lookup_opcode_name(code), val); 2912557f75e5SDag-Erling Smørgrav } 2913557f75e5SDag-Erling Smørgrav 2914557f75e5SDag-Erling Smørgrav static void 2915d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(ServerOpCodes code, int val) 2916d4af9e69SDag-Erling Smørgrav { 2917d4af9e69SDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2918d4af9e69SDag-Erling Smørgrav } 2919d4af9e69SDag-Erling Smørgrav 2920d4af9e69SDag-Erling Smørgrav static void 2921d4af9e69SDag-Erling Smørgrav dump_cfg_string(ServerOpCodes code, const char *val) 2922d4af9e69SDag-Erling Smørgrav { 2923bc5531deSDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), 2924bc5531deSDag-Erling Smørgrav val == NULL ? "none" : val); 2925d4af9e69SDag-Erling Smørgrav } 2926d4af9e69SDag-Erling Smørgrav 2927d4af9e69SDag-Erling Smørgrav static void 2928d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) 2929d4af9e69SDag-Erling Smørgrav { 2930d4af9e69SDag-Erling Smørgrav u_int i; 2931d4af9e69SDag-Erling Smørgrav 2932d4af9e69SDag-Erling Smørgrav for (i = 0; i < count; i++) 2933d4af9e69SDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2934d4af9e69SDag-Erling Smørgrav } 2935d4af9e69SDag-Erling Smørgrav 2936e146993eSDag-Erling Smørgrav static void 2937e146993eSDag-Erling Smørgrav dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) 2938e146993eSDag-Erling Smørgrav { 2939e146993eSDag-Erling Smørgrav u_int i; 2940e146993eSDag-Erling Smørgrav 2941076ad2f8SDag-Erling Smørgrav if (count <= 0 && code != sAuthenticationMethods) 2942557f75e5SDag-Erling Smørgrav return; 2943e146993eSDag-Erling Smørgrav printf("%s", lookup_opcode_name(code)); 2944e146993eSDag-Erling Smørgrav for (i = 0; i < count; i++) 2945e146993eSDag-Erling Smørgrav printf(" %s", vals[i]); 2946076ad2f8SDag-Erling Smørgrav if (code == sAuthenticationMethods && count == 0) 2947076ad2f8SDag-Erling Smørgrav printf(" any"); 2948*f374ba41SEd Maste else if (code == sChannelTimeout && count == 0) 2949*f374ba41SEd Maste printf(" none"); 2950e146993eSDag-Erling Smørgrav printf("\n"); 2951e146993eSDag-Erling Smørgrav } 2952e146993eSDag-Erling Smørgrav 295347dd1d1bSDag-Erling Smørgrav static char * 295447dd1d1bSDag-Erling Smørgrav format_listen_addrs(struct listenaddr *la) 2955d4af9e69SDag-Erling Smørgrav { 295647dd1d1bSDag-Erling Smørgrav int r; 2957d4af9e69SDag-Erling Smørgrav struct addrinfo *ai; 295847dd1d1bSDag-Erling Smørgrav char addr[NI_MAXHOST], port[NI_MAXSERV]; 2959557f75e5SDag-Erling Smørgrav char *laddr1 = xstrdup(""), *laddr2 = NULL; 2960d4af9e69SDag-Erling Smørgrav 2961557f75e5SDag-Erling Smørgrav /* 2962557f75e5SDag-Erling Smørgrav * ListenAddress must be after Port. add_one_listen_addr pushes 2963557f75e5SDag-Erling Smørgrav * addresses onto a stack, so to maintain ordering we need to 2964557f75e5SDag-Erling Smørgrav * print these in reverse order. 2965557f75e5SDag-Erling Smørgrav */ 296647dd1d1bSDag-Erling Smørgrav for (ai = la->addrs; ai; ai = ai->ai_next) { 296747dd1d1bSDag-Erling Smørgrav if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, 2968d4af9e69SDag-Erling Smørgrav sizeof(addr), port, sizeof(port), 2969d4af9e69SDag-Erling Smørgrav NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { 297047dd1d1bSDag-Erling Smørgrav error("getnameinfo: %.100s", ssh_gai_strerror(r)); 297147dd1d1bSDag-Erling Smørgrav continue; 297247dd1d1bSDag-Erling Smørgrav } 2973557f75e5SDag-Erling Smørgrav laddr2 = laddr1; 297447dd1d1bSDag-Erling Smørgrav if (ai->ai_family == AF_INET6) { 297547dd1d1bSDag-Erling Smørgrav xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s", 297647dd1d1bSDag-Erling Smørgrav addr, port, 297747dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : " rdomain ", 297847dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : la->rdomain, 297947dd1d1bSDag-Erling Smørgrav laddr2); 298047dd1d1bSDag-Erling Smørgrav } else { 298147dd1d1bSDag-Erling Smørgrav xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s", 298247dd1d1bSDag-Erling Smørgrav addr, port, 298347dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : " rdomain ", 298447dd1d1bSDag-Erling Smørgrav la->rdomain == NULL ? "" : la->rdomain, 298547dd1d1bSDag-Erling Smørgrav laddr2); 298647dd1d1bSDag-Erling Smørgrav } 2987557f75e5SDag-Erling Smørgrav free(laddr2); 2988d4af9e69SDag-Erling Smørgrav } 298947dd1d1bSDag-Erling Smørgrav return laddr1; 2990d4af9e69SDag-Erling Smørgrav } 299147dd1d1bSDag-Erling Smørgrav 299247dd1d1bSDag-Erling Smørgrav void 299347dd1d1bSDag-Erling Smørgrav dump_config(ServerOptions *o) 299447dd1d1bSDag-Erling Smørgrav { 299547dd1d1bSDag-Erling Smørgrav char *s; 299647dd1d1bSDag-Erling Smørgrav u_int i; 299747dd1d1bSDag-Erling Smørgrav 299847dd1d1bSDag-Erling Smørgrav /* these are usually at the top of the config */ 299947dd1d1bSDag-Erling Smørgrav for (i = 0; i < o->num_ports; i++) 300047dd1d1bSDag-Erling Smørgrav printf("port %d\n", o->ports[i]); 300147dd1d1bSDag-Erling Smørgrav dump_cfg_fmtint(sAddressFamily, o->address_family); 300247dd1d1bSDag-Erling Smørgrav 300347dd1d1bSDag-Erling Smørgrav for (i = 0; i < o->num_listen_addrs; i++) { 300447dd1d1bSDag-Erling Smørgrav s = format_listen_addrs(&o->listen_addrs[i]); 300547dd1d1bSDag-Erling Smørgrav printf("%s", s); 300647dd1d1bSDag-Erling Smørgrav free(s); 300747dd1d1bSDag-Erling Smørgrav } 3008d4af9e69SDag-Erling Smørgrav 3009d4af9e69SDag-Erling Smørgrav /* integer arguments */ 3010cce7d346SDag-Erling Smørgrav #ifdef USE_PAM 3011557f75e5SDag-Erling Smørgrav dump_cfg_fmtint(sUsePAM, o->use_pam); 3012cce7d346SDag-Erling Smørgrav #endif 3013d4af9e69SDag-Erling Smørgrav dump_cfg_int(sLoginGraceTime, o->login_grace_time); 3014d4af9e69SDag-Erling Smørgrav dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); 3015d4af9e69SDag-Erling Smørgrav dump_cfg_int(sMaxAuthTries, o->max_authtries); 3016cce7d346SDag-Erling Smørgrav dump_cfg_int(sMaxSessions, o->max_sessions); 3017d4af9e69SDag-Erling Smørgrav dump_cfg_int(sClientAliveInterval, o->client_alive_interval); 3018d4af9e69SDag-Erling Smørgrav dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); 301938a52bd3SEd Maste dump_cfg_int(sRequiredRSASize, o->required_rsa_size); 3020557f75e5SDag-Erling Smørgrav dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); 3021*f374ba41SEd Maste dump_cfg_int(sUnusedConnectionTimeout, o->unused_connection_timeout); 3022d4af9e69SDag-Erling Smørgrav 3023d4af9e69SDag-Erling Smørgrav /* formatted integer arguments */ 3024d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); 3025d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); 3026d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); 3027d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); 3028d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, 3029d4af9e69SDag-Erling Smørgrav o->hostbased_uses_name_from_packet_only); 3030d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); 3031cce7d346SDag-Erling Smørgrav #ifdef KRB5 3032d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); 3033d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); 3034d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); 3035cce7d346SDag-Erling Smørgrav # ifdef USE_AFS 3036d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); 3037cce7d346SDag-Erling Smørgrav # endif 3038cce7d346SDag-Erling Smørgrav #endif 3039cce7d346SDag-Erling Smørgrav #ifdef GSSAPI 3040d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 3041d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 3042cce7d346SDag-Erling Smørgrav #endif 3043d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 3044d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sKbdInteractiveAuthentication, 3045d4af9e69SDag-Erling Smørgrav o->kbd_interactive_authentication); 3046d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPrintMotd, o->print_motd); 3047acc1a9efSDag-Erling Smørgrav #ifndef DISABLE_LASTLOG 3048d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); 3049acc1a9efSDag-Erling Smørgrav #endif 3050d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); 3051d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); 3052f7167e0eSDag-Erling Smørgrav dump_cfg_fmtint(sPermitTTY, o->permit_tty); 3053a0ee8cc6SDag-Erling Smørgrav dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); 3054d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sStrictModes, o->strict_modes); 3055d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); 3056d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); 3057d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sCompression, o->compression); 3058a0ee8cc6SDag-Erling Smørgrav dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); 3059d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sUseDNS, o->use_dns); 3060d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 3061557f75e5SDag-Erling Smørgrav dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); 3062ca86bcf2SDag-Erling Smørgrav dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding); 3063a0ee8cc6SDag-Erling Smørgrav dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); 3064076ad2f8SDag-Erling Smørgrav dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 3065bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); 30664f52dfbbSDag-Erling Smørgrav dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); 3067b2af61ecSKurt Lidl dump_cfg_fmtint(sUseBlacklist, o->use_blacklist); 3068d4af9e69SDag-Erling Smørgrav 3069d4af9e69SDag-Erling Smørgrav /* string arguments */ 3070d4af9e69SDag-Erling Smørgrav dump_cfg_string(sPidFile, o->pid_file); 307119261079SEd Maste dump_cfg_string(sModuliFile, o->moduli_file); 3072d4af9e69SDag-Erling Smørgrav dump_cfg_string(sXAuthLocation, o->xauth_location); 307319261079SEd Maste dump_cfg_string(sCiphers, o->ciphers); 307419261079SEd Maste dump_cfg_string(sMacs, o->macs); 3075d4af9e69SDag-Erling Smørgrav dump_cfg_string(sBanner, o->banner); 3076d4af9e69SDag-Erling Smørgrav dump_cfg_string(sForceCommand, o->adm_forced_command); 3077b15c8340SDag-Erling Smørgrav dump_cfg_string(sChrootDirectory, o->chroot_directory); 3078b15c8340SDag-Erling Smørgrav dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); 3079b15c8340SDag-Erling Smørgrav dump_cfg_string(sRevokedKeys, o->revoked_keys_file); 308019261079SEd Maste dump_cfg_string(sSecurityKeyProvider, o->sk_provider); 3081e2f6069cSDag-Erling Smørgrav dump_cfg_string(sAuthorizedPrincipalsFile, 3082e2f6069cSDag-Erling Smørgrav o->authorized_principals_file); 3083557f75e5SDag-Erling Smørgrav dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' 3084557f75e5SDag-Erling Smørgrav ? "none" : o->version_addendum); 30856888a9beSDag-Erling Smørgrav dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); 30866888a9beSDag-Erling Smørgrav dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); 3087557f75e5SDag-Erling Smørgrav dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); 3088557f75e5SDag-Erling Smørgrav dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); 3089e4a9863fSDag-Erling Smørgrav dump_cfg_string(sHostKeyAgent, o->host_key_agent); 309019261079SEd Maste dump_cfg_string(sKexAlgorithms, o->kex_algorithms); 309119261079SEd Maste dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms); 309219261079SEd Maste dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 309319261079SEd Maste dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms); 309419261079SEd Maste dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); 309519261079SEd Maste #if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN) 309647dd1d1bSDag-Erling Smørgrav dump_cfg_string(sRDomain, o->routing_domain); 309719261079SEd Maste #endif 3098d4af9e69SDag-Erling Smørgrav 3099d4af9e69SDag-Erling Smørgrav /* string arguments requiring a lookup */ 3100d4af9e69SDag-Erling Smørgrav dump_cfg_string(sLogLevel, log_level_name(o->log_level)); 3101d4af9e69SDag-Erling Smørgrav dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); 3102d4af9e69SDag-Erling Smørgrav 3103d4af9e69SDag-Erling Smørgrav /* string array arguments */ 3104e146993eSDag-Erling Smørgrav dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, 3105e146993eSDag-Erling Smørgrav o->authorized_keys_files); 3106d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, 3107d4af9e69SDag-Erling Smørgrav o->host_key_files); 3108557f75e5SDag-Erling Smørgrav dump_cfg_strarray(sHostCertificate, o->num_host_cert_files, 3109b15c8340SDag-Erling Smørgrav o->host_cert_files); 3110d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); 3111d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); 3112d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); 3113d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); 3114d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); 3115190cef3dSDag-Erling Smørgrav dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv); 31166888a9beSDag-Erling Smørgrav dump_cfg_strarray_oneline(sAuthenticationMethods, 31176888a9beSDag-Erling Smørgrav o->num_auth_methods, o->auth_methods); 311819261079SEd Maste dump_cfg_strarray_oneline(sLogVerbose, 311919261079SEd Maste o->num_log_verbose, o->log_verbose); 3120*f374ba41SEd Maste dump_cfg_strarray_oneline(sChannelTimeout, 3121*f374ba41SEd Maste o->num_channel_timeouts, o->channel_timeouts); 3122d4af9e69SDag-Erling Smørgrav 3123d4af9e69SDag-Erling Smørgrav /* other arguments */ 3124d4af9e69SDag-Erling Smørgrav for (i = 0; i < o->num_subsystems; i++) 3125d4af9e69SDag-Erling Smørgrav printf("subsystem %s %s\n", o->subsystem_name[i], 3126d4af9e69SDag-Erling Smørgrav o->subsystem_args[i]); 3127d4af9e69SDag-Erling Smørgrav 3128d4af9e69SDag-Erling Smørgrav printf("maxstartups %d:%d:%d\n", o->max_startups_begin, 3129d4af9e69SDag-Erling Smørgrav o->max_startups_rate, o->max_startups); 313019261079SEd Maste printf("persourcemaxstartups "); 313119261079SEd Maste if (o->per_source_max_startups == INT_MAX) 313219261079SEd Maste printf("none\n"); 313319261079SEd Maste else 313419261079SEd Maste printf("%d\n", o->per_source_max_startups); 313519261079SEd Maste printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4, 313619261079SEd Maste o->per_source_masklen_ipv6); 3137d4af9e69SDag-Erling Smørgrav 313847dd1d1bSDag-Erling Smørgrav s = NULL; 313947dd1d1bSDag-Erling Smørgrav for (i = 0; tunmode_desc[i].val != -1; i++) { 3140d4af9e69SDag-Erling Smørgrav if (tunmode_desc[i].val == o->permit_tun) { 3141d4af9e69SDag-Erling Smørgrav s = tunmode_desc[i].text; 3142d4af9e69SDag-Erling Smørgrav break; 3143d4af9e69SDag-Erling Smørgrav } 314447dd1d1bSDag-Erling Smørgrav } 3145d4af9e69SDag-Erling Smørgrav dump_cfg_string(sPermitTunnel, s); 3146d4af9e69SDag-Erling Smørgrav 3147e146993eSDag-Erling Smørgrav printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 3148e146993eSDag-Erling Smørgrav printf("%s\n", iptos2str(o->ip_qos_bulk)); 31494a421b63SDag-Erling Smørgrav 3150acc1a9efSDag-Erling Smørgrav printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, 3151e4a9863fSDag-Erling Smørgrav o->rekey_interval); 3152e4a9863fSDag-Erling Smørgrav 31534f52dfbbSDag-Erling Smørgrav printf("permitopen"); 31544f52dfbbSDag-Erling Smørgrav if (o->num_permitted_opens == 0) 31554f52dfbbSDag-Erling Smørgrav printf(" any"); 31564f52dfbbSDag-Erling Smørgrav else { 31574f52dfbbSDag-Erling Smørgrav for (i = 0; i < o->num_permitted_opens; i++) 31584f52dfbbSDag-Erling Smørgrav printf(" %s", o->permitted_opens[i]); 31594f52dfbbSDag-Erling Smørgrav } 31604f52dfbbSDag-Erling Smørgrav printf("\n"); 3161190cef3dSDag-Erling Smørgrav printf("permitlisten"); 3162190cef3dSDag-Erling Smørgrav if (o->num_permitted_listens == 0) 3163190cef3dSDag-Erling Smørgrav printf(" any"); 3164190cef3dSDag-Erling Smørgrav else { 3165190cef3dSDag-Erling Smørgrav for (i = 0; i < o->num_permitted_listens; i++) 3166190cef3dSDag-Erling Smørgrav printf(" %s", o->permitted_listens[i]); 3167190cef3dSDag-Erling Smørgrav } 3168190cef3dSDag-Erling Smørgrav printf("\n"); 3169190cef3dSDag-Erling Smørgrav 317019261079SEd Maste if (o->permit_user_env_allowlist == NULL) { 3171190cef3dSDag-Erling Smørgrav dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 3172190cef3dSDag-Erling Smørgrav } else { 3173190cef3dSDag-Erling Smørgrav printf("permituserenvironment %s\n", 317419261079SEd Maste o->permit_user_env_allowlist); 3175190cef3dSDag-Erling Smørgrav } 3176190cef3dSDag-Erling Smørgrav 317719261079SEd Maste printf("pubkeyauthoptions"); 317819261079SEd Maste if (o->pubkey_auth_options == 0) 317919261079SEd Maste printf(" none"); 318019261079SEd Maste if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) 318119261079SEd Maste printf(" touch-required"); 318219261079SEd Maste if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) 318319261079SEd Maste printf(" verify-required"); 318419261079SEd Maste printf("\n"); 3185d4af9e69SDag-Erling Smørgrav } 3186