|
Lines 150-156
typedef enum {
Link Here
|
| 150 |
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, |
150 |
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, |
| 151 |
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
151 |
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
| 152 |
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
152 |
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
| 153 |
oStreamLocalBindMask, oStreamLocalBindUnlink, |
153 |
oStreamLocalBindMask, oStreamLocalBindUnlink, oRereadConfig, |
| 154 |
oIgnoredUnknownOption, oDeprecated, oUnsupported |
154 |
oIgnoredUnknownOption, oDeprecated, oUnsupported |
| 155 |
} OpCodes; |
155 |
} OpCodes; |
| 156 |
|
156 |
|
|
Lines 266-271
static struct {
Link Here
|
| 266 |
{ "streamlocalbindmask", oStreamLocalBindMask }, |
266 |
{ "streamlocalbindmask", oStreamLocalBindMask }, |
| 267 |
{ "streamlocalbindunlink", oStreamLocalBindUnlink }, |
267 |
{ "streamlocalbindunlink", oStreamLocalBindUnlink }, |
| 268 |
{ "ignoreunknown", oIgnoreUnknown }, |
268 |
{ "ignoreunknown", oIgnoreUnknown }, |
|
|
269 |
{ "rereadconfig", oRereadConfig }, |
| 269 |
|
270 |
|
| 270 |
{ NULL, oBadOption } |
271 |
{ NULL, oBadOption } |
| 271 |
}; |
272 |
}; |
|
Lines 476-486
execute_in_shell(const char *cmd)
Link Here
|
| 476 |
*/ |
477 |
*/ |
| 477 |
static int |
478 |
static int |
| 478 |
match_cfg_line(Options *options, char **condition, struct passwd *pw, |
479 |
match_cfg_line(Options *options, char **condition, struct passwd *pw, |
| 479 |
const char *host_arg, const char *filename, int linenum) |
480 |
const char *host_arg, const char *original_host, int post_canon, |
|
|
481 |
const char *filename, int linenum) |
| 480 |
{ |
482 |
{ |
| 481 |
char *arg, *attrib, *cmd, *cp = *condition, *host; |
483 |
char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; |
| 482 |
const char *ruser; |
484 |
const char *ruser; |
| 483 |
int r, port, result = 1, attributes = 0; |
485 |
int r, port, this_result, result = 1, attributes = 0, negate; |
| 484 |
size_t len; |
486 |
size_t len; |
| 485 |
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
487 |
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
| 486 |
|
488 |
|
|
Lines 497-517
match_cfg_line(Options *options, char **
Link Here
|
| 497 |
} else |
499 |
} else |
| 498 |
host = xstrdup(host_arg); |
500 |
host = xstrdup(host_arg); |
| 499 |
|
501 |
|
| 500 |
debug3("checking match for '%s' host %s", cp, host); |
502 |
debug2("checking match for '%s' host %s originally %s", |
| 501 |
while ((attrib = strdelim(&cp)) && *attrib != '\0') { |
503 |
cp, host, original_host); |
|
|
504 |
while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { |
| 505 |
criteria = NULL; |
| 506 |
this_result = 1; |
| 502 |
attributes++; |
507 |
attributes++; |
|
|
508 |
negate = attrib[0] == '!'; |
| 509 |
if (negate) |
| 510 |
attrib++; |
| 511 |
/* criteria "all" and "canonical" have no argument */ |
| 503 |
if (strcasecmp(attrib, "all") == 0) { |
512 |
if (strcasecmp(attrib, "all") == 0) { |
| 504 |
if (attributes != 1 || |
513 |
if (attributes != 1 || |
| 505 |
((arg = strdelim(&cp)) != NULL && *arg != '\0')) { |
514 |
((arg = strdelim(&cp)) != NULL && *arg != '\0')) { |
| 506 |
error("'all' cannot be combined with other " |
515 |
error("%.200s line %d: '%s' cannot be combined " |
| 507 |
"Match attributes"); |
516 |
"with other Match attributes", |
|
|
517 |
filename, linenum, oattrib); |
| 508 |
result = -1; |
518 |
result = -1; |
| 509 |
goto out; |
519 |
goto out; |
| 510 |
} |
520 |
} |
| 511 |
*condition = cp; |
521 |
*condition = cp; |
| 512 |
result = 1; |
522 |
result = negate ? 0 : 1; |
| 513 |
goto out; |
523 |
goto out; |
|
|
524 |
} else if (strcasecmp(attrib, "canonical") == 0) { |
| 525 |
r = !!post_canon; /* force bitmask member to boolean */ |
| 526 |
if (r == (negate ? 1 : 0)) |
| 527 |
this_result = result = 0; |
| 528 |
debug3("%.200s line %d: %smatched '%s'", |
| 529 |
filename, linenum, |
| 530 |
this_result ? "" : "not ", oattrib); |
| 531 |
continue; |
| 514 |
} |
532 |
} |
|
|
533 |
/* All other criteria require an argument */ |
| 515 |
if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { |
534 |
if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { |
| 516 |
error("Missing Match criteria for %s", attrib); |
535 |
error("Missing Match criteria for %s", attrib); |
| 517 |
result = -1; |
536 |
result = -1; |
|
Lines 519-549
match_cfg_line(Options *options, char **
Link Here
|
| 519 |
} |
538 |
} |
| 520 |
len = strlen(arg); |
539 |
len = strlen(arg); |
| 521 |
if (strcasecmp(attrib, "host") == 0) { |
540 |
if (strcasecmp(attrib, "host") == 0) { |
| 522 |
if (match_hostname(host, arg, len) != 1) |
541 |
criteria = xstrdup(host); |
| 523 |
result = 0; |
542 |
r = match_hostname(host, arg, len) == 1; |
| 524 |
else |
543 |
if (r == (negate ? 1 : 0)) |
| 525 |
debug("%.200s line %d: matched 'Host %.100s' ", |
544 |
this_result = result = 0; |
| 526 |
filename, linenum, host); |
|
|
| 527 |
} else if (strcasecmp(attrib, "originalhost") == 0) { |
545 |
} else if (strcasecmp(attrib, "originalhost") == 0) { |
| 528 |
if (match_hostname(host_arg, arg, len) != 1) |
546 |
criteria = xstrdup(original_host); |
| 529 |
result = 0; |
547 |
r = match_hostname(original_host, arg, len) == 1; |
| 530 |
else |
548 |
if (r == (negate ? 1 : 0)) |
| 531 |
debug("%.200s line %d: matched " |
549 |
this_result = result = 0; |
| 532 |
"'OriginalHost %.100s' ", |
|
|
| 533 |
filename, linenum, host_arg); |
| 534 |
} else if (strcasecmp(attrib, "user") == 0) { |
550 |
} else if (strcasecmp(attrib, "user") == 0) { |
| 535 |
if (match_pattern_list(ruser, arg, len, 0) != 1) |
551 |
criteria = xstrdup(ruser); |
| 536 |
result = 0; |
552 |
r = match_pattern_list(ruser, arg, len, 0) == 1; |
| 537 |
else |
553 |
if (r == (negate ? 1 : 0)) |
| 538 |
debug("%.200s line %d: matched 'User %.100s' ", |
554 |
this_result = result = 0; |
| 539 |
filename, linenum, ruser); |
|
|
| 540 |
} else if (strcasecmp(attrib, "localuser") == 0) { |
555 |
} else if (strcasecmp(attrib, "localuser") == 0) { |
| 541 |
if (match_pattern_list(pw->pw_name, arg, len, 0) != 1) |
556 |
criteria = xstrdup(pw->pw_name); |
| 542 |
result = 0; |
557 |
r = match_pattern_list(pw->pw_name, arg, len, 0) == 1; |
| 543 |
else |
558 |
if (r == (negate ? 1 : 0)) |
| 544 |
debug("%.200s line %d: matched " |
559 |
this_result = result = 0; |
| 545 |
"'LocalUser %.100s' ", |
|
|
| 546 |
filename, linenum, pw->pw_name); |
| 547 |
} else if (strcasecmp(attrib, "exec") == 0) { |
560 |
} else if (strcasecmp(attrib, "exec") == 0) { |
| 548 |
if (gethostname(thishost, sizeof(thishost)) == -1) |
561 |
if (gethostname(thishost, sizeof(thishost)) == -1) |
| 549 |
fatal("gethostname: %s", strerror(errno)); |
562 |
fatal("gethostname: %s", strerror(errno)); |
|
Lines 556-600
match_cfg_line(Options *options, char **
Link Here
|
| 556 |
"d", pw->pw_dir, |
569 |
"d", pw->pw_dir, |
| 557 |
"h", host, |
570 |
"h", host, |
| 558 |
"l", thishost, |
571 |
"l", thishost, |
| 559 |
"n", host_arg, |
572 |
"n", original_host, |
| 560 |
"p", portstr, |
573 |
"p", portstr, |
| 561 |
"r", ruser, |
574 |
"r", ruser, |
| 562 |
"u", pw->pw_name, |
575 |
"u", pw->pw_name, |
| 563 |
(char *)NULL); |
576 |
(char *)NULL); |
| 564 |
if (result != 1) { |
577 |
if (result != 1) { |
| 565 |
/* skip execution if prior predicate failed */ |
578 |
/* skip execution if prior predicate failed */ |
| 566 |
debug("%.200s line %d: skipped exec \"%.100s\"", |
579 |
debug3("%.200s line %d: skipped exec " |
| 567 |
filename, linenum, cmd); |
580 |
"\"%.100s\"", filename, linenum, cmd); |
| 568 |
} else { |
581 |
free(cmd); |
| 569 |
r = execute_in_shell(cmd); |
582 |
continue; |
| 570 |
if (r == -1) { |
|
|
| 571 |
fatal("%.200s line %d: match exec " |
| 572 |
"'%.100s' error", filename, |
| 573 |
linenum, cmd); |
| 574 |
} else if (r == 0) { |
| 575 |
debug("%.200s line %d: matched " |
| 576 |
"'exec \"%.100s\"'", filename, |
| 577 |
linenum, cmd); |
| 578 |
} else { |
| 579 |
debug("%.200s line %d: no match " |
| 580 |
"'exec \"%.100s\"'", filename, |
| 581 |
linenum, cmd); |
| 582 |
result = 0; |
| 583 |
} |
| 584 |
} |
583 |
} |
|
|
584 |
r = execute_in_shell(cmd); |
| 585 |
if (r == -1) { |
| 586 |
fatal("%.200s line %d: match exec " |
| 587 |
"'%.100s' error", filename, |
| 588 |
linenum, cmd); |
| 589 |
} |
| 590 |
criteria = xstrdup(cmd); |
| 585 |
free(cmd); |
591 |
free(cmd); |
|
|
592 |
/* Force exit status to boolean */ |
| 593 |
r = r == 0; |
| 594 |
if (r == (negate ? 1 : 0)) |
| 595 |
this_result = result = 0; |
| 586 |
} else { |
596 |
} else { |
| 587 |
error("Unsupported Match attribute %s", attrib); |
597 |
error("Unsupported Match attribute %s", attrib); |
| 588 |
result = -1; |
598 |
result = -1; |
| 589 |
goto out; |
599 |
goto out; |
| 590 |
} |
600 |
} |
|
|
601 |
debug3("%.200s line %d: %smatched '%s \"%.100s\"' ", |
| 602 |
filename, linenum, this_result ? "": "not ", |
| 603 |
oattrib, criteria); |
| 604 |
free(criteria); |
| 591 |
} |
605 |
} |
| 592 |
if (attributes == 0) { |
606 |
if (attributes == 0) { |
| 593 |
error("One or more attributes required for Match"); |
607 |
error("One or more attributes required for Match"); |
| 594 |
result = -1; |
608 |
result = -1; |
| 595 |
goto out; |
609 |
goto out; |
| 596 |
} |
610 |
} |
| 597 |
debug3("match %sfound", result ? "" : "not "); |
611 |
debug2("match %sfound", result ? "" : "not "); |
| 598 |
*condition = cp; |
612 |
*condition = cp; |
| 599 |
out: |
613 |
out: |
| 600 |
free(host); |
614 |
free(host); |
|
Lines 711-716
static const struct multistate multistat
Link Here
|
| 711 |
{ "always", SSH_CANONICALISE_ALWAYS }, |
725 |
{ "always", SSH_CANONICALISE_ALWAYS }, |
| 712 |
{ NULL, -1 } |
726 |
{ NULL, -1 } |
| 713 |
}; |
727 |
}; |
|
|
728 |
static const struct multistate multistate_reread_config[] = { |
| 729 |
{ "true", SSH_REREAD_YES }, |
| 730 |
{ "false", SSH_REREAD_NO }, |
| 731 |
{ "yes", SSH_REREAD_YES }, |
| 732 |
{ "no", SSH_REREAD_NO }, |
| 733 |
{ "if-canon", SSH_REREAD_CANON }, |
| 734 |
{ NULL, -1 } |
| 735 |
}; |
| 714 |
|
736 |
|
| 715 |
/* |
737 |
/* |
| 716 |
* Processes a single option line as used in the configuration files. This |
738 |
* Processes a single option line as used in the configuration files. This |
|
Lines 719-725
static const struct multistate multistat
Link Here
|
| 719 |
#define WHITESPACE " \t\r\n" |
741 |
#define WHITESPACE " \t\r\n" |
| 720 |
int |
742 |
int |
| 721 |
process_config_line(Options *options, struct passwd *pw, const char *host, |
743 |
process_config_line(Options *options, struct passwd *pw, const char *host, |
| 722 |
char *line, const char *filename, int linenum, int *activep, int userconfig) |
744 |
const char *original_host, char *line, const char *filename, |
|
|
745 |
int linenum, int *activep, int flags) |
| 723 |
{ |
746 |
{ |
| 724 |
char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; |
747 |
char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; |
| 725 |
char **cpptr, fwdarg[256]; |
748 |
char **cpptr, fwdarg[256]; |
|
Lines 947-953
parse_time:
Link Here
|
| 947 |
if (*intptr >= SSH_MAX_IDENTITY_FILES) |
970 |
if (*intptr >= SSH_MAX_IDENTITY_FILES) |
| 948 |
fatal("%.200s line %d: Too many identity files specified (max %d).", |
971 |
fatal("%.200s line %d: Too many identity files specified (max %d).", |
| 949 |
filename, linenum, SSH_MAX_IDENTITY_FILES); |
972 |
filename, linenum, SSH_MAX_IDENTITY_FILES); |
| 950 |
add_identity_file(options, NULL, arg, userconfig); |
973 |
add_identity_file(options, NULL, |
|
|
974 |
arg, flags & SSHCONF_USERCONF); |
| 951 |
} |
975 |
} |
| 952 |
break; |
976 |
break; |
| 953 |
|
977 |
|
|
Lines 1195-1202
parse_int:
Link Here
|
| 1195 |
if (cmdline) |
1219 |
if (cmdline) |
| 1196 |
fatal("Host directive not supported as a command-line " |
1220 |
fatal("Host directive not supported as a command-line " |
| 1197 |
"option"); |
1221 |
"option"); |
| 1198 |
value = match_cfg_line(options, &s, pw, host, |
1222 |
value = match_cfg_line(options, &s, pw, host, original_host, |
| 1199 |
filename, linenum); |
1223 |
flags & SSHCONF_POSTCANON, filename, linenum); |
| 1200 |
if (value < 0) |
1224 |
if (value < 0) |
| 1201 |
fatal("%.200s line %d: Bad Match condition", filename, |
1225 |
fatal("%.200s line %d: Bad Match condition", filename, |
| 1202 |
linenum); |
1226 |
linenum); |
|
Lines 1433-1438
parse_int:
Link Here
|
| 1433 |
intptr = &options->fwd_opts.streamlocal_bind_unlink; |
1457 |
intptr = &options->fwd_opts.streamlocal_bind_unlink; |
| 1434 |
goto parse_flag; |
1458 |
goto parse_flag; |
| 1435 |
|
1459 |
|
|
|
1460 |
case oRereadConfig: |
| 1461 |
intptr = &options->reread_config; |
| 1462 |
multistate_ptr = multistate_reread_config; |
| 1463 |
goto parse_multistate; |
| 1464 |
|
| 1436 |
case oDeprecated: |
1465 |
case oDeprecated: |
| 1437 |
debug("%s line %d: Deprecated option \"%s\"", |
1466 |
debug("%s line %d: Deprecated option \"%s\"", |
| 1438 |
filename, linenum, keyword); |
1467 |
filename, linenum, keyword); |
|
Lines 1444-1450
parse_int:
Link Here
|
| 1444 |
return 0; |
1473 |
return 0; |
| 1445 |
|
1474 |
|
| 1446 |
default: |
1475 |
default: |
| 1447 |
fatal("process_config_line: Unimplemented opcode %d", opcode); |
1476 |
fatal("%s: Unimplemented opcode %d", __func__, opcode); |
| 1448 |
} |
1477 |
} |
| 1449 |
|
1478 |
|
| 1450 |
/* Check that there is no garbage at end of line. */ |
1479 |
/* Check that there is no garbage at end of line. */ |
|
Lines 1464-1470
parse_int:
Link Here
|
| 1464 |
|
1493 |
|
| 1465 |
int |
1494 |
int |
| 1466 |
read_config_file(const char *filename, struct passwd *pw, const char *host, |
1495 |
read_config_file(const char *filename, struct passwd *pw, const char *host, |
| 1467 |
Options *options, int flags) |
1496 |
const char *original_host, Options *options, int flags) |
| 1468 |
{ |
1497 |
{ |
| 1469 |
FILE *f; |
1498 |
FILE *f; |
| 1470 |
char line[1024]; |
1499 |
char line[1024]; |
|
Lines 1495-1502
read_config_file(const char *filename, s
Link Here
|
| 1495 |
while (fgets(line, sizeof(line), f)) { |
1524 |
while (fgets(line, sizeof(line), f)) { |
| 1496 |
/* Update line number counter. */ |
1525 |
/* Update line number counter. */ |
| 1497 |
linenum++; |
1526 |
linenum++; |
| 1498 |
if (process_config_line(options, pw, host, line, filename, |
1527 |
if (process_config_line(options, pw, host, original_host, |
| 1499 |
linenum, &active, flags & SSHCONF_USERCONF) != 0) |
1528 |
line, filename, linenum, &active, flags) != 0) |
| 1500 |
bad_options++; |
1529 |
bad_options++; |
| 1501 |
} |
1530 |
} |
| 1502 |
fclose(f); |
1531 |
fclose(f); |
|
Lines 1609-1614
initialize_options(Options * options)
Link Here
|
| 1609 |
options->canonicalize_max_dots = -1; |
1638 |
options->canonicalize_max_dots = -1; |
| 1610 |
options->canonicalize_fallback_local = -1; |
1639 |
options->canonicalize_fallback_local = -1; |
| 1611 |
options->canonicalize_hostname = -1; |
1640 |
options->canonicalize_hostname = -1; |
|
|
1641 |
options->reread_config = -1; |
| 1612 |
} |
1642 |
} |
| 1613 |
|
1643 |
|
| 1614 |
/* |
1644 |
/* |
|
Lines 1786-1791
fill_default_options(Options * options)
Link Here
|
| 1786 |
options->canonicalize_fallback_local = 1; |
1816 |
options->canonicalize_fallback_local = 1; |
| 1787 |
if (options->canonicalize_hostname == -1) |
1817 |
if (options->canonicalize_hostname == -1) |
| 1788 |
options->canonicalize_hostname = SSH_CANONICALISE_NO; |
1818 |
options->canonicalize_hostname = SSH_CANONICALISE_NO; |
|
|
1819 |
if (options->reread_config == -1) |
| 1820 |
options->reread_config = SSH_REREAD_CANON; |
| 1789 |
#define CLEAR_ON_NONE(v) \ |
1821 |
#define CLEAR_ON_NONE(v) \ |
| 1790 |
do { \ |
1822 |
do { \ |
| 1791 |
if (option_clear_or_none(v)) { \ |
1823 |
if (option_clear_or_none(v)) { \ |