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