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