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