Mercurial > dropbear
annotate svr-tcpfwd.c @ 63:dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
- still a checkpoint-ish commit
- sorted out listening on localhost only
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 11 Aug 2004 17:26:47 +0000 |
parents | 20563735e8b5 |
children | efb5e0b335cf |
rev | line source |
---|---|
62 | 1 #include "includes.h" |
2 #include "ssh.h" | |
3 #include "tcp-accept.h" | |
4 #include "tcp-connect.h" | |
5 #include "dbutil.h" | |
6 #include "session.h" | |
7 #include "buffer.h" | |
8 #include "packet.h" | |
9 #include "listener.h" | |
10 #include "runopts.h" | |
11 | |
12 #ifndef DISABLE_SVR_REMOTETCPFWD | |
13 | |
14 static void send_msg_request_success(); | |
15 static void send_msg_request_failure(); | |
16 static int svr_cancelremotetcp(); | |
17 static int svr_remotetcpreq(); | |
18 | |
19 | |
20 const struct ChanType svr_chan_tcpdirect = { | |
21 1, /* sepfds */ | |
22 "direct-tcpip", | |
23 newtcpdirect, /* init */ | |
24 NULL, /* checkclose */ | |
25 NULL, /* reqhandler */ | |
26 NULL /* closehandler */ | |
27 }; | |
28 | |
29 static const struct ChanType svr_chan_tcpremote = { | |
30 1, /* sepfds */ | |
31 "forwarded-tcpip", | |
32 NULL, | |
33 NULL, | |
34 NULL, | |
35 NULL | |
36 }; | |
37 | |
38 /* At the moment this is completely used for tcp code (with the name reflecting | |
39 * that). If new request types are added, this should be replaced with code | |
40 * similar to the request-switching in chansession.c */ | |
41 void recv_msg_global_request_remotetcp() { | |
42 | |
43 unsigned char* reqname = NULL; | |
44 unsigned int namelen; | |
45 unsigned int wantreply = 0; | |
46 int ret = DROPBEAR_FAILURE; | |
47 | |
48 TRACE(("enter recv_msg_global_request_remotetcp")); | |
49 | |
50 if (opts.noremotetcp) { | |
51 TRACE(("leave recv_msg_global_request_remotetcp: remote tcp forwarding disabled")); | |
52 goto out; | |
53 } | |
54 | |
55 reqname = buf_getstring(ses.payload, &namelen); | |
56 wantreply = buf_getbyte(ses.payload); | |
57 | |
58 if (namelen > MAXNAMLEN) { | |
59 TRACE(("name len is wrong: %d", namelen)); | |
60 goto out; | |
61 } | |
62 | |
63 if (strcmp("tcpip-forward", reqname) == 0) { | |
64 ret = svr_remotetcpreq(); | |
65 } else if (strcmp("cancel-tcpip-forward", reqname) == 0) { | |
66 ret = svr_cancelremotetcp(); | |
67 } else { | |
68 TRACE(("reqname isn't tcpip-forward: '%s'", reqname)); | |
69 } | |
70 | |
71 out: | |
72 if (wantreply) { | |
73 if (ret == DROPBEAR_SUCCESS) { | |
74 send_msg_request_success(); | |
75 } else { | |
76 send_msg_request_failure(); | |
77 } | |
78 } | |
79 | |
80 m_free(reqname); | |
81 | |
82 TRACE(("leave recv_msg_global_request")); | |
83 } | |
84 | |
85 | |
86 static void send_msg_request_success() { | |
87 | |
88 CHECKCLEARTOWRITE(); | |
89 buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS); | |
90 encrypt_packet(); | |
91 | |
92 } | |
93 | |
94 static void send_msg_request_failure() { | |
95 | |
96 CHECKCLEARTOWRITE(); | |
97 buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE); | |
98 encrypt_packet(); | |
99 | |
100 } | |
101 | |
102 static int matchtcp(void* typedata1, void* typedata2) { | |
103 | |
104 const struct TCPListener *info1 = (struct TCPListener*)typedata1; | |
105 const struct TCPListener *info2 = (struct TCPListener*)typedata2; | |
106 | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
107 return (info1->sendport == info2->sendport) |
62 | 108 && (info1->chantype == info2->chantype) |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
109 && (strcmp(info1->sendaddr, info2->sendaddr) == 0); |
62 | 110 } |
111 | |
112 static int svr_cancelremotetcp() { | |
113 | |
114 int ret = DROPBEAR_FAILURE; | |
115 unsigned char * bindaddr = NULL; | |
116 unsigned int addrlen; | |
117 unsigned int port; | |
118 struct Listener * listener = NULL; | |
119 struct TCPListener tcpinfo; | |
120 | |
121 TRACE(("enter cancelremotetcp")); | |
122 | |
123 bindaddr = buf_getstring(ses.payload, &addrlen); | |
124 if (addrlen > MAX_IP_LEN) { | |
125 TRACE(("addr len too long: %d", addrlen)); | |
126 goto out; | |
127 } | |
128 | |
129 port = buf_getint(ses.payload); | |
130 | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
131 tcpinfo.sendaddr = bindaddr; |
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
132 tcpinfo.sendport = port; |
62 | 133 listener = get_listener(CHANNEL_ID_TCPFORWARDED, &tcpinfo, matchtcp); |
134 if (listener) { | |
135 remove_listener( listener ); | |
136 ret = DROPBEAR_SUCCESS; | |
137 } | |
138 | |
139 out: | |
140 m_free(bindaddr); | |
141 TRACE(("leave cancelremotetcp")); | |
142 return ret; | |
143 } | |
144 | |
145 static int svr_remotetcpreq() { | |
146 | |
147 int ret = DROPBEAR_FAILURE; | |
148 unsigned char * bindaddr = NULL; | |
149 unsigned int addrlen; | |
150 struct TCPListener *tcpinfo = NULL; | |
151 unsigned int port; | |
152 | |
153 TRACE(("enter remotetcpreq")); | |
154 | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
155 /* NOTE: at this stage, we ignore bindaddr. see below and listen_tcpfwd */ |
62 | 156 bindaddr = buf_getstring(ses.payload, &addrlen); |
157 if (addrlen > MAX_IP_LEN) { | |
158 TRACE(("addr len too long: %d", addrlen)); | |
159 goto out; | |
160 } | |
161 | |
162 port = buf_getint(ses.payload); | |
163 | |
164 if (port == 0) { | |
165 dropbear_log(LOG_INFO, "Server chosen tcpfwd ports are unsupported"); | |
166 goto out; | |
167 } | |
168 | |
169 if (port < 1 || port > 65535) { | |
170 TRACE(("invalid port: %d", port)); | |
171 goto out; | |
172 } | |
173 | |
174 if (!ses.allowprivport && port < IPPORT_RESERVED) { | |
175 TRACE(("can't assign port < 1024 for non-root")); | |
176 goto out; | |
177 } | |
178 | |
179 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener)); | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
180 tcpinfo->sendaddr = bindaddr; |
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
181 TRACE(("sendport = %d", port)); |
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
182 tcpinfo->sendport = port; |
62 | 183 tcpinfo->chantype = &svr_chan_tcpremote; |
184 | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
185 /* Note: bindaddr is actually ignored by listen_tcpfwd, since |
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
186 * we only want to bind to localhost */ |
62 | 187 ret = listen_tcpfwd(tcpinfo); |
188 | |
189 out: | |
190 if (ret == DROPBEAR_FAILURE) { | |
191 /* we only free it if a listener wasn't created, since the listener | |
192 * has to remember it if it's to be cancelled */ | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
193 m_free(tcpinfo->sendaddr); |
62 | 194 m_free(tcpinfo); |
195 } | |
196 TRACE(("leave remotetcpreq")); | |
197 return ret; | |
198 } | |
199 #endif |