blob: b8a968aa3afccb4d57373457c4e886b3931b0011 [file] [log] [blame]
Damien Millerb84886b2008-05-19 15:05:07 +10001/* $OpenBSD: servconf.c,v 1.179 2008/05/08 12:02:23 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;
Ben Lindstrom48bd7c12001-01-09 00:35:42 +0000117 options->banner = NULL;
Damien Miller3a961dc2003-06-03 10:25:48 +1000118 options->use_dns = -1;
Ben Lindstrom5744dc42001-04-13 23:28:01 +0000119 options->client_alive_interval = -1;
120 options->client_alive_count_max = -1;
Ben Lindstrombfb3a0e2001-06-05 20:25:05 +0000121 options->authorized_keys_file = NULL;
122 options->authorized_keys_file2 = NULL;
Darren Tucker46bc0752004-05-02 22:11:30 +1000123 options->num_accept_env = 0;
Damien Millerd27b9472005-12-13 19:29:02 +1100124 options->permit_tun = -1;
Damien Millera765cf42006-07-24 14:08:13 +1000125 options->num_permitted_opens = -1;
Damien Millere2754432006-07-24 14:06:47 +1000126 options->adm_forced_command = NULL;
Damien Millerd8cb1f12008-02-10 22:40:12 +1100127 options->chroot_directory = NULL;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000128}
129
Damien Miller4af51302000-04-16 11:18:38 +1000130void
Damien Miller95def091999-11-25 00:26:21 +1100131fill_default_server_options(ServerOptions *options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000132{
Damien Miller726273e2001-11-12 11:40:11 +1100133 /* Portable-specific options */
Damien Miller4e448a32003-05-14 15:11:48 +1000134 if (options->use_pam == -1)
Damien Miller5c3a5582003-09-23 22:12:38 +1000135 options->use_pam = 0;
Damien Miller726273e2001-11-12 11:40:11 +1100136
137 /* Standard Options */
Damien Miller0bc1bd82000-11-13 22:57:25 +1100138 if (options->protocol == SSH_PROTO_UNKNOWN)
139 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
140 if (options->num_host_key_files == 0) {
141 /* fill default hostkeys for protocols */
142 if (options->protocol & SSH_PROTO_1)
Damien Miller7fc23732002-01-22 23:19:11 +1100143 options->host_key_files[options->num_host_key_files++] =
144 _PATH_HOST_KEY_FILE;
145 if (options->protocol & SSH_PROTO_2) {
146 options->host_key_files[options->num_host_key_files++] =
147 _PATH_HOST_RSA_KEY_FILE;
148 options->host_key_files[options->num_host_key_files++] =
149 _PATH_HOST_DSA_KEY_FILE;
150 }
Damien Miller0bc1bd82000-11-13 22:57:25 +1100151 }
Damien Miller34132e52000-01-14 15:45:46 +1100152 if (options->num_ports == 0)
153 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
154 if (options->listen_addrs == NULL)
Ben Lindstrom19066a12001-04-12 23:39:26 +0000155 add_listen_addr(options, NULL, 0);
Damien Miller6f83b8e2000-05-02 09:23:45 +1000156 if (options->pid_file == NULL)
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000157 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
Damien Miller95def091999-11-25 00:26:21 +1100158 if (options->server_key_bits == -1)
159 options->server_key_bits = 768;
160 if (options->login_grace_time == -1)
Damien Millerc1348632002-09-05 14:35:14 +1000161 options->login_grace_time = 120;
Damien Miller95def091999-11-25 00:26:21 +1100162 if (options->key_regeneration_time == -1)
163 options->key_regeneration_time = 3600;
Ben Lindstromd8a90212001-02-15 03:08:27 +0000164 if (options->permit_root_login == PERMIT_NOT_SET)
165 options->permit_root_login = PERMIT_YES;
Damien Miller95def091999-11-25 00:26:21 +1100166 if (options->ignore_rhosts == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100167 options->ignore_rhosts = 1;
Damien Miller95def091999-11-25 00:26:21 +1100168 if (options->ignore_user_known_hosts == -1)
169 options->ignore_user_known_hosts = 0;
Damien Miller95def091999-11-25 00:26:21 +1100170 if (options->print_motd == -1)
171 options->print_motd = 1;
Ben Lindstrom7bfff362001-03-26 05:45:53 +0000172 if (options->print_lastlog == -1)
173 options->print_lastlog = 1;
Damien Miller95def091999-11-25 00:26:21 +1100174 if (options->x11_forwarding == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100175 options->x11_forwarding = 0;
Damien Miller95def091999-11-25 00:26:21 +1100176 if (options->x11_display_offset == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100177 options->x11_display_offset = 10;
Damien Miller95c249f2002-02-05 12:11:34 +1100178 if (options->x11_use_localhost == -1)
179 options->x11_use_localhost = 1;
Damien Millerd3a18572000-06-07 19:55:44 +1000180 if (options->xauth_location == NULL)
Ben Lindstrom1bf11f62001-06-09 01:48:01 +0000181 options->xauth_location = _PATH_XAUTH;
Damien Miller95def091999-11-25 00:26:21 +1100182 if (options->strict_modes == -1)
183 options->strict_modes = 1;
Damien Miller12c150e2003-12-17 16:31:10 +1100184 if (options->tcp_keep_alive == -1)
185 options->tcp_keep_alive = 1;
Damien Millerfcd93202002-02-05 12:26:34 +1100186 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
Damien Miller95def091999-11-25 00:26:21 +1100187 options->log_facility = SYSLOG_FACILITY_AUTH;
Damien Millerfcd93202002-02-05 12:26:34 +1100188 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
Ben Lindstromdb65e8f2001-01-19 04:26:52 +0000189 options->log_level = SYSLOG_LEVEL_INFO;
Damien Miller95def091999-11-25 00:26:21 +1100190 if (options->rhosts_rsa_authentication == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100191 options->rhosts_rsa_authentication = 0;
Ben Lindstrom5eabda32001-04-12 23:34:34 +0000192 if (options->hostbased_authentication == -1)
193 options->hostbased_authentication = 0;
194 if (options->hostbased_uses_name_from_packet_only == -1)
195 options->hostbased_uses_name_from_packet_only = 0;
Damien Miller95def091999-11-25 00:26:21 +1100196 if (options->rsa_authentication == -1)
197 options->rsa_authentication = 1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100198 if (options->pubkey_authentication == -1)
199 options->pubkey_authentication = 1;
Damien Miller95def091999-11-25 00:26:21 +1100200 if (options->kerberos_authentication == -1)
Damien Millerd7de14b2002-04-23 21:04:51 +1000201 options->kerberos_authentication = 0;
Damien Miller95def091999-11-25 00:26:21 +1100202 if (options->kerberos_or_local_passwd == -1)
203 options->kerberos_or_local_passwd = 1;
204 if (options->kerberos_ticket_cleanup == -1)
205 options->kerberos_ticket_cleanup = 1;
Darren Tucker22ef5082003-12-31 11:37:34 +1100206 if (options->kerberos_get_afs_token == -1)
207 options->kerberos_get_afs_token = 0;
Darren Tucker0efd1552003-08-26 11:49:55 +1000208 if (options->gss_authentication == -1)
209 options->gss_authentication = 0;
210 if (options->gss_cleanup_creds == -1)
211 options->gss_cleanup_creds = 1;
Damien Miller95def091999-11-25 00:26:21 +1100212 if (options->password_authentication == -1)
213 options->password_authentication = 1;
Damien Miller874d77b2000-10-14 16:23:11 +1100214 if (options->kbd_interactive_authentication == -1)
215 options->kbd_interactive_authentication = 0;
Ben Lindstrom551ea372001-06-05 18:56:16 +0000216 if (options->challenge_response_authentication == -1)
217 options->challenge_response_authentication = 1;
Damien Miller95def091999-11-25 00:26:21 +1100218 if (options->permit_empty_passwd == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100219 options->permit_empty_passwd = 0;
Ben Lindstrom5d860f02002-08-01 01:28:38 +0000220 if (options->permit_user_env == -1)
221 options->permit_user_env = 0;
Damien Miller95def091999-11-25 00:26:21 +1100222 if (options->use_login == -1)
223 options->use_login = 0;
Ben Lindstrom23e0f662002-06-21 01:09:47 +0000224 if (options->compression == -1)
Damien Miller9786e6e2005-07-26 21:54:56 +1000225 options->compression = COMP_DELAYED;
Damien Miller50a41ed2000-10-16 12:14:42 +1100226 if (options->allow_tcp_forwarding == -1)
227 options->allow_tcp_forwarding = 1;
Damien Miller4f755cd2008-05-19 14:57:41 +1000228 if (options->allow_agent_forwarding == -1)
229 options->allow_agent_forwarding = 1;
Damien Millere247cc42000-05-07 12:03:14 +1000230 if (options->gateway_ports == -1)
231 options->gateway_ports = 0;
Damien Miller37023962000-07-11 17:31:38 +1000232 if (options->max_startups == -1)
233 options->max_startups = 10;
Damien Miller942da032000-08-18 13:59:06 +1000234 if (options->max_startups_rate == -1)
235 options->max_startups_rate = 100; /* 100% */
236 if (options->max_startups_begin == -1)
237 options->max_startups_begin = options->max_startups;
Darren Tucker89413db2004-05-24 10:36:23 +1000238 if (options->max_authtries == -1)
239 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
Damien Miller3a961dc2003-06-03 10:25:48 +1000240 if (options->use_dns == -1)
241 options->use_dns = 1;
Ben Lindstrom5744dc42001-04-13 23:28:01 +0000242 if (options->client_alive_interval == -1)
Damien Miller9f0f5c62001-12-21 14:45:46 +1100243 options->client_alive_interval = 0;
Ben Lindstrom5744dc42001-04-13 23:28:01 +0000244 if (options->client_alive_count_max == -1)
245 options->client_alive_count_max = 3;
Damien Miller75413ac2001-11-12 11:14:35 +1100246 if (options->authorized_keys_file2 == NULL) {
247 /* authorized_keys_file2 falls back to authorized_keys_file */
248 if (options->authorized_keys_file != NULL)
249 options->authorized_keys_file2 = options->authorized_keys_file;
250 else
251 options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
252 }
253 if (options->authorized_keys_file == NULL)
254 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
Damien Millerd27b9472005-12-13 19:29:02 +1100255 if (options->permit_tun == -1)
Damien Miller7b58e802005-12-13 19:33:19 +1100256 options->permit_tun = SSH_TUNMODE_NO;
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000257
Ben Lindstromfb62a692002-06-06 19:47:11 +0000258 /* Turn privilege separation on by default */
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000259 if (use_privsep == -1)
Ben Lindstromfb62a692002-06-06 19:47:11 +0000260 use_privsep = 1;
Damien Miller4903eb42002-06-21 16:20:44 +1000261
Tim Rice40017b02002-07-14 13:36:49 -0700262#ifndef HAVE_MMAP
Damien Miller4903eb42002-06-21 16:20:44 +1000263 if (use_privsep && options->compression == 1) {
264 error("This platform does not support both privilege "
265 "separation and compression");
266 error("Compression disabled");
267 options->compression = 0;
268 }
269#endif
270
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000271}
272
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000273/* Keyword tokens. */
Damien Miller95def091999-11-25 00:26:21 +1100274typedef enum {
275 sBadOption, /* == unknown option */
Damien Miller726273e2001-11-12 11:40:11 +1100276 /* Portable-specific options */
Damien Miller4e448a32003-05-14 15:11:48 +1000277 sUsePAM,
Damien Miller726273e2001-11-12 11:40:11 +1100278 /* Standard Options */
Damien Miller95def091999-11-25 00:26:21 +1100279 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
280 sPermitRootLogin, sLogFacility, sLogLevel,
Darren Tuckerec960f22003-08-13 20:37:05 +1000281 sRhostsRSAAuthentication, sRSAAuthentication,
Damien Miller95def091999-11-25 00:26:21 +1100282 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
Darren Tucker22ef5082003-12-31 11:37:34 +1100283 sKerberosGetAFSToken,
Darren Tucker6aaa58c2003-08-02 22:24:49 +1000284 sKerberosTgtPassing, sChallengeResponseAuthentication,
Darren Tucker0f383232005-01-20 10:57:56 +1100285 sPasswordAuthentication, sKbdInteractiveAuthentication,
286 sListenAddress, sAddressFamily,
Ben Lindstrom7bfff362001-03-26 05:45:53 +0000287 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
Damien Miller95c249f2002-02-05 12:11:34 +1100288 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
Damien Miller12c150e2003-12-17 16:31:10 +1100289 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
Ben Lindstrom5d860f02002-08-01 01:28:38 +0000290 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
Damien Miller50a41ed2000-10-16 12:14:42 +1100291 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
Ben Lindstrom06b33aa2001-02-15 03:01:59 +0000292 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
Darren Tucker89413db2004-05-24 10:36:23 +1000293 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
294 sMaxStartups, sMaxAuthTries,
Damien Miller3a961dc2003-06-03 10:25:48 +1000295 sBanner, sUseDNS, sHostbasedAuthentication,
Damien Miller9f0f5c62001-12-21 14:45:46 +1100296 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
Ben Lindstrombfb3a0e2001-06-05 20:25:05 +0000297 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
Damien Millerd27b9472005-12-13 19:29:02 +1100298 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
Damien Millerd8cb1f12008-02-10 22:40:12 +1100299 sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
Damien Miller4f755cd2008-05-19 14:57:41 +1000300 sUsePrivilegeSeparation, sAllowAgentForwarding,
Damien Millerf9b3feb2003-05-16 11:38:32 +1000301 sDeprecated, sUnsupported
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000302} ServerOpCodes;
303
Darren Tucker45150472006-07-12 22:34:17 +1000304#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
305#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
306#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
307
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000308/* Textual representation of the tokens. */
Damien Miller95def091999-11-25 00:26:21 +1100309static struct {
310 const char *name;
311 ServerOpCodes opcode;
Darren Tucker45150472006-07-12 22:34:17 +1000312 u_int flags;
Damien Miller95def091999-11-25 00:26:21 +1100313} keywords[] = {
Damien Miller726273e2001-11-12 11:40:11 +1100314 /* Portable-specific options */
Damien Miller6ac2c482003-05-16 11:42:35 +1000315#ifdef USE_PAM
Darren Tucker45150472006-07-12 22:34:17 +1000316 { "usepam", sUsePAM, SSHCFG_GLOBAL },
Damien Miller6ac2c482003-05-16 11:42:35 +1000317#else
Darren Tucker45150472006-07-12 22:34:17 +1000318 { "usepam", sUnsupported, SSHCFG_GLOBAL },
Damien Miller6ac2c482003-05-16 11:42:35 +1000319#endif
Darren Tucker45150472006-07-12 22:34:17 +1000320 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
Damien Miller726273e2001-11-12 11:40:11 +1100321 /* Standard Options */
Darren Tucker45150472006-07-12 22:34:17 +1000322 { "port", sPort, SSHCFG_GLOBAL },
323 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
324 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
325 { "pidfile", sPidFile, SSHCFG_GLOBAL },
326 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
327 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
328 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
Darren Tucker15f94272008-01-01 20:36:56 +1100329 { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000330 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
331 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
332 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
Darren Tucker1629c072007-02-19 22:25:37 +1100333 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
334 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000335 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
Darren Tucker1629c072007-02-19 22:25:37 +1100336 { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
337 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000338 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
Darren Tucker6aaa58c2003-08-02 22:24:49 +1000339#ifdef KRB5
Darren Tucker1629c072007-02-19 22:25:37 +1100340 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000341 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
342 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
Darren Tucker3c78c5e2004-01-23 22:03:10 +1100343#ifdef USE_AFS
Darren Tucker45150472006-07-12 22:34:17 +1000344 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
Damien Millerf9b3feb2003-05-16 11:38:32 +1000345#else
Darren Tucker45150472006-07-12 22:34:17 +1000346 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
Darren Tucker409cb322004-01-05 22:36:51 +1100347#endif
348#else
Darren Tucker1629c072007-02-19 22:25:37 +1100349 { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000350 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
351 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
352 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
Damien Millerf9b3feb2003-05-16 11:38:32 +1000353#endif
Darren Tucker45150472006-07-12 22:34:17 +1000354 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
355 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
Darren Tucker0efd1552003-08-26 11:49:55 +1000356#ifdef GSSAPI
Darren Tucker1629c072007-02-19 22:25:37 +1100357 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000358 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
Darren Tucker0efd1552003-08-26 11:49:55 +1000359#else
Darren Tucker1629c072007-02-19 22:25:37 +1100360 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000361 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
Darren Tucker0efd1552003-08-26 11:49:55 +1000362#endif
Darren Tucker1629c072007-02-19 22:25:37 +1100363 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
364 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
Darren Tucker1d75f222007-03-01 21:31:28 +1100365 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
Darren Tucker45150472006-07-12 22:34:17 +1000366 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
367 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
368 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
369 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
370 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
371 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
372 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
373 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
Damien Millerd1de9952006-07-24 14:05:48 +1000374 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
375 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
376 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000377 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
378 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
379 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
380 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
381 { "uselogin", sUseLogin, SSHCFG_GLOBAL },
382 { "compression", sCompression, SSHCFG_GLOBAL },
383 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
384 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
385 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
Damien Miller4f755cd2008-05-19 14:57:41 +1000386 { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000387 { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
388 { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
389 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
390 { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
391 { "ciphers", sCiphers, SSHCFG_GLOBAL },
392 { "macs", sMacs, SSHCFG_GLOBAL },
393 { "protocol", sProtocol, SSHCFG_GLOBAL },
394 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
395 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
396 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
397 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
Darren Tucker1629c072007-02-19 22:25:37 +1100398 { "banner", sBanner, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000399 { "usedns", sUseDNS, SSHCFG_GLOBAL },
400 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
401 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
402 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
403 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
404 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
405 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
406 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
407 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
408 { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
Damien Miller9b439df2006-07-24 14:04:00 +1000409 { "match", sMatch, SSHCFG_ALL },
410 { "permitopen", sPermitOpen, SSHCFG_ALL },
Damien Millere2754432006-07-24 14:06:47 +1000411 { "forcecommand", sForceCommand, SSHCFG_ALL },
Damien Millerd8cb1f12008-02-10 22:40:12 +1100412 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
Darren Tucker45150472006-07-12 22:34:17 +1000413 { NULL, sBadOption, 0 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000414};
415
Damien Miller5428f641999-11-25 11:54:57 +1100416/*
Ben Lindstrom3704c262001-04-02 18:20:03 +0000417 * Returns the number of the token pointed to by cp or sBadOption.
Damien Miller5428f641999-11-25 11:54:57 +1100418 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000419
Damien Miller4af51302000-04-16 11:18:38 +1000420static ServerOpCodes
Damien Miller95def091999-11-25 00:26:21 +1100421parse_token(const char *cp, const char *filename,
Darren Tucker45150472006-07-12 22:34:17 +1000422 int linenum, u_int *flags)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000423{
Ben Lindstrom46c16222000-12-22 01:43:59 +0000424 u_int i;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000425
Damien Miller95def091999-11-25 00:26:21 +1100426 for (i = 0; keywords[i].name; i++)
Darren Tucker45150472006-07-12 22:34:17 +1000427 if (strcasecmp(cp, keywords[i].name) == 0) {
428 *flags = keywords[i].flags;
Damien Miller95def091999-11-25 00:26:21 +1100429 return keywords[i].opcode;
Darren Tucker45150472006-07-12 22:34:17 +1000430 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000431
Ben Lindstromb5cdc662001-04-16 02:13:26 +0000432 error("%s: line %d: Bad configuration option: %s",
433 filename, linenum, cp);
Damien Miller95def091999-11-25 00:26:21 +1100434 return sBadOption;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000435}
436
Ben Lindstrombba81212001-06-25 05:01:22 +0000437static void
Ben Lindstrom19066a12001-04-12 23:39:26 +0000438add_listen_addr(ServerOptions *options, char *addr, u_short port)
Damien Miller34132e52000-01-14 15:45:46 +1100439{
Damien Millereccb9de2005-06-17 12:59:34 +1000440 u_int i;
Damien Miller34132e52000-01-14 15:45:46 +1100441
442 if (options->num_ports == 0)
443 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
Darren Tucker0f383232005-01-20 10:57:56 +1100444 if (options->address_family == -1)
445 options->address_family = AF_UNSPEC;
Ben Lindstrom19066a12001-04-12 23:39:26 +0000446 if (port == 0)
Ben Lindstromc510af42001-04-07 17:25:48 +0000447 for (i = 0; i < options->num_ports; i++)
448 add_one_listen_addr(options, addr, options->ports[i]);
449 else
Ben Lindstrom19066a12001-04-12 23:39:26 +0000450 add_one_listen_addr(options, addr, port);
Ben Lindstromc510af42001-04-07 17:25:48 +0000451}
452
Ben Lindstrombba81212001-06-25 05:01:22 +0000453static void
Ben Lindstromc510af42001-04-07 17:25:48 +0000454add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
455{
456 struct addrinfo hints, *ai, *aitop;
457 char strport[NI_MAXSERV];
458 int gaierr;
459
460 memset(&hints, 0, sizeof(hints));
Darren Tucker0f383232005-01-20 10:57:56 +1100461 hints.ai_family = options->address_family;
Ben Lindstromc510af42001-04-07 17:25:48 +0000462 hints.ai_socktype = SOCK_STREAM;
463 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
Ben Lindstrome1353632002-06-23 21:29:23 +0000464 snprintf(strport, sizeof strport, "%u", port);
Ben Lindstromc510af42001-04-07 17:25:48 +0000465 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
466 fatal("bad addr or host: %s (%s)",
467 addr ? addr : "<NULL>",
Darren Tucker4abde772007-12-29 02:43:51 +1100468 ssh_gai_strerror(gaierr));
Ben Lindstromc510af42001-04-07 17:25:48 +0000469 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
470 ;
471 ai->ai_next = options->listen_addrs;
472 options->listen_addrs = aitop;
Damien Miller34132e52000-01-14 15:45:46 +1100473}
474
Darren Tucker45150472006-07-12 22:34:17 +1000475/*
476 * The strategy for the Match blocks is that the config file is parsed twice.
477 *
478 * The first time is at startup. activep is initialized to 1 and the
479 * directives in the global context are processed and acted on. Hitting a
480 * Match directive unsets activep and the directives inside the block are
481 * checked for syntax only.
482 *
483 * The second time is after a connection has been established but before
484 * authentication. activep is initialized to 2 and global config directives
485 * are ignored since they have already been processed. If the criteria in a
486 * Match block is met, activep is set and the subsequent directives
487 * processed and actioned until EOF or another Match block unsets it. Any
488 * options set are copied into the main server config.
489 *
490 * Potential additions/improvements:
491 * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
492 *
493 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
494 * Match Address 192.168.0.*
495 * Tag trusted
496 * Match Group wheel
497 * Tag trusted
498 * Match Tag trusted
499 * AllowTcpForwarding yes
500 * GatewayPorts clientspecified
501 * [...]
502 *
503 * - Add a PermittedChannelRequests directive
504 * Match Group shell
505 * PermittedChannelRequests session,forwarded-tcpip
506 */
507
508static int
Damien Miller565ca3f2006-08-19 00:23:15 +1000509match_cfg_line_group(const char *grps, int line, const char *user)
510{
511 int result = 0;
512 u_int ngrps = 0;
513 char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
514 struct passwd *pw;
515
516 /*
517 * Even if we do not have a user yet, we still need to check for
518 * valid syntax.
519 */
520 arg = cp = xstrdup(grps);
521 while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
522 if (ngrps >= MAX_MATCH_GROUPS) {
523 error("line %d: too many groups in Match Group", line);
524 result = -1;
525 goto out;
526 }
527 grplist[ngrps++] = p;
528 }
529
530 if (user == NULL)
531 goto out;
532
533 if ((pw = getpwnam(user)) == NULL) {
534 debug("Can't match group at line %d because user %.100s does "
535 "not exist", line, user);
536 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
537 debug("Can't Match group because user %.100s not in any group "
538 "at line %d", user, line);
539 } else if (ga_match(grplist, ngrps) != 1) {
540 debug("user %.100s does not match group %.100s at line %d",
541 user, arg, line);
542 } else {
543 debug("user %.100s matched group %.100s at line %d", user,
544 arg, line);
545 result = 1;
546 }
547out:
548 ga_free();
549 xfree(arg);
550 return result;
551}
552
553static int
Darren Tucker45150472006-07-12 22:34:17 +1000554match_cfg_line(char **condition, int line, const char *user, const char *host,
555 const char *address)
556{
557 int result = 1;
558 char *arg, *attrib, *cp = *condition;
559 size_t len;
560
561 if (user == NULL)
562 debug3("checking syntax for 'Match %s'", cp);
563 else
564 debug3("checking match for '%s' user %s host %s addr %s", cp,
565 user ? user : "(null)", host ? host : "(null)",
566 address ? address : "(null)");
567
568 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
569 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
570 error("Missing Match criteria for %s", attrib);
571 return -1;
572 }
573 len = strlen(arg);
574 if (strcasecmp(attrib, "user") == 0) {
575 if (!user) {
576 result = 0;
577 continue;
578 }
579 if (match_pattern_list(user, arg, len, 0) != 1)
580 result = 0;
581 else
582 debug("user %.100s matched 'User %.100s' at "
583 "line %d", user, arg, line);
Damien Miller565ca3f2006-08-19 00:23:15 +1000584 } else if (strcasecmp(attrib, "group") == 0) {
585 switch (match_cfg_line_group(arg, line, user)) {
586 case -1:
587 return -1;
588 case 0:
589 result = 0;
590 }
Darren Tucker45150472006-07-12 22:34:17 +1000591 } else if (strcasecmp(attrib, "host") == 0) {
592 if (!host) {
593 result = 0;
594 continue;
595 }
596 if (match_hostname(host, arg, len) != 1)
597 result = 0;
598 else
599 debug("connection from %.100s matched 'Host "
600 "%.100s' at line %d", host, arg, line);
601 } else if (strcasecmp(attrib, "address") == 0) {
Darren Tucker45150472006-07-12 22:34:17 +1000602 if (!address) {
603 result = 0;
604 continue;
605 }
606 if (match_hostname(address, arg, len) != 1)
607 result = 0;
608 else
609 debug("connection from %.100s matched 'Address "
610 "%.100s' at line %d", address, arg, line);
611 } else {
612 error("Unsupported Match attribute %s", attrib);
613 return -1;
614 }
615 }
616 if (user != NULL)
617 debug3("match %sfound", result ? "" : "not ");
618 *condition = cp;
619 return result;
620}
621
Damien Millere2754432006-07-24 14:06:47 +1000622#define WHITESPACE " \t\r\n"
623
Ben Lindstromade03f62001-12-06 18:22:17 +0000624int
625process_server_config_line(ServerOptions *options, char *line,
Darren Tucker45150472006-07-12 22:34:17 +1000626 const char *filename, int linenum, int *activep, const char *user,
627 const char *host, const char *address)
Ben Lindstromade03f62001-12-06 18:22:17 +0000628{
629 char *cp, **charptr, *arg, *p;
Darren Tucker45150472006-07-12 22:34:17 +1000630 int cmdline = 0, *intptr, value, n;
Darren Tucker1e44c5d2008-01-01 20:32:26 +1100631 SyslogFacility *log_facility_ptr;
632 LogLevel *log_level_ptr;
Ben Lindstromade03f62001-12-06 18:22:17 +0000633 ServerOpCodes opcode;
Damien Millerf91ee4c2005-03-01 21:24:33 +1100634 u_short port;
Darren Tucker45150472006-07-12 22:34:17 +1000635 u_int i, flags = 0;
Damien Miller917f9b62006-07-10 20:36:47 +1000636 size_t len;
Ben Lindstromade03f62001-12-06 18:22:17 +0000637
638 cp = line;
Damien Miller78f16cb2006-03-26 13:54:37 +1100639 if ((arg = strdelim(&cp)) == NULL)
Damien Miller928b2362006-03-26 13:53:32 +1100640 return 0;
Ben Lindstromade03f62001-12-06 18:22:17 +0000641 /* Ignore leading whitespace */
642 if (*arg == '\0')
643 arg = strdelim(&cp);
644 if (!arg || !*arg || *arg == '#')
645 return 0;
646 intptr = NULL;
647 charptr = NULL;
Darren Tucker45150472006-07-12 22:34:17 +1000648 opcode = parse_token(arg, filename, linenum, &flags);
649
650 if (activep == NULL) { /* We are processing a command line directive */
651 cmdline = 1;
652 activep = &cmdline;
653 }
654 if (*activep && opcode != sMatch)
655 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
656 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
657 if (user == NULL) {
658 fatal("%s line %d: Directive '%s' is not allowed "
659 "within a Match block", filename, linenum, arg);
660 } else { /* this is a directive we have already processed */
661 while (arg)
662 arg = strdelim(&cp);
663 return 0;
664 }
665 }
666
Ben Lindstromade03f62001-12-06 18:22:17 +0000667 switch (opcode) {
668 /* Portable-specific options */
Damien Miller4e448a32003-05-14 15:11:48 +1000669 case sUsePAM:
670 intptr = &options->use_pam;
Ben Lindstromade03f62001-12-06 18:22:17 +0000671 goto parse_flag;
672
673 /* Standard Options */
674 case sBadOption:
675 return -1;
676 case sPort:
677 /* ignore ports from configfile if cmdline specifies ports */
678 if (options->ports_from_cmdline)
679 return 0;
680 if (options->listen_addrs != NULL)
681 fatal("%s line %d: ports must be specified before "
Damien Miller4fbf08a2002-01-22 23:35:09 +1100682 "ListenAddress.", filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +0000683 if (options->num_ports >= MAX_PORTS)
684 fatal("%s line %d: too many ports.",
685 filename, linenum);
686 arg = strdelim(&cp);
687 if (!arg || *arg == '\0')
688 fatal("%s line %d: missing port number.",
689 filename, linenum);
690 options->ports[options->num_ports++] = a2port(arg);
691 if (options->ports[options->num_ports-1] == 0)
692 fatal("%s line %d: Badly formatted port number.",
693 filename, linenum);
694 break;
695
696 case sServerKeyBits:
697 intptr = &options->server_key_bits;
698parse_int:
699 arg = strdelim(&cp);
700 if (!arg || *arg == '\0')
701 fatal("%s line %d: missing integer value.",
702 filename, linenum);
703 value = atoi(arg);
Darren Tucker45150472006-07-12 22:34:17 +1000704 if (*activep && *intptr == -1)
Ben Lindstromade03f62001-12-06 18:22:17 +0000705 *intptr = value;
706 break;
707
708 case sLoginGraceTime:
709 intptr = &options->login_grace_time;
710parse_time:
711 arg = strdelim(&cp);
712 if (!arg || *arg == '\0')
713 fatal("%s line %d: missing time value.",
714 filename, linenum);
715 if ((value = convtime(arg)) == -1)
716 fatal("%s line %d: invalid time value.",
717 filename, linenum);
718 if (*intptr == -1)
719 *intptr = value;
720 break;
721
722 case sKeyRegenerationTime:
723 intptr = &options->key_regeneration_time;
724 goto parse_time;
725
726 case sListenAddress:
727 arg = strdelim(&cp);
Damien Millerf91ee4c2005-03-01 21:24:33 +1100728 if (arg == NULL || *arg == '\0')
729 fatal("%s line %d: missing address",
Ben Lindstromade03f62001-12-06 18:22:17 +0000730 filename, linenum);
Damien Miller203c7052005-08-12 22:11:37 +1000731 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
732 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
733 && strchr(p+1, ':') != NULL) {
734 add_listen_addr(options, arg, 0);
735 break;
736 }
Damien Millerf91ee4c2005-03-01 21:24:33 +1100737 p = hpdelim(&arg);
738 if (p == NULL)
739 fatal("%s line %d: bad address:port usage",
740 filename, linenum);
741 p = cleanhostname(p);
742 if (arg == NULL)
743 port = 0;
744 else if ((port = a2port(arg)) == 0)
745 fatal("%s line %d: bad port number", filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +0000746
Damien Millerf91ee4c2005-03-01 21:24:33 +1100747 add_listen_addr(options, p, port);
748
Ben Lindstromade03f62001-12-06 18:22:17 +0000749 break;
750
Darren Tucker0f383232005-01-20 10:57:56 +1100751 case sAddressFamily:
752 arg = strdelim(&cp);
Damien Miller17b23d82005-05-26 12:11:56 +1000753 if (!arg || *arg == '\0')
754 fatal("%s line %d: missing address family.",
755 filename, linenum);
Darren Tucker0f383232005-01-20 10:57:56 +1100756 intptr = &options->address_family;
757 if (options->listen_addrs != NULL)
758 fatal("%s line %d: address family must be specified before "
759 "ListenAddress.", filename, linenum);
760 if (strcasecmp(arg, "inet") == 0)
761 value = AF_INET;
762 else if (strcasecmp(arg, "inet6") == 0)
763 value = AF_INET6;
764 else if (strcasecmp(arg, "any") == 0)
765 value = AF_UNSPEC;
766 else
767 fatal("%s line %d: unsupported address family \"%s\".",
768 filename, linenum, arg);
769 if (*intptr == -1)
770 *intptr = value;
771 break;
772
Ben Lindstromade03f62001-12-06 18:22:17 +0000773 case sHostKeyFile:
774 intptr = &options->num_host_key_files;
775 if (*intptr >= MAX_HOSTKEYS)
776 fatal("%s line %d: too many host keys specified (max %d).",
777 filename, linenum, MAX_HOSTKEYS);
778 charptr = &options->host_key_files[*intptr];
779parse_filename:
780 arg = strdelim(&cp);
781 if (!arg || *arg == '\0')
782 fatal("%s line %d: missing file name.",
783 filename, linenum);
Darren Tucker45150472006-07-12 22:34:17 +1000784 if (*activep && *charptr == NULL) {
Ben Lindstromade03f62001-12-06 18:22:17 +0000785 *charptr = tilde_expand_filename(arg, getuid());
786 /* increase optional counter */
787 if (intptr != NULL)
788 *intptr = *intptr + 1;
789 }
790 break;
791
792 case sPidFile:
793 charptr = &options->pid_file;
794 goto parse_filename;
795
796 case sPermitRootLogin:
797 intptr = &options->permit_root_login;
798 arg = strdelim(&cp);
799 if (!arg || *arg == '\0')
800 fatal("%s line %d: missing yes/"
801 "without-password/forced-commands-only/no "
802 "argument.", filename, linenum);
803 value = 0; /* silence compiler */
804 if (strcmp(arg, "without-password") == 0)
805 value = PERMIT_NO_PASSWD;
806 else if (strcmp(arg, "forced-commands-only") == 0)
807 value = PERMIT_FORCED_ONLY;
808 else if (strcmp(arg, "yes") == 0)
809 value = PERMIT_YES;
810 else if (strcmp(arg, "no") == 0)
811 value = PERMIT_NO;
812 else
813 fatal("%s line %d: Bad yes/"
814 "without-password/forced-commands-only/no "
815 "argument: %s", filename, linenum, arg);
Darren Tucker15f94272008-01-01 20:36:56 +1100816 if (*activep && *intptr == -1)
Ben Lindstromade03f62001-12-06 18:22:17 +0000817 *intptr = value;
818 break;
819
820 case sIgnoreRhosts:
821 intptr = &options->ignore_rhosts;
822parse_flag:
823 arg = strdelim(&cp);
824 if (!arg || *arg == '\0')
825 fatal("%s line %d: missing yes/no argument.",
826 filename, linenum);
827 value = 0; /* silence compiler */
828 if (strcmp(arg, "yes") == 0)
829 value = 1;
830 else if (strcmp(arg, "no") == 0)
831 value = 0;
832 else
833 fatal("%s line %d: Bad yes/no argument: %s",
834 filename, linenum, arg);
Darren Tucker45150472006-07-12 22:34:17 +1000835 if (*activep && *intptr == -1)
Ben Lindstromade03f62001-12-06 18:22:17 +0000836 *intptr = value;
837 break;
838
839 case sIgnoreUserKnownHosts:
840 intptr = &options->ignore_user_known_hosts;
841 goto parse_flag;
842
Ben Lindstromade03f62001-12-06 18:22:17 +0000843 case sRhostsRSAAuthentication:
844 intptr = &options->rhosts_rsa_authentication;
845 goto parse_flag;
846
847 case sHostbasedAuthentication:
848 intptr = &options->hostbased_authentication;
849 goto parse_flag;
850
851 case sHostbasedUsesNameFromPacketOnly:
852 intptr = &options->hostbased_uses_name_from_packet_only;
853 goto parse_flag;
854
855 case sRSAAuthentication:
856 intptr = &options->rsa_authentication;
857 goto parse_flag;
858
859 case sPubkeyAuthentication:
860 intptr = &options->pubkey_authentication;
861 goto parse_flag;
Damien Miller2aa0ab42003-05-15 12:05:28 +1000862
Ben Lindstromade03f62001-12-06 18:22:17 +0000863 case sKerberosAuthentication:
864 intptr = &options->kerberos_authentication;
865 goto parse_flag;
866
867 case sKerberosOrLocalPasswd:
868 intptr = &options->kerberos_or_local_passwd;
869 goto parse_flag;
870
871 case sKerberosTicketCleanup:
872 intptr = &options->kerberos_ticket_cleanup;
873 goto parse_flag;
Damien Miller2aa0ab42003-05-15 12:05:28 +1000874
Darren Tucker22ef5082003-12-31 11:37:34 +1100875 case sKerberosGetAFSToken:
876 intptr = &options->kerberos_get_afs_token;
877 goto parse_flag;
878
Darren Tucker0efd1552003-08-26 11:49:55 +1000879 case sGssAuthentication:
880 intptr = &options->gss_authentication;
881 goto parse_flag;
882
883 case sGssCleanupCreds:
884 intptr = &options->gss_cleanup_creds;
885 goto parse_flag;
886
Ben Lindstromade03f62001-12-06 18:22:17 +0000887 case sPasswordAuthentication:
888 intptr = &options->password_authentication;
889 goto parse_flag;
890
891 case sKbdInteractiveAuthentication:
892 intptr = &options->kbd_interactive_authentication;
893 goto parse_flag;
894
895 case sChallengeResponseAuthentication:
896 intptr = &options->challenge_response_authentication;
897 goto parse_flag;
898
899 case sPrintMotd:
900 intptr = &options->print_motd;
901 goto parse_flag;
902
903 case sPrintLastLog:
904 intptr = &options->print_lastlog;
905 goto parse_flag;
906
907 case sX11Forwarding:
908 intptr = &options->x11_forwarding;
909 goto parse_flag;
910
911 case sX11DisplayOffset:
912 intptr = &options->x11_display_offset;
913 goto parse_int;
914
Damien Miller95c249f2002-02-05 12:11:34 +1100915 case sX11UseLocalhost:
916 intptr = &options->x11_use_localhost;
917 goto parse_flag;
918
Ben Lindstromade03f62001-12-06 18:22:17 +0000919 case sXAuthLocation:
920 charptr = &options->xauth_location;
921 goto parse_filename;
922
923 case sStrictModes:
924 intptr = &options->strict_modes;
925 goto parse_flag;
926
Damien Miller12c150e2003-12-17 16:31:10 +1100927 case sTCPKeepAlive:
928 intptr = &options->tcp_keep_alive;
Ben Lindstromade03f62001-12-06 18:22:17 +0000929 goto parse_flag;
930
931 case sEmptyPasswd:
932 intptr = &options->permit_empty_passwd;
933 goto parse_flag;
934
Ben Lindstrom5d860f02002-08-01 01:28:38 +0000935 case sPermitUserEnvironment:
936 intptr = &options->permit_user_env;
937 goto parse_flag;
938
Ben Lindstromade03f62001-12-06 18:22:17 +0000939 case sUseLogin:
940 intptr = &options->use_login;
941 goto parse_flag;
942
Ben Lindstrom23e0f662002-06-21 01:09:47 +0000943 case sCompression:
944 intptr = &options->compression;
Damien Miller9786e6e2005-07-26 21:54:56 +1000945 arg = strdelim(&cp);
946 if (!arg || *arg == '\0')
947 fatal("%s line %d: missing yes/no/delayed "
948 "argument.", filename, linenum);
949 value = 0; /* silence compiler */
950 if (strcmp(arg, "delayed") == 0)
951 value = COMP_DELAYED;
952 else if (strcmp(arg, "yes") == 0)
953 value = COMP_ZLIB;
954 else if (strcmp(arg, "no") == 0)
955 value = COMP_NONE;
956 else
957 fatal("%s line %d: Bad yes/no/delayed "
958 "argument: %s", filename, linenum, arg);
959 if (*intptr == -1)
960 *intptr = value;
961 break;
Ben Lindstrom23e0f662002-06-21 01:09:47 +0000962
Ben Lindstromade03f62001-12-06 18:22:17 +0000963 case sGatewayPorts:
964 intptr = &options->gateway_ports;
Damien Millerf91ee4c2005-03-01 21:24:33 +1100965 arg = strdelim(&cp);
966 if (!arg || *arg == '\0')
967 fatal("%s line %d: missing yes/no/clientspecified "
968 "argument.", filename, linenum);
969 value = 0; /* silence compiler */
970 if (strcmp(arg, "clientspecified") == 0)
971 value = 2;
972 else if (strcmp(arg, "yes") == 0)
973 value = 1;
974 else if (strcmp(arg, "no") == 0)
975 value = 0;
976 else
977 fatal("%s line %d: Bad yes/no/clientspecified "
978 "argument: %s", filename, linenum, arg);
Darren Tucker82347a82007-02-25 20:37:52 +1100979 if (*activep && *intptr == -1)
Damien Millerf91ee4c2005-03-01 21:24:33 +1100980 *intptr = value;
981 break;
Ben Lindstromade03f62001-12-06 18:22:17 +0000982
Damien Miller3a961dc2003-06-03 10:25:48 +1000983 case sUseDNS:
984 intptr = &options->use_dns;
Ben Lindstromade03f62001-12-06 18:22:17 +0000985 goto parse_flag;
986
987 case sLogFacility:
Darren Tucker1e44c5d2008-01-01 20:32:26 +1100988 log_facility_ptr = &options->log_facility;
Ben Lindstromade03f62001-12-06 18:22:17 +0000989 arg = strdelim(&cp);
990 value = log_facility_number(arg);
Damien Millerfcd93202002-02-05 12:26:34 +1100991 if (value == SYSLOG_FACILITY_NOT_SET)
Ben Lindstromade03f62001-12-06 18:22:17 +0000992 fatal("%.200s line %d: unsupported log facility '%s'",
993 filename, linenum, arg ? arg : "<NONE>");
Darren Tucker1e44c5d2008-01-01 20:32:26 +1100994 if (*log_facility_ptr == -1)
995 *log_facility_ptr = (SyslogFacility) value;
Ben Lindstromade03f62001-12-06 18:22:17 +0000996 break;
997
998 case sLogLevel:
Darren Tucker1e44c5d2008-01-01 20:32:26 +1100999 log_level_ptr = &options->log_level;
Ben Lindstromade03f62001-12-06 18:22:17 +00001000 arg = strdelim(&cp);
1001 value = log_level_number(arg);
Damien Millerfcd93202002-02-05 12:26:34 +11001002 if (value == SYSLOG_LEVEL_NOT_SET)
Ben Lindstromade03f62001-12-06 18:22:17 +00001003 fatal("%.200s line %d: unsupported log level '%s'",
1004 filename, linenum, arg ? arg : "<NONE>");
Darren Tucker1e44c5d2008-01-01 20:32:26 +11001005 if (*log_level_ptr == -1)
1006 *log_level_ptr = (LogLevel) value;
Ben Lindstromade03f62001-12-06 18:22:17 +00001007 break;
1008
1009 case sAllowTcpForwarding:
1010 intptr = &options->allow_tcp_forwarding;
1011 goto parse_flag;
1012
Damien Miller4f755cd2008-05-19 14:57:41 +10001013 case sAllowAgentForwarding:
1014 intptr = &options->allow_agent_forwarding;
1015 goto parse_flag;
1016
Ben Lindstrom7a2073c2002-03-22 02:30:41 +00001017 case sUsePrivilegeSeparation:
1018 intptr = &use_privsep;
1019 goto parse_flag;
1020
Ben Lindstromade03f62001-12-06 18:22:17 +00001021 case sAllowUsers:
1022 while ((arg = strdelim(&cp)) && *arg != '\0') {
1023 if (options->num_allow_users >= MAX_ALLOW_USERS)
1024 fatal("%s line %d: too many allow users.",
1025 filename, linenum);
Ben Lindstrome1353632002-06-23 21:29:23 +00001026 options->allow_users[options->num_allow_users++] =
1027 xstrdup(arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001028 }
1029 break;
1030
1031 case sDenyUsers:
1032 while ((arg = strdelim(&cp)) && *arg != '\0') {
1033 if (options->num_deny_users >= MAX_DENY_USERS)
Damien Miller4dec5d72006-08-05 11:38:40 +10001034 fatal("%s line %d: too many deny users.",
Ben Lindstromade03f62001-12-06 18:22:17 +00001035 filename, linenum);
Ben Lindstrome1353632002-06-23 21:29:23 +00001036 options->deny_users[options->num_deny_users++] =
1037 xstrdup(arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001038 }
1039 break;
1040
1041 case sAllowGroups:
1042 while ((arg = strdelim(&cp)) && *arg != '\0') {
1043 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1044 fatal("%s line %d: too many allow groups.",
1045 filename, linenum);
Ben Lindstrome1353632002-06-23 21:29:23 +00001046 options->allow_groups[options->num_allow_groups++] =
1047 xstrdup(arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001048 }
1049 break;
1050
1051 case sDenyGroups:
1052 while ((arg = strdelim(&cp)) && *arg != '\0') {
1053 if (options->num_deny_groups >= MAX_DENY_GROUPS)
1054 fatal("%s line %d: too many deny groups.",
1055 filename, linenum);
1056 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1057 }
1058 break;
1059
1060 case sCiphers:
1061 arg = strdelim(&cp);
1062 if (!arg || *arg == '\0')
1063 fatal("%s line %d: Missing argument.", filename, linenum);
1064 if (!ciphers_valid(arg))
1065 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1066 filename, linenum, arg ? arg : "<NONE>");
1067 if (options->ciphers == NULL)
1068 options->ciphers = xstrdup(arg);
1069 break;
1070
1071 case sMacs:
1072 arg = strdelim(&cp);
1073 if (!arg || *arg == '\0')
1074 fatal("%s line %d: Missing argument.", filename, linenum);
1075 if (!mac_valid(arg))
1076 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1077 filename, linenum, arg ? arg : "<NONE>");
1078 if (options->macs == NULL)
1079 options->macs = xstrdup(arg);
1080 break;
1081
1082 case sProtocol:
1083 intptr = &options->protocol;
1084 arg = strdelim(&cp);
1085 if (!arg || *arg == '\0')
1086 fatal("%s line %d: Missing argument.", filename, linenum);
1087 value = proto_spec(arg);
1088 if (value == SSH_PROTO_UNKNOWN)
1089 fatal("%s line %d: Bad protocol spec '%s'.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001090 filename, linenum, arg ? arg : "<NONE>");
Ben Lindstromade03f62001-12-06 18:22:17 +00001091 if (*intptr == SSH_PROTO_UNKNOWN)
1092 *intptr = value;
1093 break;
1094
1095 case sSubsystem:
1096 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1097 fatal("%s line %d: too many subsystems defined.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001098 filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +00001099 }
1100 arg = strdelim(&cp);
1101 if (!arg || *arg == '\0')
1102 fatal("%s line %d: Missing subsystem name.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001103 filename, linenum);
Darren Tucker45150472006-07-12 22:34:17 +10001104 if (!*activep) {
1105 arg = strdelim(&cp);
1106 break;
1107 }
Ben Lindstromade03f62001-12-06 18:22:17 +00001108 for (i = 0; i < options->num_subsystems; i++)
1109 if (strcmp(arg, options->subsystem_name[i]) == 0)
1110 fatal("%s line %d: Subsystem '%s' already defined.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001111 filename, linenum, arg);
Ben Lindstromade03f62001-12-06 18:22:17 +00001112 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1113 arg = strdelim(&cp);
1114 if (!arg || *arg == '\0')
1115 fatal("%s line %d: Missing subsystem command.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001116 filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +00001117 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
Damien Miller917f9b62006-07-10 20:36:47 +10001118
1119 /* Collect arguments (separate to executable) */
1120 p = xstrdup(arg);
1121 len = strlen(p) + 1;
1122 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1123 len += 1 + strlen(arg);
1124 p = xrealloc(p, 1, len);
1125 strlcat(p, " ", len);
1126 strlcat(p, arg, len);
1127 }
1128 options->subsystem_args[options->num_subsystems] = p;
Ben Lindstromade03f62001-12-06 18:22:17 +00001129 options->num_subsystems++;
1130 break;
1131
1132 case sMaxStartups:
1133 arg = strdelim(&cp);
1134 if (!arg || *arg == '\0')
1135 fatal("%s line %d: Missing MaxStartups spec.",
Damien Miller9f0f5c62001-12-21 14:45:46 +11001136 filename, linenum);
Ben Lindstromade03f62001-12-06 18:22:17 +00001137 if ((n = sscanf(arg, "%d:%d:%d",
1138 &options->max_startups_begin,
1139 &options->max_startups_rate,
1140 &options->max_startups)) == 3) {
1141 if (options->max_startups_begin >
1142 options->max_startups ||
1143 options->max_startups_rate > 100 ||
1144 options->max_startups_rate < 1)
1145 fatal("%s line %d: Illegal MaxStartups spec.",
1146 filename, linenum);
1147 } else if (n != 1)
1148 fatal("%s line %d: Illegal MaxStartups spec.",
1149 filename, linenum);
1150 else
1151 options->max_startups = options->max_startups_begin;
1152 break;
1153
Darren Tucker89413db2004-05-24 10:36:23 +10001154 case sMaxAuthTries:
1155 intptr = &options->max_authtries;
1156 goto parse_int;
1157
Ben Lindstromade03f62001-12-06 18:22:17 +00001158 case sBanner:
1159 charptr = &options->banner;
1160 goto parse_filename;
Damien Millerd8cb1f12008-02-10 22:40:12 +11001161
Ben Lindstromade03f62001-12-06 18:22:17 +00001162 /*
1163 * These options can contain %X options expanded at
1164 * connect time, so that you can specify paths like:
1165 *
1166 * AuthorizedKeysFile /etc/ssh_keys/%u
1167 */
1168 case sAuthorizedKeysFile:
1169 case sAuthorizedKeysFile2:
Damien Miller4dec5d72006-08-05 11:38:40 +10001170 charptr = (opcode == sAuthorizedKeysFile) ?
Ben Lindstromade03f62001-12-06 18:22:17 +00001171 &options->authorized_keys_file :
1172 &options->authorized_keys_file2;
1173 goto parse_filename;
1174
1175 case sClientAliveInterval:
1176 intptr = &options->client_alive_interval;
1177 goto parse_time;
1178
1179 case sClientAliveCountMax:
1180 intptr = &options->client_alive_count_max;
1181 goto parse_int;
1182
Darren Tucker46bc0752004-05-02 22:11:30 +10001183 case sAcceptEnv:
1184 while ((arg = strdelim(&cp)) && *arg != '\0') {
1185 if (strchr(arg, '=') != NULL)
1186 fatal("%s line %d: Invalid environment name.",
1187 filename, linenum);
1188 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1189 fatal("%s line %d: too many allow env.",
1190 filename, linenum);
Darren Tucker45150472006-07-12 22:34:17 +10001191 if (!*activep)
1192 break;
Darren Tucker46bc0752004-05-02 22:11:30 +10001193 options->accept_env[options->num_accept_env++] =
1194 xstrdup(arg);
1195 }
1196 break;
1197
Damien Millerd27b9472005-12-13 19:29:02 +11001198 case sPermitTunnel:
1199 intptr = &options->permit_tun;
Damien Miller7b58e802005-12-13 19:33:19 +11001200 arg = strdelim(&cp);
1201 if (!arg || *arg == '\0')
1202 fatal("%s line %d: Missing yes/point-to-point/"
1203 "ethernet/no argument.", filename, linenum);
1204 value = 0; /* silence compiler */
1205 if (strcasecmp(arg, "ethernet") == 0)
1206 value = SSH_TUNMODE_ETHERNET;
1207 else if (strcasecmp(arg, "point-to-point") == 0)
1208 value = SSH_TUNMODE_POINTOPOINT;
1209 else if (strcasecmp(arg, "yes") == 0)
1210 value = SSH_TUNMODE_YES;
1211 else if (strcasecmp(arg, "no") == 0)
1212 value = SSH_TUNMODE_NO;
1213 else
1214 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1215 "no argument: %s", filename, linenum, arg);
1216 if (*intptr == -1)
1217 *intptr = value;
1218 break;
Damien Millerd27b9472005-12-13 19:29:02 +11001219
Darren Tucker45150472006-07-12 22:34:17 +10001220 case sMatch:
1221 if (cmdline)
1222 fatal("Match directive not supported as a command-line "
1223 "option");
1224 value = match_cfg_line(&cp, linenum, user, host, address);
1225 if (value < 0)
1226 fatal("%s line %d: Bad Match condition", filename,
1227 linenum);
1228 *activep = value;
1229 break;
1230
Damien Miller9b439df2006-07-24 14:04:00 +10001231 case sPermitOpen:
1232 arg = strdelim(&cp);
1233 if (!arg || *arg == '\0')
1234 fatal("%s line %d: missing PermitOpen specification",
1235 filename, linenum);
Damien Miller9fc6a562007-01-05 16:29:02 +11001236 n = options->num_permitted_opens; /* modified later */
Damien Miller9b439df2006-07-24 14:04:00 +10001237 if (strcmp(arg, "any") == 0) {
Damien Miller9fc6a562007-01-05 16:29:02 +11001238 if (*activep && n == -1) {
Damien Miller9b439df2006-07-24 14:04:00 +10001239 channel_clear_adm_permitted_opens();
Damien Millera765cf42006-07-24 14:08:13 +10001240 options->num_permitted_opens = 0;
1241 }
Damien Miller9b439df2006-07-24 14:04:00 +10001242 break;
1243 }
Damien Millera29b95e2007-01-05 16:28:36 +11001244 if (*activep && n == -1)
1245 channel_clear_adm_permitted_opens();
Damien Millera765cf42006-07-24 14:08:13 +10001246 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1247 p = hpdelim(&arg);
1248 if (p == NULL)
1249 fatal("%s line %d: missing host in PermitOpen",
1250 filename, linenum);
1251 p = cleanhostname(p);
1252 if (arg == NULL || (port = a2port(arg)) == 0)
1253 fatal("%s line %d: bad port number in "
1254 "PermitOpen", filename, linenum);
Damien Millera29b95e2007-01-05 16:28:36 +11001255 if (*activep && n == -1)
Damien Millera765cf42006-07-24 14:08:13 +10001256 options->num_permitted_opens =
1257 channel_add_adm_permitted_opens(p, port);
Damien Millera765cf42006-07-24 14:08:13 +10001258 }
Damien Miller9b439df2006-07-24 14:04:00 +10001259 break;
1260
Damien Millere2754432006-07-24 14:06:47 +10001261 case sForceCommand:
1262 if (cp == NULL)
1263 fatal("%.200s line %d: Missing argument.", filename,
1264 linenum);
1265 len = strspn(cp, WHITESPACE);
1266 if (*activep && options->adm_forced_command == NULL)
1267 options->adm_forced_command = xstrdup(cp + len);
1268 return 0;
1269
Damien Millerd8cb1f12008-02-10 22:40:12 +11001270 case sChrootDirectory:
1271 charptr = &options->chroot_directory;
Damien Miller54e37732008-02-10 22:48:55 +11001272
1273 arg = strdelim(&cp);
1274 if (!arg || *arg == '\0')
1275 fatal("%s line %d: missing file name.",
1276 filename, linenum);
1277 if (*activep && *charptr == NULL)
1278 *charptr = xstrdup(arg);
1279 break;
Damien Millerd8cb1f12008-02-10 22:40:12 +11001280
Ben Lindstromade03f62001-12-06 18:22:17 +00001281 case sDeprecated:
Damien Miller996acd22003-04-09 20:59:48 +10001282 logit("%s line %d: Deprecated option %s",
Ben Lindstromade03f62001-12-06 18:22:17 +00001283 filename, linenum, arg);
1284 while (arg)
1285 arg = strdelim(&cp);
1286 break;
1287
Damien Millerf9b3feb2003-05-16 11:38:32 +10001288 case sUnsupported:
1289 logit("%s line %d: Unsupported option %s",
1290 filename, linenum, arg);
1291 while (arg)
1292 arg = strdelim(&cp);
1293 break;
1294
Ben Lindstromade03f62001-12-06 18:22:17 +00001295 default:
1296 fatal("%s line %d: Missing handler for opcode %s (%d)",
1297 filename, linenum, arg, opcode);
1298 }
1299 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1300 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1301 filename, linenum, arg);
1302 return 0;
1303}
1304
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001305/* Reads the server configuration file. */
1306
Damien Miller4af51302000-04-16 11:18:38 +10001307void
Darren Tucker645ab752004-06-25 13:33:20 +10001308load_server_config(const char *filename, Buffer *conf)
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001309{
Darren Tucker645ab752004-06-25 13:33:20 +10001310 char line[1024], *cp;
Ben Lindstrome1353632002-06-23 21:29:23 +00001311 FILE *f;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001312
Darren Tucker645ab752004-06-25 13:33:20 +10001313 debug2("%s: filename %s", __func__, filename);
1314 if ((f = fopen(filename, "r")) == NULL) {
Damien Miller95def091999-11-25 00:26:21 +11001315 perror(filename);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001316 exit(1);
Damien Miller95def091999-11-25 00:26:21 +11001317 }
Darren Tucker645ab752004-06-25 13:33:20 +10001318 buffer_clear(conf);
Damien Miller95def091999-11-25 00:26:21 +11001319 while (fgets(line, sizeof(line), f)) {
Darren Tucker645ab752004-06-25 13:33:20 +10001320 /*
1321 * Trim out comments and strip whitespace
Darren Tuckerfc959702004-07-17 16:12:08 +10001322 * NB - preserve newlines, they are needed to reproduce
Darren Tucker645ab752004-06-25 13:33:20 +10001323 * line numbers later for error messages
1324 */
1325 if ((cp = strchr(line, '#')) != NULL)
1326 memcpy(cp, "\n", 2);
1327 cp = line + strspn(line, " \t\r");
1328
1329 buffer_append(conf, cp, strlen(cp));
1330 }
1331 buffer_append(conf, "\0", 1);
1332 fclose(f);
1333 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1334}
1335
1336void
Darren Tucker45150472006-07-12 22:34:17 +10001337parse_server_match_config(ServerOptions *options, const char *user,
1338 const char *host, const char *address)
Darren Tucker645ab752004-06-25 13:33:20 +10001339{
Darren Tucker45150472006-07-12 22:34:17 +10001340 ServerOptions mo;
1341
1342 initialize_server_options(&mo);
1343 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
Darren Tucker1629c072007-02-19 22:25:37 +11001344 copy_set_server_options(options, &mo, 0);
Darren Tucker45150472006-07-12 22:34:17 +10001345}
1346
Darren Tucker1629c072007-02-19 22:25:37 +11001347/* Helper macros */
1348#define M_CP_INTOPT(n) do {\
1349 if (src->n != -1) \
1350 dst->n = src->n; \
1351} while (0)
1352#define M_CP_STROPT(n) do {\
1353 if (src->n != NULL) { \
1354 if (dst->n != NULL) \
1355 xfree(dst->n); \
1356 dst->n = src->n; \
1357 } \
1358} while(0)
1359
1360/*
1361 * Copy any supported values that are set.
1362 *
1363 * If the preauth flag is set, we do not bother copying the the string or
1364 * array values that are not used pre-authentication, because any that we
1365 * do use must be explictly sent in mm_getpwnamallow().
1366 */
Darren Tucker45150472006-07-12 22:34:17 +10001367void
Darren Tucker1629c072007-02-19 22:25:37 +11001368copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
Darren Tucker45150472006-07-12 22:34:17 +10001369{
Darren Tucker1629c072007-02-19 22:25:37 +11001370 M_CP_INTOPT(password_authentication);
1371 M_CP_INTOPT(gss_authentication);
1372 M_CP_INTOPT(rsa_authentication);
1373 M_CP_INTOPT(pubkey_authentication);
1374 M_CP_INTOPT(kerberos_authentication);
1375 M_CP_INTOPT(hostbased_authentication);
1376 M_CP_INTOPT(kbd_interactive_authentication);
Darren Tucker15f94272008-01-01 20:36:56 +11001377 M_CP_INTOPT(permit_root_login);
Darren Tucker1629c072007-02-19 22:25:37 +11001378
1379 M_CP_INTOPT(allow_tcp_forwarding);
Damien Miller4f755cd2008-05-19 14:57:41 +10001380 M_CP_INTOPT(allow_agent_forwarding);
Darren Tucker1629c072007-02-19 22:25:37 +11001381 M_CP_INTOPT(gateway_ports);
1382 M_CP_INTOPT(x11_display_offset);
1383 M_CP_INTOPT(x11_forwarding);
1384 M_CP_INTOPT(x11_use_localhost);
1385
1386 M_CP_STROPT(banner);
1387 if (preauth)
1388 return;
1389 M_CP_STROPT(adm_forced_command);
Damien Millerd8cb1f12008-02-10 22:40:12 +11001390 M_CP_STROPT(chroot_directory);
Darren Tucker45150472006-07-12 22:34:17 +10001391}
1392
Darren Tucker1629c072007-02-19 22:25:37 +11001393#undef M_CP_INTOPT
1394#undef M_CP_STROPT
1395
Darren Tucker45150472006-07-12 22:34:17 +10001396void
1397parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1398 const char *user, const char *host, const char *address)
1399{
1400 int active, linenum, bad_options = 0;
Darren Tucker9fbac712004-08-12 22:41:44 +10001401 char *cp, *obuf, *cbuf;
Darren Tucker645ab752004-06-25 13:33:20 +10001402
1403 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1404
Darren Tucker9fbac712004-08-12 22:41:44 +10001405 obuf = cbuf = xstrdup(buffer_ptr(conf));
Darren Tucker45150472006-07-12 22:34:17 +10001406 active = user ? 0 : 1;
Darren Tucker137e9c92004-08-13 21:30:24 +10001407 linenum = 1;
Darren Tucker47eede72005-03-14 23:08:12 +11001408 while ((cp = strsep(&cbuf, "\n")) != NULL) {
Darren Tucker645ab752004-06-25 13:33:20 +10001409 if (process_server_config_line(options, cp, filename,
Darren Tucker45150472006-07-12 22:34:17 +10001410 linenum++, &active, user, host, address) != 0)
Damien Miller95def091999-11-25 00:26:21 +11001411 bad_options++;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001412 }
Darren Tucker9fbac712004-08-12 22:41:44 +10001413 xfree(obuf);
Ben Lindstromb5cdc662001-04-16 02:13:26 +00001414 if (bad_options > 0)
1415 fatal("%s: terminating, %d bad configuration options",
1416 filename, bad_options);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001417}