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