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