1 /* $OpenBSD: servconf.c,v 1.172 2007/04/23 10:15:39 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>
33 #include "pathnames.h"
41 #include "groupaccess.h"
43 static void add_listen_addr(ServerOptions *, char *, u_short);
44 static void add_one_listen_addr(ServerOptions *, char *, u_short);
46 /* Use of privilege separation or not */
47 extern int use_privsep;
50 /* Initializes the server options to their default values. */
53 initialize_server_options(ServerOptions *options)
55 memset(options, 0, sizeof(*options));
57 /* Portable-specific options */
58 options->use_pam = -1;
60 /* Standard Options */
61 options->num_ports = 0;
62 options->ports_from_cmdline = 0;
63 options->listen_addrs = NULL;
64 options->address_family = -1;
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;
77 options->x11_use_localhost = -1;
78 options->xauth_location = NULL;
79 options->strict_modes = -1;
80 options->tcp_keep_alive = -1;
81 options->log_facility = SYSLOG_FACILITY_NOT_SET;
82 options->log_level = SYSLOG_LEVEL_NOT_SET;
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;
88 options->kerberos_authentication = -1;
89 options->kerberos_or_local_passwd = -1;
90 options->kerberos_ticket_cleanup = -1;
92 options->session_hooks_allow = -1;
93 options->session_hooks_startup_cmd = NULL;
94 options->session_hooks_shutdown_cmd = NULL;
96 options->kerberos_get_afs_token = -1;
97 options->gss_authentication=-1;
98 options->gss_keyex = -1;
99 options->gss_cleanup_creds = -1;
100 options->gss_strict_acceptor = -1;
101 options->gsi_allow_limited_proxy = -1;
102 options->password_authentication = -1;
103 options->kbd_interactive_authentication = -1;
104 options->challenge_response_authentication = -1;
105 options->permit_empty_passwd = -1;
106 options->permit_user_env = -1;
107 options->use_login = -1;
108 options->compression = -1;
109 options->allow_tcp_forwarding = -1;
110 options->num_allow_users = 0;
111 options->num_deny_users = 0;
112 options->num_allow_groups = 0;
113 options->num_deny_groups = 0;
114 options->ciphers = NULL;
115 options->macs = NULL;
116 options->protocol = SSH_PROTO_UNKNOWN;
117 options->gateway_ports = -1;
118 options->num_subsystems = 0;
119 options->max_startups_begin = -1;
120 options->max_startups_rate = -1;
121 options->max_startups = -1;
122 options->max_authtries = -1;
123 options->banner = NULL;
124 options->use_dns = -1;
125 options->client_alive_interval = -1;
126 options->client_alive_count_max = -1;
127 options->authorized_keys_file = NULL;
128 options->authorized_keys_file2 = NULL;
129 options->num_accept_env = 0;
130 options->permit_tun = -1;
131 options->num_permitted_opens = -1;
132 options->adm_forced_command = NULL;
133 options->none_enabled = -1;
134 options->tcp_rcv_buf_poll = -1;
135 options->hpn_disabled = -1;
136 options->hpn_buffer_size = -1;
140 fill_default_server_options(ServerOptions *options)
144 int socksizelen = sizeof(int);
146 /* Portable-specific options */
147 if (options->use_pam == -1)
148 options->use_pam = 0;
150 /* Standard Options */
151 if (options->protocol == SSH_PROTO_UNKNOWN)
152 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
153 if (options->num_host_key_files == 0) {
154 /* fill default hostkeys for protocols */
155 if (options->protocol & SSH_PROTO_1)
156 options->host_key_files[options->num_host_key_files++] =
158 if (options->protocol & SSH_PROTO_2) {
159 options->host_key_files[options->num_host_key_files++] =
160 _PATH_HOST_RSA_KEY_FILE;
161 options->host_key_files[options->num_host_key_files++] =
162 _PATH_HOST_DSA_KEY_FILE;
165 if (options->num_ports == 0)
166 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
167 if (options->listen_addrs == NULL)
168 add_listen_addr(options, NULL, 0);
169 if (options->pid_file == NULL)
170 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
171 if (options->server_key_bits == -1)
172 options->server_key_bits = 768;
173 if (options->login_grace_time == -1)
174 options->login_grace_time = 120;
175 if (options->key_regeneration_time == -1)
176 options->key_regeneration_time = 3600;
177 if (options->permit_root_login == PERMIT_NOT_SET)
178 options->permit_root_login = PERMIT_YES;
179 if (options->ignore_rhosts == -1)
180 options->ignore_rhosts = 1;
181 if (options->ignore_user_known_hosts == -1)
182 options->ignore_user_known_hosts = 0;
183 if (options->print_motd == -1)
184 options->print_motd = 1;
185 if (options->print_lastlog == -1)
186 options->print_lastlog = 1;
187 if (options->x11_forwarding == -1)
188 options->x11_forwarding = 0;
189 if (options->x11_display_offset == -1)
190 options->x11_display_offset = 10;
191 if (options->x11_use_localhost == -1)
192 options->x11_use_localhost = 1;
193 if (options->xauth_location == NULL)
194 options->xauth_location = _PATH_XAUTH;
195 if (options->strict_modes == -1)
196 options->strict_modes = 1;
197 if (options->tcp_keep_alive == -1)
198 options->tcp_keep_alive = 1;
199 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
200 options->log_facility = SYSLOG_FACILITY_AUTH;
201 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
202 options->log_level = SYSLOG_LEVEL_INFO;
203 if (options->rhosts_rsa_authentication == -1)
204 options->rhosts_rsa_authentication = 0;
205 if (options->hostbased_authentication == -1)
206 options->hostbased_authentication = 0;
207 if (options->hostbased_uses_name_from_packet_only == -1)
208 options->hostbased_uses_name_from_packet_only = 0;
209 if (options->rsa_authentication == -1)
210 options->rsa_authentication = 1;
211 if (options->pubkey_authentication == -1)
212 options->pubkey_authentication = 1;
213 if (options->kerberos_authentication == -1)
214 options->kerberos_authentication = 0;
215 if (options->kerberos_or_local_passwd == -1)
216 options->kerberos_or_local_passwd = 1;
217 if (options->kerberos_ticket_cleanup == -1)
218 options->kerberos_ticket_cleanup = 1;
219 if (options->kerberos_get_afs_token == -1)
220 options->kerberos_get_afs_token = 0;
221 if (options->gss_authentication == -1)
222 options->gss_authentication = 1;
223 if (options->gss_keyex == -1)
224 options->gss_keyex = 1;
225 if (options->gss_cleanup_creds == -1)
226 options->gss_cleanup_creds = 1;
227 if (options->gss_strict_acceptor == -1)
228 options->gss_strict_acceptor = 1;
229 if (options->gsi_allow_limited_proxy == -1)
230 options->gsi_allow_limited_proxy = 0;
231 if (options->password_authentication == -1)
232 options->password_authentication = 1;
233 if (options->kbd_interactive_authentication == -1)
234 options->kbd_interactive_authentication = 0;
235 if (options->challenge_response_authentication == -1)
236 options->challenge_response_authentication = 1;
237 if (options->permit_empty_passwd == -1)
238 options->permit_empty_passwd = 0;
239 if (options->permit_user_env == -1)
240 options->permit_user_env = 0;
241 if (options->use_login == -1)
242 options->use_login = 0;
243 if (options->compression == -1)
244 options->compression = COMP_DELAYED;
245 if (options->allow_tcp_forwarding == -1)
246 options->allow_tcp_forwarding = 1;
247 if (options->gateway_ports == -1)
248 options->gateway_ports = 0;
249 if (options->max_startups == -1)
250 options->max_startups = 10;
251 if (options->max_startups_rate == -1)
252 options->max_startups_rate = 100; /* 100% */
253 if (options->max_startups_begin == -1)
254 options->max_startups_begin = options->max_startups;
255 if (options->max_authtries == -1)
256 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
257 if (options->use_dns == -1)
258 options->use_dns = 1;
259 if (options->client_alive_interval == -1)
260 options->client_alive_interval = 0;
261 if (options->client_alive_count_max == -1)
262 options->client_alive_count_max = 3;
263 if (options->authorized_keys_file2 == NULL) {
264 /* authorized_keys_file2 falls back to authorized_keys_file */
265 if (options->authorized_keys_file != NULL)
266 options->authorized_keys_file2 = options->authorized_keys_file;
268 options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
270 if (options->authorized_keys_file == NULL)
271 options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
272 if (options->permit_tun == -1)
273 options->permit_tun = SSH_TUNMODE_NO;
275 if (options->hpn_disabled == -1)
276 options->hpn_disabled = 0;
278 if (options->hpn_buffer_size == -1)
280 /* option not explicitly set. Now we have to figure out */
281 /* what value to use */
282 if (options->hpn_disabled == 1)
284 options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT;
288 /* get the current RCV size and set it to that */
289 /*create a socket but don't connect it */
290 /* we use that the get the rcv socket size */
291 sock = socket(AF_INET, SOCK_STREAM, 0);
292 getsockopt(sock, SOL_SOCKET, SO_RCVBUF,
293 &socksize, &socksizelen);
295 options->hpn_buffer_size = socksize;
296 debug ("HPN Buffer Size: %d", options->hpn_buffer_size);
302 /* we have to do this incase the user sets both values in a contradictory */
303 /* manner. hpn_disabled overrrides hpn_buffer_size*/
304 if (options->hpn_disabled <= 0)
306 if (options->hpn_buffer_size == 0)
307 options->hpn_buffer_size = 1;
308 /* limit the maximum buffer to 64MB */
309 if (options->hpn_buffer_size > 64*1024)
310 options->hpn_buffer_size = 64*1024;
311 options->hpn_buffer_size *=1024;
314 options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT;
317 /* Turn privilege separation on by default */
318 if (use_privsep == -1)
322 if (use_privsep && options->compression == 1) {
323 error("This platform does not support both privilege "
324 "separation and compression");
325 error("Compression disabled");
326 options->compression = 0;
332 /* Keyword tokens. */
334 sBadOption, /* == unknown option */
335 /* Portable-specific options */
337 /* Standard Options */
338 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
339 sPermitRootLogin, sLogFacility, sLogLevel,
340 sRhostsRSAAuthentication, sRSAAuthentication,
341 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
342 sKerberosGetAFSToken,
343 sKerberosTgtPassing, sChallengeResponseAuthentication,
345 sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
347 sPasswordAuthentication, sKbdInteractiveAuthentication,
348 sListenAddress, sAddressFamily,
349 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
350 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
351 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
352 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
353 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
354 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
355 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
356 sMaxStartups, sMaxAuthTries,
357 sBanner, sUseDNS, sHostbasedAuthentication,
358 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
359 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
360 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
363 sGsiAllowLimitedProxy,
364 sAcceptEnv, sPermitTunnel,
365 sMatch, sPermitOpen, sForceCommand,
366 sUsePrivilegeSeparation, sNoneEnabled, sTcpRcvBufPoll,
367 sHPNDisabled, sHPNBufferSize,
368 sDeprecated, sUnsupported
371 #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
372 #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
373 #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
375 /* Textual representation of the tokens. */
378 ServerOpCodes opcode;
381 /* Portable-specific options */
383 { "usepam", sUsePAM, SSHCFG_GLOBAL },
385 { "usepam", sUnsupported, SSHCFG_GLOBAL },
387 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
388 /* Standard Options */
389 { "port", sPort, SSHCFG_GLOBAL },
390 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
391 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
392 { "pidfile", sPidFile, SSHCFG_GLOBAL },
393 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
394 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
395 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
396 { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL },
397 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
398 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
399 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
400 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
401 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
402 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
403 { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
404 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
405 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
407 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
408 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
409 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
411 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
413 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
416 { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
417 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
418 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
419 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
421 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
422 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
424 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
425 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
426 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
427 { "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL },
428 { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
430 { "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL },
433 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
434 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
435 { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
436 { "gssapicredentialspath", sUnsupported, SSHCFG_GLOBAL },
437 { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
439 { "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL },
443 { "allowsessionhooks", sAllowSessionHooks, SSHCFG_GLOBAL },
444 { "sessionhookstartupcmd", sSessionHookStartupCmd, SSHCFG_GLOBAL },
445 { "sessionhookshutdowncmd", sSessionHookShutdownCmd, SSHCFG_GLOBAL },
447 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
448 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
449 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
450 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
451 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
452 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
453 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
454 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
455 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
456 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
457 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
458 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
459 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
460 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
461 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
462 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
463 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
464 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
465 { "uselogin", sUseLogin, SSHCFG_GLOBAL },
466 { "compression", sCompression, SSHCFG_GLOBAL },
467 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
468 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
469 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
470 { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
471 { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
472 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
473 { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
474 { "ciphers", sCiphers, SSHCFG_GLOBAL },
475 { "macs", sMacs, SSHCFG_GLOBAL },
476 { "protocol", sProtocol, SSHCFG_GLOBAL },
477 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
478 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
479 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
480 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
481 { "banner", sBanner, SSHCFG_ALL },
482 { "usedns", sUseDNS, SSHCFG_GLOBAL },
483 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
484 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
485 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
486 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
487 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
488 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
489 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
490 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
491 { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
492 { "match", sMatch, SSHCFG_ALL },
493 { "permitopen", sPermitOpen, SSHCFG_ALL },
494 { "forcecommand", sForceCommand, SSHCFG_ALL },
495 { "noneenabled", sNoneEnabled },
496 { "hpndisabled", sHPNDisabled },
497 { "hpnbuffersize", sHPNBufferSize },
498 { "tcprcvbufpoll", sTcpRcvBufPoll },
499 { NULL, sBadOption, 0 }
503 * Returns the number of the token pointed to by cp or sBadOption.
507 parse_token(const char *cp, const char *filename,
508 int linenum, u_int *flags)
512 for (i = 0; keywords[i].name; i++)
513 if (strcasecmp(cp, keywords[i].name) == 0) {
514 debug ("Config token is %s", keywords[i].name);
515 *flags = keywords[i].flags;
516 return keywords[i].opcode;
519 error("%s: line %d: Bad configuration option: %s",
520 filename, linenum, cp);
525 add_listen_addr(ServerOptions *options, char *addr, u_short port)
529 if (options->num_ports == 0)
530 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
531 if (options->address_family == -1)
532 options->address_family = AF_UNSPEC;
534 for (i = 0; i < options->num_ports; i++)
535 add_one_listen_addr(options, addr, options->ports[i]);
537 add_one_listen_addr(options, addr, port);
541 add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
543 struct addrinfo hints, *ai, *aitop;
544 char strport[NI_MAXSERV];
547 memset(&hints, 0, sizeof(hints));
548 hints.ai_family = options->address_family;
549 hints.ai_socktype = SOCK_STREAM;
550 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
551 snprintf(strport, sizeof strport, "%u", port);
552 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
553 fatal("bad addr or host: %s (%s)",
554 addr ? addr : "<NULL>",
555 gai_strerror(gaierr));
556 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
558 ai->ai_next = options->listen_addrs;
559 options->listen_addrs = aitop;
563 * The strategy for the Match blocks is that the config file is parsed twice.
565 * The first time is at startup. activep is initialized to 1 and the
566 * directives in the global context are processed and acted on. Hitting a
567 * Match directive unsets activep and the directives inside the block are
568 * checked for syntax only.
570 * The second time is after a connection has been established but before
571 * authentication. activep is initialized to 2 and global config directives
572 * are ignored since they have already been processed. If the criteria in a
573 * Match block is met, activep is set and the subsequent directives
574 * processed and actioned until EOF or another Match block unsets it. Any
575 * options set are copied into the main server config.
577 * Potential additions/improvements:
578 * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
580 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
581 * Match Address 192.168.0.*
586 * AllowTcpForwarding yes
587 * GatewayPorts clientspecified
590 * - Add a PermittedChannelRequests directive
592 * PermittedChannelRequests session,forwarded-tcpip
596 match_cfg_line_group(const char *grps, int line, const char *user)
600 char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
604 * Even if we do not have a user yet, we still need to check for
607 arg = cp = xstrdup(grps);
608 while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
609 if (ngrps >= MAX_MATCH_GROUPS) {
610 error("line %d: too many groups in Match Group", line);
614 grplist[ngrps++] = p;
620 if ((pw = getpwnam(user)) == NULL) {
621 debug("Can't match group at line %d because user %.100s does "
622 "not exist", line, user);
623 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
624 debug("Can't Match group because user %.100s not in any group "
625 "at line %d", user, line);
626 } else if (ga_match(grplist, ngrps) != 1) {
627 debug("user %.100s does not match group %.100s at line %d",
630 debug("user %.100s matched group %.100s at line %d", user,
641 match_cfg_line(char **condition, int line, const char *user, const char *host,
645 char *arg, *attrib, *cp = *condition;
649 debug3("checking syntax for 'Match %s'", cp);
651 debug3("checking match for '%s' user %s host %s addr %s", cp,
652 user ? user : "(null)", host ? host : "(null)",
653 address ? address : "(null)");
655 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
656 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
657 error("Missing Match criteria for %s", attrib);
661 if (strcasecmp(attrib, "user") == 0) {
666 if (match_pattern_list(user, arg, len, 0) != 1)
669 debug("user %.100s matched 'User %.100s' at "
670 "line %d", user, arg, line);
671 } else if (strcasecmp(attrib, "group") == 0) {
672 switch (match_cfg_line_group(arg, line, user)) {
678 } else if (strcasecmp(attrib, "host") == 0) {
683 if (match_hostname(host, arg, len) != 1)
686 debug("connection from %.100s matched 'Host "
687 "%.100s' at line %d", host, arg, line);
688 } else if (strcasecmp(attrib, "address") == 0) {
693 if (match_hostname(address, arg, len) != 1)
696 debug("connection from %.100s matched 'Address "
697 "%.100s' at line %d", address, arg, line);
699 error("Unsupported Match attribute %s", attrib);
704 debug3("match %sfound", result ? "" : "not ");
709 #define WHITESPACE " \t\r\n"
712 process_server_config_line(ServerOptions *options, char *line,
713 const char *filename, int linenum, int *activep, const char *user,
714 const char *host, const char *address)
716 char *cp, **charptr, *arg, *p;
717 int cmdline = 0, *intptr, value, n;
718 ServerOpCodes opcode;
724 if ((arg = strdelim(&cp)) == NULL)
726 /* Ignore leading whitespace */
729 if (!arg || !*arg || *arg == '#')
733 opcode = parse_token(arg, filename, linenum, &flags);
735 if (activep == NULL) { /* We are processing a command line directive */
739 if (*activep && opcode != sMatch)
740 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
741 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
743 fatal("%s line %d: Directive '%s' is not allowed "
744 "within a Match block", filename, linenum, arg);
745 } else { /* this is a directive we have already processed */
753 /* Portable-specific options */
755 intptr = &options->use_pam;
758 /* Standard Options */
762 /* ignore ports from configfile if cmdline specifies ports */
763 if (options->ports_from_cmdline)
765 if (options->listen_addrs != NULL)
766 fatal("%s line %d: ports must be specified before "
767 "ListenAddress.", filename, linenum);
768 if (options->num_ports >= MAX_PORTS)
769 fatal("%s line %d: too many ports.",
772 if (!arg || *arg == '\0')
773 fatal("%s line %d: missing port number.",
775 options->ports[options->num_ports++] = a2port(arg);
776 if (options->ports[options->num_ports-1] == 0)
777 fatal("%s line %d: Badly formatted port number.",
782 intptr = &options->server_key_bits;
785 if (!arg || *arg == '\0')
786 fatal("%s line %d: missing integer value.",
789 if (*activep && *intptr == -1)
793 case sLoginGraceTime:
794 intptr = &options->login_grace_time;
797 if (!arg || *arg == '\0')
798 fatal("%s line %d: missing time value.",
800 if ((value = convtime(arg)) == -1)
801 fatal("%s line %d: invalid time value.",
807 case sKeyRegenerationTime:
808 intptr = &options->key_regeneration_time;
813 if (arg == NULL || *arg == '\0')
814 fatal("%s line %d: missing address",
816 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
817 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
818 && strchr(p+1, ':') != NULL) {
819 add_listen_addr(options, arg, 0);
824 fatal("%s line %d: bad address:port usage",
826 p = cleanhostname(p);
829 else if ((port = a2port(arg)) == 0)
830 fatal("%s line %d: bad port number", filename, linenum);
832 add_listen_addr(options, p, port);
838 if (!arg || *arg == '\0')
839 fatal("%s line %d: missing address family.",
841 intptr = &options->address_family;
842 if (options->listen_addrs != NULL)
843 fatal("%s line %d: address family must be specified before "
844 "ListenAddress.", filename, linenum);
845 if (strcasecmp(arg, "inet") == 0)
847 else if (strcasecmp(arg, "inet6") == 0)
849 else if (strcasecmp(arg, "any") == 0)
852 fatal("%s line %d: unsupported address family \"%s\".",
853 filename, linenum, arg);
859 intptr = &options->num_host_key_files;
860 if (*intptr >= MAX_HOSTKEYS)
861 fatal("%s line %d: too many host keys specified (max %d).",
862 filename, linenum, MAX_HOSTKEYS);
863 charptr = &options->host_key_files[*intptr];
866 if (!arg || *arg == '\0')
867 fatal("%s line %d: missing file name.",
869 if (*activep && *charptr == NULL) {
870 *charptr = tilde_expand_filename(arg, getuid());
871 /* increase optional counter */
873 *intptr = *intptr + 1;
878 charptr = &options->pid_file;
881 case sPermitRootLogin:
882 intptr = &options->permit_root_login;
884 if (!arg || *arg == '\0')
885 fatal("%s line %d: missing yes/"
886 "without-password/forced-commands-only/no "
887 "argument.", filename, linenum);
888 value = 0; /* silence compiler */
889 if (strcmp(arg, "without-password") == 0)
890 value = PERMIT_NO_PASSWD;
891 else if (strcmp(arg, "forced-commands-only") == 0)
892 value = PERMIT_FORCED_ONLY;
893 else if (strcmp(arg, "yes") == 0)
895 else if (strcmp(arg, "no") == 0)
898 fatal("%s line %d: Bad yes/"
899 "without-password/forced-commands-only/no "
900 "argument: %s", filename, linenum, arg);
906 intptr = &options->ignore_rhosts;
909 if (!arg || *arg == '\0')
910 fatal("%s line %d: missing yes/no argument.",
912 value = 0; /* silence compiler */
913 if (strcmp(arg, "yes") == 0)
915 else if (strcmp(arg, "no") == 0)
918 fatal("%s line %d: Bad yes/no argument: %s",
919 filename, linenum, arg);
920 if (*activep && *intptr == -1)
925 intptr = &options->none_enabled;
929 intptr = &options->tcp_rcv_buf_poll;
933 intptr = &options->hpn_disabled;
937 intptr = &options->hpn_buffer_size;
940 case sIgnoreUserKnownHosts:
941 intptr = &options->ignore_user_known_hosts;
944 case sRhostsRSAAuthentication:
945 intptr = &options->rhosts_rsa_authentication;
948 case sHostbasedAuthentication:
949 intptr = &options->hostbased_authentication;
952 case sHostbasedUsesNameFromPacketOnly:
953 intptr = &options->hostbased_uses_name_from_packet_only;
956 case sRSAAuthentication:
957 intptr = &options->rsa_authentication;
960 case sPubkeyAuthentication:
961 intptr = &options->pubkey_authentication;
964 case sKerberosAuthentication:
965 intptr = &options->kerberos_authentication;
968 case sKerberosOrLocalPasswd:
969 intptr = &options->kerberos_or_local_passwd;
972 case sKerberosTicketCleanup:
973 intptr = &options->kerberos_ticket_cleanup;
976 case sKerberosGetAFSToken:
977 intptr = &options->kerberos_get_afs_token;
980 case sGssAuthentication:
981 intptr = &options->gss_authentication;
985 intptr = &options->gss_keyex;
988 case sGssCleanupCreds:
989 intptr = &options->gss_cleanup_creds;
992 case sGssStrictAcceptor:
993 intptr = &options->gss_strict_acceptor;
997 charptr = &options->gss_creds_path;
1000 case sGsiAllowLimitedProxy:
1001 intptr = &options->gsi_allow_limited_proxy;
1004 #ifdef SESSION_HOOKS
1005 case sAllowSessionHooks:
1006 intptr = &options->session_hooks_allow;
1008 case sSessionHookStartupCmd:
1009 case sSessionHookShutdownCmd:
1010 arg = strdelim(&cp);
1011 if (!arg || *arg == '\0')
1012 fatal("%s line %d: empty session hook command",
1014 if (opcode==sSessionHookStartupCmd)
1015 options->session_hooks_startup_cmd = strdup(arg);
1017 options->session_hooks_shutdown_cmd = strdup(arg);
1021 case sPasswordAuthentication:
1022 intptr = &options->password_authentication;
1025 case sKbdInteractiveAuthentication:
1026 intptr = &options->kbd_interactive_authentication;
1029 case sChallengeResponseAuthentication:
1030 intptr = &options->challenge_response_authentication;
1034 intptr = &options->print_motd;
1038 intptr = &options->print_lastlog;
1041 case sX11Forwarding:
1042 intptr = &options->x11_forwarding;
1045 case sX11DisplayOffset:
1046 intptr = &options->x11_display_offset;
1049 case sX11UseLocalhost:
1050 intptr = &options->x11_use_localhost;
1053 case sXAuthLocation:
1054 charptr = &options->xauth_location;
1055 goto parse_filename;
1058 intptr = &options->strict_modes;
1062 intptr = &options->tcp_keep_alive;
1066 intptr = &options->permit_empty_passwd;
1069 case sPermitUserEnvironment:
1070 intptr = &options->permit_user_env;
1074 intptr = &options->use_login;
1078 intptr = &options->compression;
1079 arg = strdelim(&cp);
1080 if (!arg || *arg == '\0')
1081 fatal("%s line %d: missing yes/no/delayed "
1082 "argument.", filename, linenum);
1083 value = 0; /* silence compiler */
1084 if (strcmp(arg, "delayed") == 0)
1085 value = COMP_DELAYED;
1086 else if (strcmp(arg, "yes") == 0)
1088 else if (strcmp(arg, "no") == 0)
1091 fatal("%s line %d: Bad yes/no/delayed "
1092 "argument: %s", filename, linenum, arg);
1098 intptr = &options->gateway_ports;
1099 arg = strdelim(&cp);
1100 if (!arg || *arg == '\0')
1101 fatal("%s line %d: missing yes/no/clientspecified "
1102 "argument.", filename, linenum);
1103 value = 0; /* silence compiler */
1104 if (strcmp(arg, "clientspecified") == 0)
1106 else if (strcmp(arg, "yes") == 0)
1108 else if (strcmp(arg, "no") == 0)
1111 fatal("%s line %d: Bad yes/no/clientspecified "
1112 "argument: %s", filename, linenum, arg);
1113 if (*activep && *intptr == -1)
1118 intptr = &options->use_dns;
1122 intptr = (int *) &options->log_facility;
1123 arg = strdelim(&cp);
1124 value = log_facility_number(arg);
1125 if (value == SYSLOG_FACILITY_NOT_SET)
1126 fatal("%.200s line %d: unsupported log facility '%s'",
1127 filename, linenum, arg ? arg : "<NONE>");
1129 *intptr = (SyslogFacility) value;
1133 intptr = (int *) &options->log_level;
1134 arg = strdelim(&cp);
1135 value = log_level_number(arg);
1136 if (value == SYSLOG_LEVEL_NOT_SET)
1137 fatal("%.200s line %d: unsupported log level '%s'",
1138 filename, linenum, arg ? arg : "<NONE>");
1140 *intptr = (LogLevel) value;
1143 case sAllowTcpForwarding:
1144 intptr = &options->allow_tcp_forwarding;
1147 case sUsePrivilegeSeparation:
1148 intptr = &use_privsep;
1152 while ((arg = strdelim(&cp)) && *arg != '\0') {
1153 if (options->num_allow_users >= MAX_ALLOW_USERS)
1154 fatal("%s line %d: too many allow users.",
1156 options->allow_users[options->num_allow_users++] =
1162 while ((arg = strdelim(&cp)) && *arg != '\0') {
1163 if (options->num_deny_users >= MAX_DENY_USERS)
1164 fatal("%s line %d: too many deny users.",
1166 options->deny_users[options->num_deny_users++] =
1172 while ((arg = strdelim(&cp)) && *arg != '\0') {
1173 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1174 fatal("%s line %d: too many allow groups.",
1176 options->allow_groups[options->num_allow_groups++] =
1182 while ((arg = strdelim(&cp)) && *arg != '\0') {
1183 if (options->num_deny_groups >= MAX_DENY_GROUPS)
1184 fatal("%s line %d: too many deny groups.",
1186 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1191 arg = strdelim(&cp);
1192 if (!arg || *arg == '\0')
1193 fatal("%s line %d: Missing argument.", filename, linenum);
1194 if (!ciphers_valid(arg))
1195 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1196 filename, linenum, arg ? arg : "<NONE>");
1197 if (options->ciphers == NULL)
1198 options->ciphers = xstrdup(arg);
1202 arg = strdelim(&cp);
1203 if (!arg || *arg == '\0')
1204 fatal("%s line %d: Missing argument.", filename, linenum);
1205 if (!mac_valid(arg))
1206 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1207 filename, linenum, arg ? arg : "<NONE>");
1208 if (options->macs == NULL)
1209 options->macs = xstrdup(arg);
1213 intptr = &options->protocol;
1214 arg = strdelim(&cp);
1215 if (!arg || *arg == '\0')
1216 fatal("%s line %d: Missing argument.", filename, linenum);
1217 value = proto_spec(arg);
1218 if (value == SSH_PROTO_UNKNOWN)
1219 fatal("%s line %d: Bad protocol spec '%s'.",
1220 filename, linenum, arg ? arg : "<NONE>");
1221 if (*intptr == SSH_PROTO_UNKNOWN)
1226 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1227 fatal("%s line %d: too many subsystems defined.",
1230 arg = strdelim(&cp);
1231 if (!arg || *arg == '\0')
1232 fatal("%s line %d: Missing subsystem name.",
1235 arg = strdelim(&cp);
1238 for (i = 0; i < options->num_subsystems; i++)
1239 if (strcmp(arg, options->subsystem_name[i]) == 0)
1240 fatal("%s line %d: Subsystem '%s' already defined.",
1241 filename, linenum, arg);
1242 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1243 arg = strdelim(&cp);
1244 if (!arg || *arg == '\0')
1245 fatal("%s line %d: Missing subsystem command.",
1247 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
1249 /* Collect arguments (separate to executable) */
1251 len = strlen(p) + 1;
1252 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1253 len += 1 + strlen(arg);
1254 p = xrealloc(p, 1, len);
1255 strlcat(p, " ", len);
1256 strlcat(p, arg, len);
1258 options->subsystem_args[options->num_subsystems] = p;
1259 options->num_subsystems++;
1263 arg = strdelim(&cp);
1264 if (!arg || *arg == '\0')
1265 fatal("%s line %d: Missing MaxStartups spec.",
1267 if ((n = sscanf(arg, "%d:%d:%d",
1268 &options->max_startups_begin,
1269 &options->max_startups_rate,
1270 &options->max_startups)) == 3) {
1271 if (options->max_startups_begin >
1272 options->max_startups ||
1273 options->max_startups_rate > 100 ||
1274 options->max_startups_rate < 1)
1275 fatal("%s line %d: Illegal MaxStartups spec.",
1278 fatal("%s line %d: Illegal MaxStartups spec.",
1281 options->max_startups = options->max_startups_begin;
1285 intptr = &options->max_authtries;
1289 charptr = &options->banner;
1290 goto parse_filename;
1292 * These options can contain %X options expanded at
1293 * connect time, so that you can specify paths like:
1295 * AuthorizedKeysFile /etc/ssh_keys/%u
1297 case sAuthorizedKeysFile:
1298 case sAuthorizedKeysFile2:
1299 charptr = (opcode == sAuthorizedKeysFile) ?
1300 &options->authorized_keys_file :
1301 &options->authorized_keys_file2;
1302 goto parse_filename;
1304 case sClientAliveInterval:
1305 intptr = &options->client_alive_interval;
1308 case sClientAliveCountMax:
1309 intptr = &options->client_alive_count_max;
1313 while ((arg = strdelim(&cp)) && *arg != '\0') {
1314 if (strchr(arg, '=') != NULL)
1315 fatal("%s line %d: Invalid environment name.",
1317 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1318 fatal("%s line %d: too many allow env.",
1322 options->accept_env[options->num_accept_env++] =
1328 intptr = &options->permit_tun;
1329 arg = strdelim(&cp);
1330 if (!arg || *arg == '\0')
1331 fatal("%s line %d: Missing yes/point-to-point/"
1332 "ethernet/no argument.", filename, linenum);
1333 value = 0; /* silence compiler */
1334 if (strcasecmp(arg, "ethernet") == 0)
1335 value = SSH_TUNMODE_ETHERNET;
1336 else if (strcasecmp(arg, "point-to-point") == 0)
1337 value = SSH_TUNMODE_POINTOPOINT;
1338 else if (strcasecmp(arg, "yes") == 0)
1339 value = SSH_TUNMODE_YES;
1340 else if (strcasecmp(arg, "no") == 0)
1341 value = SSH_TUNMODE_NO;
1343 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1344 "no argument: %s", filename, linenum, arg);
1351 fatal("Match directive not supported as a command-line "
1353 value = match_cfg_line(&cp, linenum, user, host, address);
1355 fatal("%s line %d: Bad Match condition", filename,
1361 arg = strdelim(&cp);
1362 if (!arg || *arg == '\0')
1363 fatal("%s line %d: missing PermitOpen specification",
1365 n = options->num_permitted_opens; /* modified later */
1366 if (strcmp(arg, "any") == 0) {
1367 if (*activep && n == -1) {
1368 channel_clear_adm_permitted_opens();
1369 options->num_permitted_opens = 0;
1373 if (*activep && n == -1)
1374 channel_clear_adm_permitted_opens();
1375 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1378 fatal("%s line %d: missing host in PermitOpen",
1380 p = cleanhostname(p);
1381 if (arg == NULL || (port = a2port(arg)) == 0)
1382 fatal("%s line %d: bad port number in "
1383 "PermitOpen", filename, linenum);
1384 if (*activep && n == -1)
1385 options->num_permitted_opens =
1386 channel_add_adm_permitted_opens(p, port);
1392 fatal("%.200s line %d: Missing argument.", filename,
1394 len = strspn(cp, WHITESPACE);
1395 if (*activep && options->adm_forced_command == NULL)
1396 options->adm_forced_command = xstrdup(cp + len);
1400 logit("%s line %d: Deprecated option %s",
1401 filename, linenum, arg);
1403 arg = strdelim(&cp);
1407 logit("%s line %d: Unsupported option %s",
1408 filename, linenum, arg);
1410 arg = strdelim(&cp);
1414 fatal("%s line %d: Missing handler for opcode %s (%d)",
1415 filename, linenum, arg, opcode);
1417 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1418 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1419 filename, linenum, arg);
1423 /* Reads the server configuration file. */
1426 load_server_config(const char *filename, Buffer *conf)
1428 char line[1024], *cp;
1431 debug2("%s: filename %s", __func__, filename);
1432 if ((f = fopen(filename, "r")) == NULL) {
1437 while (fgets(line, sizeof(line), f)) {
1439 * Trim out comments and strip whitespace
1440 * NB - preserve newlines, they are needed to reproduce
1441 * line numbers later for error messages
1443 if ((cp = strchr(line, '#')) != NULL)
1444 memcpy(cp, "\n", 2);
1445 cp = line + strspn(line, " \t\r");
1447 buffer_append(conf, cp, strlen(cp));
1449 buffer_append(conf, "\0", 1);
1451 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1455 parse_server_match_config(ServerOptions *options, const char *user,
1456 const char *host, const char *address)
1460 initialize_server_options(&mo);
1461 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1462 copy_set_server_options(options, &mo, 0);
1466 #define M_CP_INTOPT(n) do {\
1470 #define M_CP_STROPT(n) do {\
1471 if (src->n != NULL) { \
1472 if (dst->n != NULL) \
1479 * Copy any supported values that are set.
1481 * If the preauth flag is set, we do not bother copying the the string or
1482 * array values that are not used pre-authentication, because any that we
1483 * do use must be explictly sent in mm_getpwnamallow().
1486 copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1488 M_CP_INTOPT(password_authentication);
1489 M_CP_INTOPT(gss_authentication);
1490 M_CP_INTOPT(rsa_authentication);
1491 M_CP_INTOPT(pubkey_authentication);
1492 M_CP_INTOPT(kerberos_authentication);
1493 M_CP_INTOPT(hostbased_authentication);
1494 M_CP_INTOPT(kbd_interactive_authentication);
1496 M_CP_INTOPT(allow_tcp_forwarding);
1497 M_CP_INTOPT(gateway_ports);
1498 M_CP_INTOPT(x11_display_offset);
1499 M_CP_INTOPT(x11_forwarding);
1500 M_CP_INTOPT(x11_use_localhost);
1502 M_CP_STROPT(banner);
1505 M_CP_STROPT(adm_forced_command);
1512 parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1513 const char *user, const char *host, const char *address)
1515 int active, linenum, bad_options = 0;
1516 char *cp, *obuf, *cbuf;
1518 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1520 obuf = cbuf = xstrdup(buffer_ptr(conf));
1521 active = user ? 0 : 1;
1523 while ((cp = strsep(&cbuf, "\n")) != NULL) {
1524 if (process_server_config_line(options, cp, filename,
1525 linenum++, &active, user, host, address) != 0)
1529 if (bad_options > 0)
1530 fatal("%s: terminating, %d bad configuration options",
1531 filename, bad_options);