예제 #1
0
파일: httpp.c 프로젝트: xaiki/IceCast
/** TODO: This is almost certainly buggy in some cases */
static void parse_query(http_parser_t *parser, char *query)
{
    int len;
    int i=0;
    char *key = query;
    char *val=NULL;

    if(!query || !*query)
        return;

    len = strlen(query);

    while(i<len) {
        switch(query[i]) {
        case '&':
            query[i] = 0;
            if(val && key)
                httpp_set_query_param(parser, key, val);
            key = query+i+1;
            break;
        case '=':
            query[i] = 0;
            val = query+i+1;
            break;
        }
        i++;
    }

    if(val && key) {
        httpp_set_query_param(parser, key, val);
    }
}
예제 #2
0
static int command_shoutcast_metadata (client_t *client, source_t *source)
{
    const char *action;
    const char *value;
    int same_ip = 1;

    if (COMMAND_REQUIRE(client, "mode", action) < 0)
    {
        thread_mutex_unlock (&source->lock);
        return client_send_400 (client, "missing arg, mode");
    }

    if ((source->flags & SOURCE_SHOUTCAST_COMPAT) == 0)
    {
        thread_mutex_unlock (&source->lock);
        ERROR0 ("illegal request on non-shoutcast compatible stream");
        return client_send_400 (client, "Not a shoutcast compatible stream");
    }

    if (strcmp (action, "updinfo") == 0)
    {
        DEBUG0("Got shoutcast metadata update request");
        if (COMMAND_REQUIRE (client, "song", value) < 0)
        {
            thread_mutex_unlock (&source->lock);
            return client_send_400 (client, "missing arg, song");
        }
        if (source->client && strcmp (client->connection.ip, source->client->connection.ip) != 0)
            if (connection_check_admin_pass (client->parser) == 0)
                same_ip = 0;

        if (same_ip && source->format && source->format->set_tag)
        {
            httpp_set_query_param (client->parser, "mount", client->server_conn->shoutcast_mount);
            source->format->set_tag (source->format, "title", value, NULL);
            source->format->set_tag (source->format, NULL, NULL, NULL);

            DEBUG2("Metadata on mountpoint %s changed to \"%s\"", source->mount, value);
            thread_mutex_unlock (&source->lock);
            return html_success(client, "Metadata update successful");
        }
        thread_mutex_unlock (&source->lock);
        return client_send_400 (client, "mountpoint will not accept URL updates");
    }
    if (strcmp (action, "viewxml") == 0)
    {
        xmlDocPtr doc;
        DEBUG0("Got shoutcast viewxml request");
        thread_mutex_unlock (&source->lock);
        doc = stats_get_xml (STATS_ALL, source->mount);
        return admin_send_response (doc, client, XSLT, "viewxml.xsl");
    }
    thread_mutex_unlock (&source->lock);
    return client_send_400 (client, "No such action");
}
예제 #3
0
파일: admin.c 프로젝트: krattai/AEBL
void admin_handle_request(client_t *client, const char *uri)
{
    const char *mount, *command_string;
    int command;

    DEBUG1("Admin request (%s)", uri);
    if (!((strcmp(uri, "/admin.cgi") == 0) ||
         (strncmp("/admin/", uri, 7) == 0))) {
        ERROR0("Internal error: admin request isn't");
        client_send_401(client);
        return;
    }

    if (strcmp(uri, "/admin.cgi") == 0) {
        command_string = uri + 1;
    }
    else {
        command_string = uri + 7;
    }

    DEBUG1("Got command (%s)", command_string);
    command = admin_get_command(command_string);

    if(command < 0) {
        ERROR1("Error parsing command string or unrecognised command: %s",
                command_string);
        client_send_400(client, "Unrecognised command");
        return;
    }

    if (command == COMMAND_SHOUTCAST_METADATA_UPDATE) {

        ice_config_t *config;
        const char *sc_mount;
        const char *pass = httpp_get_query_param (client->parser, "pass");
        listener_t *listener;

        if (pass == NULL)
        {
            client_send_400 (client, "missing pass parameter");
            return;
        }
        config = config_get_config ();
        sc_mount = config->shoutcast_mount;
        listener = config_get_listen_sock (config, client->con);
        if (listener && listener->shoutcast_mount)
            sc_mount = listener->shoutcast_mount;

        httpp_set_query_param (client->parser, "mount", sc_mount);
        httpp_setvar (client->parser, HTTPP_VAR_PROTOCOL, "ICY");
        httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, pass);
        config_release_config ();
    }

    mount = httpp_get_query_param(client->parser, "mount");

    if(mount != NULL) {
        source_t *source;

        /* this request does not require auth but can apply to files on webroot */
        if (command == COMMAND_BUILDM3U)
        {
            command_buildm3u (client, mount);
            return;
        }
        /* This is a mount request, handle it as such */
        if (!connection_check_admin_pass(client->parser))
        {
            if (!connection_check_source_pass(client->parser, mount))
            {
                INFO1("Bad or missing password on mount modification admin "
                        "request (command: %s)", command_string);
                client_send_401(client);
                return;
            }
        }
        
        avl_tree_rlock(global.source_tree);
        source = source_find_mount_raw(mount);

        if (source == NULL)
        {
            WARN2("Admin command %s on non-existent source %s", 
                    command_string, mount);
            avl_tree_unlock(global.source_tree);
            client_send_400(client, "Source does not exist");
        }
        else
        {
            if (source->running == 0 && source->on_demand == 0)
            {
                avl_tree_unlock (global.source_tree);
                INFO2("Received admin command %s on unavailable mount \"%s\"",
                        command_string, mount);
                client_send_400 (client, "Source is not available");
                return;
            }
            if (command == COMMAND_SHOUTCAST_METADATA_UPDATE &&
                    source->shoutcast_compat == 0)
            {
                avl_tree_unlock (global.source_tree);
                ERROR0 ("illegal change of metadata on non-shoutcast "
                        "compatible stream");
                client_send_400 (client, "illegal metadata call");
                return;
            }
            INFO2("Received admin command %s on mount \"%s\"", 
                    command_string, mount);
            admin_handle_mount_request(client, source, command);
            avl_tree_unlock(global.source_tree);
        }
    }
    else {

        if (command == COMMAND_PLAINTEXT_LISTSTREAM) {
        /* this request is used by a slave relay to retrieve
           mounts from the master, so handle this request
           validating against the relay password */
            if(!connection_check_relay_pass(client->parser)) {
                INFO1("Bad or missing password on admin command "
                      "request (command: %s)", command_string);
                client_send_401(client);
                return;
            }
        }
        else {
            if(!connection_check_admin_pass(client->parser)) {
                INFO1("Bad or missing password on admin command "
                      "request (command: %s)", command_string);
                client_send_401(client);
                return;
            }
        }
        
        admin_handle_general_request(client, command);
    }
}
예제 #4
0
/* Connection thread. Here we take clients off the connection queue and check
 * the contents provided. We set up the parser then hand off to the specific
 * request handler.
 */
static void _handle_connection(void)
{
    http_parser_t *parser;
    const char *rawuri;
    client_queue_t *node;

    while (1)
    {
        node = _get_connection();
        if (node)
        {
            client_t *client = node->client;

            /* Check for special shoutcast compatability processing */
            if (node->shoutcast)
            {
                _handle_shoutcast_compatible (node);
                continue;
            }

            /* process normal HTTP headers */
            parser = httpp_create_parser();
            httpp_initialize(parser, NULL);
            client->parser = parser;
            if (httpp_parse (parser, client->refbuf->data, node->offset))
            {
                char *uri;

                /* we may have more than just headers, so prepare for it */
                if (node->stream_offset == node->offset)
                    client->refbuf->len = 0;
                else
                {
                    char *ptr = client->refbuf->data;
                    client->refbuf->len = node->offset - node->stream_offset;
                    memmove (ptr, ptr + node->stream_offset, client->refbuf->len);
                }

                rawuri = httpp_getvar(parser, HTTPP_VAR_URI);

                /* assign a port-based shoutcast mountpoint if required */
                if (node->shoutcast_mount && strcmp (rawuri, "/admin.cgi") == 0)
                    httpp_set_query_param (client->parser, "mount", node->shoutcast_mount);

                free (node->shoutcast_mount);
                free (node);

                if (strcmp("ICE",  httpp_getvar(parser, HTTPP_VAR_PROTOCOL)) &&
                    strcmp("HTTP", httpp_getvar(parser, HTTPP_VAR_PROTOCOL))) {
                    ERROR0("Bad HTTP protocol detected");
                    client_destroy (client);
                    continue;
                }

                uri = util_normalise_uri(rawuri);

                if (uri == NULL)
                {
                    client_destroy (client);
                    continue;
                }

                if (parser->req_type == httpp_req_source || parser->req_type == httpp_req_put) {
                    _handle_source_request (client, uri);
                }
                else if (parser->req_type == httpp_req_stats) {
                    _handle_stats_request (client, uri);
                }
                else if (parser->req_type == httpp_req_get) {
                    _handle_get_request (client, uri);
                }
                else {
                    ERROR0("Wrong request type from client");
                    client_send_400 (client, "unknown request");
                }

                free(uri);
            } 
            else
            {
                free (node);
                ERROR0("HTTP request parsing failed");
                client_destroy (client);
            }
            continue;
        }
        break;
    }
}
예제 #5
0
int admin_handle_request (client_t *client, const char *uri)
{
    const char *mount = httpp_get_query_param(client->parser, "mount");

    if (strcmp (uri, "/admin.cgi") == 0)
    {
        const char *pass = httpp_get_query_param (client->parser, "pass");
        if (pass == NULL)
            return client_send_400 (client, "missing pass parameter");
        uri++;
        if (mount == NULL)
        {
            if (client->server_conn && client->server_conn->shoutcast_mount)
                httpp_set_query_param (client->parser, "mount",
                        client->server_conn->shoutcast_mount);
            mount = httpp_get_query_param (client->parser, "mount");
        }
        httpp_setvar (client->parser, HTTPP_VAR_PROTOCOL, "ICY");
        httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, pass);
        client->username = strdup ("source");
        client->password = strdup (pass);
    }
    else
        uri += 7;

    if (connection_check_admin_pass (client->parser))
        client->flags |= CLIENT_AUTHENTICATED;
    else
    {
        /* special case for slaves requesting a streamlist for authenticated relaying */
        if (strcmp (uri, "streams") == 0 || strcmp (uri, "streamlist.txt") == 0)
        {
            if (connection_check_relay_pass (client->parser))
                client->flags |= CLIENT_AUTHENTICATED;
        }
    }

    if (mount)
    {
        /* no auth/stream required for this */
        if (strcmp (uri, "buildm3u") == 0)
            return command_buildm3u (client, mount);
        if (strcmp (uri, "showimage") == 0)
            return command_show_image (client, mount);

        /* This is a mount request, but admin user is allowed */
        if ((client->flags & CLIENT_AUTHENTICATED) == 0)
        {
            switch (auth_check_source (client, mount))
            {
                case 0:
                    break;
                default:
                    INFO1("Bad or missing password on mount modification "
                            "admin request (%s)", uri);
                    return client_send_401 (client, NULL);
                    /* fall through */
                case 1:
                    return 0;
            }
        }
        if (strcmp (uri, "streams") == 0)
            return auth_add_listener ("/admin/streams", client);
        return admin_mount_request (client, uri);
    }

    return admin_handle_general_request (client, uri);
}