]> andersk Git - openssh.git/blame - servconf.c
- dtucker@cvs.openbsd.org 2008/06/10 04:50:25
[openssh.git] / servconf.c
CommitLineData
1760c982 1/* $OpenBSD: servconf.c,v 1.182 2008/06/10 04:50:25 dtucker 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)
161 options->server_key_bits = 768;
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 },
401 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
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;
528 u_int ngrps = 0;
529 char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
530 struct passwd *pw;
531
532 /*
533 * Even if we do not have a user yet, we still need to check for
534 * valid syntax.
535 */
536 arg = cp = xstrdup(grps);
537 while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
538 if (ngrps >= MAX_MATCH_GROUPS) {
539 error("line %d: too many groups in Match Group", line);
540 result = -1;
541 goto out;
542 }
543 grplist[ngrps++] = p;
544 }
545
546 if (user == NULL)
547 goto out;
548
549 if ((pw = getpwnam(user)) == NULL) {
550 debug("Can't match group at line %d because user %.100s does "
551 "not exist", line, user);
552 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
553 debug("Can't Match group because user %.100s not in any group "
554 "at line %d", user, line);
555 } else if (ga_match(grplist, ngrps) != 1) {
556 debug("user %.100s does not match group %.100s at line %d",
557 user, arg, line);
558 } else {
559 debug("user %.100s matched group %.100s at line %d", user,
560 arg, line);
561 result = 1;
562 }
563out:
564 ga_free();
565 xfree(arg);
566 return result;
567}
568
d231781a 569static int
570match_cfg_line(char **condition, int line, const char *user, const char *host,
571 const char *address)
572{
573 int result = 1;
574 char *arg, *attrib, *cp = *condition;
575 size_t len;
576
577 if (user == NULL)
578 debug3("checking syntax for 'Match %s'", cp);
579 else
580 debug3("checking match for '%s' user %s host %s addr %s", cp,
581 user ? user : "(null)", host ? host : "(null)",
582 address ? address : "(null)");
583
584 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
585 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
586 error("Missing Match criteria for %s", attrib);
587 return -1;
588 }
589 len = strlen(arg);
590 if (strcasecmp(attrib, "user") == 0) {
591 if (!user) {
592 result = 0;
593 continue;
594 }
595 if (match_pattern_list(user, arg, len, 0) != 1)
596 result = 0;
597 else
598 debug("user %.100s matched 'User %.100s' at "
599 "line %d", user, arg, line);
fa47fe3c 600 } else if (strcasecmp(attrib, "group") == 0) {
601 switch (match_cfg_line_group(arg, line, user)) {
602 case -1:
603 return -1;
604 case 0:
605 result = 0;
606 }
d231781a 607 } else if (strcasecmp(attrib, "host") == 0) {
608 if (!host) {
609 result = 0;
610 continue;
611 }
612 if (match_hostname(host, arg, len) != 1)
613 result = 0;
614 else
615 debug("connection from %.100s matched 'Host "
616 "%.100s' at line %d", host, arg, line);
617 } else if (strcasecmp(attrib, "address") == 0) {
15b5fa9b 618 switch (addr_match_list(address, arg)) {
619 case 1:
d231781a 620 debug("connection from %.100s matched 'Address "
621 "%.100s' at line %d", address, arg, line);
15b5fa9b 622 break;
623 case 0:
624 result = 0;
625 break;
626 case -1:
627 return -1;
628 }
d231781a 629 } else {
630 error("Unsupported Match attribute %s", attrib);
631 return -1;
632 }
633 }
634 if (user != NULL)
635 debug3("match %sfound", result ? "" : "not ");
636 *condition = cp;
637 return result;
638}
639
e7259e8d 640#define WHITESPACE " \t\r\n"
641
2717fa0f 642int
643process_server_config_line(ServerOptions *options, char *line,
d231781a 644 const char *filename, int linenum, int *activep, const char *user,
645 const char *host, const char *address)
8efc0c15 646{
d11c1288 647 char *cp, **charptr, *arg, *p;
d231781a 648 int cmdline = 0, *intptr, value, n;
2a72bc03 649 SyslogFacility *log_facility_ptr;
650 LogLevel *log_level_ptr;
5260325f 651 ServerOpCodes opcode;
3867aa0a 652 u_short port;
d231781a 653 u_int i, flags = 0;
d66ce1a1 654 size_t len;
5260325f 655
2717fa0f 656 cp = line;
0f8cd5a6 657 if ((arg = strdelim(&cp)) == NULL)
88299971 658 return 0;
2717fa0f 659 /* Ignore leading whitespace */
660 if (*arg == '\0')
704b1659 661 arg = strdelim(&cp);
2717fa0f 662 if (!arg || !*arg || *arg == '#')
663 return 0;
664 intptr = NULL;
665 charptr = NULL;
d231781a 666 opcode = parse_token(arg, filename, linenum, &flags);
667
668 if (activep == NULL) { /* We are processing a command line directive */
669 cmdline = 1;
670 activep = &cmdline;
671 }
672 if (*activep && opcode != sMatch)
673 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
674 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
675 if (user == NULL) {
676 fatal("%s line %d: Directive '%s' is not allowed "
677 "within a Match block", filename, linenum, arg);
678 } else { /* this is a directive we have already processed */
679 while (arg)
680 arg = strdelim(&cp);
681 return 0;
682 }
683 }
684
2717fa0f 685 switch (opcode) {
686 /* Portable-specific options */
7fceb20d 687 case sUsePAM:
688 intptr = &options->use_pam;
2717fa0f 689 goto parse_flag;
48e671d5 690
2717fa0f 691 /* Standard Options */
692 case sBadOption:
693 return -1;
694 case sPort:
695 /* ignore ports from configfile if cmdline specifies ports */
696 if (options->ports_from_cmdline)
697 return 0;
698 if (options->listen_addrs != NULL)
699 fatal("%s line %d: ports must be specified before "
3a454b6a 700 "ListenAddress.", filename, linenum);
2717fa0f 701 if (options->num_ports >= MAX_PORTS)
702 fatal("%s line %d: too many ports.",
703 filename, linenum);
704 arg = strdelim(&cp);
705 if (!arg || *arg == '\0')
706 fatal("%s line %d: missing port number.",
707 filename, linenum);
708 options->ports[options->num_ports++] = a2port(arg);
709 if (options->ports[options->num_ports-1] == 0)
710 fatal("%s line %d: Badly formatted port number.",
711 filename, linenum);
712 break;
713
714 case sServerKeyBits:
715 intptr = &options->server_key_bits;
c6dca55e 716 parse_int:
2717fa0f 717 arg = strdelim(&cp);
718 if (!arg || *arg == '\0')
719 fatal("%s line %d: missing integer value.",
720 filename, linenum);
721 value = atoi(arg);
d231781a 722 if (*activep && *intptr == -1)
2717fa0f 723 *intptr = value;
724 break;
725
726 case sLoginGraceTime:
727 intptr = &options->login_grace_time;
c6dca55e 728 parse_time:
2717fa0f 729 arg = strdelim(&cp);
730 if (!arg || *arg == '\0')
731 fatal("%s line %d: missing time value.",
732 filename, linenum);
733 if ((value = convtime(arg)) == -1)
734 fatal("%s line %d: invalid time value.",
735 filename, linenum);
736 if (*intptr == -1)
737 *intptr = value;
738 break;
739
740 case sKeyRegenerationTime:
741 intptr = &options->key_regeneration_time;
742 goto parse_time;
743
744 case sListenAddress:
745 arg = strdelim(&cp);
3867aa0a 746 if (arg == NULL || *arg == '\0')
747 fatal("%s line %d: missing address",
2717fa0f 748 filename, linenum);
91135a0e 749 /* check for bare IPv6 address: no "[]" and 2 or more ":" */
750 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
751 && strchr(p+1, ':') != NULL) {
752 add_listen_addr(options, arg, 0);
753 break;
754 }
3867aa0a 755 p = hpdelim(&arg);
756 if (p == NULL)
757 fatal("%s line %d: bad address:port usage",
2717fa0f 758 filename, linenum);
3867aa0a 759 p = cleanhostname(p);
760 if (arg == NULL)
761 port = 0;
762 else if ((port = a2port(arg)) == 0)
763 fatal("%s line %d: bad port number", filename, linenum);
764
765 add_listen_addr(options, p, port);
766
2717fa0f 767 break;
768
31b41ceb 769 case sAddressFamily:
770 arg = strdelim(&cp);
38634ff6 771 if (!arg || *arg == '\0')
772 fatal("%s line %d: missing address family.",
773 filename, linenum);
31b41ceb 774 intptr = &options->address_family;
775 if (options->listen_addrs != NULL)
776 fatal("%s line %d: address family must be specified before "
777 "ListenAddress.", filename, linenum);
778 if (strcasecmp(arg, "inet") == 0)
779 value = AF_INET;
780 else if (strcasecmp(arg, "inet6") == 0)
781 value = AF_INET6;
782 else if (strcasecmp(arg, "any") == 0)
783 value = AF_UNSPEC;
784 else
785 fatal("%s line %d: unsupported address family \"%s\".",
786 filename, linenum, arg);
787 if (*intptr == -1)
788 *intptr = value;
789 break;
790
2717fa0f 791 case sHostKeyFile:
792 intptr = &options->num_host_key_files;
793 if (*intptr >= MAX_HOSTKEYS)
794 fatal("%s line %d: too many host keys specified (max %d).",
795 filename, linenum, MAX_HOSTKEYS);
796 charptr = &options->host_key_files[*intptr];
c6dca55e 797 parse_filename:
2717fa0f 798 arg = strdelim(&cp);
799 if (!arg || *arg == '\0')
800 fatal("%s line %d: missing file name.",
801 filename, linenum);
d231781a 802 if (*activep && *charptr == NULL) {
2717fa0f 803 *charptr = tilde_expand_filename(arg, getuid());
804 /* increase optional counter */
805 if (intptr != NULL)
806 *intptr = *intptr + 1;
807 }
808 break;
0fbe8c74 809
2717fa0f 810 case sPidFile:
811 charptr = &options->pid_file;
812 goto parse_filename;
5260325f 813
2717fa0f 814 case sPermitRootLogin:
815 intptr = &options->permit_root_login;
816 arg = strdelim(&cp);
817 if (!arg || *arg == '\0')
818 fatal("%s line %d: missing yes/"
819 "without-password/forced-commands-only/no "
820 "argument.", filename, linenum);
821 value = 0; /* silence compiler */
822 if (strcmp(arg, "without-password") == 0)
823 value = PERMIT_NO_PASSWD;
824 else if (strcmp(arg, "forced-commands-only") == 0)
825 value = PERMIT_FORCED_ONLY;
826 else if (strcmp(arg, "yes") == 0)
827 value = PERMIT_YES;
828 else if (strcmp(arg, "no") == 0)
829 value = PERMIT_NO;
830 else
831 fatal("%s line %d: Bad yes/"
832 "without-password/forced-commands-only/no "
833 "argument: %s", filename, linenum, arg);
2ef741a3 834 if (*activep && *intptr == -1)
2717fa0f 835 *intptr = value;
836 break;
837
838 case sIgnoreRhosts:
839 intptr = &options->ignore_rhosts;
c6dca55e 840 parse_flag:
2717fa0f 841 arg = strdelim(&cp);
842 if (!arg || *arg == '\0')
843 fatal("%s line %d: missing yes/no argument.",
844 filename, linenum);
845 value = 0; /* silence compiler */
846 if (strcmp(arg, "yes") == 0)
847 value = 1;
848 else if (strcmp(arg, "no") == 0)
849 value = 0;
850 else
851 fatal("%s line %d: Bad yes/no argument: %s",
852 filename, linenum, arg);
d231781a 853 if (*activep && *intptr == -1)
2717fa0f 854 *intptr = value;
855 break;
856
857 case sIgnoreUserKnownHosts:
858 intptr = &options->ignore_user_known_hosts;
859 goto parse_flag;
860
2717fa0f 861 case sRhostsRSAAuthentication:
862 intptr = &options->rhosts_rsa_authentication;
863 goto parse_flag;
864
865 case sHostbasedAuthentication:
866 intptr = &options->hostbased_authentication;
867 goto parse_flag;
868
869 case sHostbasedUsesNameFromPacketOnly:
870 intptr = &options->hostbased_uses_name_from_packet_only;
871 goto parse_flag;
872
873 case sRSAAuthentication:
874 intptr = &options->rsa_authentication;
875 goto parse_flag;
876
877 case sPubkeyAuthentication:
878 intptr = &options->pubkey_authentication;
879 goto parse_flag;
d0ec7f42 880
2717fa0f 881 case sKerberosAuthentication:
882 intptr = &options->kerberos_authentication;
883 goto parse_flag;
5260325f 884
2717fa0f 885 case sKerberosOrLocalPasswd:
886 intptr = &options->kerberos_or_local_passwd;
887 goto parse_flag;
5260325f 888
2717fa0f 889 case sKerberosTicketCleanup:
890 intptr = &options->kerberos_ticket_cleanup;
891 goto parse_flag;
d0ec7f42 892
a1e30b47 893 case sKerberosGetAFSToken:
894 intptr = &options->kerberos_get_afs_token;
895 goto parse_flag;
896
7364bd04 897 case sGssAuthentication:
898 intptr = &options->gss_authentication;
899 goto parse_flag;
900
901 case sGssCleanupCreds:
902 intptr = &options->gss_cleanup_creds;
903 goto parse_flag;
904
2717fa0f 905 case sPasswordAuthentication:
906 intptr = &options->password_authentication;
907 goto parse_flag;
5260325f 908
2717fa0f 909 case sKbdInteractiveAuthentication:
910 intptr = &options->kbd_interactive_authentication;
911 goto parse_flag;
8002af61 912
2717fa0f 913 case sChallengeResponseAuthentication:
914 intptr = &options->challenge_response_authentication;
915 goto parse_flag;
8002af61 916
2717fa0f 917 case sPrintMotd:
918 intptr = &options->print_motd;
919 goto parse_flag;
5260325f 920
2717fa0f 921 case sPrintLastLog:
922 intptr = &options->print_lastlog;
923 goto parse_flag;
5260325f 924
2717fa0f 925 case sX11Forwarding:
926 intptr = &options->x11_forwarding;
927 goto parse_flag;
5260325f 928
2717fa0f 929 case sX11DisplayOffset:
930 intptr = &options->x11_display_offset;
931 goto parse_int;
8efc0c15 932
e6e573bd 933 case sX11UseLocalhost:
934 intptr = &options->x11_use_localhost;
935 goto parse_flag;
936
2717fa0f 937 case sXAuthLocation:
938 charptr = &options->xauth_location;
939 goto parse_filename;
5260325f 940
2717fa0f 941 case sStrictModes:
942 intptr = &options->strict_modes;
943 goto parse_flag;
5260325f 944
fd573618 945 case sTCPKeepAlive:
946 intptr = &options->tcp_keep_alive;
2717fa0f 947 goto parse_flag;
33de75a3 948
2717fa0f 949 case sEmptyPasswd:
950 intptr = &options->permit_empty_passwd;
951 goto parse_flag;
5260325f 952
f00bab84 953 case sPermitUserEnvironment:
954 intptr = &options->permit_user_env;
955 goto parse_flag;
956
2717fa0f 957 case sUseLogin:
958 intptr = &options->use_login;
959 goto parse_flag;
5260325f 960
636f76ca 961 case sCompression:
962 intptr = &options->compression;
07200973 963 arg = strdelim(&cp);
964 if (!arg || *arg == '\0')
965 fatal("%s line %d: missing yes/no/delayed "
966 "argument.", filename, linenum);
967 value = 0; /* silence compiler */
968 if (strcmp(arg, "delayed") == 0)
969 value = COMP_DELAYED;
970 else if (strcmp(arg, "yes") == 0)
971 value = COMP_ZLIB;
972 else if (strcmp(arg, "no") == 0)
973 value = COMP_NONE;
974 else
975 fatal("%s line %d: Bad yes/no/delayed "
976 "argument: %s", filename, linenum, arg);
977 if (*intptr == -1)
978 *intptr = value;
979 break;
636f76ca 980
2717fa0f 981 case sGatewayPorts:
982 intptr = &options->gateway_ports;
3867aa0a 983 arg = strdelim(&cp);
984 if (!arg || *arg == '\0')
985 fatal("%s line %d: missing yes/no/clientspecified "
986 "argument.", filename, linenum);
987 value = 0; /* silence compiler */
988 if (strcmp(arg, "clientspecified") == 0)
989 value = 2;
990 else if (strcmp(arg, "yes") == 0)
991 value = 1;
992 else if (strcmp(arg, "no") == 0)
993 value = 0;
994 else
995 fatal("%s line %d: Bad yes/no/clientspecified "
996 "argument: %s", filename, linenum, arg);
f3e3d6ce 997 if (*activep && *intptr == -1)
3867aa0a 998 *intptr = value;
999 break;
5260325f 1000
c5a7d788 1001 case sUseDNS:
1002 intptr = &options->use_dns;
2717fa0f 1003 goto parse_flag;
5260325f 1004
2717fa0f 1005 case sLogFacility:
2a72bc03 1006 log_facility_ptr = &options->log_facility;
2717fa0f 1007 arg = strdelim(&cp);
1008 value = log_facility_number(arg);
5eaf8578 1009 if (value == SYSLOG_FACILITY_NOT_SET)
2717fa0f 1010 fatal("%.200s line %d: unsupported log facility '%s'",
1011 filename, linenum, arg ? arg : "<NONE>");
2a72bc03 1012 if (*log_facility_ptr == -1)
1013 *log_facility_ptr = (SyslogFacility) value;
2717fa0f 1014 break;
1015
1016 case sLogLevel:
2a72bc03 1017 log_level_ptr = &options->log_level;
2717fa0f 1018 arg = strdelim(&cp);
1019 value = log_level_number(arg);
5eaf8578 1020 if (value == SYSLOG_LEVEL_NOT_SET)
2717fa0f 1021 fatal("%.200s line %d: unsupported log level '%s'",
1022 filename, linenum, arg ? arg : "<NONE>");
2a72bc03 1023 if (*log_level_ptr == -1)
1024 *log_level_ptr = (LogLevel) value;
2717fa0f 1025 break;
1026
1027 case sAllowTcpForwarding:
1028 intptr = &options->allow_tcp_forwarding;
1029 goto parse_flag;
1030
43c3f85c 1031 case sAllowAgentForwarding:
1032 intptr = &options->allow_agent_forwarding;
1033 goto parse_flag;
1034
1853d1ef 1035 case sUsePrivilegeSeparation:
1036 intptr = &use_privsep;
1037 goto parse_flag;
1038
2717fa0f 1039 case sAllowUsers:
1040 while ((arg = strdelim(&cp)) && *arg != '\0') {
1041 if (options->num_allow_users >= MAX_ALLOW_USERS)
1042 fatal("%s line %d: too many allow users.",
1043 filename, linenum);
7528d467 1044 options->allow_users[options->num_allow_users++] =
1045 xstrdup(arg);
2717fa0f 1046 }
1047 break;
a8be9f80 1048
2717fa0f 1049 case sDenyUsers:
1050 while ((arg = strdelim(&cp)) && *arg != '\0') {
1051 if (options->num_deny_users >= MAX_DENY_USERS)
d4f40d92 1052 fatal("%s line %d: too many deny users.",
2717fa0f 1053 filename, linenum);
7528d467 1054 options->deny_users[options->num_deny_users++] =
1055 xstrdup(arg);
2717fa0f 1056 }
1057 break;
b2552997 1058
2717fa0f 1059 case sAllowGroups:
1060 while ((arg = strdelim(&cp)) && *arg != '\0') {
1061 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1062 fatal("%s line %d: too many allow groups.",
1063 filename, linenum);
7528d467 1064 options->allow_groups[options->num_allow_groups++] =
1065 xstrdup(arg);
2717fa0f 1066 }
1067 break;
a8be9f80 1068
2717fa0f 1069 case sDenyGroups:
1070 while ((arg = strdelim(&cp)) && *arg != '\0') {
1071 if (options->num_deny_groups >= MAX_DENY_GROUPS)
1072 fatal("%s line %d: too many deny groups.",
1073 filename, linenum);
1074 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1075 }
1076 break;
38c295d6 1077
2717fa0f 1078 case sCiphers:
1079 arg = strdelim(&cp);
1080 if (!arg || *arg == '\0')
1081 fatal("%s line %d: Missing argument.", filename, linenum);
1082 if (!ciphers_valid(arg))
1083 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1084 filename, linenum, arg ? arg : "<NONE>");
1085 if (options->ciphers == NULL)
1086 options->ciphers = xstrdup(arg);
1087 break;
1088
1089 case sMacs:
1090 arg = strdelim(&cp);
1091 if (!arg || *arg == '\0')
1092 fatal("%s line %d: Missing argument.", filename, linenum);
1093 if (!mac_valid(arg))
1094 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1095 filename, linenum, arg ? arg : "<NONE>");
1096 if (options->macs == NULL)
1097 options->macs = xstrdup(arg);
1098 break;
1099
1100 case sProtocol:
1101 intptr = &options->protocol;
1102 arg = strdelim(&cp);
1103 if (!arg || *arg == '\0')
1104 fatal("%s line %d: Missing argument.", filename, linenum);
1105 value = proto_spec(arg);
1106 if (value == SSH_PROTO_UNKNOWN)
1107 fatal("%s line %d: Bad protocol spec '%s'.",
184eed6a 1108 filename, linenum, arg ? arg : "<NONE>");
2717fa0f 1109 if (*intptr == SSH_PROTO_UNKNOWN)
1110 *intptr = value;
1111 break;
1112
1113 case sSubsystem:
1114 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1115 fatal("%s line %d: too many subsystems defined.",
184eed6a 1116 filename, linenum);
2717fa0f 1117 }
1118 arg = strdelim(&cp);
1119 if (!arg || *arg == '\0')
1120 fatal("%s line %d: Missing subsystem name.",
184eed6a 1121 filename, linenum);
d231781a 1122 if (!*activep) {
1123 arg = strdelim(&cp);
1124 break;
1125 }
2717fa0f 1126 for (i = 0; i < options->num_subsystems; i++)
1127 if (strcmp(arg, options->subsystem_name[i]) == 0)
1128 fatal("%s line %d: Subsystem '%s' already defined.",
184eed6a 1129 filename, linenum, arg);
2717fa0f 1130 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1131 arg = strdelim(&cp);
1132 if (!arg || *arg == '\0')
1133 fatal("%s line %d: Missing subsystem command.",
184eed6a 1134 filename, linenum);
2717fa0f 1135 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
d66ce1a1 1136
1137 /* Collect arguments (separate to executable) */
1138 p = xstrdup(arg);
1139 len = strlen(p) + 1;
1140 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1141 len += 1 + strlen(arg);
1142 p = xrealloc(p, 1, len);
1143 strlcat(p, " ", len);
1144 strlcat(p, arg, len);
1145 }
1146 options->subsystem_args[options->num_subsystems] = p;
2717fa0f 1147 options->num_subsystems++;
1148 break;
1149
1150 case sMaxStartups:
1151 arg = strdelim(&cp);
1152 if (!arg || *arg == '\0')
1153 fatal("%s line %d: Missing MaxStartups spec.",
184eed6a 1154 filename, linenum);
2717fa0f 1155 if ((n = sscanf(arg, "%d:%d:%d",
1156 &options->max_startups_begin,
1157 &options->max_startups_rate,
1158 &options->max_startups)) == 3) {
1159 if (options->max_startups_begin >
1160 options->max_startups ||
1161 options->max_startups_rate > 100 ||
1162 options->max_startups_rate < 1)
c345cf9d 1163 fatal("%s line %d: Illegal MaxStartups spec.",
97de229c 1164 filename, linenum);
2717fa0f 1165 } else if (n != 1)
1166 fatal("%s line %d: Illegal MaxStartups spec.",
1167 filename, linenum);
1168 else
1169 options->max_startups = options->max_startups_begin;
1170 break;
1171
af4bd935 1172 case sMaxAuthTries:
1173 intptr = &options->max_authtries;
1174 goto parse_int;
1175
c6dca55e 1176 case sMaxSessions:
1177 intptr = &options->max_sessions;
1178 goto parse_int;
1179
2717fa0f 1180 case sBanner:
1181 charptr = &options->banner;
1182 goto parse_filename;
db49deeb 1183
2717fa0f 1184 /*
1185 * These options can contain %X options expanded at
1186 * connect time, so that you can specify paths like:
1187 *
1188 * AuthorizedKeysFile /etc/ssh_keys/%u
1189 */
1190 case sAuthorizedKeysFile:
1191 case sAuthorizedKeysFile2:
d4f40d92 1192 charptr = (opcode == sAuthorizedKeysFile) ?
2717fa0f 1193 &options->authorized_keys_file :
1194 &options->authorized_keys_file2;
1195 goto parse_filename;
1196
1197 case sClientAliveInterval:
1198 intptr = &options->client_alive_interval;
1199 goto parse_time;
1200
1201 case sClientAliveCountMax:
1202 intptr = &options->client_alive_count_max;
1203 goto parse_int;
1204
61a2c1da 1205 case sAcceptEnv:
1206 while ((arg = strdelim(&cp)) && *arg != '\0') {
1207 if (strchr(arg, '=') != NULL)
1208 fatal("%s line %d: Invalid environment name.",
1209 filename, linenum);
1210 if (options->num_accept_env >= MAX_ACCEPT_ENV)
1211 fatal("%s line %d: too many allow env.",
1212 filename, linenum);
d231781a 1213 if (!*activep)
1214 break;
61a2c1da 1215 options->accept_env[options->num_accept_env++] =
1216 xstrdup(arg);
1217 }
1218 break;
1219
d20f3c9e 1220 case sPermitTunnel:
1221 intptr = &options->permit_tun;
a4f24bf8 1222 arg = strdelim(&cp);
1223 if (!arg || *arg == '\0')
1224 fatal("%s line %d: Missing yes/point-to-point/"
1225 "ethernet/no argument.", filename, linenum);
1760c982 1226 value = -1;
1227 for (i = 0; tunmode_desc[i].val != -1; i++)
1228 if (strcmp(tunmode_desc[i].text, arg) == 0) {
1229 value = tunmode_desc[i].val;
1230 break;
1231 }
1232 if (value == -1)
a4f24bf8 1233 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1234 "no argument: %s", filename, linenum, arg);
1235 if (*intptr == -1)
1236 *intptr = value;
1237 break;
d20f3c9e 1238
d231781a 1239 case sMatch:
1240 if (cmdline)
1241 fatal("Match directive not supported as a command-line "
1242 "option");
1243 value = match_cfg_line(&cp, linenum, user, host, address);
1244 if (value < 0)
1245 fatal("%s line %d: Bad Match condition", filename,
1246 linenum);
1247 *activep = value;
1248 break;
1249
2fefbadf 1250 case sPermitOpen:
1251 arg = strdelim(&cp);
1252 if (!arg || *arg == '\0')
1253 fatal("%s line %d: missing PermitOpen specification",
1254 filename, linenum);
38757197 1255 n = options->num_permitted_opens; /* modified later */
2fefbadf 1256 if (strcmp(arg, "any") == 0) {
38757197 1257 if (*activep && n == -1) {
2fefbadf 1258 channel_clear_adm_permitted_opens();
ea46e550 1259 options->num_permitted_opens = 0;
1260 }
2fefbadf 1261 break;
1262 }
75b6d52c 1263 if (*activep && n == -1)
1264 channel_clear_adm_permitted_opens();
ea46e550 1265 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1266 p = hpdelim(&arg);
1267 if (p == NULL)
1268 fatal("%s line %d: missing host in PermitOpen",
1269 filename, linenum);
1270 p = cleanhostname(p);
1271 if (arg == NULL || (port = a2port(arg)) == 0)
1272 fatal("%s line %d: bad port number in "
1273 "PermitOpen", filename, linenum);
75b6d52c 1274 if (*activep && n == -1)
ea46e550 1275 options->num_permitted_opens =
1276 channel_add_adm_permitted_opens(p, port);
ea46e550 1277 }
2fefbadf 1278 break;
1279
e7259e8d 1280 case sForceCommand:
1281 if (cp == NULL)
1282 fatal("%.200s line %d: Missing argument.", filename,
1283 linenum);
1284 len = strspn(cp, WHITESPACE);
1285 if (*activep && options->adm_forced_command == NULL)
1286 options->adm_forced_command = xstrdup(cp + len);
1287 return 0;
1288
db49deeb 1289 case sChrootDirectory:
1290 charptr = &options->chroot_directory;
c5bf32e6 1291
1292 arg = strdelim(&cp);
1293 if (!arg || *arg == '\0')
1294 fatal("%s line %d: missing file name.",
1295 filename, linenum);
1296 if (*activep && *charptr == NULL)
1297 *charptr = xstrdup(arg);
1298 break;
db49deeb 1299
2717fa0f 1300 case sDeprecated:
bbe88b6d 1301 logit("%s line %d: Deprecated option %s",
2717fa0f 1302 filename, linenum, arg);
1303 while (arg)
1304 arg = strdelim(&cp);
1305 break;
1306
a2144546 1307 case sUnsupported:
1308 logit("%s line %d: Unsupported option %s",
1309 filename, linenum, arg);
1310 while (arg)
1311 arg = strdelim(&cp);
1312 break;
1313
2717fa0f 1314 default:
1315 fatal("%s line %d: Missing handler for opcode %s (%d)",
1316 filename, linenum, arg, opcode);
1317 }
1318 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1319 fatal("%s line %d: garbage at end of line; \"%.200s\".",
1320 filename, linenum, arg);
1321 return 0;
1322}
089fbbd2 1323
2717fa0f 1324/* Reads the server configuration file. */
5c53a31e 1325
2717fa0f 1326void
b9a549d7 1327load_server_config(const char *filename, Buffer *conf)
2717fa0f 1328{
b9a549d7 1329 char line[1024], *cp;
7528d467 1330 FILE *f;
2717fa0f 1331
b9a549d7 1332 debug2("%s: filename %s", __func__, filename);
1333 if ((f = fopen(filename, "r")) == NULL) {
2717fa0f 1334 perror(filename);
1335 exit(1);
1336 }
b9a549d7 1337 buffer_clear(conf);
2717fa0f 1338 while (fgets(line, sizeof(line), f)) {
b9a549d7 1339 /*
1340 * Trim out comments and strip whitespace
f2107e97 1341 * NB - preserve newlines, they are needed to reproduce
b9a549d7 1342 * line numbers later for error messages
1343 */
1344 if ((cp = strchr(line, '#')) != NULL)
1345 memcpy(cp, "\n", 2);
1346 cp = line + strspn(line, " \t\r");
1347
1348 buffer_append(conf, cp, strlen(cp));
8efc0c15 1349 }
b9a549d7 1350 buffer_append(conf, "\0", 1);
5260325f 1351 fclose(f);
b9a549d7 1352 debug2("%s: done config len = %d", __func__, buffer_len(conf));
1353}
1354
1355void
d231781a 1356parse_server_match_config(ServerOptions *options, const char *user,
1357 const char *host, const char *address)
1358{
1359 ServerOptions mo;
1360
1361 initialize_server_options(&mo);
1362 parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
03bcbf84 1363 copy_set_server_options(options, &mo, 0);
d231781a 1364}
1365
03bcbf84 1366/* Helper macros */
1367#define M_CP_INTOPT(n) do {\
1368 if (src->n != -1) \
1369 dst->n = src->n; \
1370} while (0)
1371#define M_CP_STROPT(n) do {\
1372 if (src->n != NULL) { \
1373 if (dst->n != NULL) \
1374 xfree(dst->n); \
1375 dst->n = src->n; \
1376 } \
1377} while(0)
1378
1379/*
1380 * Copy any supported values that are set.
1381 *
1382 * If the preauth flag is set, we do not bother copying the the string or
1383 * array values that are not used pre-authentication, because any that we
1384 * do use must be explictly sent in mm_getpwnamallow().
1385 */
d231781a 1386void
03bcbf84 1387copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
d231781a 1388{
03bcbf84 1389 M_CP_INTOPT(password_authentication);
1390 M_CP_INTOPT(gss_authentication);
1391 M_CP_INTOPT(rsa_authentication);
1392 M_CP_INTOPT(pubkey_authentication);
1393 M_CP_INTOPT(kerberos_authentication);
1394 M_CP_INTOPT(hostbased_authentication);
1395 M_CP_INTOPT(kbd_interactive_authentication);
2ef741a3 1396 M_CP_INTOPT(permit_root_login);
03bcbf84 1397
1398 M_CP_INTOPT(allow_tcp_forwarding);
43c3f85c 1399 M_CP_INTOPT(allow_agent_forwarding);
03bcbf84 1400 M_CP_INTOPT(gateway_ports);
1401 M_CP_INTOPT(x11_display_offset);
1402 M_CP_INTOPT(x11_forwarding);
1403 M_CP_INTOPT(x11_use_localhost);
c6dca55e 1404 M_CP_INTOPT(max_sessions);
03bcbf84 1405
1406 M_CP_STROPT(banner);
1407 if (preauth)
1408 return;
1409 M_CP_STROPT(adm_forced_command);
db49deeb 1410 M_CP_STROPT(chroot_directory);
d231781a 1411}
1412
03bcbf84 1413#undef M_CP_INTOPT
1414#undef M_CP_STROPT
1415
d231781a 1416void
1417parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1418 const char *user, const char *host, const char *address)
b9a549d7 1419{
d231781a 1420 int active, linenum, bad_options = 0;
16acb158 1421 char *cp, *obuf, *cbuf;
b9a549d7 1422
1423 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1424
16acb158 1425 obuf = cbuf = xstrdup(buffer_ptr(conf));
d231781a 1426 active = user ? 0 : 1;
861cc543 1427 linenum = 1;
f8cc7664 1428 while ((cp = strsep(&cbuf, "\n")) != NULL) {
b9a549d7 1429 if (process_server_config_line(options, cp, filename,
d231781a 1430 linenum++, &active, user, host, address) != 0)
b9a549d7 1431 bad_options++;
1432 }
16acb158 1433 xfree(obuf);
b7c70970 1434 if (bad_options > 0)
1435 fatal("%s: terminating, %d bad configuration options",
1436 filename, bad_options);
8efc0c15 1437}
1760c982 1438
1439static const char *
1440fmt_intarg(ServerOpCodes code, int val)
1441{
1442 if (code == sAddressFamily) {
1443 switch (val) {
1444 case AF_INET:
1445 return "inet";
1446 case AF_INET6:
1447 return "inet6";
1448 case AF_UNSPEC:
1449 return "any";
1450 default:
1451 return "UNKNOWN";
1452 }
1453 }
1454 if (code == sPermitRootLogin) {
1455 switch (val) {
1456 case PERMIT_NO_PASSWD:
1457 return "without-passord";
1458 case PERMIT_FORCED_ONLY:
1459 return "forced-commands-only";
1460 case PERMIT_YES:
1461 return "yes";
1462 }
1463 }
1464 if (code == sProtocol) {
1465 switch (val) {
1466 case SSH_PROTO_1:
1467 return "1";
1468 case SSH_PROTO_2:
1469 return "2";
1470 case (SSH_PROTO_1|SSH_PROTO_2):
1471 return "2,1";
1472 default:
1473 return "UNKNOWN";
1474 }
1475 }
1476 if (code == sGatewayPorts && val == 2)
1477 return "clientspecified";
1478 if (code == sCompression && val == COMP_DELAYED)
1479 return "delayed";
1480 switch (val) {
1481 case -1:
1482 return "unset";
1483 case 0:
1484 return "no";
1485 case 1:
1486 return "yes";
1487 }
1488 return "UNKNOWN";
1489}
1490
1491static const char *
1492lookup_opcode_name(ServerOpCodes code)
1493{
1494 u_int i;
1495
1496 for (i = 0; keywords[i].name != NULL; i++)
1497 if (keywords[i].opcode == code)
1498 return(keywords[i].name);
1499 return "UNKNOWN";
1500}
1501
1502static void
1503dump_cfg_int(ServerOpCodes code, int val)
1504{
1505 printf("%s %d\n", lookup_opcode_name(code), val);
1506}
1507
1508static void
1509dump_cfg_fmtint(ServerOpCodes code, int val)
1510{
1511 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
1512}
1513
1514static void
1515dump_cfg_string(ServerOpCodes code, const char *val)
1516{
1517 if (val == NULL)
1518 return;
1519 printf("%s %s\n", lookup_opcode_name(code), val);
1520}
1521
1522static void
1523dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
1524{
1525 u_int i;
1526
1527 for (i = 0; i < count; i++)
1528 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
1529}
1530
1531void
1532dump_config(ServerOptions *o)
1533{
1534 u_int i;
1535 int ret;
1536 struct addrinfo *ai;
1537 char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
1538
1539 /* these are usually at the top of the config */
1540 for (i = 0; i < o->num_ports; i++)
1541 printf("port %d\n", o->ports[i]);
1542 dump_cfg_fmtint(sProtocol, o->protocol);
1543 dump_cfg_fmtint(sAddressFamily, o->address_family);
1544
1545 /* ListenAddress must be after Port */
1546 for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
1547 if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
1548 sizeof(addr), port, sizeof(port),
1549 NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
1550 error("getnameinfo failed: %.100s",
1551 (ret != EAI_SYSTEM) ? gai_strerror(ret) :
1552 strerror(errno));
1553 } else {
1554 if (ai->ai_family == AF_INET6)
1555 printf("listenaddress [%s]:%s\n", addr, port);
1556 else
1557 printf("listenaddress %s:%s\n", addr, port);
1558 }
1559 }
1560
1561 /* integer arguments */
1562 dump_cfg_int(sServerKeyBits, o->server_key_bits);
1563 dump_cfg_int(sLoginGraceTime, o->login_grace_time);
1564 dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
1565 dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
1566 dump_cfg_int(sMaxAuthTries, o->max_authtries);
1567 dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
1568 dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
1569
1570 /* formatted integer arguments */
1571 dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
1572 dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
1573 dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
1574 dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
1575 dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
1576 dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
1577 o->hostbased_uses_name_from_packet_only);
1578 dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
1579 dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
1580 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
1581 dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
1582 dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
1583 dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
1584 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
1585 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
1586 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
1587 dump_cfg_fmtint(sKbdInteractiveAuthentication,
1588 o->kbd_interactive_authentication);
1589 dump_cfg_fmtint(sChallengeResponseAuthentication,
1590 o->challenge_response_authentication);
1591 dump_cfg_fmtint(sPrintMotd, o->print_motd);
1592 dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
1593 dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
1594 dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
1595 dump_cfg_fmtint(sStrictModes, o->strict_modes);
1596 dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
1597 dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
1598 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
1599 dump_cfg_fmtint(sUseLogin, o->use_login);
1600 dump_cfg_fmtint(sCompression, o->compression);
1601 dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
1602 dump_cfg_fmtint(sUseDNS, o->use_dns);
1603 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
1604 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
1605
1606 /* string arguments */
1607 dump_cfg_string(sPidFile, o->pid_file);
1608 dump_cfg_string(sXAuthLocation, o->xauth_location);
1609 dump_cfg_string(sCiphers, o->ciphers);
1610 dump_cfg_string(sMacs, o->macs);
1611 dump_cfg_string(sBanner, o->banner);
1612 dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
1613 dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
1614 dump_cfg_string(sForceCommand, o->adm_forced_command);
1615
1616 /* string arguments requiring a lookup */
1617 dump_cfg_string(sLogLevel, log_level_name(o->log_level));
1618 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
1619
1620 /* string array arguments */
1621 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
1622 o->host_key_files);
1623 dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
1624 dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
1625 dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
1626 dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
1627 dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
1628
1629 /* other arguments */
1630 for (i = 0; i < o->num_subsystems; i++)
1631 printf("subsystem %s %s\n", o->subsystem_name[i],
1632 o->subsystem_args[i]);
1633
1634 printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
1635 o->max_startups_rate, o->max_startups);
1636
1637 for (i = 0; tunmode_desc[i].val != -1; i++)
1638 if (tunmode_desc[i].val == o->permit_tun) {
1639 s = tunmode_desc[i].text;
1640 break;
1641 }
1642 dump_cfg_string(sPermitTunnel, s);
1643
1644 printf("permitopen");
1645 channel_print_adm_permitted_opens();
1646 printf("\n");
1647}
This page took 0.551763 seconds and 5 git commands to generate.