blob: 94dff1fd62150ab331f1f17328192d85af142e64 [file] [log] [blame]
Damien Miller7207f642008-05-19 15:34:50 +10001/* $OpenBSD: servconf.c,v 1.180 2008/05/08 12:21:16 djm Exp $ */
Damien Millerd4a8b7e1999-10-27 13:42:43 +10002/*
Damien Miller95def091999-11-25 00:26:21 +11003 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
Damien Miller4af51302000-04-16 11:18:38 +10005 *
Damien Millere4340be2000-09-16 13:29:08 +11006 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
Damien Miller95def091999-11-25 00:26:21 +110011 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100012
13#include "includes.h"
Damien Millerd4a8b7e1999-10-27 13:42:43 +100014
Damien Millere3b60b52006-07-10 21:08:03 +100015#include <sys/types.h>
16#include <sys/socket.h>
17
Damien Millerb8fe89c2006-07-24 14:51:00 +100018#include <netdb.h>
Damien Miller565ca3f2006-08-19 00:23:15 +100019#include <pwd.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100020#include <stdio.h>
Damien Millere7a1e5c2006-08-05 11:34:19 +100021#include <stdlib.h>
Damien Millere3476ed2006-07-24 14:13:33 +100022#include <string.h>
Damien Millerd7834352006-08-05 12:39:39 +100023#include <signal.h>
Damien Millere6b3b612006-07-24 14:01:23 +100024#include <unistd.h>
Damien Millerd7834352006-08-05 12:39:39 +100025#include <stdarg.h>
Damien Millerbe43ebf2006-07-24 13:51:51 +100026
Damien Millerb84886b2008-05-19 15:05:07 +100027#include "openbsd-compat/sys-queue.h"
Damien Millerd7834352006-08-05 12:39:39 +100028#include "xmalloc.h"
Damien Millerd4a8b7e1999-10-27 13:42:43 +100029#include "ssh.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000030#include "log.h"
Damien Millerd7834352006-08-05 12:39:39 +100031#include "buffer.h"
Damien Millerd4a8b7e1999-10-27 13:42:43 +100032#include "servconf.h"
Damien Miller78928792000-04-12 20:17:38 +100033#include "compat.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000034#include "pathnames.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000035#include "misc.h"
36#include "cipher.h"
Damien Millerd7834352006-08-05 12:39:39 +100037#include "key.h"
Ben Lindstrom06b33aa2001-02-15 03:01:59 +000038#include "kex.h"
39#include "mac.h"
Darren Tucker45150472006-07-12 22:34:17 +100040#include "match.h"
Damien Miller9b439df2006-07-24 14:04:00 +100041#include "channels.h"
Damien Miller565ca3f2006-08-19 00:23:15 +100042#include "groupaccess.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000043
Ben Lindstrombba81212001-06-25 05:01:22 +000044static void add_listen_addr(ServerOptions *, char *, u_short);
45static void add_one_listen_addr(ServerOptions *, char *, u_short);
Damien Miller34132e52000-01-14 15:45:46 +110046
Ben Lindstrom7a2073c2002-03-22 02:30:41 +000047/* Use of privilege separation or not */
48extern int use_privsep;
Darren Tucker45150472006-07-12 22:34:17 +100049extern Buffer cfg;
Ben Lindstrom226cfa02001-01-22 05:34:40 +000050
Damien Millerd4a8b7e1999-10-27 13:42:43 +100051/* Initializes the server options to their default values. */
52
Damien Miller4af51302000-04-16 11:18:38 +100053void
Damien Miller95def091999-11-25 00:26:21 +110054initialize_server_options(ServerOptions *options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100055{
Damien Miller95def091999-11-25 00:26:21 +110056 memset(options, 0, sizeof(*options));
Damien Miller726273e2001-11-12 11:40:11 +110057
58 /* Portable-specific options */
Damien Miller4e448a32003-05-14 15:11:48 +100059 options->use_pam = -1;
Damien Miller726273e2001-11-12 11:40:11 +110060
61 /* Standard Options */
Damien Miller34132e52000-01-14 15:45:46 +110062 options->num_ports = 0;
63 options->ports_from_cmdline = 0;
64 options->listen_addrs = NULL;
Darren Tucker0f383232005-01-20 10:57:56 +110065 options->address_family = -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +110066 options->num_host_key_files = 0;
Damien Miller6f83b8e2000-05-02 09:23:45 +100067 options->pid_file = NULL;
Damien Miller95def091999-11-25 00:26:21 +110068 options->server_key_bits = -1;
69 options->login_grace_time = -1;
70 options->key_regeneration_time = -1;
Ben Lindstromd8a90212001-02-15 03:08:27 +000071 options->permit_root_login = PERMIT_NOT_SET;
Damien Miller95def091999-11-25 00:26:21 +110072 options->ignore_rhosts = -1;
73 options->ignore_user_known_hosts = -1;
74 options->print_motd = -1;
Ben Lindstrom7bfff362001-03-26 05:45:53 +000075 options->print_lastlog = -1;
Damien Miller95def091999-11-25 00:26:21 +110076 options->x11_forwarding = -1;
77 options->x11_display_offset = -1;
Damien Miller95c249f2002-02-05 12:11:34 +110078 options->x11_use_localhost = -1;
Damien Millerd3a18572000-06-07 19:55:44 +100079 options->xauth_location = NULL;
Damien Miller95def091999-11-25 00:26:21 +110080 options->strict_modes = -1;
Damien Miller12c150e2003-12-17 16:31:10 +110081 options->tcp_keep_alive = -1;
Damien Millerfcd93202002-02-05 12:26:34 +110082 options->log_facility = SYSLOG_FACILITY_NOT_SET;
83 options->log_level = SYSLOG_LEVEL_NOT_SET;
Damien Miller95def091999-11-25 00:26:21 +110084 options->rhosts_rsa_authentication = -1;
Ben Lindstrom5eabda32001-04-12 23:34:34 +000085 options->hostbased_authentication = -1;
86 options->hostbased_uses_name_from_packet_only = -1;
Damien Miller95def091999-11-25 00:26:21 +110087 options->rsa_authentication = -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +110088 options->pubkey_authentication = -1;
Damien Miller95def091999-11-25 00:26:21 +110089 options->kerberos_authentication = -1;
90 options->kerberos_or_local_passwd = -1;
91 options->kerberos_ticket_cleanup = -1;
Darren Tucker22ef5082003-12-31 11:37:34 +110092 options->kerberos_get_afs_token = -1;
Darren Tucker0efd1552003-08-26 11:49:55 +100093 options->gss_authentication=-1;
94 options->gss_cleanup_creds = -1;
Damien Miller95def091999-11-25 00:26:21 +110095 options->password_authentication = -1;
Damien Miller874d77b2000-10-14 16:23:11 +110096 options->kbd_interactive_authentication = -1;
Ben Lindstrom551ea372001-06-05 18:56:16 +000097 options->challenge_response_authentication = -1;
Damien Miller95def091999-11-25 00:26:21 +110098 options->permit_empty_passwd = -1;
Ben Lindstrom5d860f02002-08-01 01:28:38 +000099 options->permit_user_env = -1;
Damien Miller95def091999-11-25 00:26:21 +1100100 options->use_login = -1;
Ben Lindstrom23e0f662002-06-21 01:09:47 +0000101 options->compression = -1;
Damien Miller50a41ed2000-10-16 12:14:42 +1100102 options->allow_tcp_forwarding = -1;
Damien Miller4f755cd2008-05-19 14:57:41 +1000103 options->allow_agent_forwarding = -1;
Damien Miller95def091999-11-25 00:26:21 +1100104 options->num_allow_users = 0;
105 options->num_deny_users = 0;
106 options->num_allow_groups = 0;
107 options->num_deny_groups = 0;
Damien Miller78928792000-04-12 20:17:38 +1000108 options->ciphers = NULL;
Ben Lindstrom06b33aa2001-02-15 03:01:59 +0000109 options->macs = NULL;
Damien Miller78928792000-04-12 20:17:38 +1000110 options->protocol = SSH_PROTO_UNKNOWN;
Damien Millere247cc42000-05-07 12:03:14 +1000111 options->gateway_ports = -1;
Damien Millerf6d9e222000-06-18 14:50:44 +1000112 options->num_subsystems = 0;
Damien Miller942da032000-08-18 13:59:06 +1000113 options->max_startups_begin = -1;
114 options->max_startups_rate = -1;
Damien Miller37023962000-07-11 17:31:38 +1000115 options->max_startups = -1;
Darren Tucker89413db2004-05-24 10:36:23 +1000116 options->max_authtries = -1;
Damien Miller7207f642008-05-19 15:34:50 +1000117 options->max_sessions = -1;
Ben Lindstrom48bd7c12001-01-09 00:35:42 +0000118 options->banner = NULL;
Damien Miller3a961dc2003-06-03 10:25:48 +1000119 options->use_dns = -1;
Ben Lindstrom5744dc42001-04-13 23:28:01 +0000120 options->client_alive_interval = -1;
121 options->client_alive_count_max = -1;
Ben Lindstrombfb3a0e2001-06-05 20:25:05 +0000122 options->authorized_keys_file = NULL;
123 options->authorized_keys_file2 = NULL;
Darren Tucker46bc0752004-05-02 22:11:30 +1000124 options->num_accept_env = 0;
Damien Millerd27b9472005-12-13 19:29:02 +1100125 options->permit_tun = -1;
Damien Millera765cf42006-07-24 14:08:13 +1000126 options->num_permitted_opens = -1;
Damien Millere2754432006-07-24 14:06:47 +1000127 options->adm_forced_command = NULL;
Damien Millerd8cb1f12008-02-10 22:40:12 +1100128 options->chroot_directory = NULL;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000129}
130
Damien Miller4af51302000-04-16 11:18:38 +1000131void
Damien Miller95def091999-11-25 00:26:21 +1100132fill_default_server_options(ServerOptions *options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000133{
Damien Miller726273e2001-11-12 11:40:11 +1100134 /* Portable-specific options */
Damien Miller4e448a32003-05-14 15:11:48 +1000135 if (options->use_pam == -1)
Damien Miller5c3a5582003-09-23 22:12:38 +1000136 options->use_pam = 0;
Damien Miller726273e2001-11-12 11:40:11 +1100137
138 /* Standard Options */
Damien Miller0bc1bd82000-11-13 22:57:25 +1100139 if (options->protocol == SSH_PROTO_UNKNOWN)
140 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
141 if (options->num_host_key_files == 0) {
142 /* fill default hostkeys for protocols */
143 if (options->protocol & SSH_PROTO_1)
Damien Miller7fc23732002-01-22 23:19:11 +1100144 options->host_key_files[options->num_host_key_files++] =
145 _PATH_HOST_KEY_FILE;
146 if (options->protocol & SSH_PROTO_2) {
147 options->host_key_files[options->num_host_key_files++] =
148 _PATH_HOST_RSA_KEY_FILE;
149 options->host_key_files[options->num_host_key_files++] =
150 _PATH_HOST_DSA_KEY_FILE;
151 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100152 }
Damien Miller34132e52000-01-14 15:45:46 +1100153 if (options->num_ports == 0)
154 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
155 if (options->listen_addrs == NULL)
Ben Lindstrom19066a12001-04-12 23:39:26 +0000156 add_listen_addr(options, NULL, 0);
Damien Miller6f83b8e2000-05-02 09:23:45 +1000157 if (options->pid_file == NULL)
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000158 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
Damien Miller95def091999-11-25 00:26:21 +1100159 if (options->server_key_bits == -1)
160 options->server_key_bits = 768;
161 if (options->login_grace_time == -1)
Damien Millerc1348632002-09-05 14:35:14 +1000162 options->login_grace_time = 120;
Damien Miller95def091999-11-25 00:26:21 +1100163 if (options->key_regeneration_time == -1)
164 options->key_regeneration_time = 3600;
Ben Lindstromd8a90212001-02-15 03:08:27 +0000165 if (options->permit_root_login == PERMIT_NOT_SET)
166 options->permit_root_login = PERMIT_YES;
Damien Miller95def091999-11-25 00:26:21 +1100167 if (options->ignore_rhosts == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100168 options->ignore_rhosts = 1;
Damien Miller95def091999-11-25 00:26:21 +1100169 if (options->ignore_user_known_hosts == -1)
170 options->ignore_user_known_hosts = 0;
Damien Miller95def091999-11-25 00:26:21 +1100171 if (options->print_motd == -1)
172 options->print_motd = 1;
Ben Lindstrom7bfff362001-03-26 05:45:53 +0000173 if (options->print_lastlog == -1)
174 options->print_lastlog = 1;
Damien Miller95def091999-11-25 00:26:21 +1100175 if (options->x11_forwarding == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100176 options->x11_forwarding = 0;
Damien Miller95def091999-11-25 00:26:21 +1100177 if (options->x11_display_offset == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100178 options->x11_display_offset = 10;
Damien Miller95c249f2002-02-05 12:11:34 +1100179 if (options->x11_use_localhost == -1)
180 options->x11_use_localhost = 1;
Damien Millerd3a18572000-06-07 19:55:44 +1000181 if (options->xauth_location == NULL)
Ben Lindstrom1bf11f62001-06-09 01:48:01 +0000182 options->xauth_location = _PATH_XAUTH;
Damien Miller95def091999-11-25 00:26:21 +1100183 if (options->strict_modes == -1)
184 options->strict_modes = 1;
Damien Miller12c150e2003-12-17 16:31:10 +1100185 if (options->tcp_keep_alive == -1)
186 options->tcp_keep_alive = 1;
Damien Millerfcd93202002-02-05 12:26:34 +1100187 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
Damien Miller95def091999-11-25 00:26:21 +1100188 options->log_facility = SYSLOG_FACILITY_AUTH;
Damien Millerfcd93202002-02-05 12:26:34 +1100189 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
Ben Lindstromdb65e8f2001-01-19 04:26:52 +0000190 options->log_level = SYSLOG_LEVEL_INFO;
Damien Miller95def091999-11-25 00:26:21 +1100191 if (options->rhosts_rsa_authentication == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100192 options->rhosts_rsa_authentication = 0;
Ben Lindstrom5eabda32001-04-12 23:34:34 +0000193 if (options->hostbased_authentication == -1)
194 options->hostbased_authentication = 0;
195 if (options->hostbased_uses_name_from_packet_only == -1)
196 options->hostbased_uses_name_from_packet_only = 0;
Damien Miller95def091999-11-25 00:26:21 +1100197 if (options->rsa_authentication == -1)
198 options->rsa_authentication = 1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100199 if (options->pubkey_authentication == -1)
200 options->pubkey_authentication = 1;
Damien Miller95def091999-11-25 00:26:21 +1100201 if (options->kerberos_authentication == -1)
Damien Millerd7de14b2002-04-23 21:04:51 +1000202 options->kerberos_authentication = 0;
Damien Miller95def091999-11-25 00:26:21 +1100203 if (options->kerberos_or_local_passwd == -1)
204 options->kerberos_or_local_passwd = 1;
205 if (options->kerberos_ticket_cleanup == -1)
206 options->kerberos_ticket_cleanup = 1;
Darren Tucker22ef5082003-12-31 11:37:34 +1100207 if (options->kerberos_get_afs_token == -1)
208 options->kerberos_get_afs_token = 0;
Darren Tucker0efd1552003-08-26 11:49:55 +1000209 if (options->gss_authentication == -1)
210 options->gss_authentication = 0;
211 if (options->gss_cleanup_creds == -1)
212 options->gss_cleanup_creds = 1;
Damien Miller95def091999-11-25 00:26:21 +1100213 if (options->password_authentication == -1)
214 options->password_authentication = 1;
Damien Miller874d77b2000-10-14 16:23:11 +1100215 if (options->kbd_interactive_authentication == -1)
216 options->kbd_interactive_authentication = 0;
Ben Lindstrom551ea372001-06-05 18:56:16 +0000217 if (options->challenge_response_authentication == -1)
218 options->challenge_response_authentication = 1;
Damien Miller95def091999-11-25 00:26:21 +1100219 if (options->permit_empty_passwd == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100220 options->permit_empty_passwd = 0;
Ben Lindstrom5d860f02002-08-01 01:28:38 +0000221 if (options->permit_user_env == -1)
222 options->permit_user_env = 0;
Damien Miller95def091999-11-25 00:26:21 +1100223 if (options->use_login == -1)
224 options->use_login = 0;
Ben Lindstrom23e0f662002-06-21 01:09:47 +0000225 if (options->compression == -1)
Damien Miller9786e6e2005-07-26 21:54:56 +1000226 options->compression = COMP_DELAYED;
Damien Miller50a41ed2000-10-16 12:14:42 +1100227 if (options->allow_tcp_forwarding == -1)
228 options->allow_tcp_forwarding = 1;
Damien Miller4f755cd2008-05-19 14:57:41 +1000229 if (options->allow_agent_forwarding == -1)
230 options->allow_agent_forwarding = 1;
Damien Millere247cc42000-05-07 12:03:14 +1000231 if (options->gateway_ports == -1)
232 options->gateway_ports = 0;
Damien Miller37023962000-07-11 17:31:38 +1000233 if (options->max_startups == -1)
234 options->max_startups = 10;
Damien Miller942da032000-08-18 13:59:06 +1000235 if (options->max_startups_rate == -1)
236 options->max_startups_rate = 100; /* 100% */
237 if (options->max_startups_begin == -1)
238 options->max_startups_begin = options->max_startups;
Darren Tucker89413db2004-05-24 10:36:23 +1000239 if (options->max_authtries == -1)
240 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
Damien Miller7207f642008-05-19 15:34:50 +1000241 if (options->max_sessions == -1)
242 options->max_sessions = DEFAULT_SESSIONS_MAX;
Damien Miller3a961dc2003-06-03 10:25:48 +1000243 if (options->use_dns == -1)
244 options->use_dns = 1;
Ben Lindstrom5744dc42001-04-13 23:28:01 +0000245 if (options->client_alive_interval == -1)
Damien Miller9f0f5c62001-12-21 14:45:46 +1100246 options->client_alive_interval = 0;
Ben Lindstrom5744dc42001-04-13 23:28:01 +0000247 if (options->client_alive_count_max == -1)
248 options->client_alive_count_max = 3;
Damien Miller75413ac2001-11-12 11:14:35 +1100249 if (options->authorized_keys_file2 == NULL) {
250 /* authorized_keys_file2 falls back to authorized_keys_file */
251 if (options->authorized_keys_file != NULL)
252 options->authorized_keys_file2 = options->authorized_keys_file;
253 else
254 options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
255 }
256 if (options->authorized_keys_file == NULL)
257 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
Damien Millerd27b9472005-12-13 19:29:02 +1100258 if (options->permit_tun == -1)
Damien Miller7b58e802005-12-13 19:33:19 +1100259 options->permit_tun = SSH_TUNMODE_NO;
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000260
Ben Lindstromfb62a692002-06-06 19:47:11 +0000261 /* Turn privilege separation on by default */
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000262 if (use_privsep == -1)
Ben Lindstromfb62a692002-06-06 19:47:11 +0000263 use_privsep = 1;
Damien Miller4903eb42002-06-21 16:20:44 +1000264
Tim Rice40017b02002-07-14 13:36:49 -0700265#ifndef HAVE_MMAP
Damien Miller4903eb42002-06-21 16:20:44 +1000266 if (use_privsep && options->compression == 1) {
267 error("This platform does not support both privilege "
268 "separation and compression");
269 error("Compression disabled");
270 options->compression = 0;
271 }
272#endif
273
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000274}
275
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000276/* Keyword tokens. */
Damien Miller95def091999-11-25 00:26:21 +1100277typedef enum {
278 sBadOption, /* == unknown option */
Damien Miller726273e2001-11-12 11:40:11 +1100279 /* Portable-specific options */
Damien Miller4e448a32003-05-14 15:11:48 +1000280 sUsePAM,
Damien Miller726273e2001-11-12 11:40:11 +1100281 /* Standard Options */
Damien Miller95def091999-11-25 00:26:21 +1100282 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
283 sPermitRootLogin, sLogFacility, sLogLevel,
Darren Tuckerec960f22003-08-13 20:37:05 +1000284 sRhostsRSAAuthentication, sRSAAuthentication,
Damien Miller95def091999-11-25 00:26:21 +1100285 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
Darren Tucker22ef5082003-12-31 11:37:34 +1100286 sKerberosGetAFSToken,
Darren Tucker6aaa58c2003-08-02 22:24:49 +1000287 sKerberosTgtPassing, sChallengeResponseAuthentication,
Darren Tucker0f383232005-01-20 10:57:56 +1100288 sPasswordAuthentication, sKbdInteractiveAuthentication,
289 sListenAddress, sAddressFamily,
Ben Lindstrom7bfff362001-03-26 05:45:53 +0000290 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
Damien Miller95c249f2002-02-05 12:11:34 +1100291 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
Damien Miller12c150e2003-12-17 16:31:10 +1100292 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
Ben Lindstrom5d860f02002-08-01 01:28:38 +0000293 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
Damien Miller50a41ed2000-10-16 12:14:42 +1100294 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
Ben Lindstrom06b33aa2001-02-15 03:01:59 +0000295 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
Darren Tucker89413db2004-05-24 10:36:23 +1000296 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
Damien Miller7207f642008-05-19 15:34:50 +1000297 sMaxStartups, sMaxAuthTries, sMaxSessions,
Damien Miller3a961dc2003-06-03 10:25:48 +1000298 sBanner, sUseDNS, sHostbasedAuthentication,
Damien Miller9f0f5c62001-12-21 14:45:46 +1100299 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
Ben Lindstrombfb3a0e2001-06-05 20:25:05 +0000300 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
Damien Millerd27b9472005-12-13 19:29:02 +1100301 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
Damien Millerd8cb1f12008-02-10 22:40:12 +1100302 sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
Damien Miller4f755cd2008-05-19 14:57:41 +1000303 sUsePrivilegeSeparation, sAllowAgentForwarding,
Damien Millerf9b3feb2003-05-16 11:38:32 +1000304 sDeprecated, sUnsupported
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000305} ServerOpCodes;
306
Darren Tucker45150472006-07-12 22:34:17 +1000307#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
308#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
309#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
310
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000311/* Textual representation of the tokens. */
Damien Miller95def091999-11-25 00:26:21 +1100312static struct {
313 const char *name;
314 ServerOpCodes opcode;
Darren Tucker45150472006-07-12 22:34:17 +1000315 u_int flags;
Damien Miller95def091999-11-25 00:26:21 +1100316} keywords[] = {
Damien Miller726273e2001-11-12 11:40:11 +1100317 /* Portable-specific options */
Damien Miller6ac2c482003-05-16 11:42:35 +1000318#ifdef USE_PAM
Darren Tucker45150472006-07-12 22:34:17 +1000319 { "usepam", sUsePAM, SSHCFG_GLOBAL },
Damien Miller6ac2c482003-05-16 11:42:35 +1000320#else
Darren Tucker45150472006-07-12 22:34:17 +1000321 { "usepam", sUnsupported, SSHCFG_GLOBAL },
Damien Miller6ac2c482003-05-16 11:42:35 +1000322#endif
Darren Tucker45150472006-07-12 22:34:17 +1000323 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
Damien Miller726273e2001-11-12 11:40:11 +1100324 /* Standard Options */
Darren Tucker45150472006-07-12 22:34:17 +1000325 { "port", sPort, SSHCFG_GLOBAL },
326 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
327 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
328 { "pidfile", sPidFile, SSHCFG_GLOBAL },
329 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
330 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
331 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
Darren Tucker15f94272008-01-01 20:36:56 +1100332 { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000333 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
334 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
335 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
Darren Tucker1629c072007-02-19 22:25:37 +1100336 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
337 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000338 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
Darren Tucker1629c072007-02-19 22:25:37 +1100339 { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
340 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000341 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
Darren Tucker6aaa58c2003-08-02 22:24:49 +1000342#ifdef KRB5
Darren Tucker1629c072007-02-19 22:25:37 +1100343 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000344 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
345 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
Darren Tucker3c78c5e2004-01-23 22:03:10 +1100346#ifdef USE_AFS
Darren Tucker45150472006-07-12 22:34:17 +1000347 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
Damien Millerf9b3feb2003-05-16 11:38:32 +1000348#else
Darren Tucker45150472006-07-12 22:34:17 +1000349 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
Darren Tucker409cb322004-01-05 22:36:51 +1100350#endif
351#else
Darren Tucker1629c072007-02-19 22:25:37 +1100352 { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000353 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
354 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
355 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
Damien Millerf9b3feb2003-05-16 11:38:32 +1000356#endif
Darren Tucker45150472006-07-12 22:34:17 +1000357 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
358 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
Darren Tucker0efd1552003-08-26 11:49:55 +1000359#ifdef GSSAPI
Darren Tucker1629c072007-02-19 22:25:37 +1100360 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000361 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
Darren Tucker0efd1552003-08-26 11:49:55 +1000362#else
Darren Tucker1629c072007-02-19 22:25:37 +1100363 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000364 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
Darren Tucker0efd1552003-08-26 11:49:55 +1000365#endif
Darren Tucker1629c072007-02-19 22:25:37 +1100366 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
367 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
Darren Tucker1d75f222007-03-01 21:31:28 +1100368 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
Darren Tucker45150472006-07-12 22:34:17 +1000369 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
370 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
371 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
372 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
373 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
374 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
375 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
376 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
Damien Millerd1de9952006-07-24 14:05:48 +1000377 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
378 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
379 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000380 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
381 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
382 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
383 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
384 { "uselogin", sUseLogin, SSHCFG_GLOBAL },
385 { "compression", sCompression, SSHCFG_GLOBAL },
386 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
387 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
388 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
Damien Miller4f755cd2008-05-19 14:57:41 +1000389 { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000390 { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
391 { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
392 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
393 { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
394 { "ciphers", sCiphers, SSHCFG_GLOBAL },
395 { "macs", sMacs, SSHCFG_GLOBAL },
396 { "protocol", sProtocol, SSHCFG_GLOBAL },
397 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
398 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
399 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
400 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
Damien Miller7207f642008-05-19 15:34:50 +1000401 { "maxsessions", sMaxSessions, SSHCFG_ALL },
Darren Tucker1629c072007-02-19 22:25:37 +1100402 { "banner", sBanner, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000403 { "usedns", sUseDNS, SSHCFG_GLOBAL },
404 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
405 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
406 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
407 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
408 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
409 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
410 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
411 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
412 { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
Damien Miller9b439df2006-07-24 14:04:00 +1000413 { "match", sMatch, SSHCFG_ALL },
414 { "permitopen", sPermitOpen, SSHCFG_ALL },
Damien Millere2754432006-07-24 14:06:47 +1000415 { "forcecommand", sForceCommand, SSHCFG_ALL },
Damien Millerd8cb1f12008-02-10 22:40:12 +1100416 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000417 { NULL, sBadOption, 0 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000418};
419
Damien Miller5428f641999-11-25 11:54:57 +1100420/*
Ben Lindstrom3704c262001-04-02 18:20:03 +0000421 * Returns the number of the token pointed to by cp or sBadOption.
Damien Miller5428f641999-11-25 11:54:57 +1100422 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000423
Damien Miller4af51302000-04-16 11:18:38 +1000424static ServerOpCodes
Damien Miller95def091999-11-25 00:26:21 +1100425parse_token(const char *cp, const char *filename,
Darren Tucker45150472006-07-12 22:34:17 +1000426 int linenum, u_int *flags)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000427{
Ben Lindstrom46c16222000-12-22 01:43:59 +0000428 u_int i;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000429
Damien Miller95def091999-11-25 00:26:21 +1100430 for (i = 0; keywords[i].name; i++)
Darren Tucker45150472006-07-12 22:34:17 +1000431 if (strcasecmp(cp, keywords[i].name) == 0) {
432 *flags = keywords[i].flags;
Damien Miller95def091999-11-25 00:26:21 +1100433 return keywords[i].opcode;
Darren Tucker45150472006-07-12 22:34:17 +1000434 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000435
Ben Lindstromb5cdc662001-04-16 02:13:26 +0000436 error("%s: line %d: Bad configuration option: %s",
437 filename, linenum, cp);
Damien Miller95def091999-11-25 00:26:21 +1100438 return sBadOption;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000439}
440
Ben Lindstrombba81212001-06-25 05:01:22 +0000441static void
Ben Lindstrom19066a12001-04-12 23:39:26 +0000442add_listen_addr(ServerOptions *options, char *addr, u_short port)
Damien Miller34132e52000-01-14 15:45:46 +1100443{
Damien Millereccb9de2005-06-17 12:59:34 +1000444 u_int i;
Damien Miller34132e52000-01-14 15:45:46 +1100445
446 if (options->num_ports == 0)
447 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
Darren Tucker0f383232005-01-20 10:57:56 +1100448 if (options->address_family == -1)
449 options->address_family = AF_UNSPEC;
Ben Lindstrom19066a12001-04-12 23:39:26 +0000450 if (port == 0)
Ben Lindstromc510af42001-04-07 17:25:48 +0000451 for (i = 0; i < options->num_ports; i++)
452 add_one_listen_addr(options, addr, options->ports[i]);
453 else
Ben Lindstrom19066a12001-04-12 23:39:26 +0000454 add_one_listen_addr(options, addr, port);
Ben Lindstromc510af42001-04-07 17:25:48 +0000455}
456
Ben Lindstrombba81212001-06-25 05:01:22 +0000457static void
Ben Lindstromc510af42001-04-07 17:25:48 +0000458add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
459{
460 struct addrinfo hints, *ai, *aitop;
461 char strport[NI_MAXSERV];
462 int gaierr;
463
464 memset(&hints, 0, sizeof(hints));
Darren Tucker0f383232005-01-20 10:57:56 +1100465 hints.ai_family = options->address_family;
Ben Lindstromc510af42001-04-07 17:25:48 +0000466 hints.ai_socktype = SOCK_STREAM;
467 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
Ben Lindstrome1353632002-06-23 21:29:23 +0000468 snprintf(strport, sizeof strport, "%u", port);
Ben Lindstromc510af42001-04-07 17:25:48 +0000469 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
470 fatal("bad addr or host: %s (%s)",
471 addr ? addr : "<NULL>",
Darren Tucker4abde772007-12-29 02:43:51 +1100472 ssh_gai_strerror(gaierr));
Ben Lindstromc510af42001-04-07 17:25:48 +0000473 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
474 ;
475 ai->ai_next = options->listen_addrs;
476 options->listen_addrs = aitop;
Damien Miller34132e52000-01-14 15:45:46 +1100477}
478
Darren Tucker45150472006-07-12 22:34:17 +1000479/*
480 * The strategy for the Match blocks is that the config file is parsed twice.
481 *
482 * The first time is at startup. activep is initialized to 1 and the
483 * directives in the global context are processed and acted on. Hitting a
484 * Match directive unsets activep and the directives inside the block are
485 * checked for syntax only.
486 *
487 * The second time is after a connection has been established but before
488 * authentication. activep is initialized to 2 and global config directives
489 * are ignored since they have already been processed. If the criteria in a
490 * Match block is met, activep is set and the subsequent directives
491 * processed and actioned until EOF or another Match block unsets it. Any
492 * options set are copied into the main server config.
493 *
494 * Potential additions/improvements:
495 * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
496 *
497 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
498 * Match Address 192.168.0.*
499 * Tag trusted
500 * Match Group wheel
501 * Tag trusted
502 * Match Tag trusted
503 * AllowTcpForwarding yes
504 * GatewayPorts clientspecified
505 * [...]
506 *
507 * - Add a PermittedChannelRequests directive
508 * Match Group shell
509 * PermittedChannelRequests session,forwarded-tcpip
510 */
511
512static int
Damien Miller565ca3f2006-08-19 00:23:15 +1000513match_cfg_line_group(const char *grps, int line, const char *user)
514{
515 int result = 0;
516 u_int ngrps = 0;
517 char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
518 struct passwd *pw;
519
520 /*
521 * Even if we do not have a user yet, we still need to check for
522 * valid syntax.
523 */
524 arg = cp = xstrdup(grps);
525 while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
526 if (ngrps >= MAX_MATCH_GROUPS) {
527 error("line %d: too many groups in Match Group", line);
528 result = -1;
529 goto out;
530 }
531 grplist[ngrps++] = p;
532 }
533
534 if (user == NULL)
535 goto out;
536
537 if ((pw = getpwnam(user)) == NULL) {
538 debug("Can't match group at line %d because user %.100s does "
539 "not exist", line, user);
540 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
541 debug("Can't Match group because user %.100s not in any group "
542 "at line %d", user, line);
543 } else if (ga_match(grplist, ngrps) != 1) {
544 debug("user %.100s does not match group %.100s at line %d",
545 user, arg, line);
546 } else {
547 debug("user %.100s matched group %.100s at line %d", user,
548 arg, line);
549 result = 1;
550 }
551out:
552 ga_free();
553 xfree(arg);
554 return result;
555}
556
557static int
Darren Tucker45150472006-07-12 22:34:17 +1000558match_cfg_line(char **condition, int line, const char *user, const char *host,
559 const char *address)
560{
561 int result = 1;
562 char *arg, *attrib, *cp = *condition;
563 size_t len;
564
565 if (user == NULL)
566 debug3("checking syntax for 'Match %s'", cp);
567 else
568 debug3("checking match for '%s' user %s host %s addr %s", cp,
569 user ? user : "(null)", host ? host : "(null)",
570 address ? address : "(null)");
571
572 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
573 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
574 error("Missing Match criteria for %s", attrib);
575 return -1;
576 }
577 len = strlen(arg);
578 if (strcasecmp(attrib, "user") == 0) {
579 if (!user) {
580 result = 0;
581 continue;
582 }
583 if (match_pattern_list(user, arg, len, 0) != 1)
584 result = 0;
585 else
586 debug("user %.100s matched 'User %.100s' at "
587 "line %d", user, arg, line);
Damien Miller565ca3f2006-08-19 00:23:15 +1000588 } else if (strcasecmp(attrib, "group") == 0) {
589 switch (match_cfg_line_group(arg, line, user)) {
590 case -1:
591 return -1;
592 case 0:
593 result = 0;
594 }
Darren Tucker45150472006-07-12 22:34:17 +1000595 } else if (strcasecmp(attrib, "host") == 0) {
596 if (!host) {
597 result = 0;
598 continue;
599 }
600 if (match_hostname(host, arg, len) != 1)
601 result = 0;
602 else
603 debug("connection from %.100s matched 'Host "
604 "%.100s' at line %d", host, arg, line);
605 } else if (strcasecmp(attrib, "address") == 0) {
Darren Tucker45150472006-07-12 22:34:17 +1000606 if (!address) {
607 result = 0;
608 continue;
609 }
610 if (match_hostname(address, arg, len) != 1)
611 result = 0;
612 else
613 debug("connection from %.100s matched 'Address "
614 "%.100s' at line %d", address, arg, line);
615 } else {
616 error("Unsupported Match attribute %s", attrib);
617 return -1;
618 }
619 }
620 if (user != NULL)
621 debug3("match %sfound", result ? "" : "not ");
622 *condition = cp;
623 return result;
624}
625
Damien Millere2754432006-07-24 14:06:47 +1000626#define WHITESPACE " \t\r\n"
627
Ben Lindstromade03f62001-12-06 18:22:17 +0000628int
629process_server_config_line(ServerOptions *options, char *line,
Darren Tucker45150472006-07-12 22:34:17 +1000630 const char *filename, int linenum, int *activep, const char *user,
631 const char *host, const char *address)
Ben Lindstromade03f62001-12-06 18:22:17 +0000632{
633 char *cp, **charptr, *arg, *p;
Darren Tucker45150472006-07-12 22:34:17 +1000634 int cmdline = 0, *intptr, value, n;
Darren Tucker1e44c5d2008-01-01 20:32:26 +1100635 SyslogFacility *log_facility_ptr;
636 LogLevel *log_level_ptr;
Ben Lindstromade03f62001-12-06 18:22:17 +0000637 ServerOpCodes opcode;
Damien Millerf91ee4c2005-03-01 21:24:33 +1100638 u_short port;
Darren Tucker45150472006-07-12 22:34:17 +1000639 u_int i, flags = 0;
Damien Miller917f9b62006-07-10 20:36:47 +1000640 size_t len;
Ben Lindstromade03f62001-12-06 18:22:17 +0000641
642 cp = line;
Damien Miller78f16cb2006-03-26 13:54:37 +1100643 if ((arg = strdelim(&cp)) == NULL)
Damien Miller928b2362006-03-26 13:53:32 +1100644 return 0;
Ben Lindstromade03f62001-12-06 18:22:17 +0000645 /* Ignore leading whitespace */
646 if (*arg == '\0')
647 arg = strdelim(&cp);
648 if (!arg || !*arg || *arg == '#')
649 return 0;
650 intptr = NULL;
651 charptr = NULL;
Darren Tucker45150472006-07-12 22:34:17 +1000652 opcode = parse_token(arg, filename, linenum, &flags);
653
654 if (activep == NULL) { /* We are processing a command line directive */
655 cmdline = 1;
656 activep = &cmdline;
657 }
658 if (*activep && opcode != sMatch)
659 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
660 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
661 if (user == NULL) {
662 fatal("%s line %d: Directive '%s' is not allowed "
663 "within a Match block", filename, linenum, arg);
664 } else { /* this is a directive we have already processed */
665 while (arg)
666 arg = strdelim(&cp);
667 return 0;
668 }
669 }
670
Ben Lindstromade03f62001-12-06 18:22:17 +0000671 switch (opcode) {
672 /* Portable-specific options */
Damien Miller4e448a32003-05-14 15:11:48 +1000673 case sUsePAM:
674 intptr = &options->use_pam;
Ben Lindstromade03f62001-12-06 18:22:17 +0000675 goto parse_flag;
676
677 /* Standard Options */
678 case sBadOption:
679 return -1;
680 case sPort:
681 /* ignore ports from configfile if cmdline specifies ports */
682 if (options->ports_from_cmdline)
683 return 0;
684 if (options->listen_addrs != NULL)
685 fatal("%s line %d: ports must be specified before "
Damien Miller4fbf08a2002-01-22 23:35:09 +1100686 "ListenAddress.", filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +0000687 if (options->num_ports >= MAX_PORTS)
688 fatal("%s line %d: too many ports.",
689 filename, linenum);
690 arg = strdelim(&cp);
691 if (!arg || *arg == '\0')
692 fatal("%s line %d: missing port number.",
693 filename, linenum);
694 options->ports[options->num_ports++] = a2port(arg);
695 if (options->ports[options->num_ports-1] == 0)
696 fatal("%s line %d: Badly formatted port number.",
697 filename, linenum);
698 break;
699
700 case sServerKeyBits:
701 intptr = &options->server_key_bits;
Damien Miller7207f642008-05-19 15:34:50 +1000702 parse_int:
Ben Lindstromade03f62001-12-06 18:22:17 +0000703 arg = strdelim(&cp);
704 if (!arg || *arg == '\0')
705 fatal("%s line %d: missing integer value.",
706 filename, linenum);
707 value = atoi(arg);
Darren Tucker45150472006-07-12 22:34:17 +1000708 if (*activep && *intptr == -1)
Ben Lindstromade03f62001-12-06 18:22:17 +0000709 *intptr = value;
710 break;
711
712 case sLoginGraceTime:
713 intptr = &options->login_grace_time;
Damien Miller7207f642008-05-19 15:34:50 +1000714 parse_time:
Ben Lindstromade03f62001-12-06 18:22:17 +0000715 arg = strdelim(&cp);
716 if (!arg || *arg == '\0')
717 fatal("%s line %d: missing time value.",
718 filename, linenum);
719 if ((value = convtime(arg)) == -1)
720 fatal("%s line %d: invalid time value.",
721 filename, linenum);
722 if (*intptr == -1)
723 *intptr = value;
724 break;
725
726 case sKeyRegenerationTime:
727 intptr = &options->key_regeneration_time;
728 goto parse_time;
729
730 case sListenAddress:
731 arg = strdelim(&cp);
Damien Millerf91ee4c2005-03-01 21:24:33 +1100732 if (arg == NULL || *arg == '\0')
733 fatal("%s line %d: missing address",
Ben Lindstromade03f62001-12-06 18:22:17 +0000734 filename, linenum);
Damien Miller203c7052005-08-12 22:11:37 +1000735 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
736 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
737 && strchr(p+1, ':') != NULL) {
738 add_listen_addr(options, arg, 0);
739 break;
740 }
Damien Millerf91ee4c2005-03-01 21:24:33 +1100741 p = hpdelim(&arg);
742 if (p == NULL)
743 fatal("%s line %d: bad address:port usage",
744 filename, linenum);
745 p = cleanhostname(p);
746 if (arg == NULL)
747 port = 0;
748 else if ((port = a2port(arg)) == 0)
749 fatal("%s line %d: bad port number", filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +0000750
Damien Millerf91ee4c2005-03-01 21:24:33 +1100751 add_listen_addr(options, p, port);
752
Ben Lindstromade03f62001-12-06 18:22:17 +0000753 break;
754
Darren Tucker0f383232005-01-20 10:57:56 +1100755 case sAddressFamily:
756 arg = strdelim(&cp);
Damien Miller17b23d82005-05-26 12:11:56 +1000757 if (!arg || *arg == '\0')
758 fatal("%s line %d: missing address family.",
759 filename, linenum);
Darren Tucker0f383232005-01-20 10:57:56 +1100760 intptr = &options->address_family;
761 if (options->listen_addrs != NULL)
762 fatal("%s line %d: address family must be specified before "
763 "ListenAddress.", filename, linenum);
764 if (strcasecmp(arg, "inet") == 0)
765 value = AF_INET;
766 else if (strcasecmp(arg, "inet6") == 0)
767 value = AF_INET6;
768 else if (strcasecmp(arg, "any") == 0)
769 value = AF_UNSPEC;
770 else
771 fatal("%s line %d: unsupported address family \"%s\".",
772 filename, linenum, arg);
773 if (*intptr == -1)
774 *intptr = value;
775 break;
776
Ben Lindstromade03f62001-12-06 18:22:17 +0000777 case sHostKeyFile:
778 intptr = &options->num_host_key_files;
779 if (*intptr >= MAX_HOSTKEYS)
780 fatal("%s line %d: too many host keys specified (max %d).",
781 filename, linenum, MAX_HOSTKEYS);
782 charptr = &options->host_key_files[*intptr];
Damien Miller7207f642008-05-19 15:34:50 +1000783 parse_filename:
Ben Lindstromade03f62001-12-06 18:22:17 +0000784 arg = strdelim(&cp);
785 if (!arg || *arg == '\0')
786 fatal("%s line %d: missing file name.",
787 filename, linenum);
Darren Tucker45150472006-07-12 22:34:17 +1000788 if (*activep && *charptr == NULL) {
Ben Lindstromade03f62001-12-06 18:22:17 +0000789 *charptr = tilde_expand_filename(arg, getuid());
790 /* increase optional counter */
791 if (intptr != NULL)
792 *intptr = *intptr + 1;
793 }
794 break;
795
796 case sPidFile:
797 charptr = &options->pid_file;
798 goto parse_filename;
799
800 case sPermitRootLogin:
801 intptr = &options->permit_root_login;
802 arg = strdelim(&cp);
803 if (!arg || *arg == '\0')
804 fatal("%s line %d: missing yes/"
805 "without-password/forced-commands-only/no "
806 "argument.", filename, linenum);
807 value = 0; /* silence compiler */
808 if (strcmp(arg, "without-password") == 0)
809 value = PERMIT_NO_PASSWD;
810 else if (strcmp(arg, "forced-commands-only") == 0)
811 value = PERMIT_FORCED_ONLY;
812 else if (strcmp(arg, "yes") == 0)
813 value = PERMIT_YES;
814 else if (strcmp(arg, "no") == 0)
815 value = PERMIT_NO;
816 else
817 fatal("%s line %d: Bad yes/"
818 "without-password/forced-commands-only/no "
819 "argument: %s", filename, linenum, arg);
Darren Tucker15f94272008-01-01 20:36:56 +1100820 if (*activep && *intptr == -1)
Ben Lindstromade03f62001-12-06 18:22:17 +0000821 *intptr = value;
822 break;
823
824 case sIgnoreRhosts:
825 intptr = &options->ignore_rhosts;
Damien Miller7207f642008-05-19 15:34:50 +1000826 parse_flag:
Ben Lindstromade03f62001-12-06 18:22:17 +0000827 arg = strdelim(&cp);
828 if (!arg || *arg == '\0')
829 fatal("%s line %d: missing yes/no argument.",
830 filename, linenum);
831 value = 0; /* silence compiler */
832 if (strcmp(arg, "yes") == 0)
833 value = 1;
834 else if (strcmp(arg, "no") == 0)
835 value = 0;
836 else
837 fatal("%s line %d: Bad yes/no argument: %s",
838 filename, linenum, arg);
Darren Tucker45150472006-07-12 22:34:17 +1000839 if (*activep && *intptr == -1)
Ben Lindstromade03f62001-12-06 18:22:17 +0000840 *intptr = value;
841 break;
842
843 case sIgnoreUserKnownHosts:
844 intptr = &options->ignore_user_known_hosts;
845 goto parse_flag;
846
Ben Lindstromade03f62001-12-06 18:22:17 +0000847 case sRhostsRSAAuthentication:
848 intptr = &options->rhosts_rsa_authentication;
849 goto parse_flag;
850
851 case sHostbasedAuthentication:
852 intptr = &options->hostbased_authentication;
853 goto parse_flag;
854
855 case sHostbasedUsesNameFromPacketOnly:
856 intptr = &options->hostbased_uses_name_from_packet_only;
857 goto parse_flag;
858
859 case sRSAAuthentication:
860 intptr = &options->rsa_authentication;
861 goto parse_flag;
862
863 case sPubkeyAuthentication:
864 intptr = &options->pubkey_authentication;
865 goto parse_flag;
Damien Miller2aa0ab42003-05-15 12:05:28 +1000866
Ben Lindstromade03f62001-12-06 18:22:17 +0000867 case sKerberosAuthentication:
868 intptr = &options->kerberos_authentication;
869 goto parse_flag;
870
871 case sKerberosOrLocalPasswd:
872 intptr = &options->kerberos_or_local_passwd;
873 goto parse_flag;
874
875 case sKerberosTicketCleanup:
876 intptr = &options->kerberos_ticket_cleanup;
877 goto parse_flag;
Damien Miller2aa0ab42003-05-15 12:05:28 +1000878
Darren Tucker22ef5082003-12-31 11:37:34 +1100879 case sKerberosGetAFSToken:
880 intptr = &options->kerberos_get_afs_token;
881 goto parse_flag;
882
Darren Tucker0efd1552003-08-26 11:49:55 +1000883 case sGssAuthentication:
884 intptr = &options->gss_authentication;
885 goto parse_flag;
886
887 case sGssCleanupCreds:
888 intptr = &options->gss_cleanup_creds;
889 goto parse_flag;
890
Ben Lindstromade03f62001-12-06 18:22:17 +0000891 case sPasswordAuthentication:
892 intptr = &options->password_authentication;
893 goto parse_flag;
894
895 case sKbdInteractiveAuthentication:
896 intptr = &options->kbd_interactive_authentication;
897 goto parse_flag;
898
899 case sChallengeResponseAuthentication:
900 intptr = &options->challenge_response_authentication;
901 goto parse_flag;
902
903 case sPrintMotd:
904 intptr = &options->print_motd;
905 goto parse_flag;
906
907 case sPrintLastLog:
908 intptr = &options->print_lastlog;
909 goto parse_flag;
910
911 case sX11Forwarding:
912 intptr = &options->x11_forwarding;
913 goto parse_flag;
914
915 case sX11DisplayOffset:
916 intptr = &options->x11_display_offset;
917 goto parse_int;
918
Damien Miller95c249f2002-02-05 12:11:34 +1100919 case sX11UseLocalhost:
920 intptr = &options->x11_use_localhost;
921 goto parse_flag;
922
Ben Lindstromade03f62001-12-06 18:22:17 +0000923 case sXAuthLocation:
924 charptr = &options->xauth_location;
925 goto parse_filename;
926
927 case sStrictModes:
928 intptr = &options->strict_modes;
929 goto parse_flag;
930
Damien Miller12c150e2003-12-17 16:31:10 +1100931 case sTCPKeepAlive:
932 intptr = &options->tcp_keep_alive;
Ben Lindstromade03f62001-12-06 18:22:17 +0000933 goto parse_flag;
934
935 case sEmptyPasswd:
936 intptr = &options->permit_empty_passwd;
937 goto parse_flag;
938
Ben Lindstrom5d860f02002-08-01 01:28:38 +0000939 case sPermitUserEnvironment:
940 intptr = &options->permit_user_env;
941 goto parse_flag;
942
Ben Lindstromade03f62001-12-06 18:22:17 +0000943 case sUseLogin:
944 intptr = &options->use_login;
945 goto parse_flag;
946
Ben Lindstrom23e0f662002-06-21 01:09:47 +0000947 case sCompression:
948 intptr = &options->compression;
Damien Miller9786e6e2005-07-26 21:54:56 +1000949 arg = strdelim(&cp);
950 if (!arg || *arg == '\0')
951 fatal("%s line %d: missing yes/no/delayed "
952 "argument.", filename, linenum);
953 value = 0; /* silence compiler */
954 if (strcmp(arg, "delayed") == 0)
955 value = COMP_DELAYED;
956 else if (strcmp(arg, "yes") == 0)
957 value = COMP_ZLIB;
958 else if (strcmp(arg, "no") == 0)
959 value = COMP_NONE;
960 else
961 fatal("%s line %d: Bad yes/no/delayed "
962 "argument: %s", filename, linenum, arg);
963 if (*intptr == -1)
964 *intptr = value;
965 break;
Ben Lindstrom23e0f662002-06-21 01:09:47 +0000966
Ben Lindstromade03f62001-12-06 18:22:17 +0000967 case sGatewayPorts:
968 intptr = &options->gateway_ports;
Damien Millerf91ee4c2005-03-01 21:24:33 +1100969 arg = strdelim(&cp);
970 if (!arg || *arg == '\0')
971 fatal("%s line %d: missing yes/no/clientspecified "
972 "argument.", filename, linenum);
973 value = 0; /* silence compiler */
974 if (strcmp(arg, "clientspecified") == 0)
975 value = 2;
976 else if (strcmp(arg, "yes") == 0)
977 value = 1;
978 else if (strcmp(arg, "no") == 0)
979 value = 0;
980 else
981 fatal("%s line %d: Bad yes/no/clientspecified "
982 "argument: %s", filename, linenum, arg);
Darren Tucker82347a82007-02-25 20:37:52 +1100983 if (*activep && *intptr == -1)
Damien Millerf91ee4c2005-03-01 21:24:33 +1100984 *intptr = value;
985 break;
Ben Lindstromade03f62001-12-06 18:22:17 +0000986
Damien Miller3a961dc2003-06-03 10:25:48 +1000987 case sUseDNS:
988 intptr = &options->use_dns;
Ben Lindstromade03f62001-12-06 18:22:17 +0000989 goto parse_flag;
990
991 case sLogFacility:
Darren Tucker1e44c5d2008-01-01 20:32:26 +1100992 log_facility_ptr = &options->log_facility;
Ben Lindstromade03f62001-12-06 18:22:17 +0000993 arg = strdelim(&cp);
994 value = log_facility_number(arg);
Damien Millerfcd93202002-02-05 12:26:34 +1100995 if (value == SYSLOG_FACILITY_NOT_SET)
Ben Lindstromade03f62001-12-06 18:22:17 +0000996 fatal("%.200s line %d: unsupported log facility '%s'",
997 filename, linenum, arg ? arg : "<NONE>");
Darren Tucker1e44c5d2008-01-01 20:32:26 +1100998 if (*log_facility_ptr == -1)
999 *log_facility_ptr = (SyslogFacility) value;
Ben Lindstromade03f62001-12-06 18:22:17 +00001000 break;
1001
1002 case sLogLevel:
Darren Tucker1e44c5d2008-01-01 20:32:26 +11001003 log_level_ptr = &options->log_level;
Ben Lindstromade03f62001-12-06 18:22:17 +00001004 arg = strdelim(&cp);
1005 value = log_level_number(arg);
Damien Millerfcd93202002-02-05 12:26:34 +11001006 if (value == SYSLOG_LEVEL_NOT_SET)
Ben Lindstromade03f62001-12-06 18:22:17 +00001007 fatal("%.200s line %d: unsupported log level '%s'",
1008 filename, linenum, arg ? arg : "<NONE>");
Darren Tucker1e44c5d2008-01-01 20:32:26 +11001009 if (*log_level_ptr == -1)
1010 *log_level_ptr = (LogLevel) value;
Ben Lindstromade03f62001-12-06 18:22:17 +00001011 break;
1012
1013 case sAllowTcpForwarding:
1014 intptr = &options->allow_tcp_forwarding;
1015 goto parse_flag;
1016
Damien Miller4f755cd2008-05-19 14:57:41 +10001017 case sAllowAgentForwarding:
1018 intptr = &options->allow_agent_forwarding;
1019 goto parse_flag;
1020
Ben Lindstrom7a2073c2002-03-22 02:30:41 +00001021 case sUsePrivilegeSeparation:
1022 intptr = &use_privsep;
1023 goto parse_flag;
1024
Ben Lindstromade03f62001-12-06 18:22:17 +00001025 case sAllowUsers:
1026 while ((arg = strdelim(&cp)) && *arg != '\0') {
1027 if (options->num_allow_users >= MAX_ALLOW_USERS)
1028 fatal("%s line %d: too many allow users.",
1029 filename, linenum);
Ben Lindstrome1353632002-06-23 21:29:23 +00001030 options->allow_users[options->num_allow_users++] =
1031 xstrdup(arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001032 }
1033 break;
1034
1035 case sDenyUsers:
1036 while ((arg = strdelim(&cp)) && *arg != '\0') {
1037 if (options->num_deny_users >= MAX_DENY_USERS)
Damien Miller4dec5d72006-08-05 11:38:40 +10001038 fatal("%s line %d: too many deny users.",
Ben Lindstromade03f62001-12-06 18:22:17 +00001039 filename, linenum);
Ben Lindstrome1353632002-06-23 21:29:23 +00001040 options->deny_users[options->num_deny_users++] =
1041 xstrdup(arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001042 }
1043 break;
1044
1045 case sAllowGroups:
1046 while ((arg = strdelim(&cp)) && *arg != '\0') {
1047 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1048 fatal("%s line %d: too many allow groups.",
1049 filename, linenum);
Ben Lindstrome1353632002-06-23 21:29:23 +00001050 options->allow_groups[options->num_allow_groups++] =
1051 xstrdup(arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001052 }
1053 break;
1054
1055 case sDenyGroups:
1056 while ((arg = strdelim(&cp)) && *arg != '\0') {
1057 if (options->num_deny_groups >= MAX_DENY_GROUPS)
1058 fatal("%s line %d: too many deny groups.",
1059 filename, linenum);
1060 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1061 }
1062 break;
1063
1064 case sCiphers:
1065 arg = strdelim(&cp);
1066 if (!arg || *arg == '\0')
1067 fatal("%s line %d: Missing argument.", filename, linenum);
1068 if (!ciphers_valid(arg))
1069 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1070 filename, linenum, arg ? arg : "<NONE>");
1071 if (options->ciphers == NULL)
1072 options->ciphers = xstrdup(arg);
1073 break;
1074
1075 case sMacs:
1076 arg = strdelim(&cp);
1077 if (!arg || *arg == '\0')
1078 fatal("%s line %d: Missing argument.", filename, linenum);
1079 if (!mac_valid(arg))
1080 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1081 filename, linenum, arg ? arg : "<NONE>");
1082 if (options->macs == NULL)
1083 options->macs = xstrdup(arg);
1084 break;
1085
1086 case sProtocol:
1087 intptr = &options->protocol;
1088 arg = strdelim(&cp);
1089 if (!arg || *arg == '\0')
1090 fatal("%s line %d: Missing argument.", filename, linenum);
1091 value = proto_spec(arg);
1092 if (value == SSH_PROTO_UNKNOWN)
1093 fatal("%s line %d: Bad protocol spec '%s'.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001094 filename, linenum, arg ? arg : "<NONE>");
Ben Lindstromade03f62001-12-06 18:22:17 +00001095 if (*intptr == SSH_PROTO_UNKNOWN)
1096 *intptr = value;
1097 break;
1098
1099 case sSubsystem:
1100 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1101 fatal("%s line %d: too many subsystems defined.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001102 filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +00001103 }
1104 arg = strdelim(&cp);
1105 if (!arg || *arg == '\0')
1106 fatal("%s line %d: Missing subsystem name.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001107 filename, linenum);
Darren Tucker45150472006-07-12 22:34:17 +10001108 if (!*activep) {
1109 arg = strdelim(&cp);
1110 break;
1111 }
Ben Lindstromade03f62001-12-06 18:22:17 +00001112 for (i = 0; i < options->num_subsystems; i++)
1113 if (strcmp(arg, options->subsystem_name[i]) == 0)
1114 fatal("%s line %d: Subsystem '%s' already defined.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001115 filename, linenum, arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001116 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1117 arg = strdelim(&cp);
1118 if (!arg || *arg == '\0')
1119 fatal("%s line %d: Missing subsystem command.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001120 filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +00001121 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
Damien Miller917f9b62006-07-10 20:36:47 +10001122
1123 /* Collect arguments (separate to executable) */
1124 p = xstrdup(arg);
1125 len = strlen(p) + 1;
1126 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1127 len += 1 + strlen(arg);
1128 p = xrealloc(p, 1, len);
1129 strlcat(p, " ", len);
1130 strlcat(p, arg, len);
1131 }
1132 options->subsystem_args[options->num_subsystems] = p;
Ben Lindstromade03f62001-12-06 18:22:17 +00001133 options->num_subsystems++;
1134 break;
1135
1136 case sMaxStartups:
1137 arg = strdelim(&cp);
1138 if (!arg || *arg == '\0')
1139 fatal("%s line %d: Missing MaxStartups spec.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001140 filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +00001141 if ((n = sscanf(arg, "%d:%d:%d",
1142 &options->max_startups_begin,
1143 &options->max_startups_rate,
1144 &options->max_startups)) == 3) {
1145 if (options->max_startups_begin >
1146 options->max_startups ||
1147 options->max_startups_rate > 100 ||
1148 options->max_startups_rate < 1)
1149 fatal("%s line %d: Illegal MaxStartups spec.",
1150 filename, linenum);
1151 } else if (n != 1)
1152 fatal("%s line %d: Illegal MaxStartups spec.",
1153 filename, linenum);
1154 else
1155 options->max_startups = options->max_startups_begin;
1156 break;
1157
Darren Tucker89413db2004-05-24 10:36:23 +10001158 case sMaxAuthTries:
1159 intptr = &options->max_authtries;
1160 goto parse_int;
1161
Damien Miller7207f642008-05-19 15:34:50 +10001162 case sMaxSessions:
1163 intptr = &options->max_sessions;
1164 goto parse_int;
1165
Ben Lindstromade03f62001-12-06 18:22:17 +00001166 case sBanner:
1167 charptr = &options->banner;
1168 goto parse_filename;
Damien Millerd8cb1f12008-02-10 22:40:12 +11001169
Ben Lindstromade03f62001-12-06 18:22:17 +00001170 /*
1171 * These options can contain %X options expanded at
1172 * connect time, so that you can specify paths like:
1173 *
1174 * AuthorizedKeysFile /etc/ssh_keys/%u
1175 */
1176 case sAuthorizedKeysFile:
1177 case sAuthorizedKeysFile2:
Damien Miller4dec5d72006-08-05 11:38:40 +10001178 charptr = (opcode == sAuthorizedKeysFile) ?
Ben Lindstromade03f62001-12-06 18:22:17 +00001179 &options->authorized_keys_file :
1180 &options->authorized_keys_file2;
1181 goto parse_filename;
1182
1183 case sClientAliveInterval:
1184 intptr = &options->client_alive_interval;
1185 goto parse_time;
1186
1187 case sClientAliveCountMax:
1188 intptr = &options->client_alive_count_max;
1189 goto parse_int;
1190
Darren Tucker46bc0752004-05-02 22:11:30 +10001191 case sAcceptEnv:
1192 while ((arg = strdelim(&cp)) && *arg != '\0') {
1193 if (strchr(arg, '=') != NULL)
1194 fatal("%s line %d: Invalid environment name.",
1195 filename, linenum);
1196 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1197 fatal("%s line %d: too many allow env.",
1198 filename, linenum);
Darren Tucker45150472006-07-12 22:34:17 +10001199 if (!*activep)
1200 break;
Darren Tucker46bc0752004-05-02 22:11:30 +10001201 options->accept_env[options->num_accept_env++] =
1202 xstrdup(arg);
1203 }
1204 break;
1205
Damien Millerd27b9472005-12-13 19:29:02 +11001206 case sPermitTunnel:
1207 intptr = &options->permit_tun;
Damien Miller7b58e802005-12-13 19:33:19 +11001208 arg = strdelim(&cp);
1209 if (!arg || *arg == '\0')
1210 fatal("%s line %d: Missing yes/point-to-point/"
1211 "ethernet/no argument.", filename, linenum);
1212 value = 0; /* silence compiler */
1213 if (strcasecmp(arg, "ethernet") == 0)
1214 value = SSH_TUNMODE_ETHERNET;
1215 else if (strcasecmp(arg, "point-to-point") == 0)
1216 value = SSH_TUNMODE_POINTOPOINT;
1217 else if (strcasecmp(arg, "yes") == 0)
1218 value = SSH_TUNMODE_YES;
1219 else if (strcasecmp(arg, "no") == 0)
1220 value = SSH_TUNMODE_NO;
1221 else
1222 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1223 "no argument: %s", filename, linenum, arg);
1224 if (*intptr == -1)
1225 *intptr = value;
1226 break;
Damien Millerd27b9472005-12-13 19:29:02 +11001227
Darren Tucker45150472006-07-12 22:34:17 +10001228 case sMatch:
1229 if (cmdline)
1230 fatal("Match directive not supported as a command-line "
1231 "option");
1232 value = match_cfg_line(&cp, linenum, user, host, address);
1233 if (value < 0)
1234 fatal("%s line %d: Bad Match condition", filename,
1235 linenum);
1236 *activep = value;
1237 break;
1238
Damien Miller9b439df2006-07-24 14:04:00 +10001239 case sPermitOpen:
1240 arg = strdelim(&cp);
1241 if (!arg || *arg == '\0')
1242 fatal("%s line %d: missing PermitOpen specification",
1243 filename, linenum);
Damien Miller9fc6a562007-01-05 16:29:02 +11001244 n = options->num_permitted_opens; /* modified later */
Damien Miller9b439df2006-07-24 14:04:00 +10001245 if (strcmp(arg, "any") == 0) {
Damien Miller9fc6a562007-01-05 16:29:02 +11001246 if (*activep && n == -1) {
Damien Miller9b439df2006-07-24 14:04:00 +10001247 channel_clear_adm_permitted_opens();
Damien Millera765cf42006-07-24 14:08:13 +10001248 options->num_permitted_opens = 0;
1249 }
Damien Miller9b439df2006-07-24 14:04:00 +10001250 break;
1251 }
Damien Millera29b95e2007-01-05 16:28:36 +11001252 if (*activep && n == -1)
1253 channel_clear_adm_permitted_opens();
Damien Millera765cf42006-07-24 14:08:13 +10001254 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1255 p = hpdelim(&arg);
1256 if (p == NULL)
1257 fatal("%s line %d: missing host in PermitOpen",
1258 filename, linenum);
1259 p = cleanhostname(p);
1260 if (arg == NULL || (port = a2port(arg)) == 0)
1261 fatal("%s line %d: bad port number in "
1262 "PermitOpen", filename, linenum);
Damien Millera29b95e2007-01-05 16:28:36 +11001263 if (*activep && n == -1)
Damien Millera765cf42006-07-24 14:08:13 +10001264 options->num_permitted_opens =
1265 channel_add_adm_permitted_opens(p, port);
Damien Millera765cf42006-07-24 14:08:13 +10001266 }
Damien Miller9b439df2006-07-24 14:04:00 +10001267 break;
1268
Damien Millere2754432006-07-24 14:06:47 +10001269 case sForceCommand:
1270 if (cp == NULL)
1271 fatal("%.200s line %d: Missing argument.", filename,
1272 linenum);
1273 len = strspn(cp, WHITESPACE);
1274 if (*activep && options->adm_forced_command == NULL)
1275 options->adm_forced_command = xstrdup(cp + len);
1276 return 0;
1277
Damien Millerd8cb1f12008-02-10 22:40:12 +11001278 case sChrootDirectory:
1279 charptr = &options->chroot_directory;
Damien Miller54e37732008-02-10 22:48:55 +11001280
1281 arg = strdelim(&cp);
1282 if (!arg || *arg == '\0')
1283 fatal("%s line %d: missing file name.",
1284 filename, linenum);
1285 if (*activep && *charptr == NULL)
1286 *charptr = xstrdup(arg);
1287 break;
Damien Millerd8cb1f12008-02-10 22:40:12 +11001288
Ben Lindstromade03f62001-12-06 18:22:17 +00001289 case sDeprecated:
Damien Miller996acd22003-04-09 20:59:48 +10001290 logit("%s line %d: Deprecated option %s",
Ben Lindstromade03f62001-12-06 18:22:17 +00001291 filename, linenum, arg);
1292 while (arg)
1293 arg = strdelim(&cp);
1294 break;
1295
Damien Millerf9b3feb2003-05-16 11:38:32 +10001296 case sUnsupported:
1297 logit("%s line %d: Unsupported option %s",
1298 filename, linenum, arg);
1299 while (arg)
1300 arg = strdelim(&cp);
1301 break;
1302
Ben Lindstromade03f62001-12-06 18:22:17 +00001303 default:
1304 fatal("%s line %d: Missing handler for opcode %s (%d)",
1305 filename, linenum, arg, opcode);
1306 }
1307 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1308 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1309 filename, linenum, arg);
1310 return 0;
1311}
1312
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001313/* Reads the server configuration file. */
1314
Damien Miller4af51302000-04-16 11:18:38 +10001315void
Darren Tucker645ab752004-06-25 13:33:20 +10001316load_server_config(const char *filename, Buffer *conf)
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001317{
Darren Tucker645ab752004-06-25 13:33:20 +10001318 char line[1024], *cp;
Ben Lindstrome1353632002-06-23 21:29:23 +00001319 FILE *f;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001320
Darren Tucker645ab752004-06-25 13:33:20 +10001321 debug2("%s: filename %s", __func__, filename);
1322 if ((f = fopen(filename, "r")) == NULL) {
Damien Miller95def091999-11-25 00:26:21 +11001323 perror(filename);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001324 exit(1);
Damien Miller95def091999-11-25 00:26:21 +11001325 }
Darren Tucker645ab752004-06-25 13:33:20 +10001326 buffer_clear(conf);
Damien Miller95def091999-11-25 00:26:21 +11001327 while (fgets(line, sizeof(line), f)) {
Darren Tucker645ab752004-06-25 13:33:20 +10001328 /*
1329 * Trim out comments and strip whitespace
Darren Tuckerfc959702004-07-17 16:12:08 +10001330 * NB - preserve newlines, they are needed to reproduce
Darren Tucker645ab752004-06-25 13:33:20 +10001331 * line numbers later for error messages
1332 */
1333 if ((cp = strchr(line, '#')) != NULL)
1334 memcpy(cp, "\n", 2);
1335 cp = line + strspn(line, " \t\r");
1336
1337 buffer_append(conf, cp, strlen(cp));
1338 }
1339 buffer_append(conf, "\0", 1);
1340 fclose(f);
1341 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1342}
1343
1344void
Darren Tucker45150472006-07-12 22:34:17 +10001345parse_server_match_config(ServerOptions *options, const char *user,
1346 const char *host, const char *address)
Darren Tucker645ab752004-06-25 13:33:20 +10001347{
Darren Tucker45150472006-07-12 22:34:17 +10001348 ServerOptions mo;
1349
1350 initialize_server_options(&mo);
1351 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
Darren Tucker1629c072007-02-19 22:25:37 +11001352 copy_set_server_options(options, &mo, 0);
Darren Tucker45150472006-07-12 22:34:17 +10001353}
1354
Darren Tucker1629c072007-02-19 22:25:37 +11001355/* Helper macros */
1356#define M_CP_INTOPT(n) do {\
1357 if (src->n != -1) \
1358 dst->n = src->n; \
1359} while (0)
1360#define M_CP_STROPT(n) do {\
1361 if (src->n != NULL) { \
1362 if (dst->n != NULL) \
1363 xfree(dst->n); \
1364 dst->n = src->n; \
1365 } \
1366} while(0)
1367
1368/*
1369 * Copy any supported values that are set.
1370 *
1371 * If the preauth flag is set, we do not bother copying the the string or
1372 * array values that are not used pre-authentication, because any that we
1373 * do use must be explictly sent in mm_getpwnamallow().
1374 */
Darren Tucker45150472006-07-12 22:34:17 +10001375void
Darren Tucker1629c072007-02-19 22:25:37 +11001376copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
Darren Tucker45150472006-07-12 22:34:17 +10001377{
Darren Tucker1629c072007-02-19 22:25:37 +11001378 M_CP_INTOPT(password_authentication);
1379 M_CP_INTOPT(gss_authentication);
1380 M_CP_INTOPT(rsa_authentication);
1381 M_CP_INTOPT(pubkey_authentication);
1382 M_CP_INTOPT(kerberos_authentication);
1383 M_CP_INTOPT(hostbased_authentication);
1384 M_CP_INTOPT(kbd_interactive_authentication);
Darren Tucker15f94272008-01-01 20:36:56 +11001385 M_CP_INTOPT(permit_root_login);
Darren Tucker1629c072007-02-19 22:25:37 +11001386
1387 M_CP_INTOPT(allow_tcp_forwarding);
Damien Miller4f755cd2008-05-19 14:57:41 +10001388 M_CP_INTOPT(allow_agent_forwarding);
Darren Tucker1629c072007-02-19 22:25:37 +11001389 M_CP_INTOPT(gateway_ports);
1390 M_CP_INTOPT(x11_display_offset);
1391 M_CP_INTOPT(x11_forwarding);
1392 M_CP_INTOPT(x11_use_localhost);
Damien Miller7207f642008-05-19 15:34:50 +10001393 M_CP_INTOPT(max_sessions);
Darren Tucker1629c072007-02-19 22:25:37 +11001394
1395 M_CP_STROPT(banner);
1396 if (preauth)
1397 return;
1398 M_CP_STROPT(adm_forced_command);
Damien Millerd8cb1f12008-02-10 22:40:12 +11001399 M_CP_STROPT(chroot_directory);
Darren Tucker45150472006-07-12 22:34:17 +10001400}
1401
Darren Tucker1629c072007-02-19 22:25:37 +11001402#undef M_CP_INTOPT
1403#undef M_CP_STROPT
1404
Darren Tucker45150472006-07-12 22:34:17 +10001405void
1406parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1407 const char *user, const char *host, const char *address)
1408{
1409 int active, linenum, bad_options = 0;
Darren Tucker9fbac712004-08-12 22:41:44 +10001410 char *cp, *obuf, *cbuf;
Darren Tucker645ab752004-06-25 13:33:20 +10001411
1412 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1413
Darren Tucker9fbac712004-08-12 22:41:44 +10001414 obuf = cbuf = xstrdup(buffer_ptr(conf));
Darren Tucker45150472006-07-12 22:34:17 +10001415 active = user ? 0 : 1;
Darren Tucker137e9c92004-08-13 21:30:24 +10001416 linenum = 1;
Darren Tucker47eede72005-03-14 23:08:12 +11001417 while ((cp = strsep(&cbuf, "\n")) != NULL) {
Darren Tucker645ab752004-06-25 13:33:20 +10001418 if (process_server_config_line(options, cp, filename,
Darren Tucker45150472006-07-12 22:34:17 +10001419 linenum++, &active, user, host, address) != 0)
Damien Miller95def091999-11-25 00:26:21 +11001420 bad_options++;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001421 }
Darren Tucker9fbac712004-08-12 22:41:44 +10001422 xfree(obuf);
Ben Lindstromb5cdc662001-04-16 02:13:26 +00001423 if (bad_options > 0)
1424 fatal("%s: terminating, %d bad configuration options",
1425 filename, bad_options);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001426}