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