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