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