ssl.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:15k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: ssl.c,v 1.92 1999/01/29 23:39:23 wessels Exp $
  3.  *
  4.  * DEBUG: section 26    Secure Sockets Layer Proxy
  5.  * AUTHOR: Duane Wessels
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. typedef struct {
  36.     char *url;
  37.     char *host; /* either request->host or proxy host */
  38.     u_short port;
  39.     request_t *request;
  40.     struct {
  41. int fd;
  42. int len;
  43. char *buf;
  44.     } client, server;
  45.     size_t *size_ptr; /* pointer to size in an ConnStateData for logging */
  46.     int proxying;
  47. #if DELAY_POOLS
  48.     delay_id delay_id;
  49. #endif
  50. } SslStateData;
  51. static const char *const conn_established = "HTTP/1.0 200 Connection establishedrnrn";
  52. static CNCB sslConnectDone;
  53. static ERCB sslErrorComplete;
  54. static PF sslServerClosed;
  55. static PF sslClientClosed;
  56. static PF sslReadClient;
  57. static PF sslReadServer;
  58. static PF sslTimeout;
  59. static PF sslWriteClient;
  60. static PF sslWriteServer;
  61. static PSC sslPeerSelectComplete;
  62. static void sslStateFree(SslStateData * sslState);
  63. static void sslConnected(int fd, void *);
  64. static void sslProxyConnected(int fd, void *);
  65. static void sslSetSelect(SslStateData * sslState);
  66. #if DELAY_POOLS
  67. static DEFER sslDeferServerRead;
  68. #endif
  69. static void
  70. sslServerClosed(int fd, void *data)
  71. {
  72.     SslStateData *sslState = data;
  73.     debug(26, 3) ("sslServerClosed: FD %dn", fd);
  74.     assert(fd == sslState->server.fd);
  75.     sslState->server.fd = -1;
  76.     if (sslState->client.fd == -1)
  77. sslStateFree(sslState);
  78. }
  79. static void
  80. sslClientClosed(int fd, void *data)
  81. {
  82.     SslStateData *sslState = data;
  83.     debug(26, 3) ("sslClientClosed: FD %dn", fd);
  84.     assert(fd == sslState->client.fd);
  85.     sslState->client.fd = -1;
  86.     if (sslState->server.fd == -1)
  87. sslStateFree(sslState);
  88. }
  89. static void
  90. sslStateFree(SslStateData * sslState)
  91. {
  92.     debug(26, 3) ("sslStateFree: sslState=%pn", sslState);
  93.     assert(sslState != NULL);
  94.     assert(sslState->client.fd == -1);
  95.     assert(sslState->server.fd == -1);
  96.     safe_free(sslState->server.buf);
  97.     safe_free(sslState->client.buf);
  98.     safe_free(sslState->url);
  99.     sslState->host = NULL;
  100.     requestUnlink(sslState->request);
  101.     sslState->request = NULL;
  102.     cbdataFree(sslState);
  103. }
  104. #if DELAY_POOLS
  105. static int
  106. sslDeferServerRead(int fdnotused, void *data)
  107. {
  108.     SslStateData *s = data;
  109.     return delayBytesWanted(s->delay_id, 0, 1) == 0;
  110. }
  111. #endif
  112. static void
  113. sslSetSelect(SslStateData * sslState)
  114. {
  115.     size_t read_sz = SQUID_TCP_SO_RCVBUF;
  116.     assert(sslState->server.fd > -1 || sslState->client.fd > -1);
  117.     if (sslState->client.fd > -1) {
  118. if (sslState->server.len > 0) {
  119.     commSetSelect(sslState->client.fd,
  120. COMM_SELECT_WRITE,
  121. sslWriteClient,
  122. sslState,
  123. 0);
  124. }
  125. if (sslState->client.len < read_sz) {
  126.     commSetSelect(sslState->client.fd,
  127. COMM_SELECT_READ,
  128. sslReadClient,
  129. sslState,
  130. Config.Timeout.read);
  131. }
  132.     } else if (sslState->client.len == 0) {
  133. comm_close(sslState->server.fd);
  134.     }
  135.     if (sslState->server.fd > -1) {
  136. if (sslState->client.len > 0) {
  137.     commSetSelect(sslState->server.fd,
  138. COMM_SELECT_WRITE,
  139. sslWriteServer,
  140. sslState,
  141. 0);
  142. }
  143. #if DELAY_POOLS
  144. /* If this was allowed to return 0, there would be a possibility
  145.  * of the socket becoming "hung" with data accumulating but no
  146.  * write handler (server.len==0) and no read handler (!(0<0)) and
  147.  * no data flowing in the other direction.  Hence the argument of
  148.  * 1 as min.
  149.  */
  150. read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
  151. #endif
  152. if (sslState->server.len < read_sz) {
  153.     /* Have room to read more */
  154.     commSetSelect(sslState->server.fd,
  155. COMM_SELECT_READ,
  156. sslReadServer,
  157. sslState,
  158. Config.Timeout.read);
  159. }
  160.     } else if (sslState->client.fd == -1) {
  161. /* client already closed, nothing more to do */
  162.     } else if (sslState->server.len == 0) {
  163. comm_close(sslState->client.fd);
  164.     }
  165. }
  166. /* Read from server side and queue it for writing to the client */
  167. static void
  168. sslReadServer(int fd, void *data)
  169. {
  170.     SslStateData *sslState = data;
  171.     int len;
  172.     size_t read_sz = SQUID_TCP_SO_RCVBUF - sslState->server.len;
  173.     assert(fd == sslState->server.fd);
  174.     debug(26, 3) ("sslReadServer: FD %d, reading %d bytes at offset %dn",
  175. fd, read_sz, sslState->server.len);
  176.     errno = 0;
  177. #if DELAY_POOLS
  178.     read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
  179. #endif
  180.     Counter.syscalls.sock.reads++;
  181.     len = read(fd, sslState->server.buf + sslState->server.len, read_sz);
  182.     debug(26, 3) ("sslReadServer: FD %d, read   %d bytesn", fd, len);
  183.     if (len > 0) {
  184. fd_bytes(fd, len, FD_READ);
  185. #if DELAY_POOLS
  186. delayBytesIn(sslState->delay_id, len);
  187. #endif
  188. kb_incr(&Counter.server.all.kbytes_in, len);
  189. kb_incr(&Counter.server.other.kbytes_in, len);
  190. sslState->server.len += len;
  191.     }
  192.     cbdataLock(sslState);
  193.     if (len < 0) {
  194. debug(50, 1) ("sslReadServer: FD %d: read failure: %sn",
  195.     fd, xstrerror());
  196. if (!ignoreErrno(errno))
  197.     comm_close(fd);
  198.     } else if (len == 0) {
  199. comm_close(sslState->server.fd);
  200.     }
  201.     if (cbdataValid(sslState))
  202. sslSetSelect(sslState);
  203.     cbdataUnlock(sslState);
  204. }
  205. /* Read from client side and queue it for writing to the server */
  206. static void
  207. sslReadClient(int fd, void *data)
  208. {
  209.     SslStateData *sslState = data;
  210.     int len;
  211.     assert(fd == sslState->client.fd);
  212.     debug(26, 3) ("sslReadClient: FD %d, reading %d bytes at offset %dn",
  213. fd, SQUID_TCP_SO_RCVBUF - sslState->client.len,
  214. sslState->client.len);
  215.     Counter.syscalls.sock.reads++;
  216.     len = read(fd,
  217. sslState->client.buf + sslState->client.len,
  218. SQUID_TCP_SO_RCVBUF - sslState->client.len);
  219.     debug(26, 3) ("sslReadClient: FD %d, read   %d bytesn", fd, len);
  220.     if (len > 0) {
  221. fd_bytes(fd, len, FD_READ);
  222. kb_incr(&Counter.client_http.kbytes_in, len);
  223. sslState->client.len += len;
  224.     }
  225.     cbdataLock(sslState);
  226.     if (len < 0) {
  227. debug(50, 1) ("sslReadClient: FD %d: read failure: %sn",
  228.     fd, xstrerror());
  229. if (!ignoreErrno(errno))
  230.     comm_close(fd);
  231.     } else if (len == 0) {
  232. comm_close(fd);
  233.     }
  234.     if (cbdataValid(sslState))
  235. sslSetSelect(sslState);
  236.     cbdataUnlock(sslState);
  237. }
  238. /* Writes data from the client buffer to the server side */
  239. static void
  240. sslWriteServer(int fd, void *data)
  241. {
  242.     SslStateData *sslState = data;
  243.     int len;
  244.     assert(fd == sslState->server.fd);
  245.     debug(26, 3) ("sslWriteServer: FD %d, %d bytes to writen",
  246. fd, sslState->client.len);
  247.     Counter.syscalls.sock.writes++;
  248.     len = write(fd,
  249. sslState->client.buf,
  250. sslState->client.len);
  251.     debug(26, 3) ("sslWriteServer: FD %d, %d bytes writtenn", fd, len);
  252.     if (len > 0) {
  253. fd_bytes(fd, len, FD_WRITE);
  254. kb_incr(&Counter.server.all.kbytes_out, len);
  255. kb_incr(&Counter.server.other.kbytes_out, len);
  256. assert(len <= sslState->client.len);
  257. sslState->client.len -= len;
  258. if (sslState->client.len > 0) {
  259.     /* we didn't write the whole thing */
  260.     xmemmove(sslState->client.buf,
  261. sslState->client.buf + len,
  262. sslState->client.len);
  263. }
  264.     }
  265.     cbdataLock(sslState);
  266.     if (len < 0) {
  267. debug(50, 1) ("sslWriteServer: FD %d: write failure: %s.n",
  268.     fd, xstrerror());
  269. if (!ignoreErrno(errno))
  270.     comm_close(fd);
  271.     }
  272.     if (cbdataValid(sslState))
  273. sslSetSelect(sslState);
  274.     cbdataUnlock(sslState);
  275. }
  276. /* Writes data from the server buffer to the client side */
  277. static void
  278. sslWriteClient(int fd, void *data)
  279. {
  280.     SslStateData *sslState = data;
  281.     int len;
  282.     assert(fd == sslState->client.fd);
  283.     debug(26, 3) ("sslWriteClient: FD %d, %d bytes to writen",
  284. fd, sslState->server.len);
  285.     Counter.syscalls.sock.writes++;
  286.     len = write(fd,
  287. sslState->server.buf,
  288. sslState->server.len);
  289.     debug(26, 3) ("sslWriteClient: FD %d, %d bytes writtenn", fd, len);
  290.     if (len > 0) {
  291. fd_bytes(fd, len, FD_WRITE);
  292. kb_incr(&Counter.client_http.kbytes_out, len);
  293. assert(len <= sslState->server.len);
  294. sslState->server.len -= len;
  295. /* increment total object size */
  296. if (sslState->size_ptr)
  297.     *sslState->size_ptr += len;
  298. if (sslState->server.len > 0) {
  299.     /* we didn't write the whole thing */
  300.     xmemmove(sslState->server.buf,
  301. sslState->server.buf + len,
  302. sslState->server.len);
  303. }
  304.     }
  305.     cbdataLock(sslState);
  306.     if (len < 0) {
  307. debug(50, 1) ("sslWriteClient: FD %d: write failure: %s.n",
  308.     fd, xstrerror());
  309. if (!ignoreErrno(errno))
  310.     comm_close(fd);
  311.     }
  312.     if (cbdataValid(sslState))
  313. sslSetSelect(sslState);
  314.     cbdataUnlock(sslState);
  315. }
  316. static void
  317. sslTimeout(int fd, void *data)
  318. {
  319.     SslStateData *sslState = data;
  320.     debug(26, 3) ("sslTimeout: FD %dn", fd);
  321.     if (sslState->client.fd > -1)
  322. comm_close(sslState->client.fd);
  323.     if (sslState->server.fd > -1)
  324. comm_close(sslState->server.fd);
  325. }
  326. static void
  327. sslConnected(int fd, void *data)
  328. {
  329.     SslStateData *sslState = data;
  330.     debug(26, 3) ("sslConnected: FD %d sslState=%pn", fd, sslState);
  331.     xstrncpy(sslState->server.buf, conn_established, SQUID_TCP_SO_RCVBUF);
  332.     sslState->server.len = strlen(conn_established);
  333.     sslSetSelect(sslState);
  334. }
  335. static void
  336. sslErrorComplete(int fdnotused, void *data, size_t sizenotused)
  337. {
  338.     SslStateData *sslState = data;
  339.     assert(sslState != NULL);
  340.     if (sslState->client.fd > -1)
  341. comm_close(sslState->client.fd);
  342.     if (sslState->server.fd > -1)
  343. comm_close(sslState->server.fd);
  344. }
  345. static void
  346. sslConnectDone(int fdnotused, int status, void *data)
  347. {
  348.     SslStateData *sslState = data;
  349.     request_t *request = sslState->request;
  350.     ErrorState *err = NULL;
  351.     if (status == COMM_ERR_DNS) {
  352. debug(26, 4) ("sslConnect: Unknown host: %sn", sslState->host);
  353. err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND);
  354. err->request = requestLink(request);
  355. err->dnsserver_msg = xstrdup(dns_error_message);
  356. err->callback = sslErrorComplete;
  357. err->callback_data = sslState;
  358. errorSend(sslState->client.fd, err);
  359.     } else if (status != COMM_OK) {
  360. err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
  361. err->xerrno = errno;
  362. err->host = xstrdup(sslState->host);
  363. err->port = sslState->port;
  364. err->request = requestLink(request);
  365. err->callback = sslErrorComplete;
  366. err->callback_data = sslState;
  367. errorSend(sslState->client.fd, err);
  368.     } else {
  369. if (sslState->proxying)
  370.     sslProxyConnected(sslState->server.fd, sslState);
  371. else
  372.     sslConnected(sslState->server.fd, sslState);
  373. commSetTimeout(sslState->server.fd,
  374.     Config.Timeout.read,
  375.     sslTimeout,
  376.     sslState);
  377. #if DELAY_POOLS
  378. commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
  379. #endif
  380.     }
  381. }
  382. void
  383. sslStart(int fd, const char *url, request_t * request, size_t * size_ptr)
  384. {
  385.     /* Create state structure. */
  386.     SslStateData *sslState = NULL;
  387.     int sock;
  388.     ErrorState *err = NULL;
  389.     debug(26, 3) ("sslStart: '%s %s'n",
  390. RequestMethodStr[request->method], url);
  391.     Counter.server.all.requests++;
  392.     Counter.server.other.requests++;
  393.     /* Create socket. */
  394.     sock = comm_open(SOCK_STREAM,
  395. 0,
  396. Config.Addrs.tcp_outgoing,
  397. 0,
  398. COMM_NONBLOCKING,
  399. url);
  400.     if (sock == COMM_ERROR) {
  401. debug(26, 4) ("sslStart: Failed because we're out of sockets.n");
  402. err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
  403. err->xerrno = errno;
  404. err->request = requestLink(request);
  405. errorSend(fd, err);
  406. return;
  407.     }
  408.     sslState = xcalloc(1, sizeof(SslStateData));
  409.     cbdataAdd(sslState, cbdataXfree, 0);
  410. #if DELAY_POOLS
  411.     sslState->delay_id = delayClient(request);
  412. #endif
  413.     sslState->url = xstrdup(url);
  414.     sslState->request = requestLink(request);
  415.     sslState->size_ptr = size_ptr;
  416.     sslState->client.fd = fd;
  417.     sslState->server.fd = sock;
  418.     sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
  419.     sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
  420.     comm_add_close_handler(sslState->server.fd,
  421. sslServerClosed,
  422. sslState);
  423.     comm_add_close_handler(sslState->client.fd,
  424. sslClientClosed,
  425. sslState);
  426.     commSetTimeout(sslState->client.fd,
  427. Config.Timeout.lifetime,
  428. sslTimeout,
  429. sslState);
  430.     commSetTimeout(sslState->server.fd,
  431. Config.Timeout.connect,
  432. sslTimeout,
  433. sslState);
  434.     peerSelect(request,
  435. NULL,
  436. sslPeerSelectComplete,
  437. sslState);
  438.     /*
  439.      * Disable the client read handler until peer selection is complete
  440.      * Take control away from client_side.c.
  441.      */
  442.     commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0);
  443. }
  444. static void
  445. sslProxyConnected(int fd, void *data)
  446. {
  447.     SslStateData *sslState = data;
  448.     MemBuf mb;
  449.     HttpHeader hdr_out;
  450.     Packer p;
  451.     http_state_flags flags;
  452.     debug(26, 3) ("sslProxyConnected: FD %d sslState=%pn", fd, sslState);
  453.     memset(&flags, '', sizeof(flags));
  454.     memBufDefInit(&mb);
  455.     memBufPrintf(&mb, "CONNECT %s HTTP/1.0rn", sslState->url);
  456.     httpBuildRequestHeader(sslState->request,
  457. sslState->request,
  458. NULL, /* StoreEntry */
  459. &hdr_out,
  460. sslState->client.fd,
  461. flags); /* flags */
  462.     packerToMemInit(&p, &mb);
  463.     httpHeaderPackInto(&hdr_out, &p);
  464.     httpHeaderClean(&hdr_out);
  465.     packerClean(&p);
  466.     memBufAppend(&mb, "rn", 2);
  467.     xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF);
  468.     debug(26, 3) ("sslProxyConnected: Sending {%s}n", sslState->client.buf);
  469.     sslState->client.len = mb.size;
  470.     memBufClean(&mb);
  471.     commSetTimeout(sslState->server.fd,
  472. Config.Timeout.read,
  473. sslTimeout,
  474. sslState);
  475.     sslSetSelect(sslState);
  476. }
  477. static void
  478. sslPeerSelectComplete(FwdServer * fs, void *data)
  479. {
  480.     SslStateData *sslState = data;
  481.     request_t *request = sslState->request;
  482.     peer *g = NULL;
  483.     if (fs == NULL) {
  484. ErrorState *err;
  485. err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
  486. err->request = requestLink(sslState->request);
  487. err->callback = sslErrorComplete;
  488. err->callback_data = sslState;
  489. errorSend(sslState->client.fd, err);
  490. return;
  491.     }
  492.     sslState->proxying = fs->peer ? 1 : 0;
  493.     sslState->host = fs->peer ? fs->peer->host : request->host;
  494.     if (fs->peer == NULL) {
  495. sslState->port = request->port;
  496.     } else if (fs->peer->http_port != 0) {
  497. sslState->port = fs->peer->http_port;
  498.     } else if ((g = peerFindByName(fs->peer->host))) {
  499. sslState->port = g->http_port;
  500.     } else {
  501. sslState->port = CACHE_HTTP_PORT;
  502.     }
  503. #if DELAY_POOLS
  504.     /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
  505.     if (g && g->options.no_delay)
  506. sslState->delay_id = 0;
  507. #endif
  508.     commConnectStart(sslState->server.fd,
  509. sslState->host,
  510. sslState->port,
  511. sslConnectDone,
  512. sslState);
  513. }