diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | auth.c | 5 | ||||
-rw-r--r-- | servconf.c | 356 | ||||
-rw-r--r-- | servconf.h | 11 | ||||
-rw-r--r-- | sshd.c | 17 | ||||
-rw-r--r-- | sshd_config.5 | 23 |
6 files changed, 314 insertions, 112 deletions
@@ -43,6 +43,18 @@ | |||
43 | - stevesk@cvs.openbsd.org 2006/07/11 20:27:56 | 43 | - stevesk@cvs.openbsd.org 2006/07/11 20:27:56 |
44 | [authfile.c ssh.c] | 44 | [authfile.c ssh.c] |
45 | need <errno.h> here also (it's also included in <openssl/err.h>) | 45 | need <errno.h> here also (it's also included in <openssl/err.h>) |
46 | - dtucker@cvs.openbsd.org 2006/07/12 11:34:58 | ||
47 | [sshd.c servconf.h servconf.c sshd_config.5 auth.c] | ||
48 | Add support for conditional directives to sshd_config via a "Match" | ||
49 | keyword, which works similarly to the "Host" directive in ssh_config. | ||
50 | Lines after a Match line override the default set in the main section | ||
51 | if the condition on the Match line is true, eg | ||
52 | AllowTcpForwarding yes | ||
53 | Match User anoncvs | ||
54 | AllowTcpForwarding no | ||
55 | will allow port forwarding by all users except "anoncvs". | ||
56 | Currently only a very small subset of directives are supported. | ||
57 | ok djm@ | ||
46 | 58 | ||
47 | 20060711 | 59 | 20060711 |
48 | - (dtucker) [configure.ac ssh-keygen.c openbsd-compat/bsd-openpty.c | 60 | - (dtucker) [configure.ac ssh-keygen.c openbsd-compat/bsd-openpty.c |
@@ -4892,4 +4904,4 @@ | |||
4892 | - (djm) Trim deprecated options from INSTALL. Mention UsePAM | 4904 | - (djm) Trim deprecated options from INSTALL. Mention UsePAM |
4893 | - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu | 4905 | - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu |
4894 | 4906 | ||
4895 | $Id: ChangeLog,v 1.4399 2006/07/12 12:24:22 dtucker Exp $ | 4907 | $Id: ChangeLog,v 1.4400 2006/07/12 12:34:17 dtucker Exp $ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.70 2006/07/11 20:07:25 stevesk Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.71 2006/07/12 11:34:58 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -467,6 +467,9 @@ getpwnamallow(const char *user) | |||
467 | #endif | 467 | #endif |
468 | struct passwd *pw; | 468 | struct passwd *pw; |
469 | 469 | ||
470 | parse_server_match_config(&options, user, | ||
471 | get_canonical_hostname(options.use_dns), get_remote_ipaddr()); | ||
472 | |||
470 | pw = getpwnam(user); | 473 | pw = getpwnam(user); |
471 | if (pw == NULL) { | 474 | if (pw == NULL) { |
472 | logit("Invalid user %.100s from %.100s", | 475 | logit("Invalid user %.100s from %.100s", |
diff --git a/servconf.c b/servconf.c index c5b933ab9..42ec340f3 100644 --- a/servconf.c +++ b/servconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: servconf.c,v 1.152 2006/07/08 21:47:12 stevesk Exp $ */ | 1 | /* $OpenBSD: servconf.c,v 1.153 2006/07/12 11:34:58 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -25,12 +25,14 @@ | |||
25 | #include "cipher.h" | 25 | #include "cipher.h" |
26 | #include "kex.h" | 26 | #include "kex.h" |
27 | #include "mac.h" | 27 | #include "mac.h" |
28 | #include "match.h" | ||
28 | 29 | ||
29 | static void add_listen_addr(ServerOptions *, char *, u_short); | 30 | static void add_listen_addr(ServerOptions *, char *, u_short); |
30 | static void add_one_listen_addr(ServerOptions *, char *, u_short); | 31 | static void add_one_listen_addr(ServerOptions *, char *, u_short); |
31 | 32 | ||
32 | /* Use of privilege separation or not */ | 33 | /* Use of privilege separation or not */ |
33 | extern int use_privsep; | 34 | extern int use_privsep; |
35 | extern Buffer cfg; | ||
34 | 36 | ||
35 | /* Initializes the server options to their default values. */ | 37 | /* Initializes the server options to their default values. */ |
36 | 38 | ||
@@ -105,9 +107,6 @@ initialize_server_options(ServerOptions *options) | |||
105 | options->authorized_keys_file2 = NULL; | 107 | options->authorized_keys_file2 = NULL; |
106 | options->num_accept_env = 0; | 108 | options->num_accept_env = 0; |
107 | options->permit_tun = -1; | 109 | options->permit_tun = -1; |
108 | |||
109 | /* Needs to be accessable in many places */ | ||
110 | use_privsep = -1; | ||
111 | } | 110 | } |
112 | 111 | ||
113 | void | 112 | void |
@@ -277,110 +276,116 @@ typedef enum { | |||
277 | sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, | 276 | sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, |
278 | sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, | 277 | sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, |
279 | sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, | 278 | sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, |
279 | sMatch, | ||
280 | sUsePrivilegeSeparation, | 280 | sUsePrivilegeSeparation, |
281 | sDeprecated, sUnsupported | 281 | sDeprecated, sUnsupported |
282 | } ServerOpCodes; | 282 | } ServerOpCodes; |
283 | 283 | ||
284 | #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ | ||
285 | #define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ | ||
286 | #define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) | ||
287 | |||
284 | /* Textual representation of the tokens. */ | 288 | /* Textual representation of the tokens. */ |
285 | static struct { | 289 | static struct { |
286 | const char *name; | 290 | const char *name; |
287 | ServerOpCodes opcode; | 291 | ServerOpCodes opcode; |
292 | u_int flags; | ||
288 | } keywords[] = { | 293 | } keywords[] = { |
289 | /* Portable-specific options */ | 294 | /* Portable-specific options */ |
290 | #ifdef USE_PAM | 295 | #ifdef USE_PAM |
291 | { "usepam", sUsePAM }, | 296 | { "usepam", sUsePAM, SSHCFG_GLOBAL }, |
292 | #else | 297 | #else |
293 | { "usepam", sUnsupported }, | 298 | { "usepam", sUnsupported, SSHCFG_GLOBAL }, |
294 | #endif | 299 | #endif |
295 | { "pamauthenticationviakbdint", sDeprecated }, | 300 | { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, |
296 | /* Standard Options */ | 301 | /* Standard Options */ |
297 | { "port", sPort }, | 302 | { "port", sPort, SSHCFG_GLOBAL }, |
298 | { "hostkey", sHostKeyFile }, | 303 | { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, |
299 | { "hostdsakey", sHostKeyFile }, /* alias */ | 304 | { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ |
300 | { "pidfile", sPidFile }, | 305 | { "pidfile", sPidFile, SSHCFG_GLOBAL }, |
301 | { "serverkeybits", sServerKeyBits }, | 306 | { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, |
302 | { "logingracetime", sLoginGraceTime }, | 307 | { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, |
303 | { "keyregenerationinterval", sKeyRegenerationTime }, | 308 | { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, |
304 | { "permitrootlogin", sPermitRootLogin }, | 309 | { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL }, |
305 | { "syslogfacility", sLogFacility }, | 310 | { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, |
306 | { "loglevel", sLogLevel }, | 311 | { "loglevel", sLogLevel, SSHCFG_GLOBAL }, |
307 | { "rhostsauthentication", sDeprecated }, | 312 | { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, |
308 | { "rhostsrsaauthentication", sRhostsRSAAuthentication }, | 313 | { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL }, |
309 | { "hostbasedauthentication", sHostbasedAuthentication }, | 314 | { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL }, |
310 | { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, | 315 | { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL }, |
311 | { "rsaauthentication", sRSAAuthentication }, | 316 | { "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL }, |
312 | { "pubkeyauthentication", sPubkeyAuthentication }, | 317 | { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, |
313 | { "dsaauthentication", sPubkeyAuthentication }, /* alias */ | 318 | { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ |
314 | #ifdef KRB5 | 319 | #ifdef KRB5 |
315 | { "kerberosauthentication", sKerberosAuthentication }, | 320 | { "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL }, |
316 | { "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, | 321 | { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, |
317 | { "kerberosticketcleanup", sKerberosTicketCleanup }, | 322 | { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, |
318 | #ifdef USE_AFS | 323 | #ifdef USE_AFS |
319 | { "kerberosgetafstoken", sKerberosGetAFSToken }, | 324 | { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, |
320 | #else | 325 | #else |
321 | { "kerberosgetafstoken", sUnsupported }, | 326 | { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, |
322 | #endif | 327 | #endif |
323 | #else | 328 | #else |
324 | { "kerberosauthentication", sUnsupported }, | 329 | { "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL }, |
325 | { "kerberosorlocalpasswd", sUnsupported }, | 330 | { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, |
326 | { "kerberosticketcleanup", sUnsupported }, | 331 | { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, |
327 | { "kerberosgetafstoken", sUnsupported }, | 332 | { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, |
328 | #endif | 333 | #endif |
329 | { "kerberostgtpassing", sUnsupported }, | 334 | { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, |
330 | { "afstokenpassing", sUnsupported }, | 335 | { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, |
331 | #ifdef GSSAPI | 336 | #ifdef GSSAPI |
332 | { "gssapiauthentication", sGssAuthentication }, | 337 | { "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL }, |
333 | { "gssapicleanupcredentials", sGssCleanupCreds }, | 338 | { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, |
334 | #else | 339 | #else |
335 | { "gssapiauthentication", sUnsupported }, | 340 | { "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL }, |
336 | { "gssapicleanupcredentials", sUnsupported }, | 341 | { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, |
337 | #endif | 342 | #endif |
338 | { "passwordauthentication", sPasswordAuthentication }, | 343 | { "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL }, |
339 | { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, | 344 | { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL }, |
340 | { "challengeresponseauthentication", sChallengeResponseAuthentication }, | 345 | { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, |
341 | { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */ | 346 | { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ |
342 | { "checkmail", sDeprecated }, | 347 | { "checkmail", sDeprecated, SSHCFG_GLOBAL }, |
343 | { "listenaddress", sListenAddress }, | 348 | { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, |
344 | { "addressfamily", sAddressFamily }, | 349 | { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, |
345 | { "printmotd", sPrintMotd }, | 350 | { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, |
346 | { "printlastlog", sPrintLastLog }, | 351 | { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, |
347 | { "ignorerhosts", sIgnoreRhosts }, | 352 | { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, |
348 | { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, | 353 | { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, |
349 | { "x11forwarding", sX11Forwarding }, | 354 | { "x11forwarding", sX11Forwarding, SSHCFG_GLOBAL }, |
350 | { "x11displayoffset", sX11DisplayOffset }, | 355 | { "x11displayoffset", sX11DisplayOffset, SSHCFG_GLOBAL }, |
351 | { "x11uselocalhost", sX11UseLocalhost }, | 356 | { "x11uselocalhost", sX11UseLocalhost, SSHCFG_GLOBAL }, |
352 | { "xauthlocation", sXAuthLocation }, | 357 | { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, |
353 | { "strictmodes", sStrictModes }, | 358 | { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, |
354 | { "permitemptypasswords", sEmptyPasswd }, | 359 | { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL }, |
355 | { "permituserenvironment", sPermitUserEnvironment }, | 360 | { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, |
356 | { "uselogin", sUseLogin }, | 361 | { "uselogin", sUseLogin, SSHCFG_GLOBAL }, |
357 | { "compression", sCompression }, | 362 | { "compression", sCompression, SSHCFG_GLOBAL }, |
358 | { "tcpkeepalive", sTCPKeepAlive }, | 363 | { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, |
359 | { "keepalive", sTCPKeepAlive }, /* obsolete alias */ | 364 | { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ |
360 | { "allowtcpforwarding", sAllowTcpForwarding }, | 365 | { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, |
361 | { "allowusers", sAllowUsers }, | 366 | { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, |
362 | { "denyusers", sDenyUsers }, | 367 | { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, |
363 | { "allowgroups", sAllowGroups }, | 368 | { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, |
364 | { "denygroups", sDenyGroups }, | 369 | { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, |
365 | { "ciphers", sCiphers }, | 370 | { "ciphers", sCiphers, SSHCFG_GLOBAL }, |
366 | { "macs", sMacs }, | 371 | { "macs", sMacs, SSHCFG_GLOBAL }, |
367 | { "protocol", sProtocol }, | 372 | { "protocol", sProtocol, SSHCFG_GLOBAL }, |
368 | { "gatewayports", sGatewayPorts }, | 373 | { "gatewayports", sGatewayPorts, SSHCFG_ALL }, |
369 | { "subsystem", sSubsystem }, | 374 | { "subsystem", sSubsystem, SSHCFG_GLOBAL }, |
370 | { "maxstartups", sMaxStartups }, | 375 | { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, |
371 | { "maxauthtries", sMaxAuthTries }, | 376 | { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL }, |
372 | { "banner", sBanner }, | 377 | { "banner", sBanner, SSHCFG_GLOBAL }, |
373 | { "usedns", sUseDNS }, | 378 | { "usedns", sUseDNS, SSHCFG_GLOBAL }, |
374 | { "verifyreversemapping", sDeprecated }, | 379 | { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, |
375 | { "reversemappingcheck", sDeprecated }, | 380 | { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, |
376 | { "clientaliveinterval", sClientAliveInterval }, | 381 | { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, |
377 | { "clientalivecountmax", sClientAliveCountMax }, | 382 | { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, |
378 | { "authorizedkeysfile", sAuthorizedKeysFile }, | 383 | { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, |
379 | { "authorizedkeysfile2", sAuthorizedKeysFile2 }, | 384 | { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, |
380 | { "useprivilegeseparation", sUsePrivilegeSeparation}, | 385 | { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, |
381 | { "acceptenv", sAcceptEnv }, | 386 | { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, |
382 | { "permittunnel", sPermitTunnel }, | 387 | { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL }, |
383 | { NULL, sBadOption } | 388 | { NULL, sBadOption, 0 } |
384 | }; | 389 | }; |
385 | 390 | ||
386 | /* | 391 | /* |
@@ -389,13 +394,15 @@ static struct { | |||
389 | 394 | ||
390 | static ServerOpCodes | 395 | static ServerOpCodes |
391 | parse_token(const char *cp, const char *filename, | 396 | parse_token(const char *cp, const char *filename, |
392 | int linenum) | 397 | int linenum, u_int *flags) |
393 | { | 398 | { |
394 | u_int i; | 399 | u_int i; |
395 | 400 | ||
396 | for (i = 0; keywords[i].name; i++) | 401 | for (i = 0; keywords[i].name; i++) |
397 | if (strcasecmp(cp, keywords[i].name) == 0) | 402 | if (strcasecmp(cp, keywords[i].name) == 0) { |
403 | *flags = keywords[i].flags; | ||
398 | return keywords[i].opcode; | 404 | return keywords[i].opcode; |
405 | } | ||
399 | 406 | ||
400 | error("%s: line %d: Bad configuration option: %s", | 407 | error("%s: line %d: Bad configuration option: %s", |
401 | filename, linenum, cp); | 408 | filename, linenum, cp); |
@@ -440,15 +447,112 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port) | |||
440 | options->listen_addrs = aitop; | 447 | options->listen_addrs = aitop; |
441 | } | 448 | } |
442 | 449 | ||
450 | /* | ||
451 | * The strategy for the Match blocks is that the config file is parsed twice. | ||
452 | * | ||
453 | * The first time is at startup. activep is initialized to 1 and the | ||
454 | * directives in the global context are processed and acted on. Hitting a | ||
455 | * Match directive unsets activep and the directives inside the block are | ||
456 | * checked for syntax only. | ||
457 | * | ||
458 | * The second time is after a connection has been established but before | ||
459 | * authentication. activep is initialized to 2 and global config directives | ||
460 | * are ignored since they have already been processed. If the criteria in a | ||
461 | * Match block is met, activep is set and the subsequent directives | ||
462 | * processed and actioned until EOF or another Match block unsets it. Any | ||
463 | * options set are copied into the main server config. | ||
464 | * | ||
465 | * Potential additions/improvements: | ||
466 | * - Add Match support for pre-kex directives, eg Protocol, Ciphers. | ||
467 | * | ||
468 | * - Add a Tag directive (idea from David Leonard) ala pf, eg: | ||
469 | * Match Address 192.168.0.* | ||
470 | * Tag trusted | ||
471 | * Match Group wheel | ||
472 | * Tag trusted | ||
473 | * Match Tag trusted | ||
474 | * AllowTcpForwarding yes | ||
475 | * GatewayPorts clientspecified | ||
476 | * [...] | ||
477 | * | ||
478 | * - Add a PermittedChannelRequests directive | ||
479 | * Match Group shell | ||
480 | * PermittedChannelRequests session,forwarded-tcpip | ||
481 | */ | ||
482 | |||
483 | static int | ||
484 | match_cfg_line(char **condition, int line, const char *user, const char *host, | ||
485 | const char *address) | ||
486 | { | ||
487 | int result = 1; | ||
488 | char *arg, *attrib, *cp = *condition; | ||
489 | size_t len; | ||
490 | |||
491 | if (user == NULL) | ||
492 | debug3("checking syntax for 'Match %s'", cp); | ||
493 | else | ||
494 | debug3("checking match for '%s' user %s host %s addr %s", cp, | ||
495 | user ? user : "(null)", host ? host : "(null)", | ||
496 | address ? address : "(null)"); | ||
497 | |||
498 | while ((attrib = strdelim(&cp)) && *attrib != '\0') { | ||
499 | if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { | ||
500 | error("Missing Match criteria for %s", attrib); | ||
501 | return -1; | ||
502 | } | ||
503 | len = strlen(arg); | ||
504 | if (strcasecmp(attrib, "user") == 0) { | ||
505 | if (!user) { | ||
506 | result = 0; | ||
507 | continue; | ||
508 | } | ||
509 | if (match_pattern_list(user, arg, len, 0) != 1) | ||
510 | result = 0; | ||
511 | else | ||
512 | debug("user %.100s matched 'User %.100s' at " | ||
513 | "line %d", user, arg, line); | ||
514 | } else if (strcasecmp(attrib, "host") == 0) { | ||
515 | if (!host) { | ||
516 | result = 0; | ||
517 | continue; | ||
518 | } | ||
519 | if (match_hostname(host, arg, len) != 1) | ||
520 | result = 0; | ||
521 | else | ||
522 | debug("connection from %.100s matched 'Host " | ||
523 | "%.100s' at line %d", host, arg, line); | ||
524 | } else if (strcasecmp(attrib, "address") == 0) { | ||
525 | debug("address '%s' arg '%s'", address, arg); | ||
526 | if (!address) { | ||
527 | result = 0; | ||
528 | continue; | ||
529 | } | ||
530 | if (match_hostname(address, arg, len) != 1) | ||
531 | result = 0; | ||
532 | else | ||
533 | debug("connection from %.100s matched 'Address " | ||
534 | "%.100s' at line %d", address, arg, line); | ||
535 | } else { | ||
536 | error("Unsupported Match attribute %s", attrib); | ||
537 | return -1; | ||
538 | } | ||
539 | } | ||
540 | if (user != NULL) | ||
541 | debug3("match %sfound", result ? "" : "not "); | ||
542 | *condition = cp; | ||
543 | return result; | ||
544 | } | ||
545 | |||
443 | int | 546 | int |
444 | process_server_config_line(ServerOptions *options, char *line, | 547 | process_server_config_line(ServerOptions *options, char *line, |
445 | const char *filename, int linenum) | 548 | const char *filename, int linenum, int *activep, const char *user, |
549 | const char *host, const char *address) | ||
446 | { | 550 | { |
447 | char *cp, **charptr, *arg, *p; | 551 | char *cp, **charptr, *arg, *p; |
448 | int *intptr, value, n; | 552 | int cmdline = 0, *intptr, value, n; |
449 | ServerOpCodes opcode; | 553 | ServerOpCodes opcode; |
450 | u_short port; | 554 | u_short port; |
451 | u_int i; | 555 | u_int i, flags = 0; |
452 | size_t len; | 556 | size_t len; |
453 | 557 | ||
454 | cp = line; | 558 | cp = line; |
@@ -461,7 +565,25 @@ process_server_config_line(ServerOptions *options, char *line, | |||
461 | return 0; | 565 | return 0; |
462 | intptr = NULL; | 566 | intptr = NULL; |
463 | charptr = NULL; | 567 | charptr = NULL; |
464 | opcode = parse_token(arg, filename, linenum); | 568 | opcode = parse_token(arg, filename, linenum, &flags); |
569 | |||
570 | if (activep == NULL) { /* We are processing a command line directive */ | ||
571 | cmdline = 1; | ||
572 | activep = &cmdline; | ||
573 | } | ||
574 | if (*activep && opcode != sMatch) | ||
575 | debug3("%s:%d setting %s %s", filename, linenum, arg, cp); | ||
576 | if (*activep == 0 && !(flags & SSHCFG_MATCH)) { | ||
577 | if (user == NULL) { | ||
578 | fatal("%s line %d: Directive '%s' is not allowed " | ||
579 | "within a Match block", filename, linenum, arg); | ||
580 | } else { /* this is a directive we have already processed */ | ||
581 | while (arg) | ||
582 | arg = strdelim(&cp); | ||
583 | return 0; | ||
584 | } | ||
585 | } | ||
586 | |||
465 | switch (opcode) { | 587 | switch (opcode) { |
466 | /* Portable-specific options */ | 588 | /* Portable-specific options */ |
467 | case sUsePAM: | 589 | case sUsePAM: |
@@ -499,7 +621,7 @@ parse_int: | |||
499 | fatal("%s line %d: missing integer value.", | 621 | fatal("%s line %d: missing integer value.", |
500 | filename, linenum); | 622 | filename, linenum); |
501 | value = atoi(arg); | 623 | value = atoi(arg); |
502 | if (*intptr == -1) | 624 | if (*activep && *intptr == -1) |
503 | *intptr = value; | 625 | *intptr = value; |
504 | break; | 626 | break; |
505 | 627 | ||
@@ -579,7 +701,7 @@ parse_filename: | |||
579 | if (!arg || *arg == '\0') | 701 | if (!arg || *arg == '\0') |
580 | fatal("%s line %d: missing file name.", | 702 | fatal("%s line %d: missing file name.", |
581 | filename, linenum); | 703 | filename, linenum); |
582 | if (*charptr == NULL) { | 704 | if (*activep && *charptr == NULL) { |
583 | *charptr = tilde_expand_filename(arg, getuid()); | 705 | *charptr = tilde_expand_filename(arg, getuid()); |
584 | /* increase optional counter */ | 706 | /* increase optional counter */ |
585 | if (intptr != NULL) | 707 | if (intptr != NULL) |
@@ -630,7 +752,7 @@ parse_flag: | |||
630 | else | 752 | else |
631 | fatal("%s line %d: Bad yes/no argument: %s", | 753 | fatal("%s line %d: Bad yes/no argument: %s", |
632 | filename, linenum, arg); | 754 | filename, linenum, arg); |
633 | if (*intptr == -1) | 755 | if (*activep && *intptr == -1) |
634 | *intptr = value; | 756 | *intptr = value; |
635 | break; | 757 | break; |
636 | 758 | ||
@@ -895,6 +1017,10 @@ parse_flag: | |||
895 | if (!arg || *arg == '\0') | 1017 | if (!arg || *arg == '\0') |
896 | fatal("%s line %d: Missing subsystem name.", | 1018 | fatal("%s line %d: Missing subsystem name.", |
897 | filename, linenum); | 1019 | filename, linenum); |
1020 | if (!*activep) { | ||
1021 | arg = strdelim(&cp); | ||
1022 | break; | ||
1023 | } | ||
898 | for (i = 0; i < options->num_subsystems; i++) | 1024 | for (i = 0; i < options->num_subsystems; i++) |
899 | if (strcmp(arg, options->subsystem_name[i]) == 0) | 1025 | if (strcmp(arg, options->subsystem_name[i]) == 0) |
900 | fatal("%s line %d: Subsystem '%s' already defined.", | 1026 | fatal("%s line %d: Subsystem '%s' already defined.", |
@@ -977,6 +1103,8 @@ parse_flag: | |||
977 | if (options->num_accept_env >= MAX_ACCEPT_ENV) | 1103 | if (options->num_accept_env >= MAX_ACCEPT_ENV) |
978 | fatal("%s line %d: too many allow env.", | 1104 | fatal("%s line %d: too many allow env.", |
979 | filename, linenum); | 1105 | filename, linenum); |
1106 | if (!*activep) | ||
1107 | break; | ||
980 | options->accept_env[options->num_accept_env++] = | 1108 | options->accept_env[options->num_accept_env++] = |
981 | xstrdup(arg); | 1109 | xstrdup(arg); |
982 | } | 1110 | } |
@@ -1004,6 +1132,17 @@ parse_flag: | |||
1004 | *intptr = value; | 1132 | *intptr = value; |
1005 | break; | 1133 | break; |
1006 | 1134 | ||
1135 | case sMatch: | ||
1136 | if (cmdline) | ||
1137 | fatal("Match directive not supported as a command-line " | ||
1138 | "option"); | ||
1139 | value = match_cfg_line(&cp, linenum, user, host, address); | ||
1140 | if (value < 0) | ||
1141 | fatal("%s line %d: Bad Match condition", filename, | ||
1142 | linenum); | ||
1143 | *activep = value; | ||
1144 | break; | ||
1145 | |||
1007 | case sDeprecated: | 1146 | case sDeprecated: |
1008 | logit("%s line %d: Deprecated option %s", | 1147 | logit("%s line %d: Deprecated option %s", |
1009 | filename, linenum, arg); | 1148 | filename, linenum, arg); |
@@ -1060,18 +1199,41 @@ load_server_config(const char *filename, Buffer *conf) | |||
1060 | } | 1199 | } |
1061 | 1200 | ||
1062 | void | 1201 | void |
1063 | parse_server_config(ServerOptions *options, const char *filename, Buffer *conf) | 1202 | parse_server_match_config(ServerOptions *options, const char *user, |
1203 | const char *host, const char *address) | ||
1204 | { | ||
1205 | ServerOptions mo; | ||
1206 | |||
1207 | initialize_server_options(&mo); | ||
1208 | parse_server_config(&mo, "reprocess config", &cfg, user, host, address); | ||
1209 | copy_set_server_options(options, &mo); | ||
1210 | } | ||
1211 | |||
1212 | /* Copy any (supported) values that are set */ | ||
1213 | void | ||
1214 | copy_set_server_options(ServerOptions *dst, ServerOptions *src) | ||
1215 | { | ||
1216 | if (src->allow_tcp_forwarding != -1) | ||
1217 | dst->allow_tcp_forwarding = src->allow_tcp_forwarding; | ||
1218 | if (src->gateway_ports != -1) | ||
1219 | dst->gateway_ports = src->gateway_ports; | ||
1220 | } | ||
1221 | |||
1222 | void | ||
1223 | parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, | ||
1224 | const char *user, const char *host, const char *address) | ||
1064 | { | 1225 | { |
1065 | int linenum, bad_options = 0; | 1226 | int active, linenum, bad_options = 0; |
1066 | char *cp, *obuf, *cbuf; | 1227 | char *cp, *obuf, *cbuf; |
1067 | 1228 | ||
1068 | debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); | 1229 | debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); |
1069 | 1230 | ||
1070 | obuf = cbuf = xstrdup(buffer_ptr(conf)); | 1231 | obuf = cbuf = xstrdup(buffer_ptr(conf)); |
1232 | active = user ? 0 : 1; | ||
1071 | linenum = 1; | 1233 | linenum = 1; |
1072 | while ((cp = strsep(&cbuf, "\n")) != NULL) { | 1234 | while ((cp = strsep(&cbuf, "\n")) != NULL) { |
1073 | if (process_server_config_line(options, cp, filename, | 1235 | if (process_server_config_line(options, cp, filename, |
1074 | linenum++) != 0) | 1236 | linenum++, &active, user, host, address) != 0) |
1075 | bad_options++; | 1237 | bad_options++; |
1076 | } | 1238 | } |
1077 | xfree(obuf); | 1239 | xfree(obuf); |
diff --git a/servconf.h b/servconf.h index 671050e4c..a74716e6f 100644 --- a/servconf.h +++ b/servconf.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: servconf.h,v 1.74 2006/07/06 10:47:05 djm Exp $ */ | 1 | /* $OpenBSD: servconf.h,v 1.75 2006/07/12 11:34:58 dtucker Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -142,8 +142,13 @@ typedef struct { | |||
142 | 142 | ||
143 | void initialize_server_options(ServerOptions *); | 143 | void initialize_server_options(ServerOptions *); |
144 | void fill_default_server_options(ServerOptions *); | 144 | void fill_default_server_options(ServerOptions *); |
145 | int process_server_config_line(ServerOptions *, char *, const char *, int); | 145 | int process_server_config_line(ServerOptions *, char *, const char *, int, |
146 | int *, const char *, const char *, const char *); | ||
146 | void load_server_config(const char *, Buffer *); | 147 | void load_server_config(const char *, Buffer *); |
147 | void parse_server_config(ServerOptions *, const char *, Buffer *); | 148 | void parse_server_config(ServerOptions *, const char *, Buffer *, |
149 | const char *, const char *, const char *); | ||
150 | void parse_server_match_config(ServerOptions *, const char *, const char *, | ||
151 | const char *); | ||
152 | void copy_set_server_options(ServerOptions *, ServerOptions *); | ||
148 | 153 | ||
149 | #endif /* SERVCONF_H */ | 154 | #endif /* SERVCONF_H */ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.336 2006/07/11 20:07:25 stevesk Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.337 2006/07/12 11:34:58 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -219,12 +219,15 @@ int *startup_pipes = NULL; | |||
219 | int startup_pipe; /* in child */ | 219 | int startup_pipe; /* in child */ |
220 | 220 | ||
221 | /* variables used for privilege separation */ | 221 | /* variables used for privilege separation */ |
222 | int use_privsep; | 222 | int use_privsep = -1; |
223 | struct monitor *pmonitor = NULL; | 223 | struct monitor *pmonitor = NULL; |
224 | 224 | ||
225 | /* global authentication context */ | 225 | /* global authentication context */ |
226 | Authctxt *the_authctxt = NULL; | 226 | Authctxt *the_authctxt = NULL; |
227 | 227 | ||
228 | /* sshd_config buffer */ | ||
229 | Buffer cfg; | ||
230 | |||
228 | /* message to be displayed after login */ | 231 | /* message to be displayed after login */ |
229 | Buffer loginmsg; | 232 | Buffer loginmsg; |
230 | 233 | ||
@@ -916,7 +919,6 @@ main(int ac, char **av) | |||
916 | Key *key; | 919 | Key *key; |
917 | Authctxt *authctxt; | 920 | Authctxt *authctxt; |
918 | int ret, key_used = 0; | 921 | int ret, key_used = 0; |
919 | Buffer cfg; | ||
920 | 922 | ||
921 | #ifdef HAVE_SECUREWARE | 923 | #ifdef HAVE_SECUREWARE |
922 | (void)set_auth_parameters(ac, av); | 924 | (void)set_auth_parameters(ac, av); |
@@ -1036,7 +1038,7 @@ main(int ac, char **av) | |||
1036 | case 'o': | 1038 | case 'o': |
1037 | line = xstrdup(optarg); | 1039 | line = xstrdup(optarg); |
1038 | if (process_server_config_line(&options, line, | 1040 | if (process_server_config_line(&options, line, |
1039 | "command-line", 0) != 0) | 1041 | "command-line", 0, NULL, NULL, NULL, NULL) != 0) |
1040 | exit(1); | 1042 | exit(1); |
1041 | xfree(line); | 1043 | xfree(line); |
1042 | break; | 1044 | break; |
@@ -1094,11 +1096,8 @@ main(int ac, char **av) | |||
1094 | else | 1096 | else |
1095 | load_server_config(config_file_name, &cfg); | 1097 | load_server_config(config_file_name, &cfg); |
1096 | 1098 | ||
1097 | parse_server_config(&options, | 1099 | parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, |
1098 | rexeced_flag ? "rexec" : config_file_name, &cfg); | 1100 | &cfg, NULL, NULL, NULL); |
1099 | |||
1100 | if (!rexec_flag) | ||
1101 | buffer_free(&cfg); | ||
1102 | 1101 | ||
1103 | seed_rng(); | 1102 | seed_rng(); |
1104 | 1103 | ||
diff --git a/sshd_config.5 b/sshd_config.5 index 3b639b17d..0b2646027 100644 --- a/sshd_config.5 +++ b/sshd_config.5 | |||
@@ -34,7 +34,7 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .\" $OpenBSD: sshd_config.5,v 1.59 2006/07/06 10:47:05 djm Exp $ | 37 | .\" $OpenBSD: sshd_config.5,v 1.60 2006/07/12 11:34:58 dtucker Exp $ |
38 | .Dd September 25, 1999 | 38 | .Dd September 25, 1999 |
39 | .Dt SSHD_CONFIG 5 | 39 | .Dt SSHD_CONFIG 5 |
40 | .Os | 40 | .Os |
@@ -463,6 +463,27 @@ for data integrity protection. | |||
463 | Multiple algorithms must be comma-separated. | 463 | Multiple algorithms must be comma-separated. |
464 | The default is: | 464 | The default is: |
465 | .Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 . | 465 | .Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 . |
466 | .It Cm Match | ||
467 | Introduces a conditional block. Keywords on lines following a | ||
468 | .Cm Match | ||
469 | block are only applied if all of the criteria on the | ||
470 | .Cm Match | ||
471 | are satisfied. | ||
472 | The the arguments to | ||
473 | .Cm Match | ||
474 | block are one or more criteria-pattern pairs. | ||
475 | The available criteria are | ||
476 | .Cm User , | ||
477 | .Cm Host , | ||
478 | and | ||
479 | .Cm Address . | ||
480 | Only a subset of keywords may be used on the lines following a | ||
481 | .Cm Match | ||
482 | keyword. | ||
483 | Available keywords are | ||
484 | .Cm AllowTcpForwarding , | ||
485 | and | ||
486 | .Cm GatewayPorts . | ||
466 | .It Cm MaxAuthTries | 487 | .It Cm MaxAuthTries |
467 | Specifies the maximum number of authentication attempts permitted per | 488 | Specifies the maximum number of authentication attempts permitted per |
468 | connection. | 489 | connection. |