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