1 /* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; version 2 of the License. For a copy,
4 * see http://www.gnu.org/licenses/gpl-2.0.html.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 */
11
12 #include "config.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <time.h>
17 #include <string.h>
18 #include <sys/socket.h>
19 #ifdef HAVE_NETINET_IN_H
20 #include <netinet/in.h>
21 #endif
22 #ifdef HAVE_ARPA_INET_H
23 #include <arpa/inet.h>
24 #endif
25 #include <pthread.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include "tls.h"
29 #include "libfs.h"
30 #include "libstr.h"
31 #include "liblist.h"
32 #include "http.h"
33 #include "log.h"
34 #include "send.h"
35 #include "serverconfig.h"
36 #include "tomahawk.h"
37 #include "memdbg.h"
38
39 #define MAX_TO_BUFFER 1000
40 #define NONCE_DIGITS 10
41 #define TIMESTR_SIZE 64
42 #define FCGI_CHUNK_SIZE (64 * KILOBYTE - 8)
43 #define STREAM_BUFFER_SIZE 32 * KILOBYTE
44
45 char *hs_http10 = "HTTP/1.0 "; /* 9 */
46 char *hs_http11 = "HTTP/1.1 "; /* 9 */
47 char *hs_server = "Server: "; /* 8 */
48 char *hs_conn = "Connection: "; /* 12 */
49 char *hs_concl = "close\r\n"; /* 7 */
50 char *hs_conka = "keep-alive\r\n"; /* 12 */
51 char *hs_conup = "upgrade\r\n"; /* 9 */
52 char *hs_contyp = "Content-Type: "; /* 14 */
53 char *hs_conlen = "Content-Length: "; /* 16 */
54 char *hs_lctn = "Location: "; /* 10 */
55 char *hs_caco = "Cache-Control: "; /* 15 */
56 char *hs_public = "public\r\n"; /* 8 */
57 char *hs_private = "private\r\n"; /* 9 */
58 char *hs_expires = "Expires: "; /* 9 */
59 char *hs_http = "http://"; /* 7 */
60 char *hs_https = "https://"; /* 8 */
61 char *hs_hsts = "Strict-Transport-Security: max-age="; /* 35 */
62 char *hs_range = "Accept-Ranges: bytes\r\n"; /* 22 */
63 char *hs_gzip = "Content-Encoding: gzip\r\n"; /* 24 */
64 char *hs_chunked = "Transfer-Encoding: chunked\r\n"; /* 28 */
65 char *hs_eol = "\r\n"; /* 2 */
66 char *hs_forwarded = "Forwarded:"; /* 10 */
67 char *hs_x_forwarded_for = "X-Forwarded-For:"; /* 16 */
68
69 char *unknown_http_code = "Unknown Error";
70
71 static char *ec_doctype = "<!DOCTYPE html>\n";
72 static char *ec_head = "<html>\n<head>\n<title>";
73 static char *ec_body1 = "</title>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<style type=\"text/css\">\n"
74 "body { background-color:#d0d0d0; font-family:sans-serif; padding:0 30px }\n"
75 "div { background-color:#f8f8f8; letter-spacing:4px; max-width:400px; margin:100px auto 0 auto; padding:50px; "
76 "border-radius:10px; border:1px solid #808080; box-shadow:8px 15px 20px #404040 }\n"
77 "h1 { margin:0; font-size:22px; font-weight:normal }\n"
78 "p { margin:10px 0 0 0; padding-top:2px; font-size:14px; color:#606060; border-top:1px solid #a0a0ff; "
79 "text-align:right; font-weight:bold }\n"
80 "@media (max-width:767px) { h1 { font-size:90%; letter-spacing:2px } p { font-size:70% } }\n"
81 "</style>\n</head>\n<body>\n<div>\n<h1>";
82 static char *ec_body2 = "</h1>\n<p>";
83 static char *ec_tail = "</p>\n</div>\n</body>\n</html>";
84 static int ec_doctype_len, ec_head_len, ec_body1_len, ec_body2_len, ec_tail_len;
85
init_send_module(void)86 void init_send_module(void) {
87 ec_doctype_len = strlen(ec_doctype);
88 ec_head_len = strlen(ec_head);
89 ec_body1_len = strlen(ec_body1);
90 ec_body2_len = strlen(ec_body2);
91 ec_tail_len = strlen(ec_tail);
92 }
93
94 /* Send a char buffer to the client. Traffic throttling is handled here.
95 */
send_to_client(t_session * session,const char * buffer,int size)96 static int send_to_client(t_session *session, const char *buffer, int size) {
97 int bytes_sent = 0, total_sent = 0, can_send, rest;
98 time_t new_time;
99
100 /* Send buffer to browser.
101 */
102 if (session->socket_open == false) {
103 return -1;
104 } else if ((buffer == NULL) || (size <= 0)) {
105 return 0;
106 }
107
108 if (session->directory != NULL) {
109 if (session->directory->session_speed > 0) {
110 session->throttle = session->directory->session_speed;
111 }
112 }
113
114 do {
115 rest = size - total_sent;
116 if (session->throttle > 0) {
117 do {
118 new_time = time(NULL);
119 if (session->throttle_timer < new_time) {
120 session->bytecounter = 0;
121 session->throttle_timer = new_time;
122 }
123 can_send = session->throttle - session->bytecounter;
124 if (can_send <= 0) {
125 usleep(10000);
126 }
127 } while (can_send <= 0);
128 if (can_send > rest) {
129 can_send = rest;
130 }
131 } else {
132 can_send = rest;
133 }
134
135 #ifdef ENABLE_TLS
136 if (session->binding->use_tls) {
137 if ((bytes_sent = tls_send(&(session->tls_context), (char*)(buffer + total_sent), can_send)) <= 0) {
138 bytes_sent = -1;
139 }
140 } else
141 #endif
142 if ((bytes_sent = send(session->client_socket, (char*)(buffer + total_sent), can_send, 0)) <= 0) {
143 bytes_sent = -1;
144 }
145
146 /* Handle read result
147 */
148 if (bytes_sent == -1) {
149 if (errno != EINTR) {
150 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
151 if (session->config->log_timeouts) {
152 log_error_session(session, "send timeout");
153 }
154 } else if ((errno != EPIPE) && (errno != ECONNRESET)) {
155 log_error_session(session, "error while sending response");
156 }
157 close_socket(session);
158 session->keep_alive = false;
159 session->error_cause = ec_SOCKET_WRITE_ERROR;
160 return -1;
161 }
162 } else {
163 total_sent += bytes_sent;
164 session->bytecounter += bytes_sent;
165 }
166 } while (total_sent < size);
167 #ifdef ENABLE_TOMAHAWK
168 increment_transfer(TRANSFER_SEND, total_sent);
169 #endif
170
171 return 0;
172 }
173
174 /* This function has been added to improve speed by buffering small amounts of data to be sent.
175 */
send_buffer(t_session * session,const char * buffer,int size)176 int send_buffer(t_session *session, const char *buffer, int size) {
177 if (size > MAX_TO_BUFFER) {
178 if (session->output_size > 0) {
179 if (send_to_client(session, session->output_buffer, session->output_size) == -1) {
180 return -1;
181 }
182 session->output_size = 0;
183 }
184 if (send_to_client(session, buffer, size) == -1) {
185 return -1;
186 }
187 } else if (buffer == NULL) {
188 if (session->output_size > 0) {
189 if (send_to_client(session, session->output_buffer, session->output_size) == -1) {
190 return -1;
191 }
192 session->output_size = 0;
193 }
194 } else {
195 if ((session->output_size + size > OUTPUT_BUFFER_SIZE) && (session->output_size > 0)) {
196 if (send_to_client(session, session->output_buffer, session->output_size) == -1) {
197 return -1;
198 }
199 session->output_size = 0;
200 }
201
202 memcpy(session->output_buffer + session->output_size, buffer, size);
203 session->output_size += size;
204 }
205
206 session->bytes_sent += size;
207
208 return 0;
209 }
210
211 /* Send a HTTP header to the client. Header is not closed by this function.
212 */
send_header(t_session * session)213 int send_header(t_session *session) {
214 #ifdef ENABLE_TLS
215 char random_header[MAX_RANDOM_HEADER_LENGTH + 13];
216 char *rand_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789PR";
217 unsigned long length, i;
218 int random;
219 #endif
220 char ecode[5], timestr[TIMESTR_SIZE];
221 const char *emesg;
222 time_t t;
223 struct tm s;
224 t_keyvalue *header;
225
226 /* Send HTTP header.
227 */
228 ecode[4] = '\0';
229 snprintf(ecode, 4, "%d", session->return_code);
230 if ((emesg = http_error(session->return_code)) == NULL) {
231 emesg = unknown_http_code;
232 }
233
234 session->data_sent = true;
235
236 /* HTTP version
237 */
238 if (session->http_version != NULL) {
239 if (*(session->http_version + 7) == '0') {
240 if (send_buffer(session, hs_http10, 9) == -1) {
241 return -1;
242 }
243 } else {
244 if (send_buffer(session, hs_http11, 9) == -1) {
245 return -1;
246 }
247 }
248 } else {
249 if (send_buffer(session, hs_http11, 9) == -1) {
250 return -1;
251 }
252 }
253
254 /* HTTP code
255 */
256 if (send_buffer(session, ecode, 3) == -1) {
257 return -1;
258 } else if (send_buffer(session, " ", 1) == -1) {
259 return -1;
260 } else if (send_buffer(session, emesg, strlen(emesg)) == -1) {
261 return -1;
262 } else if (send_buffer(session, hs_eol, 2) == -1) {
263 return -1;
264 }
265
266 /* Date
267 */
268 if (session->send_date) {
269 if (time(&t) == -1) {
270 return -1;
271 } else if (gmtime_r(&t, &s) == NULL) {
272 return -1;
273 } else if (strftime(timestr, TIMESTR_SIZE, "%a, %d %b %Y %X GMT\r\n", &s) == 0) {
274 return -1;
275 } else if (send_buffer(session, "Date: ", 6) == -1) {
276 return -1;
277 } else if (send_buffer(session, timestr, strlen(timestr)) == -1) {
278 return -1;
279 }
280 }
281
282 /* Server
283 */
284 if (session->config->server_string != NULL) {
285 if (send_buffer(session, hs_server, 8) == -1) {
286 return -1;
287 } else if (send_buffer(session, session->config->server_string, strlen(session->config->server_string)) == -1) {
288 return -1;
289 } else if (send_buffer(session, hs_eol, 2) == -1) {
290 return -1;
291 }
292 }
293
294 /* Range
295 */
296 if ((session->cgi_type == no_cgi) && (session->uri_is_dir == false)) {
297 if (send_buffer(session, hs_range, 22) == -1) {
298 return -1;
299 }
300 }
301
302 /* Connection
303 */
304 if (send_buffer(session, hs_conn, 12) == -1) {
305 return -1;
306 } else if (session->keep_alive) {
307 if (send_buffer(session, hs_conka, 12) == -1) {
308 return -1;
309 }
310 } else if (send_buffer(session, hs_concl, 7) == -1) {
311 return -1;
312 }
313
314 /* Content-Encoding
315 */
316 if (session->encode_gzip) {
317 if (send_buffer(session, hs_gzip, 24) == -1) {
318 return -1;
319 }
320 }
321
322 /* Content-Type
323 */
324 if (session->mimetype != NULL) {
325 if (send_buffer(session, hs_contyp, 14) == -1) {
326 return -1;
327 } else if (send_buffer(session, session->mimetype, strlen(session->mimetype)) == -1) {
328 return -1;
329 } else if (send_buffer(session, "\r\n", 2) == -1) {
330 return -1;
331 }
332 }
333
334 /* Expires
335 */
336 if (session->send_expires && (session->expires > -1) && (session->return_code == 200)) {
337 if (time(&t) == -1) {
338 return -1;
339 }
340 t += (time_t)session->expires;
341
342 if (gmtime_r(&t, &s) == NULL) {
343 return -1;
344 } else if (send_buffer(session, hs_caco, 15) == -1) {
345 return -1;
346 }
347
348 if (session->caco_private) {
349 if (send_buffer(session, hs_private, 9) == -1) {
350 return -1;
351 }
352 } else {
353 if (send_buffer(session, hs_public, 8) == -1) {
354 return -1;
355 }
356 }
357
358 if (send_buffer(session, hs_expires, 9) == -1) {
359 return -1;
360 } else if (strftime(timestr, TIMESTR_SIZE, "%a, %d %b %Y %X GMT\r\n", &s) == 0) {
361 return -1;
362 } else if (send_buffer(session, timestr, strlen(timestr)) == -1) {
363 return -1;
364 }
365 }
366
367 /* Custom headers
368 */
369 header = session->host->custom_headers_client;
370 while (header != NULL) {
371 if (send_buffer(session, header->key, strlen(header->key)) == -1) {
372 return -1;
373 } else if (send_buffer(session, ": ", 2) == -1) {
374 return -1;
375 } else if (send_buffer(session, header->value, strlen(header->value)) == -1) {
376 return -1;
377 } else if (send_buffer(session, "\r\n", 2) == -1) {
378 return -1;
379 }
380
381 header = header->next;
382 }
383
384 #ifdef ENABLE_TLS
385 /* Random header
386 */
387 if ((session->host->random_header_length > -1) && session->binding->use_tls) {
388 sprintf(random_header, "X-Random: ");
389 length = (session->host->random_header_length * ((unsigned int)rand() & MAX_RANDOM_HEADER_LENGTH_MASK)) / MAX_RANDOM_HEADER_LENGTH_MASK;
390 if (length == 0) {
391 length = 1;
392 }
393 sprintf(random_header + 10 + length, "\r\n");
394
395 random = rand() & 63;
396 for (i = 0; i < length; i++) {
397 random_header[10 + i] = rand_set[random];
398 }
399
400 if (send_buffer(session, random_header, 12 + length) == -1) {
401 return -1;
402 }
403 }
404
405 /* HTTP Strict Transport Security
406 */
407 if ((session->host->hsts_time != NULL) && session->binding->use_tls) {
408 if (send_buffer(session, hs_hsts, 35) == -1) {
409 return -1;
410 }
411 if (send_buffer(session, session->host->hsts_time, strlen(session->host->hsts_time)) == -1) {
412 return -1;
413 }
414 if (send_buffer(session, "\r\n", 2) == -1) {
415 return -1;
416 }
417 }
418
419 /* HTTP Public Key Pinning
420 */
421 if (session->binding->use_tls && (session->host->hpkp_data != NULL)) {
422 if (session->host->hpkp_data->http_header != NULL) {
423 send_buffer(session, session->host->hpkp_data->http_header, session->host->hpkp_data->header_size);
424 }
425 }
426 #endif
427
428 return 0;
429 }
430
431 /* Send a datachunk to the client without buffering
432 */
send_chunk_to_client(t_session * session,const char * chunk,int size)433 static int send_chunk_to_client(t_session *session, const char *chunk, int size) {
434 char hex[10];
435
436 if (session->keep_alive) {
437 hex[9] = '\0';
438 if (snprintf(hex, 9, "%x\r\n", size) < 0) {
439 return -1;
440 } else if (send_to_client(session, hex, strlen(hex)) == -1) {
441 return -1;
442 }
443 }
444
445 if (send_to_client(session, chunk, size) == -1) {
446 return -1;
447 }
448
449 if (session->keep_alive) {
450 if (send_to_client(session, "\r\n", 2) == -1) {
451 return -1;
452 }
453 }
454
455 return 0;
456 }
457
send_chunk(t_session * session,const char * chunk,int size)458 int send_chunk(t_session *session, const char *chunk, int size) {
459 if (size > MAX_TO_BUFFER) {
460 if (session->output_size > 0) {
461 if (send_chunk_to_client(session, session->output_buffer, session->output_size) == -1) {
462 return -1;
463 }
464 session->output_size = 0;
465 }
466 if (send_chunk_to_client(session, chunk, size) == -1) {
467 return -1;
468 }
469 } else if (chunk == NULL) {
470 if (session->output_size > 0) {
471 if (send_chunk_to_client(session, session->output_buffer, session->output_size) == -1) {
472 return -1;
473 }
474 session->output_size = 0;
475 }
476
477 if (size == 0) {
478 if (send_to_client(session, "0\r\n\r\n", 5) == -1) {
479 return -1;
480 }
481 }
482 } else {
483 if ((session->output_size + size > OUTPUT_BUFFER_SIZE) && (session->output_size > 0)) {
484 if (send_chunk_to_client(session, session->output_buffer, session->output_size) == -1) {
485 return -1;
486 }
487 session->output_size = 0;
488 }
489
490 memcpy(session->output_buffer + session->output_size, chunk, size);
491 session->output_size += size;
492 }
493
494 session->bytes_sent += size;
495
496 return 0;
497 }
498
499 /* Send header of HTTP error message.
500 */
send_http_code_header(t_session * session)501 int send_http_code_header(t_session *session) {
502 if (session->return_code == -1) {
503 session->return_code = 500;
504 }
505
506 session->encode_gzip = false;
507 session->mimetype = NULL;
508 if (send_header(session) == -1) {
509 return -1;
510 }
511
512 switch (session->return_code) {
513 case 301:
514 case 302:
515 case 303:
516 case 304:
517 case 305:
518 case 306:
519 case 307:
520 case 308:
521 if (send_buffer(session, hs_lctn, 10) == -1) {
522 return -1;
523 }
524
525 if (session->cause_of_30x == enforce_first_hostname) {
526 #ifdef ENABLE_TLS
527 if (session->binding->use_tls || session->host->require_tls) {
528 if (send_buffer(session, hs_https, 8) == -1) {
529 return -1;
530 }
531 } else
532 #endif
533 if (send_buffer(session, hs_http, 7) == -1) {
534 return -1;
535 }
536
537 if (send_buffer(session, *(session->host->hostname.item), strlen(*(session->host->hostname.item))) == -1) {
538 return -1;
539 }
540 }
541
542 if (session->cause_of_30x == location) {
543 if (session->location != NULL) {
544 if (send_buffer(session, session->location, strlen(session->location)) == -1) {
545 return -1;
546 }
547 }
548 if (send_buffer(session, "\r\n", 2) == -1) {
549 return -1;
550 }
551 break;
552 }
553
554 #ifdef ENABLE_TLS
555 if (session->cause_of_30x == require_tls) {
556 if (send_buffer(session, hs_https, 8) == -1) {
557 return -1;
558 }
559
560 if (session->hostname != NULL) {
561 if (send_buffer(session, session->hostname, strlen(session->hostname)) == -1) {
562 return -1;
563 }
564 } else if (send_buffer(session, *(session->host->hostname.item), strlen(*(session->host->hostname.item))) == -1) {
565 return -1;
566 }
567 }
568 #endif
569
570 if (send_buffer(session, session->uri, session->uri_len) == -1) {
571 return -1;
572 }
573
574 if (session->cause_of_30x == missing_slash) {
575 if (send_buffer(session, "/", 1) == -1) {
576 return -1;
577 }
578 }
579 if (session->vars != NULL) {
580 if (send_buffer(session, "?", 1) == -1) {
581 return -1;
582 } else if (send_buffer(session, session->vars, strlen(session->vars)) == -1) {
583 return -1;
584 }
585 }
586 if (send_buffer(session, "\r\n", 2) == -1) {
587 return -1;
588 }
589 break;
590 case 401:
591 if (session->host->auth_method == basic) {
592 if (send_basic_auth(session) == -1) {
593 return -1;
594 }
595 } else {
596 if (send_digest_auth(session) == -1) {
597 return -1;
598 }
599 }
600 break;
601 }
602
603 return 0;
604 }
605
606 /* Send body of HTTP error message
607 */
send_http_code_body(t_session * session)608 int send_http_code_body(t_session *session) {
609 char ecode[5], len[10];
610 const char *emesg;
611 size_t ecode_len, emesg_len;
612
613 ecode[4] = '\0';
614 snprintf(ecode, 4, "%d", session->return_code);
615 ecode_len = strlen(ecode);
616
617 if ((emesg = http_error(session->return_code)) == NULL) {
618 emesg = unknown_http_code;
619 }
620 emesg_len = strlen(emesg);
621 len[9] = '\0';
622 snprintf(len, 9, "%d", (int)((2 * emesg_len) + (2 * ecode_len) + 3 + ec_doctype_len + ec_head_len + ec_body1_len + ec_body2_len + ec_tail_len));
623
624 if (send_buffer(session, hs_conlen, 16) == -1) {
625 return -1;
626 } else if (send_buffer(session, len, strlen(len)) == -1) {
627 return -1;
628 } else if (send_buffer(session, "\r\n", 2) == -1) {
629 return -1;
630 } else if (send_buffer(session, hs_contyp, 14) == -1) {
631 return -1;
632 } else if (send_buffer(session, "text/html\r\n\r\n", 13) == -1) {
633 return -1;
634 }
635 session->header_sent = true;
636
637 if (session->request_method == HEAD) {
638 return 0;
639 }
640
641 if (send_buffer(session, ec_doctype, ec_doctype_len) == -1) {
642 return -1;
643 } else if (send_buffer(session, ec_head, ec_head_len) == -1) {
644 return -1;
645 } else if (send_buffer(session, ecode, ecode_len) == -1) {
646 return -1;
647 } else if (send_buffer(session, " - ", 3) == -1) {
648 return -1;
649 } else if (send_buffer(session, emesg, emesg_len) == -1) {
650 return -1;
651 } else if (send_buffer(session, ec_body1, ec_body1_len) == -1) {
652 return -1;
653 } else if (send_buffer(session, emesg, emesg_len) == -1) {
654 return -1;
655 } else if (send_buffer(session, ec_body2, ec_body2_len) == -1) {
656 return -1;
657 } else if (send_buffer(session, ecode, ecode_len) == -1) {
658 return -1;
659 } else if (send_buffer(session, ec_tail, ec_tail_len) == -1) {
660 return -1;
661 }
662
663 return 0;
664 }
665
fcgi_set_padding(t_fcgi_buffer * fcgi_buffer)666 static void fcgi_set_padding(t_fcgi_buffer *fcgi_buffer) {
667 unsigned char padding;
668
669 if ((padding = fcgi_buffer->data[5] & 7) > 0) {
670 padding = 8 - padding;
671 memset(fcgi_buffer->data + fcgi_buffer->size, 0, (size_t)padding);
672 fcgi_buffer->size += (long)padding;
673 }
674 fcgi_buffer->data[6] = padding;
675 }
676
send_fcgi_buffer(t_fcgi_buffer * fcgi_buffer,const char * buffer,long size)677 int send_fcgi_buffer(t_fcgi_buffer *fcgi_buffer, const char *buffer, long size) {
678 long written;
679
680 if (size > FCGI_BUFFER_SIZE) {
681 if (fcgi_buffer->size > 0) {
682 fcgi_set_padding(fcgi_buffer);
683 if (write_buffer(fcgi_buffer->sock, (char*)fcgi_buffer->data, fcgi_buffer->size) == -1) {
684 return -1;
685 }
686
687 fcgi_buffer->size = 0;
688 }
689
690 memcpy(fcgi_buffer->data, "\x01\x00\x00\x01" "\xff\xff\x00\x00", 8);
691 fcgi_buffer->data[1] = fcgi_buffer->type;
692 fcgi_buffer->data[4] = (FCGI_CHUNK_SIZE >> 8) & 255;
693 fcgi_buffer->data[5] = FCGI_CHUNK_SIZE & 255;
694
695 written = 0;
696 do {
697 if (write_buffer(fcgi_buffer->sock, (char*)fcgi_buffer->data, 8) == -1) {
698 return -1;
699 } else if (write_buffer(fcgi_buffer->sock, buffer + written, FCGI_CHUNK_SIZE) == -1) {
700 return -1;
701 }
702 written += FCGI_CHUNK_SIZE;
703 } while (size - written > FCGI_BUFFER_SIZE);
704
705 if (send_fcgi_buffer(fcgi_buffer, buffer + written, size - written) == -1) {
706 return -1;
707 }
708 } else if (buffer == NULL) {
709 if (fcgi_buffer->size > 0) {
710 fcgi_set_padding(fcgi_buffer);
711 if (write_buffer(fcgi_buffer->sock, (char*)fcgi_buffer->data, fcgi_buffer->size) == -1) {
712 return -1;
713 }
714 }
715
716 memcpy(fcgi_buffer->data, "\x01\x00\x00\x01" "\x00\x00\x00\x00", 8);
717 fcgi_buffer->data[1] = fcgi_buffer->type;
718 if (write_buffer(fcgi_buffer->sock, (char*)fcgi_buffer->data, 8) == -1) {
719 return -1;
720 }
721
722 fcgi_buffer->size = 0;
723 } else {
724 if ((fcgi_buffer->size + size > FCGI_BUFFER_SIZE) && (fcgi_buffer->size > 0)) {
725 fcgi_set_padding(fcgi_buffer);
726 if (write_buffer(fcgi_buffer->sock, (char*)fcgi_buffer->data, fcgi_buffer->size) == -1) {
727 return -1;
728 }
729 fcgi_buffer->size = 0;
730 }
731
732 if (fcgi_buffer->size == 0) {
733 memcpy(fcgi_buffer->data, "\x01\x00\x00\x01" "\x00\x00\x00\x00", 8);
734 fcgi_buffer->data[1] = fcgi_buffer->type;
735 fcgi_buffer->size = 8;
736 }
737
738 memcpy(fcgi_buffer->data + fcgi_buffer->size, buffer, size);
739 fcgi_buffer->size += size;
740 fcgi_buffer->data[4] = ((fcgi_buffer->size - 8) >> 8) & 255;
741 fcgi_buffer->data[5] = (fcgi_buffer->size - 8) & 255;
742 }
743
744 return 0;
745 }
746
747 /* Send a Basic Authentication message to the client.
748 */
send_basic_auth(t_session * session)749 int send_basic_auth(t_session *session) {
750 if (send_buffer(session, "WWW-Authenticate: Basic", 23) == -1) {
751 return -1;
752 } else if (session->host->login_message != NULL) {
753 if (send_buffer(session, " realm=\"", 8) == -1) {
754 return -1;
755 } else if (send_buffer(session, session->host->login_message, strlen(session->host->login_message)) == -1) {
756 return -1;
757 } else if (send_buffer(session, "\"", 1) == -1) {
758 return -1;
759 }
760 }
761
762 return send_buffer(session, "\r\n", 2);
763 }
764
765 /* Send a Digest Authentication message to the client.
766 */
send_digest_auth(t_session * session)767 int send_digest_auth(t_session *session) {
768 char nonce[2 * NONCE_DIGITS + 1];
769 int i;
770
771 for (i = 0; i < NONCE_DIGITS; i++) {
772 snprintf(nonce + (2 * i), 3, "%02hhX", (char)random());
773 }
774
775 if (send_buffer(session, "WWW-Authenticate: Digest", 24) == -1) {
776 return -1;
777 } else if (session->host->login_message != NULL) {
778 if (send_buffer(session, " realm=\"", 8) == -1) {
779 return -1;
780 } else if (send_buffer(session, session->host->login_message, strlen(session->host->login_message)) == -1) {
781 return -1;
782 } else if (send_buffer(session, "\"", 1) == -1) {
783 return -1;
784 }
785 }
786
787 if (send_buffer(session, ", nonce=\"", 9) == -1) {
788 return -1;
789 } else if (send_buffer(session, nonce, 2 * NONCE_DIGITS) == -1) {
790 return -1;
791 }
792
793 return send_buffer(session, "\", algorithm=MD5\r\n", 18);
794 }
795
796 /* Link two streams
797 */
link_streams(t_stream * stream1,t_stream * stream2,int poll_timeout)798 int link_streams(t_stream *stream1, t_stream *stream2, int poll_timeout) {
799 struct pollfd poll_data[2];
800 int result, poll_result, bytes_read;
801 bool keep_reading;
802 char buffer[STREAM_BUFFER_SIZE];
803
804 poll_data[0].fd = stream1->socket;
805 poll_data[0].events = POLL_EVENT_BITS;
806 poll_data[1].fd = stream2->socket;
807 poll_data[1].events = POLL_EVENT_BITS;
808
809 result = 0;
810 keep_reading = true;
811 poll_timeout *= 1000;
812
813 /* Forward data
814 */
815 do {
816 #ifdef ENABLE_TLS
817 poll_result = stream1->use_tls ? tls_pending(stream1->tls_context) : 0;
818 if (poll_result == 0) {
819 poll_result = stream2->use_tls ? tls_pending(stream2->tls_context) : 0;
820 }
821
822 if (poll_result == 0)
823 #endif
824 poll_result = poll(poll_data, 2, poll_timeout);
825
826 switch (poll_result) {
827 case -1:
828 result = -1;
829 keep_reading = false;
830 break;
831 case 0:
832 result = 504;
833 keep_reading = false;
834 break;
835 default:
836 /* Data from stream1 to stream2
837 */
838 if (poll_data[0].revents != 0) {
839 #ifdef ENABLE_TLS
840 if (stream1->use_tls) {
841 if ((bytes_read = tls_receive(stream1->tls_context, buffer, STREAM_BUFFER_SIZE)) == -1) {
842 keep_reading = false;
843 result = -1;
844 break;
845 }
846 } else
847 #endif
848 if ((bytes_read = read(stream1->socket, buffer, STREAM_BUFFER_SIZE)) == -1) {
849 keep_reading = false;
850 result = -1;
851 break;
852 }
853
854 if (bytes_read == 0) {
855 keep_reading = false;
856 break;
857 }
858
859 #ifdef ENABLE_TLS
860 if (stream2->use_tls) {
861 if (tls_send_buffer(stream2->tls_context, buffer, bytes_read) == -1) {
862 keep_reading = false;
863 result = -1;
864 break;
865 }
866 } else
867 #endif
868 if (write_buffer(stream2->socket, buffer, bytes_read) == -1) {
869 keep_reading = false;
870 result = -1;
871 break;
872 }
873 }
874
875 /* Data from stream2 to stream1
876 */
877 if (poll_data[1].revents != 0) {
878 #ifdef ENABLE_TLS
879 if (stream2->use_tls) {
880 if ((bytes_read = tls_receive(stream2->tls_context, buffer, STREAM_BUFFER_SIZE)) == -1) {
881 keep_reading = false;
882 result = -1;
883 break;
884 }
885 } else
886 #endif
887 if ((bytes_read = read(stream2->socket, buffer, STREAM_BUFFER_SIZE)) == -1) {
888 keep_reading = false;
889 result = -1;
890 break;
891 }
892
893 if (bytes_read == 0) {
894 keep_reading = false;
895 break;
896 }
897
898 #ifdef ENABLE_TLS
899 if (stream1->use_tls) {
900 if (tls_send_buffer(stream1->tls_context, buffer, bytes_read) == -1) {
901 keep_reading = false;
902 result = -1;
903 break;
904 }
905 } else
906 #endif
907 if (write_buffer(stream1->socket, buffer, bytes_read) == -1) {
908 keep_reading = false;
909 result = -1;
910 break;
911 }
912 }
913 }
914 } while (keep_reading);
915
916 return result;
917 }
918