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