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