Mercurial > dropbear
comparison svr-tcpfwd.c @ 62:20563735e8b5
just checkpointing
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 10 Aug 2004 17:09:52 +0000 |
parents | |
children | dcc43965928f |
comparison
equal
deleted
inserted
replaced
61:3a4f0ef1e8c3 | 62:20563735e8b5 |
---|---|
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 | |
107 return (info1->port == info2->port) | |
108 && (info1->chantype == info2->chantype) | |
109 && (strcmp(info1->addr, info2->addr) == 0); | |
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 | |
131 tcpinfo.addr = bindaddr; | |
132 tcpinfo.port = port; | |
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 | |
155 bindaddr = buf_getstring(ses.payload, &addrlen); | |
156 if (addrlen > MAX_IP_LEN) { | |
157 TRACE(("addr len too long: %d", addrlen)); | |
158 goto out; | |
159 } | |
160 | |
161 port = buf_getint(ses.payload); | |
162 | |
163 if (port == 0) { | |
164 dropbear_log(LOG_INFO, "Server chosen tcpfwd ports are unsupported"); | |
165 goto out; | |
166 } | |
167 | |
168 if (port < 1 || port > 65535) { | |
169 TRACE(("invalid port: %d", port)); | |
170 goto out; | |
171 } | |
172 | |
173 if (!ses.allowprivport && port < IPPORT_RESERVED) { | |
174 TRACE(("can't assign port < 1024 for non-root")); | |
175 goto out; | |
176 } | |
177 | |
178 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener)); | |
179 tcpinfo->addr = bindaddr; | |
180 tcpinfo->port = port; | |
181 tcpinfo->localport = -1; | |
182 tcpinfo->chantype = &svr_chan_tcpremote; | |
183 | |
184 ret = listen_tcpfwd(tcpinfo); | |
185 | |
186 out: | |
187 if (ret == DROPBEAR_FAILURE) { | |
188 /* we only free it if a listener wasn't created, since the listener | |
189 * has to remember it if it's to be cancelled */ | |
190 m_free(tcpinfo->addr); | |
191 m_free(tcpinfo); | |
192 } | |
193 TRACE(("leave remotetcpreq")); | |
194 return ret; | |
195 } | |
196 #endif |