1 /* $OpenBSD: servconf.c,v 1.165 2006/08/14 12:40:25 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)
324 if (use_privsep && options->compression == 1) {
325 error("This platform does not support both privilege "
326 "separation and compression");
327 error("Compression disabled");
328 options->compression = 0;
334 /* Keyword tokens. */
336 sBadOption, /* == unknown option */
337 /* Portable-specific options */
339 /* Standard Options */
340 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
341 sPermitRootLogin, sLogFacility, sLogLevel,
342 sRhostsRSAAuthentication, sRSAAuthentication,
343 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
344 sKerberosGetAFSToken,
345 sKerberosTgtPassing, sChallengeResponseAuthentication,
347 sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
349 sPasswordAuthentication, sKbdInteractiveAuthentication,
350 sListenAddress, sAddressFamily,
351 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
352 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
353 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
354 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
355 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
356 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
357 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
358 sMaxStartups, sMaxAuthTries,
359 sBanner, sUseDNS, sHostbasedAuthentication,
360 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
361 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
362 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
365 sGsiAllowLimitedProxy,
366 sAcceptEnv, sPermitTunnel,
367 sMatch, sPermitOpen, sForceCommand,
368 sUsePrivilegeSeparation, sNoneEnabled, sTcpRcvBufPoll,
369 sHPNDisabled, sHPNBufferSize,
370 sDeprecated, sUnsupported
373 #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
374 #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
375 #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
377 /* Textual representation of the tokens. */
380 ServerOpCodes opcode;
383 /* Portable-specific options */
385 { "usepam", sUsePAM, SSHCFG_GLOBAL },
387 { "usepam", sUnsupported, SSHCFG_GLOBAL },
389 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
390 /* Standard Options */
391 { "port", sPort, SSHCFG_GLOBAL },
392 { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
393 { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
394 { "pidfile", sPidFile, SSHCFG_GLOBAL },
395 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
396 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
397 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
398 { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL },
399 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
400 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
401 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
402 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL },
403 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL },
404 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
405 { "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL },
406 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },
407 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
409 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL },
410 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
411 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
413 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
415 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
418 { "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL },
419 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
420 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
421 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
423 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
424 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
426 { "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
427 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
428 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
429 { "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL },
430 { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
432 { "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL },
435 { "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
436 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
437 { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
438 { "gssapicredentialspath", sUnsupported, SSHCFG_GLOBAL },
439 { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
441 { "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL },
445 { "allowsessionhooks", sAllowSessionHooks, SSHCFG_GLOBAL },
446 { "sessionhookstartupcmd", sSessionHookStartupCmd, SSHCFG_GLOBAL },
447 { "sessionhookshutdowncmd", sSessionHookShutdownCmd, SSHCFG_GLOBAL },
449 { "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
450 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL },
451 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
452 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
453 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
454 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
455 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
456 { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
457 { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
458 { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
459 { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
460 { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
461 { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
462 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
463 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
464 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
465 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
466 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
467 { "uselogin", sUseLogin, SSHCFG_GLOBAL },
468 { "compression", sCompression, SSHCFG_GLOBAL },
469 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
470 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
471 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
472 { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
473 { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
474 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
475 { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
476 { "ciphers", sCiphers, SSHCFG_GLOBAL },
477 { "macs", sMacs, SSHCFG_GLOBAL },
478 { "protocol", sProtocol, SSHCFG_GLOBAL },
479 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
480 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
481 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
482 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
483 { "banner", sBanner, SSHCFG_GLOBAL },
484 { "usedns", sUseDNS, SSHCFG_GLOBAL },
485 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
486 { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
487 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
488 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
489 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
490 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
491 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
492 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
493 { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
494 { "match", sMatch, SSHCFG_ALL },
495 { "permitopen", sPermitOpen, SSHCFG_ALL },
496 { "forcecommand", sForceCommand, SSHCFG_ALL },
497 { "noneenabled", sNoneEnabled },
498 { "hpndisabled", sHPNDisabled },
499 { "hpnbuffersize", sHPNBufferSize },
500 { "tcprcvbufpoll", sTcpRcvBufPoll },
501 { NULL, sBadOption, 0 }
505 * Returns the number of the token pointed to by cp or sBadOption.
509 parse_token(const char *cp, const char *filename,
510 int linenum, u_int *flags)
514 for (i = 0; keywords[i].name; i++)
515 if (strcasecmp(cp, keywords[i].name) == 0) {
516 debug ("Config token is %s", keywords[i].name);
517 *flags = keywords[i].flags;
518 return keywords[i].opcode;
521 error("%s: line %d: Bad configuration option: %s",
522 filename, linenum, cp);
527 add_listen_addr(ServerOptions *options, char *addr, u_short port)
531 if (options->num_ports == 0)
532 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
533 if (options->address_family == -1)
534 options->address_family = AF_UNSPEC;
536 for (i = 0; i < options->num_ports; i++)
537 add_one_listen_addr(options, addr, options->ports[i]);
539 add_one_listen_addr(options, addr, port);
543 add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
545 struct addrinfo hints, *ai, *aitop;
546 char strport[NI_MAXSERV];
549 memset(&hints, 0, sizeof(hints));
550 hints.ai_family = options->address_family;
551 hints.ai_socktype = SOCK_STREAM;
552 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
553 snprintf(strport, sizeof strport, "%u", port);
554 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
555 fatal("bad addr or host: %s (%s)",
556 addr ? addr : "<NULL>",
557 gai_strerror(gaierr));
558 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
560 ai->ai_next = options->listen_addrs;
561 options->listen_addrs = aitop;
565 * The strategy for the Match blocks is that the config file is parsed twice.
567 * The first time is at startup. activep is initialized to 1 and the
568 * directives in the global context are processed and acted on. Hitting a
569 * Match directive unsets activep and the directives inside the block are
570 * checked for syntax only.
572 * The second time is after a connection has been established but before
573 * authentication. activep is initialized to 2 and global config directives
574 * are ignored since they have already been processed. If the criteria in a
575 * Match block is met, activep is set and the subsequent directives
576 * processed and actioned until EOF or another Match block unsets it. Any
577 * options set are copied into the main server config.
579 * Potential additions/improvements:
580 * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
582 * - Add a Tag directive (idea from David Leonard) ala pf, eg:
583 * Match Address 192.168.0.*
588 * AllowTcpForwarding yes
589 * GatewayPorts clientspecified
592 * - Add a PermittedChannelRequests directive
594 * PermittedChannelRequests session,forwarded-tcpip
598 match_cfg_line_group(const char *grps, int line, const char *user)
602 char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
606 * Even if we do not have a user yet, we still need to check for
609 arg = cp = xstrdup(grps);
610 while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
611 if (ngrps >= MAX_MATCH_GROUPS) {
612 error("line %d: too many groups in Match Group", line);
616 grplist[ngrps++] = p;
622 if ((pw = getpwnam(user)) == NULL) {
623 debug("Can't match group at line %d because user %.100s does "
624 "not exist", line, user);
625 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
626 debug("Can't Match group because user %.100s not in any group "
627 "at line %d", user, line);
628 } else if (ga_match(grplist, ngrps) != 1) {
629 debug("user %.100s does not match group %.100s at line %d",
632 debug("user %.100s matched group %.100s at line %d", user,
643 match_cfg_line(char **condition, int line, const char *user, const char *host,
647 char *arg, *attrib, *cp = *condition;
651 debug3("checking syntax for 'Match %s'", cp);
653 debug3("checking match for '%s' user %s host %s addr %s", cp,
654 user ? user : "(null)", host ? host : "(null)",
655 address ? address : "(null)");
657 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
658 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
659 error("Missing Match criteria for %s", attrib);
663 if (strcasecmp(attrib, "user") == 0) {
668 if (match_pattern_list(user, arg, len, 0) != 1)
671 debug("user %.100s matched 'User %.100s' at "
672 "line %d", user, arg, line);
673 } else if (strcasecmp(attrib, "group") == 0) {
674 switch (match_cfg_line_group(arg, line, user)) {
680 } else if (strcasecmp(attrib, "host") == 0) {
685 if (match_hostname(host, arg, len) != 1)
688 debug("connection from %.100s matched 'Host "
689 "%.100s' at line %d", host, arg, line);
690 } else if (strcasecmp(attrib, "address") == 0) {
691 debug("address '%s' arg '%s'", address, arg);
696 if (match_hostname(address, arg, len) != 1)
699 debug("connection from %.100s matched 'Address "
700 "%.100s' at line %d", address, arg, line);
702 error("Unsupported Match attribute %s", attrib);
707 debug3("match %sfound", result ? "" : "not ");
712 #define WHITESPACE " \t\r\n"
715 process_server_config_line(ServerOptions *options, char *line,
716 const char *filename, int linenum, int *activep, const char *user,
717 const char *host, const char *address)
719 char *cp, **charptr, *arg, *p;
720 int cmdline = 0, *intptr, value, n;
721 ServerOpCodes opcode;
727 if ((arg = strdelim(&cp)) == NULL)
729 /* Ignore leading whitespace */
732 if (!arg || !*arg || *arg == '#')
736 opcode = parse_token(arg, filename, linenum, &flags);
738 if (activep == NULL) { /* We are processing a command line directive */
742 if (*activep && opcode != sMatch)
743 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
744 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
746 fatal("%s line %d: Directive '%s' is not allowed "
747 "within a Match block", filename, linenum, arg);
748 } else { /* this is a directive we have already processed */
756 /* Portable-specific options */
758 intptr = &options->use_pam;
761 /* Standard Options */
765 /* ignore ports from configfile if cmdline specifies ports */
766 if (options->ports_from_cmdline)
768 if (options->listen_addrs != NULL)
769 fatal("%s line %d: ports must be specified before "
770 "ListenAddress.", filename, linenum);
771 if (options->num_ports >= MAX_PORTS)
772 fatal("%s line %d: too many ports.",
775 if (!arg || *arg == '\0')
776 fatal("%s line %d: missing port number.",
778 options->ports[options->num_ports++] = a2port(arg);
779 if (options->ports[options->num_ports-1] == 0)
780 fatal("%s line %d: Badly formatted port number.",
785 intptr = &options->server_key_bits;
788 if (!arg || *arg == '\0')
789 fatal("%s line %d: missing integer value.",
792 if (*activep && *intptr == -1)
796 case sLoginGraceTime:
797 intptr = &options->login_grace_time;
800 if (!arg || *arg == '\0')
801 fatal("%s line %d: missing time value.",
803 if ((value = convtime(arg)) == -1)
804 fatal("%s line %d: invalid time value.",
810 case sKeyRegenerationTime:
811 intptr = &options->key_regeneration_time;
816 if (arg == NULL || *arg == '\0')
817 fatal("%s line %d: missing address",
819 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
820 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
821 && strchr(p+1, ':') != NULL) {
822 add_listen_addr(options, arg, 0);
827 fatal("%s line %d: bad address:port usage",
829 p = cleanhostname(p);
832 else if ((port = a2port(arg)) == 0)
833 fatal("%s line %d: bad port number", filename, linenum);
835 add_listen_addr(options, p, port);
841 if (!arg || *arg == '\0')
842 fatal("%s line %d: missing address family.",
844 intptr = &options->address_family;
845 if (options->listen_addrs != NULL)
846 fatal("%s line %d: address family must be specified before "
847 "ListenAddress.", filename, linenum);
848 if (strcasecmp(arg, "inet") == 0)
850 else if (strcasecmp(arg, "inet6") == 0)
852 else if (strcasecmp(arg, "any") == 0)
855 fatal("%s line %d: unsupported address family \"%s\".",
856 filename, linenum, arg);
862 intptr = &options->num_host_key_files;
863 if (*intptr >= MAX_HOSTKEYS)
864 fatal("%s line %d: too many host keys specified (max %d).",
865 filename, linenum, MAX_HOSTKEYS);
866 charptr = &options->host_key_files[*intptr];
869 if (!arg || *arg == '\0')
870 fatal("%s line %d: missing file name.",
872 if (*activep && *charptr == NULL) {
873 *charptr = tilde_expand_filename(arg, getuid());
874 /* increase optional counter */
876 *intptr = *intptr + 1;
881 charptr = &options->pid_file;
884 case sPermitRootLogin:
885 intptr = &options->permit_root_login;
887 if (!arg || *arg == '\0')
888 fatal("%s line %d: missing yes/"
889 "without-password/forced-commands-only/no "
890 "argument.", filename, linenum);
891 value = 0; /* silence compiler */
892 if (strcmp(arg, "without-password") == 0)
893 value = PERMIT_NO_PASSWD;
894 else if (strcmp(arg, "forced-commands-only") == 0)
895 value = PERMIT_FORCED_ONLY;
896 else if (strcmp(arg, "yes") == 0)
898 else if (strcmp(arg, "no") == 0)
901 fatal("%s line %d: Bad yes/"
902 "without-password/forced-commands-only/no "
903 "argument: %s", filename, linenum, arg);
909 intptr = &options->ignore_rhosts;
912 if (!arg || *arg == '\0')
913 fatal("%s line %d: missing yes/no argument.",
915 value = 0; /* silence compiler */
916 if (strcmp(arg, "yes") == 0)
918 else if (strcmp(arg, "no") == 0)
921 fatal("%s line %d: Bad yes/no argument: %s",
922 filename, linenum, arg);
923 if (*activep && *intptr == -1)
928 intptr = &options->none_enabled;
932 intptr = &options->tcp_rcv_buf_poll;
936 intptr = &options->hpn_disabled;
940 intptr = &options->hpn_buffer_size;
943 case sIgnoreUserKnownHosts:
944 intptr = &options->ignore_user_known_hosts;
947 case sRhostsRSAAuthentication:
948 intptr = &options->rhosts_rsa_authentication;
951 case sHostbasedAuthentication:
952 intptr = &options->hostbased_authentication;
955 case sHostbasedUsesNameFromPacketOnly:
956 intptr = &options->hostbased_uses_name_from_packet_only;
959 case sRSAAuthentication:
960 intptr = &options->rsa_authentication;
963 case sPubkeyAuthentication:
964 intptr = &options->pubkey_authentication;
967 case sKerberosAuthentication:
968 intptr = &options->kerberos_authentication;
971 case sKerberosOrLocalPasswd:
972 intptr = &options->kerberos_or_local_passwd;
975 case sKerberosTicketCleanup:
976 intptr = &options->kerberos_ticket_cleanup;
979 case sKerberosGetAFSToken:
980 intptr = &options->kerberos_get_afs_token;
983 case sGssAuthentication:
984 intptr = &options->gss_authentication;
988 intptr = &options->gss_keyex;
991 case sGssCleanupCreds:
992 intptr = &options->gss_cleanup_creds;
995 case sGssStrictAcceptor:
996 intptr = &options->gss_strict_acceptor;
1000 charptr = &options->gss_creds_path;
1001 goto parse_filename;
1003 case sGsiAllowLimitedProxy:
1004 intptr = &options->gsi_allow_limited_proxy;
1007 #ifdef SESSION_HOOKS
1008 case sAllowSessionHooks:
1009 intptr = &options->session_hooks_allow;
1011 case sSessionHookStartupCmd:
1012 case sSessionHookShutdownCmd:
1013 arg = strdelim(&cp);
1014 if (!arg || *arg == '\0')
1015 fatal("%s line %d: empty session hook command",
1017 if (opcode==sSessionHookStartupCmd)
1018 options->session_hooks_startup_cmd = strdup(arg);
1020 options->session_hooks_shutdown_cmd = strdup(arg);
1024 case sPasswordAuthentication:
1025 intptr = &options->password_authentication;
1028 case sKbdInteractiveAuthentication:
1029 intptr = &options->kbd_interactive_authentication;
1032 case sChallengeResponseAuthentication:
1033 intptr = &options->challenge_response_authentication;
1037 intptr = &options->print_motd;
1041 intptr = &options->print_lastlog;
1044 case sX11Forwarding:
1045 intptr = &options->x11_forwarding;
1048 case sX11DisplayOffset:
1049 intptr = &options->x11_display_offset;
1052 case sX11UseLocalhost:
1053 intptr = &options->x11_use_localhost;
1056 case sXAuthLocation:
1057 charptr = &options->xauth_location;
1058 goto parse_filename;
1061 intptr = &options->strict_modes;
1065 intptr = &options->tcp_keep_alive;
1069 intptr = &options->permit_empty_passwd;
1072 case sPermitUserEnvironment:
1073 intptr = &options->permit_user_env;
1077 intptr = &options->use_login;
1081 intptr = &options->compression;
1082 arg = strdelim(&cp);
1083 if (!arg || *arg == '\0')
1084 fatal("%s line %d: missing yes/no/delayed "
1085 "argument.", filename, linenum);
1086 value = 0; /* silence compiler */
1087 if (strcmp(arg, "delayed") == 0)
1088 value = COMP_DELAYED;
1089 else if (strcmp(arg, "yes") == 0)
1091 else if (strcmp(arg, "no") == 0)
1094 fatal("%s line %d: Bad yes/no/delayed "
1095 "argument: %s", filename, linenum, arg);
1101 intptr = &options->gateway_ports;
1102 arg = strdelim(&cp);
1103 if (!arg || *arg == '\0')
1104 fatal("%s line %d: missing yes/no/clientspecified "
1105 "argument.", filename, linenum);
1106 value = 0; /* silence compiler */
1107 if (strcmp(arg, "clientspecified") == 0)
1109 else if (strcmp(arg, "yes") == 0)
1111 else if (strcmp(arg, "no") == 0)
1114 fatal("%s line %d: Bad yes/no/clientspecified "
1115 "argument: %s", filename, linenum, arg);
1121 intptr = &options->use_dns;
1125 intptr = (int *) &options->log_facility;
1126 arg = strdelim(&cp);
1127 value = log_facility_number(arg);
1128 if (value == SYSLOG_FACILITY_NOT_SET)
1129 fatal("%.200s line %d: unsupported log facility '%s'",
1130 filename, linenum, arg ? arg : "<NONE>");
1132 *intptr = (SyslogFacility) value;
1136 intptr = (int *) &options->log_level;
1137 arg = strdelim(&cp);
1138 value = log_level_number(arg);
1139 if (value == SYSLOG_LEVEL_NOT_SET)
1140 fatal("%.200s line %d: unsupported log level '%s'",
1141 filename, linenum, arg ? arg : "<NONE>");
1143 *intptr = (LogLevel) value;
1146 case sAllowTcpForwarding:
1147 intptr = &options->allow_tcp_forwarding;
1150 case sUsePrivilegeSeparation:
1151 intptr = &use_privsep;
1155 while ((arg = strdelim(&cp)) && *arg != '\0') {
1156 if (options->num_allow_users >= MAX_ALLOW_USERS)
1157 fatal("%s line %d: too many allow users.",
1159 options->allow_users[options->num_allow_users++] =
1165 while ((arg = strdelim(&cp)) && *arg != '\0') {
1166 if (options->num_deny_users >= MAX_DENY_USERS)
1167 fatal("%s line %d: too many deny users.",
1169 options->deny_users[options->num_deny_users++] =
1175 while ((arg = strdelim(&cp)) && *arg != '\0') {
1176 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1177 fatal("%s line %d: too many allow groups.",
1179 options->allow_groups[options->num_allow_groups++] =
1185 while ((arg = strdelim(&cp)) && *arg != '\0') {
1186 if (options->num_deny_groups >= MAX_DENY_GROUPS)
1187 fatal("%s line %d: too many deny groups.",
1189 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1194 arg = strdelim(&cp);
1195 if (!arg || *arg == '\0')
1196 fatal("%s line %d: Missing argument.", filename, linenum);
1197 if (!ciphers_valid(arg))
1198 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1199 filename, linenum, arg ? arg : "<NONE>");
1200 if (options->ciphers == NULL)
1201 options->ciphers = xstrdup(arg);
1205 arg = strdelim(&cp);
1206 if (!arg || *arg == '\0')
1207 fatal("%s line %d: Missing argument.", filename, linenum);
1208 if (!mac_valid(arg))
1209 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1210 filename, linenum, arg ? arg : "<NONE>");
1211 if (options->macs == NULL)
1212 options->macs = xstrdup(arg);
1216 intptr = &options->protocol;
1217 arg = strdelim(&cp);
1218 if (!arg || *arg == '\0')
1219 fatal("%s line %d: Missing argument.", filename, linenum);
1220 value = proto_spec(arg);
1221 if (value == SSH_PROTO_UNKNOWN)
1222 fatal("%s line %d: Bad protocol spec '%s'.",
1223 filename, linenum, arg ? arg : "<NONE>");
1224 if (*intptr == SSH_PROTO_UNKNOWN)
1229 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1230 fatal("%s line %d: too many subsystems defined.",
1233 arg = strdelim(&cp);
1234 if (!arg || *arg == '\0')
1235 fatal("%s line %d: Missing subsystem name.",
1238 arg = strdelim(&cp);
1241 for (i = 0; i < options->num_subsystems; i++)
1242 if (strcmp(arg, options->subsystem_name[i]) == 0)
1243 fatal("%s line %d: Subsystem '%s' already defined.",
1244 filename, linenum, arg);
1245 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1246 arg = strdelim(&cp);
1247 if (!arg || *arg == '\0')
1248 fatal("%s line %d: Missing subsystem command.",
1250 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
1252 /* Collect arguments (separate to executable) */
1254 len = strlen(p) + 1;
1255 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1256 len += 1 + strlen(arg);
1257 p = xrealloc(p, 1, len);
1258 strlcat(p, " ", len);
1259 strlcat(p, arg, len);
1261 options->subsystem_args[options->num_subsystems] = p;
1262 options->num_subsystems++;
1266 arg = strdelim(&cp);
1267 if (!arg || *arg == '\0')
1268 fatal("%s line %d: Missing MaxStartups spec.",
1270 if ((n = sscanf(arg, "%d:%d:%d",
1271 &options->max_startups_begin,
1272 &options->max_startups_rate,
1273 &options->max_startups)) == 3) {
1274 if (options->max_startups_begin >
1275 options->max_startups ||
1276 options->max_startups_rate > 100 ||
1277 options->max_startups_rate < 1)
1278 fatal("%s line %d: Illegal MaxStartups spec.",
1281 fatal("%s line %d: Illegal MaxStartups spec.",
1284 options->max_startups = options->max_startups_begin;
1288 intptr = &options->max_authtries;
1292 charptr = &options->banner;
1293 goto parse_filename;
1295 * These options can contain %X options expanded at
1296 * connect time, so that you can specify paths like:
1298 * AuthorizedKeysFile /etc/ssh_keys/%u
1300 case sAuthorizedKeysFile:
1301 case sAuthorizedKeysFile2:
1302 charptr = (opcode == sAuthorizedKeysFile) ?
1303 &options->authorized_keys_file :
1304 &options->authorized_keys_file2;
1305 goto parse_filename;
1307 case sClientAliveInterval:
1308 intptr = &options->client_alive_interval;
1311 case sClientAliveCountMax:
1312 intptr = &options->client_alive_count_max;
1316 while ((arg = strdelim(&cp)) && *arg != '\0') {
1317 if (strchr(arg, '=') != NULL)
1318 fatal("%s line %d: Invalid environment name.",
1320 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1321 fatal("%s line %d: too many allow env.",
1325 options->accept_env[options->num_accept_env++] =
1331 intptr = &options->permit_tun;
1332 arg = strdelim(&cp);
1333 if (!arg || *arg == '\0')
1334 fatal("%s line %d: Missing yes/point-to-point/"
1335 "ethernet/no argument.", filename, linenum);
1336 value = 0; /* silence compiler */
1337 if (strcasecmp(arg, "ethernet") == 0)
1338 value = SSH_TUNMODE_ETHERNET;
1339 else if (strcasecmp(arg, "point-to-point") == 0)
1340 value = SSH_TUNMODE_POINTOPOINT;
1341 else if (strcasecmp(arg, "yes") == 0)
1342 value = SSH_TUNMODE_YES;
1343 else if (strcasecmp(arg, "no") == 0)
1344 value = SSH_TUNMODE_NO;
1346 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1347 "no argument: %s", filename, linenum, arg);
1354 fatal("Match directive not supported as a command-line "
1356 value = match_cfg_line(&cp, linenum, user, host, address);
1358 fatal("%s line %d: Bad Match condition", filename,
1364 arg = strdelim(&cp);
1365 if (!arg || *arg == '\0')
1366 fatal("%s line %d: missing PermitOpen specification",
1368 if (strcmp(arg, "any") == 0) {
1370 channel_clear_adm_permitted_opens();
1371 options->num_permitted_opens = 0;
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 && options->num_permitted_opens == -1) {
1385 channel_clear_adm_permitted_opens();
1386 options->num_permitted_opens =
1387 channel_add_adm_permitted_opens(p, port);
1394 fatal("%.200s line %d: Missing argument.", filename,
1396 len = strspn(cp, WHITESPACE);
1397 if (*activep && options->adm_forced_command == NULL)
1398 options->adm_forced_command = xstrdup(cp + len);
1402 logit("%s line %d: Deprecated option %s",
1403 filename, linenum, arg);
1405 arg = strdelim(&cp);
1409 logit("%s line %d: Unsupported option %s",
1410 filename, linenum, arg);
1412 arg = strdelim(&cp);
1416 fatal("%s line %d: Missing handler for opcode %s (%d)",
1417 filename, linenum, arg, opcode);
1419 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1420 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1421 filename, linenum, arg);
1425 /* Reads the server configuration file. */
1428 load_server_config(const char *filename, Buffer *conf)
1430 char line[1024], *cp;
1433 debug2("%s: filename %s", __func__, filename);
1434 if ((f = fopen(filename, "r")) == NULL) {
1439 while (fgets(line, sizeof(line), f)) {
1441 * Trim out comments and strip whitespace
1442 * NB - preserve newlines, they are needed to reproduce
1443 * line numbers later for error messages
1445 if ((cp = strchr(line, '#')) != NULL)
1446 memcpy(cp, "\n", 2);
1447 cp = line + strspn(line, " \t\r");
1449 buffer_append(conf, cp, strlen(cp));
1451 buffer_append(conf, "\0", 1);
1453 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1457 parse_server_match_config(ServerOptions *options, const char *user,
1458 const char *host, const char *address)
1462 initialize_server_options(&mo);
1463 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1464 copy_set_server_options(options, &mo);
1467 /* Copy any (supported) values that are set */
1469 copy_set_server_options(ServerOptions *dst, ServerOptions *src)
1471 if (src->allow_tcp_forwarding != -1)
1472 dst->allow_tcp_forwarding = src->allow_tcp_forwarding;
1473 if (src->gateway_ports != -1)
1474 dst->gateway_ports = src->gateway_ports;
1475 if (src->adm_forced_command != NULL) {
1476 if (dst->adm_forced_command != NULL)
1477 xfree(dst->adm_forced_command);
1478 dst->adm_forced_command = src->adm_forced_command;
1480 if (src->x11_display_offset != -1)
1481 dst->x11_display_offset = src->x11_display_offset;
1482 if (src->x11_forwarding != -1)
1483 dst->x11_forwarding = src->x11_forwarding;
1484 if (src->x11_use_localhost != -1)
1485 dst->x11_use_localhost = src->x11_use_localhost;
1489 parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1490 const char *user, const char *host, const char *address)
1492 int active, linenum, bad_options = 0;
1493 char *cp, *obuf, *cbuf;
1495 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1497 obuf = cbuf = xstrdup(buffer_ptr(conf));
1498 active = user ? 0 : 1;
1500 while ((cp = strsep(&cbuf, "\n")) != NULL) {
1501 if (process_server_config_line(options, cp, filename,
1502 linenum++, &active, user, host, address) != 0)
1506 if (bad_options > 0)
1507 fatal("%s: terminating, %d bad configuration options",
1508 filename, bad_options);