17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 37c478bd9Sstevel@tonic-gate * All rights reserved 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 67c478bd9Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 77c478bd9Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 87c478bd9Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 97c478bd9Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 107c478bd9Sstevel@tonic-gate */ 117c478bd9Sstevel@tonic-gate /* 12bdb005b5SDarren J Moffat * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 13*33c41f2bSJoshua M. Clulow * Copyright 2013 Joyent, Inc. All rights reserved. 147c478bd9Sstevel@tonic-gate */ 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate #include "includes.h" 177c478bd9Sstevel@tonic-gate RCSID("$OpenBSD: servconf.c,v 1.115 2002/09/04 18:52:42 stevesk Exp $"); 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN 207c478bd9Sstevel@tonic-gate #include <deflt.h> 217c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate #if defined(KRB4) 247c478bd9Sstevel@tonic-gate #include <krb.h> 257c478bd9Sstevel@tonic-gate #endif 267c478bd9Sstevel@tonic-gate #if defined(KRB5) 277c478bd9Sstevel@tonic-gate #ifdef HEIMDAL 287c478bd9Sstevel@tonic-gate #include <krb.h> 297c478bd9Sstevel@tonic-gate #else 307c478bd9Sstevel@tonic-gate /* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V 317c478bd9Sstevel@tonic-gate * keytab */ 327c478bd9Sstevel@tonic-gate #define KEYFILE "/etc/krb5.keytab" 337c478bd9Sstevel@tonic-gate #endif 347c478bd9Sstevel@tonic-gate #endif 357c478bd9Sstevel@tonic-gate #ifdef AFS 367c478bd9Sstevel@tonic-gate #include <kafs.h> 377c478bd9Sstevel@tonic-gate #endif 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include "ssh.h" 407c478bd9Sstevel@tonic-gate #include "log.h" 41b07b2f5cSHuie-Ying Lee #include "buffer.h" 427c478bd9Sstevel@tonic-gate #include "servconf.h" 437c478bd9Sstevel@tonic-gate #include "xmalloc.h" 447c478bd9Sstevel@tonic-gate #include "compat.h" 457c478bd9Sstevel@tonic-gate #include "pathnames.h" 467c478bd9Sstevel@tonic-gate #include "tildexpand.h" 477c478bd9Sstevel@tonic-gate #include "misc.h" 487c478bd9Sstevel@tonic-gate #include "cipher.h" 497c478bd9Sstevel@tonic-gate #include "kex.h" 507c478bd9Sstevel@tonic-gate #include "mac.h" 517c478bd9Sstevel@tonic-gate #include "auth.h" 52b07b2f5cSHuie-Ying Lee #include "match.h" 53b07b2f5cSHuie-Ying Lee #include "groupaccess.h" 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate static void add_listen_addr(ServerOptions *, char *, u_short); 567c478bd9Sstevel@tonic-gate static void add_one_listen_addr(ServerOptions *, char *, u_short); 577c478bd9Sstevel@tonic-gate 58b07b2f5cSHuie-Ying Lee extern Buffer cfg; 59b07b2f5cSHuie-Ying Lee 607c478bd9Sstevel@tonic-gate /* AF_UNSPEC or AF_INET or AF_INET6 */ 617c478bd9Sstevel@tonic-gate extern int IPv4or6; 627c478bd9Sstevel@tonic-gate 636f8d59d8SJan Pechanec /* 646f8d59d8SJan Pechanec * Initializes the server options to their initial (unset) values. Some of those 656f8d59d8SJan Pechanec * that stay unset after the command line options and configuration files are 666f8d59d8SJan Pechanec * read are set to their default values in fill_default_server_options(). 676f8d59d8SJan Pechanec */ 687c478bd9Sstevel@tonic-gate void 697c478bd9Sstevel@tonic-gate initialize_server_options(ServerOptions *options) 707c478bd9Sstevel@tonic-gate { 717c478bd9Sstevel@tonic-gate (void) memset(options, 0, sizeof(*options)); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* Standard Options */ 747c478bd9Sstevel@tonic-gate options->num_ports = 0; 757c478bd9Sstevel@tonic-gate options->ports_from_cmdline = 0; 767c478bd9Sstevel@tonic-gate options->listen_addrs = NULL; 777c478bd9Sstevel@tonic-gate options->num_host_key_files = 0; 787c478bd9Sstevel@tonic-gate options->pid_file = NULL; 797c478bd9Sstevel@tonic-gate options->server_key_bits = -1; 807c478bd9Sstevel@tonic-gate options->login_grace_time = -1; 817c478bd9Sstevel@tonic-gate options->key_regeneration_time = -1; 827c478bd9Sstevel@tonic-gate options->permit_root_login = PERMIT_NOT_SET; 837c478bd9Sstevel@tonic-gate options->ignore_rhosts = -1; 847c478bd9Sstevel@tonic-gate options->ignore_user_known_hosts = -1; 857c478bd9Sstevel@tonic-gate options->print_motd = -1; 867c478bd9Sstevel@tonic-gate options->print_lastlog = -1; 877c478bd9Sstevel@tonic-gate options->x11_forwarding = -1; 887c478bd9Sstevel@tonic-gate options->x11_display_offset = -1; 897c478bd9Sstevel@tonic-gate options->x11_use_localhost = -1; 907c478bd9Sstevel@tonic-gate options->xauth_location = NULL; 917c478bd9Sstevel@tonic-gate options->strict_modes = -1; 927c478bd9Sstevel@tonic-gate options->keepalives = -1; 937c478bd9Sstevel@tonic-gate options->log_facility = SYSLOG_FACILITY_NOT_SET; 947c478bd9Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_NOT_SET; 957c478bd9Sstevel@tonic-gate options->rhosts_authentication = -1; 967c478bd9Sstevel@tonic-gate options->rhosts_rsa_authentication = -1; 977c478bd9Sstevel@tonic-gate options->hostbased_authentication = -1; 987c478bd9Sstevel@tonic-gate options->hostbased_uses_name_from_packet_only = -1; 997c478bd9Sstevel@tonic-gate options->rsa_authentication = -1; 1007c478bd9Sstevel@tonic-gate options->pubkey_authentication = -1; 1017c478bd9Sstevel@tonic-gate #ifdef GSSAPI 1027c478bd9Sstevel@tonic-gate options->gss_authentication = -1; 1037c478bd9Sstevel@tonic-gate options->gss_keyex = -1; 1047c478bd9Sstevel@tonic-gate options->gss_store_creds = -1; 1057c478bd9Sstevel@tonic-gate options->gss_use_session_ccache = -1; 1067c478bd9Sstevel@tonic-gate options->gss_cleanup_creds = -1; 1077c478bd9Sstevel@tonic-gate #endif 1087c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 1097c478bd9Sstevel@tonic-gate options->kerberos_authentication = -1; 1107c478bd9Sstevel@tonic-gate options->kerberos_or_local_passwd = -1; 1117c478bd9Sstevel@tonic-gate options->kerberos_ticket_cleanup = -1; 1127c478bd9Sstevel@tonic-gate #endif 1137c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 1147c478bd9Sstevel@tonic-gate options->kerberos_tgt_passing = -1; 1157c478bd9Sstevel@tonic-gate #endif 1167c478bd9Sstevel@tonic-gate #ifdef AFS 1177c478bd9Sstevel@tonic-gate options->afs_token_passing = -1; 1187c478bd9Sstevel@tonic-gate #endif 1197c478bd9Sstevel@tonic-gate options->password_authentication = -1; 1207c478bd9Sstevel@tonic-gate options->kbd_interactive_authentication = -1; 1217c478bd9Sstevel@tonic-gate options->challenge_response_authentication = -1; 1224a2e944dSJan Pechanec options->pam_authentication_via_kbd_int = -1; 1237c478bd9Sstevel@tonic-gate options->permit_empty_passwd = -1; 1247c478bd9Sstevel@tonic-gate options->permit_user_env = -1; 1257c478bd9Sstevel@tonic-gate options->compression = -1; 1267c478bd9Sstevel@tonic-gate options->allow_tcp_forwarding = -1; 1277c478bd9Sstevel@tonic-gate options->num_allow_users = 0; 1287c478bd9Sstevel@tonic-gate options->num_deny_users = 0; 1297c478bd9Sstevel@tonic-gate options->num_allow_groups = 0; 1307c478bd9Sstevel@tonic-gate options->num_deny_groups = 0; 1317c478bd9Sstevel@tonic-gate options->ciphers = NULL; 1327c478bd9Sstevel@tonic-gate options->macs = NULL; 1337c478bd9Sstevel@tonic-gate options->protocol = SSH_PROTO_UNKNOWN; 1347c478bd9Sstevel@tonic-gate options->gateway_ports = -1; 1357c478bd9Sstevel@tonic-gate options->num_subsystems = 0; 1367c478bd9Sstevel@tonic-gate options->max_startups_begin = -1; 1377c478bd9Sstevel@tonic-gate options->max_startups_rate = -1; 1387c478bd9Sstevel@tonic-gate options->max_startups = -1; 1397c478bd9Sstevel@tonic-gate options->banner = NULL; 1407c478bd9Sstevel@tonic-gate options->verify_reverse_mapping = -1; 1417c478bd9Sstevel@tonic-gate options->client_alive_interval = -1; 1427c478bd9Sstevel@tonic-gate options->client_alive_count_max = -1; 1437c478bd9Sstevel@tonic-gate options->authorized_keys_file = NULL; 1447c478bd9Sstevel@tonic-gate options->authorized_keys_file2 = NULL; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate options->max_auth_tries = -1; 1477c478bd9Sstevel@tonic-gate options->max_auth_tries_log = -1; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate options->max_init_auth_tries = -1; 1507c478bd9Sstevel@tonic-gate options->max_init_auth_tries_log = -1; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate options->lookup_client_hostnames = -1; 153cd7d5fafSJan Pechanec options->use_openssl_engine = -1; 1546f8d59d8SJan Pechanec options->chroot_directory = NULL; 155d8a94255SErik Trauschke options->pre_userauth_hook = NULL; 156bdb005b5SDarren J Moffat options->pam_service_name = NULL; 157bdb005b5SDarren J Moffat options->pam_service_prefix = NULL; 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Reads /etc/default/login and defaults several ServerOptions: 1637c478bd9Sstevel@tonic-gate * 1647c478bd9Sstevel@tonic-gate * PermitRootLogin 1657c478bd9Sstevel@tonic-gate * PermitEmptyPasswords 1667c478bd9Sstevel@tonic-gate * LoginGraceTime 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate * CONSOLE=* -> PermitRootLogin=without-password 1697c478bd9Sstevel@tonic-gate * #CONSOLE=* -> PermitRootLogin=yes 1707c478bd9Sstevel@tonic-gate * 1717c478bd9Sstevel@tonic-gate * PASSREQ=YES -> PermitEmptyPasswords=no 1727c478bd9Sstevel@tonic-gate * PASSREQ=NO -> PermitEmptyPasswords=yes 1737c478bd9Sstevel@tonic-gate * #PASSREQ=* -> PermitEmptyPasswords=no 1747c478bd9Sstevel@tonic-gate * 1757c478bd9Sstevel@tonic-gate * TIMEOUT=<secs> -> LoginGraceTime=<secs> 1767c478bd9Sstevel@tonic-gate * #TIMEOUT=<secs> -> LoginGraceTime=300 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate static 1797c478bd9Sstevel@tonic-gate void 1807c478bd9Sstevel@tonic-gate deflt_fill_default_server_options(ServerOptions *options) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate int flags; 1837c478bd9Sstevel@tonic-gate char *ptr; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if (defopen(_PATH_DEFAULT_LOGIN)) 1867c478bd9Sstevel@tonic-gate return; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* Ignore case */ 1897c478bd9Sstevel@tonic-gate flags = defcntl(DC_GETFLAGS, 0); 1907c478bd9Sstevel@tonic-gate TURNOFF(flags, DC_CASE); 1917c478bd9Sstevel@tonic-gate (void) defcntl(DC_SETFLAGS, flags); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate if (options->permit_root_login == PERMIT_NOT_SET && 1947c478bd9Sstevel@tonic-gate (ptr = defread("CONSOLE=")) != NULL) 1957c478bd9Sstevel@tonic-gate options->permit_root_login = PERMIT_NO_PASSWD; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (options->permit_empty_passwd == -1 && 1987c478bd9Sstevel@tonic-gate (ptr = defread("PASSREQ=")) != NULL) { 1997c478bd9Sstevel@tonic-gate if (strcasecmp("YES", ptr) == 0) 2007c478bd9Sstevel@tonic-gate options->permit_empty_passwd = 0; 2017c478bd9Sstevel@tonic-gate else if (strcasecmp("NO", ptr) == 0) 2027c478bd9Sstevel@tonic-gate options->permit_empty_passwd = 1; 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate if (options->max_init_auth_tries == -1 && 2067c478bd9Sstevel@tonic-gate (ptr = defread("RETRIES=")) != NULL) { 2077c478bd9Sstevel@tonic-gate options->max_init_auth_tries = atoi(ptr); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if (options->max_init_auth_tries_log == -1 && 2117c478bd9Sstevel@tonic-gate (ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) { 2127c478bd9Sstevel@tonic-gate options->max_init_auth_tries_log = atoi(ptr); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate if (options->login_grace_time == -1) { 2167c478bd9Sstevel@tonic-gate if ((ptr = defread("TIMEOUT=")) != NULL) 2177c478bd9Sstevel@tonic-gate options->login_grace_time = (unsigned)atoi(ptr); 2187c478bd9Sstevel@tonic-gate else 2197c478bd9Sstevel@tonic-gate options->login_grace_time = 300; 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate (void) defopen((char *)NULL); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */ 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate void 2277c478bd9Sstevel@tonic-gate fill_default_server_options(ServerOptions *options) 2287c478bd9Sstevel@tonic-gate { 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN 2317c478bd9Sstevel@tonic-gate deflt_fill_default_server_options(options); 2327c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */ 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* Standard Options */ 2357c478bd9Sstevel@tonic-gate if (options->protocol == SSH_PROTO_UNKNOWN) 2367c478bd9Sstevel@tonic-gate options->protocol = SSH_PROTO_1|SSH_PROTO_2; 2377c478bd9Sstevel@tonic-gate if (options->num_host_key_files == 0) { 2387c478bd9Sstevel@tonic-gate /* fill default hostkeys for protocols */ 2397c478bd9Sstevel@tonic-gate if (options->protocol & SSH_PROTO_1) 2407c478bd9Sstevel@tonic-gate options->host_key_files[options->num_host_key_files++] = 2417c478bd9Sstevel@tonic-gate _PATH_HOST_KEY_FILE; 2427c478bd9Sstevel@tonic-gate #ifndef GSSAPI 2437c478bd9Sstevel@tonic-gate /* With GSS keyex we can run v2 w/ no host keys */ 2447c478bd9Sstevel@tonic-gate if (options->protocol & SSH_PROTO_2) { 2457c478bd9Sstevel@tonic-gate options->host_key_files[options->num_host_key_files++] = 2467c478bd9Sstevel@tonic-gate _PATH_HOST_RSA_KEY_FILE; 2477c478bd9Sstevel@tonic-gate options->host_key_files[options->num_host_key_files++] = 2487c478bd9Sstevel@tonic-gate _PATH_HOST_DSA_KEY_FILE; 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate #endif /* GSSAPI */ 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate if (options->num_ports == 0) 2537c478bd9Sstevel@tonic-gate options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 2547c478bd9Sstevel@tonic-gate if (options->listen_addrs == NULL) 2557c478bd9Sstevel@tonic-gate add_listen_addr(options, NULL, 0); 2567c478bd9Sstevel@tonic-gate if (options->pid_file == NULL) 2577c478bd9Sstevel@tonic-gate options->pid_file = _PATH_SSH_DAEMON_PID_FILE; 2587c478bd9Sstevel@tonic-gate if (options->server_key_bits == -1) 2597c478bd9Sstevel@tonic-gate options->server_key_bits = 768; 2607c478bd9Sstevel@tonic-gate if (options->login_grace_time == -1) 2617c478bd9Sstevel@tonic-gate options->login_grace_time = 120; 2627c478bd9Sstevel@tonic-gate if (options->key_regeneration_time == -1) 2637c478bd9Sstevel@tonic-gate options->key_regeneration_time = 3600; 2647c478bd9Sstevel@tonic-gate if (options->permit_root_login == PERMIT_NOT_SET) 2657c478bd9Sstevel@tonic-gate options->permit_root_login = PERMIT_YES; 2667c478bd9Sstevel@tonic-gate if (options->ignore_rhosts == -1) 2677c478bd9Sstevel@tonic-gate options->ignore_rhosts = 1; 2687c478bd9Sstevel@tonic-gate if (options->ignore_user_known_hosts == -1) 2697c478bd9Sstevel@tonic-gate options->ignore_user_known_hosts = 0; 2707c478bd9Sstevel@tonic-gate if (options->print_motd == -1) 2717c478bd9Sstevel@tonic-gate options->print_motd = 1; 2727c478bd9Sstevel@tonic-gate if (options->print_lastlog == -1) 2737c478bd9Sstevel@tonic-gate options->print_lastlog = 1; 2747c478bd9Sstevel@tonic-gate if (options->x11_forwarding == -1) 2757c478bd9Sstevel@tonic-gate options->x11_forwarding = 1; 2767c478bd9Sstevel@tonic-gate if (options->x11_display_offset == -1) 2777c478bd9Sstevel@tonic-gate options->x11_display_offset = 10; 2787c478bd9Sstevel@tonic-gate if (options->x11_use_localhost == -1) 2797c478bd9Sstevel@tonic-gate options->x11_use_localhost = 1; 2807c478bd9Sstevel@tonic-gate if (options->xauth_location == NULL) 2817c478bd9Sstevel@tonic-gate options->xauth_location = _PATH_XAUTH; 2827c478bd9Sstevel@tonic-gate if (options->strict_modes == -1) 2837c478bd9Sstevel@tonic-gate options->strict_modes = 1; 2847c478bd9Sstevel@tonic-gate if (options->keepalives == -1) 2857c478bd9Sstevel@tonic-gate options->keepalives = 1; 2867c478bd9Sstevel@tonic-gate if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2877c478bd9Sstevel@tonic-gate options->log_facility = SYSLOG_FACILITY_AUTH; 2887c478bd9Sstevel@tonic-gate if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2897c478bd9Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_INFO; 2907c478bd9Sstevel@tonic-gate if (options->rhosts_authentication == -1) 2917c478bd9Sstevel@tonic-gate options->rhosts_authentication = 0; 2927c478bd9Sstevel@tonic-gate if (options->rhosts_rsa_authentication == -1) 2937c478bd9Sstevel@tonic-gate options->rhosts_rsa_authentication = 0; 2947c478bd9Sstevel@tonic-gate if (options->hostbased_authentication == -1) 2957c478bd9Sstevel@tonic-gate options->hostbased_authentication = 0; 2967c478bd9Sstevel@tonic-gate if (options->hostbased_uses_name_from_packet_only == -1) 2977c478bd9Sstevel@tonic-gate options->hostbased_uses_name_from_packet_only = 0; 2987c478bd9Sstevel@tonic-gate if (options->rsa_authentication == -1) 2997c478bd9Sstevel@tonic-gate options->rsa_authentication = 1; 3007c478bd9Sstevel@tonic-gate if (options->pubkey_authentication == -1) 3017c478bd9Sstevel@tonic-gate options->pubkey_authentication = 1; 3027c478bd9Sstevel@tonic-gate #ifdef GSSAPI 3037c478bd9Sstevel@tonic-gate if (options->gss_authentication == -1) 3047c478bd9Sstevel@tonic-gate options->gss_authentication = 1; 3057c478bd9Sstevel@tonic-gate if (options->gss_keyex == -1) 3067c478bd9Sstevel@tonic-gate options->gss_keyex = 1; 3077c478bd9Sstevel@tonic-gate if (options->gss_store_creds == -1) 3087c478bd9Sstevel@tonic-gate options->gss_store_creds = 1; 3097c478bd9Sstevel@tonic-gate if (options->gss_use_session_ccache == -1) 3107c478bd9Sstevel@tonic-gate options->gss_use_session_ccache = 1; 3117c478bd9Sstevel@tonic-gate if (options->gss_cleanup_creds == -1) 3127c478bd9Sstevel@tonic-gate options->gss_cleanup_creds = 1; 3137c478bd9Sstevel@tonic-gate #endif 3147c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 3157c478bd9Sstevel@tonic-gate if (options->kerberos_authentication == -1) 3167c478bd9Sstevel@tonic-gate options->kerberos_authentication = 0; 3177c478bd9Sstevel@tonic-gate if (options->kerberos_or_local_passwd == -1) 3187c478bd9Sstevel@tonic-gate options->kerberos_or_local_passwd = 1; 3197c478bd9Sstevel@tonic-gate if (options->kerberos_ticket_cleanup == -1) 3207c478bd9Sstevel@tonic-gate options->kerberos_ticket_cleanup = 1; 3217c478bd9Sstevel@tonic-gate #endif 3227c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 3237c478bd9Sstevel@tonic-gate if (options->kerberos_tgt_passing == -1) 3247c478bd9Sstevel@tonic-gate options->kerberos_tgt_passing = 0; 3257c478bd9Sstevel@tonic-gate #endif 3267c478bd9Sstevel@tonic-gate #ifdef AFS 3277c478bd9Sstevel@tonic-gate if (options->afs_token_passing == -1) 3287c478bd9Sstevel@tonic-gate options->afs_token_passing = 0; 3297c478bd9Sstevel@tonic-gate #endif 3307c478bd9Sstevel@tonic-gate if (options->password_authentication == -1) 3317c478bd9Sstevel@tonic-gate options->password_authentication = 1; 3324a2e944dSJan Pechanec /* 3334a2e944dSJan Pechanec * options->pam_authentication_via_kbd_int has intentionally no default 3344a2e944dSJan Pechanec * value since we do not need it. 3354a2e944dSJan Pechanec */ 3367c478bd9Sstevel@tonic-gate if (options->kbd_interactive_authentication == -1) 3374a2e944dSJan Pechanec options->kbd_interactive_authentication = 1; 3387c478bd9Sstevel@tonic-gate if (options->challenge_response_authentication == -1) 3397c478bd9Sstevel@tonic-gate options->challenge_response_authentication = 1; 3407c478bd9Sstevel@tonic-gate if (options->permit_empty_passwd == -1) 3417c478bd9Sstevel@tonic-gate options->permit_empty_passwd = 0; 3427c478bd9Sstevel@tonic-gate if (options->permit_user_env == -1) 3437c478bd9Sstevel@tonic-gate options->permit_user_env = 0; 3447c478bd9Sstevel@tonic-gate if (options->compression == -1) 3457c478bd9Sstevel@tonic-gate options->compression = 1; 3467c478bd9Sstevel@tonic-gate if (options->allow_tcp_forwarding == -1) 3477c478bd9Sstevel@tonic-gate options->allow_tcp_forwarding = 1; 3487c478bd9Sstevel@tonic-gate if (options->gateway_ports == -1) 3497c478bd9Sstevel@tonic-gate options->gateway_ports = 0; 3507c478bd9Sstevel@tonic-gate if (options->max_startups == -1) 3517c478bd9Sstevel@tonic-gate options->max_startups = 10; 3527c478bd9Sstevel@tonic-gate if (options->max_startups_rate == -1) 3537c478bd9Sstevel@tonic-gate options->max_startups_rate = 100; /* 100% */ 3547c478bd9Sstevel@tonic-gate if (options->max_startups_begin == -1) 3557c478bd9Sstevel@tonic-gate options->max_startups_begin = options->max_startups; 3567c478bd9Sstevel@tonic-gate if (options->verify_reverse_mapping == -1) 3577c478bd9Sstevel@tonic-gate options->verify_reverse_mapping = 0; 3587c478bd9Sstevel@tonic-gate if (options->client_alive_interval == -1) 3597c478bd9Sstevel@tonic-gate options->client_alive_interval = 0; 3607c478bd9Sstevel@tonic-gate if (options->client_alive_count_max == -1) 3617c478bd9Sstevel@tonic-gate options->client_alive_count_max = 3; 3627c478bd9Sstevel@tonic-gate if (options->authorized_keys_file2 == NULL) { 3637c478bd9Sstevel@tonic-gate /* authorized_keys_file2 falls back to authorized_keys_file */ 3647c478bd9Sstevel@tonic-gate if (options->authorized_keys_file != NULL) 3657c478bd9Sstevel@tonic-gate options->authorized_keys_file2 = options->authorized_keys_file; 3667c478bd9Sstevel@tonic-gate else 3677c478bd9Sstevel@tonic-gate options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate if (options->authorized_keys_file == NULL) 3707c478bd9Sstevel@tonic-gate options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate if (options->max_auth_tries == -1) 3737c478bd9Sstevel@tonic-gate options->max_auth_tries = AUTH_FAIL_MAX; 3747c478bd9Sstevel@tonic-gate if (options->max_auth_tries_log == -1) 3757c478bd9Sstevel@tonic-gate options->max_auth_tries_log = options->max_auth_tries / 2; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (options->max_init_auth_tries == -1) 3787c478bd9Sstevel@tonic-gate options->max_init_auth_tries = AUTH_FAIL_MAX; 3797c478bd9Sstevel@tonic-gate if (options->max_init_auth_tries_log == -1) 3807c478bd9Sstevel@tonic-gate options->max_init_auth_tries_log = options->max_init_auth_tries / 2; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if (options->lookup_client_hostnames == -1) 3837c478bd9Sstevel@tonic-gate options->lookup_client_hostnames = 1; 384cd7d5fafSJan Pechanec if (options->use_openssl_engine == -1) 385cd7d5fafSJan Pechanec options->use_openssl_engine = 1; 386bdb005b5SDarren J Moffat if (options->pam_service_prefix == NULL) 387bdb005b5SDarren J Moffat options->pam_service_prefix = _SSH_PAM_SERVICE_PREFIX; 388bdb005b5SDarren J Moffat if (options->pam_service_name == NULL) 389bdb005b5SDarren J Moffat options->pam_service_name = NULL; 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate /* Keyword tokens. */ 3937c478bd9Sstevel@tonic-gate typedef enum { 3947c478bd9Sstevel@tonic-gate sBadOption, /* == unknown option */ 3957c478bd9Sstevel@tonic-gate /* Portable-specific options */ 3967c478bd9Sstevel@tonic-gate sPAMAuthenticationViaKbdInt, 3977c478bd9Sstevel@tonic-gate /* Standard Options */ 3987c478bd9Sstevel@tonic-gate sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, 3997c478bd9Sstevel@tonic-gate sPermitRootLogin, sLogFacility, sLogLevel, 4007c478bd9Sstevel@tonic-gate sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication, 4017c478bd9Sstevel@tonic-gate #ifdef GSSAPI 4027c478bd9Sstevel@tonic-gate sGssAuthentication, sGssKeyEx, sGssStoreDelegCreds, 4037c478bd9Sstevel@tonic-gate sGssUseSessionCredCache, sGssCleanupCreds, 4047c478bd9Sstevel@tonic-gate #endif /* GSSAPI */ 4057c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 4067c478bd9Sstevel@tonic-gate sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 4077c478bd9Sstevel@tonic-gate #endif 4087c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 4097c478bd9Sstevel@tonic-gate sKerberosTgtPassing, 4107c478bd9Sstevel@tonic-gate #endif 4117c478bd9Sstevel@tonic-gate #ifdef AFS 4127c478bd9Sstevel@tonic-gate sAFSTokenPassing, 4137c478bd9Sstevel@tonic-gate #endif 4147c478bd9Sstevel@tonic-gate sChallengeResponseAuthentication, 4157c478bd9Sstevel@tonic-gate sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, 4167c478bd9Sstevel@tonic-gate sPrintMotd, sPrintLastLog, sIgnoreRhosts, 4177c478bd9Sstevel@tonic-gate sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 4187c478bd9Sstevel@tonic-gate sStrictModes, sEmptyPasswd, sKeepAlives, 4197c478bd9Sstevel@tonic-gate sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, 4207c478bd9Sstevel@tonic-gate sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 4217c478bd9Sstevel@tonic-gate sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 4227c478bd9Sstevel@tonic-gate sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, 4237c478bd9Sstevel@tonic-gate sBanner, sVerifyReverseMapping, sHostbasedAuthentication, 4247c478bd9Sstevel@tonic-gate sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 4257c478bd9Sstevel@tonic-gate sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 4267c478bd9Sstevel@tonic-gate sMaxAuthTries, sMaxAuthTriesLog, sUsePrivilegeSeparation, 4276f8d59d8SJan Pechanec sLookupClientHostnames, sUseOpenSSLEngine, sChrootDirectory, 428bdb005b5SDarren J Moffat sPreUserauthHook, sMatch, sPAMServicePrefix, sPAMServiceName, 4297c478bd9Sstevel@tonic-gate sDeprecated 4307c478bd9Sstevel@tonic-gate } ServerOpCodes; 4317c478bd9Sstevel@tonic-gate 432b07b2f5cSHuie-Ying Lee #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ 433b07b2f5cSHuie-Ying Lee #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 434b07b2f5cSHuie-Ying Lee #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 435b07b2f5cSHuie-Ying Lee 4367c478bd9Sstevel@tonic-gate /* Textual representation of the tokens. */ 4377c478bd9Sstevel@tonic-gate static struct { 4387c478bd9Sstevel@tonic-gate const char *name; 4397c478bd9Sstevel@tonic-gate ServerOpCodes opcode; 440b07b2f5cSHuie-Ying Lee u_int flags; 4417c478bd9Sstevel@tonic-gate } keywords[] = { 4427c478bd9Sstevel@tonic-gate /* Portable-specific options */ 443b07b2f5cSHuie-Ying Lee { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt, SSHCFG_GLOBAL }, 4447c478bd9Sstevel@tonic-gate /* Standard Options */ 445b07b2f5cSHuie-Ying Lee { "port", sPort, SSHCFG_GLOBAL }, 446b07b2f5cSHuie-Ying Lee { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 447b07b2f5cSHuie-Ying Lee { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 448b07b2f5cSHuie-Ying Lee { "pidfile", sPidFile, SSHCFG_GLOBAL }, 449b07b2f5cSHuie-Ying Lee { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, 450b07b2f5cSHuie-Ying Lee { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 451b07b2f5cSHuie-Ying Lee { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, 452b07b2f5cSHuie-Ying Lee { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, 453b07b2f5cSHuie-Ying Lee { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 454b07b2f5cSHuie-Ying Lee { "loglevel", sLogLevel, SSHCFG_GLOBAL }, 455b07b2f5cSHuie-Ying Lee { "rhostsauthentication", sRhostsAuthentication, SSHCFG_GLOBAL }, 456b07b2f5cSHuie-Ying Lee { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, 457b07b2f5cSHuie-Ying Lee { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, 4587c478bd9Sstevel@tonic-gate { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, 459b07b2f5cSHuie-Ying Lee { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, 460b07b2f5cSHuie-Ying Lee { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 461b07b2f5cSHuie-Ying Lee { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 4627c478bd9Sstevel@tonic-gate #ifdef GSSAPI 463b07b2f5cSHuie-Ying Lee { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 464b07b2f5cSHuie-Ying Lee { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, 465b07b2f5cSHuie-Ying Lee { "gssapistoredelegatedcredentials", sGssStoreDelegCreds, SSHCFG_GLOBAL }, 466b07b2f5cSHuie-Ying Lee { "gssauthentication", sGssAuthentication, SSHCFG_GLOBAL }, /* alias */ 467b07b2f5cSHuie-Ying Lee { "gsskeyex", sGssKeyEx, SSHCFG_GLOBAL }, /* alias */ 468b07b2f5cSHuie-Ying Lee { "gssstoredelegcreds", sGssStoreDelegCreds, SSHCFG_GLOBAL }, /* alias */ 4697c478bd9Sstevel@tonic-gate #ifndef SUNW_GSSAPI 470b07b2f5cSHuie-Ying Lee { "gssusesessionccache", sGssUseSessionCredCache, SSHCFG_GLOBAL }, 471b07b2f5cSHuie-Ying Lee { "gssusesessioncredcache", sGssUseSessionCredCache, SSHCFG_GLOBAL }, 472b07b2f5cSHuie-Ying Lee { "gsscleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, 4737c478bd9Sstevel@tonic-gate #endif /* SUNW_GSSAPI */ 4747c478bd9Sstevel@tonic-gate #endif 4757c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 476b07b2f5cSHuie-Ying Lee { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 477b07b2f5cSHuie-Ying Lee { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 478b07b2f5cSHuie-Ying Lee { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 4797c478bd9Sstevel@tonic-gate #endif 4807c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 481b07b2f5cSHuie-Ying Lee { "kerberostgtpassing", sKerberosTgtPassing, SSHCFG_GLOBAL }, 4827c478bd9Sstevel@tonic-gate #endif 4837c478bd9Sstevel@tonic-gate #ifdef AFS 484b07b2f5cSHuie-Ying Lee { "afstokenpassing", sAFSTokenPassing, SSHCFG_GLOBAL }, 4857c478bd9Sstevel@tonic-gate #endif 486b07b2f5cSHuie-Ying Lee { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 487b07b2f5cSHuie-Ying Lee { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 488b07b2f5cSHuie-Ying Lee { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 489b07b2f5cSHuie-Ying Lee { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ 490b07b2f5cSHuie-Ying Lee { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 491b07b2f5cSHuie-Ying Lee { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 492b07b2f5cSHuie-Ying Lee { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 493b07b2f5cSHuie-Ying Lee { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 494b07b2f5cSHuie-Ying Lee { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, 495b07b2f5cSHuie-Ying Lee { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 496b07b2f5cSHuie-Ying Lee { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 497b07b2f5cSHuie-Ying Lee { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 498b07b2f5cSHuie-Ying Lee { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 499b07b2f5cSHuie-Ying Lee { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 500b07b2f5cSHuie-Ying Lee { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 501b07b2f5cSHuie-Ying Lee { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, 502b07b2f5cSHuie-Ying Lee { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 503b07b2f5cSHuie-Ying Lee { "uselogin", sUseLogin, SSHCFG_GLOBAL }, 504b07b2f5cSHuie-Ying Lee { "compression", sCompression, SSHCFG_GLOBAL }, 505*33c41f2bSJoshua M. Clulow { "tcpkeepalive", sKeepAlives, SSHCFG_GLOBAL }, 506*33c41f2bSJoshua M. Clulow { "keepalive", sKeepAlives, SSHCFG_GLOBAL }, /* obsolete */ 507b07b2f5cSHuie-Ying Lee { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 508b07b2f5cSHuie-Ying Lee { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, 509b07b2f5cSHuie-Ying Lee { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, 510b07b2f5cSHuie-Ying Lee { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, 511b07b2f5cSHuie-Ying Lee { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, 512b07b2f5cSHuie-Ying Lee { "ciphers", sCiphers, SSHCFG_GLOBAL }, 513b07b2f5cSHuie-Ying Lee { "macs", sMacs, SSHCFG_GLOBAL}, 514b07b2f5cSHuie-Ying Lee { "protocol", sProtocol,SSHCFG_GLOBAL }, 515b07b2f5cSHuie-Ying Lee { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 516b07b2f5cSHuie-Ying Lee { "subsystem", sSubsystem, SSHCFG_GLOBAL}, 517b07b2f5cSHuie-Ying Lee { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 518b07b2f5cSHuie-Ying Lee { "banner", sBanner, SSHCFG_ALL }, 519b07b2f5cSHuie-Ying Lee { "verifyreversemapping", sVerifyReverseMapping, SSHCFG_GLOBAL }, 520b07b2f5cSHuie-Ying Lee { "reversemappingcheck", sVerifyReverseMapping,SSHCFG_GLOBAL }, 521b07b2f5cSHuie-Ying Lee { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 522b07b2f5cSHuie-Ying Lee { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 523b07b2f5cSHuie-Ying Lee { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, 524b07b2f5cSHuie-Ying Lee { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, 525b07b2f5cSHuie-Ying Lee { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, 526b07b2f5cSHuie-Ying Lee { "maxauthtrieslog", sMaxAuthTriesLog, SSHCFG_GLOBAL }, 527b07b2f5cSHuie-Ying Lee { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, 528b07b2f5cSHuie-Ying Lee { "lookupclienthostnames", sLookupClientHostnames, SSHCFG_GLOBAL }, 529b07b2f5cSHuie-Ying Lee { "useopensslengine", sUseOpenSSLEngine, SSHCFG_GLOBAL }, 530b07b2f5cSHuie-Ying Lee { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 531d8a94255SErik Trauschke { "preuserauthhook", sPreUserauthHook, SSHCFG_ALL}, 532b07b2f5cSHuie-Ying Lee { "match", sMatch, SSHCFG_ALL }, 533bdb005b5SDarren J Moffat { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL }, 534bdb005b5SDarren J Moffat { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL }, 535b07b2f5cSHuie-Ying Lee 536b07b2f5cSHuie-Ying Lee { NULL, sBadOption, 0 } 5377c478bd9Sstevel@tonic-gate }; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate /* 5407c478bd9Sstevel@tonic-gate * Returns the number of the token pointed to by cp or sBadOption. 5417c478bd9Sstevel@tonic-gate */ 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate static ServerOpCodes 5447c478bd9Sstevel@tonic-gate parse_token(const char *cp, const char *filename, 545b07b2f5cSHuie-Ying Lee int linenum, u_int *flags) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate u_int i; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate for (i = 0; keywords[i].name; i++) 550b07b2f5cSHuie-Ying Lee if (strcasecmp(cp, keywords[i].name) == 0) { 551b07b2f5cSHuie-Ying Lee *flags = keywords[i].flags; 5527c478bd9Sstevel@tonic-gate return keywords[i].opcode; 553b07b2f5cSHuie-Ying Lee } 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate error("%s: line %d: Bad configuration option: %s", 5567c478bd9Sstevel@tonic-gate filename, linenum, cp); 5577c478bd9Sstevel@tonic-gate return sBadOption; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate static void 5617c478bd9Sstevel@tonic-gate add_listen_addr(ServerOptions *options, char *addr, u_short port) 5627c478bd9Sstevel@tonic-gate { 5637c478bd9Sstevel@tonic-gate int i; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (options->num_ports == 0) 5667c478bd9Sstevel@tonic-gate options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 5677c478bd9Sstevel@tonic-gate if (port == 0) 5687c478bd9Sstevel@tonic-gate for (i = 0; i < options->num_ports; i++) 5697c478bd9Sstevel@tonic-gate add_one_listen_addr(options, addr, options->ports[i]); 5707c478bd9Sstevel@tonic-gate else 5717c478bd9Sstevel@tonic-gate add_one_listen_addr(options, addr, port); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate static void 5757c478bd9Sstevel@tonic-gate add_one_listen_addr(ServerOptions *options, char *addr, u_short port) 5767c478bd9Sstevel@tonic-gate { 5777c478bd9Sstevel@tonic-gate struct addrinfo hints, *ai, *aitop; 5787c478bd9Sstevel@tonic-gate char strport[NI_MAXSERV]; 5797c478bd9Sstevel@tonic-gate int gaierr; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate (void) memset(&hints, 0, sizeof(hints)); 5827c478bd9Sstevel@tonic-gate hints.ai_family = IPv4or6; 5837c478bd9Sstevel@tonic-gate hints.ai_socktype = SOCK_STREAM; 5847c478bd9Sstevel@tonic-gate hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 5857c478bd9Sstevel@tonic-gate (void) snprintf(strport, sizeof strport, "%u", port); 5867c478bd9Sstevel@tonic-gate if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 5877c478bd9Sstevel@tonic-gate fatal("bad addr or host: %s (%s)", 5887c478bd9Sstevel@tonic-gate addr ? addr : "<NULL>", 5897c478bd9Sstevel@tonic-gate gai_strerror(gaierr)); 5907c478bd9Sstevel@tonic-gate for (ai = aitop; ai->ai_next; ai = ai->ai_next) 5917c478bd9Sstevel@tonic-gate ; 5927c478bd9Sstevel@tonic-gate ai->ai_next = options->listen_addrs; 5937c478bd9Sstevel@tonic-gate options->listen_addrs = aitop; 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 596b07b2f5cSHuie-Ying Lee /* 597b07b2f5cSHuie-Ying Lee * The strategy for the Match blocks is that the config file is parsed twice. 598b07b2f5cSHuie-Ying Lee * 599b07b2f5cSHuie-Ying Lee * The first time is at startup. activep is initialized to 1 and the 600b07b2f5cSHuie-Ying Lee * directives in the global context are processed and acted on. Hitting a 601b07b2f5cSHuie-Ying Lee * Match directive unsets activep and the directives inside the block are 602b07b2f5cSHuie-Ying Lee * checked for syntax only. 603b07b2f5cSHuie-Ying Lee * 604b07b2f5cSHuie-Ying Lee * The second time is after a connection has been established but before 605b07b2f5cSHuie-Ying Lee * authentication. activep is initialized to 2 and global config directives 606b07b2f5cSHuie-Ying Lee * are ignored since they have already been processed. If the criteria in a 607b07b2f5cSHuie-Ying Lee * Match block is met, activep is set and the subsequent directives 608b07b2f5cSHuie-Ying Lee * processed and actioned until EOF or another Match block unsets it. Any 609b07b2f5cSHuie-Ying Lee * options set are copied into the main server config. 610b07b2f5cSHuie-Ying Lee * 611b07b2f5cSHuie-Ying Lee * Potential additions/improvements: 612b07b2f5cSHuie-Ying Lee * - Add Match support for pre-kex directives, eg Protocol, Ciphers. 613b07b2f5cSHuie-Ying Lee * 614b07b2f5cSHuie-Ying Lee * - Add a Tag directive (idea from David Leonard) ala pf, eg: 615b07b2f5cSHuie-Ying Lee * Match Address 192.168.0.* 616b07b2f5cSHuie-Ying Lee * Tag trusted 617b07b2f5cSHuie-Ying Lee * Match Group wheel 618b07b2f5cSHuie-Ying Lee * Tag trusted 619b07b2f5cSHuie-Ying Lee * Match Tag trusted 620b07b2f5cSHuie-Ying Lee * AllowTcpForwarding yes 621b07b2f5cSHuie-Ying Lee * GatewayPorts clientspecified 622b07b2f5cSHuie-Ying Lee * [...] 623b07b2f5cSHuie-Ying Lee * 624b07b2f5cSHuie-Ying Lee * - Add a PermittedChannelRequests directive 625b07b2f5cSHuie-Ying Lee * Match Group shell 626b07b2f5cSHuie-Ying Lee * PermittedChannelRequests session,forwarded-tcpip 627b07b2f5cSHuie-Ying Lee */ 628b07b2f5cSHuie-Ying Lee 629b07b2f5cSHuie-Ying Lee static int 630b07b2f5cSHuie-Ying Lee match_cfg_line_group(const char *grps, int line, const char *user) 631b07b2f5cSHuie-Ying Lee { 632b07b2f5cSHuie-Ying Lee int result = 0; 633b07b2f5cSHuie-Ying Lee struct passwd *pw; 634b07b2f5cSHuie-Ying Lee 635b07b2f5cSHuie-Ying Lee if (user == NULL) 636b07b2f5cSHuie-Ying Lee goto out; 637b07b2f5cSHuie-Ying Lee 638b07b2f5cSHuie-Ying Lee if ((pw = getpwnam(user)) == NULL) { 639b07b2f5cSHuie-Ying Lee debug("Can't match group at line %d because user %.100s does " 640b07b2f5cSHuie-Ying Lee "not exist", line, user); 641b07b2f5cSHuie-Ying Lee } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 642b07b2f5cSHuie-Ying Lee debug("Can't Match group because user %.100s not in any group " 643b07b2f5cSHuie-Ying Lee "at line %d", user, line); 644b07b2f5cSHuie-Ying Lee } else if (ga_match_pattern_list(grps) != 1) { 645b07b2f5cSHuie-Ying Lee debug("user %.100s does not match group list %.100s at line %d", 646b07b2f5cSHuie-Ying Lee user, grps, line); 647b07b2f5cSHuie-Ying Lee } else { 648b07b2f5cSHuie-Ying Lee debug("user %.100s matched group list %.100s at line %d", user, 649b07b2f5cSHuie-Ying Lee grps, line); 650b07b2f5cSHuie-Ying Lee result = 1; 651b07b2f5cSHuie-Ying Lee } 652b07b2f5cSHuie-Ying Lee out: 653b07b2f5cSHuie-Ying Lee ga_free(); 654b07b2f5cSHuie-Ying Lee return result; 655b07b2f5cSHuie-Ying Lee } 656b07b2f5cSHuie-Ying Lee 657b07b2f5cSHuie-Ying Lee static int 658b07b2f5cSHuie-Ying Lee match_cfg_line(char **condition, int line, const char *user, const char *host, 659b07b2f5cSHuie-Ying Lee const char *address) 660b07b2f5cSHuie-Ying Lee { 661b07b2f5cSHuie-Ying Lee int result = 1; 662b07b2f5cSHuie-Ying Lee char *arg, *attrib, *cp = *condition; 663b07b2f5cSHuie-Ying Lee size_t len; 664b07b2f5cSHuie-Ying Lee 665b07b2f5cSHuie-Ying Lee if (user == NULL) 666b07b2f5cSHuie-Ying Lee debug3("checking syntax for 'Match %s'", cp); 667b07b2f5cSHuie-Ying Lee else 668b07b2f5cSHuie-Ying Lee debug3("checking match for '%s' user %s host %s addr %s", cp, 669b07b2f5cSHuie-Ying Lee user ? user : "(null)", host ? host : "(null)", 670b07b2f5cSHuie-Ying Lee address ? address : "(null)"); 671b07b2f5cSHuie-Ying Lee 67256e7e6c6SHuie-Ying Lee while ((attrib = strdelim(&cp)) != NULL && *attrib != '\0') { 673b07b2f5cSHuie-Ying Lee if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 674b07b2f5cSHuie-Ying Lee error("Missing Match criteria for %s", attrib); 675b07b2f5cSHuie-Ying Lee return -1; 676b07b2f5cSHuie-Ying Lee } 677b07b2f5cSHuie-Ying Lee len = strlen(arg); 678b07b2f5cSHuie-Ying Lee if (strcasecmp(attrib, "user") == 0) { 679b07b2f5cSHuie-Ying Lee if (!user) { 680b07b2f5cSHuie-Ying Lee result = 0; 681b07b2f5cSHuie-Ying Lee continue; 682b07b2f5cSHuie-Ying Lee } 683b07b2f5cSHuie-Ying Lee if (match_pattern_list(user, arg, len, 0) != 1) 684b07b2f5cSHuie-Ying Lee result = 0; 685b07b2f5cSHuie-Ying Lee else 686b07b2f5cSHuie-Ying Lee debug("user %.100s matched 'User %.100s' at " 687b07b2f5cSHuie-Ying Lee "line %d", user, arg, line); 688b07b2f5cSHuie-Ying Lee } else if (strcasecmp(attrib, "group") == 0) { 689b07b2f5cSHuie-Ying Lee switch (match_cfg_line_group(arg, line, user)) { 690b07b2f5cSHuie-Ying Lee case -1: 691b07b2f5cSHuie-Ying Lee return -1; 692b07b2f5cSHuie-Ying Lee case 0: 693b07b2f5cSHuie-Ying Lee result = 0; 694b07b2f5cSHuie-Ying Lee } 695b07b2f5cSHuie-Ying Lee } else if (strcasecmp(attrib, "host") == 0) { 696b07b2f5cSHuie-Ying Lee if (!host) { 697b07b2f5cSHuie-Ying Lee result = 0; 698b07b2f5cSHuie-Ying Lee continue; 699b07b2f5cSHuie-Ying Lee } 700b07b2f5cSHuie-Ying Lee if (match_hostname(host, arg, len) != 1) 701b07b2f5cSHuie-Ying Lee result = 0; 702b07b2f5cSHuie-Ying Lee else 703b07b2f5cSHuie-Ying Lee debug("connection from %.100s matched 'Host " 704b07b2f5cSHuie-Ying Lee "%.100s' at line %d", host, arg, line); 705b07b2f5cSHuie-Ying Lee } else if (strcasecmp(attrib, "address") == 0) { 706b07b2f5cSHuie-Ying Lee switch (addr_match_list(address, arg)) { 707b07b2f5cSHuie-Ying Lee case 1: 708b07b2f5cSHuie-Ying Lee debug("connection from %.100s matched 'Address " 709b07b2f5cSHuie-Ying Lee "%.100s' at line %d", address, arg, line); 710b07b2f5cSHuie-Ying Lee break; 711b07b2f5cSHuie-Ying Lee case 0: 712b07b2f5cSHuie-Ying Lee case -1: 713b07b2f5cSHuie-Ying Lee result = 0; 714b07b2f5cSHuie-Ying Lee break; 715b07b2f5cSHuie-Ying Lee case -2: 716b07b2f5cSHuie-Ying Lee return -1; 717b07b2f5cSHuie-Ying Lee } 718b07b2f5cSHuie-Ying Lee } else { 719b07b2f5cSHuie-Ying Lee error("Unsupported Match attribute %s", attrib); 720b07b2f5cSHuie-Ying Lee return -1; 721b07b2f5cSHuie-Ying Lee } 722b07b2f5cSHuie-Ying Lee } 723b07b2f5cSHuie-Ying Lee if (user != NULL) 724b07b2f5cSHuie-Ying Lee debug3("match %sfound", result ? "" : "not "); 725b07b2f5cSHuie-Ying Lee *condition = cp; 726b07b2f5cSHuie-Ying Lee return result; 727b07b2f5cSHuie-Ying Lee } 728b07b2f5cSHuie-Ying Lee 729b07b2f5cSHuie-Ying Lee #define WHITESPACE " \t\r\n" 730b07b2f5cSHuie-Ying Lee 7317c478bd9Sstevel@tonic-gate int 7327c478bd9Sstevel@tonic-gate process_server_config_line(ServerOptions *options, char *line, 733b07b2f5cSHuie-Ying Lee const char *filename, int linenum, int *activep, const char *user, 734b07b2f5cSHuie-Ying Lee const char *host, const char *address) 7357c478bd9Sstevel@tonic-gate { 7367c478bd9Sstevel@tonic-gate char *cp, **charptr, *arg, *p; 737b07b2f5cSHuie-Ying Lee int cmdline = 0, *intptr, value, n; 7387c478bd9Sstevel@tonic-gate ServerOpCodes opcode; 739b07b2f5cSHuie-Ying Lee u_int i, flags = 0; 7406f8d59d8SJan Pechanec size_t len; 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate cp = line; 7437c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 7447c478bd9Sstevel@tonic-gate /* Ignore leading whitespace */ 7457c478bd9Sstevel@tonic-gate if (*arg == '\0') 7467c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 7477c478bd9Sstevel@tonic-gate if (!arg || !*arg || *arg == '#') 7487c478bd9Sstevel@tonic-gate return 0; 7497c478bd9Sstevel@tonic-gate intptr = NULL; 7507c478bd9Sstevel@tonic-gate charptr = NULL; 751b07b2f5cSHuie-Ying Lee opcode = parse_token(arg, filename, linenum, &flags); 752b07b2f5cSHuie-Ying Lee 753b07b2f5cSHuie-Ying Lee if (activep == NULL) { /* We are processing a command line directive */ 754b07b2f5cSHuie-Ying Lee cmdline = 1; 755b07b2f5cSHuie-Ying Lee activep = &cmdline; 756b07b2f5cSHuie-Ying Lee } 757b07b2f5cSHuie-Ying Lee if (*activep && opcode != sMatch) 758b07b2f5cSHuie-Ying Lee debug3("%s:%d setting %s %s", filename, linenum, arg, cp); 759b07b2f5cSHuie-Ying Lee if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 760b07b2f5cSHuie-Ying Lee if (user == NULL) { 761b07b2f5cSHuie-Ying Lee fatal("%s line %d: Directive '%s' is not allowed " 762b07b2f5cSHuie-Ying Lee "within a Match block", filename, linenum, arg); 763b07b2f5cSHuie-Ying Lee } else { /* this is a directive we have already processed */ 764b07b2f5cSHuie-Ying Lee while (arg) 765b07b2f5cSHuie-Ying Lee arg = strdelim(&cp); 766b07b2f5cSHuie-Ying Lee return 0; 767b07b2f5cSHuie-Ying Lee } 768b07b2f5cSHuie-Ying Lee } 769b07b2f5cSHuie-Ying Lee 7707c478bd9Sstevel@tonic-gate switch (opcode) { 7717c478bd9Sstevel@tonic-gate /* Portable-specific options */ 7727c478bd9Sstevel@tonic-gate case sPAMAuthenticationViaKbdInt: 7734a2e944dSJan Pechanec log("%s line %d: PAMAuthenticationViaKbdInt has been " 7744a2e944dSJan Pechanec "deprecated. You should use KbdInteractiveAuthentication " 7754a2e944dSJan Pechanec "instead (which defaults to \"yes\").", filename, linenum); 7767c478bd9Sstevel@tonic-gate intptr = &options->pam_authentication_via_kbd_int; 7777c478bd9Sstevel@tonic-gate goto parse_flag; 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* Standard Options */ 7807c478bd9Sstevel@tonic-gate case sBadOption: 7817c478bd9Sstevel@tonic-gate return -1; 7827c478bd9Sstevel@tonic-gate case sPort: 7837c478bd9Sstevel@tonic-gate /* ignore ports from configfile if cmdline specifies ports */ 7847c478bd9Sstevel@tonic-gate if (options->ports_from_cmdline) 7857c478bd9Sstevel@tonic-gate return 0; 7867c478bd9Sstevel@tonic-gate if (options->listen_addrs != NULL) 7877c478bd9Sstevel@tonic-gate fatal("%s line %d: ports must be specified before " 7887c478bd9Sstevel@tonic-gate "ListenAddress.", filename, linenum); 7897c478bd9Sstevel@tonic-gate if (options->num_ports >= MAX_PORTS) 7907c478bd9Sstevel@tonic-gate fatal("%s line %d: too many ports.", 7917c478bd9Sstevel@tonic-gate filename, linenum); 7927c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 7937c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 7947c478bd9Sstevel@tonic-gate fatal("%s line %d: missing port number.", 7957c478bd9Sstevel@tonic-gate filename, linenum); 7967c478bd9Sstevel@tonic-gate options->ports[options->num_ports++] = a2port(arg); 7977c478bd9Sstevel@tonic-gate if (options->ports[options->num_ports-1] == 0) 7987c478bd9Sstevel@tonic-gate fatal("%s line %d: Badly formatted port number.", 7997c478bd9Sstevel@tonic-gate filename, linenum); 8007c478bd9Sstevel@tonic-gate break; 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate case sServerKeyBits: 8037c478bd9Sstevel@tonic-gate intptr = &options->server_key_bits; 8047c478bd9Sstevel@tonic-gate parse_int: 8057c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 8067c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 8077c478bd9Sstevel@tonic-gate fatal("%s line %d: missing integer value.", 8087c478bd9Sstevel@tonic-gate filename, linenum); 8097c478bd9Sstevel@tonic-gate value = atoi(arg); 810b07b2f5cSHuie-Ying Lee if (*activep && *intptr == -1) 8117c478bd9Sstevel@tonic-gate *intptr = value; 8127c478bd9Sstevel@tonic-gate break; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate case sLoginGraceTime: 8157c478bd9Sstevel@tonic-gate intptr = &options->login_grace_time; 8167c478bd9Sstevel@tonic-gate parse_time: 8177c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 8187c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 8197c478bd9Sstevel@tonic-gate fatal("%s line %d: missing time value.", 8207c478bd9Sstevel@tonic-gate filename, linenum); 8217c478bd9Sstevel@tonic-gate if ((value = convtime(arg)) == -1) 8227c478bd9Sstevel@tonic-gate fatal("%s line %d: invalid time value.", 8237c478bd9Sstevel@tonic-gate filename, linenum); 8247c478bd9Sstevel@tonic-gate if (*intptr == -1) 8257c478bd9Sstevel@tonic-gate *intptr = value; 8267c478bd9Sstevel@tonic-gate break; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate case sKeyRegenerationTime: 8297c478bd9Sstevel@tonic-gate intptr = &options->key_regeneration_time; 8307c478bd9Sstevel@tonic-gate goto parse_time; 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate case sListenAddress: 8337c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 8347c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) 8357c478bd9Sstevel@tonic-gate fatal("%s line %d: missing inet addr.", 8367c478bd9Sstevel@tonic-gate filename, linenum); 8377c478bd9Sstevel@tonic-gate if (*arg == '[') { 8387c478bd9Sstevel@tonic-gate if ((p = strchr(arg, ']')) == NULL) 8397c478bd9Sstevel@tonic-gate fatal("%s line %d: bad ipv6 inet addr usage.", 8407c478bd9Sstevel@tonic-gate filename, linenum); 8417c478bd9Sstevel@tonic-gate arg++; 8427c478bd9Sstevel@tonic-gate (void) memmove(p, p+1, strlen(p+1)+1); 8437c478bd9Sstevel@tonic-gate } else if (((p = strchr(arg, ':')) == NULL) || 8447c478bd9Sstevel@tonic-gate (strchr(p+1, ':') != NULL)) { 8457c478bd9Sstevel@tonic-gate add_listen_addr(options, arg, 0); 8467c478bd9Sstevel@tonic-gate break; 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate if (*p == ':') { 8497c478bd9Sstevel@tonic-gate u_short port; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate p++; 8527c478bd9Sstevel@tonic-gate if (*p == '\0') 8537c478bd9Sstevel@tonic-gate fatal("%s line %d: bad inet addr:port usage.", 8547c478bd9Sstevel@tonic-gate filename, linenum); 8557c478bd9Sstevel@tonic-gate else { 8567c478bd9Sstevel@tonic-gate *(p-1) = '\0'; 8577c478bd9Sstevel@tonic-gate if ((port = a2port(p)) == 0) 8587c478bd9Sstevel@tonic-gate fatal("%s line %d: bad port number.", 8597c478bd9Sstevel@tonic-gate filename, linenum); 8607c478bd9Sstevel@tonic-gate add_listen_addr(options, arg, port); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate } else if (*p == '\0') 8637c478bd9Sstevel@tonic-gate add_listen_addr(options, arg, 0); 8647c478bd9Sstevel@tonic-gate else 8657c478bd9Sstevel@tonic-gate fatal("%s line %d: bad inet addr usage.", 8667c478bd9Sstevel@tonic-gate filename, linenum); 8677c478bd9Sstevel@tonic-gate break; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate case sHostKeyFile: 8707c478bd9Sstevel@tonic-gate intptr = &options->num_host_key_files; 8717c478bd9Sstevel@tonic-gate if (*intptr >= MAX_HOSTKEYS) 8727c478bd9Sstevel@tonic-gate fatal("%s line %d: too many host keys specified (max %d).", 8737c478bd9Sstevel@tonic-gate filename, linenum, MAX_HOSTKEYS); 8747c478bd9Sstevel@tonic-gate charptr = &options->host_key_files[*intptr]; 8757c478bd9Sstevel@tonic-gate parse_filename: 8767c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 8777c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 8787c478bd9Sstevel@tonic-gate fatal("%s line %d: missing file name.", 8797c478bd9Sstevel@tonic-gate filename, linenum); 880b07b2f5cSHuie-Ying Lee if (*activep && *charptr == NULL) { 8817c478bd9Sstevel@tonic-gate *charptr = tilde_expand_filename(arg, getuid()); 8827c478bd9Sstevel@tonic-gate /* increase optional counter */ 8837c478bd9Sstevel@tonic-gate if (intptr != NULL) 8847c478bd9Sstevel@tonic-gate *intptr = *intptr + 1; 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate break; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate case sPidFile: 8897c478bd9Sstevel@tonic-gate charptr = &options->pid_file; 8907c478bd9Sstevel@tonic-gate goto parse_filename; 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate case sPermitRootLogin: 8937c478bd9Sstevel@tonic-gate intptr = &options->permit_root_login; 8947c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 8957c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 8967c478bd9Sstevel@tonic-gate fatal("%s line %d: missing yes/" 8977c478bd9Sstevel@tonic-gate "without-password/forced-commands-only/no " 8987c478bd9Sstevel@tonic-gate "argument.", filename, linenum); 8997c478bd9Sstevel@tonic-gate value = 0; /* silence compiler */ 9007c478bd9Sstevel@tonic-gate if (strcmp(arg, "without-password") == 0) 9017c478bd9Sstevel@tonic-gate value = PERMIT_NO_PASSWD; 9027c478bd9Sstevel@tonic-gate else if (strcmp(arg, "forced-commands-only") == 0) 9037c478bd9Sstevel@tonic-gate value = PERMIT_FORCED_ONLY; 9047c478bd9Sstevel@tonic-gate else if (strcmp(arg, "yes") == 0) 9057c478bd9Sstevel@tonic-gate value = PERMIT_YES; 9067c478bd9Sstevel@tonic-gate else if (strcmp(arg, "no") == 0) 9077c478bd9Sstevel@tonic-gate value = PERMIT_NO; 9087c478bd9Sstevel@tonic-gate else 9097c478bd9Sstevel@tonic-gate fatal("%s line %d: Bad yes/" 9107c478bd9Sstevel@tonic-gate "without-password/forced-commands-only/no " 9117c478bd9Sstevel@tonic-gate "argument: %s", filename, linenum, arg); 912b07b2f5cSHuie-Ying Lee if (*activep && *intptr == -1) 9137c478bd9Sstevel@tonic-gate *intptr = value; 9147c478bd9Sstevel@tonic-gate break; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate case sIgnoreRhosts: 9177c478bd9Sstevel@tonic-gate intptr = &options->ignore_rhosts; 9187c478bd9Sstevel@tonic-gate parse_flag: 9197c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 9207c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 9217c478bd9Sstevel@tonic-gate fatal("%s line %d: missing yes/no argument.", 9227c478bd9Sstevel@tonic-gate filename, linenum); 9237c478bd9Sstevel@tonic-gate value = 0; /* silence compiler */ 9247c478bd9Sstevel@tonic-gate if (strcmp(arg, "yes") == 0) 9257c478bd9Sstevel@tonic-gate value = 1; 9267c478bd9Sstevel@tonic-gate else if (strcmp(arg, "no") == 0) 9277c478bd9Sstevel@tonic-gate value = 0; 9287c478bd9Sstevel@tonic-gate else 9297c478bd9Sstevel@tonic-gate fatal("%s line %d: Bad yes/no argument: %s", 9307c478bd9Sstevel@tonic-gate filename, linenum, arg); 931b07b2f5cSHuie-Ying Lee if (*activep && *intptr == -1) 9327c478bd9Sstevel@tonic-gate *intptr = value; 9337c478bd9Sstevel@tonic-gate break; 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate case sIgnoreUserKnownHosts: 9367c478bd9Sstevel@tonic-gate intptr = &options->ignore_user_known_hosts; 9377c478bd9Sstevel@tonic-gate goto parse_flag; 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate case sRhostsAuthentication: 9407c478bd9Sstevel@tonic-gate intptr = &options->rhosts_authentication; 9417c478bd9Sstevel@tonic-gate goto parse_flag; 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate case sRhostsRSAAuthentication: 9447c478bd9Sstevel@tonic-gate intptr = &options->rhosts_rsa_authentication; 9457c478bd9Sstevel@tonic-gate goto parse_flag; 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate case sHostbasedAuthentication: 9487c478bd9Sstevel@tonic-gate intptr = &options->hostbased_authentication; 9497c478bd9Sstevel@tonic-gate goto parse_flag; 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate case sHostbasedUsesNameFromPacketOnly: 9527c478bd9Sstevel@tonic-gate intptr = &options->hostbased_uses_name_from_packet_only; 9537c478bd9Sstevel@tonic-gate goto parse_flag; 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate case sRSAAuthentication: 9567c478bd9Sstevel@tonic-gate intptr = &options->rsa_authentication; 9577c478bd9Sstevel@tonic-gate goto parse_flag; 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate case sPubkeyAuthentication: 9607c478bd9Sstevel@tonic-gate intptr = &options->pubkey_authentication; 9617c478bd9Sstevel@tonic-gate goto parse_flag; 9627c478bd9Sstevel@tonic-gate #ifdef GSSAPI 9637c478bd9Sstevel@tonic-gate case sGssAuthentication: 9647c478bd9Sstevel@tonic-gate intptr = &options->gss_authentication; 9657c478bd9Sstevel@tonic-gate goto parse_flag; 9667c478bd9Sstevel@tonic-gate case sGssKeyEx: 9677c478bd9Sstevel@tonic-gate intptr = &options->gss_keyex; 9687c478bd9Sstevel@tonic-gate goto parse_flag; 9697c478bd9Sstevel@tonic-gate case sGssStoreDelegCreds: 9707c478bd9Sstevel@tonic-gate intptr = &options->gss_keyex; 9717c478bd9Sstevel@tonic-gate goto parse_flag; 9727c478bd9Sstevel@tonic-gate #ifndef SUNW_GSSAPI 9737c478bd9Sstevel@tonic-gate case sGssUseSessionCredCache: 9747c478bd9Sstevel@tonic-gate intptr = &options->gss_use_session_ccache; 9757c478bd9Sstevel@tonic-gate goto parse_flag; 9767c478bd9Sstevel@tonic-gate case sGssCleanupCreds: 9777c478bd9Sstevel@tonic-gate intptr = &options->gss_cleanup_creds; 9787c478bd9Sstevel@tonic-gate goto parse_flag; 9797c478bd9Sstevel@tonic-gate #endif /* SUNW_GSSAPI */ 9807c478bd9Sstevel@tonic-gate #endif /* GSSAPI */ 9817c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 9827c478bd9Sstevel@tonic-gate case sKerberosAuthentication: 9837c478bd9Sstevel@tonic-gate intptr = &options->kerberos_authentication; 9847c478bd9Sstevel@tonic-gate goto parse_flag; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate case sKerberosOrLocalPasswd: 9877c478bd9Sstevel@tonic-gate intptr = &options->kerberos_or_local_passwd; 9887c478bd9Sstevel@tonic-gate goto parse_flag; 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate case sKerberosTicketCleanup: 9917c478bd9Sstevel@tonic-gate intptr = &options->kerberos_ticket_cleanup; 9927c478bd9Sstevel@tonic-gate goto parse_flag; 9937c478bd9Sstevel@tonic-gate #endif 9947c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 9957c478bd9Sstevel@tonic-gate case sKerberosTgtPassing: 9967c478bd9Sstevel@tonic-gate intptr = &options->kerberos_tgt_passing; 9977c478bd9Sstevel@tonic-gate goto parse_flag; 9987c478bd9Sstevel@tonic-gate #endif 9997c478bd9Sstevel@tonic-gate #ifdef AFS 10007c478bd9Sstevel@tonic-gate case sAFSTokenPassing: 10017c478bd9Sstevel@tonic-gate intptr = &options->afs_token_passing; 10027c478bd9Sstevel@tonic-gate goto parse_flag; 10037c478bd9Sstevel@tonic-gate #endif 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate case sPasswordAuthentication: 10067c478bd9Sstevel@tonic-gate intptr = &options->password_authentication; 10077c478bd9Sstevel@tonic-gate goto parse_flag; 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate case sKbdInteractiveAuthentication: 10107c478bd9Sstevel@tonic-gate intptr = &options->kbd_interactive_authentication; 10117c478bd9Sstevel@tonic-gate goto parse_flag; 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate case sChallengeResponseAuthentication: 10147c478bd9Sstevel@tonic-gate intptr = &options->challenge_response_authentication; 10157c478bd9Sstevel@tonic-gate goto parse_flag; 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate case sPrintMotd: 10187c478bd9Sstevel@tonic-gate intptr = &options->print_motd; 10197c478bd9Sstevel@tonic-gate goto parse_flag; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate case sPrintLastLog: 10227c478bd9Sstevel@tonic-gate intptr = &options->print_lastlog; 10237c478bd9Sstevel@tonic-gate goto parse_flag; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate case sX11Forwarding: 10267c478bd9Sstevel@tonic-gate intptr = &options->x11_forwarding; 10277c478bd9Sstevel@tonic-gate goto parse_flag; 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate case sX11DisplayOffset: 10307c478bd9Sstevel@tonic-gate intptr = &options->x11_display_offset; 10317c478bd9Sstevel@tonic-gate goto parse_int; 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate case sX11UseLocalhost: 10347c478bd9Sstevel@tonic-gate intptr = &options->x11_use_localhost; 10357c478bd9Sstevel@tonic-gate goto parse_flag; 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate case sXAuthLocation: 10387c478bd9Sstevel@tonic-gate charptr = &options->xauth_location; 10397c478bd9Sstevel@tonic-gate goto parse_filename; 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate case sStrictModes: 10427c478bd9Sstevel@tonic-gate intptr = &options->strict_modes; 10437c478bd9Sstevel@tonic-gate goto parse_flag; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate case sKeepAlives: 10467c478bd9Sstevel@tonic-gate intptr = &options->keepalives; 10477c478bd9Sstevel@tonic-gate goto parse_flag; 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate case sEmptyPasswd: 10507c478bd9Sstevel@tonic-gate intptr = &options->permit_empty_passwd; 10517c478bd9Sstevel@tonic-gate goto parse_flag; 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate case sPermitUserEnvironment: 10547c478bd9Sstevel@tonic-gate intptr = &options->permit_user_env; 10557c478bd9Sstevel@tonic-gate goto parse_flag; 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate case sUseLogin: 1058b9aa66a7SJan Pechanec log("%s line %d: ignoring UseLogin option value." 1059b9aa66a7SJan Pechanec " This option is always off.", filename, linenum); 1060b9aa66a7SJan Pechanec while (arg) 1061b9aa66a7SJan Pechanec arg = strdelim(&cp); 1062b9aa66a7SJan Pechanec break; 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate case sCompression: 10657c478bd9Sstevel@tonic-gate intptr = &options->compression; 10667c478bd9Sstevel@tonic-gate goto parse_flag; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate case sGatewayPorts: 1069b07b2f5cSHuie-Ying Lee intptr = &options->gateway_ports; 10709b03ea0fSjp161948 arg = strdelim(&cp); 1071b07b2f5cSHuie-Ying Lee if (!arg || *arg == '\0') 1072b07b2f5cSHuie-Ying Lee fatal("%s line %d: missing yes/no/clientspecified " 10739b03ea0fSjp161948 "argument.", filename, linenum); 1074b07b2f5cSHuie-Ying Lee value = 0; /* silence compiler */ 1075b07b2f5cSHuie-Ying Lee if (strcmp(arg, "clientspecified") == 0) 1076b07b2f5cSHuie-Ying Lee value = 2; 1077b07b2f5cSHuie-Ying Lee else if (strcmp(arg, "yes") == 0) 1078b07b2f5cSHuie-Ying Lee value = 1; 1079b07b2f5cSHuie-Ying Lee else if (strcmp(arg, "no") == 0) 1080b07b2f5cSHuie-Ying Lee value = 0; 1081b07b2f5cSHuie-Ying Lee else 1082b07b2f5cSHuie-Ying Lee fatal("%s line %d: Bad yes/no/clientspecified " 1083b07b2f5cSHuie-Ying Lee "argument: %s", filename, linenum, arg); 1084b07b2f5cSHuie-Ying Lee if (*activep && *intptr == -1) 1085b07b2f5cSHuie-Ying Lee *intptr = value; 10869b03ea0fSjp161948 break; 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate case sVerifyReverseMapping: 10897c478bd9Sstevel@tonic-gate intptr = &options->verify_reverse_mapping; 10907c478bd9Sstevel@tonic-gate goto parse_flag; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate case sLogFacility: 10937c478bd9Sstevel@tonic-gate intptr = (int *) &options->log_facility; 10947c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 10957c478bd9Sstevel@tonic-gate value = log_facility_number(arg); 10967c478bd9Sstevel@tonic-gate if (value == SYSLOG_FACILITY_NOT_SET) 10977c478bd9Sstevel@tonic-gate fatal("%.200s line %d: unsupported log facility '%s'", 10987c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 10997c478bd9Sstevel@tonic-gate if (*intptr == -1) 11007c478bd9Sstevel@tonic-gate *intptr = (SyslogFacility) value; 11017c478bd9Sstevel@tonic-gate break; 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate case sLogLevel: 11047c478bd9Sstevel@tonic-gate intptr = (int *) &options->log_level; 11057c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 11067c478bd9Sstevel@tonic-gate value = log_level_number(arg); 11077c478bd9Sstevel@tonic-gate if (value == SYSLOG_LEVEL_NOT_SET) 11087c478bd9Sstevel@tonic-gate fatal("%.200s line %d: unsupported log level '%s'", 11097c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 11107c478bd9Sstevel@tonic-gate if (*intptr == -1) 11117c478bd9Sstevel@tonic-gate *intptr = (LogLevel) value; 11127c478bd9Sstevel@tonic-gate break; 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate case sAllowTcpForwarding: 11157c478bd9Sstevel@tonic-gate intptr = &options->allow_tcp_forwarding; 11167c478bd9Sstevel@tonic-gate goto parse_flag; 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate case sUsePrivilegeSeparation: 11199a8058b5Sjp161948 log("%s line %d: ignoring UsePrivilegeSeparation option value." 11209a8058b5Sjp161948 " This option is always on.", filename, linenum); 11219a8058b5Sjp161948 while (arg) 11229a8058b5Sjp161948 arg = strdelim(&cp); 11239a8058b5Sjp161948 break; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate case sAllowUsers: 11267c478bd9Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11277c478bd9Sstevel@tonic-gate if (options->num_allow_users >= MAX_ALLOW_USERS) 11287c478bd9Sstevel@tonic-gate fatal("%s line %d: too many allow users.", 11297c478bd9Sstevel@tonic-gate filename, linenum); 11307c478bd9Sstevel@tonic-gate options->allow_users[options->num_allow_users++] = 11317c478bd9Sstevel@tonic-gate xstrdup(arg); 11327c478bd9Sstevel@tonic-gate } 11337c478bd9Sstevel@tonic-gate break; 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate case sDenyUsers: 11367c478bd9Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11377c478bd9Sstevel@tonic-gate if (options->num_deny_users >= MAX_DENY_USERS) 11387c478bd9Sstevel@tonic-gate fatal( "%s line %d: too many deny users.", 11397c478bd9Sstevel@tonic-gate filename, linenum); 11407c478bd9Sstevel@tonic-gate options->deny_users[options->num_deny_users++] = 11417c478bd9Sstevel@tonic-gate xstrdup(arg); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate break; 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate case sAllowGroups: 11467c478bd9Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11477c478bd9Sstevel@tonic-gate if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 11487c478bd9Sstevel@tonic-gate fatal("%s line %d: too many allow groups.", 11497c478bd9Sstevel@tonic-gate filename, linenum); 11507c478bd9Sstevel@tonic-gate options->allow_groups[options->num_allow_groups++] = 11517c478bd9Sstevel@tonic-gate xstrdup(arg); 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate break; 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate case sDenyGroups: 11567c478bd9Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11577c478bd9Sstevel@tonic-gate if (options->num_deny_groups >= MAX_DENY_GROUPS) 11587c478bd9Sstevel@tonic-gate fatal("%s line %d: too many deny groups.", 11597c478bd9Sstevel@tonic-gate filename, linenum); 11607c478bd9Sstevel@tonic-gate options->deny_groups[options->num_deny_groups++] = xstrdup(arg); 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate break; 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate case sCiphers: 11657c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 11667c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 11677c478bd9Sstevel@tonic-gate fatal("%s line %d: Missing argument.", filename, linenum); 11687c478bd9Sstevel@tonic-gate if (!ciphers_valid(arg)) 11697c478bd9Sstevel@tonic-gate fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 11707c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 11717c478bd9Sstevel@tonic-gate if (options->ciphers == NULL) 11727c478bd9Sstevel@tonic-gate options->ciphers = xstrdup(arg); 11737c478bd9Sstevel@tonic-gate break; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate case sMacs: 11767c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 11777c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 11787c478bd9Sstevel@tonic-gate fatal("%s line %d: Missing argument.", filename, linenum); 11797c478bd9Sstevel@tonic-gate if (!mac_valid(arg)) 11807c478bd9Sstevel@tonic-gate fatal("%s line %d: Bad SSH2 mac spec '%s'.", 11817c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 11827c478bd9Sstevel@tonic-gate if (options->macs == NULL) 11837c478bd9Sstevel@tonic-gate options->macs = xstrdup(arg); 11847c478bd9Sstevel@tonic-gate break; 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate case sProtocol: 11877c478bd9Sstevel@tonic-gate intptr = &options->protocol; 11887c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 11897c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 11907c478bd9Sstevel@tonic-gate fatal("%s line %d: Missing argument.", filename, linenum); 11917c478bd9Sstevel@tonic-gate value = proto_spec(arg); 11927c478bd9Sstevel@tonic-gate if (value == SSH_PROTO_UNKNOWN) 11937c478bd9Sstevel@tonic-gate fatal("%s line %d: Bad protocol spec '%s'.", 11947c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 11957c478bd9Sstevel@tonic-gate if (*intptr == SSH_PROTO_UNKNOWN) 11967c478bd9Sstevel@tonic-gate *intptr = value; 11977c478bd9Sstevel@tonic-gate break; 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate case sSubsystem: 12007c478bd9Sstevel@tonic-gate if (options->num_subsystems >= MAX_SUBSYSTEMS) { 12017c478bd9Sstevel@tonic-gate fatal("%s line %d: too many subsystems defined.", 12027c478bd9Sstevel@tonic-gate filename, linenum); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 12057c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 12067c478bd9Sstevel@tonic-gate fatal("%s line %d: Missing subsystem name.", 12077c478bd9Sstevel@tonic-gate filename, linenum); 1208b07b2f5cSHuie-Ying Lee if (!*activep) { 1209b07b2f5cSHuie-Ying Lee arg = strdelim(&cp); 1210b07b2f5cSHuie-Ying Lee break; 1211b07b2f5cSHuie-Ying Lee } 12127c478bd9Sstevel@tonic-gate for (i = 0; i < options->num_subsystems; i++) 12137c478bd9Sstevel@tonic-gate if (strcmp(arg, options->subsystem_name[i]) == 0) 12147c478bd9Sstevel@tonic-gate fatal("%s line %d: Subsystem '%s' already defined.", 12157c478bd9Sstevel@tonic-gate filename, linenum, arg); 12167c478bd9Sstevel@tonic-gate options->subsystem_name[options->num_subsystems] = xstrdup(arg); 12177c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 12187c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 12197c478bd9Sstevel@tonic-gate fatal("%s line %d: Missing subsystem command.", 12207c478bd9Sstevel@tonic-gate filename, linenum); 12217c478bd9Sstevel@tonic-gate options->subsystem_command[options->num_subsystems] = xstrdup(arg); 12226f8d59d8SJan Pechanec 12236f8d59d8SJan Pechanec /* 12246f8d59d8SJan Pechanec * Collect arguments (separate to executable), including the 12256f8d59d8SJan Pechanec * name of the executable, in a way that is easier to parse 12266f8d59d8SJan Pechanec * later. 12276f8d59d8SJan Pechanec */ 12286f8d59d8SJan Pechanec p = xstrdup(arg); 12296f8d59d8SJan Pechanec len = strlen(p) + 1; 12306f8d59d8SJan Pechanec while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { 12316f8d59d8SJan Pechanec len += 1 + strlen(arg); 12326f8d59d8SJan Pechanec p = xrealloc(p, len); 12336f8d59d8SJan Pechanec strlcat(p, " ", len); 12346f8d59d8SJan Pechanec strlcat(p, arg, len); 12356f8d59d8SJan Pechanec } 12366f8d59d8SJan Pechanec options->subsystem_args[options->num_subsystems] = p; 12377c478bd9Sstevel@tonic-gate options->num_subsystems++; 12387c478bd9Sstevel@tonic-gate break; 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate case sMaxStartups: 12417c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 12427c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0') 12437c478bd9Sstevel@tonic-gate fatal("%s line %d: Missing MaxStartups spec.", 12447c478bd9Sstevel@tonic-gate filename, linenum); 12457c478bd9Sstevel@tonic-gate if ((n = sscanf(arg, "%d:%d:%d", 12467c478bd9Sstevel@tonic-gate &options->max_startups_begin, 12477c478bd9Sstevel@tonic-gate &options->max_startups_rate, 12487c478bd9Sstevel@tonic-gate &options->max_startups)) == 3) { 12497c478bd9Sstevel@tonic-gate if (options->max_startups_begin > 12507c478bd9Sstevel@tonic-gate options->max_startups || 12517c478bd9Sstevel@tonic-gate options->max_startups_rate > 100 || 12527c478bd9Sstevel@tonic-gate options->max_startups_rate < 1) 12537c478bd9Sstevel@tonic-gate fatal("%s line %d: Illegal MaxStartups spec.", 12547c478bd9Sstevel@tonic-gate filename, linenum); 12557c478bd9Sstevel@tonic-gate } else if (n != 1) 12567c478bd9Sstevel@tonic-gate fatal("%s line %d: Illegal MaxStartups spec.", 12577c478bd9Sstevel@tonic-gate filename, linenum); 12587c478bd9Sstevel@tonic-gate else 12597c478bd9Sstevel@tonic-gate options->max_startups = options->max_startups_begin; 12607c478bd9Sstevel@tonic-gate break; 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate case sBanner: 12637c478bd9Sstevel@tonic-gate charptr = &options->banner; 12647c478bd9Sstevel@tonic-gate goto parse_filename; 12657c478bd9Sstevel@tonic-gate /* 12667c478bd9Sstevel@tonic-gate * These options can contain %X options expanded at 12677c478bd9Sstevel@tonic-gate * connect time, so that you can specify paths like: 12687c478bd9Sstevel@tonic-gate * 12697c478bd9Sstevel@tonic-gate * AuthorizedKeysFile /etc/ssh_keys/%u 12707c478bd9Sstevel@tonic-gate */ 12717c478bd9Sstevel@tonic-gate case sAuthorizedKeysFile: 12727c478bd9Sstevel@tonic-gate case sAuthorizedKeysFile2: 12737c478bd9Sstevel@tonic-gate charptr = (opcode == sAuthorizedKeysFile) ? 12747c478bd9Sstevel@tonic-gate &options->authorized_keys_file : 12757c478bd9Sstevel@tonic-gate &options->authorized_keys_file2; 12767c478bd9Sstevel@tonic-gate goto parse_filename; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate case sClientAliveInterval: 12797c478bd9Sstevel@tonic-gate intptr = &options->client_alive_interval; 12807c478bd9Sstevel@tonic-gate goto parse_time; 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate case sClientAliveCountMax: 12837c478bd9Sstevel@tonic-gate intptr = &options->client_alive_count_max; 12847c478bd9Sstevel@tonic-gate goto parse_int; 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate case sMaxAuthTries: 12877c478bd9Sstevel@tonic-gate intptr = &options->max_auth_tries; 12887c478bd9Sstevel@tonic-gate goto parse_int; 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate case sMaxAuthTriesLog: 12917c478bd9Sstevel@tonic-gate intptr = &options->max_auth_tries_log; 12927c478bd9Sstevel@tonic-gate goto parse_int; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate case sLookupClientHostnames: 12957c478bd9Sstevel@tonic-gate intptr = &options->lookup_client_hostnames; 12967c478bd9Sstevel@tonic-gate goto parse_flag; 12976f8d59d8SJan Pechanec 1298cd7d5fafSJan Pechanec case sUseOpenSSLEngine: 1299cd7d5fafSJan Pechanec intptr = &options->use_openssl_engine; 1300cd7d5fafSJan Pechanec goto parse_flag; 13017c478bd9Sstevel@tonic-gate 13026f8d59d8SJan Pechanec case sChrootDirectory: 13036f8d59d8SJan Pechanec charptr = &options->chroot_directory; 13046f8d59d8SJan Pechanec 13056f8d59d8SJan Pechanec arg = strdelim(&cp); 13066f8d59d8SJan Pechanec if (arg == NULL || *arg == '\0') 13076f8d59d8SJan Pechanec fatal("%s line %d: missing directory name for " 13086f8d59d8SJan Pechanec "ChrootDirectory.", filename, linenum); 1309b07b2f5cSHuie-Ying Lee if (*activep && *charptr == NULL) 13106f8d59d8SJan Pechanec *charptr = xstrdup(arg); 13116f8d59d8SJan Pechanec break; 13126f8d59d8SJan Pechanec 1313d8a94255SErik Trauschke case sPreUserauthHook: 1314d8a94255SErik Trauschke charptr = &options->pre_userauth_hook; 1315d8a94255SErik Trauschke goto parse_filename; 1316d8a94255SErik Trauschke 1317b07b2f5cSHuie-Ying Lee case sMatch: 1318b07b2f5cSHuie-Ying Lee if (cmdline) 1319b07b2f5cSHuie-Ying Lee fatal("Match directive not supported as a command-line " 1320b07b2f5cSHuie-Ying Lee "option"); 1321b07b2f5cSHuie-Ying Lee value = match_cfg_line(&cp, linenum, user, host, address); 1322b07b2f5cSHuie-Ying Lee if (value < 0) 1323b07b2f5cSHuie-Ying Lee fatal("%s line %d: Bad Match condition", filename, 1324b07b2f5cSHuie-Ying Lee linenum); 1325b07b2f5cSHuie-Ying Lee *activep = value; 1326b07b2f5cSHuie-Ying Lee break; 1327b07b2f5cSHuie-Ying Lee 13287c478bd9Sstevel@tonic-gate case sDeprecated: 13297c478bd9Sstevel@tonic-gate log("%s line %d: Deprecated option %s", 13307c478bd9Sstevel@tonic-gate filename, linenum, arg); 13317c478bd9Sstevel@tonic-gate while (arg) 13327c478bd9Sstevel@tonic-gate arg = strdelim(&cp); 13337c478bd9Sstevel@tonic-gate break; 13347c478bd9Sstevel@tonic-gate 1335bdb005b5SDarren J Moffat case sPAMServicePrefix: 1336bdb005b5SDarren J Moffat arg = strdelim(&cp); 1337bdb005b5SDarren J Moffat if (!arg || *arg == '\0') 1338bdb005b5SDarren J Moffat fatal("%s line %d: Missing argument.", 1339bdb005b5SDarren J Moffat filename, linenum); 1340bdb005b5SDarren J Moffat if (options->pam_service_name != NULL) 1341bdb005b5SDarren J Moffat fatal("%s line %d: PAMServiceName and PAMServicePrefix " 1342bdb005b5SDarren J Moffat "are mutually exclusive.", filename, linenum); 1343bdb005b5SDarren J Moffat if (options->pam_service_prefix == NULL) 1344bdb005b5SDarren J Moffat options->pam_service_prefix = xstrdup(arg); 1345bdb005b5SDarren J Moffat break; 1346bdb005b5SDarren J Moffat 1347bdb005b5SDarren J Moffat case sPAMServiceName: 1348bdb005b5SDarren J Moffat arg = strdelim(&cp); 1349bdb005b5SDarren J Moffat if (!arg || *arg == '\0') 1350bdb005b5SDarren J Moffat fatal("%s line %d: Missing argument.", 1351bdb005b5SDarren J Moffat filename, linenum); 1352bdb005b5SDarren J Moffat if (options->pam_service_prefix != NULL) 1353bdb005b5SDarren J Moffat fatal("%s line %d: PAMServiceName and PAMServicePrefix " 1354bdb005b5SDarren J Moffat "are mutually exclusive.", filename, linenum); 1355bdb005b5SDarren J Moffat if (options->pam_service_name == NULL) 1356bdb005b5SDarren J Moffat options->pam_service_name = xstrdup(arg); 1357bdb005b5SDarren J Moffat break; 1358bdb005b5SDarren J Moffat 13597c478bd9Sstevel@tonic-gate default: 13607c478bd9Sstevel@tonic-gate fatal("%s line %d: Missing handler for opcode %s (%d)", 13617c478bd9Sstevel@tonic-gate filename, linenum, arg, opcode); 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 13647c478bd9Sstevel@tonic-gate fatal("%s line %d: garbage at end of line; \"%.200s\".", 13657c478bd9Sstevel@tonic-gate filename, linenum, arg); 13667c478bd9Sstevel@tonic-gate return 0; 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate 1369b07b2f5cSHuie-Ying Lee 13707c478bd9Sstevel@tonic-gate /* Reads the server configuration file. */ 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate void 1373b07b2f5cSHuie-Ying Lee load_server_config(const char *filename, Buffer *conf) 13747c478bd9Sstevel@tonic-gate { 1375b07b2f5cSHuie-Ying Lee char line[1024], *cp; 13767c478bd9Sstevel@tonic-gate FILE *f; 13777c478bd9Sstevel@tonic-gate 1378b07b2f5cSHuie-Ying Lee debug2("%s: filename %s", __func__, filename); 1379b07b2f5cSHuie-Ying Lee if ((f = fopen(filename, "r")) == NULL) { 13807c478bd9Sstevel@tonic-gate perror(filename); 13817c478bd9Sstevel@tonic-gate exit(1); 13827c478bd9Sstevel@tonic-gate } 1383b07b2f5cSHuie-Ying Lee buffer_clear(conf); 13847c478bd9Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) { 1385b07b2f5cSHuie-Ying Lee /* 1386b07b2f5cSHuie-Ying Lee * Trim out comments and strip whitespace 1387b07b2f5cSHuie-Ying Lee * NB - preserve newlines, they are needed to reproduce 1388b07b2f5cSHuie-Ying Lee * line numbers later for error messages 1389b07b2f5cSHuie-Ying Lee */ 1390b07b2f5cSHuie-Ying Lee if ((cp = strchr(line, '#')) != NULL) 1391b07b2f5cSHuie-Ying Lee memcpy(cp, "\n", 2); 1392b07b2f5cSHuie-Ying Lee cp = line + strspn(line, " \t\r"); 1393b07b2f5cSHuie-Ying Lee 1394b07b2f5cSHuie-Ying Lee buffer_append(conf, cp, strlen(cp)); 1395b07b2f5cSHuie-Ying Lee } 1396b07b2f5cSHuie-Ying Lee buffer_append(conf, "\0", 1); 1397b07b2f5cSHuie-Ying Lee fclose(f); 1398b07b2f5cSHuie-Ying Lee debug2("%s: done config len = %d", __func__, buffer_len(conf)); 1399b07b2f5cSHuie-Ying Lee } 1400b07b2f5cSHuie-Ying Lee 1401b07b2f5cSHuie-Ying Lee void 1402b07b2f5cSHuie-Ying Lee parse_server_match_config(ServerOptions *options, const char *user, 1403b07b2f5cSHuie-Ying Lee const char *host, const char *address) 1404b07b2f5cSHuie-Ying Lee { 1405b07b2f5cSHuie-Ying Lee ServerOptions mo; 1406b07b2f5cSHuie-Ying Lee 1407b07b2f5cSHuie-Ying Lee initialize_server_options(&mo); 1408b07b2f5cSHuie-Ying Lee parse_server_config(&mo, "reprocess config", &cfg, user, host, address); 1409b07b2f5cSHuie-Ying Lee copy_set_server_options(options, &mo, 0); 1410b07b2f5cSHuie-Ying Lee } 1411b07b2f5cSHuie-Ying Lee 1412b07b2f5cSHuie-Ying Lee 1413b07b2f5cSHuie-Ying Lee 1414b07b2f5cSHuie-Ying Lee /* Helper macros */ 1415b07b2f5cSHuie-Ying Lee #define M_CP_INTOPT(n) do {\ 1416b07b2f5cSHuie-Ying Lee if (src->n != -1) \ 1417b07b2f5cSHuie-Ying Lee dst->n = src->n; \ 1418b07b2f5cSHuie-Ying Lee } while (0) 1419b07b2f5cSHuie-Ying Lee #define M_CP_STROPT(n) do {\ 1420b07b2f5cSHuie-Ying Lee if (src->n != NULL) { \ 1421b07b2f5cSHuie-Ying Lee if (dst->n != NULL) \ 1422b07b2f5cSHuie-Ying Lee xfree(dst->n); \ 1423b07b2f5cSHuie-Ying Lee dst->n = src->n; \ 1424b07b2f5cSHuie-Ying Lee } \ 1425b07b2f5cSHuie-Ying Lee } while(0) 1426b07b2f5cSHuie-Ying Lee 1427b07b2f5cSHuie-Ying Lee /* 1428b07b2f5cSHuie-Ying Lee * Copy any supported values that are set. 1429b07b2f5cSHuie-Ying Lee * 1430b07b2f5cSHuie-Ying Lee * If the preauth flag is set, we do not bother copying the the string or 1431b07b2f5cSHuie-Ying Lee * array values that are not used pre-authentication, because any that we 1432b07b2f5cSHuie-Ying Lee * do use must be explictly sent in mm_getpwnamallow(). 1433b07b2f5cSHuie-Ying Lee */ 1434b07b2f5cSHuie-Ying Lee void 1435b07b2f5cSHuie-Ying Lee copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) 1436b07b2f5cSHuie-Ying Lee { 1437b07b2f5cSHuie-Ying Lee M_CP_INTOPT(password_authentication); 1438b07b2f5cSHuie-Ying Lee M_CP_INTOPT(gss_authentication); 1439b07b2f5cSHuie-Ying Lee M_CP_INTOPT(rsa_authentication); 1440b07b2f5cSHuie-Ying Lee M_CP_INTOPT(pubkey_authentication); 1441b07b2f5cSHuie-Ying Lee M_CP_INTOPT(hostbased_authentication); 1442b07b2f5cSHuie-Ying Lee M_CP_INTOPT(kbd_interactive_authentication); 1443b07b2f5cSHuie-Ying Lee M_CP_INTOPT(permit_root_login); 1444b07b2f5cSHuie-Ying Lee M_CP_INTOPT(permit_empty_passwd); 1445b07b2f5cSHuie-Ying Lee M_CP_INTOPT(allow_tcp_forwarding); 1446b07b2f5cSHuie-Ying Lee M_CP_INTOPT(gateway_ports); 1447b07b2f5cSHuie-Ying Lee M_CP_INTOPT(x11_display_offset); 1448b07b2f5cSHuie-Ying Lee M_CP_INTOPT(x11_forwarding); 1449b07b2f5cSHuie-Ying Lee M_CP_INTOPT(x11_use_localhost); 1450b07b2f5cSHuie-Ying Lee M_CP_INTOPT(max_auth_tries); 1451b07b2f5cSHuie-Ying Lee M_CP_STROPT(banner); 1452b07b2f5cSHuie-Ying Lee 1453b07b2f5cSHuie-Ying Lee if (preauth) 1454b07b2f5cSHuie-Ying Lee return; 1455b07b2f5cSHuie-Ying Lee M_CP_STROPT(chroot_directory); 1456b07b2f5cSHuie-Ying Lee } 1457b07b2f5cSHuie-Ying Lee 1458b07b2f5cSHuie-Ying Lee #undef M_CP_INTOPT 1459b07b2f5cSHuie-Ying Lee #undef M_CP_STROPT 1460b07b2f5cSHuie-Ying Lee 1461b07b2f5cSHuie-Ying Lee void 1462b07b2f5cSHuie-Ying Lee parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1463b07b2f5cSHuie-Ying Lee const char *user, const char *host, const char *address) 1464b07b2f5cSHuie-Ying Lee { 1465b07b2f5cSHuie-Ying Lee int active, linenum, bad_options = 0; 1466b07b2f5cSHuie-Ying Lee char *cp, *obuf, *cbuf; 1467b07b2f5cSHuie-Ying Lee 1468b07b2f5cSHuie-Ying Lee debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); 1469b07b2f5cSHuie-Ying Lee 1470b07b2f5cSHuie-Ying Lee obuf = cbuf = xstrdup(buffer_ptr(conf)); 1471b07b2f5cSHuie-Ying Lee active = user ? 0 : 1; 1472b07b2f5cSHuie-Ying Lee linenum = 1; 1473b07b2f5cSHuie-Ying Lee while ((cp = strsep(&cbuf, "\n")) != NULL) { 1474b07b2f5cSHuie-Ying Lee if (process_server_config_line(options, cp, filename, 1475b07b2f5cSHuie-Ying Lee linenum++, &active, user, host, address) != 0) 14767c478bd9Sstevel@tonic-gate bad_options++; 14777c478bd9Sstevel@tonic-gate } 1478b07b2f5cSHuie-Ying Lee xfree(obuf); 14797c478bd9Sstevel@tonic-gate if (bad_options > 0) 14807c478bd9Sstevel@tonic-gate fatal("%s: terminating, %d bad configuration options", 14817c478bd9Sstevel@tonic-gate filename, bad_options); 14827c478bd9Sstevel@tonic-gate } 14836f8d59d8SJan Pechanec 1484b07b2f5cSHuie-Ying Lee 14856f8d59d8SJan Pechanec /* 14866f8d59d8SJan Pechanec * Note that "none" is a special path having the same affect on sshd 14876f8d59d8SJan Pechanec * configuration as not specifying ChrootDirectory at all. 14886f8d59d8SJan Pechanec */ 14896f8d59d8SJan Pechanec int 14906f8d59d8SJan Pechanec chroot_requested(char *chroot_directory) 14916f8d59d8SJan Pechanec { 14926f8d59d8SJan Pechanec return (chroot_directory != NULL && 14936f8d59d8SJan Pechanec strcasecmp(chroot_directory, "none") != 0); 14946f8d59d8SJan Pechanec } 1495