diff options
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 157 |
1 files changed, 119 insertions, 38 deletions
diff --git a/readconf.c b/readconf.c index a4fe1fe02..c3dc71e66 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.135 2005/03/01 10:09:52 djm Exp $"); |
16 | 16 | ||
17 | #include "ssh.h" | 17 | #include "ssh.h" |
18 | #include "xmalloc.h" | 18 | #include "xmalloc.h" |
@@ -206,21 +206,23 @@ static struct { | |||
206 | */ | 206 | */ |
207 | 207 | ||
208 | void | 208 | void |
209 | add_local_forward(Options *options, u_short port, const char *host, | 209 | add_local_forward(Options *options, const Forward *newfwd) |
210 | u_short host_port) | ||
211 | { | 210 | { |
212 | Forward *fwd; | 211 | Forward *fwd; |
213 | #ifndef NO_IPPORT_RESERVED_CONCEPT | 212 | #ifndef NO_IPPORT_RESERVED_CONCEPT |
214 | extern uid_t original_real_uid; | 213 | extern uid_t original_real_uid; |
215 | if (port < IPPORT_RESERVED && original_real_uid != 0) | 214 | if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) |
216 | fatal("Privileged ports can only be forwarded by root."); | 215 | fatal("Privileged ports can only be forwarded by root."); |
217 | #endif | 216 | #endif |
218 | if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) | 217 | if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) |
219 | fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); | 218 | fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); |
220 | fwd = &options->local_forwards[options->num_local_forwards++]; | 219 | fwd = &options->local_forwards[options->num_local_forwards++]; |
221 | fwd->port = port; | 220 | |
222 | fwd->host = xstrdup(host); | 221 | fwd->listen_host = (newfwd->listen_host == NULL) ? |
223 | fwd->host_port = host_port; | 222 | NULL : xstrdup(newfwd->listen_host); |
223 | fwd->listen_port = newfwd->listen_port; | ||
224 | fwd->connect_host = xstrdup(newfwd->connect_host); | ||
225 | fwd->connect_port = newfwd->connect_port; | ||
224 | } | 226 | } |
225 | 227 | ||
226 | /* | 228 | /* |
@@ -229,17 +231,19 @@ add_local_forward(Options *options, u_short port, const char *host, | |||
229 | */ | 231 | */ |
230 | 232 | ||
231 | void | 233 | void |
232 | add_remote_forward(Options *options, u_short port, const char *host, | 234 | add_remote_forward(Options *options, const Forward *newfwd) |
233 | u_short host_port) | ||
234 | { | 235 | { |
235 | Forward *fwd; | 236 | Forward *fwd; |
236 | if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) | 237 | if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) |
237 | fatal("Too many remote forwards (max %d).", | 238 | fatal("Too many remote forwards (max %d).", |
238 | SSH_MAX_FORWARDS_PER_DIRECTION); | 239 | SSH_MAX_FORWARDS_PER_DIRECTION); |
239 | fwd = &options->remote_forwards[options->num_remote_forwards++]; | 240 | fwd = &options->remote_forwards[options->num_remote_forwards++]; |
240 | fwd->port = port; | 241 | |
241 | fwd->host = xstrdup(host); | 242 | fwd->listen_host = (newfwd->listen_host == NULL) ? |
242 | fwd->host_port = host_port; | 243 | NULL : xstrdup(newfwd->listen_host); |
244 | fwd->listen_port = newfwd->listen_port; | ||
245 | fwd->connect_host = xstrdup(newfwd->connect_host); | ||
246 | fwd->connect_port = newfwd->connect_port; | ||
243 | } | 247 | } |
244 | 248 | ||
245 | static void | 249 | static void |
@@ -247,11 +251,15 @@ clear_forwardings(Options *options) | |||
247 | { | 251 | { |
248 | int i; | 252 | int i; |
249 | 253 | ||
250 | for (i = 0; i < options->num_local_forwards; i++) | 254 | for (i = 0; i < options->num_local_forwards; i++) { |
251 | xfree(options->local_forwards[i].host); | 255 | xfree(options->local_forwards[i].listen_host); |
256 | xfree(options->local_forwards[i].connect_host); | ||
257 | } | ||
252 | options->num_local_forwards = 0; | 258 | options->num_local_forwards = 0; |
253 | for (i = 0; i < options->num_remote_forwards; i++) | 259 | for (i = 0; i < options->num_remote_forwards; i++) { |
254 | xfree(options->remote_forwards[i].host); | 260 | xfree(options->remote_forwards[i].listen_host); |
261 | xfree(options->remote_forwards[i].connect_host); | ||
262 | } | ||
255 | options->num_remote_forwards = 0; | 263 | options->num_remote_forwards = 0; |
256 | } | 264 | } |
257 | 265 | ||
@@ -284,11 +292,10 @@ process_config_line(Options *options, const char *host, | |||
284 | char *line, const char *filename, int linenum, | 292 | char *line, const char *filename, int linenum, |
285 | int *activep) | 293 | int *activep) |
286 | { | 294 | { |
287 | char buf[256], *s, **charptr, *endofnumber, *keyword, *arg; | 295 | char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; |
288 | int opcode, *intptr, value; | 296 | int opcode, *intptr, value; |
289 | size_t len; | 297 | size_t len; |
290 | u_short fwd_port, fwd_host_port; | 298 | Forward fwd; |
291 | char sfwd_host_port[6]; | ||
292 | 299 | ||
293 | /* Strip trailing whitespace */ | 300 | /* Strip trailing whitespace */ |
294 | for(len = strlen(line) - 1; len > 0; len--) { | 301 | for(len = strlen(line) - 1; len > 0; len--) { |
@@ -645,30 +652,26 @@ parse_int: | |||
645 | case oLocalForward: | 652 | case oLocalForward: |
646 | case oRemoteForward: | 653 | case oRemoteForward: |
647 | arg = strdelim(&s); | 654 | arg = strdelim(&s); |
648 | if (!arg || *arg == '\0') | 655 | if (arg == NULL || *arg == '\0') |
649 | fatal("%.200s line %d: Missing port argument.", | 656 | fatal("%.200s line %d: Missing port argument.", |
650 | filename, linenum); | 657 | filename, linenum); |
651 | if ((fwd_port = a2port(arg)) == 0) | 658 | arg2 = strdelim(&s); |
652 | fatal("%.200s line %d: Bad listen port.", | 659 | if (arg2 == NULL || *arg2 == '\0') |
660 | fatal("%.200s line %d: Missing target argument.", | ||
653 | filename, linenum); | 661 | filename, linenum); |
654 | arg = strdelim(&s); | 662 | |
655 | if (!arg || *arg == '\0') | 663 | /* construct a string for parse_forward */ |
656 | fatal("%.200s line %d: Missing second argument.", | 664 | snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); |
657 | filename, linenum); | 665 | |
658 | if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && | 666 | if (parse_forward(&fwd, fwdarg) == 0) |
659 | sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) | ||
660 | fatal("%.200s line %d: Bad forwarding specification.", | 667 | fatal("%.200s line %d: Bad forwarding specification.", |
661 | filename, linenum); | 668 | filename, linenum); |
662 | if ((fwd_host_port = a2port(sfwd_host_port)) == 0) | 669 | |
663 | fatal("%.200s line %d: Bad forwarding port.", | ||
664 | filename, linenum); | ||
665 | if (*activep) { | 670 | if (*activep) { |
666 | if (opcode == oLocalForward) | 671 | if (opcode == oLocalForward) |
667 | add_local_forward(options, fwd_port, buf, | 672 | add_local_forward(options, &fwd); |
668 | fwd_host_port); | ||
669 | else if (opcode == oRemoteForward) | 673 | else if (opcode == oRemoteForward) |
670 | add_remote_forward(options, fwd_port, buf, | 674 | add_remote_forward(options, &fwd); |
671 | fwd_host_port); | ||
672 | } | 675 | } |
673 | break; | 676 | break; |
674 | 677 | ||
@@ -677,12 +680,25 @@ parse_int: | |||
677 | if (!arg || *arg == '\0') | 680 | if (!arg || *arg == '\0') |
678 | fatal("%.200s line %d: Missing port argument.", | 681 | fatal("%.200s line %d: Missing port argument.", |
679 | filename, linenum); | 682 | filename, linenum); |
680 | fwd_port = a2port(arg); | 683 | memset(&fwd, '\0', sizeof(fwd)); |
681 | if (fwd_port == 0) | 684 | fwd.connect_host = "socks"; |
685 | fwd.listen_host = hpdelim(&arg); | ||
686 | if (fwd.listen_host == NULL || | ||
687 | strlen(fwd.listen_host) >= NI_MAXHOST) | ||
688 | fatal("%.200s line %d: Bad forwarding specification.", | ||
689 | filename, linenum); | ||
690 | if (arg) { | ||
691 | fwd.listen_port = a2port(arg); | ||
692 | fwd.listen_host = cleanhostname(fwd.listen_host); | ||
693 | } else { | ||
694 | fwd.listen_port = a2port(fwd.listen_host); | ||
695 | fwd.listen_host = ""; | ||
696 | } | ||
697 | if (fwd.listen_port == 0) | ||
682 | fatal("%.200s line %d: Badly formatted port number.", | 698 | fatal("%.200s line %d: Badly formatted port number.", |
683 | filename, linenum); | 699 | filename, linenum); |
684 | if (*activep) | 700 | if (*activep) |
685 | add_local_forward(options, fwd_port, "socks", 0); | 701 | add_local_forward(options, &fwd); |
686 | break; | 702 | break; |
687 | 703 | ||
688 | case oClearAllForwardings: | 704 | case oClearAllForwardings: |
@@ -1045,3 +1061,68 @@ fill_default_options(Options * options) | |||
1045 | /* options->host_key_alias should not be set by default */ | 1061 | /* options->host_key_alias should not be set by default */ |
1046 | /* options->preferred_authentications will be set in ssh */ | 1062 | /* options->preferred_authentications will be set in ssh */ |
1047 | } | 1063 | } |
1064 | |||
1065 | /* | ||
1066 | * parse_forward | ||
1067 | * parses a string containing a port forwarding specification of the form: | ||
1068 | * [listenhost:]listenport:connecthost:connectport | ||
1069 | * returns number of arguments parsed or zero on error | ||
1070 | */ | ||
1071 | int | ||
1072 | parse_forward(Forward *fwd, const char *fwdspec) | ||
1073 | { | ||
1074 | int i; | ||
1075 | char *p, *cp, *fwdarg[4]; | ||
1076 | |||
1077 | memset(fwd, '\0', sizeof(*fwd)); | ||
1078 | |||
1079 | cp = p = xstrdup(fwdspec); | ||
1080 | |||
1081 | /* skip leading spaces */ | ||
1082 | while (*cp && isspace(*cp)) | ||
1083 | cp++; | ||
1084 | |||
1085 | for (i = 0; i < 4; ++i) | ||
1086 | if ((fwdarg[i] = hpdelim(&cp)) == NULL) | ||
1087 | break; | ||
1088 | |||
1089 | /* Check for trailing garbage in 4-arg case*/ | ||
1090 | if (cp != NULL) | ||
1091 | i = 0; /* failure */ | ||
1092 | |||
1093 | switch (i) { | ||
1094 | case 3: | ||
1095 | fwd->listen_host = NULL; | ||
1096 | fwd->listen_port = a2port(fwdarg[0]); | ||
1097 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); | ||
1098 | fwd->connect_port = a2port(fwdarg[2]); | ||
1099 | break; | ||
1100 | |||
1101 | case 4: | ||
1102 | fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); | ||
1103 | fwd->listen_port = a2port(fwdarg[1]); | ||
1104 | fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); | ||
1105 | fwd->connect_port = a2port(fwdarg[3]); | ||
1106 | break; | ||
1107 | default: | ||
1108 | i = 0; /* failure */ | ||
1109 | } | ||
1110 | |||
1111 | xfree(p); | ||
1112 | |||
1113 | if (fwd->listen_port == 0 && fwd->connect_port == 0) | ||
1114 | goto fail_free; | ||
1115 | |||
1116 | if (fwd->connect_host != NULL && | ||
1117 | strlen(fwd->connect_host) >= NI_MAXHOST) | ||
1118 | goto fail_free; | ||
1119 | |||
1120 | return (i); | ||
1121 | |||
1122 | fail_free: | ||
1123 | if (fwd->connect_host != NULL) | ||
1124 | xfree(fwd->connect_host); | ||
1125 | if (fwd->listen_host != NULL) | ||
1126 | xfree(fwd->listen_host); | ||
1127 | return (0); | ||
1128 | } | ||