Skip to content

Commit

Permalink
Add shoutcast user auth and mount designation
Browse files Browse the repository at this point in the history
  • Loading branch information
TheTaLlesT committed Nov 9, 2018
1 parent 2c794a1 commit 4a5eefe
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 15 deletions.
29 changes: 24 additions & 5 deletions src/admin.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,17 +326,36 @@ int admin_handle_request (client_t *client, const char *uri)
if (pass == NULL)
return client_send_400 (client, "missing pass parameter");
uri++;

char *pass_copy = strdup(pass);
char *login_end = pass_copy + strlen(pass_copy);
char *login_pass = strchr(pass_copy, ':');
char *login_mount = strchr(pass_copy, '@');

if(login_pass) *login_pass++ = '\0';
if(login_mount) *login_mount++ = '\0';

client->username = strdup(login_pass && (!login_mount || (login_mount && login_mount > pass_copy +1)) ? pass_copy : "source");
client->password = strdup(login_pass && login_pass < login_end ? login_pass : pass_copy);

if (mount == NULL)
{
if (client->server_conn && client->server_conn->shoutcast_mount)
httpp_set_query_param (client->parser, "mount",
if (login_mount && login_mount < login_end)
{
if(*login_mount != '/')
*--login_mount = '/';
httpp_set_query_param (client->parser, "mount", login_mount);
}
else 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");
}
free(pass_copy);
httpp_setvar (client->parser, HTTPP_VAR_PROTOCOL, "ICY");
httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, pass);
client->username = strdup ("source");
client->password = strdup (pass);
httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, client->password);
}
else
uri += 7;
Expand Down
2 changes: 1 addition & 1 deletion src/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ int auth_check_source (client_t *client, const char *mount)
ret = -1;
if (mountinfo->password)
pass = mountinfo->password;
if (mountinfo->username && client->server_conn->shoutcast_compat == 0)
if (mountinfo->username)
user = mountinfo->username;
}
if (connection_check_pass (client->parser, user, pass) > 0)
Expand Down
38 changes: 32 additions & 6 deletions src/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1153,14 +1153,40 @@ static int shoutcast_source_client (client_t *client)
return 0;

refbuf->data [len] = '\0';
snprintf (header, sizeof(header), "source:%s", refbuf->data);
esc_header = util_base64_encode (header);

len += 1 + strspn (refbuf->data+len+1, "\r\n");

char *login_end = refbuf->data + strlen(refbuf->data);
char *login_pass = strchr(refbuf->data, ':');
char *login_mount = strchr(refbuf->data, '@');

if(login_pass) *login_pass++ = '\0';
if(login_mount) *login_mount++ = '\0';

snprintf (header, sizeof(header), "%s:%s",
login_pass && (!login_mount || (login_mount && login_mount > refbuf->data +1)) ? refbuf->data : "source",
login_pass && login_pass < login_end ? login_pass : refbuf->data
);

if(login_mount && login_mount < login_end)
{
if(*login_mount != '/')
*--login_mount = '/';

// Reject mounts with "unsafe" characters. Behavior is unpredictable/undesirable
if (!util_url_safe(login_mount +1)) {
INFO1("rejected mount '%s'", login_mount);
break;
}
} else {
login_mount = client->server_conn->shoutcast_mount;
}

r = refbuf_new (PER_CLIENT_REFBUF_SIZE);
esc_header = util_base64_encode (header);
snprintf (r->data, PER_CLIENT_REFBUF_SIZE,
"SOURCE %s HTTP/1.0\r\n" "Authorization: Basic %s\r\n%s",
client->server_conn->shoutcast_mount, esc_header, refbuf->data+len);
"SOURCE %s HTTP/1.0\r\n" "Authorization: Basic %s\r\n%s",
login_mount, esc_header, refbuf->data+len);

r->len = strlen (r->data);
free (esc_header);
client->respcode = 200;
Expand All @@ -1171,7 +1197,7 @@ static int shoutcast_source_client (client_t *client)
client->refbuf = resp;
refbuf_release (refbuf);
client->shared_data = NULL;
INFO1 ("emulation on %s", client->server_conn->shoutcast_mount);
INFO1 ("emulation on %s", login_mount);
}
format_generic_write_to_client (client);
if (client->pos == client->refbuf->len)
Expand Down
22 changes: 19 additions & 3 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,12 @@ static char hexchars[16] = {
static char safechars[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Expand All @@ -297,6 +297,22 @@ static char safechars[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

_Bool util_url_safe (const char *src)
{
int i, len;
unsigned char *source;

len = strlen(src);
source = (unsigned char *)src;

for(i=0; i < len; i++) {
if(!safechars[source[i]]) {
return 0;
}
}
return 1;
}

char *util_url_escape (const char *src)
{
int len, i, j=0;
Expand Down
1 change: 1 addition & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ char *util_base64_encode(const char *data);
char *util_base64_decode(const char *input);
char *util_bin_to_hex(unsigned char *data, int len);

_Bool util_url_safe (const char *src);
char *util_url_unescape(const char *src);
char *util_url_escape(const char *src);

Expand Down

0 comments on commit 4a5eefe

Please sign in to comment.