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