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