10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 30Sstevel@tonic-gate * All rights reserved 40Sstevel@tonic-gate * 50Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 60Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 70Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 80Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 90Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 100Sstevel@tonic-gate */ 110Sstevel@tonic-gate /* 129139SJan.Pechanec@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 130Sstevel@tonic-gate * Use is subject to license terms. 140Sstevel@tonic-gate */ 150Sstevel@tonic-gate 160Sstevel@tonic-gate #include "includes.h" 170Sstevel@tonic-gate RCSID("$OpenBSD: servconf.c,v 1.115 2002/09/04 18:52:42 stevesk Exp $"); 180Sstevel@tonic-gate 190Sstevel@tonic-gate #ifdef HAVE_DEFOPEN 200Sstevel@tonic-gate #include <deflt.h> 210Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */ 220Sstevel@tonic-gate 230Sstevel@tonic-gate #if defined(KRB4) 240Sstevel@tonic-gate #include <krb.h> 250Sstevel@tonic-gate #endif 260Sstevel@tonic-gate #if defined(KRB5) 270Sstevel@tonic-gate #ifdef HEIMDAL 280Sstevel@tonic-gate #include <krb.h> 290Sstevel@tonic-gate #else 300Sstevel@tonic-gate /* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V 310Sstevel@tonic-gate * keytab */ 320Sstevel@tonic-gate #define KEYFILE "/etc/krb5.keytab" 330Sstevel@tonic-gate #endif 340Sstevel@tonic-gate #endif 350Sstevel@tonic-gate #ifdef AFS 360Sstevel@tonic-gate #include <kafs.h> 370Sstevel@tonic-gate #endif 380Sstevel@tonic-gate 390Sstevel@tonic-gate #include "ssh.h" 400Sstevel@tonic-gate #include "log.h" 4111044SHuie-Ying.Lee@Sun.COM #include "buffer.h" 420Sstevel@tonic-gate #include "servconf.h" 430Sstevel@tonic-gate #include "xmalloc.h" 440Sstevel@tonic-gate #include "compat.h" 450Sstevel@tonic-gate #include "pathnames.h" 460Sstevel@tonic-gate #include "tildexpand.h" 470Sstevel@tonic-gate #include "misc.h" 480Sstevel@tonic-gate #include "cipher.h" 490Sstevel@tonic-gate #include "kex.h" 500Sstevel@tonic-gate #include "mac.h" 510Sstevel@tonic-gate #include "auth.h" 5211044SHuie-Ying.Lee@Sun.COM #include "match.h" 5311044SHuie-Ying.Lee@Sun.COM #include "groupaccess.h" 540Sstevel@tonic-gate 550Sstevel@tonic-gate static void add_listen_addr(ServerOptions *, char *, u_short); 560Sstevel@tonic-gate static void add_one_listen_addr(ServerOptions *, char *, u_short); 570Sstevel@tonic-gate 5811044SHuie-Ying.Lee@Sun.COM extern Buffer cfg; 5911044SHuie-Ying.Lee@Sun.COM 600Sstevel@tonic-gate /* AF_UNSPEC or AF_INET or AF_INET6 */ 610Sstevel@tonic-gate extern int IPv4or6; 620Sstevel@tonic-gate 639139SJan.Pechanec@Sun.COM /* 649139SJan.Pechanec@Sun.COM * Initializes the server options to their initial (unset) values. Some of those 659139SJan.Pechanec@Sun.COM * that stay unset after the command line options and configuration files are 669139SJan.Pechanec@Sun.COM * read are set to their default values in fill_default_server_options(). 679139SJan.Pechanec@Sun.COM */ 680Sstevel@tonic-gate void 690Sstevel@tonic-gate initialize_server_options(ServerOptions *options) 700Sstevel@tonic-gate { 710Sstevel@tonic-gate (void) memset(options, 0, sizeof(*options)); 720Sstevel@tonic-gate 730Sstevel@tonic-gate /* Portable-specific options */ 740Sstevel@tonic-gate options->pam_authentication_via_kbd_int = -1; 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* Standard Options */ 770Sstevel@tonic-gate options->num_ports = 0; 780Sstevel@tonic-gate options->ports_from_cmdline = 0; 790Sstevel@tonic-gate options->listen_addrs = NULL; 800Sstevel@tonic-gate options->num_host_key_files = 0; 810Sstevel@tonic-gate options->pid_file = NULL; 820Sstevel@tonic-gate options->server_key_bits = -1; 830Sstevel@tonic-gate options->login_grace_time = -1; 840Sstevel@tonic-gate options->key_regeneration_time = -1; 850Sstevel@tonic-gate options->permit_root_login = PERMIT_NOT_SET; 860Sstevel@tonic-gate options->ignore_rhosts = -1; 870Sstevel@tonic-gate options->ignore_user_known_hosts = -1; 880Sstevel@tonic-gate options->print_motd = -1; 890Sstevel@tonic-gate options->print_lastlog = -1; 900Sstevel@tonic-gate options->x11_forwarding = -1; 910Sstevel@tonic-gate options->x11_display_offset = -1; 920Sstevel@tonic-gate options->x11_use_localhost = -1; 930Sstevel@tonic-gate options->xauth_location = NULL; 940Sstevel@tonic-gate options->strict_modes = -1; 950Sstevel@tonic-gate options->keepalives = -1; 960Sstevel@tonic-gate options->log_facility = SYSLOG_FACILITY_NOT_SET; 970Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_NOT_SET; 980Sstevel@tonic-gate options->rhosts_authentication = -1; 990Sstevel@tonic-gate options->rhosts_rsa_authentication = -1; 1000Sstevel@tonic-gate options->hostbased_authentication = -1; 1010Sstevel@tonic-gate options->hostbased_uses_name_from_packet_only = -1; 1020Sstevel@tonic-gate options->rsa_authentication = -1; 1030Sstevel@tonic-gate options->pubkey_authentication = -1; 1040Sstevel@tonic-gate #ifdef GSSAPI 1050Sstevel@tonic-gate options->gss_authentication = -1; 1060Sstevel@tonic-gate options->gss_keyex = -1; 1070Sstevel@tonic-gate options->gss_store_creds = -1; 1080Sstevel@tonic-gate options->gss_use_session_ccache = -1; 1090Sstevel@tonic-gate options->gss_cleanup_creds = -1; 1100Sstevel@tonic-gate #endif 1110Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 1120Sstevel@tonic-gate options->kerberos_authentication = -1; 1130Sstevel@tonic-gate options->kerberos_or_local_passwd = -1; 1140Sstevel@tonic-gate options->kerberos_ticket_cleanup = -1; 1150Sstevel@tonic-gate #endif 1160Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 1170Sstevel@tonic-gate options->kerberos_tgt_passing = -1; 1180Sstevel@tonic-gate #endif 1190Sstevel@tonic-gate #ifdef AFS 1200Sstevel@tonic-gate options->afs_token_passing = -1; 1210Sstevel@tonic-gate #endif 1220Sstevel@tonic-gate options->password_authentication = -1; 1230Sstevel@tonic-gate options->kbd_interactive_authentication = -1; 1240Sstevel@tonic-gate options->challenge_response_authentication = -1; 1250Sstevel@tonic-gate options->permit_empty_passwd = -1; 1260Sstevel@tonic-gate options->permit_user_env = -1; 1270Sstevel@tonic-gate options->compression = -1; 1280Sstevel@tonic-gate options->allow_tcp_forwarding = -1; 1290Sstevel@tonic-gate options->num_allow_users = 0; 1300Sstevel@tonic-gate options->num_deny_users = 0; 1310Sstevel@tonic-gate options->num_allow_groups = 0; 1320Sstevel@tonic-gate options->num_deny_groups = 0; 1330Sstevel@tonic-gate options->ciphers = NULL; 1340Sstevel@tonic-gate options->macs = NULL; 1350Sstevel@tonic-gate options->protocol = SSH_PROTO_UNKNOWN; 1360Sstevel@tonic-gate options->gateway_ports = -1; 1370Sstevel@tonic-gate options->num_subsystems = 0; 1380Sstevel@tonic-gate options->max_startups_begin = -1; 1390Sstevel@tonic-gate options->max_startups_rate = -1; 1400Sstevel@tonic-gate options->max_startups = -1; 1410Sstevel@tonic-gate options->banner = NULL; 1420Sstevel@tonic-gate options->verify_reverse_mapping = -1; 1430Sstevel@tonic-gate options->client_alive_interval = -1; 1440Sstevel@tonic-gate options->client_alive_count_max = -1; 1450Sstevel@tonic-gate options->authorized_keys_file = NULL; 1460Sstevel@tonic-gate options->authorized_keys_file2 = NULL; 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate options->max_auth_tries = -1; 1490Sstevel@tonic-gate options->max_auth_tries_log = -1; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate options->max_init_auth_tries = -1; 1520Sstevel@tonic-gate options->max_init_auth_tries_log = -1; 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate options->lookup_client_hostnames = -1; 1557574SJan.Pechanec@Sun.COM options->use_openssl_engine = -1; 1569139SJan.Pechanec@Sun.COM options->chroot_directory = NULL; 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate #ifdef HAVE_DEFOPEN 1600Sstevel@tonic-gate /* 1610Sstevel@tonic-gate * Reads /etc/default/login and defaults several ServerOptions: 1620Sstevel@tonic-gate * 1630Sstevel@tonic-gate * PermitRootLogin 1640Sstevel@tonic-gate * PermitEmptyPasswords 1650Sstevel@tonic-gate * LoginGraceTime 1660Sstevel@tonic-gate * 1670Sstevel@tonic-gate * CONSOLE=* -> PermitRootLogin=without-password 1680Sstevel@tonic-gate * #CONSOLE=* -> PermitRootLogin=yes 1690Sstevel@tonic-gate * 1700Sstevel@tonic-gate * PASSREQ=YES -> PermitEmptyPasswords=no 1710Sstevel@tonic-gate * PASSREQ=NO -> PermitEmptyPasswords=yes 1720Sstevel@tonic-gate * #PASSREQ=* -> PermitEmptyPasswords=no 1730Sstevel@tonic-gate * 1740Sstevel@tonic-gate * TIMEOUT=<secs> -> LoginGraceTime=<secs> 1750Sstevel@tonic-gate * #TIMEOUT=<secs> -> LoginGraceTime=300 1760Sstevel@tonic-gate */ 1770Sstevel@tonic-gate static 1780Sstevel@tonic-gate void 1790Sstevel@tonic-gate deflt_fill_default_server_options(ServerOptions *options) 1800Sstevel@tonic-gate { 1810Sstevel@tonic-gate int flags; 1820Sstevel@tonic-gate char *ptr; 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate if (defopen(_PATH_DEFAULT_LOGIN)) 1850Sstevel@tonic-gate return; 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* Ignore case */ 1880Sstevel@tonic-gate flags = defcntl(DC_GETFLAGS, 0); 1890Sstevel@tonic-gate TURNOFF(flags, DC_CASE); 1900Sstevel@tonic-gate (void) defcntl(DC_SETFLAGS, flags); 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate if (options->permit_root_login == PERMIT_NOT_SET && 1930Sstevel@tonic-gate (ptr = defread("CONSOLE=")) != NULL) 1940Sstevel@tonic-gate options->permit_root_login = PERMIT_NO_PASSWD; 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate if (options->permit_empty_passwd == -1 && 1970Sstevel@tonic-gate (ptr = defread("PASSREQ=")) != NULL) { 1980Sstevel@tonic-gate if (strcasecmp("YES", ptr) == 0) 1990Sstevel@tonic-gate options->permit_empty_passwd = 0; 2000Sstevel@tonic-gate else if (strcasecmp("NO", ptr) == 0) 2010Sstevel@tonic-gate options->permit_empty_passwd = 1; 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate if (options->max_init_auth_tries == -1 && 2050Sstevel@tonic-gate (ptr = defread("RETRIES=")) != NULL) { 2060Sstevel@tonic-gate options->max_init_auth_tries = atoi(ptr); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate if (options->max_init_auth_tries_log == -1 && 2100Sstevel@tonic-gate (ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) { 2110Sstevel@tonic-gate options->max_init_auth_tries_log = atoi(ptr); 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate if (options->login_grace_time == -1) { 2150Sstevel@tonic-gate if ((ptr = defread("TIMEOUT=")) != NULL) 2160Sstevel@tonic-gate options->login_grace_time = (unsigned)atoi(ptr); 2170Sstevel@tonic-gate else 2180Sstevel@tonic-gate options->login_grace_time = 300; 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate (void) defopen((char *)NULL); 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */ 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate void 2260Sstevel@tonic-gate fill_default_server_options(ServerOptions *options) 2270Sstevel@tonic-gate { 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate #ifdef HAVE_DEFOPEN 2300Sstevel@tonic-gate deflt_fill_default_server_options(options); 2310Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */ 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* Portable-specific options */ 2340Sstevel@tonic-gate if (options->pam_authentication_via_kbd_int == -1) 2350Sstevel@tonic-gate options->pam_authentication_via_kbd_int = 0; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate /* Standard Options */ 2380Sstevel@tonic-gate if (options->protocol == SSH_PROTO_UNKNOWN) 2390Sstevel@tonic-gate options->protocol = SSH_PROTO_1|SSH_PROTO_2; 2400Sstevel@tonic-gate if (options->num_host_key_files == 0) { 2410Sstevel@tonic-gate /* fill default hostkeys for protocols */ 2420Sstevel@tonic-gate if (options->protocol & SSH_PROTO_1) 2430Sstevel@tonic-gate options->host_key_files[options->num_host_key_files++] = 2440Sstevel@tonic-gate _PATH_HOST_KEY_FILE; 2450Sstevel@tonic-gate #ifndef GSSAPI 2460Sstevel@tonic-gate /* With GSS keyex we can run v2 w/ no host keys */ 2470Sstevel@tonic-gate if (options->protocol & SSH_PROTO_2) { 2480Sstevel@tonic-gate options->host_key_files[options->num_host_key_files++] = 2490Sstevel@tonic-gate _PATH_HOST_RSA_KEY_FILE; 2500Sstevel@tonic-gate options->host_key_files[options->num_host_key_files++] = 2510Sstevel@tonic-gate _PATH_HOST_DSA_KEY_FILE; 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate #endif /* GSSAPI */ 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate if (options->num_ports == 0) 2560Sstevel@tonic-gate options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 2570Sstevel@tonic-gate if (options->listen_addrs == NULL) 2580Sstevel@tonic-gate add_listen_addr(options, NULL, 0); 2590Sstevel@tonic-gate if (options->pid_file == NULL) 2600Sstevel@tonic-gate options->pid_file = _PATH_SSH_DAEMON_PID_FILE; 2610Sstevel@tonic-gate if (options->server_key_bits == -1) 2620Sstevel@tonic-gate options->server_key_bits = 768; 2630Sstevel@tonic-gate if (options->login_grace_time == -1) 2640Sstevel@tonic-gate options->login_grace_time = 120; 2650Sstevel@tonic-gate if (options->key_regeneration_time == -1) 2660Sstevel@tonic-gate options->key_regeneration_time = 3600; 2670Sstevel@tonic-gate if (options->permit_root_login == PERMIT_NOT_SET) 2680Sstevel@tonic-gate options->permit_root_login = PERMIT_YES; 2690Sstevel@tonic-gate if (options->ignore_rhosts == -1) 2700Sstevel@tonic-gate options->ignore_rhosts = 1; 2710Sstevel@tonic-gate if (options->ignore_user_known_hosts == -1) 2720Sstevel@tonic-gate options->ignore_user_known_hosts = 0; 2730Sstevel@tonic-gate if (options->print_motd == -1) 2740Sstevel@tonic-gate options->print_motd = 1; 2750Sstevel@tonic-gate if (options->print_lastlog == -1) 2760Sstevel@tonic-gate options->print_lastlog = 1; 2770Sstevel@tonic-gate if (options->x11_forwarding == -1) 2780Sstevel@tonic-gate options->x11_forwarding = 1; 2790Sstevel@tonic-gate if (options->x11_display_offset == -1) 2800Sstevel@tonic-gate options->x11_display_offset = 10; 2810Sstevel@tonic-gate if (options->x11_use_localhost == -1) 2820Sstevel@tonic-gate options->x11_use_localhost = 1; 2830Sstevel@tonic-gate if (options->xauth_location == NULL) 2840Sstevel@tonic-gate options->xauth_location = _PATH_XAUTH; 2850Sstevel@tonic-gate if (options->strict_modes == -1) 2860Sstevel@tonic-gate options->strict_modes = 1; 2870Sstevel@tonic-gate if (options->keepalives == -1) 2880Sstevel@tonic-gate options->keepalives = 1; 2890Sstevel@tonic-gate if (options->log_facility == SYSLOG_FACILITY_NOT_SET) 2900Sstevel@tonic-gate options->log_facility = SYSLOG_FACILITY_AUTH; 2910Sstevel@tonic-gate if (options->log_level == SYSLOG_LEVEL_NOT_SET) 2920Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_INFO; 2930Sstevel@tonic-gate if (options->rhosts_authentication == -1) 2940Sstevel@tonic-gate options->rhosts_authentication = 0; 2950Sstevel@tonic-gate if (options->rhosts_rsa_authentication == -1) 2960Sstevel@tonic-gate options->rhosts_rsa_authentication = 0; 2970Sstevel@tonic-gate if (options->hostbased_authentication == -1) 2980Sstevel@tonic-gate options->hostbased_authentication = 0; 2990Sstevel@tonic-gate if (options->hostbased_uses_name_from_packet_only == -1) 3000Sstevel@tonic-gate options->hostbased_uses_name_from_packet_only = 0; 3010Sstevel@tonic-gate if (options->rsa_authentication == -1) 3020Sstevel@tonic-gate options->rsa_authentication = 1; 3030Sstevel@tonic-gate if (options->pubkey_authentication == -1) 3040Sstevel@tonic-gate options->pubkey_authentication = 1; 3050Sstevel@tonic-gate #ifdef GSSAPI 3060Sstevel@tonic-gate if (options->gss_authentication == -1) 3070Sstevel@tonic-gate options->gss_authentication = 1; 3080Sstevel@tonic-gate if (options->gss_keyex == -1) 3090Sstevel@tonic-gate options->gss_keyex = 1; 3100Sstevel@tonic-gate if (options->gss_store_creds == -1) 3110Sstevel@tonic-gate options->gss_store_creds = 1; 3120Sstevel@tonic-gate if (options->gss_use_session_ccache == -1) 3130Sstevel@tonic-gate options->gss_use_session_ccache = 1; 3140Sstevel@tonic-gate if (options->gss_cleanup_creds == -1) 3150Sstevel@tonic-gate options->gss_cleanup_creds = 1; 3160Sstevel@tonic-gate #endif 3170Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 3180Sstevel@tonic-gate if (options->kerberos_authentication == -1) 3190Sstevel@tonic-gate options->kerberos_authentication = 0; 3200Sstevel@tonic-gate if (options->kerberos_or_local_passwd == -1) 3210Sstevel@tonic-gate options->kerberos_or_local_passwd = 1; 3220Sstevel@tonic-gate if (options->kerberos_ticket_cleanup == -1) 3230Sstevel@tonic-gate options->kerberos_ticket_cleanup = 1; 3240Sstevel@tonic-gate #endif 3250Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 3260Sstevel@tonic-gate if (options->kerberos_tgt_passing == -1) 3270Sstevel@tonic-gate options->kerberos_tgt_passing = 0; 3280Sstevel@tonic-gate #endif 3290Sstevel@tonic-gate #ifdef AFS 3300Sstevel@tonic-gate if (options->afs_token_passing == -1) 3310Sstevel@tonic-gate options->afs_token_passing = 0; 3320Sstevel@tonic-gate #endif 3330Sstevel@tonic-gate if (options->password_authentication == -1) 3340Sstevel@tonic-gate options->password_authentication = 1; 3350Sstevel@tonic-gate if (options->kbd_interactive_authentication == -1) 3360Sstevel@tonic-gate options->kbd_interactive_authentication = 0; 3370Sstevel@tonic-gate if (options->challenge_response_authentication == -1) 3380Sstevel@tonic-gate options->challenge_response_authentication = 1; 3390Sstevel@tonic-gate if (options->permit_empty_passwd == -1) 3400Sstevel@tonic-gate options->permit_empty_passwd = 0; 3410Sstevel@tonic-gate if (options->permit_user_env == -1) 3420Sstevel@tonic-gate options->permit_user_env = 0; 3430Sstevel@tonic-gate if (options->compression == -1) 3440Sstevel@tonic-gate options->compression = 1; 3450Sstevel@tonic-gate if (options->allow_tcp_forwarding == -1) 3460Sstevel@tonic-gate options->allow_tcp_forwarding = 1; 3470Sstevel@tonic-gate if (options->gateway_ports == -1) 3480Sstevel@tonic-gate options->gateway_ports = 0; 3490Sstevel@tonic-gate if (options->max_startups == -1) 3500Sstevel@tonic-gate options->max_startups = 10; 3510Sstevel@tonic-gate if (options->max_startups_rate == -1) 3520Sstevel@tonic-gate options->max_startups_rate = 100; /* 100% */ 3530Sstevel@tonic-gate if (options->max_startups_begin == -1) 3540Sstevel@tonic-gate options->max_startups_begin = options->max_startups; 3550Sstevel@tonic-gate if (options->verify_reverse_mapping == -1) 3560Sstevel@tonic-gate options->verify_reverse_mapping = 0; 3570Sstevel@tonic-gate if (options->client_alive_interval == -1) 3580Sstevel@tonic-gate options->client_alive_interval = 0; 3590Sstevel@tonic-gate if (options->client_alive_count_max == -1) 3600Sstevel@tonic-gate options->client_alive_count_max = 3; 3610Sstevel@tonic-gate if (options->authorized_keys_file2 == NULL) { 3620Sstevel@tonic-gate /* authorized_keys_file2 falls back to authorized_keys_file */ 3630Sstevel@tonic-gate if (options->authorized_keys_file != NULL) 3640Sstevel@tonic-gate options->authorized_keys_file2 = options->authorized_keys_file; 3650Sstevel@tonic-gate else 3660Sstevel@tonic-gate options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate if (options->authorized_keys_file == NULL) 3690Sstevel@tonic-gate options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate if (options->max_auth_tries == -1) 3720Sstevel@tonic-gate options->max_auth_tries = AUTH_FAIL_MAX; 3730Sstevel@tonic-gate if (options->max_auth_tries_log == -1) 3740Sstevel@tonic-gate options->max_auth_tries_log = options->max_auth_tries / 2; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate if (options->max_init_auth_tries == -1) 3770Sstevel@tonic-gate options->max_init_auth_tries = AUTH_FAIL_MAX; 3780Sstevel@tonic-gate if (options->max_init_auth_tries_log == -1) 3790Sstevel@tonic-gate options->max_init_auth_tries_log = options->max_init_auth_tries / 2; 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate if (options->lookup_client_hostnames == -1) 3820Sstevel@tonic-gate options->lookup_client_hostnames = 1; 3837574SJan.Pechanec@Sun.COM if (options->use_openssl_engine == -1) 3847574SJan.Pechanec@Sun.COM options->use_openssl_engine = 1; 3850Sstevel@tonic-gate } 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* Keyword tokens. */ 3880Sstevel@tonic-gate typedef enum { 3890Sstevel@tonic-gate sBadOption, /* == unknown option */ 3900Sstevel@tonic-gate /* Portable-specific options */ 3910Sstevel@tonic-gate sPAMAuthenticationViaKbdInt, 3920Sstevel@tonic-gate /* Standard Options */ 3930Sstevel@tonic-gate sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, 3940Sstevel@tonic-gate sPermitRootLogin, sLogFacility, sLogLevel, 3950Sstevel@tonic-gate sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication, 3960Sstevel@tonic-gate #ifdef GSSAPI 3970Sstevel@tonic-gate sGssAuthentication, sGssKeyEx, sGssStoreDelegCreds, 3980Sstevel@tonic-gate sGssUseSessionCredCache, sGssCleanupCreds, 3990Sstevel@tonic-gate #endif /* GSSAPI */ 4000Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 4010Sstevel@tonic-gate sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, 4020Sstevel@tonic-gate #endif 4030Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 4040Sstevel@tonic-gate sKerberosTgtPassing, 4050Sstevel@tonic-gate #endif 4060Sstevel@tonic-gate #ifdef AFS 4070Sstevel@tonic-gate sAFSTokenPassing, 4080Sstevel@tonic-gate #endif 4090Sstevel@tonic-gate sChallengeResponseAuthentication, 4100Sstevel@tonic-gate sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, 4110Sstevel@tonic-gate sPrintMotd, sPrintLastLog, sIgnoreRhosts, 4120Sstevel@tonic-gate sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 4130Sstevel@tonic-gate sStrictModes, sEmptyPasswd, sKeepAlives, 4140Sstevel@tonic-gate sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, 4150Sstevel@tonic-gate sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 4160Sstevel@tonic-gate sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 4170Sstevel@tonic-gate sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, 4180Sstevel@tonic-gate sBanner, sVerifyReverseMapping, sHostbasedAuthentication, 4190Sstevel@tonic-gate sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 4200Sstevel@tonic-gate sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 4210Sstevel@tonic-gate sMaxAuthTries, sMaxAuthTriesLog, sUsePrivilegeSeparation, 4229139SJan.Pechanec@Sun.COM sLookupClientHostnames, sUseOpenSSLEngine, sChrootDirectory, 42311044SHuie-Ying.Lee@Sun.COM sMatch, 4240Sstevel@tonic-gate sDeprecated 4250Sstevel@tonic-gate } ServerOpCodes; 4260Sstevel@tonic-gate 42711044SHuie-Ying.Lee@Sun.COM #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ 42811044SHuie-Ying.Lee@Sun.COM #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 42911044SHuie-Ying.Lee@Sun.COM #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 43011044SHuie-Ying.Lee@Sun.COM 4310Sstevel@tonic-gate /* Textual representation of the tokens. */ 4320Sstevel@tonic-gate static struct { 4330Sstevel@tonic-gate const char *name; 4340Sstevel@tonic-gate ServerOpCodes opcode; 43511044SHuie-Ying.Lee@Sun.COM u_int flags; 4360Sstevel@tonic-gate } keywords[] = { 4370Sstevel@tonic-gate /* Portable-specific options */ 43811044SHuie-Ying.Lee@Sun.COM { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt, SSHCFG_GLOBAL }, 4390Sstevel@tonic-gate /* Standard Options */ 44011044SHuie-Ying.Lee@Sun.COM { "port", sPort, SSHCFG_GLOBAL }, 44111044SHuie-Ying.Lee@Sun.COM { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, 44211044SHuie-Ying.Lee@Sun.COM { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ 44311044SHuie-Ying.Lee@Sun.COM { "pidfile", sPidFile, SSHCFG_GLOBAL }, 44411044SHuie-Ying.Lee@Sun.COM { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, 44511044SHuie-Ying.Lee@Sun.COM { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 44611044SHuie-Ying.Lee@Sun.COM { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, 44711044SHuie-Ying.Lee@Sun.COM { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, 44811044SHuie-Ying.Lee@Sun.COM { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 44911044SHuie-Ying.Lee@Sun.COM { "loglevel", sLogLevel, SSHCFG_GLOBAL }, 45011044SHuie-Ying.Lee@Sun.COM { "rhostsauthentication", sRhostsAuthentication, SSHCFG_GLOBAL }, 45111044SHuie-Ying.Lee@Sun.COM { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, 45211044SHuie-Ying.Lee@Sun.COM { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, 4530Sstevel@tonic-gate { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, 45411044SHuie-Ying.Lee@Sun.COM { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, 45511044SHuie-Ying.Lee@Sun.COM { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 45611044SHuie-Ying.Lee@Sun.COM { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 4570Sstevel@tonic-gate #ifdef GSSAPI 45811044SHuie-Ying.Lee@Sun.COM { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 45911044SHuie-Ying.Lee@Sun.COM { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, 46011044SHuie-Ying.Lee@Sun.COM { "gssapistoredelegatedcredentials", sGssStoreDelegCreds, SSHCFG_GLOBAL }, 46111044SHuie-Ying.Lee@Sun.COM { "gssauthentication", sGssAuthentication, SSHCFG_GLOBAL }, /* alias */ 46211044SHuie-Ying.Lee@Sun.COM { "gsskeyex", sGssKeyEx, SSHCFG_GLOBAL }, /* alias */ 46311044SHuie-Ying.Lee@Sun.COM { "gssstoredelegcreds", sGssStoreDelegCreds, SSHCFG_GLOBAL }, /* alias */ 4640Sstevel@tonic-gate #ifndef SUNW_GSSAPI 46511044SHuie-Ying.Lee@Sun.COM { "gssusesessionccache", sGssUseSessionCredCache, SSHCFG_GLOBAL }, 46611044SHuie-Ying.Lee@Sun.COM { "gssusesessioncredcache", sGssUseSessionCredCache, SSHCFG_GLOBAL }, 46711044SHuie-Ying.Lee@Sun.COM { "gsscleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, 4680Sstevel@tonic-gate #endif /* SUNW_GSSAPI */ 4690Sstevel@tonic-gate #endif 4700Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 47111044SHuie-Ying.Lee@Sun.COM { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 47211044SHuie-Ying.Lee@Sun.COM { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, 47311044SHuie-Ying.Lee@Sun.COM { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, 4740Sstevel@tonic-gate #endif 4750Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 47611044SHuie-Ying.Lee@Sun.COM { "kerberostgtpassing", sKerberosTgtPassing, SSHCFG_GLOBAL }, 4770Sstevel@tonic-gate #endif 4780Sstevel@tonic-gate #ifdef AFS 47911044SHuie-Ying.Lee@Sun.COM { "afstokenpassing", sAFSTokenPassing, SSHCFG_GLOBAL }, 4800Sstevel@tonic-gate #endif 48111044SHuie-Ying.Lee@Sun.COM { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 48211044SHuie-Ying.Lee@Sun.COM { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 48311044SHuie-Ying.Lee@Sun.COM { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 48411044SHuie-Ying.Lee@Sun.COM { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ 48511044SHuie-Ying.Lee@Sun.COM { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 48611044SHuie-Ying.Lee@Sun.COM { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 48711044SHuie-Ying.Lee@Sun.COM { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, 48811044SHuie-Ying.Lee@Sun.COM { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, 48911044SHuie-Ying.Lee@Sun.COM { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, 49011044SHuie-Ying.Lee@Sun.COM { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, 49111044SHuie-Ying.Lee@Sun.COM { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, 49211044SHuie-Ying.Lee@Sun.COM { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, 49311044SHuie-Ying.Lee@Sun.COM { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 49411044SHuie-Ying.Lee@Sun.COM { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 49511044SHuie-Ying.Lee@Sun.COM { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 49611044SHuie-Ying.Lee@Sun.COM { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, 49711044SHuie-Ying.Lee@Sun.COM { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 49811044SHuie-Ying.Lee@Sun.COM { "uselogin", sUseLogin, SSHCFG_GLOBAL }, 49911044SHuie-Ying.Lee@Sun.COM { "compression", sCompression, SSHCFG_GLOBAL }, 50011044SHuie-Ying.Lee@Sun.COM { "keepalive", sKeepAlives, SSHCFG_GLOBAL }, 50111044SHuie-Ying.Lee@Sun.COM { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 50211044SHuie-Ying.Lee@Sun.COM { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, 50311044SHuie-Ying.Lee@Sun.COM { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, 50411044SHuie-Ying.Lee@Sun.COM { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, 50511044SHuie-Ying.Lee@Sun.COM { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, 50611044SHuie-Ying.Lee@Sun.COM { "ciphers", sCiphers, SSHCFG_GLOBAL }, 50711044SHuie-Ying.Lee@Sun.COM { "macs", sMacs, SSHCFG_GLOBAL}, 50811044SHuie-Ying.Lee@Sun.COM { "protocol", sProtocol,SSHCFG_GLOBAL }, 50911044SHuie-Ying.Lee@Sun.COM { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 51011044SHuie-Ying.Lee@Sun.COM { "subsystem", sSubsystem, SSHCFG_GLOBAL}, 51111044SHuie-Ying.Lee@Sun.COM { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 51211044SHuie-Ying.Lee@Sun.COM { "banner", sBanner, SSHCFG_ALL }, 51311044SHuie-Ying.Lee@Sun.COM { "verifyreversemapping", sVerifyReverseMapping, SSHCFG_GLOBAL }, 51411044SHuie-Ying.Lee@Sun.COM { "reversemappingcheck", sVerifyReverseMapping,SSHCFG_GLOBAL }, 51511044SHuie-Ying.Lee@Sun.COM { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 51611044SHuie-Ying.Lee@Sun.COM { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 51711044SHuie-Ying.Lee@Sun.COM { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, 51811044SHuie-Ying.Lee@Sun.COM { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, 51911044SHuie-Ying.Lee@Sun.COM { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, 52011044SHuie-Ying.Lee@Sun.COM { "maxauthtrieslog", sMaxAuthTriesLog, SSHCFG_GLOBAL }, 52111044SHuie-Ying.Lee@Sun.COM { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, 52211044SHuie-Ying.Lee@Sun.COM { "lookupclienthostnames", sLookupClientHostnames, SSHCFG_GLOBAL }, 52311044SHuie-Ying.Lee@Sun.COM { "useopensslengine", sUseOpenSSLEngine, SSHCFG_GLOBAL }, 52411044SHuie-Ying.Lee@Sun.COM { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 52511044SHuie-Ying.Lee@Sun.COM { "match", sMatch, SSHCFG_ALL }, 52611044SHuie-Ying.Lee@Sun.COM 52711044SHuie-Ying.Lee@Sun.COM { NULL, sBadOption, 0 } 5280Sstevel@tonic-gate }; 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate /* 5310Sstevel@tonic-gate * Returns the number of the token pointed to by cp or sBadOption. 5320Sstevel@tonic-gate */ 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate static ServerOpCodes 5350Sstevel@tonic-gate parse_token(const char *cp, const char *filename, 53611044SHuie-Ying.Lee@Sun.COM int linenum, u_int *flags) 5370Sstevel@tonic-gate { 5380Sstevel@tonic-gate u_int i; 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate for (i = 0; keywords[i].name; i++) 54111044SHuie-Ying.Lee@Sun.COM if (strcasecmp(cp, keywords[i].name) == 0) { 54211044SHuie-Ying.Lee@Sun.COM *flags = keywords[i].flags; 5430Sstevel@tonic-gate return keywords[i].opcode; 54411044SHuie-Ying.Lee@Sun.COM } 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate error("%s: line %d: Bad configuration option: %s", 5470Sstevel@tonic-gate filename, linenum, cp); 5480Sstevel@tonic-gate return sBadOption; 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate static void 5520Sstevel@tonic-gate add_listen_addr(ServerOptions *options, char *addr, u_short port) 5530Sstevel@tonic-gate { 5540Sstevel@tonic-gate int i; 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate if (options->num_ports == 0) 5570Sstevel@tonic-gate options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 5580Sstevel@tonic-gate if (port == 0) 5590Sstevel@tonic-gate for (i = 0; i < options->num_ports; i++) 5600Sstevel@tonic-gate add_one_listen_addr(options, addr, options->ports[i]); 5610Sstevel@tonic-gate else 5620Sstevel@tonic-gate add_one_listen_addr(options, addr, port); 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate static void 5660Sstevel@tonic-gate add_one_listen_addr(ServerOptions *options, char *addr, u_short port) 5670Sstevel@tonic-gate { 5680Sstevel@tonic-gate struct addrinfo hints, *ai, *aitop; 5690Sstevel@tonic-gate char strport[NI_MAXSERV]; 5700Sstevel@tonic-gate int gaierr; 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate (void) memset(&hints, 0, sizeof(hints)); 5730Sstevel@tonic-gate hints.ai_family = IPv4or6; 5740Sstevel@tonic-gate hints.ai_socktype = SOCK_STREAM; 5750Sstevel@tonic-gate hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 5760Sstevel@tonic-gate (void) snprintf(strport, sizeof strport, "%u", port); 5770Sstevel@tonic-gate if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 5780Sstevel@tonic-gate fatal("bad addr or host: %s (%s)", 5790Sstevel@tonic-gate addr ? addr : "<NULL>", 5800Sstevel@tonic-gate gai_strerror(gaierr)); 5810Sstevel@tonic-gate for (ai = aitop; ai->ai_next; ai = ai->ai_next) 5820Sstevel@tonic-gate ; 5830Sstevel@tonic-gate ai->ai_next = options->listen_addrs; 5840Sstevel@tonic-gate options->listen_addrs = aitop; 5850Sstevel@tonic-gate } 5860Sstevel@tonic-gate 58711044SHuie-Ying.Lee@Sun.COM /* 58811044SHuie-Ying.Lee@Sun.COM * The strategy for the Match blocks is that the config file is parsed twice. 58911044SHuie-Ying.Lee@Sun.COM * 59011044SHuie-Ying.Lee@Sun.COM * The first time is at startup. activep is initialized to 1 and the 59111044SHuie-Ying.Lee@Sun.COM * directives in the global context are processed and acted on. Hitting a 59211044SHuie-Ying.Lee@Sun.COM * Match directive unsets activep and the directives inside the block are 59311044SHuie-Ying.Lee@Sun.COM * checked for syntax only. 59411044SHuie-Ying.Lee@Sun.COM * 59511044SHuie-Ying.Lee@Sun.COM * The second time is after a connection has been established but before 59611044SHuie-Ying.Lee@Sun.COM * authentication. activep is initialized to 2 and global config directives 59711044SHuie-Ying.Lee@Sun.COM * are ignored since they have already been processed. If the criteria in a 59811044SHuie-Ying.Lee@Sun.COM * Match block is met, activep is set and the subsequent directives 59911044SHuie-Ying.Lee@Sun.COM * processed and actioned until EOF or another Match block unsets it. Any 60011044SHuie-Ying.Lee@Sun.COM * options set are copied into the main server config. 60111044SHuie-Ying.Lee@Sun.COM * 60211044SHuie-Ying.Lee@Sun.COM * Potential additions/improvements: 60311044SHuie-Ying.Lee@Sun.COM * - Add Match support for pre-kex directives, eg Protocol, Ciphers. 60411044SHuie-Ying.Lee@Sun.COM * 60511044SHuie-Ying.Lee@Sun.COM * - Add a Tag directive (idea from David Leonard) ala pf, eg: 60611044SHuie-Ying.Lee@Sun.COM * Match Address 192.168.0.* 60711044SHuie-Ying.Lee@Sun.COM * Tag trusted 60811044SHuie-Ying.Lee@Sun.COM * Match Group wheel 60911044SHuie-Ying.Lee@Sun.COM * Tag trusted 61011044SHuie-Ying.Lee@Sun.COM * Match Tag trusted 61111044SHuie-Ying.Lee@Sun.COM * AllowTcpForwarding yes 61211044SHuie-Ying.Lee@Sun.COM * GatewayPorts clientspecified 61311044SHuie-Ying.Lee@Sun.COM * [...] 61411044SHuie-Ying.Lee@Sun.COM * 61511044SHuie-Ying.Lee@Sun.COM * - Add a PermittedChannelRequests directive 61611044SHuie-Ying.Lee@Sun.COM * Match Group shell 61711044SHuie-Ying.Lee@Sun.COM * PermittedChannelRequests session,forwarded-tcpip 61811044SHuie-Ying.Lee@Sun.COM */ 61911044SHuie-Ying.Lee@Sun.COM 62011044SHuie-Ying.Lee@Sun.COM static int 62111044SHuie-Ying.Lee@Sun.COM match_cfg_line_group(const char *grps, int line, const char *user) 62211044SHuie-Ying.Lee@Sun.COM { 62311044SHuie-Ying.Lee@Sun.COM int result = 0; 62411044SHuie-Ying.Lee@Sun.COM struct passwd *pw; 62511044SHuie-Ying.Lee@Sun.COM 62611044SHuie-Ying.Lee@Sun.COM if (user == NULL) 62711044SHuie-Ying.Lee@Sun.COM goto out; 62811044SHuie-Ying.Lee@Sun.COM 62911044SHuie-Ying.Lee@Sun.COM if ((pw = getpwnam(user)) == NULL) { 63011044SHuie-Ying.Lee@Sun.COM debug("Can't match group at line %d because user %.100s does " 63111044SHuie-Ying.Lee@Sun.COM "not exist", line, user); 63211044SHuie-Ying.Lee@Sun.COM } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 63311044SHuie-Ying.Lee@Sun.COM debug("Can't Match group because user %.100s not in any group " 63411044SHuie-Ying.Lee@Sun.COM "at line %d", user, line); 63511044SHuie-Ying.Lee@Sun.COM } else if (ga_match_pattern_list(grps) != 1) { 63611044SHuie-Ying.Lee@Sun.COM debug("user %.100s does not match group list %.100s at line %d", 63711044SHuie-Ying.Lee@Sun.COM user, grps, line); 63811044SHuie-Ying.Lee@Sun.COM } else { 63911044SHuie-Ying.Lee@Sun.COM debug("user %.100s matched group list %.100s at line %d", user, 64011044SHuie-Ying.Lee@Sun.COM grps, line); 64111044SHuie-Ying.Lee@Sun.COM result = 1; 64211044SHuie-Ying.Lee@Sun.COM } 64311044SHuie-Ying.Lee@Sun.COM out: 64411044SHuie-Ying.Lee@Sun.COM ga_free(); 64511044SHuie-Ying.Lee@Sun.COM return result; 64611044SHuie-Ying.Lee@Sun.COM } 64711044SHuie-Ying.Lee@Sun.COM 64811044SHuie-Ying.Lee@Sun.COM static int 64911044SHuie-Ying.Lee@Sun.COM match_cfg_line(char **condition, int line, const char *user, const char *host, 65011044SHuie-Ying.Lee@Sun.COM const char *address) 65111044SHuie-Ying.Lee@Sun.COM { 65211044SHuie-Ying.Lee@Sun.COM int result = 1; 65311044SHuie-Ying.Lee@Sun.COM char *arg, *attrib, *cp = *condition; 65411044SHuie-Ying.Lee@Sun.COM size_t len; 65511044SHuie-Ying.Lee@Sun.COM 65611044SHuie-Ying.Lee@Sun.COM if (user == NULL) 65711044SHuie-Ying.Lee@Sun.COM debug3("checking syntax for 'Match %s'", cp); 65811044SHuie-Ying.Lee@Sun.COM else 65911044SHuie-Ying.Lee@Sun.COM debug3("checking match for '%s' user %s host %s addr %s", cp, 66011044SHuie-Ying.Lee@Sun.COM user ? user : "(null)", host ? host : "(null)", 66111044SHuie-Ying.Lee@Sun.COM address ? address : "(null)"); 66211044SHuie-Ying.Lee@Sun.COM 663*11060SHuie-Ying.Lee@Sun.COM while ((attrib = strdelim(&cp)) != NULL && *attrib != '\0') { 66411044SHuie-Ying.Lee@Sun.COM if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 66511044SHuie-Ying.Lee@Sun.COM error("Missing Match criteria for %s", attrib); 66611044SHuie-Ying.Lee@Sun.COM return -1; 66711044SHuie-Ying.Lee@Sun.COM } 66811044SHuie-Ying.Lee@Sun.COM len = strlen(arg); 66911044SHuie-Ying.Lee@Sun.COM if (strcasecmp(attrib, "user") == 0) { 67011044SHuie-Ying.Lee@Sun.COM if (!user) { 67111044SHuie-Ying.Lee@Sun.COM result = 0; 67211044SHuie-Ying.Lee@Sun.COM continue; 67311044SHuie-Ying.Lee@Sun.COM } 67411044SHuie-Ying.Lee@Sun.COM if (match_pattern_list(user, arg, len, 0) != 1) 67511044SHuie-Ying.Lee@Sun.COM result = 0; 67611044SHuie-Ying.Lee@Sun.COM else 67711044SHuie-Ying.Lee@Sun.COM debug("user %.100s matched 'User %.100s' at " 67811044SHuie-Ying.Lee@Sun.COM "line %d", user, arg, line); 67911044SHuie-Ying.Lee@Sun.COM } else if (strcasecmp(attrib, "group") == 0) { 68011044SHuie-Ying.Lee@Sun.COM switch (match_cfg_line_group(arg, line, user)) { 68111044SHuie-Ying.Lee@Sun.COM case -1: 68211044SHuie-Ying.Lee@Sun.COM return -1; 68311044SHuie-Ying.Lee@Sun.COM case 0: 68411044SHuie-Ying.Lee@Sun.COM result = 0; 68511044SHuie-Ying.Lee@Sun.COM } 68611044SHuie-Ying.Lee@Sun.COM } else if (strcasecmp(attrib, "host") == 0) { 68711044SHuie-Ying.Lee@Sun.COM if (!host) { 68811044SHuie-Ying.Lee@Sun.COM result = 0; 68911044SHuie-Ying.Lee@Sun.COM continue; 69011044SHuie-Ying.Lee@Sun.COM } 69111044SHuie-Ying.Lee@Sun.COM if (match_hostname(host, arg, len) != 1) 69211044SHuie-Ying.Lee@Sun.COM result = 0; 69311044SHuie-Ying.Lee@Sun.COM else 69411044SHuie-Ying.Lee@Sun.COM debug("connection from %.100s matched 'Host " 69511044SHuie-Ying.Lee@Sun.COM "%.100s' at line %d", host, arg, line); 69611044SHuie-Ying.Lee@Sun.COM } else if (strcasecmp(attrib, "address") == 0) { 69711044SHuie-Ying.Lee@Sun.COM switch (addr_match_list(address, arg)) { 69811044SHuie-Ying.Lee@Sun.COM case 1: 69911044SHuie-Ying.Lee@Sun.COM debug("connection from %.100s matched 'Address " 70011044SHuie-Ying.Lee@Sun.COM "%.100s' at line %d", address, arg, line); 70111044SHuie-Ying.Lee@Sun.COM break; 70211044SHuie-Ying.Lee@Sun.COM case 0: 70311044SHuie-Ying.Lee@Sun.COM case -1: 70411044SHuie-Ying.Lee@Sun.COM result = 0; 70511044SHuie-Ying.Lee@Sun.COM break; 70611044SHuie-Ying.Lee@Sun.COM case -2: 70711044SHuie-Ying.Lee@Sun.COM return -1; 70811044SHuie-Ying.Lee@Sun.COM } 70911044SHuie-Ying.Lee@Sun.COM } else { 71011044SHuie-Ying.Lee@Sun.COM error("Unsupported Match attribute %s", attrib); 71111044SHuie-Ying.Lee@Sun.COM return -1; 71211044SHuie-Ying.Lee@Sun.COM } 71311044SHuie-Ying.Lee@Sun.COM } 71411044SHuie-Ying.Lee@Sun.COM if (user != NULL) 71511044SHuie-Ying.Lee@Sun.COM debug3("match %sfound", result ? "" : "not "); 71611044SHuie-Ying.Lee@Sun.COM *condition = cp; 71711044SHuie-Ying.Lee@Sun.COM return result; 71811044SHuie-Ying.Lee@Sun.COM } 71911044SHuie-Ying.Lee@Sun.COM 72011044SHuie-Ying.Lee@Sun.COM #define WHITESPACE " \t\r\n" 72111044SHuie-Ying.Lee@Sun.COM 7220Sstevel@tonic-gate int 7230Sstevel@tonic-gate process_server_config_line(ServerOptions *options, char *line, 72411044SHuie-Ying.Lee@Sun.COM const char *filename, int linenum, int *activep, const char *user, 72511044SHuie-Ying.Lee@Sun.COM const char *host, const char *address) 7260Sstevel@tonic-gate { 7270Sstevel@tonic-gate char *cp, **charptr, *arg, *p; 72811044SHuie-Ying.Lee@Sun.COM int cmdline = 0, *intptr, value, n; 7290Sstevel@tonic-gate ServerOpCodes opcode; 73011044SHuie-Ying.Lee@Sun.COM u_int i, flags = 0; 7319139SJan.Pechanec@Sun.COM size_t len; 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate cp = line; 7340Sstevel@tonic-gate arg = strdelim(&cp); 7350Sstevel@tonic-gate /* Ignore leading whitespace */ 7360Sstevel@tonic-gate if (*arg == '\0') 7370Sstevel@tonic-gate arg = strdelim(&cp); 7380Sstevel@tonic-gate if (!arg || !*arg || *arg == '#') 7390Sstevel@tonic-gate return 0; 7400Sstevel@tonic-gate intptr = NULL; 7410Sstevel@tonic-gate charptr = NULL; 74211044SHuie-Ying.Lee@Sun.COM opcode = parse_token(arg, filename, linenum, &flags); 74311044SHuie-Ying.Lee@Sun.COM 74411044SHuie-Ying.Lee@Sun.COM if (activep == NULL) { /* We are processing a command line directive */ 74511044SHuie-Ying.Lee@Sun.COM cmdline = 1; 74611044SHuie-Ying.Lee@Sun.COM activep = &cmdline; 74711044SHuie-Ying.Lee@Sun.COM } 74811044SHuie-Ying.Lee@Sun.COM if (*activep && opcode != sMatch) 74911044SHuie-Ying.Lee@Sun.COM debug3("%s:%d setting %s %s", filename, linenum, arg, cp); 75011044SHuie-Ying.Lee@Sun.COM if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 75111044SHuie-Ying.Lee@Sun.COM if (user == NULL) { 75211044SHuie-Ying.Lee@Sun.COM fatal("%s line %d: Directive '%s' is not allowed " 75311044SHuie-Ying.Lee@Sun.COM "within a Match block", filename, linenum, arg); 75411044SHuie-Ying.Lee@Sun.COM } else { /* this is a directive we have already processed */ 75511044SHuie-Ying.Lee@Sun.COM while (arg) 75611044SHuie-Ying.Lee@Sun.COM arg = strdelim(&cp); 75711044SHuie-Ying.Lee@Sun.COM return 0; 75811044SHuie-Ying.Lee@Sun.COM } 75911044SHuie-Ying.Lee@Sun.COM } 76011044SHuie-Ying.Lee@Sun.COM 7610Sstevel@tonic-gate switch (opcode) { 7620Sstevel@tonic-gate /* Portable-specific options */ 7630Sstevel@tonic-gate case sPAMAuthenticationViaKbdInt: 7640Sstevel@tonic-gate intptr = &options->pam_authentication_via_kbd_int; 7650Sstevel@tonic-gate goto parse_flag; 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate /* Standard Options */ 7680Sstevel@tonic-gate case sBadOption: 7690Sstevel@tonic-gate return -1; 7700Sstevel@tonic-gate case sPort: 7710Sstevel@tonic-gate /* ignore ports from configfile if cmdline specifies ports */ 7720Sstevel@tonic-gate if (options->ports_from_cmdline) 7730Sstevel@tonic-gate return 0; 7740Sstevel@tonic-gate if (options->listen_addrs != NULL) 7750Sstevel@tonic-gate fatal("%s line %d: ports must be specified before " 7760Sstevel@tonic-gate "ListenAddress.", filename, linenum); 7770Sstevel@tonic-gate if (options->num_ports >= MAX_PORTS) 7780Sstevel@tonic-gate fatal("%s line %d: too many ports.", 7790Sstevel@tonic-gate filename, linenum); 7800Sstevel@tonic-gate arg = strdelim(&cp); 7810Sstevel@tonic-gate if (!arg || *arg == '\0') 7820Sstevel@tonic-gate fatal("%s line %d: missing port number.", 7830Sstevel@tonic-gate filename, linenum); 7840Sstevel@tonic-gate options->ports[options->num_ports++] = a2port(arg); 7850Sstevel@tonic-gate if (options->ports[options->num_ports-1] == 0) 7860Sstevel@tonic-gate fatal("%s line %d: Badly formatted port number.", 7870Sstevel@tonic-gate filename, linenum); 7880Sstevel@tonic-gate break; 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate case sServerKeyBits: 7910Sstevel@tonic-gate intptr = &options->server_key_bits; 7920Sstevel@tonic-gate parse_int: 7930Sstevel@tonic-gate arg = strdelim(&cp); 7940Sstevel@tonic-gate if (!arg || *arg == '\0') 7950Sstevel@tonic-gate fatal("%s line %d: missing integer value.", 7960Sstevel@tonic-gate filename, linenum); 7970Sstevel@tonic-gate value = atoi(arg); 79811044SHuie-Ying.Lee@Sun.COM if (*activep && *intptr == -1) 7990Sstevel@tonic-gate *intptr = value; 8000Sstevel@tonic-gate break; 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate case sLoginGraceTime: 8030Sstevel@tonic-gate intptr = &options->login_grace_time; 8040Sstevel@tonic-gate parse_time: 8050Sstevel@tonic-gate arg = strdelim(&cp); 8060Sstevel@tonic-gate if (!arg || *arg == '\0') 8070Sstevel@tonic-gate fatal("%s line %d: missing time value.", 8080Sstevel@tonic-gate filename, linenum); 8090Sstevel@tonic-gate if ((value = convtime(arg)) == -1) 8100Sstevel@tonic-gate fatal("%s line %d: invalid time value.", 8110Sstevel@tonic-gate filename, linenum); 8120Sstevel@tonic-gate if (*intptr == -1) 8130Sstevel@tonic-gate *intptr = value; 8140Sstevel@tonic-gate break; 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate case sKeyRegenerationTime: 8170Sstevel@tonic-gate intptr = &options->key_regeneration_time; 8180Sstevel@tonic-gate goto parse_time; 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate case sListenAddress: 8210Sstevel@tonic-gate arg = strdelim(&cp); 8220Sstevel@tonic-gate if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) 8230Sstevel@tonic-gate fatal("%s line %d: missing inet addr.", 8240Sstevel@tonic-gate filename, linenum); 8250Sstevel@tonic-gate if (*arg == '[') { 8260Sstevel@tonic-gate if ((p = strchr(arg, ']')) == NULL) 8270Sstevel@tonic-gate fatal("%s line %d: bad ipv6 inet addr usage.", 8280Sstevel@tonic-gate filename, linenum); 8290Sstevel@tonic-gate arg++; 8300Sstevel@tonic-gate (void) memmove(p, p+1, strlen(p+1)+1); 8310Sstevel@tonic-gate } else if (((p = strchr(arg, ':')) == NULL) || 8320Sstevel@tonic-gate (strchr(p+1, ':') != NULL)) { 8330Sstevel@tonic-gate add_listen_addr(options, arg, 0); 8340Sstevel@tonic-gate break; 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate if (*p == ':') { 8370Sstevel@tonic-gate u_short port; 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate p++; 8400Sstevel@tonic-gate if (*p == '\0') 8410Sstevel@tonic-gate fatal("%s line %d: bad inet addr:port usage.", 8420Sstevel@tonic-gate filename, linenum); 8430Sstevel@tonic-gate else { 8440Sstevel@tonic-gate *(p-1) = '\0'; 8450Sstevel@tonic-gate if ((port = a2port(p)) == 0) 8460Sstevel@tonic-gate fatal("%s line %d: bad port number.", 8470Sstevel@tonic-gate filename, linenum); 8480Sstevel@tonic-gate add_listen_addr(options, arg, port); 8490Sstevel@tonic-gate } 8500Sstevel@tonic-gate } else if (*p == '\0') 8510Sstevel@tonic-gate add_listen_addr(options, arg, 0); 8520Sstevel@tonic-gate else 8530Sstevel@tonic-gate fatal("%s line %d: bad inet addr usage.", 8540Sstevel@tonic-gate filename, linenum); 8550Sstevel@tonic-gate break; 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate case sHostKeyFile: 8580Sstevel@tonic-gate intptr = &options->num_host_key_files; 8590Sstevel@tonic-gate if (*intptr >= MAX_HOSTKEYS) 8600Sstevel@tonic-gate fatal("%s line %d: too many host keys specified (max %d).", 8610Sstevel@tonic-gate filename, linenum, MAX_HOSTKEYS); 8620Sstevel@tonic-gate charptr = &options->host_key_files[*intptr]; 8630Sstevel@tonic-gate parse_filename: 8640Sstevel@tonic-gate arg = strdelim(&cp); 8650Sstevel@tonic-gate if (!arg || *arg == '\0') 8660Sstevel@tonic-gate fatal("%s line %d: missing file name.", 8670Sstevel@tonic-gate filename, linenum); 86811044SHuie-Ying.Lee@Sun.COM if (*activep && *charptr == NULL) { 8690Sstevel@tonic-gate *charptr = tilde_expand_filename(arg, getuid()); 8700Sstevel@tonic-gate /* increase optional counter */ 8710Sstevel@tonic-gate if (intptr != NULL) 8720Sstevel@tonic-gate *intptr = *intptr + 1; 8730Sstevel@tonic-gate } 8740Sstevel@tonic-gate break; 8750Sstevel@tonic-gate 8760Sstevel@tonic-gate case sPidFile: 8770Sstevel@tonic-gate charptr = &options->pid_file; 8780Sstevel@tonic-gate goto parse_filename; 8790Sstevel@tonic-gate 8800Sstevel@tonic-gate case sPermitRootLogin: 8810Sstevel@tonic-gate intptr = &options->permit_root_login; 8820Sstevel@tonic-gate arg = strdelim(&cp); 8830Sstevel@tonic-gate if (!arg || *arg == '\0') 8840Sstevel@tonic-gate fatal("%s line %d: missing yes/" 8850Sstevel@tonic-gate "without-password/forced-commands-only/no " 8860Sstevel@tonic-gate "argument.", filename, linenum); 8870Sstevel@tonic-gate value = 0; /* silence compiler */ 8880Sstevel@tonic-gate if (strcmp(arg, "without-password") == 0) 8890Sstevel@tonic-gate value = PERMIT_NO_PASSWD; 8900Sstevel@tonic-gate else if (strcmp(arg, "forced-commands-only") == 0) 8910Sstevel@tonic-gate value = PERMIT_FORCED_ONLY; 8920Sstevel@tonic-gate else if (strcmp(arg, "yes") == 0) 8930Sstevel@tonic-gate value = PERMIT_YES; 8940Sstevel@tonic-gate else if (strcmp(arg, "no") == 0) 8950Sstevel@tonic-gate value = PERMIT_NO; 8960Sstevel@tonic-gate else 8970Sstevel@tonic-gate fatal("%s line %d: Bad yes/" 8980Sstevel@tonic-gate "without-password/forced-commands-only/no " 8990Sstevel@tonic-gate "argument: %s", filename, linenum, arg); 90011044SHuie-Ying.Lee@Sun.COM if (*activep && *intptr == -1) 9010Sstevel@tonic-gate *intptr = value; 9020Sstevel@tonic-gate break; 9030Sstevel@tonic-gate 9040Sstevel@tonic-gate case sIgnoreRhosts: 9050Sstevel@tonic-gate intptr = &options->ignore_rhosts; 9060Sstevel@tonic-gate parse_flag: 9070Sstevel@tonic-gate arg = strdelim(&cp); 9080Sstevel@tonic-gate if (!arg || *arg == '\0') 9090Sstevel@tonic-gate fatal("%s line %d: missing yes/no argument.", 9100Sstevel@tonic-gate filename, linenum); 9110Sstevel@tonic-gate value = 0; /* silence compiler */ 9120Sstevel@tonic-gate if (strcmp(arg, "yes") == 0) 9130Sstevel@tonic-gate value = 1; 9140Sstevel@tonic-gate else if (strcmp(arg, "no") == 0) 9150Sstevel@tonic-gate value = 0; 9160Sstevel@tonic-gate else 9170Sstevel@tonic-gate fatal("%s line %d: Bad yes/no argument: %s", 9180Sstevel@tonic-gate filename, linenum, arg); 91911044SHuie-Ying.Lee@Sun.COM if (*activep && *intptr == -1) 9200Sstevel@tonic-gate *intptr = value; 9210Sstevel@tonic-gate break; 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate case sIgnoreUserKnownHosts: 9240Sstevel@tonic-gate intptr = &options->ignore_user_known_hosts; 9250Sstevel@tonic-gate goto parse_flag; 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate case sRhostsAuthentication: 9280Sstevel@tonic-gate intptr = &options->rhosts_authentication; 9290Sstevel@tonic-gate goto parse_flag; 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate case sRhostsRSAAuthentication: 9320Sstevel@tonic-gate intptr = &options->rhosts_rsa_authentication; 9330Sstevel@tonic-gate goto parse_flag; 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate case sHostbasedAuthentication: 9360Sstevel@tonic-gate intptr = &options->hostbased_authentication; 9370Sstevel@tonic-gate goto parse_flag; 9380Sstevel@tonic-gate 9390Sstevel@tonic-gate case sHostbasedUsesNameFromPacketOnly: 9400Sstevel@tonic-gate intptr = &options->hostbased_uses_name_from_packet_only; 9410Sstevel@tonic-gate goto parse_flag; 9420Sstevel@tonic-gate 9430Sstevel@tonic-gate case sRSAAuthentication: 9440Sstevel@tonic-gate intptr = &options->rsa_authentication; 9450Sstevel@tonic-gate goto parse_flag; 9460Sstevel@tonic-gate 9470Sstevel@tonic-gate case sPubkeyAuthentication: 9480Sstevel@tonic-gate intptr = &options->pubkey_authentication; 9490Sstevel@tonic-gate goto parse_flag; 9500Sstevel@tonic-gate #ifdef GSSAPI 9510Sstevel@tonic-gate case sGssAuthentication: 9520Sstevel@tonic-gate intptr = &options->gss_authentication; 9530Sstevel@tonic-gate goto parse_flag; 9540Sstevel@tonic-gate case sGssKeyEx: 9550Sstevel@tonic-gate intptr = &options->gss_keyex; 9560Sstevel@tonic-gate goto parse_flag; 9570Sstevel@tonic-gate case sGssStoreDelegCreds: 9580Sstevel@tonic-gate intptr = &options->gss_keyex; 9590Sstevel@tonic-gate goto parse_flag; 9600Sstevel@tonic-gate #ifndef SUNW_GSSAPI 9610Sstevel@tonic-gate case sGssUseSessionCredCache: 9620Sstevel@tonic-gate intptr = &options->gss_use_session_ccache; 9630Sstevel@tonic-gate goto parse_flag; 9640Sstevel@tonic-gate case sGssCleanupCreds: 9650Sstevel@tonic-gate intptr = &options->gss_cleanup_creds; 9660Sstevel@tonic-gate goto parse_flag; 9670Sstevel@tonic-gate #endif /* SUNW_GSSAPI */ 9680Sstevel@tonic-gate #endif /* GSSAPI */ 9690Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 9700Sstevel@tonic-gate case sKerberosAuthentication: 9710Sstevel@tonic-gate intptr = &options->kerberos_authentication; 9720Sstevel@tonic-gate goto parse_flag; 9730Sstevel@tonic-gate 9740Sstevel@tonic-gate case sKerberosOrLocalPasswd: 9750Sstevel@tonic-gate intptr = &options->kerberos_or_local_passwd; 9760Sstevel@tonic-gate goto parse_flag; 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate case sKerberosTicketCleanup: 9790Sstevel@tonic-gate intptr = &options->kerberos_ticket_cleanup; 9800Sstevel@tonic-gate goto parse_flag; 9810Sstevel@tonic-gate #endif 9820Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 9830Sstevel@tonic-gate case sKerberosTgtPassing: 9840Sstevel@tonic-gate intptr = &options->kerberos_tgt_passing; 9850Sstevel@tonic-gate goto parse_flag; 9860Sstevel@tonic-gate #endif 9870Sstevel@tonic-gate #ifdef AFS 9880Sstevel@tonic-gate case sAFSTokenPassing: 9890Sstevel@tonic-gate intptr = &options->afs_token_passing; 9900Sstevel@tonic-gate goto parse_flag; 9910Sstevel@tonic-gate #endif 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate case sPasswordAuthentication: 9940Sstevel@tonic-gate intptr = &options->password_authentication; 9950Sstevel@tonic-gate goto parse_flag; 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate case sKbdInteractiveAuthentication: 9980Sstevel@tonic-gate intptr = &options->kbd_interactive_authentication; 9990Sstevel@tonic-gate goto parse_flag; 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate case sChallengeResponseAuthentication: 10020Sstevel@tonic-gate intptr = &options->challenge_response_authentication; 10030Sstevel@tonic-gate goto parse_flag; 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate case sPrintMotd: 10060Sstevel@tonic-gate intptr = &options->print_motd; 10070Sstevel@tonic-gate goto parse_flag; 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate case sPrintLastLog: 10100Sstevel@tonic-gate intptr = &options->print_lastlog; 10110Sstevel@tonic-gate goto parse_flag; 10120Sstevel@tonic-gate 10130Sstevel@tonic-gate case sX11Forwarding: 10140Sstevel@tonic-gate intptr = &options->x11_forwarding; 10150Sstevel@tonic-gate goto parse_flag; 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate case sX11DisplayOffset: 10180Sstevel@tonic-gate intptr = &options->x11_display_offset; 10190Sstevel@tonic-gate goto parse_int; 10200Sstevel@tonic-gate 10210Sstevel@tonic-gate case sX11UseLocalhost: 10220Sstevel@tonic-gate intptr = &options->x11_use_localhost; 10230Sstevel@tonic-gate goto parse_flag; 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate case sXAuthLocation: 10260Sstevel@tonic-gate charptr = &options->xauth_location; 10270Sstevel@tonic-gate goto parse_filename; 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate case sStrictModes: 10300Sstevel@tonic-gate intptr = &options->strict_modes; 10310Sstevel@tonic-gate goto parse_flag; 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate case sKeepAlives: 10340Sstevel@tonic-gate intptr = &options->keepalives; 10350Sstevel@tonic-gate goto parse_flag; 10360Sstevel@tonic-gate 10370Sstevel@tonic-gate case sEmptyPasswd: 10380Sstevel@tonic-gate intptr = &options->permit_empty_passwd; 10390Sstevel@tonic-gate goto parse_flag; 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate case sPermitUserEnvironment: 10420Sstevel@tonic-gate intptr = &options->permit_user_env; 10430Sstevel@tonic-gate goto parse_flag; 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate case sUseLogin: 10469845SJan.Pechanec@Sun.COM log("%s line %d: ignoring UseLogin option value." 10479845SJan.Pechanec@Sun.COM " This option is always off.", filename, linenum); 10489845SJan.Pechanec@Sun.COM while (arg) 10499845SJan.Pechanec@Sun.COM arg = strdelim(&cp); 10509845SJan.Pechanec@Sun.COM break; 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate case sCompression: 10530Sstevel@tonic-gate intptr = &options->compression; 10540Sstevel@tonic-gate goto parse_flag; 10550Sstevel@tonic-gate 10560Sstevel@tonic-gate case sGatewayPorts: 105711044SHuie-Ying.Lee@Sun.COM intptr = &options->gateway_ports; 10585334Sjp161948 arg = strdelim(&cp); 105911044SHuie-Ying.Lee@Sun.COM if (!arg || *arg == '\0') 106011044SHuie-Ying.Lee@Sun.COM fatal("%s line %d: missing yes/no/clientspecified " 106111044SHuie-Ying.Lee@Sun.COM "argument.", filename, linenum); 106211044SHuie-Ying.Lee@Sun.COM value = 0; /* silence compiler */ 10635334Sjp161948 if (strcmp(arg, "clientspecified") == 0) 106411044SHuie-Ying.Lee@Sun.COM value = 2; 106511044SHuie-Ying.Lee@Sun.COM else if (strcmp(arg, "yes") == 0) 106611044SHuie-Ying.Lee@Sun.COM value = 1; 106711044SHuie-Ying.Lee@Sun.COM else if (strcmp(arg, "no") == 0) 106811044SHuie-Ying.Lee@Sun.COM value = 0; 10695334Sjp161948 else 107011044SHuie-Ying.Lee@Sun.COM fatal("%s line %d: Bad yes/no/clientspecified " 107111044SHuie-Ying.Lee@Sun.COM "argument: %s", filename, linenum, arg); 107211044SHuie-Ying.Lee@Sun.COM if (*activep && *intptr == -1) 107311044SHuie-Ying.Lee@Sun.COM *intptr = value; 10745334Sjp161948 break; 10750Sstevel@tonic-gate 10760Sstevel@tonic-gate case sVerifyReverseMapping: 10770Sstevel@tonic-gate intptr = &options->verify_reverse_mapping; 10780Sstevel@tonic-gate goto parse_flag; 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate case sLogFacility: 10810Sstevel@tonic-gate intptr = (int *) &options->log_facility; 10820Sstevel@tonic-gate arg = strdelim(&cp); 10830Sstevel@tonic-gate value = log_facility_number(arg); 10840Sstevel@tonic-gate if (value == SYSLOG_FACILITY_NOT_SET) 10850Sstevel@tonic-gate fatal("%.200s line %d: unsupported log facility '%s'", 10860Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 10870Sstevel@tonic-gate if (*intptr == -1) 10880Sstevel@tonic-gate *intptr = (SyslogFacility) value; 10890Sstevel@tonic-gate break; 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate case sLogLevel: 10920Sstevel@tonic-gate intptr = (int *) &options->log_level; 10930Sstevel@tonic-gate arg = strdelim(&cp); 10940Sstevel@tonic-gate value = log_level_number(arg); 10950Sstevel@tonic-gate if (value == SYSLOG_LEVEL_NOT_SET) 10960Sstevel@tonic-gate fatal("%.200s line %d: unsupported log level '%s'", 10970Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 10980Sstevel@tonic-gate if (*intptr == -1) 10990Sstevel@tonic-gate *intptr = (LogLevel) value; 11000Sstevel@tonic-gate break; 11010Sstevel@tonic-gate 11020Sstevel@tonic-gate case sAllowTcpForwarding: 11030Sstevel@tonic-gate intptr = &options->allow_tcp_forwarding; 11040Sstevel@tonic-gate goto parse_flag; 11050Sstevel@tonic-gate 11060Sstevel@tonic-gate case sUsePrivilegeSeparation: 11075562Sjp161948 log("%s line %d: ignoring UsePrivilegeSeparation option value." 11085562Sjp161948 " This option is always on.", filename, linenum); 11095562Sjp161948 while (arg) 11109845SJan.Pechanec@Sun.COM arg = strdelim(&cp); 11115562Sjp161948 break; 11120Sstevel@tonic-gate 11130Sstevel@tonic-gate case sAllowUsers: 11140Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11150Sstevel@tonic-gate if (options->num_allow_users >= MAX_ALLOW_USERS) 11160Sstevel@tonic-gate fatal("%s line %d: too many allow users.", 11170Sstevel@tonic-gate filename, linenum); 11180Sstevel@tonic-gate options->allow_users[options->num_allow_users++] = 11190Sstevel@tonic-gate xstrdup(arg); 11200Sstevel@tonic-gate } 11210Sstevel@tonic-gate break; 11220Sstevel@tonic-gate 11230Sstevel@tonic-gate case sDenyUsers: 11240Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11250Sstevel@tonic-gate if (options->num_deny_users >= MAX_DENY_USERS) 11260Sstevel@tonic-gate fatal( "%s line %d: too many deny users.", 11270Sstevel@tonic-gate filename, linenum); 11280Sstevel@tonic-gate options->deny_users[options->num_deny_users++] = 11290Sstevel@tonic-gate xstrdup(arg); 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate break; 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate case sAllowGroups: 11340Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11350Sstevel@tonic-gate if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 11360Sstevel@tonic-gate fatal("%s line %d: too many allow groups.", 11370Sstevel@tonic-gate filename, linenum); 11380Sstevel@tonic-gate options->allow_groups[options->num_allow_groups++] = 11390Sstevel@tonic-gate xstrdup(arg); 11400Sstevel@tonic-gate } 11410Sstevel@tonic-gate break; 11420Sstevel@tonic-gate 11430Sstevel@tonic-gate case sDenyGroups: 11440Sstevel@tonic-gate while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') { 11450Sstevel@tonic-gate if (options->num_deny_groups >= MAX_DENY_GROUPS) 11460Sstevel@tonic-gate fatal("%s line %d: too many deny groups.", 11470Sstevel@tonic-gate filename, linenum); 11480Sstevel@tonic-gate options->deny_groups[options->num_deny_groups++] = xstrdup(arg); 11490Sstevel@tonic-gate } 11500Sstevel@tonic-gate break; 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate case sCiphers: 11530Sstevel@tonic-gate arg = strdelim(&cp); 11540Sstevel@tonic-gate if (!arg || *arg == '\0') 11550Sstevel@tonic-gate fatal("%s line %d: Missing argument.", filename, linenum); 11560Sstevel@tonic-gate if (!ciphers_valid(arg)) 11570Sstevel@tonic-gate fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 11580Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 11590Sstevel@tonic-gate if (options->ciphers == NULL) 11600Sstevel@tonic-gate options->ciphers = xstrdup(arg); 11610Sstevel@tonic-gate break; 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate case sMacs: 11640Sstevel@tonic-gate arg = strdelim(&cp); 11650Sstevel@tonic-gate if (!arg || *arg == '\0') 11660Sstevel@tonic-gate fatal("%s line %d: Missing argument.", filename, linenum); 11670Sstevel@tonic-gate if (!mac_valid(arg)) 11680Sstevel@tonic-gate fatal("%s line %d: Bad SSH2 mac spec '%s'.", 11690Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 11700Sstevel@tonic-gate if (options->macs == NULL) 11710Sstevel@tonic-gate options->macs = xstrdup(arg); 11720Sstevel@tonic-gate break; 11730Sstevel@tonic-gate 11740Sstevel@tonic-gate case sProtocol: 11750Sstevel@tonic-gate intptr = &options->protocol; 11760Sstevel@tonic-gate arg = strdelim(&cp); 11770Sstevel@tonic-gate if (!arg || *arg == '\0') 11780Sstevel@tonic-gate fatal("%s line %d: Missing argument.", filename, linenum); 11790Sstevel@tonic-gate value = proto_spec(arg); 11800Sstevel@tonic-gate if (value == SSH_PROTO_UNKNOWN) 11810Sstevel@tonic-gate fatal("%s line %d: Bad protocol spec '%s'.", 11820Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 11830Sstevel@tonic-gate if (*intptr == SSH_PROTO_UNKNOWN) 11840Sstevel@tonic-gate *intptr = value; 11850Sstevel@tonic-gate break; 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate case sSubsystem: 11880Sstevel@tonic-gate if (options->num_subsystems >= MAX_SUBSYSTEMS) { 11890Sstevel@tonic-gate fatal("%s line %d: too many subsystems defined.", 11900Sstevel@tonic-gate filename, linenum); 11910Sstevel@tonic-gate } 11920Sstevel@tonic-gate arg = strdelim(&cp); 11930Sstevel@tonic-gate if (!arg || *arg == '\0') 11940Sstevel@tonic-gate fatal("%s line %d: Missing subsystem name.", 11950Sstevel@tonic-gate filename, linenum); 119611044SHuie-Ying.Lee@Sun.COM if (!*activep) { 119711044SHuie-Ying.Lee@Sun.COM arg = strdelim(&cp); 119811044SHuie-Ying.Lee@Sun.COM break; 119911044SHuie-Ying.Lee@Sun.COM } 12000Sstevel@tonic-gate for (i = 0; i < options->num_subsystems; i++) 12010Sstevel@tonic-gate if (strcmp(arg, options->subsystem_name[i]) == 0) 12020Sstevel@tonic-gate fatal("%s line %d: Subsystem '%s' already defined.", 12030Sstevel@tonic-gate filename, linenum, arg); 12040Sstevel@tonic-gate options->subsystem_name[options->num_subsystems] = xstrdup(arg); 12050Sstevel@tonic-gate arg = strdelim(&cp); 12060Sstevel@tonic-gate if (!arg || *arg == '\0') 12070Sstevel@tonic-gate fatal("%s line %d: Missing subsystem command.", 12080Sstevel@tonic-gate filename, linenum); 12090Sstevel@tonic-gate options->subsystem_command[options->num_subsystems] = xstrdup(arg); 12109139SJan.Pechanec@Sun.COM 12119139SJan.Pechanec@Sun.COM /* 12129139SJan.Pechanec@Sun.COM * Collect arguments (separate to executable), including the 12139139SJan.Pechanec@Sun.COM * name of the executable, in a way that is easier to parse 12149139SJan.Pechanec@Sun.COM * later. 12159139SJan.Pechanec@Sun.COM */ 12169139SJan.Pechanec@Sun.COM p = xstrdup(arg); 12179139SJan.Pechanec@Sun.COM len = strlen(p) + 1; 12189139SJan.Pechanec@Sun.COM while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { 12199139SJan.Pechanec@Sun.COM len += 1 + strlen(arg); 12209139SJan.Pechanec@Sun.COM p = xrealloc(p, len); 12219139SJan.Pechanec@Sun.COM strlcat(p, " ", len); 12229139SJan.Pechanec@Sun.COM strlcat(p, arg, len); 12239139SJan.Pechanec@Sun.COM } 12249139SJan.Pechanec@Sun.COM options->subsystem_args[options->num_subsystems] = p; 12250Sstevel@tonic-gate options->num_subsystems++; 12260Sstevel@tonic-gate break; 12270Sstevel@tonic-gate 12280Sstevel@tonic-gate case sMaxStartups: 12290Sstevel@tonic-gate arg = strdelim(&cp); 12300Sstevel@tonic-gate if (!arg || *arg == '\0') 12310Sstevel@tonic-gate fatal("%s line %d: Missing MaxStartups spec.", 12320Sstevel@tonic-gate filename, linenum); 12330Sstevel@tonic-gate if ((n = sscanf(arg, "%d:%d:%d", 12340Sstevel@tonic-gate &options->max_startups_begin, 12350Sstevel@tonic-gate &options->max_startups_rate, 12360Sstevel@tonic-gate &options->max_startups)) == 3) { 12370Sstevel@tonic-gate if (options->max_startups_begin > 12380Sstevel@tonic-gate options->max_startups || 12390Sstevel@tonic-gate options->max_startups_rate > 100 || 12400Sstevel@tonic-gate options->max_startups_rate < 1) 12410Sstevel@tonic-gate fatal("%s line %d: Illegal MaxStartups spec.", 12420Sstevel@tonic-gate filename, linenum); 12430Sstevel@tonic-gate } else if (n != 1) 12440Sstevel@tonic-gate fatal("%s line %d: Illegal MaxStartups spec.", 12450Sstevel@tonic-gate filename, linenum); 12460Sstevel@tonic-gate else 12470Sstevel@tonic-gate options->max_startups = options->max_startups_begin; 12480Sstevel@tonic-gate break; 12490Sstevel@tonic-gate 12500Sstevel@tonic-gate case sBanner: 12510Sstevel@tonic-gate charptr = &options->banner; 12520Sstevel@tonic-gate goto parse_filename; 12530Sstevel@tonic-gate /* 12540Sstevel@tonic-gate * These options can contain %X options expanded at 12550Sstevel@tonic-gate * connect time, so that you can specify paths like: 12560Sstevel@tonic-gate * 12570Sstevel@tonic-gate * AuthorizedKeysFile /etc/ssh_keys/%u 12580Sstevel@tonic-gate */ 12590Sstevel@tonic-gate case sAuthorizedKeysFile: 12600Sstevel@tonic-gate case sAuthorizedKeysFile2: 12619139SJan.Pechanec@Sun.COM charptr = (opcode == sAuthorizedKeysFile) ? 12620Sstevel@tonic-gate &options->authorized_keys_file : 12630Sstevel@tonic-gate &options->authorized_keys_file2; 12640Sstevel@tonic-gate goto parse_filename; 12650Sstevel@tonic-gate 12660Sstevel@tonic-gate case sClientAliveInterval: 12670Sstevel@tonic-gate intptr = &options->client_alive_interval; 12680Sstevel@tonic-gate goto parse_time; 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate case sClientAliveCountMax: 12710Sstevel@tonic-gate intptr = &options->client_alive_count_max; 12720Sstevel@tonic-gate goto parse_int; 12730Sstevel@tonic-gate 12740Sstevel@tonic-gate case sMaxAuthTries: 12750Sstevel@tonic-gate intptr = &options->max_auth_tries; 12760Sstevel@tonic-gate goto parse_int; 12770Sstevel@tonic-gate 12780Sstevel@tonic-gate case sMaxAuthTriesLog: 12790Sstevel@tonic-gate intptr = &options->max_auth_tries_log; 12800Sstevel@tonic-gate goto parse_int; 12810Sstevel@tonic-gate 12820Sstevel@tonic-gate case sLookupClientHostnames: 12830Sstevel@tonic-gate intptr = &options->lookup_client_hostnames; 12840Sstevel@tonic-gate goto parse_flag; 12859139SJan.Pechanec@Sun.COM 12867574SJan.Pechanec@Sun.COM case sUseOpenSSLEngine: 12877574SJan.Pechanec@Sun.COM intptr = &options->use_openssl_engine; 12887574SJan.Pechanec@Sun.COM goto parse_flag; 12890Sstevel@tonic-gate 12909139SJan.Pechanec@Sun.COM case sChrootDirectory: 12919139SJan.Pechanec@Sun.COM charptr = &options->chroot_directory; 12929139SJan.Pechanec@Sun.COM 12939139SJan.Pechanec@Sun.COM arg = strdelim(&cp); 12949139SJan.Pechanec@Sun.COM if (arg == NULL || *arg == '\0') 12959139SJan.Pechanec@Sun.COM fatal("%s line %d: missing directory name for " 12969139SJan.Pechanec@Sun.COM "ChrootDirectory.", filename, linenum); 129711044SHuie-Ying.Lee@Sun.COM if (*activep && *charptr == NULL) 12989139SJan.Pechanec@Sun.COM *charptr = xstrdup(arg); 12999139SJan.Pechanec@Sun.COM break; 13009139SJan.Pechanec@Sun.COM 130111044SHuie-Ying.Lee@Sun.COM case sMatch: 130211044SHuie-Ying.Lee@Sun.COM if (cmdline) 130311044SHuie-Ying.Lee@Sun.COM fatal("Match directive not supported as a command-line " 130411044SHuie-Ying.Lee@Sun.COM "option"); 130511044SHuie-Ying.Lee@Sun.COM value = match_cfg_line(&cp, linenum, user, host, address); 130611044SHuie-Ying.Lee@Sun.COM if (value < 0) 130711044SHuie-Ying.Lee@Sun.COM fatal("%s line %d: Bad Match condition", filename, 130811044SHuie-Ying.Lee@Sun.COM linenum); 130911044SHuie-Ying.Lee@Sun.COM *activep = value; 131011044SHuie-Ying.Lee@Sun.COM break; 131111044SHuie-Ying.Lee@Sun.COM 13120Sstevel@tonic-gate case sDeprecated: 13130Sstevel@tonic-gate log("%s line %d: Deprecated option %s", 13140Sstevel@tonic-gate filename, linenum, arg); 13150Sstevel@tonic-gate while (arg) 13160Sstevel@tonic-gate arg = strdelim(&cp); 13170Sstevel@tonic-gate break; 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate default: 13200Sstevel@tonic-gate fatal("%s line %d: Missing handler for opcode %s (%d)", 13210Sstevel@tonic-gate filename, linenum, arg, opcode); 13220Sstevel@tonic-gate } 13230Sstevel@tonic-gate if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 13240Sstevel@tonic-gate fatal("%s line %d: garbage at end of line; \"%.200s\".", 13250Sstevel@tonic-gate filename, linenum, arg); 13260Sstevel@tonic-gate return 0; 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 132911044SHuie-Ying.Lee@Sun.COM 13300Sstevel@tonic-gate /* Reads the server configuration file. */ 13310Sstevel@tonic-gate 13320Sstevel@tonic-gate void 133311044SHuie-Ying.Lee@Sun.COM load_server_config(const char *filename, Buffer *conf) 13340Sstevel@tonic-gate { 133511044SHuie-Ying.Lee@Sun.COM char line[1024], *cp; 13360Sstevel@tonic-gate FILE *f; 13370Sstevel@tonic-gate 133811044SHuie-Ying.Lee@Sun.COM debug2("%s: filename %s", __func__, filename); 133911044SHuie-Ying.Lee@Sun.COM if ((f = fopen(filename, "r")) == NULL) { 13400Sstevel@tonic-gate perror(filename); 13410Sstevel@tonic-gate exit(1); 13420Sstevel@tonic-gate } 134311044SHuie-Ying.Lee@Sun.COM buffer_clear(conf); 13440Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) { 134511044SHuie-Ying.Lee@Sun.COM /* 134611044SHuie-Ying.Lee@Sun.COM * Trim out comments and strip whitespace 134711044SHuie-Ying.Lee@Sun.COM * NB - preserve newlines, they are needed to reproduce 134811044SHuie-Ying.Lee@Sun.COM * line numbers later for error messages 134911044SHuie-Ying.Lee@Sun.COM */ 135011044SHuie-Ying.Lee@Sun.COM if ((cp = strchr(line, '#')) != NULL) 135111044SHuie-Ying.Lee@Sun.COM memcpy(cp, "\n", 2); 135211044SHuie-Ying.Lee@Sun.COM cp = line + strspn(line, " \t\r"); 135311044SHuie-Ying.Lee@Sun.COM 135411044SHuie-Ying.Lee@Sun.COM buffer_append(conf, cp, strlen(cp)); 135511044SHuie-Ying.Lee@Sun.COM } 135611044SHuie-Ying.Lee@Sun.COM buffer_append(conf, "\0", 1); 135711044SHuie-Ying.Lee@Sun.COM fclose(f); 135811044SHuie-Ying.Lee@Sun.COM debug2("%s: done config len = %d", __func__, buffer_len(conf)); 135911044SHuie-Ying.Lee@Sun.COM } 136011044SHuie-Ying.Lee@Sun.COM 136111044SHuie-Ying.Lee@Sun.COM void 136211044SHuie-Ying.Lee@Sun.COM parse_server_match_config(ServerOptions *options, const char *user, 136311044SHuie-Ying.Lee@Sun.COM const char *host, const char *address) 136411044SHuie-Ying.Lee@Sun.COM { 136511044SHuie-Ying.Lee@Sun.COM ServerOptions mo; 136611044SHuie-Ying.Lee@Sun.COM 136711044SHuie-Ying.Lee@Sun.COM initialize_server_options(&mo); 136811044SHuie-Ying.Lee@Sun.COM parse_server_config(&mo, "reprocess config", &cfg, user, host, address); 136911044SHuie-Ying.Lee@Sun.COM copy_set_server_options(options, &mo, 0); 137011044SHuie-Ying.Lee@Sun.COM } 137111044SHuie-Ying.Lee@Sun.COM 137211044SHuie-Ying.Lee@Sun.COM 137311044SHuie-Ying.Lee@Sun.COM 137411044SHuie-Ying.Lee@Sun.COM /* Helper macros */ 137511044SHuie-Ying.Lee@Sun.COM #define M_CP_INTOPT(n) do {\ 137611044SHuie-Ying.Lee@Sun.COM if (src->n != -1) \ 137711044SHuie-Ying.Lee@Sun.COM dst->n = src->n; \ 137811044SHuie-Ying.Lee@Sun.COM } while (0) 137911044SHuie-Ying.Lee@Sun.COM #define M_CP_STROPT(n) do {\ 138011044SHuie-Ying.Lee@Sun.COM if (src->n != NULL) { \ 138111044SHuie-Ying.Lee@Sun.COM if (dst->n != NULL) \ 138211044SHuie-Ying.Lee@Sun.COM xfree(dst->n); \ 138311044SHuie-Ying.Lee@Sun.COM dst->n = src->n; \ 138411044SHuie-Ying.Lee@Sun.COM } \ 138511044SHuie-Ying.Lee@Sun.COM } while(0) 138611044SHuie-Ying.Lee@Sun.COM 138711044SHuie-Ying.Lee@Sun.COM /* 138811044SHuie-Ying.Lee@Sun.COM * Copy any supported values that are set. 138911044SHuie-Ying.Lee@Sun.COM * 139011044SHuie-Ying.Lee@Sun.COM * If the preauth flag is set, we do not bother copying the the string or 139111044SHuie-Ying.Lee@Sun.COM * array values that are not used pre-authentication, because any that we 139211044SHuie-Ying.Lee@Sun.COM * do use must be explictly sent in mm_getpwnamallow(). 139311044SHuie-Ying.Lee@Sun.COM */ 139411044SHuie-Ying.Lee@Sun.COM void 139511044SHuie-Ying.Lee@Sun.COM copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) 139611044SHuie-Ying.Lee@Sun.COM { 139711044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(password_authentication); 139811044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(gss_authentication); 139911044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(rsa_authentication); 140011044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(pubkey_authentication); 140111044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(hostbased_authentication); 140211044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(kbd_interactive_authentication); 140311044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(permit_root_login); 140411044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(permit_empty_passwd); 140511044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(allow_tcp_forwarding); 140611044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(gateway_ports); 140711044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(x11_display_offset); 140811044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(x11_forwarding); 140911044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(x11_use_localhost); 141011044SHuie-Ying.Lee@Sun.COM M_CP_INTOPT(max_auth_tries); 141111044SHuie-Ying.Lee@Sun.COM M_CP_STROPT(banner); 141211044SHuie-Ying.Lee@Sun.COM 141311044SHuie-Ying.Lee@Sun.COM if (preauth) 141411044SHuie-Ying.Lee@Sun.COM return; 141511044SHuie-Ying.Lee@Sun.COM M_CP_STROPT(chroot_directory); 141611044SHuie-Ying.Lee@Sun.COM } 141711044SHuie-Ying.Lee@Sun.COM 141811044SHuie-Ying.Lee@Sun.COM #undef M_CP_INTOPT 141911044SHuie-Ying.Lee@Sun.COM #undef M_CP_STROPT 142011044SHuie-Ying.Lee@Sun.COM 142111044SHuie-Ying.Lee@Sun.COM void 142211044SHuie-Ying.Lee@Sun.COM parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 142311044SHuie-Ying.Lee@Sun.COM const char *user, const char *host, const char *address) 142411044SHuie-Ying.Lee@Sun.COM { 142511044SHuie-Ying.Lee@Sun.COM int active, linenum, bad_options = 0; 142611044SHuie-Ying.Lee@Sun.COM char *cp, *obuf, *cbuf; 142711044SHuie-Ying.Lee@Sun.COM 142811044SHuie-Ying.Lee@Sun.COM debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); 142911044SHuie-Ying.Lee@Sun.COM 143011044SHuie-Ying.Lee@Sun.COM obuf = cbuf = xstrdup(buffer_ptr(conf)); 143111044SHuie-Ying.Lee@Sun.COM active = user ? 0 : 1; 143211044SHuie-Ying.Lee@Sun.COM linenum = 1; 143311044SHuie-Ying.Lee@Sun.COM while ((cp = strsep(&cbuf, "\n")) != NULL) { 143411044SHuie-Ying.Lee@Sun.COM if (process_server_config_line(options, cp, filename, 143511044SHuie-Ying.Lee@Sun.COM linenum++, &active, user, host, address) != 0) 14360Sstevel@tonic-gate bad_options++; 14370Sstevel@tonic-gate } 143811044SHuie-Ying.Lee@Sun.COM xfree(obuf); 14390Sstevel@tonic-gate if (bad_options > 0) 14400Sstevel@tonic-gate fatal("%s: terminating, %d bad configuration options", 14410Sstevel@tonic-gate filename, bad_options); 14420Sstevel@tonic-gate } 14439139SJan.Pechanec@Sun.COM 144411044SHuie-Ying.Lee@Sun.COM 14459139SJan.Pechanec@Sun.COM /* 14469139SJan.Pechanec@Sun.COM * Note that "none" is a special path having the same affect on sshd 14479139SJan.Pechanec@Sun.COM * configuration as not specifying ChrootDirectory at all. 14489139SJan.Pechanec@Sun.COM */ 14499139SJan.Pechanec@Sun.COM int 14509139SJan.Pechanec@Sun.COM chroot_requested(char *chroot_directory) 14519139SJan.Pechanec@Sun.COM { 14529139SJan.Pechanec@Sun.COM return (chroot_directory != NULL && 14539139SJan.Pechanec@Sun.COM strcasecmp(chroot_directory, "none") != 0); 14549139SJan.Pechanec@Sun.COM } 1455