mirror of
https://github.com/SuperBFG7/ympd
synced 2024-12-22 17:10:26 +00:00
Added authentication for webservice connection.
This commit is contained in:
parent
f5080c8419
commit
3c70301789
@ -30,6 +30,7 @@ var MAX_ELEMENTS_PER_PAGE = 512;
|
||||
var isTouch = Modernizr.touch ? 1 : 0;
|
||||
var filter = '';
|
||||
var scrobbler = '';
|
||||
var wss_auth_token = '';
|
||||
|
||||
var app = $.sammy(function () {
|
||||
function runBrowse() {
|
||||
@ -38,7 +39,8 @@ var app = $.sammy(function () {
|
||||
$('#breadcrump').addClass('hide');
|
||||
$('#filter').addClass('hide');
|
||||
$('#salamisandwich').removeClass('hide').find('tr:gt(0)').remove();
|
||||
socket.send('MPD_API_GET_QUEUE,' + pagination);
|
||||
if (wss_auth_token !== '')
|
||||
socket.send('MPD_API_GET_QUEUE,' + pagination);
|
||||
|
||||
$('#panel-heading').text('Queue');
|
||||
$('#panel-heading-info').empty();
|
||||
@ -249,6 +251,25 @@ $(document).ready(function () {
|
||||
);
|
||||
});
|
||||
|
||||
function webSocketAuthenticate() {
|
||||
var u = document.URL.split('#');
|
||||
var separator;
|
||||
|
||||
if (/\/$/.test(u[0])) {
|
||||
separator = '';
|
||||
} else {
|
||||
separator = '/';
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: u[0] + separator + 'wss-auth',
|
||||
success: function (data) {
|
||||
wss_auth_token = data;
|
||||
socket.send('MPD_API_AUTHORIZE,' + wss_auth_token);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function webSocketConnect() {
|
||||
if (typeof MozWebSocket != 'undefined') {
|
||||
socket = new MozWebSocket(get_appropriate_ws_url());
|
||||
@ -267,9 +288,8 @@ function webSocketConnect() {
|
||||
.show();
|
||||
|
||||
app.run();
|
||||
/* emit initial request for output names */
|
||||
socket.send('MPD_API_GET_OUTPUTS');
|
||||
socket.send('MPD_API_GET_CHANNELS');
|
||||
|
||||
if (wss_auth_token === '') webSocketAuthenticate();
|
||||
};
|
||||
|
||||
socket.onmessage = function got_packet(msg) {
|
||||
@ -904,6 +924,15 @@ function webSocketConnect() {
|
||||
$('#mpd_password_set').removeClass('hide');
|
||||
break;
|
||||
|
||||
case 'authorized':
|
||||
if (obj.data === 'true') {
|
||||
/* emit initial request for output names */
|
||||
socket.send('MPD_API_GET_OUTPUTS');
|
||||
socket.send('MPD_API_GET_CHANNELS');
|
||||
} else webSocketAuthenticate();
|
||||
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
$('.top-right')
|
||||
.notify({
|
||||
@ -918,6 +947,7 @@ function webSocketConnect() {
|
||||
|
||||
socket.onclose = function () {
|
||||
console.log('disconnected');
|
||||
wss_auth_token = '';
|
||||
$('.top-right')
|
||||
.notify({
|
||||
message: {
|
||||
|
@ -18,8 +18,11 @@
|
||||
|
||||
#include "http_server.h"
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mpd_client.h"
|
||||
|
||||
int callback_http(struct mg_connection *c) {
|
||||
const struct embedded_file *req_file;
|
||||
|
||||
@ -35,6 +38,22 @@ int callback_http(struct mg_connection *c) {
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
if (!strcmp(c->uri, "/wss-auth")) {
|
||||
unsigned char salt[WSS_AUTH_TOKEN_SIZE + 1];
|
||||
|
||||
RAND_bytes(salt, WSS_AUTH_TOKEN_SIZE);
|
||||
for (int i = 0; i <= WSS_AUTH_TOKEN_SIZE; i++) salt[i] = salt[i] % 26 + 65;
|
||||
salt[WSS_AUTH_TOKEN_SIZE] = 0;
|
||||
if (mpd.wss_auth_token)
|
||||
free(mpd.wss_auth_token);
|
||||
mpd.wss_auth_token = strdup((char *)salt);
|
||||
|
||||
mg_send_header(c, "Content-Type", "text/plain");
|
||||
mg_send_data(c, salt, WSS_AUTH_TOKEN_SIZE);
|
||||
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
mg_send_status(c, 404);
|
||||
mg_printf_data(c, "Not Found");
|
||||
return MG_TRUE;
|
||||
|
@ -58,6 +58,18 @@ int callback_mpd(struct mg_connection *c) {
|
||||
int int_buf;
|
||||
char *p_charbuf = NULL, *token;
|
||||
|
||||
if (!c->connection_param)
|
||||
c->connection_param = calloc(1, sizeof(struct t_mpd_client_session));
|
||||
|
||||
struct t_mpd_client_session *s = (struct t_mpd_client_session *)c->connection_param;
|
||||
|
||||
if (!s->authorized && (cmd_id != MPD_API_AUTHORIZE)) {
|
||||
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\",\"data\":\"not authorized\"}");
|
||||
mg_websocket_write(c, 1, mpd.buf, n);
|
||||
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
if (cmd_id == -1)
|
||||
return MG_TRUE;
|
||||
|
||||
@ -66,6 +78,25 @@ int callback_mpd(struct mg_connection *c) {
|
||||
return MG_TRUE;
|
||||
|
||||
switch (cmd_id) {
|
||||
case MPD_API_AUTHORIZE:
|
||||
p_charbuf = strdup(c->content);
|
||||
if (strcmp(strtok(p_charbuf, ","), "MPD_API_AUTHORIZE"))
|
||||
goto out_authorize;
|
||||
|
||||
if ((token = strtok(NULL, ",")) == NULL)
|
||||
goto out_authorize;
|
||||
|
||||
free(p_charbuf);
|
||||
p_charbuf = strdup(c->content);
|
||||
s->auth_token = strdup(get_arg1(p_charbuf));
|
||||
if (!strcmp(mpd.wss_auth_token, s->auth_token))
|
||||
s->authorized = 1;
|
||||
|
||||
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"authorized\", \"data\":\"%s\"}",
|
||||
s->authorized ? "true" : "false");
|
||||
out_authorize:
|
||||
free(p_charbuf);
|
||||
break;
|
||||
case MPD_API_UPDATE_DB:
|
||||
mpd_run_update(mpd.conn, NULL);
|
||||
break;
|
||||
@ -332,8 +363,13 @@ int callback_mpd(struct mg_connection *c) {
|
||||
|
||||
int mpd_close_handler(struct mg_connection *c) {
|
||||
/* Cleanup session data */
|
||||
if (c->connection_param)
|
||||
if (c->connection_param) {
|
||||
struct t_mpd_client_session *s = (struct t_mpd_client_session *)c->connection_param;
|
||||
if (s->auth_token)
|
||||
free(s->auth_token);
|
||||
free(c->connection_param);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -343,6 +379,14 @@ static int mpd_notify_callback(struct mg_connection *c, enum mg_event ev) {
|
||||
if (!c->is_websocket)
|
||||
return MG_TRUE;
|
||||
|
||||
if (!c->connection_param)
|
||||
return MG_TRUE;
|
||||
|
||||
struct t_mpd_client_session *s = (struct t_mpd_client_session *)c->connection_param;
|
||||
|
||||
if (!s->authorized)
|
||||
return MG_TRUE;
|
||||
|
||||
if (c->callback_param) {
|
||||
/* error message? */
|
||||
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\",\"data\":\"%s\"}",
|
||||
@ -352,11 +396,6 @@ static int mpd_notify_callback(struct mg_connection *c, enum mg_event ev) {
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
if (!c->connection_param)
|
||||
c->connection_param = calloc(1, sizeof(struct t_mpd_client_session));
|
||||
|
||||
struct t_mpd_client_session *s = (struct t_mpd_client_session *)c->connection_param;
|
||||
|
||||
if (mpd.conn_state != MPD_CONNECTED) {
|
||||
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"disconnected\"}");
|
||||
mg_websocket_write(c, 1, mpd.buf, n);
|
||||
@ -444,6 +483,11 @@ void mpd_poll(struct mg_server *s) {
|
||||
c->callback_param = NULL;
|
||||
mpd_notify_callback(c, MG_POLL);
|
||||
}
|
||||
mpd.buf_size = mpd_put_channels(mpd.buf);
|
||||
for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) {
|
||||
c->callback_param = NULL;
|
||||
mpd_notify_callback(c, MG_POLL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@
|
||||
#define MAX_SIZE 1024 * 100
|
||||
#define MAX_ELEMENTS_PER_PAGE 512
|
||||
|
||||
#define WSS_AUTH_TOKEN_SIZE 50
|
||||
|
||||
#define GEN_ENUM(X) X,
|
||||
#define GEN_STR(X) #X,
|
||||
#define MPD_CMDS(X) \
|
||||
@ -68,7 +70,8 @@
|
||||
X(MPD_API_TOGGLE_CONSUME) \
|
||||
X(MPD_API_TOGGLE_SINGLE) \
|
||||
X(MPD_API_TOGGLE_CROSSFADE) \
|
||||
X(MPD_API_TOGGLE_REPEAT)
|
||||
X(MPD_API_TOGGLE_REPEAT) \
|
||||
X(MPD_API_AUTHORIZE)
|
||||
|
||||
enum mpd_cmd_ids { MPD_CMDS(GEN_ENUM) };
|
||||
|
||||
@ -86,6 +89,7 @@ struct t_mpd {
|
||||
char host[128];
|
||||
char *password;
|
||||
char *gpass;
|
||||
char *wss_auth_token;
|
||||
|
||||
struct mpd_connection *conn;
|
||||
enum mpd_conn_states conn_state;
|
||||
@ -103,6 +107,8 @@ extern struct t_mpd mpd;
|
||||
struct t_mpd_client_session {
|
||||
int song_id;
|
||||
unsigned queue_version;
|
||||
int authorized;
|
||||
char *auth_token;
|
||||
};
|
||||
|
||||
void mpd_poll(struct mg_server *s);
|
||||
|
Loading…
Reference in New Issue
Block a user