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