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