Added authentication for webservice connection.

This commit is contained in:
SuperBFG7 2021-08-23 17:23:48 +02:00
parent f5080c8419
commit 3c70301789
4 changed files with 110 additions and 11 deletions

View File

@ -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: {

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);