]> andersk Git - gssapi-openssh.git/blame - openssh/servconf.c
4.2 release
[gssapi-openssh.git] / openssh / servconf.c
CommitLineData
25d429a2 1/* $OpenBSD: servconf.c,v 1.172 2007/04/23 10:15:39 dtucker Exp $ */
3c0ef626 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"
3c0ef626 14
2e437378 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"
3c0ef626 28#include "ssh.h"
29#include "log.h"
2e437378 30#include "buffer.h"
3c0ef626 31#include "servconf.h"
3c0ef626 32#include "compat.h"
33#include "pathnames.h"
3c0ef626 34#include "misc.h"
35#include "cipher.h"
2e437378 36#include "key.h"
3c0ef626 37#include "kex.h"
38#include "mac.h"
2e437378 39#include "match.h"
40#include "channels.h"
41#include "groupaccess.h"
3c0ef626 42
43static void add_listen_addr(ServerOptions *, char *, u_short);
44static void add_one_listen_addr(ServerOptions *, char *, u_short);
45
2980ea68 46/* Use of privilege separation or not */
47extern int use_privsep;
2e437378 48extern Buffer cfg;
3c0ef626 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 */
70791e56 58 options->use_pam = -1;
3c0ef626 59
60 /* Standard Options */
61 options->num_ports = 0;
62 options->ports_from_cmdline = 0;
63 options->listen_addrs = NULL;
34fee935 64 options->address_family = -1;
3c0ef626 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;
e9a17296 77 options->x11_use_localhost = -1;
3c0ef626 78 options->xauth_location = NULL;
79 options->strict_modes = -1;
416fd2a8 80 options->tcp_keep_alive = -1;
e9a17296 81 options->log_facility = SYSLOG_FACILITY_NOT_SET;
82 options->log_level = SYSLOG_LEVEL_NOT_SET;
3c0ef626 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;
3c0ef626 88 options->kerberos_authentication = -1;
89 options->kerberos_or_local_passwd = -1;
90 options->kerberos_ticket_cleanup = -1;
88928908 91#ifdef SESSION_HOOKS
92 options->session_hooks_allow = -1;
93 options->session_hooks_startup_cmd = NULL;
94 options->session_hooks_shutdown_cmd = NULL;
3c0ef626 95#endif
416fd2a8 96 options->kerberos_get_afs_token = -1;
70791e56 97 options->gss_authentication=-1;
34fee935 98 options->gss_keyex = -1;
70791e56 99 options->gss_cleanup_creds = -1;
2e437378 100 options->gss_strict_acceptor = -1;
9374f80e 101 options->gsi_allow_limited_proxy = -1;
3c0ef626 102 options->password_authentication = -1;
103 options->kbd_interactive_authentication = -1;
104 options->challenge_response_authentication = -1;
105 options->permit_empty_passwd = -1;
e54b3d7c 106 options->permit_user_env = -1;
3c0ef626 107 options->use_login = -1;
ff2d7a98 108 options->compression = -1;
3c0ef626 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;
1b56ff3d 122 options->max_authtries = -1;
3c0ef626 123 options->banner = NULL;
70791e56 124 options->use_dns = -1;
3c0ef626 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;
1b56ff3d 129 options->num_accept_env = 0;
e00da40d 130 options->permit_tun = -1;
2e437378 131 options->num_permitted_opens = -1;
132 options->adm_forced_command = NULL;
e00da40d 133 options->none_enabled = -1;
134 options->tcp_rcv_buf_poll = -1;
2e437378 135 options->hpn_disabled = -1;
136 options->hpn_buffer_size = -1;
3c0ef626 137}
138
139void
140fill_default_server_options(ServerOptions *options)
141{
2e437378 142 int sock;
143 int socksize;
144 int socksizelen = sizeof(int);
e00da40d 145
3c0ef626 146 /* Portable-specific options */
70791e56 147 if (options->use_pam == -1)
148 options->use_pam = 0;
3c0ef626 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)
e9a17296 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 }
3c0ef626 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)
e54b3d7c 174 options->login_grace_time = 120;
3c0ef626 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;
e9a17296 191 if (options->x11_use_localhost == -1)
192 options->x11_use_localhost = 1;
3c0ef626 193 if (options->xauth_location == NULL)
194 options->xauth_location = _PATH_XAUTH;
3c0ef626 195 if (options->strict_modes == -1)
196 options->strict_modes = 1;
416fd2a8 197 if (options->tcp_keep_alive == -1)
198 options->tcp_keep_alive = 1;
e9a17296 199 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
3c0ef626 200 options->log_facility = SYSLOG_FACILITY_AUTH;
e9a17296 201 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
3c0ef626 202 options->log_level = SYSLOG_LEVEL_INFO;
3c0ef626 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;
70791e56 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;
416fd2a8 219 if (options->kerberos_get_afs_token == -1)
220 options->kerberos_get_afs_token = 0;
b9a54c29 221 if (options->gss_authentication == -1)
222 options->gss_authentication = 1;
223 if (options->gss_keyex == -1)
70791e56 224 options->gss_keyex = 1;
b9a54c29 225 if (options->gss_cleanup_creds == -1)
226 options->gss_cleanup_creds = 1;
2e437378 227 if (options->gss_strict_acceptor == -1)
228 options->gss_strict_acceptor = 1;
9374f80e 229 if (options->gsi_allow_limited_proxy == -1)
230 options->gsi_allow_limited_proxy = 0;
3c0ef626 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;
e54b3d7c 239 if (options->permit_user_env == -1)
240 options->permit_user_env = 0;
3c0ef626 241 if (options->use_login == -1)
242 options->use_login = 0;
ff2d7a98 243 if (options->compression == -1)
34fee935 244 options->compression = COMP_DELAYED;
3c0ef626 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;
1b56ff3d 255 if (options->max_authtries == -1)
256 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
70791e56 257 if (options->use_dns == -1)
258 options->use_dns = 1;
3c0ef626 259 if (options->client_alive_interval == -1)
e9a17296 260 options->client_alive_interval = 0;
3c0ef626 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;
e00da40d 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
2e437378 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;
e00da40d 315 }
2980ea68 316
ff2d7a98 317 /* Turn privilege separation on by default */
2980ea68 318 if (use_privsep == -1)
ff2d7a98 319 use_privsep = 1;
320
e54b3d7c 321#ifndef HAVE_MMAP
ff2d7a98 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
3c0ef626 330}
331
332/* Keyword tokens. */
333typedef enum {
334 sBadOption, /* == unknown option */
335 /* Portable-specific options */
70791e56 336 sUsePAM,
3c0ef626 337 /* Standard Options */
338 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
339 sPermitRootLogin, sLogFacility, sLogLevel,
70791e56 340 sRhostsRSAAuthentication, sRSAAuthentication,
3c0ef626 341 sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
416fd2a8 342 sKerberosGetAFSToken,
70791e56 343 sKerberosTgtPassing, sChallengeResponseAuthentication,
88928908 344#ifdef SESSION_HOOKS
345 sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
3c0ef626 346#endif
34fee935 347 sPasswordAuthentication, sKbdInteractiveAuthentication,
348 sListenAddress, sAddressFamily,
3c0ef626 349 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
e9a17296 350 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
416fd2a8 351 sStrictModes, sEmptyPasswd, sTCPKeepAlive,
e54b3d7c 352 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
3c0ef626 353 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
354 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
1b56ff3d 355 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
356 sMaxStartups, sMaxAuthTries,
70791e56 357 sBanner, sUseDNS, sHostbasedAuthentication,
e9a17296 358 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
3c0ef626 359 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
2e437378 360 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
e00da40d 361 sGssKeyEx,
2e437378 362 sGssCredsPath,
9374f80e 363 sGsiAllowLimitedProxy,
2e437378 364 sAcceptEnv, sPermitTunnel,
365 sMatch, sPermitOpen, sForceCommand,
e00da40d 366 sUsePrivilegeSeparation, sNoneEnabled, sTcpRcvBufPoll,
2e437378 367 sHPNDisabled, sHPNBufferSize,
70791e56 368 sDeprecated, sUnsupported
3c0ef626 369} ServerOpCodes;
370
2e437378 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
3c0ef626 375/* Textual representation of the tokens. */
376static struct {
377 const char *name;
378 ServerOpCodes opcode;
2e437378 379 u_int flags;
3c0ef626 380} keywords[] = {
381 /* Portable-specific options */
70791e56 382#ifdef USE_PAM
2e437378 383 { "usepam", sUsePAM, SSHCFG_GLOBAL },
70791e56 384#else
2e437378 385 { "usepam", sUnsupported, SSHCFG_GLOBAL },
70791e56 386#endif
2e437378 387 { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
3c0ef626 388 /* Standard Options */
2e437378 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 },
2278ffa1 400 { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
401 { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
2e437378 402 { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
2278ffa1 403 { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
404 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
2e437378 405 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
70791e56 406#ifdef KRB5
2278ffa1 407 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
2e437378 408 { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
409 { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
416fd2a8 410#ifdef USE_AFS
2e437378 411 { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
416fd2a8 412#else
2e437378 413 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
416fd2a8 414#endif
70791e56 415#else
2278ffa1 416 { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
2e437378 417 { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
418 { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
419 { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
70791e56 420#endif
2e437378 421 { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
422 { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
b9a54c29 423#ifdef GSSAPI
2278ffa1 424 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
2e437378 425 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
426 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
427 { "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL },
428 { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
9374f80e 429#ifdef GSI
2e437378 430 { "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL },
9374f80e 431#endif
70791e56 432#else
2278ffa1 433 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
2e437378 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
3c0ef626 441#endif
88928908 442#ifdef SESSION_HOOKS
2e437378 443 { "allowsessionhooks", sAllowSessionHooks, SSHCFG_GLOBAL },
444 { "sessionhookstartupcmd", sSessionHookStartupCmd, SSHCFG_GLOBAL },
445 { "sessionhookshutdowncmd", sSessionHookShutdownCmd, SSHCFG_GLOBAL },
88928908 446#endif
2278ffa1 447 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
448 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
2e437378 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 },
2278ffa1 481 { "banner", sBanner, SSHCFG_ALL },
2e437378 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 }
3c0ef626 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,
2e437378 508 int linenum, u_int *flags)
3c0ef626 509{
510 u_int i;
511
512 for (i = 0; keywords[i].name; i++)
2e437378 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
3c0ef626 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{
34fee935 527 u_int i;
3c0ef626 528
529 if (options->num_ports == 0)
530 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
34fee935 531 if (options->address_family == -1)
532 options->address_family = AF_UNSPEC;
3c0ef626 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));
34fee935 548 hints.ai_family = options->address_family;
3c0ef626 549 hints.ai_socktype = SOCK_STREAM;
550 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
ff2d7a98 551 snprintf(strport, sizeof strport, "%u", port);
3c0ef626 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
2e437378 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) {
2e437378 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
e9a17296 711int
712process_server_config_line(ServerOptions *options, char *line,
2e437378 713 const char *filename, int linenum, int *activep, const char *user,
714 const char *host, const char *address)
3c0ef626 715{
3c0ef626 716 char *cp, **charptr, *arg, *p;
2e437378 717 int cmdline = 0, *intptr, value, n;
3c0ef626 718 ServerOpCodes opcode;
34fee935 719 u_short port;
2e437378 720 u_int i, flags = 0;
721 size_t len;
3c0ef626 722
e9a17296 723 cp = line;
2e437378 724 if ((arg = strdelim(&cp)) == NULL)
725 return 0;
e9a17296 726 /* Ignore leading whitespace */
727 if (*arg == '\0')
3c0ef626 728 arg = strdelim(&cp);
e9a17296 729 if (!arg || !*arg || *arg == '#')
730 return 0;
731 intptr = NULL;
732 charptr = NULL;
2e437378 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 }
e00da40d 751
e9a17296 752 switch (opcode) {
753 /* Portable-specific options */
70791e56 754 case sUsePAM:
755 intptr = &options->use_pam;
e9a17296 756 goto parse_flag;
3c0ef626 757
e9a17296 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;
3c0ef626 783parse_int:
e9a17296 784 arg = strdelim(&cp);
785 if (!arg || *arg == '\0')
786 fatal("%s line %d: missing integer value.",
787 filename, linenum);
788 value = atoi(arg);
2e437378 789 if (*activep && *intptr == -1)
e9a17296 790 *intptr = value;
791 break;
792
793 case sLoginGraceTime:
794 intptr = &options->login_grace_time;
3c0ef626 795parse_time:
e9a17296 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);
34fee935 813 if (arg == NULL || *arg == '\0')
814 fatal("%s line %d: missing address",
e9a17296 815 filename, linenum);
34fee935 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) {
e9a17296 819 add_listen_addr(options, arg, 0);
3c0ef626 820 break;
e9a17296 821 }
34fee935 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);
3c0ef626 831
34fee935 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.",
e9a17296 840 filename, linenum);
34fee935 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;
e9a17296 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];
3c0ef626 864parse_filename:
e9a17296 865 arg = strdelim(&cp);
866 if (!arg || *arg == '\0')
867 fatal("%s line %d: missing file name.",
868 filename, linenum);
2e437378 869 if (*activep && *charptr == NULL) {
e9a17296 870 *charptr = tilde_expand_filename(arg, getuid());
871 /* increase optional counter */
872 if (intptr != NULL)
873 *intptr = *intptr + 1;
874 }
875 break;
3c0ef626 876
e9a17296 877 case sPidFile:
878 charptr = &options->pid_file;
879 goto parse_filename;
3c0ef626 880
e9a17296 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;
3c0ef626 907parse_flag:
e9a17296 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);
2e437378 920 if (*activep && *intptr == -1)
e9a17296 921 *intptr = value;
922 break;
923
e00da40d 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
e9a17296 940 case sIgnoreUserKnownHosts:
941 intptr = &options->ignore_user_known_hosts;
942 goto parse_flag;
943
e9a17296 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;
70791e56 963
e9a17296 964 case sKerberosAuthentication:
965 intptr = &options->kerberos_authentication;
966 goto parse_flag;
3c0ef626 967
e9a17296 968 case sKerberosOrLocalPasswd:
969 intptr = &options->kerberos_or_local_passwd;
970 goto parse_flag;
3c0ef626 971
e9a17296 972 case sKerberosTicketCleanup:
973 intptr = &options->kerberos_ticket_cleanup;
974 goto parse_flag;
70791e56 975
416fd2a8 976 case sKerberosGetAFSToken:
977 intptr = &options->kerberos_get_afs_token;
978 goto parse_flag;
979
70791e56 980 case sGssAuthentication:
981 intptr = &options->gss_authentication;
e9a17296 982 goto parse_flag;
70791e56 983
984 case sGssKeyEx:
985 intptr = &options->gss_keyex;
e9a17296 986 goto parse_flag;
70791e56 987
70791e56 988 case sGssCleanupCreds:
989 intptr = &options->gss_cleanup_creds;
990 goto parse_flag;
991
2e437378 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
9374f80e 1000 case sGsiAllowLimitedProxy:
1001 intptr = &options->gsi_allow_limited_proxy;
1002 goto parse_flag;
1003
88928908 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
70791e56 1020
e9a17296 1021 case sPasswordAuthentication:
1022 intptr = &options->password_authentication;
1023 goto parse_flag;
3c0ef626 1024
e9a17296 1025 case sKbdInteractiveAuthentication:
1026 intptr = &options->kbd_interactive_authentication;
1027 goto parse_flag;
3c0ef626 1028
e9a17296 1029 case sChallengeResponseAuthentication:
1030 intptr = &options->challenge_response_authentication;
1031 goto parse_flag;
3c0ef626 1032
e9a17296 1033 case sPrintMotd:
1034 intptr = &options->print_motd;
1035 goto parse_flag;
3c0ef626 1036
e9a17296 1037 case sPrintLastLog:
1038 intptr = &options->print_lastlog;
1039 goto parse_flag;
3c0ef626 1040
e9a17296 1041 case sX11Forwarding:
1042 intptr = &options->x11_forwarding;
1043 goto parse_flag;
3c0ef626 1044
e9a17296 1045 case sX11DisplayOffset:
1046 intptr = &options->x11_display_offset;
1047 goto parse_int;
3c0ef626 1048
e9a17296 1049 case sX11UseLocalhost:
1050 intptr = &options->x11_use_localhost;
1051 goto parse_flag;
3c0ef626 1052
e9a17296 1053 case sXAuthLocation:
1054 charptr = &options->xauth_location;
1055 goto parse_filename;
3c0ef626 1056
e9a17296 1057 case sStrictModes:
1058 intptr = &options->strict_modes;
1059 goto parse_flag;
3c0ef626 1060
416fd2a8 1061 case sTCPKeepAlive:
1062 intptr = &options->tcp_keep_alive;
e9a17296 1063 goto parse_flag;
3c0ef626 1064
e9a17296 1065 case sEmptyPasswd:
1066 intptr = &options->permit_empty_passwd;
1067 goto parse_flag;
3c0ef626 1068
e54b3d7c 1069 case sPermitUserEnvironment:
1070 intptr = &options->permit_user_env;
1071 goto parse_flag;
1072
e9a17296 1073 case sUseLogin:
1074 intptr = &options->use_login;
1075 goto parse_flag;
3c0ef626 1076
ff2d7a98 1077 case sCompression:
1078 intptr = &options->compression;
34fee935 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;
ff2d7a98 1096
e9a17296 1097 case sGatewayPorts:
1098 intptr = &options->gateway_ports;
34fee935 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);
2278ffa1 1113 if (*activep && *intptr == -1)
34fee935 1114 *intptr = value;
1115 break;
3c0ef626 1116
70791e56 1117 case sUseDNS:
1118 intptr = &options->use_dns;
e9a17296 1119 goto parse_flag;
3c0ef626 1120
e9a17296 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
2980ea68 1147 case sUsePrivilegeSeparation:
1148 intptr = &use_privsep;
1149 goto parse_flag;
1150
e9a17296 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);
ff2d7a98 1156 options->allow_users[options->num_allow_users++] =
1157 xstrdup(arg);
e9a17296 1158 }
1159 break;
3c0ef626 1160
e9a17296 1161 case sDenyUsers:
1162 while ((arg = strdelim(&cp)) && *arg != '\0') {
1163 if (options->num_deny_users >= MAX_DENY_USERS)
2e437378 1164 fatal("%s line %d: too many deny users.",
e9a17296 1165 filename, linenum);
ff2d7a98 1166 options->deny_users[options->num_deny_users++] =
1167 xstrdup(arg);
e9a17296 1168 }
1169 break;
3c0ef626 1170
e9a17296 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);
ff2d7a98 1176 options->allow_groups[options->num_allow_groups++] =
1177 xstrdup(arg);
e9a17296 1178 }
1179 break;
3c0ef626 1180
e9a17296 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);
2e437378 1234 if (!*activep) {
1235 arg = strdelim(&cp);
1236 break;
1237 }
e9a17296 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);
2e437378 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;
e9a17296 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)
3c0ef626 1275 fatal("%s line %d: Illegal MaxStartups spec.",
1276 filename, linenum);
e9a17296 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
1b56ff3d 1284 case sMaxAuthTries:
1285 intptr = &options->max_authtries;
1286 goto parse_int;
1287
e9a17296 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:
2e437378 1299 charptr = (opcode == sAuthorizedKeysFile) ?
e9a17296 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
1b56ff3d 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);
2e437378 1320 if (!*activep)
1321 break;
1b56ff3d 1322 options->accept_env[options->num_accept_env++] =
1323 xstrdup(arg);
1324 }
1325 break;
1326
e00da40d 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
2e437378 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);
2278ffa1 1365 n = options->num_permitted_opens; /* modified later */
2e437378 1366 if (strcmp(arg, "any") == 0) {
2278ffa1 1367 if (*activep && n == -1) {
2e437378 1368 channel_clear_adm_permitted_opens();
1369 options->num_permitted_opens = 0;
1370 }
1371 break;
1372 }
2278ffa1 1373 if (*activep && n == -1)
1374 channel_clear_adm_permitted_opens();
2e437378 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);
2278ffa1 1384 if (*activep && n == -1)
2e437378 1385 options->num_permitted_opens =
1386 channel_add_adm_permitted_opens(p, port);
2e437378 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
e9a17296 1399 case sDeprecated:
70791e56 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",
e9a17296 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}
3c0ef626 1422
e9a17296 1423/* Reads the server configuration file. */
3c0ef626 1424
e9a17296 1425void
1b56ff3d 1426load_server_config(const char *filename, Buffer *conf)
e9a17296 1427{
1b56ff3d 1428 char line[1024], *cp;
ff2d7a98 1429 FILE *f;
e9a17296 1430
1b56ff3d 1431 debug2("%s: filename %s", __func__, filename);
1432 if ((f = fopen(filename, "r")) == NULL) {
e9a17296 1433 perror(filename);
1434 exit(1);
1435 }
1b56ff3d 1436 buffer_clear(conf);
e9a17296 1437 while (fgets(line, sizeof(line), f)) {
1b56ff3d 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));
3c0ef626 1448 }
1b56ff3d 1449 buffer_append(conf, "\0", 1);
3c0ef626 1450 fclose(f);
1b56ff3d 1451 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1452}
1453
1454void
2e437378 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);
2278ffa1 1462 copy_set_server_options(options, &mo, 0);
2e437378 1463}
1464
2278ffa1 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 */
2e437378 1485void
2278ffa1 1486copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
2e437378 1487{
2278ffa1 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);
2e437378 1506}
1507
2278ffa1 1508#undef M_CP_INTOPT
1509#undef M_CP_STROPT
1510
2e437378 1511void
1512parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1513 const char *user, const char *host, const char *address)
1b56ff3d 1514{
2e437378 1515 int active, linenum, bad_options = 0;
1b56ff3d 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));
2e437378 1521 active = user ? 0 : 1;
1b56ff3d 1522 linenum = 1;
34fee935 1523 while ((cp = strsep(&cbuf, "\n")) != NULL) {
1b56ff3d 1524 if (process_server_config_line(options, cp, filename,
2e437378 1525 linenum++, &active, user, host, address) != 0)
1b56ff3d 1526 bad_options++;
1527 }
1528 xfree(obuf);
3c0ef626 1529 if (bad_options > 0)
1530 fatal("%s: terminating, %d bad configuration options",
1531 filename, bad_options);
1532}
This page took 0.333975 seconds and 5 git commands to generate.