clientprotocol.c
上传用户:zm130024
上传日期:2007-01-04
资源大小:432k
文件大小:10k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1997, 1998, 1999
  3.  *      Inferno Nettverk A/S, Norway.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. The above copyright notice, this list of conditions and the following
  9.  *    disclaimer must appear in all copies of the software, derivative works
  10.  *    or modified versions, and any portions thereof, aswell as in all
  11.  *    supporting documentation.
  12.  * 2. All advertising materials mentioning features or use of this software
  13.  *    must display the following acknowledgement:
  14.  *      This product includes software developed by
  15.  *      Inferno Nettverk A/S, Norway.
  16.  * 3. The name of the author may not be used to endorse or promote products
  17.  *    derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  *
  30.  * Inferno Nettverk A/S requests users of this software to return to
  31.  *
  32.  *  Software Distribution Coordinator  or  sdc@inet.no
  33.  *  Inferno Nettverk A/S
  34.  *  Oslo Research Park
  35.  *  Gaustadal閑n 21
  36.  *  N-0349 Oslo
  37.  *  Norway
  38.  *
  39.  * any improvements or extensions that they make and grant Inferno Nettverk A/S
  40.  * the rights to redistribute these changes.
  41.  *
  42.  */
  43. #include "common.h"
  44. static const char rcsid[] =
  45. "$Id: clientprotocol.c,v 1.34 1999/09/02 10:41:26 michaels Exp $";
  46. int
  47. socks_sendrequest(s, request)
  48. int s;
  49. const struct request_t *request;
  50. {
  51. const char *function = "socks_sendrequest()";
  52. char requestmem[sizeof(*request)];
  53. char *p = requestmem;
  54. switch (request->version) {
  55. case SOCKS_V4:
  56. /*
  57.  * VN   CD  DSTPORT DSTIP USERID   0
  58.  *  1 + 1  +   2   +  4  +  ?    + 1  = 9 + USERID
  59.  */
  60. /* VN */
  61. memcpy(p, &request->version, sizeof(request->version));
  62. p += sizeof(request->version);
  63. /* CD */
  64. memcpy(p, &request->command, sizeof(request->command));
  65. p += sizeof(request->command);
  66. p = sockshost2mem(&request->host, p, request->version);
  67. *p++ = 0; /* not bothering to send any userid.  Should we? */
  68. break; /* SOCKS_V4 */
  69.  case SOCKS_V5:
  70. /*
  71.  * rfc1928 request:
  72.     *
  73.  * +----+-----+-------+------+----------+----------+
  74.  * |VER | CMD |  FLAG | ATYP | DST.ADDR | DST.PORT |
  75.  * +----+-----+-------+------+----------+----------+
  76.  * | 1  |  1  |   1   |  1   | Variable |    2     |
  77.  * +----+-----+-------+------+----------+----------+
  78.  *   1    1     1      1       > 0         2
  79.  *
  80.  * Which gives a fixed size of minimum 7 octets.
  81.  * The first octet of DST.ADDR when it is SOCKS_ADDR_DOMAINNAME
  82.  * contains the length of DST.ADDR.
  83.  */
  84. /* VER */
  85. memcpy(p, &request->version, sizeof(request->version));
  86. p += sizeof(request->version);
  87. /* CMD */
  88. memcpy(p, &request->command, sizeof(request->command));
  89. p += sizeof(request->command);
  90. /* FLAG */
  91. memcpy(p, &request->flag, sizeof(request->flag));
  92. p += sizeof(request->flag);
  93. p = sockshost2mem(&request->host, p, request->version);
  94. break;
  95.  default:
  96. SERRX(request->version);
  97. }
  98. slog(LOG_DEBUG, "%s: sending request: %s",
  99. function, socks_packet2string(request, SOCKS_REQUEST));
  100. /*
  101.  * Send the request to the server.
  102.  */
  103. if (writen(s, requestmem, (size_t)(p - requestmem)) != p - requestmem) {
  104. swarn("%s: writen()", function);
  105. return -1;
  106. }
  107. return 0;
  108. }
  109. int
  110. socks_recvresponse(s, response, version)
  111. int s;
  112. struct response_t *response;
  113. int version;
  114. {
  115. const char *function = "socks_recvresponse()";
  116. /* get the versionspecific data. */
  117. switch (version) {
  118. case SOCKS_V4: {
  119. /*
  120.  * The socks V4 reply length is fixed:
  121.  * VN   CD  DSTPORT  DSTIP
  122.  *  1 + 1  +   2   +   4
  123.  */
  124. char responsemem[ sizeof(response->version)
  125.  + sizeof(response->reply)
  126.  ];
  127. char *p = responsemem;
  128. if (readn(s, responsemem, sizeof(responsemem)) != sizeof(responsemem)){
  129. swarn("%s: readn()", function);
  130. return -1;
  131. }
  132. /* VN */
  133. memcpy(&response->version, p, sizeof(response->version));
  134. p += sizeof(response->version);
  135. if (response->version != SOCKS_V4REPLY_VERSION) {
  136. swarnx("%s: unexpected version from server (%d != %d)",
  137. function, response->version, SOCKS_V4REPLY_VERSION);
  138. return -1;
  139. }
  140. response->version = SOCKS_V4; /* silly v4 semantics, ignore it. */
  141. /* CD */
  142. memcpy(&response->reply, p, sizeof(response->reply));
  143. p += sizeof(response->reply);
  144. break;
  145. }
  146. case SOCKS_V5: {
  147. /*
  148.  * rfc1928 reply:
  149.  *
  150.  * +----+-----+-------+------+----------+----------+
  151.  * |VER | REP |  FLAG | ATYP | BND.ADDR | BND.PORT |
  152.  * +----+-----+-------+------+----------+----------+
  153.  * | 1  |  1  |   1   |  1   |  > 0     |    2     |
  154.  * +----+-----+-------+------+----------+----------+
  155.  *
  156.  * Which gives a size of >= 7 octets.
  157.  *
  158.  */
  159. char responsemem[sizeof(response->version)
  160. + sizeof(response->reply)
  161. + sizeof(response->flag)
  162. ];
  163. char *p = responsemem;
  164. if (readn(s, responsemem, sizeof(responsemem)) != sizeof(responsemem)){
  165. swarn("%s: readn()", function);
  166. return -1;
  167. }
  168. /* VER */
  169. memcpy(&response->version, p, sizeof(response->version));
  170. p += sizeof(response->version);
  171. if (version != response->version) {
  172. swarnx("%s: unexpected version from server (%d != %d)",
  173. function, version, response->version);
  174. return -1;
  175. }
  176. /* REP */
  177. memcpy(&response->reply, p, sizeof(response->reply));
  178. p += sizeof(response->reply);
  179. /* FLAG */
  180. memcpy(&response->flag, p, sizeof(response->flag));
  181. p += sizeof(response->flag);
  182. break;
  183. }
  184. default:
  185. SERRX(version);
  186. }
  187. if (recv_sockshost(s, &response->host, version) != 0)
  188. return -1;
  189. slog(LOG_DEBUG, "%s: received response: %s",
  190. function, socks_packet2string(response, SOCKS_RESPONSE));
  191. return 0;
  192. }
  193. int
  194. send_interfacerequest(s, ifreq, version)
  195. int s;
  196. const struct interfacerequest_t *ifreq;
  197. int version;
  198. {
  199. char request[sizeof(*ifreq)];
  200. char *p = request;
  201. memcpy(p, &ifreq->rsv, sizeof(ifreq->rsv));
  202. p += sizeof(ifreq->rsv);
  203. memcpy(p, &ifreq->sub, sizeof(ifreq->sub));
  204. p += sizeof(ifreq->sub);
  205. memcpy(p, &ifreq->flag, sizeof(ifreq->flag));
  206. p += sizeof(ifreq->flag);
  207. p = sockshost2mem(&ifreq->host, p, version);
  208. if (writen(s, request, (size_t)(p - request)) != p - request)
  209. return -1;
  210. return 0;
  211. }
  212. int
  213. socks_negotiate(s, control, packet, route)
  214. int s;
  215. int control;
  216. struct socks_t *packet;
  217. struct route_t *route;
  218. {
  219. switch (packet->req.version) {
  220. case SOCKS_V5:
  221. if (negotiate_method(control, packet) != 0)
  222. return -1;
  223. /* FALLTHROUGH */ /* rest is like v4, which doesn't have method. */
  224. case SOCKS_V4:
  225. if (socks_sendrequest(control, &packet->req) != 0)
  226. return -1;
  227. if (socks_recvresponse(control, &packet->res, packet->req.version)
  228. != 0)
  229. return -1;
  230. break;
  231. case MSPROXY_V2:
  232. msproxy_negotiate(s, control, packet);
  233. break;
  234. default:
  235. SERRX(packet->req.version);
  236. }
  237. if (!serverreplyisok(packet->res.version, packet->res.reply, route))
  238. return -1;
  239. return 0;
  240. }
  241. int
  242. recv_sockshost(s, host, version)
  243. int s;
  244. struct sockshost_t *host;
  245. int version;
  246. {
  247. const char *function = "recv_sockshost()";
  248. switch (version) {
  249. case SOCKS_V4: {
  250. /*
  251.  * DSTPORT  DSTIP
  252.  *   2    +   4
  253.  */
  254. char hostmem[ sizeof(host->port)
  255.    + sizeof(host->addr.ipv4)
  256. ];
  257. char *p = hostmem;
  258. if (readn(s, hostmem, sizeof(hostmem)) != sizeof(hostmem)){
  259. swarn("%s: readn()", function);
  260. return -1;
  261. }
  262. host->atype = SOCKS_ADDR_IPV4;
  263. /* BND.PORT */
  264. memcpy(&host->port, p, sizeof(host->port));
  265. p += sizeof(host->port);
  266. /* BND.ADDR */
  267. memcpy(&host->addr.ipv4, p, sizeof(host->addr.ipv4));
  268. p += sizeof(host->addr.ipv4);
  269. break;
  270. }
  271. case SOCKS_V5:
  272. /*
  273.  * +------+----------+----------+
  274.  * | ATYP | BND.ADDR | BND.PORT |
  275.  * +------+----------+----------+
  276.  * |  1   |  > 0     |    2     |
  277.  * +------+----------+----------+
  278.  */
  279. /* ATYP */
  280. if (readn(s, &host->atype, sizeof(host->atype)) != sizeof(host->atype))
  281. return -1;
  282. switch(host->atype) {
  283. case SOCKS_ADDR_IPV4:
  284. if (readn(s, &host->addr.ipv4, sizeof(host->addr.ipv4))
  285. != sizeof(host->addr.ipv4)) {
  286. swarn("%s: readn()", function);
  287. return -1;
  288. }
  289. break;
  290. case SOCKS_ADDR_IPV6:
  291. if (readn(s, host->addr.ipv6, sizeof(host->addr.ipv6))
  292. != sizeof(host->addr.ipv6)) {
  293. swarn("%s: readn()", function);
  294. return -1;
  295. }
  296. break;
  297. case SOCKS_ADDR_DOMAIN: {
  298. unsigned char alen;
  299. /* read length of domainname. */
  300. if (readn(s, &alen, sizeof(alen)) < (ssize_t)sizeof(alen))
  301. return -1;
  302. OCTETIFY(alen);
  303. SASSERTX(alen < sizeof(host->addr.domain));
  304. /* BND.ADDR, alen octets */
  305. if (readn(s, host->addr.domain, (size_t)alen) != (ssize_t)alen) {
  306. swarn("%s: readn()", function);
  307. return -1;
  308. }
  309. host->addr.domain[alen] = NUL;
  310. break;
  311. }
  312. default:
  313. swarnx("%s: unsupported address format %d in reply",
  314. function, host->atype);
  315. return -1;
  316. }
  317. /* BND.PORT */
  318. if (readn(s, &host->port, sizeof(host->port)) != sizeof(host->port))
  319. return -1;
  320. break;
  321. }
  322. return 0;
  323. }