diff options
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 169 |
1 files changed, 130 insertions, 39 deletions
diff --git a/readconf.c b/readconf.c index aca5b8eff..963b706aa 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -12,7 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "includes.h" | 14 | #include "includes.h" |
15 | RCSID("$OpenBSD: readconf.c,v 1.134 2004/07/11 17:48:47 deraadt Exp $"); | 15 | RCSID("$OpenBSD: readconf.c,v 1.137 2005/03/04 08:48:06 djm Exp $"); |
16 | 16 | ||
17 | #include "ssh.h" | 17 | #include "ssh.h" |
18 | #include "xmalloc.h" | 18 | #include "xmalloc.h" |
@@ -106,7 +106,7 @@ typedef enum { | |||
106 | oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, | 106 | oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, |
107 | oAddressFamily, oGssAuthentication, oGssDelegateCreds, | 107 | oAddressFamily, oGssAuthentication, oGssDelegateCreds, |
108 | oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, | 108 | oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, |
109 | oSendEnv, oControlPath, oControlMaster, | 109 | oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, |
110 | oProtocolKeepAlives, oSetupTimeOut, | 110 | oProtocolKeepAlives, oSetupTimeOut, |
111 | oDeprecated, oUnsupported | 111 | oDeprecated, oUnsupported |
112 | } OpCodes; | 112 | } OpCodes; |
@@ -198,6 +198,7 @@ static struct { | |||
198 | { "sendenv", oSendEnv }, | 198 | { "sendenv", oSendEnv }, |
199 | { "controlpath", oControlPath }, | 199 | { "controlpath", oControlPath }, |
200 | { "controlmaster", oControlMaster }, | 200 | { "controlmaster", oControlMaster }, |
201 | { "hashknownhosts", oHashKnownHosts }, | ||
201 | { "protocolkeepalives", oProtocolKeepAlives }, | 202 | { "protocolkeepalives", oProtocolKeepAlives }, |
202 | { "setuptimeout", oSetupTimeOut }, | 203 | { "setuptimeout", oSetupTimeOut }, |
203 | { NULL, oBadOption } | 204 | { NULL, oBadOption } |
@@ -209,21 +210,23 @@ static struct { | |||
209 | */ | 210 | */ |
210 | 211 | ||
211 | void | 212 | void |
212 | add_local_forward(Options *options, u_short port, const char *host, | 213 | add_local_forward(Options *options, const Forward *newfwd) |
213 | u_short host_port) | ||
214 | { | 214 | { |
215 | Forward *fwd; | 215 | Forward *fwd; |
216 | #ifndef NO_IPPORT_RESERVED_CONCEPT | 216 | #ifndef NO_IPPORT_RESERVED_CONCEPT |
217 | extern uid_t original_real_uid; | 217 | extern uid_t original_real_uid; |
218 | if (port < IPPORT_RESERVED && original_real_uid != 0) | 218 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) |
219 | fatal("Privileged ports can only be forwarded by root."); | 219 | fatal("Privileged ports can only be forwarded by root."); |
220 | #endif | 220 | #endif |
221 | if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) | 221 | if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) |
222 | fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); | 222 | fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); |
223 | fwd = &options->local_forwards[options->num_local_forwards++]; | 223 | fwd = &options->local_forwards[options->num_local_forwards++]; |
224 | fwd->port = port; | 224 | |
225 | fwd->host = xstrdup(host); | 225 | fwd->listen_host = (newfwd->listen_host == NULL) ? |
226 | fwd->host_port = host_port; | 226 | NULL : xstrdup(newfwd->listen_host); |
227 | fwd->listen_port = newfwd->listen_port; | ||
228 | fwd->connect_host = xstrdup(newfwd->connect_host); | ||
229 | fwd->connect_port = newfwd->connect_port; | ||
227 | } | 230 | } |
228 | 231 | ||
229 | /* | 232 | /* |
@@ -232,17 +235,19 @@ add_local_forward(Options *options, u_short port, const char *host, | |||
232 | */ | 235 | */ |
233 | 236 | ||
234 | void | 237 | void |
235 | add_remote_forward(Options *options, u_short port, const char *host, | 238 | add_remote_forward(Options *options, const Forward *newfwd) |
236 | u_short host_port) | ||
237 | { | 239 | { |
238 | Forward *fwd; | 240 | Forward *fwd; |
239 | if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) | 241 | if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) |
240 | fatal("Too many remote forwards (max %d).", | 242 | fatal("Too many remote forwards (max %d).", |
241 | SSH_MAX_FORWARDS_PER_DIRECTION); | 243 | SSH_MAX_FORWARDS_PER_DIRECTION); |
242 | fwd = &options->remote_forwards[options->num_remote_forwards++]; | 244 | fwd = &options->remote_forwards[options->num_remote_forwards++]; |
243 | fwd->port = port; | 245 | |
244 | fwd->host = xstrdup(host); | 246 | fwd->listen_host = (newfwd->listen_host == NULL) ? |
245 | fwd->host_port = host_port; | 247 | NULL : xstrdup(newfwd->listen_host); |
248 | fwd->listen_port = newfwd->listen_port; | ||
249 | fwd->connect_host = xstrdup(newfwd->connect_host); | ||
250 | fwd->connect_port = newfwd->connect_port; | ||
246 | } | 251 | } |
247 | 252 | ||
248 | static void | 253 | static void |
@@ -250,11 +255,15 @@ clear_forwardings(Options *options) | |||
250 | { | 255 | { |
251 | int i; | 256 | int i; |
252 | 257 | ||
253 | for (i = 0; i < options->num_local_forwards; i++) | 258 | for (i = 0; i < options->num_local_forwards; i++) { |
254 | xfree(options->local_forwards[i].host); | 259 | xfree(options->local_forwards[i].listen_host); |
260 | xfree(options->local_forwards[i].connect_host); | ||
261 | } | ||
255 | options->num_local_forwards = 0; | 262 | options->num_local_forwards = 0; |
256 | for (i = 0; i < options->num_remote_forwards; i++) | 263 | for (i = 0; i < options->num_remote_forwards; i++) { |
257 | xfree(options->remote_forwards[i].host); | 264 | xfree(options->remote_forwards[i].listen_host); |
265 | xfree(options->remote_forwards[i].connect_host); | ||
266 | } | ||
258 | options->num_remote_forwards = 0; | 267 | options->num_remote_forwards = 0; |
259 | } | 268 | } |
260 | 269 | ||
@@ -287,11 +296,10 @@ process_config_line(Options *options, const char *host, | |||
287 | char *line, const char *filename, int linenum, | 296 | char *line, const char *filename, int linenum, |
288 | int *activep) | 297 | int *activep) |
289 | { | 298 | { |
290 | char buf[256], *s, **charptr, *endofnumber, *keyword, *arg; | 299 | char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; |
291 | int opcode, *intptr, value; | 300 | int opcode, *intptr, value; |
292 | size_t len; | 301 | size_t len; |
293 | u_short fwd_port, fwd_host_port; | 302 | Forward fwd; |
294 | char sfwd_host_port[6]; | ||
295 | 303 | ||
296 | /* Strip trailing whitespace */ | 304 | /* Strip trailing whitespace */ |
297 | for(len = strlen(line) - 1; len > 0; len--) { | 305 | for(len = strlen(line) - 1; len > 0; len--) { |
@@ -648,30 +656,26 @@ parse_int: | |||
648 | case oLocalForward: | 656 | case oLocalForward: |
649 | case oRemoteForward: | 657 | case oRemoteForward: |
650 | arg = strdelim(&s); | 658 | arg = strdelim(&s); |
651 | if (!arg || *arg == '\0') | 659 | if (arg == NULL || *arg == '\0') |
652 | fatal("%.200s line %d: Missing port argument.", | 660 | fatal("%.200s line %d: Missing port argument.", |
653 | filename, linenum); | 661 | filename, linenum); |
654 | if ((fwd_port = a2port(arg)) == 0) | 662 | arg2 = strdelim(&s); |
655 | fatal("%.200s line %d: Bad listen port.", | 663 | if (arg2 == NULL || *arg2 == '\0') |
664 | fatal("%.200s line %d: Missing target argument.", | ||
656 | filename, linenum); | 665 | filename, linenum); |
657 | arg = strdelim(&s); | 666 | |
658 | if (!arg || *arg == '\0') | 667 | /* construct a string for parse_forward */ |
659 | fatal("%.200s line %d: Missing second argument.", | 668 | snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); |
660 | filename, linenum); | 669 | |
661 | if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && | 670 | if (parse_forward(&fwd, fwdarg) == 0) |
662 | sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) | ||
663 | fatal("%.200s line %d: Bad forwarding specification.", | 671 | fatal("%.200s line %d: Bad forwarding specification.", |
664 | filename, linenum); | 672 | filename, linenum); |
665 | if ((fwd_host_port = a2port(sfwd_host_port)) == 0) | 673 | |
666 | fatal("%.200s line %d: Bad forwarding port.", | ||
667 | filename, linenum); | ||
668 | if (*activep) { | 674 | if (*activep) { |
669 | if (opcode == oLocalForward) | 675 | if (opcode == oLocalForward) |
670 | add_local_forward(options, fwd_port, buf, | 676 | add_local_forward(options, &fwd); |
671 | fwd_host_port); | ||
672 | else if (opcode == oRemoteForward) | 677 | else if (opcode == oRemoteForward) |
673 | add_remote_forward(options, fwd_port, buf, | 678 | add_remote_forward(options, &fwd); |
674 | fwd_host_port); | ||
675 | } | 679 | } |
676 | break; | 680 | break; |
677 | 681 | ||
@@ -680,12 +684,25 @@ parse_int: | |||
680 | if (!arg || *arg == '\0') | 684 | if (!arg || *arg == '\0') |
681 | fatal("%.200s line %d: Missing port argument.", | 685 | fatal("%.200s line %d: Missing port argument.", |
682 | filename, linenum); | 686 | filename, linenum); |
683 | fwd_port = a2port(arg); | 687 | memset(&fwd, '\0', sizeof(fwd)); |
684 | if (fwd_port == 0) | 688 | fwd.connect_host = "socks"; |
689 | fwd.listen_host = hpdelim(&arg); | ||
690 | if (fwd.listen_host == NULL || | ||
691 | strlen(fwd.listen_host) >= NI_MAXHOST) | ||
692 | fatal("%.200s line %d: Bad forwarding specification.", | ||
693 | filename, linenum); | ||
694 | if (arg) { | ||
695 | fwd.listen_port = a2port(arg); | ||
696 | fwd.listen_host = cleanhostname(fwd.listen_host); | ||
697 | } else { | ||
698 | fwd.listen_port = a2port(fwd.listen_host); | ||
699 | fwd.listen_host = ""; | ||
700 | } | ||
701 | if (fwd.listen_port == 0) | ||
685 | fatal("%.200s line %d: Badly formatted port number.", | 702 | fatal("%.200s line %d: Badly formatted port number.", |
686 | filename, linenum); | 703 | filename, linenum); |
687 | if (*activep) | 704 | if (*activep) |
688 | add_local_forward(options, fwd_port, "socks", 0); | 705 | add_local_forward(options, &fwd); |
689 | break; | 706 | break; |
690 | 707 | ||
691 | case oClearAllForwardings: | 708 | case oClearAllForwardings: |
@@ -762,6 +779,8 @@ parse_int: | |||
762 | if (strchr(arg, '=') != NULL) | 779 | if (strchr(arg, '=') != NULL) |
763 | fatal("%s line %d: Invalid environment name.", | 780 | fatal("%s line %d: Invalid environment name.", |
764 | filename, linenum); | 781 | filename, linenum); |
782 | if (!*activep) | ||
783 | continue; | ||
765 | if (options->num_send_env >= MAX_SEND_ENV) | 784 | if (options->num_send_env >= MAX_SEND_ENV) |
766 | fatal("%s line %d: too many send env.", | 785 | fatal("%s line %d: too many send env.", |
767 | filename, linenum); | 786 | filename, linenum); |
@@ -778,6 +797,10 @@ parse_int: | |||
778 | intptr = &options->control_master; | 797 | intptr = &options->control_master; |
779 | goto parse_yesnoask; | 798 | goto parse_yesnoask; |
780 | 799 | ||
800 | case oHashKnownHosts: | ||
801 | intptr = &options->hash_known_hosts; | ||
802 | goto parse_flag; | ||
803 | |||
781 | case oSetupTimeOut: | 804 | case oSetupTimeOut: |
782 | intptr = &options->setuptimeout; | 805 | intptr = &options->setuptimeout; |
783 | goto parse_int; | 806 | goto parse_int; |
@@ -926,6 +949,7 @@ initialize_options(Options * options) | |||
926 | options->num_send_env = 0; | 949 | options->num_send_env = 0; |
927 | options->control_path = NULL; | 950 | options->control_path = NULL; |
928 | options->control_master = -1; | 951 | options->control_master = -1; |
952 | options->hash_known_hosts = -1; | ||
929 | } | 953 | } |
930 | 954 | ||
931 | /* | 955 | /* |
@@ -1053,6 +1077,8 @@ fill_default_options(Options * options) | |||
1053 | options->server_alive_count_max = 3; | 1077 | options->server_alive_count_max = 3; |
1054 | if (options->control_master == -1) | 1078 | if (options->control_master == -1) |
1055 | options->control_master = 0; | 1079 | options->control_master = 0; |
1080 | if (options->hash_known_hosts == -1) | ||
1081 | options->hash_known_hosts = 0; | ||
1056 | if (options->setuptimeout == -1) { | 1082 | if (options->setuptimeout == -1) { |
1057 | /* in batch mode, default is 5mins */ | 1083 | /* in batch mode, default is 5mins */ |
1058 | if (options->batch_mode == 1) | 1084 | if (options->batch_mode == 1) |
@@ -1066,3 +1092,68 @@ fill_default_options(Options * options) | |||
1066 | /* options->host_key_alias should not be set by default */ | 1092 | /* options->host_key_alias should not be set by default */ |
1067 | /* options->preferred_authentications will be set in ssh */ | 1093 | /* options->preferred_authentications will be set in ssh */ |
1068 | } | 1094 | } |
1095 | |||
1096 | /* | ||
1097 | * parse_forward | ||
1098 | * parses a string containing a port forwarding specification of the form: | ||
1099 | * [listenhost:]listenport:connecthost:connectport | ||
1100 | * returns number of arguments parsed or zero on error | ||
1101 | */ | ||
1102 | int | ||
1103 | parse_forward(Forward *fwd, const char *fwdspec) | ||
1104 | { | ||
1105 | int i; | ||
1106 | char *p, *cp, *fwdarg[4]; | ||
1107 | |||
1108 | memset(fwd, '\0', sizeof(*fwd)); | ||
1109 | |||
1110 | cp = p = xstrdup(fwdspec); | ||
1111 | |||
1112 | /* skip leading spaces */ | ||
1113 | while (*cp && isspace(*cp)) | ||
1114 | cp++; | ||
1115 | |||
1116 | for (i = 0; i < 4; ++i) | ||
1117 | if ((fwdarg[i] = hpdelim(&cp)) == NULL) | ||
1118 | break; | ||
1119 | |||
1120 | /* Check for trailing garbage in 4-arg case*/ | ||
1121 | if (cp != NULL) | ||
1122 | i = 0; /* failure */ | ||
1123 | |||
1124 | switch (i) { | ||
1125 | case 3: | ||
1126 | fwd->listen_host = NULL; | ||
1127 | fwd->listen_port = a2port(fwdarg[0]); | ||
1128 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); | ||
1129 | fwd->connect_port = a2port(fwdarg[2]); | ||
1130 | break; | ||
1131 | |||
1132 | case 4: | ||
1133 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | ||
1134 | fwd->listen_port = a2port(fwdarg[1]); | ||
1135 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); | ||
1136 | fwd->connect_port = a2port(fwdarg[3]); | ||
1137 | break; | ||
1138 | default: | ||
1139 | i = 0; /* failure */ | ||
1140 | } | ||
1141 | |||
1142 | xfree(p); | ||
1143 | |||
1144 | if (fwd->listen_port == 0 && fwd->connect_port == 0) | ||
1145 | goto fail_free; | ||
1146 | |||
1147 | if (fwd->connect_host != NULL && | ||
1148 | strlen(fwd->connect_host) >= NI_MAXHOST) | ||
1149 | goto fail_free; | ||
1150 | |||
1151 | return (i); | ||
1152 | |||
1153 | fail_free: | ||
1154 | if (fwd->connect_host != NULL) | ||
1155 | xfree(fwd->connect_host); | ||
1156 | if (fwd->listen_host != NULL) | ||
1157 | xfree(fwd->listen_host); | ||
1158 | return (0); | ||
1159 | } | ||