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