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