]> andersk Git - openssh.git/blame - servconf.c
- djm@cvs.openbsd.org 2008/06/10 04:17:46
[openssh.git] / servconf.c
CommitLineData
15b5fa9b 1/* $OpenBSD: servconf.c,v 1.181 2008/06/10 03:57:27 djm Exp $ */
8efc0c15 2/*
5260325f 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
6ae2364d 5 *
bcbf86ec 6 * 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".
5260325f 11 */
8efc0c15 12
13#include "includes.h"
8efc0c15 14
5b04a8bf 15#include <sys/types.h>
16#include <sys/socket.h>
17
28cb0a43 18#include <netdb.h>
fa47fe3c 19#include <pwd.h>
cf851879 20#include <stdio.h>
ffa517a8 21#include <stdlib.h>
00146caa 22#include <string.h>
31652869 23#include <signal.h>
5188ba17 24#include <unistd.h>
31652869 25#include <stdarg.h>
c8dfff33 26
3593bdc0 27#include "openbsd-compat/sys-queue.h"
31652869 28#include "xmalloc.h"
8efc0c15 29#include "ssh.h"
42f11eb2 30#include "log.h"
31652869 31#include "buffer.h"
8efc0c15 32#include "servconf.h"
a8be9f80 33#include "compat.h"
42f11eb2 34#include "pathnames.h"
42f11eb2 35#include "misc.h"
36#include "cipher.h"
31652869 37#include "key.h"
b2552997 38#include "kex.h"
39#include "mac.h"
d231781a 40#include "match.h"
2fefbadf 41#include "channels.h"
fa47fe3c 42#include "groupaccess.h"
42f11eb2 43
396c147e 44static void add_listen_addr(ServerOptions *, char *, u_short);
45static void add_one_listen_addr(ServerOptions *, char *, u_short);
48e671d5 46
1853d1ef 47/* Use of privilege separation or not */
48extern int use_privsep;
d231781a 49extern Buffer cfg;
42f11eb2 50
8efc0c15 51/* Initializes the server options to their default values. */
52
6ae2364d 53void
5260325f 54initialize_server_options(ServerOptions *options)
8efc0c15 55{
5260325f 56 memset(options, 0, sizeof(*options));
e15895cd 57
58 /* Portable-specific options */
7fceb20d 59 options->use_pam = -1;
e15895cd 60
61 /* Standard Options */
48e671d5 62 options->num_ports = 0;
63 options->ports_from_cmdline = 0;
64 options->listen_addrs = NULL;
31b41ceb 65 options->address_family = -1;
fa08c86b 66 options->num_host_key_files = 0;
0fbe8c74 67 options->pid_file = NULL;
5260325f 68 options->server_key_bits = -1;
69 options->login_grace_time = -1;
70 options->key_regeneration_time = -1;
15853e93 71 options->permit_root_login = PERMIT_NOT_SET;
5260325f 72 options->ignore_rhosts = -1;
73 options->ignore_user_known_hosts = -1;
74 options->print_motd = -1;
4f4648f9 75 options->print_lastlog = -1;
5260325f 76 options->x11_forwarding = -1;
77 options->x11_display_offset = -1;
e6e573bd 78 options->x11_use_localhost = -1;
fa649821 79 options->xauth_location = NULL;
5260325f 80 options->strict_modes = -1;
fd573618 81 options->tcp_keep_alive = -1;
5eaf8578 82 options->log_facility = SYSLOG_FACILITY_NOT_SET;
83 options->log_level = SYSLOG_LEVEL_NOT_SET;
5260325f 84 options->rhosts_rsa_authentication = -1;
8002af61 85 options->hostbased_authentication = -1;
86 options->hostbased_uses_name_from_packet_only = -1;
5260325f 87 options->rsa_authentication = -1;
fa08c86b 88 options->pubkey_authentication = -1;
5260325f 89 options->kerberos_authentication = -1;
90 options->kerberos_or_local_passwd = -1;
91 options->kerberos_ticket_cleanup = -1;
a1e30b47 92 options->kerberos_get_afs_token = -1;
7364bd04 93 options->gss_authentication=-1;
94 options->gss_cleanup_creds = -1;
5260325f 95 options->password_authentication = -1;
94ec8c6b 96 options->kbd_interactive_authentication = -1;
5ba55ada 97 options->challenge_response_authentication = -1;
5260325f 98 options->permit_empty_passwd = -1;
f00bab84 99 options->permit_user_env = -1;
5260325f 100 options->use_login = -1;
636f76ca 101 options->compression = -1;
33de75a3 102 options->allow_tcp_forwarding = -1;
43c3f85c 103 options->allow_agent_forwarding = -1;
5260325f 104 options->num_allow_users = 0;
105 options->num_deny_users = 0;
106 options->num_allow_groups = 0;
107 options->num_deny_groups = 0;
a8be9f80 108 options->ciphers = NULL;
b2552997 109 options->macs = NULL;
a8be9f80 110 options->protocol = SSH_PROTO_UNKNOWN;
1d1ffb87 111 options->gateway_ports = -1;
38c295d6 112 options->num_subsystems = 0;
c345cf9d 113 options->max_startups_begin = -1;
114 options->max_startups_rate = -1;
089fbbd2 115 options->max_startups = -1;
af4bd935 116 options->max_authtries = -1;
c6dca55e 117 options->max_sessions = -1;
eea39c02 118 options->banner = NULL;
c5a7d788 119 options->use_dns = -1;
3ffc6336 120 options->client_alive_interval = -1;
121 options->client_alive_count_max = -1;
c8445989 122 options->authorized_keys_file = NULL;
123 options->authorized_keys_file2 = NULL;
61a2c1da 124 options->num_accept_env = 0;
d20f3c9e 125 options->permit_tun = -1;
ea46e550 126 options->num_permitted_opens = -1;
e7259e8d 127 options->adm_forced_command = NULL;
db49deeb 128 options->chroot_directory = NULL;
8efc0c15 129}
130
6ae2364d 131void
5260325f 132fill_default_server_options(ServerOptions *options)
8efc0c15 133{
e15895cd 134 /* Portable-specific options */
7fceb20d 135 if (options->use_pam == -1)
0a23d79f 136 options->use_pam = 0;
e15895cd 137
138 /* Standard Options */
fa08c86b 139 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)
0f84fe37 144 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 }
fa08c86b 152 }
48e671d5 153 if (options->num_ports == 0)
154 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
155 if (options->listen_addrs == NULL)
2d2a2c65 156 add_listen_addr(options, NULL, 0);
0fbe8c74 157 if (options->pid_file == NULL)
42f11eb2 158 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
5260325f 159 if (options->server_key_bits == -1)
160 options->server_key_bits = 768;
161 if (options->login_grace_time == -1)
3445ca02 162 options->login_grace_time = 120;
5260325f 163 if (options->key_regeneration_time == -1)
164 options->key_regeneration_time = 3600;
15853e93 165 if (options->permit_root_login == PERMIT_NOT_SET)
166 options->permit_root_login = PERMIT_YES;
5260325f 167 if (options->ignore_rhosts == -1)
c8d54615 168 options->ignore_rhosts = 1;
5260325f 169 if (options->ignore_user_known_hosts == -1)
170 options->ignore_user_known_hosts = 0;
5260325f 171 if (options->print_motd == -1)
172 options->print_motd = 1;
4f4648f9 173 if (options->print_lastlog == -1)
174 options->print_lastlog = 1;
5260325f 175 if (options->x11_forwarding == -1)
c8d54615 176 options->x11_forwarding = 0;
5260325f 177 if (options->x11_display_offset == -1)
c8d54615 178 options->x11_display_offset = 10;
e6e573bd 179 if (options->x11_use_localhost == -1)
180 options->x11_use_localhost = 1;
fa649821 181 if (options->xauth_location == NULL)
fd9ede94 182 options->xauth_location = _PATH_XAUTH;
5260325f 183 if (options->strict_modes == -1)
184 options->strict_modes = 1;
fd573618 185 if (options->tcp_keep_alive == -1)
186 options->tcp_keep_alive = 1;
5eaf8578 187 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
5260325f 188 options->log_facility = SYSLOG_FACILITY_AUTH;
5eaf8578 189 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
59c97189 190 options->log_level = SYSLOG_LEVEL_INFO;
5260325f 191 if (options->rhosts_rsa_authentication == -1)
c8d54615 192 options->rhosts_rsa_authentication = 0;
8002af61 193 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;
5260325f 197 if (options->rsa_authentication == -1)
198 options->rsa_authentication = 1;
fa08c86b 199 if (options->pubkey_authentication == -1)
200 options->pubkey_authentication = 1;
5260325f 201 if (options->kerberos_authentication == -1)
eadc806d 202 options->kerberos_authentication = 0;
5260325f 203 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;
a1e30b47 207 if (options->kerberos_get_afs_token == -1)
208 options->kerberos_get_afs_token = 0;
7364bd04 209 if (options->gss_authentication == -1)
210 options->gss_authentication = 0;
211 if (options->gss_cleanup_creds == -1)
212 options->gss_cleanup_creds = 1;
5260325f 213 if (options->password_authentication == -1)
214 options->password_authentication = 1;
94ec8c6b 215 if (options->kbd_interactive_authentication == -1)
216 options->kbd_interactive_authentication = 0;
5ba55ada 217 if (options->challenge_response_authentication == -1)
218 options->challenge_response_authentication = 1;
5260325f 219 if (options->permit_empty_passwd == -1)
c8d54615 220 options->permit_empty_passwd = 0;
f00bab84 221 if (options->permit_user_env == -1)
222 options->permit_user_env = 0;
5260325f 223 if (options->use_login == -1)
224 options->use_login = 0;
636f76ca 225 if (options->compression == -1)
07200973 226 options->compression = COMP_DELAYED;
33de75a3 227 if (options->allow_tcp_forwarding == -1)
228 options->allow_tcp_forwarding = 1;
43c3f85c 229 if (options->allow_agent_forwarding == -1)
230 options->allow_agent_forwarding = 1;
1d1ffb87 231 if (options->gateway_ports == -1)
232 options->gateway_ports = 0;
089fbbd2 233 if (options->max_startups == -1)
234 options->max_startups = 10;
c345cf9d 235 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;
af4bd935 239 if (options->max_authtries == -1)
240 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
c6dca55e 241 if (options->max_sessions == -1)
242 options->max_sessions = DEFAULT_SESSIONS_MAX;
c5a7d788 243 if (options->use_dns == -1)
244 options->use_dns = 1;
3ffc6336 245 if (options->client_alive_interval == -1)
184eed6a 246 options->client_alive_interval = 0;
3ffc6336 247 if (options->client_alive_count_max == -1)
248 options->client_alive_count_max = 3;
5df83e07 249 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;
d20f3c9e 258 if (options->permit_tun == -1)
a4f24bf8 259 options->permit_tun = SSH_TUNMODE_NO;
1853d1ef 260
2ee1b704 261 /* Turn privilege separation on by default */
1853d1ef 262 if (use_privsep == -1)
2ee1b704 263 use_privsep = 1;
e299a298 264
4165b82e 265#ifndef HAVE_MMAP
e299a298 266 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
8efc0c15 274}
275
8efc0c15 276/* Keyword tokens. */
5260325f 277typedef enum {
278 sBadOption, /* == unknown option */
e15895cd 279 /* Portable-specific options */
7fceb20d 280 sUsePAM,
e15895cd 281 /* Standard Options */
5260325f 282 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
283 sPermitRootLogin, sLogFacility, sLogLevel,
0598d99d 284 sRhostsRSAAuthentication, sRSAAuthentication,
5260325f 285 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
a1e30b47 286 sKerberosGetAFSToken,
1c590258 287 sKerberosTgtPassing, sChallengeResponseAuthentication,
31b41ceb 288 sPasswordAuthentication, sKbdInteractiveAuthentication,
289 sListenAddress, sAddressFamily,
4f4648f9 290 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
e6e573bd 291 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
fd573618 292 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
f00bab84 293 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
33de75a3 294 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
b2552997 295 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
af4bd935 296 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
c6dca55e 297 sMaxStartups, sMaxAuthTries, sMaxSessions,
c5a7d788 298 sBanner, sUseDNS, sHostbasedAuthentication,
184eed6a 299 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
c8445989 300 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
d20f3c9e 301 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
db49deeb 302 sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
43c3f85c 303 sUsePrivilegeSeparation, sAllowAgentForwarding,
a2144546 304 sDeprecated, sUnsupported
8efc0c15 305} ServerOpCodes;
306
d231781a 307#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
8efc0c15 311/* Textual representation of the tokens. */
5260325f 312static struct {
313 const char *name;
314 ServerOpCodes opcode;
d231781a 315 u_int flags;
5260325f 316} keywords[] = {
e15895cd 317 /* Portable-specific options */
b06b11ad 318#ifdef USE_PAM
d231781a 319 { "usepam", sUsePAM, SSHCFG_GLOBAL },
b06b11ad 320#else
d231781a 321 { "usepam", sUnsupported, SSHCFG_GLOBAL },
b06b11ad 322#endif
d231781a 323 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
e15895cd 324 /* Standard Options */
d231781a 325 { "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 },
2ef741a3 332 { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
d231781a 333 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
334 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
335 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
03bcbf84 336 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
337 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
d231781a 338 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
03bcbf84 339 { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
340 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
d231781a 341 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
1c590258 342#ifdef KRB5
03bcbf84 343 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
d231781a 344 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
345 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
bcfcc5f9 346#ifdef USE_AFS
d231781a 347 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
309af4e5 348#else
d231781a 349 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
309af4e5 350#endif
a2144546 351#else
03bcbf84 352 { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
d231781a 353 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
354 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
355 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
a2144546 356#endif
d231781a 357 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
358 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
7364bd04 359#ifdef GSSAPI
03bcbf84 360 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
d231781a 361 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
7364bd04 362#else
03bcbf84 363 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
d231781a 364 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
7364bd04 365#endif
03bcbf84 366 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
367 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
121c4a34 368 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
d231781a 369 { "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 },
691712e0 377 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
378 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
379 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
d231781a 380 { "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 },
43c3f85c 389 { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
d231781a 390 { "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 },
c6dca55e 401 { "maxsessions", sMaxSessions, SSHCFG_ALL },
03bcbf84 402 { "banner", sBanner, SSHCFG_ALL },
d231781a 403 { "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 },
2fefbadf 413 { "match", sMatch, SSHCFG_ALL },
414 { "permitopen", sPermitOpen, SSHCFG_ALL },
e7259e8d 415 { "forcecommand", sForceCommand, SSHCFG_ALL },
db49deeb 416 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
d231781a 417 { NULL, sBadOption, 0 }
8efc0c15 418};
419
aa3378df 420/*
6be9a5e8 421 * Returns the number of the token pointed to by cp or sBadOption.
aa3378df 422 */
8efc0c15 423
6ae2364d 424static ServerOpCodes
5260325f 425parse_token(const char *cp, const char *filename,
d231781a 426 int linenum, u_int *flags)
8efc0c15 427{
1e3b8b07 428 u_int i;
8efc0c15 429
5260325f 430 for (i = 0; keywords[i].name; i++)
d231781a 431 if (strcasecmp(cp, keywords[i].name) == 0) {
432 *flags = keywords[i].flags;
5260325f 433 return keywords[i].opcode;
d231781a 434 }
8efc0c15 435
b7c70970 436 error("%s: line %d: Bad configuration option: %s",
437 filename, linenum, cp);
5260325f 438 return sBadOption;
8efc0c15 439}
440
396c147e 441static void
2d2a2c65 442add_listen_addr(ServerOptions *options, char *addr, u_short port)
48e671d5 443{
2ceb8101 444 u_int i;
48e671d5 445
446 if (options->num_ports == 0)
447 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
31b41ceb 448 if (options->address_family == -1)
449 options->address_family = AF_UNSPEC;
2d2a2c65 450 if (port == 0)
d11c1288 451 for (i = 0; i < options->num_ports; i++)
452 add_one_listen_addr(options, addr, options->ports[i]);
453 else
2d2a2c65 454 add_one_listen_addr(options, addr, port);
d11c1288 455}
456
396c147e 457static void
d11c1288 458add_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));
31b41ceb 465 hints.ai_family = options->address_family;
d11c1288 466 hints.ai_socktype = SOCK_STREAM;
467 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
7528d467 468 snprintf(strport, sizeof strport, "%u", port);
d11c1288 469 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
470 fatal("bad addr or host: %s (%s)",
471 addr ? addr : "<NULL>",
bb4626fe 472 ssh_gai_strerror(gaierr));
d11c1288 473 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
474 ;
475 ai->ai_next = options->listen_addrs;
476 options->listen_addrs = aitop;
48e671d5 477}
478
d231781a 479/*
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
fa47fe3c 512static int
513match_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
d231781a 557static int
558match_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);
fa47fe3c 588 } 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 }
d231781a 595 } 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) {
15b5fa9b 606 switch (addr_match_list(address, arg)) {
607 case 1:
d231781a 608 debug("connection from %.100s matched 'Address "
609 "%.100s' at line %d", address, arg, line);
15b5fa9b 610 break;
611 case 0:
612 result = 0;
613 break;
614 case -1:
615 return -1;
616 }
d231781a 617 } else {
618 error("Unsupported Match attribute %s", attrib);
619 return -1;
620 }
621 }
622 if (user != NULL)
623 debug3("match %sfound", result ? "" : "not ");
624 *condition = cp;
625 return result;
626}
627
e7259e8d 628#define WHITESPACE " \t\r\n"
629
2717fa0f 630int
631process_server_config_line(ServerOptions *options, char *line,
d231781a 632 const char *filename, int linenum, int *activep, const char *user,
633 const char *host, const char *address)
8efc0c15 634{
d11c1288 635 char *cp, **charptr, *arg, *p;
d231781a 636 int cmdline = 0, *intptr, value, n;
2a72bc03 637 SyslogFacility *log_facility_ptr;
638 LogLevel *log_level_ptr;
5260325f 639 ServerOpCodes opcode;
3867aa0a 640 u_short port;
d231781a 641 u_int i, flags = 0;
d66ce1a1 642 size_t len;
5260325f 643
2717fa0f 644 cp = line;
0f8cd5a6 645 if ((arg = strdelim(&cp)) == NULL)
88299971 646 return 0;
2717fa0f 647 /* Ignore leading whitespace */
648 if (*arg == '\0')
704b1659 649 arg = strdelim(&cp);
2717fa0f 650 if (!arg || !*arg || *arg == '#')
651 return 0;
652 intptr = NULL;
653 charptr = NULL;
d231781a 654 opcode = parse_token(arg, filename, linenum, &flags);
655
656 if (activep == NULL) { /* We are processing a command line directive */
657 cmdline = 1;
658 activep = &cmdline;
659 }
660 if (*activep && opcode != sMatch)
661 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
662 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
663 if (user == NULL) {
664 fatal("%s line %d: Directive '%s' is not allowed "
665 "within a Match block", filename, linenum, arg);
666 } else { /* this is a directive we have already processed */
667 while (arg)
668 arg = strdelim(&cp);
669 return 0;
670 }
671 }
672
2717fa0f 673 switch (opcode) {
674 /* Portable-specific options */
7fceb20d 675 case sUsePAM:
676 intptr = &options->use_pam;
2717fa0f 677 goto parse_flag;
48e671d5 678
2717fa0f 679 /* Standard Options */
680 case sBadOption:
681 return -1;
682 case sPort:
683 /* ignore ports from configfile if cmdline specifies ports */
684 if (options->ports_from_cmdline)
685 return 0;
686 if (options->listen_addrs != NULL)
687 fatal("%s line %d: ports must be specified before "
3a454b6a 688 "ListenAddress.", filename, linenum);
2717fa0f 689 if (options->num_ports >= MAX_PORTS)
690 fatal("%s line %d: too many ports.",
691 filename, linenum);
692 arg = strdelim(&cp);
693 if (!arg || *arg == '\0')
694 fatal("%s line %d: missing port number.",
695 filename, linenum);
696 options->ports[options->num_ports++] = a2port(arg);
697 if (options->ports[options->num_ports-1] == 0)
698 fatal("%s line %d: Badly formatted port number.",
699 filename, linenum);
700 break;
701
702 case sServerKeyBits:
703 intptr = &options->server_key_bits;
c6dca55e 704 parse_int:
2717fa0f 705 arg = strdelim(&cp);
706 if (!arg || *arg == '\0')
707 fatal("%s line %d: missing integer value.",
708 filename, linenum);
709 value = atoi(arg);
d231781a 710 if (*activep && *intptr == -1)
2717fa0f 711 *intptr = value;
712 break;
713
714 case sLoginGraceTime:
715 intptr = &options->login_grace_time;
c6dca55e 716 parse_time:
2717fa0f 717 arg = strdelim(&cp);
718 if (!arg || *arg == '\0')
719 fatal("%s line %d: missing time value.",
720 filename, linenum);
721 if ((value = convtime(arg)) == -1)
722 fatal("%s line %d: invalid time value.",
723 filename, linenum);
724 if (*intptr == -1)
725 *intptr = value;
726 break;
727
728 case sKeyRegenerationTime:
729 intptr = &options->key_regeneration_time;
730 goto parse_time;
731
732 case sListenAddress:
733 arg = strdelim(&cp);
3867aa0a 734 if (arg == NULL || *arg == '\0')
735 fatal("%s line %d: missing address",
2717fa0f 736 filename, linenum);
91135a0e 737 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
738 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
739 && strchr(p+1, ':') != NULL) {
740 add_listen_addr(options, arg, 0);
741 break;
742 }
3867aa0a 743 p = hpdelim(&arg);
744 if (p == NULL)
745 fatal("%s line %d: bad address:port usage",
2717fa0f 746 filename, linenum);
3867aa0a 747 p = cleanhostname(p);
748 if (arg == NULL)
749 port = 0;
750 else if ((port = a2port(arg)) == 0)
751 fatal("%s line %d: bad port number", filename, linenum);
752
753 add_listen_addr(options, p, port);
754
2717fa0f 755 break;
756
31b41ceb 757 case sAddressFamily:
758 arg = strdelim(&cp);
38634ff6 759 if (!arg || *arg == '\0')
760 fatal("%s line %d: missing address family.",
761 filename, linenum);
31b41ceb 762 intptr = &options->address_family;
763 if (options->listen_addrs != NULL)
764 fatal("%s line %d: address family must be specified before "
765 "ListenAddress.", filename, linenum);
766 if (strcasecmp(arg, "inet") == 0)
767 value = AF_INET;
768 else if (strcasecmp(arg, "inet6") == 0)
769 value = AF_INET6;
770 else if (strcasecmp(arg, "any") == 0)
771 value = AF_UNSPEC;
772 else
773 fatal("%s line %d: unsupported address family \"%s\".",
774 filename, linenum, arg);
775 if (*intptr == -1)
776 *intptr = value;
777 break;
778
2717fa0f 779 case sHostKeyFile:
780 intptr = &options->num_host_key_files;
781 if (*intptr >= MAX_HOSTKEYS)
782 fatal("%s line %d: too many host keys specified (max %d).",
783 filename, linenum, MAX_HOSTKEYS);
784 charptr = &options->host_key_files[*intptr];
c6dca55e 785 parse_filename:
2717fa0f 786 arg = strdelim(&cp);
787 if (!arg || *arg == '\0')
788 fatal("%s line %d: missing file name.",
789 filename, linenum);
d231781a 790 if (*activep && *charptr == NULL) {
2717fa0f 791 *charptr = tilde_expand_filename(arg, getuid());
792 /* increase optional counter */
793 if (intptr != NULL)
794 *intptr = *intptr + 1;
795 }
796 break;
0fbe8c74 797
2717fa0f 798 case sPidFile:
799 charptr = &options->pid_file;
800 goto parse_filename;
5260325f 801
2717fa0f 802 case sPermitRootLogin:
803 intptr = &options->permit_root_login;
804 arg = strdelim(&cp);
805 if (!arg || *arg == '\0')
806 fatal("%s line %d: missing yes/"
807 "without-password/forced-commands-only/no "
808 "argument.", filename, linenum);
809 value = 0; /* silence compiler */
810 if (strcmp(arg, "without-password") == 0)
811 value = PERMIT_NO_PASSWD;
812 else if (strcmp(arg, "forced-commands-only") == 0)
813 value = PERMIT_FORCED_ONLY;
814 else if (strcmp(arg, "yes") == 0)
815 value = PERMIT_YES;
816 else if (strcmp(arg, "no") == 0)
817 value = PERMIT_NO;
818 else
819 fatal("%s line %d: Bad yes/"
820 "without-password/forced-commands-only/no "
821 "argument: %s", filename, linenum, arg);
2ef741a3 822 if (*activep && *intptr == -1)
2717fa0f 823 *intptr = value;
824 break;
825
826 case sIgnoreRhosts:
827 intptr = &options->ignore_rhosts;
c6dca55e 828 parse_flag:
2717fa0f 829 arg = strdelim(&cp);
830 if (!arg || *arg == '\0')
831 fatal("%s line %d: missing yes/no argument.",
832 filename, linenum);
833 value = 0; /* silence compiler */
834 if (strcmp(arg, "yes") == 0)
835 value = 1;
836 else if (strcmp(arg, "no") == 0)
837 value = 0;
838 else
839 fatal("%s line %d: Bad yes/no argument: %s",
840 filename, linenum, arg);
d231781a 841 if (*activep && *intptr == -1)
2717fa0f 842 *intptr = value;
843 break;
844
845 case sIgnoreUserKnownHosts:
846 intptr = &options->ignore_user_known_hosts;
847 goto parse_flag;
848
2717fa0f 849 case sRhostsRSAAuthentication:
850 intptr = &options->rhosts_rsa_authentication;
851 goto parse_flag;
852
853 case sHostbasedAuthentication:
854 intptr = &options->hostbased_authentication;
855 goto parse_flag;
856
857 case sHostbasedUsesNameFromPacketOnly:
858 intptr = &options->hostbased_uses_name_from_packet_only;
859 goto parse_flag;
860
861 case sRSAAuthentication:
862 intptr = &options->rsa_authentication;
863 goto parse_flag;
864
865 case sPubkeyAuthentication:
866 intptr = &options->pubkey_authentication;
867 goto parse_flag;
d0ec7f42 868
2717fa0f 869 case sKerberosAuthentication:
870 intptr = &options->kerberos_authentication;
871 goto parse_flag;
5260325f 872
2717fa0f 873 case sKerberosOrLocalPasswd:
874 intptr = &options->kerberos_or_local_passwd;
875 goto parse_flag;
5260325f 876
2717fa0f 877 case sKerberosTicketCleanup:
878 intptr = &options->kerberos_ticket_cleanup;
879 goto parse_flag;
d0ec7f42 880
a1e30b47 881 case sKerberosGetAFSToken:
882 intptr = &options->kerberos_get_afs_token;
883 goto parse_flag;
884
7364bd04 885 case sGssAuthentication:
886 intptr = &options->gss_authentication;
887 goto parse_flag;
888
889 case sGssCleanupCreds:
890 intptr = &options->gss_cleanup_creds;
891 goto parse_flag;
892
2717fa0f 893 case sPasswordAuthentication:
894 intptr = &options->password_authentication;
895 goto parse_flag;
5260325f 896
2717fa0f 897 case sKbdInteractiveAuthentication:
898 intptr = &options->kbd_interactive_authentication;
899 goto parse_flag;
8002af61 900
2717fa0f 901 case sChallengeResponseAuthentication:
902 intptr = &options->challenge_response_authentication;
903 goto parse_flag;
8002af61 904
2717fa0f 905 case sPrintMotd:
906 intptr = &options->print_motd;
907 goto parse_flag;
5260325f 908
2717fa0f 909 case sPrintLastLog:
910 intptr = &options->print_lastlog;
911 goto parse_flag;
5260325f 912
2717fa0f 913 case sX11Forwarding:
914 intptr = &options->x11_forwarding;
915 goto parse_flag;
5260325f 916
2717fa0f 917 case sX11DisplayOffset:
918 intptr = &options->x11_display_offset;
919 goto parse_int;
8efc0c15 920
e6e573bd 921 case sX11UseLocalhost:
922 intptr = &options->x11_use_localhost;
923 goto parse_flag;
924
2717fa0f 925 case sXAuthLocation:
926 charptr = &options->xauth_location;
927 goto parse_filename;
5260325f 928
2717fa0f 929 case sStrictModes:
930 intptr = &options->strict_modes;
931 goto parse_flag;
5260325f 932
fd573618 933 case sTCPKeepAlive:
934 intptr = &options->tcp_keep_alive;
2717fa0f 935 goto parse_flag;
33de75a3 936
2717fa0f 937 case sEmptyPasswd:
938 intptr = &options->permit_empty_passwd;
939 goto parse_flag;
5260325f 940
f00bab84 941 case sPermitUserEnvironment:
942 intptr = &options->permit_user_env;
943 goto parse_flag;
944
2717fa0f 945 case sUseLogin:
946 intptr = &options->use_login;
947 goto parse_flag;
5260325f 948
636f76ca 949 case sCompression:
950 intptr = &options->compression;
07200973 951 arg = strdelim(&cp);
952 if (!arg || *arg == '\0')
953 fatal("%s line %d: missing yes/no/delayed "
954 "argument.", filename, linenum);
955 value = 0; /* silence compiler */
956 if (strcmp(arg, "delayed") == 0)
957 value = COMP_DELAYED;
958 else if (strcmp(arg, "yes") == 0)
959 value = COMP_ZLIB;
960 else if (strcmp(arg, "no") == 0)
961 value = COMP_NONE;
962 else
963 fatal("%s line %d: Bad yes/no/delayed "
964 "argument: %s", filename, linenum, arg);
965 if (*intptr == -1)
966 *intptr = value;
967 break;
636f76ca 968
2717fa0f 969 case sGatewayPorts:
970 intptr = &options->gateway_ports;
3867aa0a 971 arg = strdelim(&cp);
972 if (!arg || *arg == '\0')
973 fatal("%s line %d: missing yes/no/clientspecified "
974 "argument.", filename, linenum);
975 value = 0; /* silence compiler */
976 if (strcmp(arg, "clientspecified") == 0)
977 value = 2;
978 else if (strcmp(arg, "yes") == 0)
979 value = 1;
980 else if (strcmp(arg, "no") == 0)
981 value = 0;
982 else
983 fatal("%s line %d: Bad yes/no/clientspecified "
984 "argument: %s", filename, linenum, arg);
f3e3d6ce 985 if (*activep && *intptr == -1)
3867aa0a 986 *intptr = value;
987 break;
5260325f 988
c5a7d788 989 case sUseDNS:
990 intptr = &options->use_dns;
2717fa0f 991 goto parse_flag;
5260325f 992
2717fa0f 993 case sLogFacility:
2a72bc03 994 log_facility_ptr = &options->log_facility;
2717fa0f 995 arg = strdelim(&cp);
996 value = log_facility_number(arg);
5eaf8578 997 if (value == SYSLOG_FACILITY_NOT_SET)
2717fa0f 998 fatal("%.200s line %d: unsupported log facility '%s'",
999 filename, linenum, arg ? arg : "<NONE>");
2a72bc03 1000 if (*log_facility_ptr == -1)
1001 *log_facility_ptr = (SyslogFacility) value;
2717fa0f 1002 break;
1003
1004 case sLogLevel:
2a72bc03 1005 log_level_ptr = &options->log_level;
2717fa0f 1006 arg = strdelim(&cp);
1007 value = log_level_number(arg);
5eaf8578 1008 if (value == SYSLOG_LEVEL_NOT_SET)
2717fa0f 1009 fatal("%.200s line %d: unsupported log level '%s'",
1010 filename, linenum, arg ? arg : "<NONE>");
2a72bc03 1011 if (*log_level_ptr == -1)
1012 *log_level_ptr = (LogLevel) value;
2717fa0f 1013 break;
1014
1015 case sAllowTcpForwarding:
1016 intptr = &options->allow_tcp_forwarding;
1017 goto parse_flag;
1018
43c3f85c 1019 case sAllowAgentForwarding:
1020 intptr = &options->allow_agent_forwarding;
1021 goto parse_flag;
1022
1853d1ef 1023 case sUsePrivilegeSeparation:
1024 intptr = &use_privsep;
1025 goto parse_flag;
1026
2717fa0f 1027 case sAllowUsers:
1028 while ((arg = strdelim(&cp)) && *arg != '\0') {
1029 if (options->num_allow_users >= MAX_ALLOW_USERS)
1030 fatal("%s line %d: too many allow users.",
1031 filename, linenum);
7528d467 1032 options->allow_users[options->num_allow_users++] =
1033 xstrdup(arg);
2717fa0f 1034 }
1035 break;
a8be9f80 1036
2717fa0f 1037 case sDenyUsers:
1038 while ((arg = strdelim(&cp)) && *arg != '\0') {
1039 if (options->num_deny_users >= MAX_DENY_USERS)
d4f40d92 1040 fatal("%s line %d: too many deny users.",
2717fa0f 1041 filename, linenum);
7528d467 1042 options->deny_users[options->num_deny_users++] =
1043 xstrdup(arg);
2717fa0f 1044 }
1045 break;
b2552997 1046
2717fa0f 1047 case sAllowGroups:
1048 while ((arg = strdelim(&cp)) && *arg != '\0') {
1049 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1050 fatal("%s line %d: too many allow groups.",
1051 filename, linenum);
7528d467 1052 options->allow_groups[options->num_allow_groups++] =
1053 xstrdup(arg);
2717fa0f 1054 }
1055 break;
a8be9f80 1056
2717fa0f 1057 case sDenyGroups:
1058 while ((arg = strdelim(&cp)) && *arg != '\0') {
1059 if (options->num_deny_groups >= MAX_DENY_GROUPS)
1060 fatal("%s line %d: too many deny groups.",
1061 filename, linenum);
1062 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1063 }
1064 break;
38c295d6 1065
2717fa0f 1066 case sCiphers:
1067 arg = strdelim(&cp);
1068 if (!arg || *arg == '\0')
1069 fatal("%s line %d: Missing argument.", filename, linenum);
1070 if (!ciphers_valid(arg))
1071 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1072 filename, linenum, arg ? arg : "<NONE>");
1073 if (options->ciphers == NULL)
1074 options->ciphers = xstrdup(arg);
1075 break;
1076
1077 case sMacs:
1078 arg = strdelim(&cp);
1079 if (!arg || *arg == '\0')
1080 fatal("%s line %d: Missing argument.", filename, linenum);
1081 if (!mac_valid(arg))
1082 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1083 filename, linenum, arg ? arg : "<NONE>");
1084 if (options->macs == NULL)
1085 options->macs = xstrdup(arg);
1086 break;
1087
1088 case sProtocol:
1089 intptr = &options->protocol;
1090 arg = strdelim(&cp);
1091 if (!arg || *arg == '\0')
1092 fatal("%s line %d: Missing argument.", filename, linenum);
1093 value = proto_spec(arg);
1094 if (value == SSH_PROTO_UNKNOWN)
1095 fatal("%s line %d: Bad protocol spec '%s'.",
184eed6a 1096 filename, linenum, arg ? arg : "<NONE>");
2717fa0f 1097 if (*intptr == SSH_PROTO_UNKNOWN)
1098 *intptr = value;
1099 break;
1100
1101 case sSubsystem:
1102 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1103 fatal("%s line %d: too many subsystems defined.",
184eed6a 1104 filename, linenum);
2717fa0f 1105 }
1106 arg = strdelim(&cp);
1107 if (!arg || *arg == '\0')
1108 fatal("%s line %d: Missing subsystem name.",
184eed6a 1109 filename, linenum);
d231781a 1110 if (!*activep) {
1111 arg = strdelim(&cp);
1112 break;
1113 }
2717fa0f 1114 for (i = 0; i < options->num_subsystems; i++)
1115 if (strcmp(arg, options->subsystem_name[i]) == 0)
1116 fatal("%s line %d: Subsystem '%s' already defined.",
184eed6a 1117 filename, linenum, arg);
2717fa0f 1118 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1119 arg = strdelim(&cp);
1120 if (!arg || *arg == '\0')
1121 fatal("%s line %d: Missing subsystem command.",
184eed6a 1122 filename, linenum);
2717fa0f 1123 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
d66ce1a1 1124
1125 /* Collect arguments (separate to executable) */
1126 p = xstrdup(arg);
1127 len = strlen(p) + 1;
1128 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1129 len += 1 + strlen(arg);
1130 p = xrealloc(p, 1, len);
1131 strlcat(p, " ", len);
1132 strlcat(p, arg, len);
1133 }
1134 options->subsystem_args[options->num_subsystems] = p;
2717fa0f 1135 options->num_subsystems++;
1136 break;
1137
1138 case sMaxStartups:
1139 arg = strdelim(&cp);
1140 if (!arg || *arg == '\0')
1141 fatal("%s line %d: Missing MaxStartups spec.",
184eed6a 1142 filename, linenum);
2717fa0f 1143 if ((n = sscanf(arg, "%d:%d:%d",
1144 &options->max_startups_begin,
1145 &options->max_startups_rate,
1146 &options->max_startups)) == 3) {
1147 if (options->max_startups_begin >
1148 options->max_startups ||
1149 options->max_startups_rate > 100 ||
1150 options->max_startups_rate < 1)
c345cf9d 1151 fatal("%s line %d: Illegal MaxStartups spec.",
97de229c 1152 filename, linenum);
2717fa0f 1153 } else if (n != 1)
1154 fatal("%s line %d: Illegal MaxStartups spec.",
1155 filename, linenum);
1156 else
1157 options->max_startups = options->max_startups_begin;
1158 break;
1159
af4bd935 1160 case sMaxAuthTries:
1161 intptr = &options->max_authtries;
1162 goto parse_int;
1163
c6dca55e 1164 case sMaxSessions:
1165 intptr = &options->max_sessions;
1166 goto parse_int;
1167
2717fa0f 1168 case sBanner:
1169 charptr = &options->banner;
1170 goto parse_filename;
db49deeb 1171
2717fa0f 1172 /*
1173 * These options can contain %X options expanded at
1174 * connect time, so that you can specify paths like:
1175 *
1176 * AuthorizedKeysFile /etc/ssh_keys/%u
1177 */
1178 case sAuthorizedKeysFile:
1179 case sAuthorizedKeysFile2:
d4f40d92 1180 charptr = (opcode == sAuthorizedKeysFile) ?
2717fa0f 1181 &options->authorized_keys_file :
1182 &options->authorized_keys_file2;
1183 goto parse_filename;
1184
1185 case sClientAliveInterval:
1186 intptr = &options->client_alive_interval;
1187 goto parse_time;
1188
1189 case sClientAliveCountMax:
1190 intptr = &options->client_alive_count_max;
1191 goto parse_int;
1192
61a2c1da 1193 case sAcceptEnv:
1194 while ((arg = strdelim(&cp)) && *arg != '\0') {
1195 if (strchr(arg, '=') != NULL)
1196 fatal("%s line %d: Invalid environment name.",
1197 filename, linenum);
1198 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1199 fatal("%s line %d: too many allow env.",
1200 filename, linenum);
d231781a 1201 if (!*activep)
1202 break;
61a2c1da 1203 options->accept_env[options->num_accept_env++] =
1204 xstrdup(arg);
1205 }
1206 break;
1207
d20f3c9e 1208 case sPermitTunnel:
1209 intptr = &options->permit_tun;
a4f24bf8 1210 arg = strdelim(&cp);
1211 if (!arg || *arg == '\0')
1212 fatal("%s line %d: Missing yes/point-to-point/"
1213 "ethernet/no argument.", filename, linenum);
1214 value = 0; /* silence compiler */
1215 if (strcasecmp(arg, "ethernet") == 0)
1216 value = SSH_TUNMODE_ETHERNET;
1217 else if (strcasecmp(arg, "point-to-point") == 0)
1218 value = SSH_TUNMODE_POINTOPOINT;
1219 else if (strcasecmp(arg, "yes") == 0)
1220 value = SSH_TUNMODE_YES;
1221 else if (strcasecmp(arg, "no") == 0)
1222 value = SSH_TUNMODE_NO;
1223 else
1224 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1225 "no argument: %s", filename, linenum, arg);
1226 if (*intptr == -1)
1227 *intptr = value;
1228 break;
d20f3c9e 1229
d231781a 1230 case sMatch:
1231 if (cmdline)
1232 fatal("Match directive not supported as a command-line "
1233 "option");
1234 value = match_cfg_line(&cp, linenum, user, host, address);
1235 if (value < 0)
1236 fatal("%s line %d: Bad Match condition", filename,
1237 linenum);
1238 *activep = value;
1239 break;
1240
2fefbadf 1241 case sPermitOpen:
1242 arg = strdelim(&cp);
1243 if (!arg || *arg == '\0')
1244 fatal("%s line %d: missing PermitOpen specification",
1245 filename, linenum);
38757197 1246 n = options->num_permitted_opens; /* modified later */
2fefbadf 1247 if (strcmp(arg, "any") == 0) {
38757197 1248 if (*activep && n == -1) {
2fefbadf 1249 channel_clear_adm_permitted_opens();
ea46e550 1250 options->num_permitted_opens = 0;
1251 }
2fefbadf 1252 break;
1253 }
75b6d52c 1254 if (*activep && n == -1)
1255 channel_clear_adm_permitted_opens();
ea46e550 1256 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1257 p = hpdelim(&arg);
1258 if (p == NULL)
1259 fatal("%s line %d: missing host in PermitOpen",
1260 filename, linenum);
1261 p = cleanhostname(p);
1262 if (arg == NULL || (port = a2port(arg)) == 0)
1263 fatal("%s line %d: bad port number in "
1264 "PermitOpen", filename, linenum);
75b6d52c 1265 if (*activep && n == -1)
ea46e550 1266 options->num_permitted_opens =
1267 channel_add_adm_permitted_opens(p, port);
ea46e550 1268 }
2fefbadf 1269 break;
1270
e7259e8d 1271 case sForceCommand:
1272 if (cp == NULL)
1273 fatal("%.200s line %d: Missing argument.", filename,
1274 linenum);
1275 len = strspn(cp, WHITESPACE);
1276 if (*activep && options->adm_forced_command == NULL)
1277 options->adm_forced_command = xstrdup(cp + len);
1278 return 0;
1279
db49deeb 1280 case sChrootDirectory:
1281 charptr = &options->chroot_directory;
c5bf32e6 1282
1283 arg = strdelim(&cp);
1284 if (!arg || *arg == '\0')
1285 fatal("%s line %d: missing file name.",
1286 filename, linenum);
1287 if (*activep && *charptr == NULL)
1288 *charptr = xstrdup(arg);
1289 break;
db49deeb 1290
2717fa0f 1291 case sDeprecated:
bbe88b6d 1292 logit("%s line %d: Deprecated option %s",
2717fa0f 1293 filename, linenum, arg);
1294 while (arg)
1295 arg = strdelim(&cp);
1296 break;
1297
a2144546 1298 case sUnsupported:
1299 logit("%s line %d: Unsupported option %s",
1300 filename, linenum, arg);
1301 while (arg)
1302 arg = strdelim(&cp);
1303 break;
1304
2717fa0f 1305 default:
1306 fatal("%s line %d: Missing handler for opcode %s (%d)",
1307 filename, linenum, arg, opcode);
1308 }
1309 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1310 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1311 filename, linenum, arg);
1312 return 0;
1313}
089fbbd2 1314
2717fa0f 1315/* Reads the server configuration file. */
5c53a31e 1316
2717fa0f 1317void
b9a549d7 1318load_server_config(const char *filename, Buffer *conf)
2717fa0f 1319{
b9a549d7 1320 char line[1024], *cp;
7528d467 1321 FILE *f;
2717fa0f 1322
b9a549d7 1323 debug2("%s: filename %s", __func__, filename);
1324 if ((f = fopen(filename, "r")) == NULL) {
2717fa0f 1325 perror(filename);
1326 exit(1);
1327 }
b9a549d7 1328 buffer_clear(conf);
2717fa0f 1329 while (fgets(line, sizeof(line), f)) {
b9a549d7 1330 /*
1331 * Trim out comments and strip whitespace
f2107e97 1332 * NB - preserve newlines, they are needed to reproduce
b9a549d7 1333 * line numbers later for error messages
1334 */
1335 if ((cp = strchr(line, '#')) != NULL)
1336 memcpy(cp, "\n", 2);
1337 cp = line + strspn(line, " \t\r");
1338
1339 buffer_append(conf, cp, strlen(cp));
8efc0c15 1340 }
b9a549d7 1341 buffer_append(conf, "\0", 1);
5260325f 1342 fclose(f);
b9a549d7 1343 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1344}
1345
1346void
d231781a 1347parse_server_match_config(ServerOptions *options, const char *user,
1348 const char *host, const char *address)
1349{
1350 ServerOptions mo;
1351
1352 initialize_server_options(&mo);
1353 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
03bcbf84 1354 copy_set_server_options(options, &mo, 0);
d231781a 1355}
1356
03bcbf84 1357/* Helper macros */
1358#define M_CP_INTOPT(n) do {\
1359 if (src->n != -1) \
1360 dst->n = src->n; \
1361} while (0)
1362#define M_CP_STROPT(n) do {\
1363 if (src->n != NULL) { \
1364 if (dst->n != NULL) \
1365 xfree(dst->n); \
1366 dst->n = src->n; \
1367 } \
1368} while(0)
1369
1370/*
1371 * Copy any supported values that are set.
1372 *
1373 * If the preauth flag is set, we do not bother copying the the string or
1374 * array values that are not used pre-authentication, because any that we
1375 * do use must be explictly sent in mm_getpwnamallow().
1376 */
d231781a 1377void
03bcbf84 1378copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
d231781a 1379{
03bcbf84 1380 M_CP_INTOPT(password_authentication);
1381 M_CP_INTOPT(gss_authentication);
1382 M_CP_INTOPT(rsa_authentication);
1383 M_CP_INTOPT(pubkey_authentication);
1384 M_CP_INTOPT(kerberos_authentication);
1385 M_CP_INTOPT(hostbased_authentication);
1386 M_CP_INTOPT(kbd_interactive_authentication);
2ef741a3 1387 M_CP_INTOPT(permit_root_login);
03bcbf84 1388
1389 M_CP_INTOPT(allow_tcp_forwarding);
43c3f85c 1390 M_CP_INTOPT(allow_agent_forwarding);
03bcbf84 1391 M_CP_INTOPT(gateway_ports);
1392 M_CP_INTOPT(x11_display_offset);
1393 M_CP_INTOPT(x11_forwarding);
1394 M_CP_INTOPT(x11_use_localhost);
c6dca55e 1395 M_CP_INTOPT(max_sessions);
03bcbf84 1396
1397 M_CP_STROPT(banner);
1398 if (preauth)
1399 return;
1400 M_CP_STROPT(adm_forced_command);
db49deeb 1401 M_CP_STROPT(chroot_directory);
d231781a 1402}
1403
03bcbf84 1404#undef M_CP_INTOPT
1405#undef M_CP_STROPT
1406
d231781a 1407void
1408parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1409 const char *user, const char *host, const char *address)
b9a549d7 1410{
d231781a 1411 int active, linenum, bad_options = 0;
16acb158 1412 char *cp, *obuf, *cbuf;
b9a549d7 1413
1414 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1415
16acb158 1416 obuf = cbuf = xstrdup(buffer_ptr(conf));
d231781a 1417 active = user ? 0 : 1;
861cc543 1418 linenum = 1;
f8cc7664 1419 while ((cp = strsep(&cbuf, "\n")) != NULL) {
b9a549d7 1420 if (process_server_config_line(options, cp, filename,
d231781a 1421 linenum++, &active, user, host, address) != 0)
b9a549d7 1422 bad_options++;
1423 }
16acb158 1424 xfree(obuf);
b7c70970 1425 if (bad_options > 0)
1426 fatal("%s: terminating, %d bad configuration options",
1427 filename, bad_options);
8efc0c15 1428}
This page took 0.640761 seconds and 5 git commands to generate.