Fix "JAP-client" hideous ASN1 bug, twice. (Fix1: check more thoroughly for TLS errors...
[tor.git] / src / or / buffers.c
blob7edc2cdf346adc28d6f74dbed917197d112362fa
1 /* Copyright 2001 Matej Pfajfar.
2 * Copyright 2001-2004 Roger Dingledine.
3 * Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */
4 /* See LICENSE for licensing information */
5 /* $Id$ */
6 const char buffers_c_id[] = "$Id$";
8 /**
9 * \file buffers.c
10 * \brief Abstractions for buffered IO.
11 **/
13 #include "or.h"
15 #define BUFFER_MAGIC 0xB0FFF312u
16 struct buf_t {
17 uint32_t magic; /**< Magic cookie for debugging: Must be set to BUFFER_MAGIC */
18 char *mem; /**< Storage for data in the buffer */
19 size_t len; /**< Maximum amount of data that <b>mem</b> can hold. */
20 size_t datalen; /**< Number of bytes currently in <b>mem</b>. */
23 /** Size, in bytes, for newly allocated buffers. Should be a power of 2. */
24 #define INITIAL_BUF_SIZE (4*1024)
25 /** Size, in bytes, for minimum 'shrink' size for buffers. Buffers may start
26 * out smaller than this, but they will never autoshrink to less
27 * than this size. */
28 #define MIN_BUF_SHRINK_SIZE (16*1024)
30 /** Change a buffer's capacity. <b>new_capacity</b> must be \<= buf->datalen. */
31 static INLINE void buf_resize(buf_t *buf, size_t new_capacity)
33 tor_assert(buf->datalen <= new_capacity);
34 tor_assert(new_capacity);
35 buf->mem = tor_realloc(buf->mem, new_capacity);
36 buf->len = new_capacity;
39 /** If the buffer is not large enough to hold <b>capacity</b> bytes, resize
40 * it so that it can. (The new size will be a power of 2 times the old
41 * size.)
43 static INLINE int buf_ensure_capacity(buf_t *buf, size_t capacity)
45 size_t new_len;
46 if (buf->len >= capacity) /* Don't grow if we're already big enough. */
47 return 0;
48 if (capacity > MAX_BUF_SIZE) /* Don't grow past the maximum. */
49 return -1;
50 /* Find the smallest new_len equal to (2**X)*len for some X; such that
51 * new_len is at least capacity.
53 new_len = buf->len*2;
54 while (new_len < capacity)
55 new_len *= 2;
56 /* Resize the buffer. */
57 log_fn(LOG_DEBUG,"Growing buffer from %d to %d bytes.",
58 (int)buf->len, (int)new_len);
59 buf_resize(buf,new_len);
60 return 0;
63 /** If the buffer is at least 2*MIN_BUF_SHRINK_SIZE bytes in capacity,
64 * and if the buffer is less than 1/4 full, shrink the buffer until
65 * one of the above no longer holds. (We shrink the buffer by
66 * dividing by powers of 2.)
68 static INLINE void buf_shrink_if_underfull(buf_t *buf) {
69 size_t new_len;
70 /* If the buffer is at least .25 full, or if shrinking the buffer would
71 * put it under MIN_BUF_SHRINK_SIZE, don't do it. */
72 if (buf->datalen >= buf->len/4 || buf->len < 2*MIN_BUF_SHRINK_SIZE)
73 return;
74 /* Shrink new_len by powers of 2 until: datalen is at least 1/4 of
75 * new_len, OR shrinking new_len more would put it under
76 * MIN_BUF_SHRINK_SIZE.
78 new_len = buf->len / 2;
79 while (buf->datalen < new_len/4 && new_len/2 > MIN_BUF_SHRINK_SIZE)
80 new_len /= 2;
81 log_fn(LOG_DEBUG,"Shrinking buffer from %d to %d bytes.",
82 (int)buf->len, (int)new_len);
83 buf_resize(buf, new_len);
86 /** Remove the first <b>n</b> bytes from buf.
88 static INLINE void buf_remove_from_front(buf_t *buf, size_t n) {
89 tor_assert(buf->datalen >= n);
90 buf->datalen -= n;
91 memmove(buf->mem, buf->mem+n, buf->datalen);
92 buf_shrink_if_underfull(buf);
95 /** Make sure that the memory in buf ends with a zero byte. */
96 static INLINE int buf_nul_terminate(buf_t *buf)
98 if (buf_ensure_capacity(buf,buf->datalen+1)<0)
99 return -1;
100 buf->mem[buf->datalen] = '\0';
101 return 0;
104 /** Create and return a new buf with capacity <b>size</b>.
106 buf_t *buf_new_with_capacity(size_t size) {
107 buf_t *buf;
108 buf = tor_malloc(sizeof(buf_t));
109 buf->magic = BUFFER_MAGIC;
110 buf->mem = tor_malloc(size);
111 buf->len = size;
112 buf->datalen = 0;
113 // memset(buf->mem,0,size);
115 assert_buf_ok(buf);
116 return buf;
119 /** Allocate and return a new buffer with default capacity. */
120 buf_t *buf_new()
122 return buf_new_with_capacity(INITIAL_BUF_SIZE);
125 /** Remove all data from <b>buf</b> */
126 void buf_clear(buf_t *buf)
128 buf->datalen = 0;
131 /** Return the number of bytes stored in <b>buf</b> */
132 size_t buf_datalen(const buf_t *buf)
134 return buf->datalen;
137 /** Return the maximum bytes that can be stored in <b>buf</b> before buf
138 * needs to resize. */
139 size_t buf_capacity(const buf_t *buf)
141 return buf->len;
144 /** For testing only: Return a pointer to the raw memory stored in <b>buf</b>.
146 const char *_buf_peek_raw_buffer(const buf_t *buf)
148 return buf->mem;
151 /** Release storage held by <b>buf</b>.
153 void buf_free(buf_t *buf) {
154 assert_buf_ok(buf);
155 buf->magic = 0xDEADBEEF;
156 tor_free(buf->mem);
157 tor_free(buf);
160 /** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
161 * <b>at_most</b> bytes, resizing the buffer as necessary. If recv()
162 * returns 0, set <b>*reached_eof</b> to 1 and return 0. Return -1 on error;
163 * else return the number of bytes read. Return 0 if recv() would
164 * block.
166 int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof) {
168 int read_result;
170 assert_buf_ok(buf);
171 tor_assert(reached_eof);
172 tor_assert(s>=0);
174 if (buf_ensure_capacity(buf,buf->datalen+at_most))
175 return -1;
177 if (at_most + buf->datalen > buf->len)
178 at_most = buf->len - buf->datalen; /* take the min of the two */
180 if (at_most == 0)
181 return 0; /* we shouldn't read anything */
183 // log_fn(LOG_DEBUG,"reading at most %d bytes.",at_most);
184 read_result = recv(s, buf->mem+buf->datalen, at_most, 0);
185 if (read_result < 0) {
186 int e = tor_socket_errno(s);
187 if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
188 return -1;
190 return 0; /* would block. */
191 } else if (read_result == 0) {
192 log_fn(LOG_DEBUG,"Encountered eof");
193 *reached_eof = 1;
194 return 0;
195 } else { /* we read some bytes */
196 buf->datalen += read_result;
197 log_fn(LOG_DEBUG,"Read %d bytes. %d on inbuf.",read_result,
198 (int)buf->datalen);
199 return read_result;
203 /** As read_to_buf, but reads from a TLS connection.
205 int read_to_buf_tls(tor_tls *tls, size_t at_most, buf_t *buf) {
206 int r;
207 tor_assert(tls);
208 assert_buf_ok(buf);
210 log_fn(LOG_DEBUG,"start: %d on buf, %d pending, at_most %d.",
211 (int)buf_datalen(buf), (int)tor_tls_get_pending_bytes(tls),
212 (int)at_most);
214 if (buf_ensure_capacity(buf, at_most+buf->datalen))
215 return TOR_TLS_ERROR;
217 if (at_most + buf->datalen > buf->len)
218 at_most = buf->len - buf->datalen;
220 if (at_most == 0)
221 return 0;
223 log_fn(LOG_DEBUG,"before: %d on buf, %d pending, at_most %d.",
224 (int)buf_datalen(buf), (int)tor_tls_get_pending_bytes(tls),
225 (int)at_most);
227 check_no_tls_errors();
228 r = tor_tls_read(tls, buf->mem+buf->datalen, at_most);
229 if (r<0)
230 return r;
231 buf->datalen += r;
232 log_fn(LOG_DEBUG,"Read %d bytes. %d on inbuf; %d pending",r,
233 (int)buf->datalen,(int)tor_tls_get_pending_bytes(tls));
234 return r;
237 /** Write data from <b>buf</b> to the socket <b>s</b>. Write at most
238 * <b>*buf_flushlen</b> bytes, decrement <b>*buf_flushlen</b> by
239 * the number of bytes actually written, and remove the written bytes
240 * from the buffer. Return the number of bytes written on success,
241 * -1 on failure. Return 0 if write() would block.
243 int flush_buf(int s, buf_t *buf, size_t *buf_flushlen)
245 int write_result;
247 assert_buf_ok(buf);
248 tor_assert(buf_flushlen);
249 tor_assert(s>=0);
250 tor_assert(*buf_flushlen <= buf->datalen);
252 if (*buf_flushlen == 0) /* nothing to flush */
253 return 0;
255 write_result = send(s, buf->mem, *buf_flushlen, 0);
256 if (write_result < 0) {
257 int e = tor_socket_errno(s);
258 if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
259 return -1;
261 log_fn(LOG_DEBUG,"write() would block, returning.");
262 return 0;
263 } else {
264 *buf_flushlen -= write_result;
265 log_fn(LOG_DEBUG,"%d: flushed %d bytes, %d ready to flush, %d remain.",
266 s,write_result,(int)*buf_flushlen,(int)buf->datalen);
267 buf_remove_from_front(buf, write_result);
269 return write_result;
273 /** As flush_buf, but writes data to a TLS connection.
275 int flush_buf_tls(tor_tls *tls, buf_t *buf, size_t *buf_flushlen)
277 int r;
278 assert_buf_ok(buf);
279 tor_assert(tls);
280 tor_assert(buf_flushlen);
282 /* we want to let tls write even if flushlen is zero, because it might
283 * have a partial record pending */
284 check_no_tls_errors();
285 r = tor_tls_write(tls, buf->mem, *buf_flushlen);
286 if (r < 0) {
287 return r;
289 *buf_flushlen -= r;
290 buf_remove_from_front(buf, r);
291 log_fn(LOG_DEBUG,"flushed %d bytes, %d ready to flush, %d remain.",
292 r,(int)*buf_flushlen,(int)buf->datalen);
293 return r;
296 /** Append <b>string_len</b> bytes from <b>string</b> to the end of
297 * <b>buf</b>.
299 * Return the new length of the buffer on success, -1 on failure.
301 int write_to_buf(const char *string, size_t string_len, buf_t *buf) {
303 /* append string to buf (growing as needed, return -1 if "too big")
304 * return total number of bytes on the buf
307 tor_assert(string);
308 assert_buf_ok(buf);
310 if (buf_ensure_capacity(buf, buf->datalen+string_len)) {
311 log_fn(LOG_WARN, "buflen too small, can't hold %d bytes.", (int)(buf->datalen+string_len));
312 return -1;
315 memcpy(buf->mem+buf->datalen, string, string_len);
316 buf->datalen += string_len;
317 log_fn(LOG_DEBUG,"added %d bytes to buf (now %d total).",(int)string_len, (int)buf->datalen);
318 return buf->datalen;
321 /** Remove <b>string_len</b> bytes from the front of <b>buf</b>, and store them
322 * into <b>string</b>. Return the new buffer size. <b>string_len</b> must be \<=
323 * the number of bytes on the buffer.
325 int fetch_from_buf(char *string, size_t string_len, buf_t *buf) {
327 /* There must be string_len bytes in buf; write them onto string,
328 * then memmove buf back (that is, remove them from buf).
330 * Return the number of bytes still on the buffer. */
332 tor_assert(string);
333 tor_assert(string_len <= buf->datalen); /* make sure we don't ask for too much */
334 assert_buf_ok(buf);
336 memcpy(string,buf->mem,string_len);
337 buf_remove_from_front(buf, string_len);
338 return buf->datalen;
341 /** There is a (possibly incomplete) http statement on <b>buf</b>, of the
342 * form "\%s\\r\\n\\r\\n\%s", headers, body. (body may contain nuls.)
343 * If a) the headers include a Content-Length field and all bytes in
344 * the body are present, or b) there's no Content-Length field and
345 * all headers are present, then:
347 * - strdup headers into <b>*headers_out</b>, and nul-terminate it.
348 * - memdup body into <b>*body_out</b>, and nul-terminate it.
349 * - Then remove them from <b>buf</b>, and return 1.
351 * - If headers or body is NULL, discard that part of the buf.
352 * - If a headers or body doesn't fit in the arg, return -1.
353 * (We ensure that the headers or body don't exceed max len,
354 * _even if_ we're planning to discard them.)
356 * Else, change nothing and return 0.
358 int fetch_from_buf_http(buf_t *buf,
359 char **headers_out, size_t max_headerlen,
360 char **body_out, size_t *body_used, size_t max_bodylen) {
361 char *headers, *body, *p;
362 size_t headerlen, bodylen, contentlen;
364 assert_buf_ok(buf);
366 headers = buf->mem;
367 if (buf_nul_terminate(buf)<0) {
368 log_fn(LOG_WARN,"Couldn't nul-terminate buffer");
369 return -1;
371 body = strstr(headers,"\r\n\r\n");
372 if (!body) {
373 log_fn(LOG_DEBUG,"headers not all here yet.");
374 return 0;
376 body += 4; /* Skip the the CRLFCRLF */
377 headerlen = body-headers; /* includes the CRLFCRLF */
378 bodylen = buf->datalen - headerlen;
379 log_fn(LOG_DEBUG,"headerlen %d, bodylen %d.", (int)headerlen, (int)bodylen);
381 if (max_headerlen <= headerlen) {
382 log_fn(LOG_WARN,"headerlen %d larger than %d. Failing.", (int)headerlen,
383 (int)max_headerlen-1);
384 return -1;
386 if (max_bodylen <= bodylen) {
387 log_fn(LOG_WARN,"bodylen %d larger than %d. Failing.", (int)bodylen, (int)max_bodylen-1);
388 return -1;
391 #define CONTENT_LENGTH "\r\nContent-Length: "
392 p = strstr(headers, CONTENT_LENGTH);
393 if (p) {
394 int i;
395 i = atoi(p+strlen(CONTENT_LENGTH));
396 if (i < 0) {
397 log_fn(LOG_WARN, "Content-Length is less than zero; it looks like someone is trying to crash us.");
398 return -1;
400 contentlen = i;
401 /* if content-length is malformed, then our body length is 0. fine. */
402 log_fn(LOG_DEBUG,"Got a contentlen of %d.",(int)contentlen);
403 if (bodylen < contentlen) {
404 log_fn(LOG_DEBUG,"body not all here yet.");
405 return 0; /* not all there yet */
407 if (bodylen > contentlen) {
408 bodylen = contentlen;
409 log_fn(LOG_DEBUG,"bodylen reduced to %d.",(int)bodylen);
412 /* all happy. copy into the appropriate places, and return 1 */
413 if (headers_out) {
414 *headers_out = tor_malloc(headerlen+1);
415 memcpy(*headers_out,buf->mem,headerlen);
416 (*headers_out)[headerlen] = 0; /* null terminate it */
418 if (body_out) {
419 tor_assert(body_used);
420 *body_used = bodylen;
421 *body_out = tor_malloc(bodylen+1);
422 memcpy(*body_out,buf->mem+headerlen,bodylen);
423 (*body_out)[bodylen] = 0; /* null terminate it */
425 buf_remove_from_front(buf, headerlen+bodylen);
426 return 1;
429 /** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
430 * of the forms
431 * - socks4: "socksheader username\\0"
432 * - socks4a: "socksheader username\\0 destaddr\\0"
433 * - socks5 phase one: "version #methods methods"
434 * - socks5 phase two: "version command 0 addresstype..."
435 * If it's a complete and valid handshake, and destaddr fits in
436 * MAX_SOCKS_ADDR_LEN bytes, then pull the handshake off the buf,
437 * assign to <b>req</b>, and return 1.
439 * If it's invalid or too big, return -1.
441 * Else it's not all there yet, leave buf alone and return 0.
443 * If you want to specify the socks reply, write it into <b>req->reply</b>
444 * and set <b>req->replylen</b>, else leave <b>req->replylen</b> alone.
446 * If returning 0 or -1, <b>req->address</b> and <b>req->port</b> are undefined.
448 int fetch_from_buf_socks(buf_t *buf, socks_request_t *req) {
449 unsigned char len;
450 char tmpbuf[INET_NTOA_BUF_LEN];
451 uint32_t destip;
452 enum {socks4, socks4a} socks4_prot = socks4a;
453 char *next, *startaddr;
454 struct in_addr in;
456 /* If the user connects with socks4 or the wrong variant of socks5,
457 * then log a warning to let him know that it might be unwise. */
458 static int have_warned_about_unsafe_socks = 0;
460 if (buf->datalen < 2) /* version and another byte */
461 return 0;
462 switch (*(buf->mem)) { /* which version of socks? */
464 case 5: /* socks5 */
466 if (req->socks_version != 5) { /* we need to negotiate a method */
467 unsigned char nummethods = (unsigned char)*(buf->mem+1);
468 tor_assert(!req->socks_version);
469 if (buf->datalen < 2u+nummethods)
470 return 0;
471 if (!nummethods || !memchr(buf->mem+2, 0, nummethods)) {
472 log_fn(LOG_WARN,"socks5: offered methods don't include 'no auth'. Rejecting.");
473 req->replylen = 2; /* 2 bytes of response */
474 req->reply[0] = 5;
475 req->reply[1] = '\xFF'; /* reject all methods */
476 return -1;
478 buf_remove_from_front(buf,2+nummethods);/* remove packet from buf */
480 req->replylen = 2; /* 2 bytes of response */
481 req->reply[0] = 5; /* socks5 reply */
482 req->reply[1] = SOCKS5_SUCCEEDED;
483 req->socks_version = 5; /* remember that we've already negotiated auth */
484 log_fn(LOG_DEBUG,"socks5: accepted method 0");
485 return 0;
487 /* we know the method; read in the request */
488 log_fn(LOG_DEBUG,"socks5: checking request");
489 if (buf->datalen < 8) /* basic info plus >=2 for addr plus 2 for port */
490 return 0; /* not yet */
491 req->command = (unsigned char) *(buf->mem+1);
492 if (req->command != SOCKS_COMMAND_CONNECT &&
493 req->command != SOCKS_COMMAND_RESOLVE) {
494 /* not a connect or resolve? we don't support it. */
495 log_fn(LOG_WARN,"socks5: command %d not recognized. Rejecting.",
496 req->command);
497 return -1;
499 switch (*(buf->mem+3)) { /* address type */
500 case 1: /* IPv4 address */
501 log_fn(LOG_DEBUG,"socks5: ipv4 address type");
502 if (buf->datalen < 10) /* ip/port there? */
503 return 0; /* not yet */
505 destip = ntohl(*(uint32_t*)(buf->mem+4));
506 in.s_addr = htonl(destip);
507 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
508 if (strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN) {
509 log_fn(LOG_WARN,"socks5 IP takes %d bytes, which doesn't fit in %d. Rejecting.",
510 (int)strlen(tmpbuf)+1,(int)MAX_SOCKS_ADDR_LEN);
511 return -1;
513 strlcpy(req->address,tmpbuf,sizeof(req->address));
514 req->port = ntohs(*(uint16_t*)(buf->mem+8));
515 buf_remove_from_front(buf, 10);
516 if (!have_warned_about_unsafe_socks) {
517 log_fn(LOG_WARN,"Your application (using socks5 on port %d) is giving Tor only an IP address. Applications that do DNS resolves themselves may leak information. Consider using Socks4A (e.g. via privoxy or socat) instead.", req->port);
518 // have_warned_about_unsafe_socks = 1; // (for now, warn every time)
520 return 1;
521 case 3: /* fqdn */
522 log_fn(LOG_DEBUG,"socks5: fqdn address type");
523 len = (unsigned char)*(buf->mem+4);
524 if (buf->datalen < 7u+len) /* addr/port there? */
525 return 0; /* not yet */
526 if (len+1 > MAX_SOCKS_ADDR_LEN) {
527 log_fn(LOG_WARN,"socks5 hostname is %d bytes, which doesn't fit in %d. Rejecting.",
528 len+1,MAX_SOCKS_ADDR_LEN);
529 return -1;
531 memcpy(req->address,buf->mem+5,len);
532 req->address[len] = 0;
533 req->port = ntohs(get_uint16(buf->mem+5+len));
534 buf_remove_from_front(buf, 5+len+2);
535 return 1;
536 default: /* unsupported */
537 log_fn(LOG_WARN,"socks5: unsupported address type %d. Rejecting.",*(buf->mem+3));
538 return -1;
540 tor_assert(0);
541 case 4: /* socks4 */
542 /* http://archive.socks.permeo.com/protocol/socks4.protocol */
543 /* http://archive.socks.permeo.com/protocol/socks4a.protocol */
545 req->socks_version = 4;
546 if (buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */
547 return 0; /* not yet */
549 req->command = (unsigned char) *(buf->mem+1);
550 if (req->command != SOCKS_COMMAND_CONNECT &&
551 req->command != SOCKS_COMMAND_RESOLVE) {
552 /* not a connect or resolve? we don't support it. */
553 log_fn(LOG_WARN,"socks4: command %d not recognized. Rejecting.",
554 req->command);
555 return -1;
558 req->port = ntohs(*(uint16_t*)(buf->mem+2));
559 destip = ntohl(*(uint32_t*)(buf->mem+4));
560 if ((!req->port && req->command!=SOCKS_COMMAND_RESOLVE) || !destip) {
561 log_fn(LOG_WARN,"socks4: Port or DestIP is zero. Rejecting.");
562 return -1;
564 if (destip >> 8) {
565 log_fn(LOG_DEBUG,"socks4: destip not in form 0.0.0.x.");
566 in.s_addr = htonl(destip);
567 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
568 if (strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN) {
569 log_fn(LOG_WARN,"socks4 addr (%d bytes) too long. Rejecting.",
570 (int)strlen(tmpbuf));
571 return -1;
573 log_fn(LOG_DEBUG,"socks4: successfully read destip (%s)", tmpbuf);
574 socks4_prot = socks4;
577 next = memchr(buf->mem+SOCKS4_NETWORK_LEN, 0,
578 buf->datalen-SOCKS4_NETWORK_LEN);
579 if (!next) {
580 log_fn(LOG_DEBUG,"socks4: Username not here yet.");
581 return 0;
583 tor_assert(next < buf->mem+buf->datalen);
585 startaddr = NULL;
586 if (socks4_prot != socks4a && !have_warned_about_unsafe_socks) {
587 log_fn(LOG_WARN,"Your application (using socks4 on port %d) is giving Tor only an IP address. Applications that do DNS resolves themselves may leak information. Consider using Socks4A (e.g. via privoxy or socat) instead.", req->port);
588 // have_warned_about_unsafe_socks = 1; // (for now, warn every time)
590 if (socks4_prot == socks4a) {
591 if (next+1 == buf->mem+buf->datalen) {
592 log_fn(LOG_DEBUG,"socks4: No part of destaddr here yet.");
593 return 0;
595 startaddr = next+1;
596 next = memchr(startaddr, 0, buf->mem+buf->datalen-startaddr);
597 if (!next) {
598 log_fn(LOG_DEBUG,"socks4: Destaddr not all here yet.");
599 return 0;
601 if (MAX_SOCKS_ADDR_LEN <= next-startaddr) {
602 log_fn(LOG_WARN,"socks4: Destaddr too long. Rejecting.");
603 return -1;
605 tor_assert(next < buf->mem+buf->datalen);
607 log_fn(LOG_DEBUG,"socks4: Everything is here. Success.");
608 strlcpy(req->address, startaddr ? startaddr : tmpbuf,
609 sizeof(req->address));
610 buf_remove_from_front(buf, next-buf->mem+1); /* next points to the final \0 on inbuf */
611 return 1;
613 case 'G': /* get */
614 case 'H': /* head */
615 case 'P': /* put/post */
616 case 'C': /* connect */
617 strlcpy(req->reply,
618 "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
619 "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
620 "<html>\n"
621 "<head>\n"
622 "<title>Tor is not an HTTP Proxy</title>\n"
623 "</head>\n"
624 "<body>\n"
625 "<h1>Tor is not an HTTP Proxy</h1>\n"
626 "<p>\n"
627 "It appears you have configured your web browser to use Tor as an HTTP Proxy.\n"
628 "This is not correct: Tor provides a SOCKS proxy. Please configure your\n"
629 "client accordingly.\n"
630 "</p>\n"
631 "<p>\n"
632 "See <a href=\"http://tor.eff.org/doc/tor-doc.html#installing\">http://tor.eff.org/doc/tor-doc.html#installing</a> for more information.\n"
633 "<!-- Plus this comment, to make the body response more than 512 bytes, so IE will be willing to display it. Comment comment comment comment comment comment comment comment comment comment comment comment.-->\n"
634 "</p>\n"
635 "</body>\n"
636 "</html>\n"
637 , MAX_SOCKS_REPLY_LEN);
638 req->replylen = strlen(req->reply)+1;
639 /* fall through */
640 default: /* version is not socks4 or socks5 */
641 log_fn(LOG_WARN,"Socks version %d not recognized. (Tor is not an http proxy.)",
642 *(buf->mem));
643 return -1;
647 #define CONTROL_CMD_FRAGMENTHEADER 0x0010
648 #define CONTROL_CMD_FRAGMENT 0x0011
649 /** If there is a complete control message waiting on buf, then store
650 * its contents into *<b>type_out</b>, store its body's length into
651 * *<b>len_out</b>, allocate and store a string for its body into
652 * *<b>body_out</b>, and return 1. (body_out will always be NUL-terminated,
653 * even if the control message body doesn't end with NUL.)
655 * If there is not a complete control message waiting, return 0.
657 * Return -1 on error.
659 int fetch_from_buf_control(buf_t *buf, uint32_t *len_out, uint16_t *type_out,
660 char **body_out)
662 uint32_t msglen;
663 uint16_t type;
665 tor_assert(buf);
666 tor_assert(len_out);
667 tor_assert(type_out);
668 tor_assert(body_out);
670 if (buf->datalen < 4)
671 return 0;
673 msglen = ntohs(get_uint16(buf->mem));
674 if (buf->datalen < 4 + (unsigned)msglen)
675 return 0;
677 type = ntohs(get_uint16(buf->mem+2));
678 if (type != CONTROL_CMD_FRAGMENTHEADER) {
679 *len_out = msglen;
680 *type_out = type;
681 if (msglen) {
682 *body_out = tor_malloc(msglen+1);
683 memcpy(*body_out, buf->mem+4, msglen);
684 (*body_out)[msglen] = '\0';
685 } else {
686 *body_out = NULL;
688 buf_remove_from_front(buf, 4+msglen);
690 return 1;
691 } else {
692 uint32_t totallen, sofar;
693 char *cp, *endp, *outp;
695 /* Okay, we have a fragmented message. Is it all here? */
696 if (msglen < 6)
697 return -1;
698 type = htons(get_uint16(buf->mem+4));
699 totallen = htonl(get_uint32(buf->mem+6));
700 if (totallen < 65536)
701 return -1;
703 if (buf->datalen<4+6+totallen)
704 /* The data can't possibly be here yet, no matter how well it's packed.*/
705 return 0;
707 /* Count how much data is really here. */
708 sofar = msglen-6;
709 cp = buf->mem+4+msglen;
710 endp = buf->mem+buf->datalen;
711 while (sofar < totallen) {
712 if ((endp-cp)<4)
713 return 0; /* Fragment header not all here. */
714 msglen = ntohs(get_uint16(cp));
715 if (ntohs(get_uint16(cp+2) != CONTROL_CMD_FRAGMENT))
716 return -1; /* Missing fragment message; error. */
717 if ((endp-cp) < (int)(4+msglen))
718 return 0; /* Fragment not all here. */
719 sofar += msglen;
720 cp += (4+msglen);
722 if (sofar > totallen)
723 return -1; /* Fragments add to more than expected; error. */
725 /* Okay, everything is here. */
726 *len_out = totallen;
727 *type_out = type;
728 *body_out = tor_malloc(totallen+1);
730 /* copy FRAGMENTED packet contents. */
731 msglen = ntohs(get_uint16(buf->mem));
732 if (msglen>6)
733 memcpy(*body_out,buf->mem+4+6,msglen-6);
734 sofar = msglen-6;
735 outp = *body_out+sofar;
736 cp = buf->mem+4+msglen;
737 while (sofar < totallen) {
738 msglen = ntohs(get_uint16(cp));
739 memcpy(outp,cp+4,msglen);
740 outp += msglen;
741 cp += 4+msglen;
742 sofar -= msglen;
744 (*body_out)[totallen]='\0';
746 return 1;
751 /** Log an error and exit if <b>buf</b> is corrupted.
753 void assert_buf_ok(buf_t *buf)
755 tor_assert(buf);
756 tor_assert(buf->magic == BUFFER_MAGIC);
757 tor_assert(buf->mem);
758 tor_assert(buf->datalen <= buf->len);