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