1 /* $OpenBSD: servconf.c,v 1.158 2006/07/19 13:07:10 dtucker Exp $ */
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
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".
15 #include <sys/types.h>
16 #include <sys/socket.h>
18 #if defined(HAVE_NETDB_H)
28 #include "pathnames.h"
36 static void add_listen_addr(ServerOptions *, char *, u_short);
37 static void add_one_listen_addr(ServerOptions *, char *, u_short);
39 /* Use of privilege separation or not */
40 extern int use_privsep;
43 /* Initializes the server options to their default values. */
46 initialize_server_options(ServerOptions *options)
48 memset(options, 0, sizeof(*options));
50 /* Portable-specific options */
51 options->use_pam = -1;
53 /* Standard Options */
54 options->num_ports = 0;
55 options->ports_from_cmdline = 0;
56 options->listen_addrs = NULL;
57 options->address_family = -1;
58 options->num_host_key_files = 0;
59 options->pid_file = NULL;
60 options->server_key_bits = -1;
61 options->login_grace_time = -1;
62 options->key_regeneration_time = -1;
63 options->permit_root_login = PERMIT_NOT_SET;
64 options->ignore_rhosts = -1;
65 options->ignore_user_known_hosts = -1;
66 options->print_motd = -1;
67 options->print_lastlog = -1;
68 options->x11_forwarding = -1;
69 options->x11_display_offset = -1;
70 options->x11_use_localhost = -1;
71 options->xauth_location = NULL;
72 options->strict_modes = -1;
73 options->tcp_keep_alive = -1;
74 options->log_facility = SYSLOG_FACILITY_NOT_SET;
75 options->log_level = SYSLOG_LEVEL_NOT_SET;
76 options->rhosts_rsa_authentication = -1;
77 options->hostbased_authentication = -1;
78 options->hostbased_uses_name_from_packet_only = -1;
79 options->rsa_authentication = -1;
80 options->pubkey_authentication = -1;
81 options->kerberos_authentication = -1;
82 options->kerberos_or_local_passwd = -1;
83 options->kerberos_ticket_cleanup = -1;
84 options->kerberos_get_afs_token = -1;
85 options->gss_authentication=-1;
86 options->gss_cleanup_creds = -1;
87 options->password_authentication = -1;
88 options->kbd_interactive_authentication = -1;
89 options->challenge_response_authentication = -1;
90 options->permit_empty_passwd = -1;
91 options->permit_user_env = -1;
92 options->use_login = -1;
93 options->compression = -1;
94 options->allow_tcp_forwarding = -1;
95 options->num_allow_users = 0;
96 options->num_deny_users = 0;
97 options->num_allow_groups = 0;
98 options->num_deny_groups = 0;
99 options->ciphers = NULL;
100 options->macs = NULL;
101 options->protocol = SSH_PROTO_UNKNOWN;
102 options->gateway_ports = -1;
103 options->num_subsystems = 0;
104 options->max_startups_begin = -1;
105 options->max_startups_rate = -1;
106 options->max_startups = -1;
107 options->max_authtries = -1;
108 options->banner = NULL;
109 options->use_dns = -1;
110 options->client_alive_interval = -1;
111 options->client_alive_count_max = -1;
112 options->authorized_keys_file = NULL;
113 options->authorized_keys_file2 = NULL;
114 options->num_accept_env = 0;
115 options->permit_tun = -1;
116 options->adm_forced_command = NULL;
120 fill_default_server_options(ServerOptions *options)
122 /* Portable-specific options */
123 if (options->use_pam == -1)
124 options->use_pam = 0;
126 /* Standard Options */
127 if (options->protocol == SSH_PROTO_UNKNOWN)
128 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
129 if (options->num_host_key_files == 0) {
130 /* fill default hostkeys for protocols */
131 if (options->protocol & SSH_PROTO_1)
132 options->host_key_files[options->num_host_key_files++] =
134 if (options->protocol & SSH_PROTO_2) {
135 options->host_key_files[options->num_host_key_files++] =
136 _PATH_HOST_RSA_KEY_FILE;
137 options->host_key_files[options->num_host_key_files++] =
138 _PATH_HOST_DSA_KEY_FILE;
141 if (options->num_ports == 0)
142 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
143 if (options->listen_addrs == NULL)
144 add_listen_addr(options, NULL, 0);
145 if (options->pid_file == NULL)
146 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
147 if (options->server_key_bits == -1)
148 options->server_key_bits = 768;
149 if (options->login_grace_time == -1)
150 options->login_grace_time = 120;
151 if (options->key_regeneration_time == -1)
152 options->key_regeneration_time = 3600;
153 if (options->permit_root_login == PERMIT_NOT_SET)
154 options->permit_root_login = PERMIT_YES;
155 if (options->ignore_rhosts == -1)
156 options->ignore_rhosts = 1;
157 if (options->ignore_user_known_hosts == -1)
158 options->ignore_user_known_hosts = 0;
159 if (options->print_motd == -1)
160 options->print_motd = 1;
161 if (options->print_lastlog == -1)
162 options->print_lastlog = 1;
163 if (options->x11_forwarding == -1)
164 options->x11_forwarding = 0;
165 if (options->x11_display_offset == -1)
166 options->x11_display_offset = 10;
167 if (options->x11_use_localhost == -1)
168 options->x11_use_localhost = 1;
169 if (options->xauth_location == NULL)
170 options->xauth_location = _PATH_XAUTH;
171 if (options->strict_modes == -1)
172 options->strict_modes = 1;
173 if (options->tcp_keep_alive == -1)
174 options->tcp_keep_alive = 1;
175 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
176 options->log_facility = SYSLOG_FACILITY_AUTH;
177 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
178 options->log_level = SYSLOG_LEVEL_INFO;
179 if (options->rhosts_rsa_authentication == -1)
180 options->rhosts_rsa_authentication = 0;
181 if (options->hostbased_authentication == -1)
182 options->hostbased_authentication = 0;
183 if (options->hostbased_uses_name_from_packet_only == -1)
184 options->hostbased_uses_name_from_packet_only = 0;
185 if (options->rsa_authentication == -1)
186 options->rsa_authentication = 1;
187 if (options->pubkey_authentication == -1)
188 options->pubkey_authentication = 1;
189 if (options->kerberos_authentication == -1)
190 options->kerberos_authentication = 0;
191 if (options->kerberos_or_local_passwd == -1)
192 options->kerberos_or_local_passwd = 1;
193 if (options->kerberos_ticket_cleanup == -1)
194 options->kerberos_ticket_cleanup = 1;
195 if (options->kerberos_get_afs_token == -1)
196 options->kerberos_get_afs_token = 0;
197 if (options->gss_authentication == -1)
198 options->gss_authentication = 0;
199 if (options->gss_cleanup_creds == -1)
200 options->gss_cleanup_creds = 1;
201 if (options->password_authentication == -1)
202 options->password_authentication = 1;
203 if (options->kbd_interactive_authentication == -1)
204 options->kbd_interactive_authentication = 0;
205 if (options->challenge_response_authentication == -1)
206 options->challenge_response_authentication = 1;
207 if (options->permit_empty_passwd == -1)
208 options->permit_empty_passwd = 0;
209 if (options->permit_user_env == -1)
210 options->permit_user_env = 0;
211 if (options->use_login == -1)
212 options->use_login = 0;
213 if (options->compression == -1)
214 options->compression = COMP_DELAYED;
215 if (options->allow_tcp_forwarding == -1)
216 options->allow_tcp_forwarding = 1;
217 if (options->gateway_ports == -1)
218 options->gateway_ports = 0;
219 if (options->max_startups == -1)
220 options->max_startups = 10;
221 if (options->max_startups_rate == -1)
222 options->max_startups_rate = 100; /* 100% */
223 if (options->max_startups_begin == -1)
224 options->max_startups_begin = options->max_startups;
225 if (options->max_authtries == -1)
226 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
227 if (options->use_dns == -1)
228 options->use_dns = 1;
229 if (options->client_alive_interval == -1)
230 options->client_alive_interval = 0;
231 if (options->client_alive_count_max == -1)
232 options->client_alive_count_max = 3;
233 if (options->authorized_keys_file2 == NULL) {
234 /* authorized_keys_file2 falls back to authorized_keys_file */
235 if (options->authorized_keys_file != NULL)
236 options->authorized_keys_file2 = options->authorized_keys_file;
238 options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
240 if (options->authorized_keys_file == NULL)
241 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
242 if (options->permit_tun == -1)
243 options->permit_tun = SSH_TUNMODE_NO;
245 /* Turn privilege separation on by default */
246 if (use_privsep == -1)
250 if (use_privsep && options->compression == 1) {
251 error("This platform does not support both privilege "
252 "separation and compression");
253 error("Compression disabled");
254 options->compression = 0;
260 /* Keyword tokens. */
262 sBadOption, /* == unknown option */
263 /* Portable-specific options */
265 /* Standard Options */
266 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
267 sPermitRootLogin, sLogFacility, sLogLevel,
268 sRhostsRSAAuthentication, sRSAAuthentication,
269 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
270 sKerberosGetAFSToken,
271 sKerberosTgtPassing, sChallengeResponseAuthentication,
272 sPasswordAuthentication, sKbdInteractiveAuthentication,
273 sListenAddress, sAddressFamily,
274 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
275 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
276 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
277 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
278 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
279 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
280 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
281 sMaxStartups, sMaxAuthTries,
282 sBanner, sUseDNS, sHostbasedAuthentication,
283 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
284 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
285 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
286 sMatch, sPermitOpen, sForceCommand,
287 sUsePrivilegeSeparation,
288 sDeprecated, sUnsupported
291 #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
292 #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
293 #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
295 /* Textual representation of the tokens. */
298 ServerOpCodes opcode;
301 /* Portable-specific options */
303 { "usepam", sUsePAM, SSHCFG_GLOBAL },
305 { "usepam", sUnsupported, SSHCFG_GLOBAL },
307 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
308 /* Standard Options */
309 { "port", sPort, SSHCFG_GLOBAL },
310 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
311 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
312 { "pidfile", sPidFile, SSHCFG_GLOBAL },
313 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
314 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
315 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
316 { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL },
317 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
318 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
319 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
320 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL },
321 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL },
322 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
323 { "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL },
324 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },
325 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
327 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL },
328 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
329 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
331 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
333 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
336 { "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL },
337 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
338 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
339 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
341 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
342 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
344 { "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
345 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
347 { "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
348 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
350 { "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
351 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL },
352 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
353 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
354 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
355 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
356 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
357 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
358 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
359 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
360 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
361 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
362 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
363 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
364 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
365 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
366 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
367 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
368 { "uselogin", sUseLogin, SSHCFG_GLOBAL },
369 { "compression", sCompression, SSHCFG_GLOBAL },
370 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
371 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
372 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
373 { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
374 { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
375 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
376 { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
377 { "ciphers", sCiphers, SSHCFG_GLOBAL },
378 { "macs", sMacs, SSHCFG_GLOBAL },
379 { "protocol", sProtocol, SSHCFG_GLOBAL },
380 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
381 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
382 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
383 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
384 { "banner", sBanner, SSHCFG_GLOBAL },
385 { "usedns", sUseDNS, SSHCFG_GLOBAL },
386 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
387 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
388 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
389 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
390 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
391 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
392 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
393 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
394 { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
395 { "match", sMatch, SSHCFG_ALL },
396 { "permitopen", sPermitOpen, SSHCFG_ALL },
397 { "forcecommand", sForceCommand, SSHCFG_ALL },
398 { NULL, sBadOption, 0 }
402 * Returns the number of the token pointed to by cp or sBadOption.
406 parse_token(const char *cp, const char *filename,
407 int linenum, u_int *flags)
411 for (i = 0; keywords[i].name; i++)
412 if (strcasecmp(cp, keywords[i].name) == 0) {
413 *flags = keywords[i].flags;
414 return keywords[i].opcode;
417 error("%s: line %d: Bad configuration option: %s",
418 filename, linenum, cp);
423 add_listen_addr(ServerOptions *options, char *addr, u_short port)
427 if (options->num_ports == 0)
428 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
429 if (options->address_family == -1)
430 options->address_family = AF_UNSPEC;
432 for (i = 0; i < options->num_ports; i++)
433 add_one_listen_addr(options, addr, options->ports[i]);
435 add_one_listen_addr(options, addr, port);
439 add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
441 struct addrinfo hints, *ai, *aitop;
442 char strport[NI_MAXSERV];
445 memset(&hints, 0, sizeof(hints));
446 hints.ai_family = options->address_family;
447 hints.ai_socktype = SOCK_STREAM;
448 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
449 snprintf(strport, sizeof strport, "%u", port);
450 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
451 fatal("bad addr or host: %s (%s)",
452 addr ? addr : "<NULL>",
453 gai_strerror(gaierr));
454 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
456 ai->ai_next = options->listen_addrs;
457 options->listen_addrs = aitop;
461 * The strategy for the Match blocks is that the config file is parsed twice.
463 * The first time is at startup. activep is initialized to 1 and the
464 * directives in the global context are processed and acted on. Hitting a
465 * Match directive unsets activep and the directives inside the block are
466 * checked for syntax only.
468 * The second time is after a connection has been established but before
469 * authentication. activep is initialized to 2 and global config directives
470 * are ignored since they have already been processed. If the criteria in a
471 * Match block is met, activep is set and the subsequent directives
472 * processed and actioned until EOF or another Match block unsets it. Any
473 * options set are copied into the main server config.
475 * Potential additions/improvements:
476 * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
478 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
479 * Match Address 192.168.0.*
484 * AllowTcpForwarding yes
485 * GatewayPorts clientspecified
488 * - Add a PermittedChannelRequests directive
490 * PermittedChannelRequests session,forwarded-tcpip
494 match_cfg_line(char **condition, int line, const char *user, const char *host,
498 char *arg, *attrib, *cp = *condition;
502 debug3("checking syntax for 'Match %s'", cp);
504 debug3("checking match for '%s' user %s host %s addr %s", cp,
505 user ? user : "(null)", host ? host : "(null)",
506 address ? address : "(null)");
508 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
509 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
510 error("Missing Match criteria for %s", attrib);
514 if (strcasecmp(attrib, "user") == 0) {
519 if (match_pattern_list(user, arg, len, 0) != 1)
522 debug("user %.100s matched 'User %.100s' at "
523 "line %d", user, arg, line);
524 } else if (strcasecmp(attrib, "host") == 0) {
529 if (match_hostname(host, arg, len) != 1)
532 debug("connection from %.100s matched 'Host "
533 "%.100s' at line %d", host, arg, line);
534 } else if (strcasecmp(attrib, "address") == 0) {
535 debug("address '%s' arg '%s'", address, arg);
540 if (match_hostname(address, arg, len) != 1)
543 debug("connection from %.100s matched 'Address "
544 "%.100s' at line %d", address, arg, line);
546 error("Unsupported Match attribute %s", attrib);
551 debug3("match %sfound", result ? "" : "not ");
556 #define WHITESPACE " \t\r\n"
559 process_server_config_line(ServerOptions *options, char *line,
560 const char *filename, int linenum, int *activep, const char *user,
561 const char *host, const char *address)
563 char *cp, **charptr, *arg, *p;
564 int cmdline = 0, *intptr, value, n;
565 ServerOpCodes opcode;
571 if ((arg = strdelim(&cp)) == NULL)
573 /* Ignore leading whitespace */
576 if (!arg || !*arg || *arg == '#')
580 opcode = parse_token(arg, filename, linenum, &flags);
582 if (activep == NULL) { /* We are processing a command line directive */
586 if (*activep && opcode != sMatch)
587 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
588 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
590 fatal("%s line %d: Directive '%s' is not allowed "
591 "within a Match block", filename, linenum, arg);
592 } else { /* this is a directive we have already processed */
600 /* Portable-specific options */
602 intptr = &options->use_pam;
605 /* Standard Options */
609 /* ignore ports from configfile if cmdline specifies ports */
610 if (options->ports_from_cmdline)
612 if (options->listen_addrs != NULL)
613 fatal("%s line %d: ports must be specified before "
614 "ListenAddress.", filename, linenum);
615 if (options->num_ports >= MAX_PORTS)
616 fatal("%s line %d: too many ports.",
619 if (!arg || *arg == '\0')
620 fatal("%s line %d: missing port number.",
622 options->ports[options->num_ports++] = a2port(arg);
623 if (options->ports[options->num_ports-1] == 0)
624 fatal("%s line %d: Badly formatted port number.",
629 intptr = &options->server_key_bits;
632 if (!arg || *arg == '\0')
633 fatal("%s line %d: missing integer value.",
636 if (*activep && *intptr == -1)
640 case sLoginGraceTime:
641 intptr = &options->login_grace_time;
644 if (!arg || *arg == '\0')
645 fatal("%s line %d: missing time value.",
647 if ((value = convtime(arg)) == -1)
648 fatal("%s line %d: invalid time value.",
654 case sKeyRegenerationTime:
655 intptr = &options->key_regeneration_time;
660 if (arg == NULL || *arg == '\0')
661 fatal("%s line %d: missing address",
663 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
664 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
665 && strchr(p+1, ':') != NULL) {
666 add_listen_addr(options, arg, 0);
671 fatal("%s line %d: bad address:port usage",
673 p = cleanhostname(p);
676 else if ((port = a2port(arg)) == 0)
677 fatal("%s line %d: bad port number", filename, linenum);
679 add_listen_addr(options, p, port);
685 if (!arg || *arg == '\0')
686 fatal("%s line %d: missing address family.",
688 intptr = &options->address_family;
689 if (options->listen_addrs != NULL)
690 fatal("%s line %d: address family must be specified before "
691 "ListenAddress.", filename, linenum);
692 if (strcasecmp(arg, "inet") == 0)
694 else if (strcasecmp(arg, "inet6") == 0)
696 else if (strcasecmp(arg, "any") == 0)
699 fatal("%s line %d: unsupported address family \"%s\".",
700 filename, linenum, arg);
706 intptr = &options->num_host_key_files;
707 if (*intptr >= MAX_HOSTKEYS)
708 fatal("%s line %d: too many host keys specified (max %d).",
709 filename, linenum, MAX_HOSTKEYS);
710 charptr = &options->host_key_files[*intptr];
713 if (!arg || *arg == '\0')
714 fatal("%s line %d: missing file name.",
716 if (*activep && *charptr == NULL) {
717 *charptr = tilde_expand_filename(arg, getuid());
718 /* increase optional counter */
720 *intptr = *intptr + 1;
725 charptr = &options->pid_file;
728 case sPermitRootLogin:
729 intptr = &options->permit_root_login;
731 if (!arg || *arg == '\0')
732 fatal("%s line %d: missing yes/"
733 "without-password/forced-commands-only/no "
734 "argument.", filename, linenum);
735 value = 0; /* silence compiler */
736 if (strcmp(arg, "without-password") == 0)
737 value = PERMIT_NO_PASSWD;
738 else if (strcmp(arg, "forced-commands-only") == 0)
739 value = PERMIT_FORCED_ONLY;
740 else if (strcmp(arg, "yes") == 0)
742 else if (strcmp(arg, "no") == 0)
745 fatal("%s line %d: Bad yes/"
746 "without-password/forced-commands-only/no "
747 "argument: %s", filename, linenum, arg);
753 intptr = &options->ignore_rhosts;
756 if (!arg || *arg == '\0')
757 fatal("%s line %d: missing yes/no argument.",
759 value = 0; /* silence compiler */
760 if (strcmp(arg, "yes") == 0)
762 else if (strcmp(arg, "no") == 0)
765 fatal("%s line %d: Bad yes/no argument: %s",
766 filename, linenum, arg);
767 if (*activep && *intptr == -1)
771 case sIgnoreUserKnownHosts:
772 intptr = &options->ignore_user_known_hosts;
775 case sRhostsRSAAuthentication:
776 intptr = &options->rhosts_rsa_authentication;
779 case sHostbasedAuthentication:
780 intptr = &options->hostbased_authentication;
783 case sHostbasedUsesNameFromPacketOnly:
784 intptr = &options->hostbased_uses_name_from_packet_only;
787 case sRSAAuthentication:
788 intptr = &options->rsa_authentication;
791 case sPubkeyAuthentication:
792 intptr = &options->pubkey_authentication;
795 case sKerberosAuthentication:
796 intptr = &options->kerberos_authentication;
799 case sKerberosOrLocalPasswd:
800 intptr = &options->kerberos_or_local_passwd;
803 case sKerberosTicketCleanup:
804 intptr = &options->kerberos_ticket_cleanup;
807 case sKerberosGetAFSToken:
808 intptr = &options->kerberos_get_afs_token;
811 case sGssAuthentication:
812 intptr = &options->gss_authentication;
815 case sGssCleanupCreds:
816 intptr = &options->gss_cleanup_creds;
819 case sPasswordAuthentication:
820 intptr = &options->password_authentication;
823 case sKbdInteractiveAuthentication:
824 intptr = &options->kbd_interactive_authentication;
827 case sChallengeResponseAuthentication:
828 intptr = &options->challenge_response_authentication;
832 intptr = &options->print_motd;
836 intptr = &options->print_lastlog;
840 intptr = &options->x11_forwarding;
843 case sX11DisplayOffset:
844 intptr = &options->x11_display_offset;
847 case sX11UseLocalhost:
848 intptr = &options->x11_use_localhost;
852 charptr = &options->xauth_location;
856 intptr = &options->strict_modes;
860 intptr = &options->tcp_keep_alive;
864 intptr = &options->permit_empty_passwd;
867 case sPermitUserEnvironment:
868 intptr = &options->permit_user_env;
872 intptr = &options->use_login;
876 intptr = &options->compression;
878 if (!arg || *arg == '\0')
879 fatal("%s line %d: missing yes/no/delayed "
880 "argument.", filename, linenum);
881 value = 0; /* silence compiler */
882 if (strcmp(arg, "delayed") == 0)
883 value = COMP_DELAYED;
884 else if (strcmp(arg, "yes") == 0)
886 else if (strcmp(arg, "no") == 0)
889 fatal("%s line %d: Bad yes/no/delayed "
890 "argument: %s", filename, linenum, arg);
896 intptr = &options->gateway_ports;
898 if (!arg || *arg == '\0')
899 fatal("%s line %d: missing yes/no/clientspecified "
900 "argument.", filename, linenum);
901 value = 0; /* silence compiler */
902 if (strcmp(arg, "clientspecified") == 0)
904 else if (strcmp(arg, "yes") == 0)
906 else if (strcmp(arg, "no") == 0)
909 fatal("%s line %d: Bad yes/no/clientspecified "
910 "argument: %s", filename, linenum, arg);
916 intptr = &options->use_dns;
920 intptr = (int *) &options->log_facility;
922 value = log_facility_number(arg);
923 if (value == SYSLOG_FACILITY_NOT_SET)
924 fatal("%.200s line %d: unsupported log facility '%s'",
925 filename, linenum, arg ? arg : "<NONE>");
927 *intptr = (SyslogFacility) value;
931 intptr = (int *) &options->log_level;
933 value = log_level_number(arg);
934 if (value == SYSLOG_LEVEL_NOT_SET)
935 fatal("%.200s line %d: unsupported log level '%s'",
936 filename, linenum, arg ? arg : "<NONE>");
938 *intptr = (LogLevel) value;
941 case sAllowTcpForwarding:
942 intptr = &options->allow_tcp_forwarding;
945 case sUsePrivilegeSeparation:
946 intptr = &use_privsep;
950 while ((arg = strdelim(&cp)) && *arg != '\0') {
951 if (options->num_allow_users >= MAX_ALLOW_USERS)
952 fatal("%s line %d: too many allow users.",
954 options->allow_users[options->num_allow_users++] =
960 while ((arg = strdelim(&cp)) && *arg != '\0') {
961 if (options->num_deny_users >= MAX_DENY_USERS)
962 fatal( "%s line %d: too many deny users.",
964 options->deny_users[options->num_deny_users++] =
970 while ((arg = strdelim(&cp)) && *arg != '\0') {
971 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
972 fatal("%s line %d: too many allow groups.",
974 options->allow_groups[options->num_allow_groups++] =
980 while ((arg = strdelim(&cp)) && *arg != '\0') {
981 if (options->num_deny_groups >= MAX_DENY_GROUPS)
982 fatal("%s line %d: too many deny groups.",
984 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
990 if (!arg || *arg == '\0')
991 fatal("%s line %d: Missing argument.", filename, linenum);
992 if (!ciphers_valid(arg))
993 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
994 filename, linenum, arg ? arg : "<NONE>");
995 if (options->ciphers == NULL)
996 options->ciphers = xstrdup(arg);
1000 arg = strdelim(&cp);
1001 if (!arg || *arg == '\0')
1002 fatal("%s line %d: Missing argument.", filename, linenum);
1003 if (!mac_valid(arg))
1004 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1005 filename, linenum, arg ? arg : "<NONE>");
1006 if (options->macs == NULL)
1007 options->macs = xstrdup(arg);
1011 intptr = &options->protocol;
1012 arg = strdelim(&cp);
1013 if (!arg || *arg == '\0')
1014 fatal("%s line %d: Missing argument.", filename, linenum);
1015 value = proto_spec(arg);
1016 if (value == SSH_PROTO_UNKNOWN)
1017 fatal("%s line %d: Bad protocol spec '%s'.",
1018 filename, linenum, arg ? arg : "<NONE>");
1019 if (*intptr == SSH_PROTO_UNKNOWN)
1024 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1025 fatal("%s line %d: too many subsystems defined.",
1028 arg = strdelim(&cp);
1029 if (!arg || *arg == '\0')
1030 fatal("%s line %d: Missing subsystem name.",
1033 arg = strdelim(&cp);
1036 for (i = 0; i < options->num_subsystems; i++)
1037 if (strcmp(arg, options->subsystem_name[i]) == 0)
1038 fatal("%s line %d: Subsystem '%s' already defined.",
1039 filename, linenum, arg);
1040 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1041 arg = strdelim(&cp);
1042 if (!arg || *arg == '\0')
1043 fatal("%s line %d: Missing subsystem command.",
1045 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
1047 /* Collect arguments (separate to executable) */
1049 len = strlen(p) + 1;
1050 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1051 len += 1 + strlen(arg);
1052 p = xrealloc(p, 1, len);
1053 strlcat(p, " ", len);
1054 strlcat(p, arg, len);
1056 options->subsystem_args[options->num_subsystems] = p;
1057 options->num_subsystems++;
1061 arg = strdelim(&cp);
1062 if (!arg || *arg == '\0')
1063 fatal("%s line %d: Missing MaxStartups spec.",
1065 if ((n = sscanf(arg, "%d:%d:%d",
1066 &options->max_startups_begin,
1067 &options->max_startups_rate,
1068 &options->max_startups)) == 3) {
1069 if (options->max_startups_begin >
1070 options->max_startups ||
1071 options->max_startups_rate > 100 ||
1072 options->max_startups_rate < 1)
1073 fatal("%s line %d: Illegal MaxStartups spec.",
1076 fatal("%s line %d: Illegal MaxStartups spec.",
1079 options->max_startups = options->max_startups_begin;
1083 intptr = &options->max_authtries;
1087 charptr = &options->banner;
1088 goto parse_filename;
1090 * These options can contain %X options expanded at
1091 * connect time, so that you can specify paths like:
1093 * AuthorizedKeysFile /etc/ssh_keys/%u
1095 case sAuthorizedKeysFile:
1096 case sAuthorizedKeysFile2:
1097 charptr = (opcode == sAuthorizedKeysFile ) ?
1098 &options->authorized_keys_file :
1099 &options->authorized_keys_file2;
1100 goto parse_filename;
1102 case sClientAliveInterval:
1103 intptr = &options->client_alive_interval;
1106 case sClientAliveCountMax:
1107 intptr = &options->client_alive_count_max;
1111 while ((arg = strdelim(&cp)) && *arg != '\0') {
1112 if (strchr(arg, '=') != NULL)
1113 fatal("%s line %d: Invalid environment name.",
1115 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1116 fatal("%s line %d: too many allow env.",
1120 options->accept_env[options->num_accept_env++] =
1126 intptr = &options->permit_tun;
1127 arg = strdelim(&cp);
1128 if (!arg || *arg == '\0')
1129 fatal("%s line %d: Missing yes/point-to-point/"
1130 "ethernet/no argument.", filename, linenum);
1131 value = 0; /* silence compiler */
1132 if (strcasecmp(arg, "ethernet") == 0)
1133 value = SSH_TUNMODE_ETHERNET;
1134 else if (strcasecmp(arg, "point-to-point") == 0)
1135 value = SSH_TUNMODE_POINTOPOINT;
1136 else if (strcasecmp(arg, "yes") == 0)
1137 value = SSH_TUNMODE_YES;
1138 else if (strcasecmp(arg, "no") == 0)
1139 value = SSH_TUNMODE_NO;
1141 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1142 "no argument: %s", filename, linenum, arg);
1149 fatal("Match directive not supported as a command-line "
1151 value = match_cfg_line(&cp, linenum, user, host, address);
1153 fatal("%s line %d: Bad Match condition", filename,
1159 arg = strdelim(&cp);
1160 if (!arg || *arg == '\0')
1161 fatal("%s line %d: missing PermitOpen specification",
1163 if (strcmp(arg, "any") == 0) {
1165 channel_clear_adm_permitted_opens();
1170 fatal("%s line %d: missing host in PermitOpen",
1172 p = cleanhostname(p);
1173 if (arg == NULL || (port = a2port(arg)) == 0)
1174 fatal("%s line %d: bad port number in PermitOpen",
1177 channel_add_adm_permitted_opens(p, port);
1182 fatal("%.200s line %d: Missing argument.", filename,
1184 len = strspn(cp, WHITESPACE);
1185 if (*activep && options->adm_forced_command == NULL)
1186 options->adm_forced_command = xstrdup(cp + len);
1190 logit("%s line %d: Deprecated option %s",
1191 filename, linenum, arg);
1193 arg = strdelim(&cp);
1197 logit("%s line %d: Unsupported option %s",
1198 filename, linenum, arg);
1200 arg = strdelim(&cp);
1204 fatal("%s line %d: Missing handler for opcode %s (%d)",
1205 filename, linenum, arg, opcode);
1207 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1208 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1209 filename, linenum, arg);
1213 /* Reads the server configuration file. */
1216 load_server_config(const char *filename, Buffer *conf)
1218 char line[1024], *cp;
1221 debug2("%s: filename %s", __func__, filename);
1222 if ((f = fopen(filename, "r")) == NULL) {
1227 while (fgets(line, sizeof(line), f)) {
1229 * Trim out comments and strip whitespace
1230 * NB - preserve newlines, they are needed to reproduce
1231 * line numbers later for error messages
1233 if ((cp = strchr(line, '#')) != NULL)
1234 memcpy(cp, "\n", 2);
1235 cp = line + strspn(line, " \t\r");
1237 buffer_append(conf, cp, strlen(cp));
1239 buffer_append(conf, "\0", 1);
1241 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1245 parse_server_match_config(ServerOptions *options, const char *user,
1246 const char *host, const char *address)
1250 initialize_server_options(&mo);
1251 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1252 copy_set_server_options(options, &mo);
1255 /* Copy any (supported) values that are set */
1257 copy_set_server_options(ServerOptions *dst, ServerOptions *src)
1259 if (src->allow_tcp_forwarding != -1)
1260 dst->allow_tcp_forwarding = src->allow_tcp_forwarding;
1261 if (src->gateway_ports != -1)
1262 dst->gateway_ports = src->gateway_ports;
1263 if (src->adm_forced_command != NULL) {
1264 if (dst->adm_forced_command != NULL)
1265 xfree(dst->adm_forced_command);
1266 dst->adm_forced_command = src->adm_forced_command;
1268 if (src->x11_display_offset != -1)
1269 dst->x11_display_offset = src->x11_display_offset;
1270 if (src->x11_forwarding != -1)
1271 dst->x11_forwarding = src->x11_forwarding;
1272 if (src->x11_use_localhost != -1)
1273 dst->x11_use_localhost = src->x11_use_localhost;
1277 parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1278 const char *user, const char *host, const char *address)
1280 int active, linenum, bad_options = 0;
1281 char *cp, *obuf, *cbuf;
1283 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1285 obuf = cbuf = xstrdup(buffer_ptr(conf));
1286 active = user ? 0 : 1;
1288 while ((cp = strsep(&cbuf, "\n")) != NULL) {
1289 if (process_server_config_line(options, cp, filename,
1290 linenum++, &active, user, host, address) != 0)
1294 if (bad_options > 0)
1295 fatal("%s: terminating, %d bad configuration options",
1296 filename, bad_options);