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