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