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