View | Details | Raw Unified | Return to bug 1180 | Differences between
and this patch

Collapse All | Expand All

(-)Makefile.in (-1 / +1 lines)
Lines 81-87 SSHDOBJS=sshd.o auth-rhosts.o auth-passw Link Here
81
	auth.o auth1.o auth2.o auth-options.o session.o \
81
	auth.o auth1.o auth2.o auth-options.o session.o \
82
	auth-chall.o auth2-chall.o groupaccess.o \
82
	auth-chall.o auth2-chall.o groupaccess.o \
83
	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
83
	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
84
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
84
	auth2-none.o auth2-passwd.o auth2-pubkey.o cfgmatch.o \
85
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
85
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
86
	auth-krb5.o \
86
	auth-krb5.o \
87
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
87
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
(-)auth.c (+3 lines)
Lines 492-497 getpwnamallow(const char *user) Link Here
492
#endif
492
#endif
493
	struct passwd *pw;
493
	struct passwd *pw;
494
494
495
	parse_server_match_config(&options, user,
496
	    get_canonical_hostname(options.use_dns), get_remote_ipaddr());
497
495
	pw = getpwnam(user);
498
	pw = getpwnam(user);
496
	if (pw == NULL) {
499
	if (pw == NULL) {
497
		logit("Invalid user %.100s from %.100s",
500
		logit("Invalid user %.100s from %.100s",
(-)cfgmatch.c (+116 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2006 Darren Tucker.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#include "includes.h"
26
27
#include "match.h"
28
#include "log.h"
29
#include "misc.h"
30
#include "canohost.h"
31
#include "groupaccess.h"
32
33
int
34
match_cfg_line(char **condition, int line, const char *user, const char *host,
35
    const char *address)
36
{
37
	int result = 1;
38
	char *arg, *attrib, *cp = *condition, *grplist[1];
39
	size_t len;
40
	struct passwd *pw;
41
42
	if (user == NULL)
43
		debug3("checking syntax for 'Match %s'", cp);
44
	else
45
		debug3("checking match for '%s'", cp);
46
47
	while ((attrib = strdelim(&cp)) && *attrib != '\0') {
48
		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
49
			error("Missing Match criteria for %s", attrib);
50
			return -1;
51
		}
52
		len = strlen(arg);
53
		if (strcasecmp(attrib, "user") == 0) {
54
			if (!user) {
55
				result = 0;
56
				continue;
57
			}
58
			if (match_pattern_list(user, arg, len, 0) != 1)
59
				/* XXX what about negative match? */
60
				result = 0;
61
			else
62
				debug("user %.100s matched 'User %.100s' at "
63
				    "line %d", user, arg, line);
64
		} else if (strcasecmp(attrib, "group") == 0) {
65
			if (!user) {
66
				result = 0;
67
				continue;
68
			}
69
			grplist[0] = arg; /* XXX split on comma */
70
			if ((pw = getpwnam(user)) == NULL) {
71
				debug("Can't match group at line %d because "
72
				    "user %.100s does not exist", line, user);
73
				result = 0;
74
			} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
75
				debug("Can't Match group because user %.100s "
76
				    "not in any group at line %d", user,
77
				    line);
78
				result = 0;
79
			} else if (ga_match(grplist, 1) != 1) {
80
				debug("User %.100s does not match group "
81
				    "%.100s at line %d", user, arg,
82
				    line);
83
				result = 0;
84
			} else {
85
				debug("User %.100s matched Group %.100s at "
86
				    "line %d", user, arg, line);
87
			}
88
		} else if (strcasecmp(attrib, "host") == 0) {
89
			if (!host) {
90
				result = 0;
91
				continue;
92
			}
93
			if (match_hostname(host, arg, len) != 1)
94
				result = 0;
95
			else
96
				debug("connection from %.100s matched 'Host "
97
				    "%.100s' at line %d", host, arg, line);
98
		} else if (strcasecmp(attrib, "address") == 0) {
99
			if (!address) {
100
				result = 0;
101
				continue;
102
			}
103
			if (match_hostname(address, arg, len) != 1)
104
				result = 0;
105
			else
106
				debug("connection from %.100s matched 'Address "
107
				    "%.100s' at line %d", address, arg, line);
108
		} else {
109
			error("Unsupported Match attribute %s", attrib);
110
			return -1;
111
		}
112
	}
113
	*condition = cp;
114
	debug3("match_cfg_line: returning %d", result);
115
	return result;
116
}
(-)match.h (+1 lines)
Lines 20-24 int match_hostname(const char *, const Link Here
20
int	 match_host_and_ip(const char *, const char *, const char *);
20
int	 match_host_and_ip(const char *, const char *, const char *);
21
int	 match_user(const char *, const char *, const char *, const char *);
21
int	 match_user(const char *, const char *, const char *, const char *);
22
char	*match_list(const char *, const char *, u_int *);
22
char	*match_list(const char *, const char *, u_int *);
23
int	 match_cfg_line(char **, int, const char *, const char *, const char *);
23
24
24
#endif
25
#endif
(-)monitor.c (+1 lines)
Lines 612-617 mm_answer_pwnamallow(int sock, Buffer *m Link Here
612
#endif
612
#endif
613
	buffer_put_cstring(m, pwent->pw_dir);
613
	buffer_put_cstring(m, pwent->pw_dir);
614
	buffer_put_cstring(m, pwent->pw_shell);
614
	buffer_put_cstring(m, pwent->pw_shell);
615
	buffer_put_string(m, &options, sizeof(options));
615
616
616
 out:
617
 out:
617
	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
618
	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
(-)monitor_wrap.c (-4 / +26 lines)
Lines 196-202 mm_getpwnamallow(const char *username) Link Here
196
{
196
{
197
	Buffer m;
197
	Buffer m;
198
	struct passwd *pw;
198
	struct passwd *pw;
199
	u_int pwlen;
199
	u_int len;
200
	void *p;
200
201
201
	debug3("%s entering", __func__);
202
	debug3("%s entering", __func__);
202
203
Lines 212-219 mm_getpwnamallow(const char *username) Link Here
212
		buffer_free(&m);
213
		buffer_free(&m);
213
		return (NULL);
214
		return (NULL);
214
	}
215
	}
215
	pw = buffer_get_string(&m, &pwlen);
216
	pw = buffer_get_string(&m, &len);
216
	if (pwlen != sizeof(struct passwd))
217
	if (len != sizeof(struct passwd))
217
		fatal("%s: struct passwd size mismatch", __func__);
218
		fatal("%s: struct passwd size mismatch", __func__);
218
	pw->pw_name = buffer_get_string(&m, NULL);
219
	pw->pw_name = buffer_get_string(&m, NULL);
219
	pw->pw_passwd = buffer_get_string(&m, NULL);
220
	pw->pw_passwd = buffer_get_string(&m, NULL);
Lines 223-229 mm_getpwnamallow(const char *username) Link Here
223
#endif
224
#endif
224
	pw->pw_dir = buffer_get_string(&m, NULL);
225
	pw->pw_dir = buffer_get_string(&m, NULL);
225
	pw->pw_shell = buffer_get_string(&m, NULL);
226
	pw->pw_shell = buffer_get_string(&m, NULL);
226
	buffer_free(&m);
227
	p = buffer_get_string(&m, &len);
228
	if (len != sizeof(options))
229
		fatal("%s: option block size mismatch", __func__);
230
	memcpy(&options, p, len);
231
	buffer_free(&m);
232
233
	/* we don't use these options, so zero for safety */
234
	options.num_ports = 0;
235
	options.ports_from_cmdline = 0;
236
	options.pid_file = NULL;
237
	options.xauth_location = NULL;
238
	options.ciphers = NULL;
239
	options.num_allow_users = 0;
240
	options.num_deny_users = 0;
241
	options.num_allow_groups = 0;
242
	options.num_deny_groups = 0;
243
	options.macs = NULL;
244
	options.num_subsystems = 0;
245
	options.banner = NULL;
246
	options.authorized_keys_file = NULL;
247
	options.authorized_keys_file2 = NULL;
248
	options.num_accept_env = 0;
227
249
228
	return (pw);
250
	return (pw);
229
}
251
}
(-)servconf.c (-96 / +294 lines)
Lines 22-33 RCSID("$OpenBSD: servconf.c,v 1.146 2005 Link Here
22
#include "cipher.h"
22
#include "cipher.h"
23
#include "kex.h"
23
#include "kex.h"
24
#include "mac.h"
24
#include "mac.h"
25
#include "match.h"
25
26
26
static void add_listen_addr(ServerOptions *, char *, u_short);
27
static void add_listen_addr(ServerOptions *, char *, u_short);
27
static void add_one_listen_addr(ServerOptions *, char *, u_short);
28
static void add_one_listen_addr(ServerOptions *, char *, u_short);
28
29
29
/* Use of privilege separation or not */
30
/* Use of privilege separation or not */
30
extern int use_privsep;
31
extern int use_privsep;
32
extern Buffer cfg;
31
33
32
/* Initializes the server options to their default values. */
34
/* Initializes the server options to their default values. */
33
35
Lines 102-110 initialize_server_options(ServerOptions Link Here
102
	options->authorized_keys_file2 = NULL;
104
	options->authorized_keys_file2 = NULL;
103
	options->num_accept_env = 0;
105
	options->num_accept_env = 0;
104
	options->permit_tun = -1;
106
	options->permit_tun = -1;
105
106
	/* Needs to be accessable in many places */
107
	use_privsep = -1;
108
}
107
}
109
108
110
void
109
void
Lines 274-383 typedef enum { Link Here
274
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
273
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
275
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
274
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
276
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
275
	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
276
	sMatch,
277
	sUsePrivilegeSeparation,
277
	sUsePrivilegeSeparation,
278
	sDeprecated, sUnsupported
278
	sDeprecated, sUnsupported
279
} ServerOpCodes;
279
} ServerOpCodes;
280
280
281
#define SSHCFG_GLOBAL	0x01
282
#define SSHCFG_MATCH	0x02
283
#define SSHCFG_ALL	(SSHCFG_GLOBAL|SSHCFG_MATCH)
284
281
/* Textual representation of the tokens. */
285
/* Textual representation of the tokens. */
282
static struct {
286
static struct {
283
	const char *name;
287
	const char *name;
284
	ServerOpCodes opcode;
288
	ServerOpCodes opcode;
289
	u_int flags;
285
} keywords[] = {
290
} keywords[] = {
286
	/* Portable-specific options */
291
	/* Portable-specific options */
287
#ifdef USE_PAM
292
#ifdef USE_PAM
288
	{ "usepam", sUsePAM },
293
	{ "usepam", sUsePAM, SSHCFG_ALL },
289
#else
294
#else
290
	{ "usepam", sUnsupported },
295
	{ "usepam", sUnsupported, SSHCFG_ALL },
291
#endif
296
#endif
292
	{ "pamauthenticationviakbdint", sDeprecated },
297
	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
293
	/* Standard Options */
298
	/* Standard Options */
294
	{ "port", sPort },
299
	{ "port", sPort, SSHCFG_GLOBAL },
295
	{ "hostkey", sHostKeyFile },
300
	{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
296
	{ "hostdsakey", sHostKeyFile },					/* alias */
301
	{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },		/* alias */
297
	{ "pidfile", sPidFile },
302
	{ "pidfile", sPidFile, SSHCFG_GLOBAL },
298
	{ "serverkeybits", sServerKeyBits },
303
	{ "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
299
	{ "logingracetime", sLoginGraceTime },
304
	{ "logingracetime", sLoginGraceTime, SSHCFG_ALL },
300
	{ "keyregenerationinterval", sKeyRegenerationTime },
305
	{ "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
301
	{ "permitrootlogin", sPermitRootLogin },
306
	{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
302
	{ "syslogfacility", sLogFacility },
307
	{ "syslogfacility", sLogFacility, SSHCFG_ALL },
303
	{ "loglevel", sLogLevel },
308
	{ "loglevel", sLogLevel, SSHCFG_ALL },
304
	{ "rhostsauthentication", sDeprecated },
309
	{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
305
	{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
310
	{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
306
	{ "hostbasedauthentication", sHostbasedAuthentication },
311
	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
307
	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
312
	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
308
	{ "rsaauthentication", sRSAAuthentication },
313
	{ "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
309
	{ "pubkeyauthentication", sPubkeyAuthentication },
314
	{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
310
	{ "dsaauthentication", sPubkeyAuthentication },			/* alias */
315
	{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_ALL }, /* alias */
311
#ifdef KRB5
316
#ifdef KRB5
312
	{ "kerberosauthentication", sKerberosAuthentication },
317
	{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
313
	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
318
	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_ALL },
314
	{ "kerberosticketcleanup", sKerberosTicketCleanup },
319
	{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_ALL },
315
#ifdef USE_AFS
320
#ifdef USE_AFS
316
	{ "kerberosgetafstoken", sKerberosGetAFSToken },
321
	{ "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_ALL },
317
#else
322
#else
318
	{ "kerberosgetafstoken", sUnsupported },
323
	{ "kerberosgetafstoken", sUnsupported, SSHCFG_ALL },
319
#endif
324
#endif
320
#else
325
#else
321
	{ "kerberosauthentication", sUnsupported },
326
	{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
322
	{ "kerberosorlocalpasswd", sUnsupported },
327
	{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_ALL },
323
	{ "kerberosticketcleanup", sUnsupported },
328
	{ "kerberosticketcleanup", sUnsupported, SSHCFG_ALL },
324
	{ "kerberosgetafstoken", sUnsupported },
329
	{ "kerberosgetafstoken", sUnsupported, SSHCFG_ALL },
325
#endif
330
#endif
326
	{ "kerberostgtpassing", sUnsupported },
331
	{ "kerberostgtpassing", sUnsupported, SSHCFG_ALL },
327
	{ "afstokenpassing", sUnsupported },
332
	{ "afstokenpassing", sUnsupported, SSHCFG_ALL },
328
#ifdef GSSAPI
333
#ifdef GSSAPI
329
	{ "gssapiauthentication", sGssAuthentication },
334
	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
330
	{ "gssapicleanupcredentials", sGssCleanupCreds },
335
	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_ALL },
331
#else
336
#else
332
	{ "gssapiauthentication", sUnsupported },
337
	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
333
	{ "gssapicleanupcredentials", sUnsupported },
338
	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_ALL },
334
#endif
339
#endif
335
	{ "passwordauthentication", sPasswordAuthentication },
340
	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
336
	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
341
	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
337
	{ "challengeresponseauthentication", sChallengeResponseAuthentication },
342
	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_ALL },
338
	{ "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
343
	{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_ALL }, /* alias */
339
	{ "checkmail", sDeprecated },
344
	{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
340
	{ "listenaddress", sListenAddress },
345
	{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
341
	{ "addressfamily", sAddressFamily },
346
	{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
342
	{ "printmotd", sPrintMotd },
347
	{ "printmotd", sPrintMotd, SSHCFG_ALL },
343
	{ "printlastlog", sPrintLastLog },
348
	{ "printlastlog", sPrintLastLog, SSHCFG_ALL },
344
	{ "ignorerhosts", sIgnoreRhosts },
349
	{ "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL },
345
	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
350
	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_ALL },
346
	{ "x11forwarding", sX11Forwarding },
351
	{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
347
	{ "x11displayoffset", sX11DisplayOffset },
352
	{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
348
	{ "x11uselocalhost", sX11UseLocalhost },
353
	{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
349
	{ "xauthlocation", sXAuthLocation },
354
	{ "xauthlocation", sXAuthLocation, SSHCFG_ALL },
350
	{ "strictmodes", sStrictModes },
355
	{ "strictmodes", sStrictModes, SSHCFG_ALL },
351
	{ "permitemptypasswords", sEmptyPasswd },
356
	{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
352
	{ "permituserenvironment", sPermitUserEnvironment },
357
	{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_ALL },
353
	{ "uselogin", sUseLogin },
358
	{ "uselogin", sUseLogin, SSHCFG_ALL },
354
	{ "compression", sCompression },
359
	{ "compression", sCompression, SSHCFG_GLOBAL },
355
	{ "tcpkeepalive", sTCPKeepAlive },
360
	{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
356
	{ "keepalive", sTCPKeepAlive },				/* obsolete alias */
361
	{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },	/* obsolete alias */
357
	{ "allowtcpforwarding", sAllowTcpForwarding },
362
	{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
358
	{ "allowusers", sAllowUsers },
363
	{ "allowusers", sAllowUsers, SSHCFG_GLOBAL },
359
	{ "denyusers", sDenyUsers },
364
	{ "denyusers", sDenyUsers, SSHCFG_GLOBAL },
360
	{ "allowgroups", sAllowGroups },
365
	{ "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
361
	{ "denygroups", sDenyGroups },
366
	{ "denygroups", sDenyGroups, SSHCFG_GLOBAL },
362
	{ "ciphers", sCiphers },
367
	{ "ciphers", sCiphers, SSHCFG_GLOBAL },
363
	{ "macs", sMacs },
368
	{ "macs", sMacs, SSHCFG_GLOBAL },
364
	{ "protocol", sProtocol },
369
	{ "protocol", sProtocol, SSHCFG_GLOBAL },
365
	{ "gatewayports", sGatewayPorts },
370
	{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
366
	{ "subsystem", sSubsystem },
371
	{ "subsystem", sSubsystem, SSHCFG_ALL },
367
	{ "maxstartups", sMaxStartups },
372
	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
368
	{ "maxauthtries", sMaxAuthTries },
373
	{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
369
	{ "banner", sBanner },
374
	{ "banner", sBanner, SSHCFG_ALL },
370
	{ "usedns", sUseDNS },
375
	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
371
	{ "verifyreversemapping", sDeprecated },
376
	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
372
	{ "reversemappingcheck", sDeprecated },
377
	{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
373
	{ "clientaliveinterval", sClientAliveInterval },
378
	{ "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
374
	{ "clientalivecountmax", sClientAliveCountMax },
379
	{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
375
	{ "authorizedkeysfile", sAuthorizedKeysFile },
380
	{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
376
	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
381
	{ "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL },
377
	{ "useprivilegeseparation", sUsePrivilegeSeparation},
382
	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
378
	{ "acceptenv", sAcceptEnv },
383
	{ "acceptenv", sAcceptEnv, SSHCFG_ALL },
379
	{ "permittunnel", sPermitTunnel },
384
	{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
380
	{ NULL, sBadOption }
385
	{ "match", sMatch, SSHCFG_ALL },
386
	{ NULL, sBadOption, 0 }
381
};
387
};
382
388
383
/*
389
/*
Lines 386-398 static struct { Link Here
386
392
387
static ServerOpCodes
393
static ServerOpCodes
388
parse_token(const char *cp, const char *filename,
394
parse_token(const char *cp, const char *filename,
389
	    int linenum)
395
	    int linenum, u_int *flags)
390
{
396
{
391
	u_int i;
397
	u_int i;
392
398
393
	for (i = 0; keywords[i].name; i++)
399
	for (i = 0; keywords[i].name; i++)
394
		if (strcasecmp(cp, keywords[i].name) == 0)
400
		if (strcasecmp(cp, keywords[i].name) == 0) {
401
			*flags = keywords[i].flags;
395
			return keywords[i].opcode;
402
			return keywords[i].opcode;
403
		}
396
404
397
	error("%s: line %d: Bad configuration option: %s",
405
	error("%s: line %d: Bad configuration option: %s",
398
	    filename, linenum, cp);
406
	    filename, linenum, cp);
Lines 437-451 add_one_listen_addr(ServerOptions *optio Link Here
437
	options->listen_addrs = aitop;
445
	options->listen_addrs = aitop;
438
}
446
}
439
447
448
/*
449
 * The strategy for the Match blocks is that the config file is parsed twice.
450
 *
451
 * The first time is at startup.  activep is initialized to 1 and the
452
 * directives in the global context are processed and acted on.  Hitting a
453
 * Match directive unsets activep and the directives inside the block are
454
 * checked for syntax only.
455
 *
456
 * The second time is after a connection has been established but before
457
 * authentication.  activep is initialized to 2 and global config directives
458
 * are ignored since they have already been processed.  If the criteria in a
459
 * Match block is met, activep is set and the subsequent directives
460
 * processed and actioned until EOF or another Match block unsets it.  Any
461
 * options set are copied into the main server config.
462
 *
463
 * Potential additions/improvements:
464
 *  - Add Match support for pre-kex directives, eg Protocol, Ciphers.
465
 *
466
 *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
467
 *	Match Address 192.168.0.*
468
 *		Tag trusted
469
 *	Match Group wheel
470
 *		Tag trusted
471
 *	Match Tag trusted
472
 *		AllowTcpForwarding yes
473
 *		GatewayPorts clientspecified
474
 *		[...]
475
 *
476
 *  - Add a PermittedChannelRequests directive
477
 *	Match Group shell
478
 *		PermittedChannelRequests session,forwarded-tcpip
479
 */
480
440
int
481
int
441
process_server_config_line(ServerOptions *options, char *line,
482
process_server_config_line(ServerOptions *options, char *line,
442
    const char *filename, int linenum)
483
    const char *filename, int linenum, int *activep, const char *user,
484
    const char *host, const char *address)
443
{
485
{
444
	char *cp, **charptr, *arg, *p;
486
	char *cp, **charptr, *arg, *p;
445
	int *intptr, value, n;
487
	int cmdline = 0, *intptr, value, n;
446
	ServerOpCodes opcode;
488
	ServerOpCodes opcode;
447
	u_short port;
489
	u_short port;
448
	u_int i;
490
	u_int i, flags = 0;
449
491
450
	cp = line;
492
	cp = line;
451
	arg = strdelim(&cp);
493
	arg = strdelim(&cp);
Lines 456-462 process_server_config_line(ServerOptions Link Here
456
		return 0;
498
		return 0;
457
	intptr = NULL;
499
	intptr = NULL;
458
	charptr = NULL;
500
	charptr = NULL;
459
	opcode = parse_token(arg, filename, linenum);
501
	opcode = parse_token(arg, filename, linenum, &flags);
502
503
	if (activep == NULL) { /* We are processing a command line directive */
504
		cmdline = 1;
505
		activep = &cmdline;
506
	}
507
	debug3("match: line %s active %d flags %d", line, *activep, flags);
508
	if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
509
		if (user == NULL) {
510
			fatal("%s line %d: Directive '%s' is not allowed "
511
			    "within a Match block", filename, linenum, arg);
512
		} else { /* this is a directive we have already processed */
513
			while (arg)
514
				arg = strdelim(&cp);
515
			return 0;
516
		}
517
	}
518
460
	switch (opcode) {
519
	switch (opcode) {
461
	/* Portable-specific options */
520
	/* Portable-specific options */
462
	case sUsePAM:
521
	case sUsePAM:
Lines 494-500 parse_int: Link Here
494
			fatal("%s line %d: missing integer value.",
553
			fatal("%s line %d: missing integer value.",
495
			    filename, linenum);
554
			    filename, linenum);
496
		value = atoi(arg);
555
		value = atoi(arg);
497
		if (*intptr == -1)
556
		if (*activep && *intptr == -1)
498
			*intptr = value;
557
			*intptr = value;
499
		break;
558
		break;
500
559
Lines 574-580 parse_filename: Link Here
574
		if (!arg || *arg == '\0')
633
		if (!arg || *arg == '\0')
575
			fatal("%s line %d: missing file name.",
634
			fatal("%s line %d: missing file name.",
576
			    filename, linenum);
635
			    filename, linenum);
577
		if (*charptr == NULL) {
636
		if (*activep && *charptr == NULL) {
578
			*charptr = tilde_expand_filename(arg, getuid());
637
			*charptr = tilde_expand_filename(arg, getuid());
579
			/* increase optional counter */
638
			/* increase optional counter */
580
			if (intptr != NULL)
639
			if (intptr != NULL)
Lines 625-631 parse_flag: Link Here
625
		else
684
		else
626
			fatal("%s line %d: Bad yes/no argument: %s",
685
			fatal("%s line %d: Bad yes/no argument: %s",
627
				filename, linenum, arg);
686
				filename, linenum, arg);
628
		if (*intptr == -1)
687
		if (*activep && *intptr == -1)
629
			*intptr = value;
688
			*intptr = value;
630
		break;
689
		break;
631
690
Lines 890-895 parse_flag: Link Here
890
		if (!arg || *arg == '\0')
949
		if (!arg || *arg == '\0')
891
			fatal("%s line %d: Missing subsystem name.",
950
			fatal("%s line %d: Missing subsystem name.",
892
			    filename, linenum);
951
			    filename, linenum);
952
		if (!*activep) {
953
			arg = strdelim(&cp);
954
			break;
955
		}
893
		for (i = 0; i < options->num_subsystems; i++)
956
		for (i = 0; i < options->num_subsystems; i++)
894
			if (strcmp(arg, options->subsystem_name[i]) == 0)
957
			if (strcmp(arg, options->subsystem_name[i]) == 0)
895
				fatal("%s line %d: Subsystem '%s' already defined.",
958
				fatal("%s line %d: Subsystem '%s' already defined.",
Lines 961-966 parse_flag: Link Here
961
			if (options->num_accept_env >= MAX_ACCEPT_ENV)
1024
			if (options->num_accept_env >= MAX_ACCEPT_ENV)
962
				fatal("%s line %d: too many allow env.",
1025
				fatal("%s line %d: too many allow env.",
963
				    filename, linenum);
1026
				    filename, linenum);
1027
			if (!*activep)
1028
				break;
964
			options->accept_env[options->num_accept_env++] =
1029
			options->accept_env[options->num_accept_env++] =
965
			    xstrdup(arg);
1030
			    xstrdup(arg);
966
		}
1031
		}
Lines 988-993 parse_flag: Link Here
988
			*intptr = value;
1053
			*intptr = value;
989
		break;
1054
		break;
990
1055
1056
	case sMatch:
1057
		if (cmdline)
1058
			fatal("Match directive not supported as a command-line "
1059
			   "option");
1060
		value = match_cfg_line(&cp, linenum, user, host, address);
1061
		if (value < 0)
1062
			fatal("%s line %d: Bad Match condition", filename,
1063
			    linenum);
1064
		*activep = value;
1065
		break;
1066
991
	case sDeprecated:
1067
	case sDeprecated:
992
		logit("%s line %d: Deprecated option %s",
1068
		logit("%s line %d: Deprecated option %s",
993
		    filename, linenum, arg);
1069
		    filename, linenum, arg);
Lines 1044-1061 load_server_config(const char *filename, Link Here
1044
}
1120
}
1045
1121
1046
void
1122
void
1047
parse_server_config(ServerOptions *options, const char *filename, Buffer *conf)
1123
parse_server_match_config(ServerOptions *options, const char *user,
1124
    const char *host, const char *address)
1125
{
1126
	u_int i;
1127
	ServerOptions mo;
1128
1129
	initialize_server_options(&mo);
1130
	parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1131
1132
	/* now copy any (supported) values set */
1133
	if (mo.use_pam != -1)
1134
		options->use_pam = mo.use_pam;
1135
	if (mo.num_accept_env > 0) {
1136
		for (i = 0; i < options->num_accept_env; i++)
1137
			xfree(options->accept_env[i]);
1138
		options->num_accept_env = 0;
1139
		for (i = 0; i < mo.num_accept_env; i++) {
1140
			if (options->num_accept_env >= MAX_ACCEPT_ENV)
1141
				fatal("Too many allow env in Match block.");
1142
			options->accept_env[options->num_accept_env++] =
1143
			    mo.accept_env[i];
1144
		}
1145
	}
1146
	if (mo.allow_tcp_forwarding != -1)
1147
		options->allow_tcp_forwarding = mo.allow_tcp_forwarding;
1148
	if (mo.authorized_keys_file != NULL) {
1149
		if (options->authorized_keys_file != NULL)
1150
			xfree(options->authorized_keys_file);
1151
		options->authorized_keys_file = mo.authorized_keys_file;
1152
	}
1153
	if (mo.authorized_keys_file2 != NULL) {
1154
		if (options->authorized_keys_file2 != NULL)
1155
			xfree(options->authorized_keys_file2);
1156
		options->authorized_keys_file2 = mo.authorized_keys_file2;
1157
	}
1158
	if (mo.banner != NULL) {
1159
		if (options->banner != NULL)
1160
			xfree(options->banner);
1161
		options->banner = mo.banner;
1162
	}
1163
	if (mo.password_authentication != -1)
1164
		options->password_authentication = mo.password_authentication;
1165
	if (mo.challenge_response_authentication != -1)
1166
		options->challenge_response_authentication =
1167
		    mo.challenge_response_authentication;
1168
	if (mo.client_alive_count_max != -1)
1169
		options->client_alive_count_max = mo.client_alive_count_max;
1170
	if (mo.client_alive_interval != -1)
1171
		options->client_alive_interval = mo.client_alive_interval;
1172
	if (mo.gateway_ports != -1)
1173
		options->gateway_ports = mo.gateway_ports;
1174
	if (mo.gss_authentication != -1)
1175
		options->gss_authentication = mo.gss_authentication;
1176
	if (mo.hostbased_authentication != -1)
1177
		options->hostbased_authentication = mo.hostbased_authentication;
1178
	if (mo.hostbased_uses_name_from_packet_only != -1)
1179
		options->hostbased_uses_name_from_packet_only =
1180
		    mo.hostbased_uses_name_from_packet_only;
1181
	if (mo.kerberos_authentication != -1)
1182
		options->kerberos_authentication = mo.kerberos_authentication;
1183
	if (mo.kerberos_or_local_passwd != -1)
1184
		options->kerberos_or_local_passwd = mo.kerberos_or_local_passwd;
1185
	if (mo.kerberos_ticket_cleanup != -1)
1186
		options->kerberos_ticket_cleanup = mo.kerberos_ticket_cleanup;
1187
	if (mo.kerberos_get_afs_token != -1)
1188
		options->kerberos_get_afs_token = mo.kerberos_get_afs_token;
1189
	if (mo.login_grace_time != -1)
1190
		options->login_grace_time = mo.login_grace_time;
1191
	if (mo.log_facility != -1)
1192
		options->log_facility = mo.log_facility;
1193
	if (mo.log_level != -1)
1194
		options->log_level = mo.log_level;
1195
	if (mo.permit_root_login != -1)
1196
		options->permit_root_login = mo.permit_root_login;
1197
	if (mo.max_authtries != -1)
1198
		options->max_authtries = mo.max_authtries;
1199
	if (mo.permit_empty_passwd != -1)
1200
		options->permit_empty_passwd = mo.permit_empty_passwd;
1201
	if (mo.permit_tun != -1)
1202
		options->permit_tun = mo.permit_tun;
1203
	if (mo.permit_user_env != -1)
1204
		options->permit_user_env = mo.permit_user_env;
1205
	if (mo.print_motd != -1)
1206
		options->print_motd = mo.print_motd;
1207
	if (mo.pubkey_authentication != -1)
1208
		options->pubkey_authentication = mo.pubkey_authentication;
1209
	if (mo.rsa_authentication != -1)
1210
		options->rsa_authentication = mo.rsa_authentication;
1211
	if (mo.strict_modes != -1)
1212
		options->strict_modes = mo.strict_modes;
1213
	if (mo.num_subsystems != 0) {  /* Not currently used */
1214
		for (i = 0; i < options->num_subsystems; i++) {
1215
			xfree(options->subsystem_name[i]);
1216
			xfree(options->subsystem_command[i]);
1217
		}
1218
		options->num_subsystems = 0;
1219
		for (i = 0; i < mo.num_subsystems; i++) {
1220
			options->subsystem_name[options->num_subsystems] =
1221
			    mo.subsystem_name[i];
1222
			options->subsystem_command[options->num_subsystems] =
1223
			    mo.subsystem_command[i];
1224
			options->num_subsystems++;
1225
		}
1226
	}
1227
	if (mo.use_login != -1)
1228
		options->use_login = mo.use_login;
1229
	if (mo.xauth_location != NULL) {
1230
		if (options->xauth_location != NULL)
1231
			xfree(options->xauth_location);
1232
		options->xauth_location = mo.xauth_location;
1233
	}
1234
	if (mo.x11_display_offset != -1)
1235
		options->x11_display_offset = mo.x11_display_offset;
1236
	if (mo.x11_forwarding != -1)
1237
		options->x11_forwarding = mo.x11_forwarding;
1238
	if (mo.x11_use_localhost != -1)
1239
		options->x11_use_localhost = mo.x11_use_localhost;
1240
}
1241
1242
void
1243
parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1244
    const char *user, const char *host, const char *address)
1048
{
1245
{
1049
	int linenum, bad_options = 0;
1246
	int active, linenum, bad_options = 0;
1050
	char *cp, *obuf, *cbuf;
1247
	char *cp, *obuf, *cbuf;
1051
1248
1052
	debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1249
	debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1053
1250
1054
	obuf = cbuf = xstrdup(buffer_ptr(conf));
1251
	obuf = cbuf = xstrdup(buffer_ptr(conf));
1252
	active = user ? 0 : 1;
1055
	linenum = 1;
1253
	linenum = 1;
1056
	while ((cp = strsep(&cbuf, "\n")) != NULL) {
1254
	while ((cp = strsep(&cbuf, "\n")) != NULL) {
1057
		if (process_server_config_line(options, cp, filename,
1255
		if (process_server_config_line(options, cp, filename,
1058
		    linenum++) != 0)
1256
		    linenum++, &active, user, host, address) != 0)
1059
			bad_options++;
1257
			bad_options++;
1060
	}
1258
	}
1061
	xfree(obuf);
1259
	xfree(obuf);
(-)servconf.h (-2 / +6 lines)
Lines 141-148 typedef struct { Link Here
141
141
142
void	 initialize_server_options(ServerOptions *);
142
void	 initialize_server_options(ServerOptions *);
143
void	 fill_default_server_options(ServerOptions *);
143
void	 fill_default_server_options(ServerOptions *);
144
int	 process_server_config_line(ServerOptions *, char *, const char *, int);
144
int	 process_server_config_line(ServerOptions *, char *, const char *, int,
145
	     int *, const char *, const char *, const char *);
145
void	 load_server_config(const char *, Buffer *);
146
void	 load_server_config(const char *, Buffer *);
146
void	 parse_server_config(ServerOptions *, const char *, Buffer *);
147
void	 parse_server_config(ServerOptions *, const char *, Buffer *,
148
	     const char *, const char *, const char *);
149
void	 parse_server_match_config(ServerOptions *, const char *, const char *,
150
	     const char *);
147
151
148
#endif				/* SERVCONF_H */
152
#endif				/* SERVCONF_H */
(-)sshd.c (-8 / +7 lines)
Lines 201-212 int *startup_pipes = NULL; Link Here
201
int startup_pipe;		/* in child */
201
int startup_pipe;		/* in child */
202
202
203
/* variables used for privilege separation */
203
/* variables used for privilege separation */
204
int use_privsep;
204
int use_privsep = -1;		/* Needs to be accessable in many places */
205
struct monitor *pmonitor = NULL;
205
struct monitor *pmonitor = NULL;
206
206
207
/* global authentication context */
207
/* global authentication context */
208
Authctxt *the_authctxt = NULL;
208
Authctxt *the_authctxt = NULL;
209
209
210
/* sshd_config buffer */
211
Buffer cfg;
212
210
/* message to be displayed after login */
213
/* message to be displayed after login */
211
Buffer loginmsg;
214
Buffer loginmsg;
212
215
Lines 892-898 main(int ac, char **av) Link Here
892
	Key *key;
895
	Key *key;
893
	Authctxt *authctxt;
896
	Authctxt *authctxt;
894
	int ret, key_used = 0;
897
	int ret, key_used = 0;
895
	Buffer cfg;
896
898
897
#ifdef HAVE_SECUREWARE
899
#ifdef HAVE_SECUREWARE
898
	(void)set_auth_parameters(ac, av);
900
	(void)set_auth_parameters(ac, av);
Lines 1011-1017 main(int ac, char **av) Link Here
1011
		case 'o':
1013
		case 'o':
1012
			line = xstrdup(optarg);
1014
			line = xstrdup(optarg);
1013
			if (process_server_config_line(&options, line,
1015
			if (process_server_config_line(&options, line,
1014
			    "command-line", 0) != 0)
1016
			    "command-line", 0, NULL, NULL, NULL, NULL) != 0)
1015
				exit(1);
1017
				exit(1);
1016
			xfree(line);
1018
			xfree(line);
1017
			break;
1019
			break;
Lines 1069-1079 main(int ac, char **av) Link Here
1069
	else
1071
	else
1070
		load_server_config(config_file_name, &cfg);
1072
		load_server_config(config_file_name, &cfg);
1071
1073
1072
	parse_server_config(&options,
1074
	parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
1073
	    rexeced_flag ? "rexec" : config_file_name, &cfg);
1075
	    &cfg, NULL, NULL, NULL);
1074
1075
	if (!rexec_flag)
1076
		buffer_free(&cfg);
1077
1076
1078
	seed_rng();
1077
	seed_rng();
1079
1078
(-)sshd_config.5 (+75 lines)
Lines 433-438 for data integrity protection. Link Here
433
Multiple algorithms must be comma-separated.
433
Multiple algorithms must be comma-separated.
434
The default is
434
The default is
435
.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
435
.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
436
.It Cm Match
437
Introduces a conditional block.  Keywords on lines following a
438
.Cm Match
439
block are only applied if the criteria on the
440
.Cm Match
441
are satisfied.
442
The the arguments to
443
.Cm Match
444
block are one or more criteria-pattern pairs.
445
The available criteria are
446
.Cm User ,
447
.Cm Group ,
448
.Cm Host ,
449
and
450
.Cm Address .
451
Only a subset of keywords may be used on the lines following a
452
.Cm Match
453
keyword.
454
Available keywords are
455
.Cm AcceptEnv ,
456
.Cm AllowTcpForwarding ,
457
.Cm AuthorizedKeysFile ,
458
.Cm AuthorizedKeysFile2 ,
459
.Cm Banner ,
460
.Cm ChallengeResponseAuthentication ,
461
.Cm ChallengeResponseAuthentication ,
462
.Cm ClientAliveCountMax ,
463
.Cm ClientAliveInterval ,
464
.Cm GatewayPorts ,
465
.Cm GssAuthentication ,
466
.Cm GssCleanupCreds ,
467
.Cm HostbasedAuthentication ,
468
.Cm HostbasedUsesNameFromPacketOnly ,
469
.Cm IgnoreRhosts ,
470
.Cm IgnoreUserKnownHosts ,
471
.Cm KbdInteractiveAuthentication ,
472
.Cm KerberosAuthentication ,
473
.Cm KerberosGetAFSToken ,
474
.Cm KerberosOrLocalPasswd ,
475
.Cm KerberosTicketCleanup ,
476
.Cm LogFacility ,
477
.Cm LogLevel ,
478
.Cm LoginGraceTime ,
479
.Cm MaxAuthTries ,
480
.Cm PasswordAuthentication ,
481
.Cm PermitEmptyPasswd ,
482
.Cm PermitRootLogin ,
483
.Cm PermitTunnel ,
484
.Cm PermitUserEnvironment ,
485
.Cm PrintLastLog ,
486
.Cm PrintMotd ,
487
.Cm PubkeyAuthentication ,
488
.Cm PubkeyAuthentication ,
489
.Cm RSAAuthentication ,
490
.Cm RhostsRSAAuthentication ,
491
.Cm StrictModes ,
492
.Cm Subsystem ,
493
.Cm UseLogin ,
494
.Cm UsePAM ,
495
.Cm X11DisplayOffset ,
496
.Cm X11Forwarding ,
497
.Cm X11UseLocalhost ,
498
and
499
.Cm XAuthLocation .
436
.It Cm MaxAuthTries
500
.It Cm MaxAuthTries
437
Specifies the maximum number of authentication attempts permitted per
501
Specifies the maximum number of authentication attempts permitted per
438
connection.
502
connection.
Lines 827-832 Contains configuration data for Link Here
827
This file should be writable by root only, but it is recommended
891
This file should be writable by root only, but it is recommended
828
(though not necessary) that it be world-readable.
892
(though not necessary) that it be world-readable.
829
.El
893
.El
894
.Sh EXAMPLES
895
To allow
896
.Cm PasswordAuthentication
897
only from the local private network:
898
.Bd -literal -offset indent
899
PasswordAuthentication no
900
Match Address 192.168.0.*
901
	PasswordAuthentication yes
902
.Ed
903
.Bl -tag -width Ds
904
.Bl -tag -width Ds
830
.Sh SEE ALSO
905
.Sh SEE ALSO
831
.Xr sshd 8
906
.Xr sshd 8
832
.Sh AUTHORS
907
.Sh AUTHORS

Return to bug 1180