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