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