diff options
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 199 |
1 files changed, 95 insertions, 104 deletions
diff --git a/readconf.c b/readconf.c index f7b912ef6..9340effd0 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.206 2013/10/14 22:22:02 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.207 2013/10/14 23:28:23 djm 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 |
@@ -555,6 +555,61 @@ parse_token(const char *cp, const char *filename, int linenum, | |||
555 | return oBadOption; | 555 | return oBadOption; |
556 | } | 556 | } |
557 | 557 | ||
558 | /* Multistate option parsing */ | ||
559 | struct multistate { | ||
560 | char *key; | ||
561 | int value; | ||
562 | }; | ||
563 | static const struct multistate multistate_flag[] = { | ||
564 | { "true", 1 }, | ||
565 | { "false", 0 }, | ||
566 | { "yes", 1 }, | ||
567 | { "no", 0 }, | ||
568 | { NULL, -1 } | ||
569 | }; | ||
570 | static const struct multistate multistate_yesnoask[] = { | ||
571 | { "true", 1 }, | ||
572 | { "false", 0 }, | ||
573 | { "yes", 1 }, | ||
574 | { "no", 0 }, | ||
575 | { "ask", 2 }, | ||
576 | { NULL, -1 } | ||
577 | }; | ||
578 | static const struct multistate multistate_addressfamily[] = { | ||
579 | { "inet", AF_INET }, | ||
580 | { "inet6", AF_INET6 }, | ||
581 | { "any", AF_UNSPEC }, | ||
582 | { NULL, -1 } | ||
583 | }; | ||
584 | static const struct multistate multistate_controlmaster[] = { | ||
585 | { "true", SSHCTL_MASTER_YES }, | ||
586 | { "yes", SSHCTL_MASTER_YES }, | ||
587 | { "false", SSHCTL_MASTER_NO }, | ||
588 | { "no", SSHCTL_MASTER_NO }, | ||
589 | { "auto", SSHCTL_MASTER_AUTO }, | ||
590 | { "ask", SSHCTL_MASTER_ASK }, | ||
591 | { "autoask", SSHCTL_MASTER_AUTO_ASK }, | ||
592 | { NULL, -1 } | ||
593 | }; | ||
594 | static const struct multistate multistate_tunnel[] = { | ||
595 | { "ethernet", SSH_TUNMODE_ETHERNET }, | ||
596 | { "point-to-point", SSH_TUNMODE_POINTOPOINT }, | ||
597 | { "true", SSH_TUNMODE_DEFAULT }, | ||
598 | { "yes", SSH_TUNMODE_DEFAULT }, | ||
599 | { "false", SSH_TUNMODE_NO }, | ||
600 | { "no", SSH_TUNMODE_NO }, | ||
601 | { NULL, -1 } | ||
602 | }; | ||
603 | static const struct multistate multistate_requesttty[] = { | ||
604 | { "true", REQUEST_TTY_YES }, | ||
605 | { "yes", REQUEST_TTY_YES }, | ||
606 | { "false", REQUEST_TTY_NO }, | ||
607 | { "no", REQUEST_TTY_NO }, | ||
608 | { "force", REQUEST_TTY_FORCE }, | ||
609 | { "auto", REQUEST_TTY_AUTO }, | ||
610 | { NULL, -1 } | ||
611 | }; | ||
612 | |||
558 | /* | 613 | /* |
559 | * Processes a single option line as used in the configuration files. This | 614 | * Processes a single option line as used in the configuration files. This |
560 | * only sets those values that have not already been set. | 615 | * only sets those values that have not already been set. |
@@ -572,6 +627,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
572 | long long val64; | 627 | long long val64; |
573 | size_t len; | 628 | size_t len; |
574 | Forward fwd; | 629 | Forward fwd; |
630 | const struct multistate *multistate_ptr; | ||
575 | 631 | ||
576 | if (activep == NULL) { /* We are processing a command line directive */ | 632 | if (activep == NULL) { /* We are processing a command line directive */ |
577 | cmdline = 1; | 633 | cmdline = 1; |
@@ -595,8 +651,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
595 | if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') | 651 | if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') |
596 | return 0; | 652 | return 0; |
597 | /* Match lowercase keyword */ | 653 | /* Match lowercase keyword */ |
598 | for (i = 0; i < strlen(keyword); i++) | 654 | lowercase(keyword); |
599 | keyword[i] = tolower(keyword[i]); | ||
600 | 655 | ||
601 | opcode = parse_token(keyword, filename, linenum, | 656 | opcode = parse_token(keyword, filename, linenum, |
602 | options->ignored_unknown); | 657 | options->ignored_unknown); |
@@ -626,17 +681,23 @@ parse_time: | |||
626 | 681 | ||
627 | case oForwardAgent: | 682 | case oForwardAgent: |
628 | intptr = &options->forward_agent; | 683 | intptr = &options->forward_agent; |
629 | parse_flag: | 684 | parse_flag: |
685 | multistate_ptr = multistate_flag; | ||
686 | parse_multistate: | ||
630 | arg = strdelim(&s); | 687 | arg = strdelim(&s); |
631 | if (!arg || *arg == '\0') | 688 | if (!arg || *arg == '\0') |
632 | fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); | 689 | fatal("%s line %d: missing argument.", |
633 | value = 0; /* To avoid compiler warning... */ | 690 | filename, linenum); |
634 | if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) | 691 | value = -1; |
635 | value = 1; | 692 | for (i = 0; multistate_ptr[i].key != NULL; i++) { |
636 | else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) | 693 | if (strcasecmp(arg, multistate_ptr[i].key) == 0) { |
637 | value = 0; | 694 | value = multistate_ptr[i].value; |
638 | else | 695 | break; |
639 | fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); | 696 | } |
697 | } | ||
698 | if (value == -1) | ||
699 | fatal("%s line %d: unsupported option \"%s\".", | ||
700 | filename, linenum, arg); | ||
640 | if (*activep && *intptr == -1) | 701 | if (*activep && *intptr == -1) |
641 | *intptr = value; | 702 | *intptr = value; |
642 | break; | 703 | break; |
@@ -719,27 +780,13 @@ parse_flag: | |||
719 | 780 | ||
720 | case oVerifyHostKeyDNS: | 781 | case oVerifyHostKeyDNS: |
721 | intptr = &options->verify_host_key_dns; | 782 | intptr = &options->verify_host_key_dns; |
722 | goto parse_yesnoask; | 783 | multistate_ptr = multistate_yesnoask; |
784 | goto parse_multistate; | ||
723 | 785 | ||
724 | case oStrictHostKeyChecking: | 786 | case oStrictHostKeyChecking: |
725 | intptr = &options->strict_host_key_checking; | 787 | intptr = &options->strict_host_key_checking; |
726 | parse_yesnoask: | 788 | multistate_ptr = multistate_yesnoask; |
727 | arg = strdelim(&s); | 789 | goto parse_multistate; |
728 | if (!arg || *arg == '\0') | ||
729 | fatal("%.200s line %d: Missing yes/no/ask argument.", | ||
730 | filename, linenum); | ||
731 | value = 0; /* To avoid compiler warning... */ | ||
732 | if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) | ||
733 | value = 1; | ||
734 | else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) | ||
735 | value = 0; | ||
736 | else if (strcmp(arg, "ask") == 0) | ||
737 | value = 2; | ||
738 | else | ||
739 | fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); | ||
740 | if (*activep && *intptr == -1) | ||
741 | *intptr = value; | ||
742 | break; | ||
743 | 790 | ||
744 | case oCompression: | 791 | case oCompression: |
745 | intptr = &options->compression; | 792 | intptr = &options->compression; |
@@ -1080,22 +1127,9 @@ parse_int: | |||
1080 | break; | 1127 | break; |
1081 | 1128 | ||
1082 | case oAddressFamily: | 1129 | case oAddressFamily: |
1083 | arg = strdelim(&s); | ||
1084 | if (!arg || *arg == '\0') | ||
1085 | fatal("%s line %d: missing address family.", | ||
1086 | filename, linenum); | ||
1087 | intptr = &options->address_family; | 1130 | intptr = &options->address_family; |
1088 | if (strcasecmp(arg, "inet") == 0) | 1131 | multistate_ptr = multistate_addressfamily; |
1089 | value = AF_INET; | 1132 | goto parse_multistate; |
1090 | else if (strcasecmp(arg, "inet6") == 0) | ||
1091 | value = AF_INET6; | ||
1092 | else if (strcasecmp(arg, "any") == 0) | ||
1093 | value = AF_UNSPEC; | ||
1094 | else | ||
1095 | fatal("Unsupported AddressFamily \"%s\"", arg); | ||
1096 | if (*activep && *intptr == -1) | ||
1097 | *intptr = value; | ||
1098 | break; | ||
1099 | 1133 | ||
1100 | case oEnableSSHKeysign: | 1134 | case oEnableSSHKeysign: |
1101 | intptr = &options->enable_ssh_keysign; | 1135 | intptr = &options->enable_ssh_keysign; |
@@ -1134,27 +1168,8 @@ parse_int: | |||
1134 | 1168 | ||
1135 | case oControlMaster: | 1169 | case oControlMaster: |
1136 | intptr = &options->control_master; | 1170 | intptr = &options->control_master; |
1137 | arg = strdelim(&s); | 1171 | multistate_ptr = multistate_controlmaster; |
1138 | if (!arg || *arg == '\0') | 1172 | goto parse_multistate; |
1139 | fatal("%.200s line %d: Missing ControlMaster argument.", | ||
1140 | filename, linenum); | ||
1141 | value = 0; /* To avoid compiler warning... */ | ||
1142 | if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) | ||
1143 | value = SSHCTL_MASTER_YES; | ||
1144 | else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) | ||
1145 | value = SSHCTL_MASTER_NO; | ||
1146 | else if (strcmp(arg, "auto") == 0) | ||
1147 | value = SSHCTL_MASTER_AUTO; | ||
1148 | else if (strcmp(arg, "ask") == 0) | ||
1149 | value = SSHCTL_MASTER_ASK; | ||
1150 | else if (strcmp(arg, "autoask") == 0) | ||
1151 | value = SSHCTL_MASTER_AUTO_ASK; | ||
1152 | else | ||
1153 | fatal("%.200s line %d: Bad ControlMaster argument.", | ||
1154 | filename, linenum); | ||
1155 | if (*activep && *intptr == -1) | ||
1156 | *intptr = value; | ||
1157 | break; | ||
1158 | 1173 | ||
1159 | case oControlPersist: | 1174 | case oControlPersist: |
1160 | /* no/false/yes/true, or a time spec */ | 1175 | /* no/false/yes/true, or a time spec */ |
@@ -1186,25 +1201,8 @@ parse_int: | |||
1186 | 1201 | ||
1187 | case oTunnel: | 1202 | case oTunnel: |
1188 | intptr = &options->tun_open; | 1203 | intptr = &options->tun_open; |
1189 | arg = strdelim(&s); | 1204 | multistate_ptr = multistate_tunnel; |
1190 | if (!arg || *arg == '\0') | 1205 | goto parse_multistate; |
1191 | fatal("%s line %d: Missing yes/point-to-point/" | ||
1192 | "ethernet/no argument.", filename, linenum); | ||
1193 | value = 0; /* silence compiler */ | ||
1194 | if (strcasecmp(arg, "ethernet") == 0) | ||
1195 | value = SSH_TUNMODE_ETHERNET; | ||
1196 | else if (strcasecmp(arg, "point-to-point") == 0) | ||
1197 | value = SSH_TUNMODE_POINTOPOINT; | ||
1198 | else if (strcasecmp(arg, "yes") == 0) | ||
1199 | value = SSH_TUNMODE_DEFAULT; | ||
1200 | else if (strcasecmp(arg, "no") == 0) | ||
1201 | value = SSH_TUNMODE_NO; | ||
1202 | else | ||
1203 | fatal("%s line %d: Bad yes/point-to-point/ethernet/" | ||
1204 | "no argument: %s", filename, linenum, arg); | ||
1205 | if (*activep) | ||
1206 | *intptr = value; | ||
1207 | break; | ||
1208 | 1206 | ||
1209 | case oTunnelDevice: | 1207 | case oTunnelDevice: |
1210 | arg = strdelim(&s); | 1208 | arg = strdelim(&s); |
@@ -1253,24 +1251,9 @@ parse_int: | |||
1253 | goto parse_flag; | 1251 | goto parse_flag; |
1254 | 1252 | ||
1255 | case oRequestTTY: | 1253 | case oRequestTTY: |
1256 | arg = strdelim(&s); | ||
1257 | if (!arg || *arg == '\0') | ||
1258 | fatal("%s line %d: missing argument.", | ||
1259 | filename, linenum); | ||
1260 | intptr = &options->request_tty; | 1254 | intptr = &options->request_tty; |
1261 | if (strcasecmp(arg, "yes") == 0) | 1255 | multistate_ptr = multistate_requesttty; |
1262 | value = REQUEST_TTY_YES; | 1256 | goto parse_multistate; |
1263 | else if (strcasecmp(arg, "no") == 0) | ||
1264 | value = REQUEST_TTY_NO; | ||
1265 | else if (strcasecmp(arg, "force") == 0) | ||
1266 | value = REQUEST_TTY_FORCE; | ||
1267 | else if (strcasecmp(arg, "auto") == 0) | ||
1268 | value = REQUEST_TTY_AUTO; | ||
1269 | else | ||
1270 | fatal("Unsupported RequestTTY \"%s\"", arg); | ||
1271 | if (*activep && *intptr == -1) | ||
1272 | *intptr = value; | ||
1273 | break; | ||
1274 | 1257 | ||
1275 | case oIgnoreUnknown: | 1258 | case oIgnoreUnknown: |
1276 | charptr = &options->ignored_unknown; | 1259 | charptr = &options->ignored_unknown; |
@@ -1596,8 +1579,16 @@ fill_default_options(Options * options) | |||
1596 | options->request_tty = REQUEST_TTY_AUTO; | 1579 | options->request_tty = REQUEST_TTY_AUTO; |
1597 | if (options->proxy_use_fdpass == -1) | 1580 | if (options->proxy_use_fdpass == -1) |
1598 | options->proxy_use_fdpass = 0; | 1581 | options->proxy_use_fdpass = 0; |
1599 | /* options->local_command should not be set by default */ | 1582 | #define CLEAR_ON_NONE(v) \ |
1600 | /* options->proxy_command should not be set by default */ | 1583 | do { \ |
1584 | if (v != NULL && strcasecmp(v, "none") == 0) { \ | ||
1585 | free(v); \ | ||
1586 | v = NULL; \ | ||
1587 | } \ | ||
1588 | } while(0) | ||
1589 | CLEAR_ON_NONE(options->local_command); | ||
1590 | CLEAR_ON_NONE(options->proxy_command); | ||
1591 | CLEAR_ON_NONE(options->control_path); | ||
1601 | /* options->user will be set in the main program if appropriate */ | 1592 | /* options->user will be set in the main program if appropriate */ |
1602 | /* options->hostname will be set in the main program if appropriate */ | 1593 | /* options->hostname will be set in the main program if appropriate */ |
1603 | /* options->host_key_alias should not be set by default */ | 1594 | /* options->host_key_alias should not be set by default */ |