summaryrefslogtreecommitdiff
path: root/readconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'readconf.c')
-rw-r--r--readconf.c157
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"
15RCSID("$OpenBSD: readconf.c,v 1.134 2004/07/11 17:48:47 deraadt Exp $"); 15RCSID("$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
208void 208void
209add_local_forward(Options *options, u_short port, const char *host, 209add_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
231void 233void
232add_remote_forward(Options *options, u_short port, const char *host, 234add_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
245static void 249static 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 */
1071int
1072parse_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}