comparison cli-tcpfwd.c @ 641:2b1bb792cd4d dropbear-tfm

- Update tfm changes to current default tip
author Matt Johnston <matt@ucc.asn.au>
date Mon, 21 Nov 2011 19:52:28 +0800
parents af304deacb4c
children c19acba28590
comparison
equal deleted inserted replaced
640:76097ec1a29a 641:2b1bb792cd4d
43 NULL 43 NULL
44 }; 44 };
45 #endif 45 #endif
46 46
47 #ifdef ENABLE_CLI_LOCALTCPFWD 47 #ifdef ENABLE_CLI_LOCALTCPFWD
48 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, 48 static int cli_localtcp(const char* listenaddr,
49 unsigned int listenport,
50 const char* remoteaddr,
49 unsigned int remoteport); 51 unsigned int remoteport);
50 static const struct ChanType cli_chan_tcplocal = { 52 static const struct ChanType cli_chan_tcplocal = {
51 1, /* sepfds */ 53 1, /* sepfds */
52 "direct-tcpip", 54 "direct-tcpip",
53 NULL, 55 NULL,
57 }; 59 };
58 #endif 60 #endif
59 61
60 #ifdef ENABLE_CLI_LOCALTCPFWD 62 #ifdef ENABLE_CLI_LOCALTCPFWD
61 void setup_localtcp() { 63 void setup_localtcp() {
62 64 m_list_elem *iter;
63 int ret; 65 int ret;
64 66
65 TRACE(("enter setup_localtcp")) 67 TRACE(("enter setup_localtcp"))
66 68
67 if (cli_opts.localfwds == NULL) { 69 for (iter = cli_opts.localfwds->first; iter; iter = iter->next) {
68 TRACE(("cli_opts.localfwds == NULL")) 70 struct TCPFwdEntry * fwd = (struct TCPFwdEntry*)iter->item;
69 } 71 ret = cli_localtcp(
70 72 fwd->listenaddr,
71 while (cli_opts.localfwds != NULL) { 73 fwd->listenport,
72 ret = cli_localtcp(cli_opts.localfwds->listenport, 74 fwd->connectaddr,
73 cli_opts.localfwds->connectaddr, 75 fwd->connectport);
74 cli_opts.localfwds->connectport);
75 if (ret == DROPBEAR_FAILURE) { 76 if (ret == DROPBEAR_FAILURE) {
76 dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", 77 dropbear_log(LOG_WARNING, "Failed local port forward %s:%d:%s:%d",
77 cli_opts.localfwds->listenport, 78 fwd->listenaddr,
78 cli_opts.localfwds->connectaddr, 79 fwd->listenport,
79 cli_opts.localfwds->connectport); 80 fwd->connectaddr,
80 } 81 fwd->connectport);
81 82 }
82 cli_opts.localfwds = cli_opts.localfwds->next;
83 } 83 }
84 TRACE(("leave setup_localtcp")) 84 TRACE(("leave setup_localtcp"))
85 85
86 } 86 }
87 87
88 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, 88 static int cli_localtcp(const char* listenaddr,
89 unsigned int listenport,
90 const char* remoteaddr,
89 unsigned int remoteport) { 91 unsigned int remoteport) {
90 92
91 struct TCPListener* tcpinfo = NULL; 93 struct TCPListener* tcpinfo = NULL;
92 int ret; 94 int ret;
93 95
97 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener)); 99 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
98 100
99 tcpinfo->sendaddr = m_strdup(remoteaddr); 101 tcpinfo->sendaddr = m_strdup(remoteaddr);
100 tcpinfo->sendport = remoteport; 102 tcpinfo->sendport = remoteport;
101 103
102 if (opts.listen_fwd_all) { 104 if (listenaddr)
103 tcpinfo->listenaddr = m_strdup(""); 105 {
104 } else { 106 tcpinfo->listenaddr = m_strdup(listenaddr);
105 tcpinfo->listenaddr = m_strdup("localhost"); 107 }
108 else
109 {
110 if (opts.listen_fwd_all) {
111 tcpinfo->listenaddr = m_strdup("");
112 } else {
113 tcpinfo->listenaddr = m_strdup("localhost");
114 }
106 } 115 }
107 tcpinfo->listenport = listenport; 116 tcpinfo->listenport = listenport;
108 117
109 tcpinfo->chantype = &cli_chan_tcplocal; 118 tcpinfo->chantype = &cli_chan_tcplocal;
110 tcpinfo->tcp_type = direct; 119 tcpinfo->tcp_type = direct;
118 return ret; 127 return ret;
119 } 128 }
120 #endif /* ENABLE_CLI_LOCALTCPFWD */ 129 #endif /* ENABLE_CLI_LOCALTCPFWD */
121 130
122 #ifdef ENABLE_CLI_REMOTETCPFWD 131 #ifdef ENABLE_CLI_REMOTETCPFWD
123 static void send_msg_global_request_remotetcp(int port) { 132 static void send_msg_global_request_remotetcp(const char *addr, int port) {
124 133
125 char* listenspec = NULL;
126 TRACE(("enter send_msg_global_request_remotetcp")) 134 TRACE(("enter send_msg_global_request_remotetcp"))
127 135
128 CHECKCLEARTOWRITE(); 136 CHECKCLEARTOWRITE();
129 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); 137 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
130 buf_putstring(ses.writepayload, "tcpip-forward", 13); 138 buf_putstring(ses.writepayload, "tcpip-forward", 13);
131 buf_putbyte(ses.writepayload, 1); /* want_reply */ 139 buf_putbyte(ses.writepayload, 1); /* want_reply */
132 if (opts.listen_fwd_all) { 140 buf_putstring(ses.writepayload, addr, strlen(addr));
133 listenspec = "";
134 } else {
135 listenspec = "localhost";
136 }
137 /* TODO: IPv6? */;
138 buf_putstring(ses.writepayload, listenspec, strlen(listenspec));
139 buf_putint(ses.writepayload, port); 141 buf_putint(ses.writepayload, port);
140 142
141 encrypt_packet(); 143 encrypt_packet();
142 144
143 TRACE(("leave send_msg_global_request_remotetcp")) 145 TRACE(("leave send_msg_global_request_remotetcp"))
144 } 146 }
145 147
146 /* The only global success/failure messages are for remotetcp. 148 /* The only global success/failure messages are for remotetcp.
147 * Since there isn't any identifier in these messages, we have to rely on them 149 * Since there isn't any identifier in these messages, we have to rely on them
148 * being in the same order as we sent the requests. This is the ordering 150 * being in the same order as we sent the requests. This is the ordering
149 * of the cli_opts.remotefwds list */ 151 * of the cli_opts.remotefwds list.
152 * If the requested remote port is 0 the listen port will be
153 * dynamically allocated by the server and the port number will be returned
154 * to client and the port number reported to the user. */
150 void cli_recv_msg_request_success() { 155 void cli_recv_msg_request_success() {
151 156 /* We just mark off that we have received the reply,
152 /* Nothing in the packet. We just mark off that we have received the reply,
153 * so that we can report failure for later ones. */ 157 * so that we can report failure for later ones. */
154 struct TCPFwdList * iter = NULL; 158 m_list_elem * iter = NULL;
155 159 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
156 iter = cli_opts.remotefwds; 160 struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
157 while (iter != NULL) { 161 if (!fwd->have_reply) {
158 if (!iter->have_reply) 162 fwd->have_reply = 1;
163 if (fwd->listenport == 0) {
164 /* The server should let us know which port was allocated if we requestd port 0 */
165 int allocport = buf_getint(ses.payload);
166 if (allocport > 0) {
167 dropbear_log(LOG_INFO, "Allocated port %d for remote forward to %s:%d",
168 allocport, fwd->connectaddr, fwd->connectport);
169 }
170 }
171 return;
172 }
173 }
174 }
175
176 void cli_recv_msg_request_failure() {
177 m_list_elem *iter;
178 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
179 struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
180 if (!fwd->have_reply) {
181 fwd->have_reply = 1;
182 dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", fwd->listenport, fwd->connectaddr, fwd->connectport);
183 return;
184 }
185 }
186 }
187
188 void setup_remotetcp() {
189 m_list_elem *iter;
190 TRACE(("enter setup_remotetcp"))
191
192 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
193 struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
194 if (!fwd->listenaddr)
159 { 195 {
160 iter->have_reply = 1; 196 // we store the addresses so that we can compare them
161 return; 197 // when the server sends them back
162 } 198 if (opts.listen_fwd_all) {
163 iter = iter->next; 199 fwd->listenaddr = m_strdup("");
164 } 200 } else {
165 } 201 fwd->listenaddr = m_strdup("localhost");
166 202 }
167 void cli_recv_msg_request_failure() { 203 }
168 struct TCPFwdList * iter = NULL; 204 send_msg_global_request_remotetcp(fwd->listenaddr, fwd->listenport);
169 205 }
170 iter = cli_opts.remotefwds; 206
171 while (iter != NULL) {
172 if (!iter->have_reply)
173 {
174 iter->have_reply = 1;
175 dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", iter->listenport, iter->connectaddr, iter->connectport);
176 return;
177 }
178 iter = iter->next;
179 }
180 }
181
182 void setup_remotetcp() {
183
184 struct TCPFwdList * iter = NULL;
185
186 TRACE(("enter setup_remotetcp"))
187
188 if (cli_opts.remotefwds == NULL) {
189 TRACE(("cli_opts.remotefwds == NULL"))
190 }
191
192 iter = cli_opts.remotefwds;
193
194 while (iter != NULL) {
195 send_msg_global_request_remotetcp(iter->listenport);
196 iter = iter->next;
197 }
198 TRACE(("leave setup_remotetcp")) 207 TRACE(("leave setup_remotetcp"))
199 } 208 }
200 209
201 static int newtcpforwarded(struct Channel * channel) { 210 static int newtcpforwarded(struct Channel * channel) {
202 211
212 char *origaddr = NULL;
203 unsigned int origport; 213 unsigned int origport;
204 struct TCPFwdList * iter = NULL; 214 m_list_elem * iter = NULL;
215 struct TCPFwdEntry *fwd;
205 char portstring[NI_MAXSERV]; 216 char portstring[NI_MAXSERV];
206 int sock; 217 int sock;
207 int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; 218 int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
208 219
209 /* We don't care what address they connected to */ 220 origaddr = buf_getstring(ses.payload, NULL);
210 buf_eatstring(ses.payload);
211
212 origport = buf_getint(ses.payload); 221 origport = buf_getint(ses.payload);
213 222
214 /* Find which port corresponds */ 223 /* Find which port corresponds */
215 iter = cli_opts.remotefwds; 224 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
216 225 fwd = (struct TCPFwdEntry*)iter->item;
217 while (iter != NULL) { 226 if (origport == fwd->listenport
218 if (origport == iter->listenport) { 227 && (strcmp(origaddr, fwd->listenaddr) == 0)) {
219 break; 228 break;
220 } 229 }
221 iter = iter->next;
222 } 230 }
223 231
224 if (iter == NULL) { 232 if (iter == NULL) {
225 /* We didn't request forwarding on that port */ 233 /* We didn't request forwarding on that port */
226 dropbear_log(LOG_INFO, "Server send unrequested port, from port %d", 234 cleantext(origaddr);
227 origport); 235 dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"",
236 origaddr, origport);
228 goto out; 237 goto out;
229 } 238 }
230 239
231 snprintf(portstring, sizeof(portstring), "%d", iter->connectport); 240 snprintf(portstring, sizeof(portstring), "%d", fwd->connectport);
232 sock = connect_remote(iter->connectaddr, portstring, 1, NULL); 241 sock = connect_remote(fwd->connectaddr, portstring, 1, NULL);
233 if (sock < 0) { 242 if (sock < 0) {
234 TRACE(("leave newtcpdirect: sock failed")) 243 TRACE(("leave newtcpdirect: sock failed"))
235 err = SSH_OPEN_CONNECT_FAILED; 244 err = SSH_OPEN_CONNECT_FAILED;
236 goto out; 245 goto out;
237 } 246 }
244 channel->initconn = 1; 253 channel->initconn = 1;
245 254
246 err = SSH_OPEN_IN_PROGRESS; 255 err = SSH_OPEN_IN_PROGRESS;
247 256
248 out: 257 out:
258 m_free(origaddr);
249 TRACE(("leave newtcpdirect: err %d", err)) 259 TRACE(("leave newtcpdirect: err %d", err))
250 return err; 260 return err;
251 } 261 }
252 #endif /* ENABLE_CLI_REMOTETCPFWD */ 262 #endif /* ENABLE_CLI_REMOTETCPFWD */