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