1 /* Icecast
2 *
3 * This program is distributed under the GNU General Public License, version 2.
4 * A copy of this license is included with this source.
5 *
6 * Copyright 2000-2004, Jack Moffitt <jack@xiph.org,
7 * Michael Smith <msmith@xiph.org>,
8 * oddsock <oddsock@xiph.org>,
9 * Karl Heyes <karl@xiph.org>
10 * and others (see AUTHORS for details).
11 * Copyright 2011, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
12 * Dave 'justdave' Miller <justdave@mozilla.com>.
13 */
14
15 /* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- */
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <string.h>
24 #ifdef HAVE_POLL
25 #include <sys/poll.h>
26 #endif
27 #include <sys/types.h>
28 #include <sys/stat.h>
29
30 #ifndef _WIN32
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #else
34 #include <winsock2.h>
35 #define snprintf _snprintf
36 #define strcasecmp stricmp
37 #define strncasecmp strnicmp
38 #endif
39
40 #include "compat.h"
41
42 #include "thread/thread.h"
43 #include "avl/avl.h"
44 #include "net/sock.h"
45 #include "httpp/httpp.h"
46
47 #include "cfgfile.h"
48 #include "global.h"
49 #include "util.h"
50 #include "connection.h"
51 #include "refbuf.h"
52 #include "client.h"
53 #include "stats.h"
54 #include "logging.h"
55 #include "xslt.h"
56 #include "fserve.h"
57 #include "sighandler.h"
58
59 #include "yp.h"
60 #include "source.h"
61 #include "format.h"
62 #include "format_mp3.h"
63 #include "event.h"
64 #include "admin.h"
65 #include "auth.h"
66
67 #define CATMODULE "connection"
68
69 /* Two different major types of source authentication.
70 Shoutcast style is used only by the Shoutcast DSP
71 and is a crazy version of HTTP. It looks like :
72 Source Client -> Connects to port + 1
73 Source Client -> sends encoder password (plaintext)\r\n
74 Icecast -> reads encoder password, if ok, sends OK2\r\n, else disconnects
75 Source Client -> reads OK2\r\n, then sends http-type request headers
76 that contain the stream details (icy-name, etc..)
77 Icecast -> reads headers, stores them
78 Source Client -> starts sending MP3 data
79 Source Client -> periodically updates metadata via admin.cgi call
80
81 Icecast auth style uses HTTP and Basic Authorization.
82 */
83 #define SHOUTCAST_SOURCE_AUTH 1
84 #define ICECAST_SOURCE_AUTH 0
85
86 typedef struct client_queue_tag {
87 client_t *client;
88 int offset;
89 int stream_offset;
90 int shoutcast;
91 char *shoutcast_mount;
92 struct client_queue_tag *next;
93 } client_queue_t;
94
95 typedef struct _thread_queue_tag {
96 thread_type *thread_id;
97 struct _thread_queue_tag *next;
98 } thread_queue_t;
99
100 typedef struct
101 {
102 char *filename;
103 time_t file_recheck;
104 time_t file_mtime;
105 avl_tree *contents;
106 } cache_file_contents;
107
108 static spin_t _connection_lock; // protects _current_id, _con_queue, _con_queue_tail
109 static volatile unsigned long _current_id = 0;
110 static int _initialized = 0;
111
112 static volatile client_queue_t *_req_queue = NULL, **_req_queue_tail = &_req_queue;
113 static volatile client_queue_t *_con_queue = NULL, **_con_queue_tail = &_con_queue;
114 static int ssl_ok;
115 #ifdef HAVE_OPENSSL
116 static SSL_CTX *ssl_ctx;
117 #endif
118
119 /* filtering client connection based on IP */
120 static cache_file_contents banned_ip, allowed_ip;
121
122 rwlock_t _source_shutdown_rwlock;
123
124 static void _handle_connection(void);
125
compare_ip(void * arg,void * a,void * b)126 static int compare_ip (void *arg, void *a, void *b)
127 {
128 const char *ip = (const char *)a;
129 const char *pattern = (const char *)b;
130
131 return strcmp (pattern, ip);
132 }
133
134
free_filtered_ip(void * x)135 static int free_filtered_ip (void*x)
136 {
137 free (x);
138 return 1;
139 }
140
141
connection_initialize(void)142 void connection_initialize(void)
143 {
144 if (_initialized) return;
145
146 thread_spin_create (&_connection_lock);
147 thread_mutex_create(&move_clients_mutex);
148 thread_rwlock_create(&_source_shutdown_rwlock);
149 thread_cond_create(&global.shutdown_cond);
150 _req_queue = NULL;
151 _req_queue_tail = &_req_queue;
152 _con_queue = NULL;
153 _con_queue_tail = &_con_queue;
154
155 banned_ip.contents = NULL;
156 banned_ip.file_mtime = 0;
157
158 allowed_ip.contents = NULL;
159 allowed_ip.file_mtime = 0;
160
161 _initialized = 1;
162 }
163
connection_shutdown(void)164 void connection_shutdown(void)
165 {
166 if (!_initialized) return;
167
168 #ifdef HAVE_OPENSSL
169 SSL_CTX_free (ssl_ctx);
170 #endif
171 if (banned_ip.contents) avl_tree_free (banned_ip.contents, free_filtered_ip);
172 if (allowed_ip.contents) avl_tree_free (allowed_ip.contents, free_filtered_ip);
173
174 thread_cond_destroy(&global.shutdown_cond);
175 thread_rwlock_destroy(&_source_shutdown_rwlock);
176 thread_spin_destroy (&_connection_lock);
177 thread_mutex_destroy(&move_clients_mutex);
178
179 _initialized = 0;
180 }
181
_next_connection_id(void)182 static unsigned long _next_connection_id(void)
183 {
184 unsigned long id;
185
186 thread_spin_lock (&_connection_lock);
187 id = _current_id++;
188 thread_spin_unlock (&_connection_lock);
189
190 return id;
191 }
192
193
194 #ifdef HAVE_OPENSSL
get_ssl_certificate(ice_config_t * config)195 static void get_ssl_certificate (ice_config_t *config)
196 {
197 #if OPENSSL_VERSION_NUMBER < 0x1000114fL
198 SSL_METHOD *method;
199 #else
200 const SSL_METHOD *method;
201 #endif
202 long ssl_opts;
203 ssl_ok = 0;
204
205 SSL_load_error_strings(); /* readable error messages */
206 SSL_library_init(); /* initialize library */
207
208 method = SSLv23_server_method();
209 ssl_ctx = SSL_CTX_new (method);
210 ssl_opts = SSL_CTX_get_options (ssl_ctx);
211 #ifdef SSL_OP_NO_COMPRESSION
212 SSL_CTX_set_options (ssl_ctx, ssl_opts|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION);
213 #else
214 SSL_CTX_set_options (ssl_ctx, ssl_opts|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
215 #endif
216
217 do
218 {
219 if (config->cert_file == NULL)
220 break;
221 if (SSL_CTX_use_certificate_chain_file (ssl_ctx, config->cert_file) <= 0)
222 {
223 ICECAST_LOG_WARN("Invalid cert file %s", config->cert_file);
224 break;
225 }
226 if (SSL_CTX_use_PrivateKey_file (ssl_ctx, config->cert_file, SSL_FILETYPE_PEM) <= 0)
227 {
228 ICECAST_LOG_WARN("Invalid private key file %s", config->cert_file);
229 break;
230 }
231 if (!SSL_CTX_check_private_key (ssl_ctx))
232 {
233 ICECAST_LOG_ERROR("Invalid %s - Private key does not match cert public key", config->cert_file);
234 break;
235 }
236 if (SSL_CTX_set_cipher_list(ssl_ctx, config->cipher_list) <= 0)
237 {
238 ICECAST_LOG_WARN("Invalid cipher list: %s", config->cipher_list);
239 }
240 ssl_ok = 1;
241 ICECAST_LOG_INFO("SSL certificate found at %s", config->cert_file);
242 ICECAST_LOG_INFO("SSL using ciphers %s", config->cipher_list);
243 return;
244 } while (0);
245 ICECAST_LOG_INFO("No SSL capability on any configured ports");
246 }
247
248
249 /* handlers for reading and writing a connection_t when there is ssl
250 * configured on the listening port
251 */
connection_read_ssl(connection_t * con,void * buf,size_t len)252 static int connection_read_ssl (connection_t *con, void *buf, size_t len)
253 {
254 int bytes = SSL_read (con->ssl, buf, len);
255
256 if (bytes < 0)
257 {
258 switch (SSL_get_error (con->ssl, bytes))
259 {
260 case SSL_ERROR_WANT_READ:
261 case SSL_ERROR_WANT_WRITE:
262 return -1;
263 }
264 con->error = 1;
265 }
266 return bytes;
267 }
268
connection_send_ssl(connection_t * con,const void * buf,size_t len)269 static int connection_send_ssl (connection_t *con, const void *buf, size_t len)
270 {
271 int bytes = SSL_write (con->ssl, buf, len);
272
273 if (bytes < 0)
274 {
275 switch (SSL_get_error (con->ssl, bytes))
276 {
277 case SSL_ERROR_WANT_READ:
278 case SSL_ERROR_WANT_WRITE:
279 return -1;
280 }
281 con->error = 1;
282 }
283 else
284 con->sent_bytes += bytes;
285 return bytes;
286 }
287 #else
288
289 /* SSL not compiled in, so at least log it */
get_ssl_certificate(ice_config_t * config)290 static void get_ssl_certificate (ice_config_t *config)
291 {
292 ssl_ok = 0;
293 ICECAST_LOG_INFO("No SSL capability");
294 }
295 #endif /* HAVE_OPENSSL */
296
297
298 /* handlers (default) for reading and writing a connection_t, no encrpytion
299 * used just straight access to the socket
300 */
connection_read(connection_t * con,void * buf,size_t len)301 static int connection_read (connection_t *con, void *buf, size_t len)
302 {
303 int bytes = sock_read_bytes (con->sock, buf, len);
304 if (bytes == 0)
305 con->error = 1;
306 if (bytes == -1 && !sock_recoverable (sock_error()))
307 con->error = 1;
308 return bytes;
309 }
310
connection_send(connection_t * con,const void * buf,size_t len)311 static int connection_send (connection_t *con, const void *buf, size_t len)
312 {
313 int bytes = sock_write_bytes (con->sock, buf, len);
314 if (bytes < 0)
315 {
316 if (!sock_recoverable (sock_error()))
317 con->error = 1;
318 }
319 else
320 con->sent_bytes += bytes;
321 return bytes;
322 }
323
324
325 /* function to handle the re-populating of the avl tree containing IP addresses
326 * for deciding whether a connection of an incoming request is to be dropped.
327 */
recheck_ip_file(cache_file_contents * cache)328 static void recheck_ip_file (cache_file_contents *cache)
329 {
330 time_t now = time(NULL);
331 if (now >= cache->file_recheck)
332 {
333 struct stat file_stat;
334 FILE *file = NULL;
335 int count = 0;
336 avl_tree *new_ips;
337 char line [MAX_LINE_LEN];
338
339 cache->file_recheck = now + 10;
340 if (cache->filename == NULL)
341 {
342 if (cache->contents)
343 {
344 avl_tree_free (cache->contents, free_filtered_ip);
345 cache->contents = NULL;
346 }
347 return;
348 }
349 if (stat (cache->filename, &file_stat) < 0)
350 {
351 ICECAST_LOG_WARN("failed to check status of \"%s\": %s", cache->filename, strerror(errno));
352 return;
353 }
354 if (file_stat.st_mtime == cache->file_mtime)
355 return; /* common case, no update to file */
356
357 cache->file_mtime = file_stat.st_mtime;
358
359 file = fopen (cache->filename, "r");
360 if (file == NULL)
361 {
362 ICECAST_LOG_WARN("Failed to open file \"%s\": %s", cache->filename, strerror (errno));
363 return;
364 }
365
366 new_ips = avl_tree_new (compare_ip, NULL);
367
368 while (get_line (file, line, MAX_LINE_LEN))
369 {
370 char *str;
371 if(!line[0] || line[0] == '#')
372 continue;
373 count++;
374 str = strdup (line);
375 if (str)
376 avl_insert (new_ips, str);
377 }
378 fclose (file);
379 ICECAST_LOG_INFO("%d entries read from file \"%s\"", count, cache->filename);
380
381 if (cache->contents) avl_tree_free (cache->contents, free_filtered_ip);
382 cache->contents = new_ips;
383 }
384 }
385
386
387 /* return 0 if the passed ip address is not to be handled by icecast, non-zero otherwise */
accept_ip_address(char * ip)388 static int accept_ip_address (char *ip)
389 {
390 void *result;
391
392 recheck_ip_file (&banned_ip);
393 recheck_ip_file (&allowed_ip);
394
395 if (banned_ip.contents)
396 {
397 if (avl_get_by_key (banned_ip.contents, ip, &result) == 0)
398 {
399 ICECAST_LOG_DEBUG("%s is banned", ip);
400 return 0;
401 }
402 }
403 if (allowed_ip.contents)
404 {
405 if (avl_get_by_key (allowed_ip.contents, ip, &result) == 0)
406 {
407 ICECAST_LOG_DEBUG("%s is allowed", ip);
408 return 1;
409 }
410 else
411 {
412 ICECAST_LOG_DEBUG("%s is not allowed", ip);
413 return 0;
414 }
415 }
416 return 1;
417 }
418
419
connection_create(sock_t sock,sock_t serversock,char * ip)420 connection_t *connection_create (sock_t sock, sock_t serversock, char *ip)
421 {
422 connection_t *con;
423 con = (connection_t *)calloc(1, sizeof(connection_t));
424 if (con)
425 {
426 con->sock = sock;
427 con->serversock = serversock;
428 con->con_time = time(NULL);
429 con->id = _next_connection_id();
430 con->ip = ip;
431 con->read = connection_read;
432 con->send = connection_send;
433 }
434
435 return con;
436 }
437
438 /* prepare connection for interacting over a SSL connection
439 */
connection_uses_ssl(connection_t * con)440 void connection_uses_ssl (connection_t *con)
441 {
442 #ifdef HAVE_OPENSSL
443 con->read = connection_read_ssl;
444 con->send = connection_send_ssl;
445 con->ssl = SSL_new (ssl_ctx);
446 SSL_set_accept_state (con->ssl);
447 SSL_set_fd (con->ssl, con->sock);
448 #endif
449 }
450
wait_for_serversock(int timeout)451 static sock_t wait_for_serversock(int timeout)
452 {
453 #ifdef HAVE_POLL
454 struct pollfd ufds [global.server_sockets];
455 int i, ret;
456
457 for(i=0; i < global.server_sockets; i++) {
458 ufds[i].fd = global.serversock[i];
459 ufds[i].events = POLLIN;
460 ufds[i].revents = 0;
461 }
462
463 ret = poll(ufds, global.server_sockets, timeout);
464 if(ret < 0) {
465 return SOCK_ERROR;
466 }
467 else if(ret == 0) {
468 return SOCK_ERROR;
469 }
470 else {
471 int dst;
472 for(i=0; i < global.server_sockets; i++) {
473 if(ufds[i].revents & POLLIN)
474 return ufds[i].fd;
475 if(ufds[i].revents & (POLLHUP|POLLERR|POLLNVAL))
476 {
477 if (ufds[i].revents & (POLLHUP|POLLERR))
478 {
479 sock_close (global.serversock[i]);
480 ICECAST_LOG_WARN("Had to close a listening socket");
481 }
482 global.serversock[i] = SOCK_ERROR;
483 }
484 }
485 /* remove any closed sockets */
486 for(i=0, dst=0; i < global.server_sockets; i++)
487 {
488 if (global.serversock[i] == SOCK_ERROR)
489 continue;
490 if (i!=dst)
491 global.serversock[dst] = global.serversock[i];
492 dst++;
493 }
494 global.server_sockets = dst;
495 return SOCK_ERROR;
496 }
497 #else
498 fd_set rfds;
499 struct timeval tv, *p=NULL;
500 int i, ret;
501 sock_t max = SOCK_ERROR;
502
503 FD_ZERO(&rfds);
504
505 for(i=0; i < global.server_sockets; i++) {
506 FD_SET(global.serversock[i], &rfds);
507 if (max == SOCK_ERROR || global.serversock[i] > max)
508 max = global.serversock[i];
509 }
510
511 if(timeout >= 0) {
512 tv.tv_sec = timeout/1000;
513 tv.tv_usec = (timeout % 1000) * 1000;
514 p = &tv;
515 }
516
517 ret = select(max+1, &rfds, NULL, NULL, p);
518 if(ret < 0) {
519 return SOCK_ERROR;
520 }
521 else if(ret == 0) {
522 return SOCK_ERROR;
523 }
524 else {
525 for(i=0; i < global.server_sockets; i++) {
526 if(FD_ISSET(global.serversock[i], &rfds))
527 return global.serversock[i];
528 }
529 return SOCK_ERROR; /* Should be impossible, stop compiler warnings */
530 }
531 #endif
532 }
533
_accept_connection(int duration)534 static connection_t *_accept_connection(int duration)
535 {
536 sock_t sock, serversock;
537 char *ip;
538
539 serversock = wait_for_serversock (duration);
540 if (serversock == SOCK_ERROR)
541 return NULL;
542
543 /* malloc enough room for a full IP address (including ipv6) */
544 ip = (char *)malloc(MAX_ADDR_LEN);
545
546 sock = sock_accept(serversock, ip, MAX_ADDR_LEN);
547 if (sock != SOCK_ERROR)
548 {
549 connection_t *con = NULL;
550 /* Make any IPv4 mapped IPv6 address look like a normal IPv4 address */
551 if (strncmp (ip, "::ffff:", 7) == 0)
552 memmove (ip, ip+7, strlen (ip+7)+1);
553
554 if (accept_ip_address (ip))
555 con = connection_create (sock, serversock, ip);
556 if (con)
557 return con;
558 sock_close (sock);
559 }
560 else
561 {
562 if (!sock_recoverable(sock_error()))
563 {
564 ICECAST_LOG_WARN("accept() failed with error %d: %s", sock_error(), strerror(sock_error()));
565 thread_sleep (500000);
566 }
567 }
568 free(ip);
569 return NULL;
570 }
571
572
573 /* add client to connection queue. At this point some header information
574 * has been collected, so we now pass it onto the connection thread for
575 * further processing
576 */
_add_connection(client_queue_t * node)577 static void _add_connection (client_queue_t *node)
578 {
579 thread_spin_lock (&_connection_lock);
580 *_con_queue_tail = node;
581 _con_queue_tail = (volatile client_queue_t **)&node->next;
582 thread_spin_unlock (&_connection_lock);
583 }
584
585
586 /* this returns queued clients for the connection thread. headers are
587 * already provided, but need to be parsed.
588 */
_get_connection(void)589 static client_queue_t *_get_connection(void)
590 {
591 client_queue_t *node = NULL;
592
593 thread_spin_lock (&_connection_lock);
594
595 if (_con_queue)
596 {
597 node = (client_queue_t *)_con_queue;
598 _con_queue = node->next;
599 if (_con_queue == NULL)
600 _con_queue_tail = &_con_queue;
601 node->next = NULL;
602 }
603
604 thread_spin_unlock (&_connection_lock);
605 return node;
606 }
607
608
609 /* run along queue checking for any data that has come in or a timeout */
process_request_queue(void)610 static void process_request_queue (void)
611 {
612 client_queue_t **node_ref = (client_queue_t **)&_req_queue;
613 ice_config_t *config = config_get_config ();
614 int timeout = config->header_timeout;
615 config_release_config();
616
617 while (*node_ref)
618 {
619 client_queue_t *node = *node_ref;
620 client_t *client = node->client;
621 int len = PER_CLIENT_REFBUF_SIZE - 1 - node->offset;
622 char *buf = client->refbuf->data + node->offset;
623
624 if (len > 0)
625 {
626 if (client->con->con_time + timeout <= time(NULL))
627 len = 0;
628 else
629 len = client_read_bytes (client, buf, len);
630 }
631
632 if (len > 0)
633 {
634 int pass_it = 1;
635 char *ptr;
636
637 /* handle \n, \r\n and nsvcap which for some strange reason has
638 * EOL as \r\r\n */
639 node->offset += len;
640 client->refbuf->data [node->offset] = '\000';
641 do
642 {
643 if (node->shoutcast == 1)
644 {
645 /* password line */
646 if (strstr (client->refbuf->data, "\r\r\n") != NULL)
647 break;
648 if (strstr (client->refbuf->data, "\r\n") != NULL)
649 break;
650 if (strstr (client->refbuf->data, "\n") != NULL)
651 break;
652 }
653 /* stream_offset refers to the start of any data sent after the
654 * http style headers, we don't want to lose those */
655 ptr = strstr (client->refbuf->data, "\r\r\n\r\r\n");
656 if (ptr)
657 {
658 node->stream_offset = (ptr+6) - client->refbuf->data;
659 break;
660 }
661 ptr = strstr (client->refbuf->data, "\r\n\r\n");
662 if (ptr)
663 {
664 node->stream_offset = (ptr+4) - client->refbuf->data;
665 break;
666 }
667 ptr = strstr (client->refbuf->data, "\n\n");
668 if (ptr)
669 {
670 node->stream_offset = (ptr+2) - client->refbuf->data;
671 break;
672 }
673 pass_it = 0;
674 } while (0);
675
676 if (pass_it)
677 {
678 if ((client_queue_t **)_req_queue_tail == &(node->next))
679 _req_queue_tail = (volatile client_queue_t **)node_ref;
680 *node_ref = node->next;
681 node->next = NULL;
682 _add_connection (node);
683 continue;
684 }
685 }
686 else
687 {
688 if (len == 0 || client->con->error)
689 {
690 if ((client_queue_t **)_req_queue_tail == &node->next)
691 _req_queue_tail = (volatile client_queue_t **)node_ref;
692 *node_ref = node->next;
693 client_destroy (client);
694 free (node);
695 continue;
696 }
697 }
698 node_ref = &node->next;
699 }
700 _handle_connection();
701 }
702
703
704 /* add node to the queue of requests. This is where the clients are when
705 * initial http details are read.
706 */
_add_request_queue(client_queue_t * node)707 static void _add_request_queue (client_queue_t *node)
708 {
709 *_req_queue_tail = node;
710 _req_queue_tail = (volatile client_queue_t **)&node->next;
711 }
712
713
connection_accept_loop(void)714 void connection_accept_loop (void)
715 {
716 connection_t *con;
717 ice_config_t *config;
718 int duration = 300;
719
720 config = config_get_config ();
721 get_ssl_certificate (config);
722 config_release_config ();
723
724 while (global.running == ICECAST_RUNNING)
725 {
726 con = _accept_connection (duration);
727
728 if (con)
729 {
730 client_queue_t *node;
731 ice_config_t *config;
732 client_t *client = NULL;
733 listener_t *listener;
734
735 global_lock();
736 if (client_create (&client, con, NULL) < 0)
737 {
738 global_unlock();
739 client_send_403 (client, "Icecast connection limit reached");
740 /* don't be too eager as this is an imposed hard limit */
741 thread_sleep (400000);
742 continue;
743 }
744
745 /* setup client for reading incoming http */
746 client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';
747
748 if (sock_set_blocking (client->con->sock, 0) || sock_set_nodelay (client->con->sock))
749 {
750 global_unlock();
751 ICECAST_LOG_WARN("failed to set tcp options on client connection, dropping");
752 client_destroy (client);
753 continue;
754 }
755
756 node = calloc (1, sizeof (client_queue_t));
757 if (node == NULL)
758 {
759 global_unlock();
760 client_destroy (client);
761 continue;
762 }
763 node->client = client;
764
765 config = config_get_config();
766 listener = config_get_listen_sock (config, client->con);
767
768 if (listener)
769 {
770 if (listener->shoutcast_compat)
771 node->shoutcast = 1;
772 if (listener->ssl && ssl_ok)
773 connection_uses_ssl (client->con);
774 if (listener->shoutcast_mount)
775 node->shoutcast_mount = strdup (listener->shoutcast_mount);
776 }
777 global_unlock();
778 config_release_config();
779
780 _add_request_queue (node);
781 stats_event_inc (NULL, "connections");
782 duration = 5;
783 }
784 else
785 {
786 if (_req_queue == NULL)
787 duration = 300; /* use longer timeouts when nothing waiting */
788 }
789 process_request_queue ();
790 }
791
792 /* Give all the other threads notification to shut down */
793 thread_cond_broadcast(&global.shutdown_cond);
794
795 /* wait for all the sources to shutdown */
796 thread_rwlock_wlock(&_source_shutdown_rwlock);
797 thread_rwlock_unlock(&_source_shutdown_rwlock);
798 }
799
800
801 /* Called when activating a source. Verifies that the source count is not
802 * exceeded and applies any initial parameters.
803 */
connection_complete_source(source_t * source,int response)804 int connection_complete_source (source_t *source, int response)
805 {
806 ice_config_t *config;
807
808 global_lock ();
809 ICECAST_LOG_DEBUG("sources count is %d", global.sources);
810
811 config = config_get_config();
812 if (global.sources < config->source_limit)
813 {
814 const char *contenttype;
815 const char *expectcontinue;
816 mount_proxy *mountinfo;
817 format_type_t format_type;
818
819 /* setup format handler */
820 contenttype = httpp_getvar (source->parser, "content-type");
821 if (contenttype != NULL)
822 {
823 format_type = format_get_type (contenttype);
824
825 if (format_type == FORMAT_ERROR)
826 {
827 config_release_config();
828 global_unlock();
829 if (response) {
830 client_send_403 (source->client, "Content-type not supported");
831 source->client = NULL;
832 }
833 ICECAST_LOG_WARN("Content-type \"%s\" not supported, dropping source", contenttype);
834 return -1;
835 }
836 } else if (source->parser->req_type == httpp_req_put) {
837 config_release_config();
838 global_unlock();
839 if (response) {
840 client_send_403 (source->client, "No Content-type given");
841 source->client = NULL;
842 }
843 ICECAST_LOG_ERROR("Content-type not given in PUT request, dropping source");
844 return -1;
845 } else {
846 ICECAST_LOG_ERROR("No content-type header, falling back to backwards compatibility mode "
847 "for icecast 1.x relays. Assuming content is mp3. This behaviour is deprecated "
848 "and the source client will NOT work with future Icecast versions!");
849 format_type = FORMAT_TYPE_GENERIC;
850 }
851
852 if (format_get_plugin (format_type, source) < 0)
853 {
854 global_unlock();
855 config_release_config();
856 if (response)
857 {
858 client_send_403 (source->client, "internal format allocation problem");
859 source->client = NULL;
860 }
861 ICECAST_LOG_WARN("plugin format failed for \"%s\"", source->mount);
862 return -1;
863 }
864
865 /* For PUT support we check for 100-continue and send back a 100 to stay in spec */
866 expectcontinue = httpp_getvar (source->parser, "expect");
867 if (expectcontinue != NULL)
868 {
869 #ifdef HAVE_STRCASESTR
870 if (strcasestr (expectcontinue, "100-continue") != NULL)
871 #else
872 ICECAST_LOG_WARN("OS doesn't support case insenestive substring checks...");
873 if (strstr (expectcontinue, "100-continue") != NULL)
874 #endif
875 {
876 client_send_100 (source->client);
877 }
878 }
879
880 global.sources++;
881 stats_event_args (NULL, "sources", "%d", global.sources);
882 global_unlock();
883
884 source->running = 1;
885 mountinfo = config_find_mount (config, source->mount, MOUNT_TYPE_NORMAL);
886 source_update_settings (config, source, mountinfo);
887 config_release_config();
888 slave_rebuild_mounts();
889
890 source->shutdown_rwlock = &_source_shutdown_rwlock;
891 ICECAST_LOG_DEBUG("source is ready to start");
892
893 return 0;
894 }
895 ICECAST_LOG_WARN("Request to add source when maximum source limit "
896 "reached %d", global.sources);
897
898 global_unlock();
899 config_release_config();
900
901 if (response)
902 {
903 client_send_403 (source->client, "too many sources connected");
904 source->client = NULL;
905 }
906
907 return -1;
908 }
909
910
_check_pass_http(http_parser_t * parser,const char * correctuser,const char * correctpass)911 static int _check_pass_http(http_parser_t *parser,
912 const char *correctuser, const char *correctpass)
913 {
914 /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */
915 const char *header = httpp_getvar(parser, "authorization");
916 char *userpass, *tmp;
917 char *username, *password;
918
919 if(header == NULL)
920 return 0;
921
922 if(strncmp(header, "Basic ", 6))
923 return 0;
924
925 userpass = util_base64_decode(header+6);
926 if(userpass == NULL) {
927 ICECAST_LOG_WARN("Base64 decode of Authorization header \"%s\" failed",
928 header+6);
929 return 0;
930 }
931
932 tmp = strchr(userpass, ':');
933 if(!tmp) {
934 free(userpass);
935 return 0;
936 }
937 *tmp = 0;
938 username = userpass;
939 password = tmp+1;
940
941 if(strcmp(username, correctuser) || strcmp(password, correctpass)) {
942 free(userpass);
943 return 0;
944 }
945 free(userpass);
946
947 return 1;
948 }
949
_check_pass_icy(http_parser_t * parser,const char * correctpass)950 static int _check_pass_icy(http_parser_t *parser, const char *correctpass)
951 {
952 const char *password;
953
954 password = httpp_getvar(parser, HTTPP_VAR_ICYPASSWORD);
955 if(!password)
956 return 0;
957
958 if (strcmp(password, correctpass))
959 return 0;
960 else
961 return 1;
962 }
963
_check_pass_ice(http_parser_t * parser,const char * correctpass)964 static int _check_pass_ice(http_parser_t *parser, const char *correctpass)
965 {
966 const char *password;
967
968 password = httpp_getvar(parser, "ice-password");
969 if(!password)
970 password = "";
971
972 if (strcmp(password, correctpass))
973 return 0;
974 else
975 return 1;
976 }
977
connection_check_admin_pass(http_parser_t * parser)978 int connection_check_admin_pass(http_parser_t *parser)
979 {
980 int ret;
981 ice_config_t *config = config_get_config();
982 char *pass = config->admin_password;
983 char *user = config->admin_username;
984 const char *protocol;
985
986 if(!pass || !user) {
987 config_release_config();
988 return 0;
989 }
990
991 protocol = httpp_getvar (parser, HTTPP_VAR_PROTOCOL);
992 if (protocol && strcmp (protocol, "ICY") == 0)
993 ret = _check_pass_icy (parser, pass);
994 else
995 ret = _check_pass_http (parser, user, pass);
996 config_release_config();
997 return ret;
998 }
999
connection_check_relay_pass(http_parser_t * parser)1000 int connection_check_relay_pass(http_parser_t *parser)
1001 {
1002 int ret;
1003 ice_config_t *config = config_get_config();
1004 char *pass = config->relay_password;
1005 char *user = config->relay_username;
1006
1007 if(!pass || !user) {
1008 config_release_config();
1009 return 0;
1010 }
1011
1012 ret = _check_pass_http(parser, user, pass);
1013 config_release_config();
1014 return ret;
1015 }
1016
1017
1018 /* return 0 for failed, 1 for ok
1019 */
connection_check_pass(http_parser_t * parser,const char * user,const char * pass)1020 int connection_check_pass (http_parser_t *parser, const char *user, const char *pass)
1021 {
1022 int ret;
1023 const char *protocol;
1024
1025 if(!pass) {
1026 ICECAST_LOG_WARN("No source password set, rejecting source");
1027 return -1;
1028 }
1029
1030 protocol = httpp_getvar(parser, HTTPP_VAR_PROTOCOL);
1031 if(protocol != NULL && !strcmp(protocol, "ICY")) {
1032 ret = _check_pass_icy(parser, pass);
1033 }
1034 else {
1035 ret = _check_pass_http(parser, user, pass);
1036 if (!ret)
1037 {
1038 ice_config_t *config = config_get_config_unlocked();
1039 if (config->ice_login)
1040 {
1041 ret = _check_pass_ice(parser, pass);
1042 if(ret)
1043 ICECAST_LOG_WARN("Source is using deprecated icecast login");
1044 }
1045 }
1046 }
1047 return ret;
1048 }
1049
1050
1051 /* only called for native icecast source clients */
_handle_source_request(client_t * client,const char * uri)1052 static void _handle_source_request (client_t *client, const char *uri)
1053 {
1054 ICECAST_LOG_INFO("Source logging in at mountpoint \"%s\" from %s",
1055 uri, client->con->ip);
1056
1057 if (uri[0] != '/')
1058 {
1059 ICECAST_LOG_WARN("source mountpoint not starting with /");
1060 client_send_401 (client);
1061 return;
1062 }
1063 switch (client_check_source_auth (client, uri))
1064 {
1065 case 0: /* authenticated from config file */
1066 source_startup (client, uri, ICECAST_SOURCE_AUTH);
1067 break;
1068
1069 case 1: /* auth pending */
1070 break;
1071
1072 default: /* failed */
1073 ICECAST_LOG_INFO("Source (%s) attempted to login with invalid or missing password", uri);
1074 client_send_401(client);
1075 break;
1076 }
1077 }
1078
1079
source_startup(client_t * client,const char * uri,int auth_style)1080 void source_startup (client_t *client, const char *uri, int auth_style)
1081 {
1082 source_t *source;
1083 source = source_reserve (uri);
1084
1085 if (source)
1086 {
1087 source->client = client;
1088 source->parser = client->parser;
1089 source->con = client->con;
1090 if (connection_complete_source (source, 1) < 0)
1091 {
1092 source_clear_source (source);
1093 source_free_source (source);
1094 return;
1095 }
1096 client->respcode = 200;
1097 if (auth_style == SHOUTCAST_SOURCE_AUTH)
1098 {
1099 source->shoutcast_compat = 1;
1100 source_client_callback (client, source);
1101 }
1102 else
1103 {
1104 refbuf_t *ok = refbuf_new (PER_CLIENT_REFBUF_SIZE);
1105 client->respcode = 200;
1106 snprintf (ok->data, PER_CLIENT_REFBUF_SIZE,
1107 "HTTP/1.0 200 OK\r\n\r\n");
1108 ok->len = strlen (ok->data);
1109 /* we may have unprocessed data read in, so don't overwrite it */
1110 ok->associated = client->refbuf;
1111 client->refbuf = ok;
1112 fserve_add_client_callback (client, source_client_callback, source);
1113 }
1114 }
1115 else
1116 {
1117 client_send_403 (client, "Mountpoint in use");
1118 ICECAST_LOG_WARN("Mountpoint %s in use", uri);
1119 }
1120 }
1121
1122
_handle_stats_request(client_t * client,char * uri)1123 static void _handle_stats_request (client_t *client, char *uri)
1124 {
1125 stats_event_inc(NULL, "stats_connections");
1126
1127 if (connection_check_admin_pass (client->parser) == 0)
1128 {
1129 client_send_401 (client);
1130 ICECAST_LOG_ERROR("Bad password for stats connection");
1131 return;
1132 }
1133
1134 client->respcode = 200;
1135 snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
1136 "HTTP/1.0 200 OK\r\n\r\n");
1137 client->refbuf->len = strlen (client->refbuf->data);
1138 fserve_add_client_callback (client, stats_callback, NULL);
1139 }
1140
_handle_get_request(client_t * client,char * passed_uri)1141 static void _handle_get_request (client_t *client, char *passed_uri)
1142 {
1143 char *serverhost = NULL;
1144 int serverport = 0;
1145 aliases *alias;
1146 ice_config_t *config;
1147 char *uri = passed_uri;
1148 listener_t *listen_sock;
1149
1150 config = config_get_config();
1151
1152 listen_sock = config_get_listen_sock (config, client->con);
1153 if (listen_sock)
1154 {
1155 serverhost = listen_sock->bind_address;
1156 serverport = listen_sock->port;
1157 }
1158 alias = config->aliases;
1159
1160 /* there are several types of HTTP GET clients
1161 ** media clients, which are looking for a source (eg, URI = /stream.ogg)
1162 ** stats clients, which are looking for /admin/stats.xml
1163 ** and directory server authorizers, which are looking for /GUID-xxxxxxxx
1164 ** (where xxxxxx is the GUID in question) - this isn't implemented yet.
1165 ** we need to handle the latter two before the former, as the latter two
1166 ** aren't subject to the limits.
1167 */
1168 /* TODO: add GUID-xxxxxx */
1169
1170 /* Handle aliases */
1171 while(alias) {
1172 if(strcmp(uri, alias->source) == 0 && (alias->port == -1 || alias->port == serverport) && (alias->bind_address == NULL || (serverhost != NULL && strcmp(alias->bind_address, serverhost) == 0))) {
1173 uri = strdup (alias->destination);
1174 ICECAST_LOG_DEBUG("alias has made %s into %s", passed_uri, uri);
1175 break;
1176 }
1177 alias = alias->next;
1178 }
1179 config_release_config();
1180
1181 stats_event_inc(NULL, "client_connections");
1182
1183 /* Dispatch all admin requests */
1184 if ((strcmp(uri, "/admin.cgi") == 0) ||
1185 (strncmp(uri, "/admin/", 7) == 0)) {
1186 admin_handle_request(client, uri);
1187 if (uri != passed_uri) free (uri);
1188 return;
1189 }
1190 auth_add_listener (uri, client);
1191 if (uri != passed_uri) free (uri);
1192 }
1193
_handle_shoutcast_compatible(client_queue_t * node)1194 static void _handle_shoutcast_compatible (client_queue_t *node)
1195 {
1196 char *http_compliant;
1197 int http_compliant_len = 0;
1198 http_parser_t *parser;
1199 ice_config_t *config = config_get_config ();
1200 char *shoutcast_mount;
1201 client_t *client = node->client;
1202
1203 if (node->shoutcast_mount)
1204 shoutcast_mount = node->shoutcast_mount;
1205 else
1206 shoutcast_mount = config->shoutcast_mount;
1207
1208 if (node->shoutcast == 1)
1209 {
1210 char *source_password, *ptr, *headers;
1211 mount_proxy *mountinfo = config_find_mount (config, shoutcast_mount, MOUNT_TYPE_NORMAL);
1212
1213 if (mountinfo && mountinfo->password)
1214 source_password = strdup (mountinfo->password);
1215 else
1216 {
1217 if (config->source_password)
1218 source_password = strdup (config->source_password);
1219 else
1220 source_password = NULL;
1221 }
1222 config_release_config();
1223
1224 /* Get rid of trailing \r\n or \n after password */
1225 ptr = strstr (client->refbuf->data, "\r\r\n");
1226 if (ptr)
1227 headers = ptr+3;
1228 else
1229 {
1230 ptr = strstr (client->refbuf->data, "\r\n");
1231 if (ptr)
1232 headers = ptr+2;
1233 else
1234 {
1235 ptr = strstr (client->refbuf->data, "\n");
1236 if (ptr)
1237 headers = ptr+1;
1238 }
1239 }
1240
1241 if (ptr == NULL)
1242 {
1243 client_destroy (client);
1244 free (source_password);
1245 free (node->shoutcast_mount);
1246 free (node);
1247 return;
1248 }
1249 *ptr = '\0';
1250
1251 if (source_password && strcmp (client->refbuf->data, source_password) == 0)
1252 {
1253 client->respcode = 200;
1254 /* send this non-blocking but if there is only a partial write
1255 * then leave to header timeout */
1256 client_send_bytes(client, "OK2\r\nicy-caps:11\r\n\r\n", 20); /* TODO: Replace Magic Number! */
1257 node->offset -= (headers - client->refbuf->data);
1258 memmove (client->refbuf->data, headers, node->offset+1);
1259 node->shoutcast = 2;
1260 /* we've checked the password, now send it back for reading headers */
1261 _add_request_queue (node);
1262 free (source_password);
1263 return;
1264 }
1265 else
1266 ICECAST_LOG_INFO("password does not match \"%s\"", client->refbuf->data);
1267 client_destroy (client);
1268 free (source_password);
1269 free (node->shoutcast_mount);
1270 free (node);
1271 return;
1272 }
1273 /* actually make a copy as we are dropping the config lock */
1274 shoutcast_mount = strdup (shoutcast_mount);
1275 config_release_config();
1276 /* Here we create a valid HTTP request based of the information
1277 that was passed in via the non-HTTP style protocol above. This
1278 means we can use some of our existing code to handle this case */
1279 http_compliant_len = 20 + strlen (shoutcast_mount) + node->offset;
1280 http_compliant = (char *)calloc(1, http_compliant_len);
1281 snprintf (http_compliant, http_compliant_len,
1282 "SOURCE %s HTTP/1.0\r\n%s", shoutcast_mount, client->refbuf->data);
1283 parser = httpp_create_parser();
1284 httpp_initialize(parser, NULL);
1285 if (httpp_parse (parser, http_compliant, strlen(http_compliant)))
1286 {
1287 /* we may have more than just headers, so prepare for it */
1288 if (node->stream_offset == node->offset)
1289 client->refbuf->len = 0;
1290 else
1291 {
1292 char *ptr = client->refbuf->data;
1293 client->refbuf->len = node->offset - node->stream_offset;
1294 memmove (ptr, ptr + node->stream_offset, client->refbuf->len);
1295 }
1296 client->parser = parser;
1297 source_startup (client, shoutcast_mount, SHOUTCAST_SOURCE_AUTH);
1298 }
1299 else {
1300 httpp_destroy (parser);
1301 client_destroy (client);
1302 }
1303 free (http_compliant);
1304 free (shoutcast_mount);
1305 free (node->shoutcast_mount);
1306 free (node);
1307 return;
1308 }
1309
1310
1311 /* Connection thread. Here we take clients off the connection queue and check
1312 * the contents provided. We set up the parser then hand off to the specific
1313 * request handler.
1314 */
_handle_connection(void)1315 static void _handle_connection(void)
1316 {
1317 http_parser_t *parser;
1318 const char *rawuri;
1319 client_queue_t *node;
1320
1321 while (1)
1322 {
1323 node = _get_connection();
1324 if (node)
1325 {
1326 client_t *client = node->client;
1327
1328 /* Check for special shoutcast compatability processing */
1329 if (node->shoutcast)
1330 {
1331 _handle_shoutcast_compatible (node);
1332 continue;
1333 }
1334
1335 /* process normal HTTP headers */
1336 parser = httpp_create_parser();
1337 httpp_initialize(parser, NULL);
1338 client->parser = parser;
1339 if (httpp_parse (parser, client->refbuf->data, node->offset))
1340 {
1341 char *uri;
1342
1343 /* we may have more than just headers, so prepare for it */
1344 if (node->stream_offset == node->offset)
1345 client->refbuf->len = 0;
1346 else
1347 {
1348 char *ptr = client->refbuf->data;
1349 client->refbuf->len = node->offset - node->stream_offset;
1350 memmove (ptr, ptr + node->stream_offset, client->refbuf->len);
1351 }
1352
1353 rawuri = httpp_getvar(parser, HTTPP_VAR_URI);
1354
1355 /* assign a port-based shoutcast mountpoint if required */
1356 if (node->shoutcast_mount && strcmp (rawuri, "/admin.cgi") == 0)
1357 httpp_set_query_param (client->parser, "mount", node->shoutcast_mount);
1358
1359 free (node->shoutcast_mount);
1360 free (node);
1361
1362 if (strcmp("ICE", httpp_getvar(parser, HTTPP_VAR_PROTOCOL)) &&
1363 strcmp("HTTP", httpp_getvar(parser, HTTPP_VAR_PROTOCOL))) {
1364 ICECAST_LOG_ERROR("Bad HTTP protocol detected");
1365 client_destroy (client);
1366 continue;
1367 }
1368
1369 uri = util_normalise_uri(rawuri);
1370
1371 if (uri == NULL)
1372 {
1373 client_destroy (client);
1374 continue;
1375 }
1376
1377 if (parser->req_type == httpp_req_source || parser->req_type == httpp_req_put) {
1378 _handle_source_request (client, uri);
1379 }
1380 else if (parser->req_type == httpp_req_stats) {
1381 _handle_stats_request (client, uri);
1382 }
1383 else if (parser->req_type == httpp_req_get) {
1384 _handle_get_request (client, uri);
1385 }
1386 else {
1387 ICECAST_LOG_ERROR("Wrong request type from client");
1388 client_send_400 (client, "unknown request");
1389 }
1390
1391 free(uri);
1392 }
1393 else
1394 {
1395 free (node);
1396 ICECAST_LOG_ERROR("HTTP request parsing failed");
1397 client_destroy (client);
1398 }
1399 continue;
1400 }
1401 break;
1402 }
1403 }
1404
1405
1406 /* called when listening thread is not checking for incoming connections */
connection_setup_sockets(ice_config_t * config)1407 int connection_setup_sockets (ice_config_t *config)
1408 {
1409 int count = 0;
1410 listener_t *listener, **prev;
1411
1412 free (banned_ip.filename);
1413 banned_ip.filename = NULL;
1414 free (allowed_ip.filename);
1415 allowed_ip.filename = NULL;
1416
1417 global_lock();
1418 if (global.serversock)
1419 {
1420 for (; count < global.server_sockets; count++)
1421 sock_close (global.serversock [count]);
1422 free (global.serversock);
1423 global.serversock = NULL;
1424 }
1425 if (config == NULL)
1426 {
1427 global_unlock();
1428 return 0;
1429 }
1430
1431 /* setup the banned/allowed IP filenames from the xml */
1432 if (config->banfile)
1433 banned_ip.filename = strdup (config->banfile);
1434
1435 if (config->allowfile)
1436 allowed_ip.filename = strdup (config->allowfile);
1437
1438 count = 0;
1439 global.serversock = calloc (config->listen_sock_count, sizeof (sock_t));
1440
1441 listener = config->listen_sock;
1442 prev = &config->listen_sock;
1443 while (listener)
1444 {
1445 int successful = 0;
1446
1447 do
1448 {
1449 sock_t sock = sock_get_server_socket (listener->port, listener->bind_address);
1450 if (sock == SOCK_ERROR)
1451 break;
1452 if (sock_listen (sock, ICECAST_LISTEN_QUEUE) == SOCK_ERROR)
1453 {
1454 sock_close (sock);
1455 break;
1456 }
1457 /* some win32 setups do not do TCP win scaling well, so allow an override */
1458 if (listener->so_sndbuf)
1459 sock_set_send_buffer (sock, listener->so_sndbuf);
1460 sock_set_blocking (sock, 0);
1461 successful = 1;
1462 global.serversock [count] = sock;
1463 count++;
1464 } while(0);
1465 if (successful == 0)
1466 {
1467 if (listener->bind_address)
1468 ICECAST_LOG_ERROR("Could not create listener socket on port %d bind %s",
1469 listener->port, listener->bind_address);
1470 else
1471 ICECAST_LOG_ERROR("Could not create listener socket on port %d", listener->port);
1472 /* remove failed connection */
1473 *prev = config_clear_listener (listener);
1474 listener = *prev;
1475 continue;
1476 }
1477 if (listener->bind_address)
1478 ICECAST_LOG_INFO("listener socket on port %d address %s", listener->port, listener->bind_address);
1479 else
1480 ICECAST_LOG_INFO("listener socket on port %d", listener->port);
1481 prev = &listener->next;
1482 listener = listener->next;
1483 }
1484 global.server_sockets = count;
1485 global_unlock();
1486
1487 if (count == 0)
1488 ICECAST_LOG_ERROR("No listening sockets established");
1489
1490 return count;
1491 }
1492
1493
connection_close(connection_t * con)1494 void connection_close(connection_t *con)
1495 {
1496 sock_close(con->sock);
1497 if (con->ip) free(con->ip);
1498 if (con->host) free(con->host);
1499 #ifdef HAVE_OPENSSL
1500 if (con->ssl) { SSL_shutdown (con->ssl); SSL_free (con->ssl); }
1501 #endif
1502 free(con);
1503 }
1504