]> andersk Git - openssh.git/blame - servconf.c
- djm@cvs.openbsd.org 2007/12/12 05:04:03
[openssh.git] / servconf.c
CommitLineData
51b787f2 1/* $OpenBSD: servconf.c,v 1.172 2007/04/23 10:15:39 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>",
461 gai_strerror(gaierr));
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;
5260325f 624 ServerOpCodes opcode;
3867aa0a 625 u_short port;
d231781a 626 u_int i, flags = 0;
d66ce1a1 627 size_t len;
5260325f 628
2717fa0f 629 cp = line;
0f8cd5a6 630 if ((arg = strdelim(&cp)) == NULL)
88299971 631 return 0;
2717fa0f 632 /* Ignore leading whitespace */
633 if (*arg == '\0')
704b1659 634 arg = strdelim(&cp);
2717fa0f 635 if (!arg || !*arg || *arg == '#')
636 return 0;
637 intptr = NULL;
638 charptr = NULL;
d231781a 639 opcode = parse_token(arg, filename, linenum, &flags);
640
641 if (activep == NULL) { /* We are processing a command line directive */
642 cmdline = 1;
643 activep = &cmdline;
644 }
645 if (*activep && opcode != sMatch)
646 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
647 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
648 if (user == NULL) {
649 fatal("%s line %d: Directive '%s' is not allowed "
650 "within a Match block", filename, linenum, arg);
651 } else { /* this is a directive we have already processed */
652 while (arg)
653 arg = strdelim(&cp);
654 return 0;
655 }
656 }
657
2717fa0f 658 switch (opcode) {
659 /* Portable-specific options */
7fceb20d 660 case sUsePAM:
661 intptr = &options->use_pam;
2717fa0f 662 goto parse_flag;
48e671d5 663
2717fa0f 664 /* Standard Options */
665 case sBadOption:
666 return -1;
667 case sPort:
668 /* ignore ports from configfile if cmdline specifies ports */
669 if (options->ports_from_cmdline)
670 return 0;
671 if (options->listen_addrs != NULL)
672 fatal("%s line %d: ports must be specified before "
3a454b6a 673 "ListenAddress.", filename, linenum);
2717fa0f 674 if (options->num_ports >= MAX_PORTS)
675 fatal("%s line %d: too many ports.",
676 filename, linenum);
677 arg = strdelim(&cp);
678 if (!arg || *arg == '\0')
679 fatal("%s line %d: missing port number.",
680 filename, linenum);
681 options->ports[options->num_ports++] = a2port(arg);
682 if (options->ports[options->num_ports-1] == 0)
683 fatal("%s line %d: Badly formatted port number.",
684 filename, linenum);
685 break;
686
687 case sServerKeyBits:
688 intptr = &options->server_key_bits;
5260325f 689parse_int:
2717fa0f 690 arg = strdelim(&cp);
691 if (!arg || *arg == '\0')
692 fatal("%s line %d: missing integer value.",
693 filename, linenum);
694 value = atoi(arg);
d231781a 695 if (*activep && *intptr == -1)
2717fa0f 696 *intptr = value;
697 break;
698
699 case sLoginGraceTime:
700 intptr = &options->login_grace_time;
e2b1fb42 701parse_time:
2717fa0f 702 arg = strdelim(&cp);
703 if (!arg || *arg == '\0')
704 fatal("%s line %d: missing time value.",
705 filename, linenum);
706 if ((value = convtime(arg)) == -1)
707 fatal("%s line %d: invalid time value.",
708 filename, linenum);
709 if (*intptr == -1)
710 *intptr = value;
711 break;
712
713 case sKeyRegenerationTime:
714 intptr = &options->key_regeneration_time;
715 goto parse_time;
716
717 case sListenAddress:
718 arg = strdelim(&cp);
3867aa0a 719 if (arg == NULL || *arg == '\0')
720 fatal("%s line %d: missing address",
2717fa0f 721 filename, linenum);
91135a0e 722 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
723 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
724 && strchr(p+1, ':') != NULL) {
725 add_listen_addr(options, arg, 0);
726 break;
727 }
3867aa0a 728 p = hpdelim(&arg);
729 if (p == NULL)
730 fatal("%s line %d: bad address:port usage",
2717fa0f 731 filename, linenum);
3867aa0a 732 p = cleanhostname(p);
733 if (arg == NULL)
734 port = 0;
735 else if ((port = a2port(arg)) == 0)
736 fatal("%s line %d: bad port number", filename, linenum);
737
738 add_listen_addr(options, p, port);
739
2717fa0f 740 break;
741
31b41ceb 742 case sAddressFamily:
743 arg = strdelim(&cp);
38634ff6 744 if (!arg || *arg == '\0')
745 fatal("%s line %d: missing address family.",
746 filename, linenum);
31b41ceb 747 intptr = &options->address_family;
748 if (options->listen_addrs != NULL)
749 fatal("%s line %d: address family must be specified before "
750 "ListenAddress.", filename, linenum);
751 if (strcasecmp(arg, "inet") == 0)
752 value = AF_INET;
753 else if (strcasecmp(arg, "inet6") == 0)
754 value = AF_INET6;
755 else if (strcasecmp(arg, "any") == 0)
756 value = AF_UNSPEC;
757 else
758 fatal("%s line %d: unsupported address family \"%s\".",
759 filename, linenum, arg);
760 if (*intptr == -1)
761 *intptr = value;
762 break;
763
2717fa0f 764 case sHostKeyFile:
765 intptr = &options->num_host_key_files;
766 if (*intptr >= MAX_HOSTKEYS)
767 fatal("%s line %d: too many host keys specified (max %d).",
768 filename, linenum, MAX_HOSTKEYS);
769 charptr = &options->host_key_files[*intptr];
fa649821 770parse_filename:
2717fa0f 771 arg = strdelim(&cp);
772 if (!arg || *arg == '\0')
773 fatal("%s line %d: missing file name.",
774 filename, linenum);
d231781a 775 if (*activep && *charptr == NULL) {
2717fa0f 776 *charptr = tilde_expand_filename(arg, getuid());
777 /* increase optional counter */
778 if (intptr != NULL)
779 *intptr = *intptr + 1;
780 }
781 break;
0fbe8c74 782
2717fa0f 783 case sPidFile:
784 charptr = &options->pid_file;
785 goto parse_filename;
5260325f 786
2717fa0f 787 case sPermitRootLogin:
788 intptr = &options->permit_root_login;
789 arg = strdelim(&cp);
790 if (!arg || *arg == '\0')
791 fatal("%s line %d: missing yes/"
792 "without-password/forced-commands-only/no "
793 "argument.", filename, linenum);
794 value = 0; /* silence compiler */
795 if (strcmp(arg, "without-password") == 0)
796 value = PERMIT_NO_PASSWD;
797 else if (strcmp(arg, "forced-commands-only") == 0)
798 value = PERMIT_FORCED_ONLY;
799 else if (strcmp(arg, "yes") == 0)
800 value = PERMIT_YES;
801 else if (strcmp(arg, "no") == 0)
802 value = PERMIT_NO;
803 else
804 fatal("%s line %d: Bad yes/"
805 "without-password/forced-commands-only/no "
806 "argument: %s", filename, linenum, arg);
807 if (*intptr == -1)
808 *intptr = value;
809 break;
810
811 case sIgnoreRhosts:
812 intptr = &options->ignore_rhosts;
5260325f 813parse_flag:
2717fa0f 814 arg = strdelim(&cp);
815 if (!arg || *arg == '\0')
816 fatal("%s line %d: missing yes/no argument.",
817 filename, linenum);
818 value = 0; /* silence compiler */
819 if (strcmp(arg, "yes") == 0)
820 value = 1;
821 else if (strcmp(arg, "no") == 0)
822 value = 0;
823 else
824 fatal("%s line %d: Bad yes/no argument: %s",
825 filename, linenum, arg);
d231781a 826 if (*activep && *intptr == -1)
2717fa0f 827 *intptr = value;
828 break;
829
830 case sIgnoreUserKnownHosts:
831 intptr = &options->ignore_user_known_hosts;
832 goto parse_flag;
833
2717fa0f 834 case sRhostsRSAAuthentication:
835 intptr = &options->rhosts_rsa_authentication;
836 goto parse_flag;
837
838 case sHostbasedAuthentication:
839 intptr = &options->hostbased_authentication;
840 goto parse_flag;
841
842 case sHostbasedUsesNameFromPacketOnly:
843 intptr = &options->hostbased_uses_name_from_packet_only;
844 goto parse_flag;
845
846 case sRSAAuthentication:
847 intptr = &options->rsa_authentication;
848 goto parse_flag;
849
850 case sPubkeyAuthentication:
851 intptr = &options->pubkey_authentication;
852 goto parse_flag;
d0ec7f42 853
2717fa0f 854 case sKerberosAuthentication:
855 intptr = &options->kerberos_authentication;
856 goto parse_flag;
5260325f 857
2717fa0f 858 case sKerberosOrLocalPasswd:
859 intptr = &options->kerberos_or_local_passwd;
860 goto parse_flag;
5260325f 861
2717fa0f 862 case sKerberosTicketCleanup:
863 intptr = &options->kerberos_ticket_cleanup;
864 goto parse_flag;
d0ec7f42 865
a1e30b47 866 case sKerberosGetAFSToken:
867 intptr = &options->kerberos_get_afs_token;
868 goto parse_flag;
869
7364bd04 870 case sGssAuthentication:
871 intptr = &options->gss_authentication;
872 goto parse_flag;
873
874 case sGssCleanupCreds:
875 intptr = &options->gss_cleanup_creds;
876 goto parse_flag;
877
2717fa0f 878 case sPasswordAuthentication:
879 intptr = &options->password_authentication;
880 goto parse_flag;
5260325f 881
2717fa0f 882 case sKbdInteractiveAuthentication:
883 intptr = &options->kbd_interactive_authentication;
884 goto parse_flag;
8002af61 885
2717fa0f 886 case sChallengeResponseAuthentication:
887 intptr = &options->challenge_response_authentication;
888 goto parse_flag;
8002af61 889
2717fa0f 890 case sPrintMotd:
891 intptr = &options->print_motd;
892 goto parse_flag;
5260325f 893
2717fa0f 894 case sPrintLastLog:
895 intptr = &options->print_lastlog;
896 goto parse_flag;
5260325f 897
2717fa0f 898 case sX11Forwarding:
899 intptr = &options->x11_forwarding;
900 goto parse_flag;
5260325f 901
2717fa0f 902 case sX11DisplayOffset:
903 intptr = &options->x11_display_offset;
904 goto parse_int;
8efc0c15 905
e6e573bd 906 case sX11UseLocalhost:
907 intptr = &options->x11_use_localhost;
908 goto parse_flag;
909
2717fa0f 910 case sXAuthLocation:
911 charptr = &options->xauth_location;
912 goto parse_filename;
5260325f 913
2717fa0f 914 case sStrictModes:
915 intptr = &options->strict_modes;
916 goto parse_flag;
5260325f 917
fd573618 918 case sTCPKeepAlive:
919 intptr = &options->tcp_keep_alive;
2717fa0f 920 goto parse_flag;
33de75a3 921
2717fa0f 922 case sEmptyPasswd:
923 intptr = &options->permit_empty_passwd;
924 goto parse_flag;
5260325f 925
f00bab84 926 case sPermitUserEnvironment:
927 intptr = &options->permit_user_env;
928 goto parse_flag;
929
2717fa0f 930 case sUseLogin:
931 intptr = &options->use_login;
932 goto parse_flag;
5260325f 933
636f76ca 934 case sCompression:
935 intptr = &options->compression;
07200973 936 arg = strdelim(&cp);
937 if (!arg || *arg == '\0')
938 fatal("%s line %d: missing yes/no/delayed "
939 "argument.", filename, linenum);
940 value = 0; /* silence compiler */
941 if (strcmp(arg, "delayed") == 0)
942 value = COMP_DELAYED;
943 else if (strcmp(arg, "yes") == 0)
944 value = COMP_ZLIB;
945 else if (strcmp(arg, "no") == 0)
946 value = COMP_NONE;
947 else
948 fatal("%s line %d: Bad yes/no/delayed "
949 "argument: %s", filename, linenum, arg);
950 if (*intptr == -1)
951 *intptr = value;
952 break;
636f76ca 953
2717fa0f 954 case sGatewayPorts:
955 intptr = &options->gateway_ports;
3867aa0a 956 arg = strdelim(&cp);
957 if (!arg || *arg == '\0')
958 fatal("%s line %d: missing yes/no/clientspecified "
959 "argument.", filename, linenum);
960 value = 0; /* silence compiler */
961 if (strcmp(arg, "clientspecified") == 0)
962 value = 2;
963 else if (strcmp(arg, "yes") == 0)
964 value = 1;
965 else if (strcmp(arg, "no") == 0)
966 value = 0;
967 else
968 fatal("%s line %d: Bad yes/no/clientspecified "
969 "argument: %s", filename, linenum, arg);
f3e3d6ce 970 if (*activep && *intptr == -1)
3867aa0a 971 *intptr = value;
972 break;
5260325f 973
c5a7d788 974 case sUseDNS:
975 intptr = &options->use_dns;
2717fa0f 976 goto parse_flag;
5260325f 977
2717fa0f 978 case sLogFacility:
979 intptr = (int *) &options->log_facility;
980 arg = strdelim(&cp);
981 value = log_facility_number(arg);
5eaf8578 982 if (value == SYSLOG_FACILITY_NOT_SET)
2717fa0f 983 fatal("%.200s line %d: unsupported log facility '%s'",
984 filename, linenum, arg ? arg : "<NONE>");
985 if (*intptr == -1)
986 *intptr = (SyslogFacility) value;
987 break;
988
989 case sLogLevel:
990 intptr = (int *) &options->log_level;
991 arg = strdelim(&cp);
992 value = log_level_number(arg);
5eaf8578 993 if (value == SYSLOG_LEVEL_NOT_SET)
2717fa0f 994 fatal("%.200s line %d: unsupported log level '%s'",
995 filename, linenum, arg ? arg : "<NONE>");
996 if (*intptr == -1)
997 *intptr = (LogLevel) value;
998 break;
999
1000 case sAllowTcpForwarding:
1001 intptr = &options->allow_tcp_forwarding;
1002 goto parse_flag;
1003
1853d1ef 1004 case sUsePrivilegeSeparation:
1005 intptr = &use_privsep;
1006 goto parse_flag;
1007
2717fa0f 1008 case sAllowUsers:
1009 while ((arg = strdelim(&cp)) && *arg != '\0') {
1010 if (options->num_allow_users >= MAX_ALLOW_USERS)
1011 fatal("%s line %d: too many allow users.",
1012 filename, linenum);
7528d467 1013 options->allow_users[options->num_allow_users++] =
1014 xstrdup(arg);
2717fa0f 1015 }
1016 break;
a8be9f80 1017
2717fa0f 1018 case sDenyUsers:
1019 while ((arg = strdelim(&cp)) && *arg != '\0') {
1020 if (options->num_deny_users >= MAX_DENY_USERS)
d4f40d92 1021 fatal("%s line %d: too many deny users.",
2717fa0f 1022 filename, linenum);
7528d467 1023 options->deny_users[options->num_deny_users++] =
1024 xstrdup(arg);
2717fa0f 1025 }
1026 break;
b2552997 1027
2717fa0f 1028 case sAllowGroups:
1029 while ((arg = strdelim(&cp)) && *arg != '\0') {
1030 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1031 fatal("%s line %d: too many allow groups.",
1032 filename, linenum);
7528d467 1033 options->allow_groups[options->num_allow_groups++] =
1034 xstrdup(arg);
2717fa0f 1035 }
1036 break;
a8be9f80 1037
2717fa0f 1038 case sDenyGroups:
1039 while ((arg = strdelim(&cp)) && *arg != '\0') {
1040 if (options->num_deny_groups >= MAX_DENY_GROUPS)
1041 fatal("%s line %d: too many deny groups.",
1042 filename, linenum);
1043 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1044 }
1045 break;
38c295d6 1046
2717fa0f 1047 case sCiphers:
1048 arg = strdelim(&cp);
1049 if (!arg || *arg == '\0')
1050 fatal("%s line %d: Missing argument.", filename, linenum);
1051 if (!ciphers_valid(arg))
1052 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1053 filename, linenum, arg ? arg : "<NONE>");
1054 if (options->ciphers == NULL)
1055 options->ciphers = xstrdup(arg);
1056 break;
1057
1058 case sMacs:
1059 arg = strdelim(&cp);
1060 if (!arg || *arg == '\0')
1061 fatal("%s line %d: Missing argument.", filename, linenum);
1062 if (!mac_valid(arg))
1063 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1064 filename, linenum, arg ? arg : "<NONE>");
1065 if (options->macs == NULL)
1066 options->macs = xstrdup(arg);
1067 break;
1068
1069 case sProtocol:
1070 intptr = &options->protocol;
1071 arg = strdelim(&cp);
1072 if (!arg || *arg == '\0')
1073 fatal("%s line %d: Missing argument.", filename, linenum);
1074 value = proto_spec(arg);
1075 if (value == SSH_PROTO_UNKNOWN)
1076 fatal("%s line %d: Bad protocol spec '%s'.",
184eed6a 1077 filename, linenum, arg ? arg : "<NONE>");
2717fa0f 1078 if (*intptr == SSH_PROTO_UNKNOWN)
1079 *intptr = value;
1080 break;
1081
1082 case sSubsystem:
1083 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1084 fatal("%s line %d: too many subsystems defined.",
184eed6a 1085 filename, linenum);
2717fa0f 1086 }
1087 arg = strdelim(&cp);
1088 if (!arg || *arg == '\0')
1089 fatal("%s line %d: Missing subsystem name.",
184eed6a 1090 filename, linenum);
d231781a 1091 if (!*activep) {
1092 arg = strdelim(&cp);
1093 break;
1094 }
2717fa0f 1095 for (i = 0; i < options->num_subsystems; i++)
1096 if (strcmp(arg, options->subsystem_name[i]) == 0)
1097 fatal("%s line %d: Subsystem '%s' already defined.",
184eed6a 1098 filename, linenum, arg);
2717fa0f 1099 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1100 arg = strdelim(&cp);
1101 if (!arg || *arg == '\0')
1102 fatal("%s line %d: Missing subsystem command.",
184eed6a 1103 filename, linenum);
2717fa0f 1104 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
d66ce1a1 1105
1106 /* Collect arguments (separate to executable) */
1107 p = xstrdup(arg);
1108 len = strlen(p) + 1;
1109 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1110 len += 1 + strlen(arg);
1111 p = xrealloc(p, 1, len);
1112 strlcat(p, " ", len);
1113 strlcat(p, arg, len);
1114 }
1115 options->subsystem_args[options->num_subsystems] = p;
2717fa0f 1116 options->num_subsystems++;
1117 break;
1118
1119 case sMaxStartups:
1120 arg = strdelim(&cp);
1121 if (!arg || *arg == '\0')
1122 fatal("%s line %d: Missing MaxStartups spec.",
184eed6a 1123 filename, linenum);
2717fa0f 1124 if ((n = sscanf(arg, "%d:%d:%d",
1125 &options->max_startups_begin,
1126 &options->max_startups_rate,
1127 &options->max_startups)) == 3) {
1128 if (options->max_startups_begin >
1129 options->max_startups ||
1130 options->max_startups_rate > 100 ||
1131 options->max_startups_rate < 1)
c345cf9d 1132 fatal("%s line %d: Illegal MaxStartups spec.",
97de229c 1133 filename, linenum);
2717fa0f 1134 } else if (n != 1)
1135 fatal("%s line %d: Illegal MaxStartups spec.",
1136 filename, linenum);
1137 else
1138 options->max_startups = options->max_startups_begin;
1139 break;
1140
af4bd935 1141 case sMaxAuthTries:
1142 intptr = &options->max_authtries;
1143 goto parse_int;
1144
2717fa0f 1145 case sBanner:
1146 charptr = &options->banner;
1147 goto parse_filename;
1148 /*
1149 * These options can contain %X options expanded at
1150 * connect time, so that you can specify paths like:
1151 *
1152 * AuthorizedKeysFile /etc/ssh_keys/%u
1153 */
1154 case sAuthorizedKeysFile:
1155 case sAuthorizedKeysFile2:
d4f40d92 1156 charptr = (opcode == sAuthorizedKeysFile) ?
2717fa0f 1157 &options->authorized_keys_file :
1158 &options->authorized_keys_file2;
1159 goto parse_filename;
1160
1161 case sClientAliveInterval:
1162 intptr = &options->client_alive_interval;
1163 goto parse_time;
1164
1165 case sClientAliveCountMax:
1166 intptr = &options->client_alive_count_max;
1167 goto parse_int;
1168
61a2c1da 1169 case sAcceptEnv:
1170 while ((arg = strdelim(&cp)) && *arg != '\0') {
1171 if (strchr(arg, '=') != NULL)
1172 fatal("%s line %d: Invalid environment name.",
1173 filename, linenum);
1174 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1175 fatal("%s line %d: too many allow env.",
1176 filename, linenum);
d231781a 1177 if (!*activep)
1178 break;
61a2c1da 1179 options->accept_env[options->num_accept_env++] =
1180 xstrdup(arg);
1181 }
1182 break;
1183
d20f3c9e 1184 case sPermitTunnel:
1185 intptr = &options->permit_tun;
a4f24bf8 1186 arg = strdelim(&cp);
1187 if (!arg || *arg == '\0')
1188 fatal("%s line %d: Missing yes/point-to-point/"
1189 "ethernet/no argument.", filename, linenum);
1190 value = 0; /* silence compiler */
1191 if (strcasecmp(arg, "ethernet") == 0)
1192 value = SSH_TUNMODE_ETHERNET;
1193 else if (strcasecmp(arg, "point-to-point") == 0)
1194 value = SSH_TUNMODE_POINTOPOINT;
1195 else if (strcasecmp(arg, "yes") == 0)
1196 value = SSH_TUNMODE_YES;
1197 else if (strcasecmp(arg, "no") == 0)
1198 value = SSH_TUNMODE_NO;
1199 else
1200 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1201 "no argument: %s", filename, linenum, arg);
1202 if (*intptr == -1)
1203 *intptr = value;
1204 break;
d20f3c9e 1205
d231781a 1206 case sMatch:
1207 if (cmdline)
1208 fatal("Match directive not supported as a command-line "
1209 "option");
1210 value = match_cfg_line(&cp, linenum, user, host, address);
1211 if (value < 0)
1212 fatal("%s line %d: Bad Match condition", filename,
1213 linenum);
1214 *activep = value;
1215 break;
1216
2fefbadf 1217 case sPermitOpen:
1218 arg = strdelim(&cp);
1219 if (!arg || *arg == '\0')
1220 fatal("%s line %d: missing PermitOpen specification",
1221 filename, linenum);
38757197 1222 n = options->num_permitted_opens; /* modified later */
2fefbadf 1223 if (strcmp(arg, "any") == 0) {
38757197 1224 if (*activep && n == -1) {
2fefbadf 1225 channel_clear_adm_permitted_opens();
ea46e550 1226 options->num_permitted_opens = 0;
1227 }
2fefbadf 1228 break;
1229 }
75b6d52c 1230 if (*activep && n == -1)
1231 channel_clear_adm_permitted_opens();
ea46e550 1232 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1233 p = hpdelim(&arg);
1234 if (p == NULL)
1235 fatal("%s line %d: missing host in PermitOpen",
1236 filename, linenum);
1237 p = cleanhostname(p);
1238 if (arg == NULL || (port = a2port(arg)) == 0)
1239 fatal("%s line %d: bad port number in "
1240 "PermitOpen", filename, linenum);
75b6d52c 1241 if (*activep && n == -1)
ea46e550 1242 options->num_permitted_opens =
1243 channel_add_adm_permitted_opens(p, port);
ea46e550 1244 }
2fefbadf 1245 break;
1246
e7259e8d 1247 case sForceCommand:
1248 if (cp == NULL)
1249 fatal("%.200s line %d: Missing argument.", filename,
1250 linenum);
1251 len = strspn(cp, WHITESPACE);
1252 if (*activep && options->adm_forced_command == NULL)
1253 options->adm_forced_command = xstrdup(cp + len);
1254 return 0;
1255
2717fa0f 1256 case sDeprecated:
bbe88b6d 1257 logit("%s line %d: Deprecated option %s",
2717fa0f 1258 filename, linenum, arg);
1259 while (arg)
1260 arg = strdelim(&cp);
1261 break;
1262
a2144546 1263 case sUnsupported:
1264 logit("%s line %d: Unsupported option %s",
1265 filename, linenum, arg);
1266 while (arg)
1267 arg = strdelim(&cp);
1268 break;
1269
2717fa0f 1270 default:
1271 fatal("%s line %d: Missing handler for opcode %s (%d)",
1272 filename, linenum, arg, opcode);
1273 }
1274 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1275 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1276 filename, linenum, arg);
1277 return 0;
1278}
089fbbd2 1279
2717fa0f 1280/* Reads the server configuration file. */
5c53a31e 1281
2717fa0f 1282void
b9a549d7 1283load_server_config(const char *filename, Buffer *conf)
2717fa0f 1284{
b9a549d7 1285 char line[1024], *cp;
7528d467 1286 FILE *f;
2717fa0f 1287
b9a549d7 1288 debug2("%s: filename %s", __func__, filename);
1289 if ((f = fopen(filename, "r")) == NULL) {
2717fa0f 1290 perror(filename);
1291 exit(1);
1292 }
b9a549d7 1293 buffer_clear(conf);
2717fa0f 1294 while (fgets(line, sizeof(line), f)) {
b9a549d7 1295 /*
1296 * Trim out comments and strip whitespace
f2107e97 1297 * NB - preserve newlines, they are needed to reproduce
b9a549d7 1298 * line numbers later for error messages
1299 */
1300 if ((cp = strchr(line, '#')) != NULL)
1301 memcpy(cp, "\n", 2);
1302 cp = line + strspn(line, " \t\r");
1303
1304 buffer_append(conf, cp, strlen(cp));
8efc0c15 1305 }
b9a549d7 1306 buffer_append(conf, "\0", 1);
5260325f 1307 fclose(f);
b9a549d7 1308 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1309}
1310
1311void
d231781a 1312parse_server_match_config(ServerOptions *options, const char *user,
1313 const char *host, const char *address)
1314{
1315 ServerOptions mo;
1316
1317 initialize_server_options(&mo);
1318 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
03bcbf84 1319 copy_set_server_options(options, &mo, 0);
d231781a 1320}
1321
03bcbf84 1322/* Helper macros */
1323#define M_CP_INTOPT(n) do {\
1324 if (src->n != -1) \
1325 dst->n = src->n; \
1326} while (0)
1327#define M_CP_STROPT(n) do {\
1328 if (src->n != NULL) { \
1329 if (dst->n != NULL) \
1330 xfree(dst->n); \
1331 dst->n = src->n; \
1332 } \
1333} while(0)
1334
1335/*
1336 * Copy any supported values that are set.
1337 *
1338 * If the preauth flag is set, we do not bother copying the the string or
1339 * array values that are not used pre-authentication, because any that we
1340 * do use must be explictly sent in mm_getpwnamallow().
1341 */
d231781a 1342void
03bcbf84 1343copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
d231781a 1344{
03bcbf84 1345 M_CP_INTOPT(password_authentication);
1346 M_CP_INTOPT(gss_authentication);
1347 M_CP_INTOPT(rsa_authentication);
1348 M_CP_INTOPT(pubkey_authentication);
1349 M_CP_INTOPT(kerberos_authentication);
1350 M_CP_INTOPT(hostbased_authentication);
1351 M_CP_INTOPT(kbd_interactive_authentication);
03bcbf84 1352
1353 M_CP_INTOPT(allow_tcp_forwarding);
1354 M_CP_INTOPT(gateway_ports);
1355 M_CP_INTOPT(x11_display_offset);
1356 M_CP_INTOPT(x11_forwarding);
1357 M_CP_INTOPT(x11_use_localhost);
1358
1359 M_CP_STROPT(banner);
1360 if (preauth)
1361 return;
1362 M_CP_STROPT(adm_forced_command);
d231781a 1363}
1364
03bcbf84 1365#undef M_CP_INTOPT
1366#undef M_CP_STROPT
1367
d231781a 1368void
1369parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1370 const char *user, const char *host, const char *address)
b9a549d7 1371{
d231781a 1372 int active, linenum, bad_options = 0;
16acb158 1373 char *cp, *obuf, *cbuf;
b9a549d7 1374
1375 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1376
16acb158 1377 obuf = cbuf = xstrdup(buffer_ptr(conf));
d231781a 1378 active = user ? 0 : 1;
861cc543 1379 linenum = 1;
f8cc7664 1380 while ((cp = strsep(&cbuf, "\n")) != NULL) {
b9a549d7 1381 if (process_server_config_line(options, cp, filename,
d231781a 1382 linenum++, &active, user, host, address) != 0)
b9a549d7 1383 bad_options++;
1384 }
16acb158 1385 xfree(obuf);
b7c70970 1386 if (bad_options > 0)
1387 fatal("%s: terminating, %d bad configuration options",
1388 filename, bad_options);
8efc0c15 1389}
This page took 0.534686 seconds and 5 git commands to generate.