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

代理服务器

开发平台:

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: sockd_protocol.c,v 1.79 1999/12/12 18:13:56 michaels Exp $";
  46. __BEGIN_DECLS
  47. static int
  48. recv_v4req __P((int s, struct request_t *request,
  49.  struct negotiate_state_t *state));
  50. static int
  51. recv_v5req __P((int s, struct request_t *request,
  52.  struct negotiate_state_t *state));
  53. static int
  54. recv_methods __P((int s, struct request_t *request,
  55. struct negotiate_state_t *state));
  56. static int
  57. recv_ver __P((int s, struct request_t *request,
  58.   struct negotiate_state_t *state));
  59. static int
  60. recv_cmd __P((int s, struct request_t *request,
  61.   struct negotiate_state_t *state));
  62. static int
  63. recv_flag __P((int s, struct request_t *request,
  64. struct negotiate_state_t *state));
  65. static int
  66. recv_sockshost __P((int s, struct request_t *request,
  67.   struct negotiate_state_t *state));
  68. static int
  69. recv_atyp __P((int s, struct request_t *request,
  70. struct negotiate_state_t *state));
  71. static int
  72. recv_port __P((int s, struct request_t *request,
  73. struct negotiate_state_t *state));
  74. static int
  75. recv_address __P((int s, struct request_t *request,
  76.    struct negotiate_state_t *state));
  77. static int
  78. recv_domain __P((int s, struct request_t *request,
  79.   struct negotiate_state_t *state));
  80. static int
  81. recv_username __P((int s, struct request_t *request,
  82.  struct negotiate_state_t *state));
  83. static int
  84. methodnegotiate __P((int s, struct request_t *request,
  85. struct negotiate_state_t *state));
  86. __END_DECLS
  87. int
  88. recv_request(s, request, state)
  89. int s;
  90. struct request_t *request;
  91. struct negotiate_state_t *state;
  92. {
  93. int rc;
  94. if (state->complete)
  95. return 1;
  96. if (state->rcurrent != NULL) /* not first call on this client. */
  97. rc = state->rcurrent(s, request, state);
  98. else {
  99. INIT(sizeof(request->version));
  100. CHECK(&request->version, NULL);
  101. switch (request->version) {
  102. case SOCKS_V4:
  103. state->rcurrent = recv_v4req;
  104. break;
  105. case SOCKS_V5:
  106. state->rcurrent = recv_v5req;
  107. break;
  108. default:
  109. slog(LOG_DEBUG, "unknown version %d in request", request->version);
  110. return -1;
  111. }
  112. rc = state->rcurrent(s, request, state);
  113. }
  114. state->complete = rc > 0; /* complete request read? */
  115. return rc;
  116. }
  117. int
  118. recv_sockspacket(s, request, state)
  119. int s;
  120. struct request_t *request;
  121. struct negotiate_state_t *state;
  122. {
  123. return recv_ver(s, request, state);
  124. }
  125. static int
  126. recv_v4req (s, request, state)
  127. int s;
  128. struct request_t *request;
  129. struct negotiate_state_t *state;
  130. {
  131. /*
  132.  * v4 request:
  133.  * VN   CD   DSTPORT  DSTIP  USERID   NUL
  134.  * 1  + 1  +  2     +  4   +  ?     +  1
  135.  *
  136.  * so minimum length is 9.
  137.     */
  138. /* CD */
  139. state->rcurrent = recv_cmd;
  140. return state->rcurrent(s, request, state);
  141. }
  142. static int
  143. recv_v5req (s, request, state)
  144. int s;
  145. struct request_t *request;
  146. struct negotiate_state_t *state;
  147. {
  148. /*
  149.  * method negotiation;
  150.  * client first sends method selection message:
  151.  *
  152.  * +----+----------+----------+
  153.  * |VER | NMETHODS | METHODS  |
  154.  * +----+----------+----------+
  155.  * | 1  |    1     | 1 to 255 |
  156.  * +----+----------+----------+
  157.  */
  158. /*
  159.  * then the request:
  160.  *
  161.  * +----+-----+-------+------+----------+----------+
  162.  * |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
  163.  * +----+-----+-------+------+----------+----------+
  164.  * | 1  |  1  | X'00' |  1   | Variable |    2     |
  165.  * +----+-----+-------+------+----------+----------+
  166.  *
  167.  *   1     1      1      1        ?          2
  168.  *
  169.  * Since the request can contain different address types
  170.  * we do not know how long the request is before we have
  171.  * read the address type (ATYP) field.
  172.  *
  173.  */
  174. /* NMETHODS */
  175. INIT(sizeof(char));
  176. CHECK(&state->mem[start], NULL);
  177. OCTETIFY(state->mem[start]);
  178. state->rcurrent = recv_methods;
  179. return state->rcurrent(s, request, state);
  180. }
  181. static int
  182. recv_methods(s, request, state)
  183. int s;
  184. struct request_t *request;
  185. struct negotiate_state_t *state;
  186. {
  187. const char *function = "recv_methods()";
  188. const unsigned char methodc = state->mem[state->reqread - 1]; /* NMETHODS */
  189. char reply[ 1 /* VERSION */
  190.  + 1 /* METHOD */
  191.  ];
  192. INIT(methodc);
  193. CHECK(&state->mem[start], NULL);
  194. request->auth->method = selectmethod(&state->mem[start], (size_t)methodc);
  195. /* send reply:
  196.  *
  197.  * +----+--------+
  198.  * |VER | METHOD |
  199.  * +----+--------+
  200.  * | 1  |   1    |
  201.  * +----+--------+
  202.     */
  203. slog(LOG_DEBUG, "%s: sending authentication reply: VER: %d METHOD: %d",
  204. function, request->version, request->auth->method);
  205. reply[AUTH_VERSION] = request->version;
  206. reply[AUTH_METHOD] = (char)request->auth->method;
  207. if (writen(s, reply, sizeof(reply)) != sizeof(reply))
  208. return -1;
  209. if (request->auth->method == AUTHMETHOD_NOACCEPT)
  210. return -1;
  211. state->rcurrent = methodnegotiate;
  212. return state->rcurrent(s, request, state);
  213. }
  214. static int
  215. methodnegotiate(s, request, state)
  216. int s;
  217. struct request_t *request;
  218. struct negotiate_state_t *state;
  219. {
  220. /* authentication method dependent negotiation */
  221. switch (request->auth->method) {
  222. case AUTHMETHOD_NONE:
  223. state->rcurrent = recv_sockspacket;
  224. break;
  225. case AUTHMETHOD_UNAME:
  226. state->rcurrent = method_uname;
  227. break;
  228. default:
  229. SERRX(request->auth->method);
  230. }
  231. return state->rcurrent(s, request, state);
  232. }
  233. static int
  234. recv_ver(s, request, state)
  235. int s;
  236. struct request_t *request;
  237. struct negotiate_state_t *state;
  238. {
  239. /* VER */
  240. {
  241. INIT(sizeof(request->version));
  242. CHECK(&request->version, NULL);
  243. switch (request->version) {
  244. case SOCKS_V4:
  245. case SOCKS_V5:
  246. break;
  247. default:
  248. slog(LOG_DEBUG, "unknown version %d in request", request->version);
  249. return -1;
  250. }
  251. }
  252. state->rcurrent = recv_cmd;
  253. return state->rcurrent(s, request, state);
  254. }
  255. static int
  256. recv_cmd(s, request, state)
  257. int s;
  258. struct request_t *request;
  259. struct negotiate_state_t *state;
  260. {
  261. INIT(sizeof(request->command));
  262. CHECK(&request->command, NULL);
  263. switch (request->version) {
  264. case SOCKS_V4:
  265. state->rcurrent = recv_sockshost;
  266. break;
  267. case SOCKS_V5:
  268. state->rcurrent = recv_flag;
  269. break;
  270. default:
  271. SERRX(request->version);
  272. }
  273. return state->rcurrent(s, request, state);
  274. }
  275. static int
  276. recv_flag(s, request, state)
  277. int s;
  278. struct request_t *request;
  279. struct negotiate_state_t *state;
  280. {
  281. INIT(sizeof(request->flag));
  282. CHECK(&request->flag, recv_sockshost);
  283. SERRX(0); /* NOTREACHED */
  284. }
  285. static int
  286. recv_sockshost(s, request, state)
  287. int s;
  288. struct request_t *request;
  289. struct negotiate_state_t *state;
  290. {
  291. switch (request->version) {
  292. case SOCKS_V4:
  293. state->rcurrent = recv_port;
  294. break;
  295. case SOCKS_V5:
  296. state->rcurrent = recv_atyp;
  297. break;
  298. default:
  299. SERRX(request->version);
  300. }
  301. return state->rcurrent(s, request, state);
  302. }
  303. static int
  304. recv_atyp(s, request, state)
  305. int s;
  306. struct request_t *request;
  307. struct negotiate_state_t *state;
  308. {
  309. INIT(sizeof(request->host.atype));
  310. CHECK(&request->host.atype, recv_address);
  311. SERRX(0); /* NOTREACHED */
  312. }
  313. static int
  314. recv_address(s, request, state)
  315. int s;
  316. struct request_t *request;
  317. struct negotiate_state_t *state;
  318. {
  319. switch (request->version) {
  320. case SOCKS_V4: {
  321. INIT(sizeof(request->host.addr.ipv4));
  322. request->host.atype = SOCKS_ADDR_IPV4; /* only one supported in v4. */
  323. CHECK(&request->host.addr.ipv4, recv_username);
  324. SERRX(0); /* NOTREACHED */
  325. }
  326. case SOCKS_V5:
  327. switch(request->host.atype) {
  328. case SOCKS_ADDR_IPV4: {
  329. INIT(sizeof(request->host.addr.ipv4));
  330. CHECK(&request->host.addr.ipv4, recv_port);
  331. SERRX(0); /* NOTREACHED */
  332. }
  333. case SOCKS_ADDR_IPV6: {
  334. INIT(sizeof(request->host.addr.ipv6));
  335. CHECK(&request->host.addr.ipv6, recv_port);
  336. SERRX(0); /* NOTREACHED */
  337. }
  338. case SOCKS_ADDR_DOMAIN: {
  339. INIT(sizeof(*request->host.addr.domain));
  340. CHECK(request->host.addr.domain, NULL);
  341. OCTETIFY(*request->host.addr.domain);
  342. state->rcurrent = recv_domain;
  343. return state->rcurrent(s, request, state);
  344. }
  345. default:
  346. slog(LOG_DEBUG, "unknown address format %d in reply",
  347. request->host.atype);
  348. return -1;
  349. }
  350. default:
  351. SERRX(request->version);
  352. }
  353. SERRX(0); /* NOTREACHED */
  354. }
  355. static int
  356. recv_domain(s, request, state)
  357. int s;
  358. struct request_t *request;
  359. struct negotiate_state_t *state;
  360. {
  361. size_t alen;
  362. INIT(*request->host.addr.domain); /* first byte gives length. */
  363. CHECK(request->host.addr.domain + 1, NULL);
  364. alen = (size_t)*request->host.addr.domain;
  365. /* convert to C string. */
  366. memmove(request->host.addr.domain, request->host.addr.domain + 1, alen);
  367. request->host.addr.domain[alen] = NUL;
  368. state->rcurrent = recv_port;
  369. return state->rcurrent(s, request, state);
  370. }
  371. static int
  372. recv_port(s, request, state)
  373. int s;
  374. struct request_t *request;
  375. struct negotiate_state_t *state;
  376. {
  377. INIT(sizeof(request->host.port));
  378. CHECK(&request->host.port, NULL);
  379. switch (request->version) {
  380. case SOCKS_V4:
  381. state->rcurrent = recv_address; /* in v4, address after port. */
  382. return state->rcurrent(s, request, state);
  383. case SOCKS_V5:
  384. return 1; /* all done. */
  385. default:
  386. SERRX(request->version);
  387. }
  388. SERRX(0); /* NOTREACHED */
  389. }
  390. static int
  391. recv_username(s, request, state)
  392. int s;
  393. struct request_t *request;
  394. struct negotiate_state_t *state;
  395. {
  396. const char *function = "recv_username()";
  397. char *username = &state->mem[sizeof(request->version)
  398. + sizeof(request->command)
  399. + sizeof(request->host.port)
  400. + sizeof(request->host.addr.ipv4)];
  401. /* read until 0. */
  402. do {
  403. INIT(MIN(1, MEMLEFT()));
  404. if (MEMLEFT() == 0) {
  405. /*
  406.  * Normally this would indicate an internal error and thus
  407.  * be caught in CHECK(), but for the v4 case it could be
  408.  * someone sending a really long username, which is strange
  409.  * enough to log a warning about but not an internal error.
  410.  */
  411. state->mem[state->reqread - 1] = NUL;
  412. slog(LOG_WARNING, "%s: too long username (> %d): "%s"",
  413. function, strlen(username),
  414. strcheck(username = str2vis(username, strlen(username))));
  415. free(username);
  416. return -1;
  417. }
  418. CHECK(&state->mem[start], NULL);
  419. } while (state->mem[state->reqread - 1] != 0);
  420. state->mem[state->reqread - 1] = NUL; /* style. */
  421. slog(LOG_DEBUG, "%s: got socks v4 username: %s",
  422. function, strcheck(username = str2vis(username, strlen(username))));
  423. free(username);
  424. return 1; /* end of request. */
  425. }
  426. void
  427. send_failure(s, response, failure)
  428. int s;
  429. const struct response_t *response;
  430. int failure;
  431. {
  432. struct response_t newresponse; /* keep const. */
  433. newresponse = *response;
  434. newresponse.reply = (char)sockscode(newresponse.version, failure);
  435. send_response(s, &newresponse);
  436. }
  437. int
  438. send_response(s, response)
  439. int s;
  440. const struct response_t *response;
  441. {
  442. const char *function = "send_response()";
  443. size_t length;
  444. char responsemem[sizeof(*response)];
  445. char *p = responsemem;
  446. switch (response->version) {
  447. case SOCKS_V4REPLY_VERSION:
  448. /*
  449.  * socks V4 reply packet:
  450.  *
  451.  *  VN   CD  DSTPORT  DSTIP
  452.  *  1  + 1  +  2    +  4
  453.  *
  454.  *  Always 8 octets long.
  455.  */
  456. memcpy(p, &response->version, sizeof(response->version));
  457. p += sizeof(response->version);
  458. /* CD (reply) */
  459. memcpy(p, &response->reply, sizeof(response->reply));
  460. p += sizeof(response->reply);
  461. break;
  462. case SOCKS_V5:
  463. /*
  464.  * socks V5 reply:
  465.  *
  466.  * +----+-----+-------+------+----------+----------+
  467.  * |VER | REP |  FLAG | ATYP | BND.ADDR | BND.PORT |
  468.  * +----+-----+-------+------+----------+----------+
  469.  * | 1  |  1  |   1   |  1   | Variable |    2     |
  470.  * +----+-----+-------+------+----------+----------+
  471.  *   1     1      1      1                   2
  472.  *
  473.  * Which gives a fixed size of atleast 6 octets.
  474.  * The first octet of DST.ADDR when it is SOCKS_ADDR_DOMAINNAME
  475.  * contains the length.
  476.  *
  477.  */
  478. /* VER */
  479. memcpy(p, &response->version, sizeof(response->version));
  480. p += sizeof(response->version);
  481. /* REP */
  482. memcpy(p, &response->reply, sizeof(response->reply));
  483. p += sizeof(response->reply);
  484. /* FLAG */
  485. memcpy(p, &response->flag, sizeof(response->flag));
  486. p += sizeof(response->flag);
  487. break;
  488. default:
  489. SERRX(response->version);
  490. }
  491. p = sockshost2mem(&response->host, p, response->version);
  492. length = p - responsemem;
  493. slog(LOG_DEBUG, "%s: sending response: %s",
  494. function, socks_packet2string(response, SOCKS_RESPONSE));
  495. if (writen(s, responsemem, length) != (ssize_t)length) {
  496. swarn("%s: writen()", function);
  497. return -1;
  498. }
  499. return 0;
  500. }