[mpd] password command

This commit is contained in:
Wolfgang Scherer 2017-11-10 09:55:44 +01:00
parent c908ceff4e
commit c48b819170

View File

@ -143,6 +143,11 @@ static const char * const ffmpeg_mime_types[] = { "application/flv", "applicatio
NULL NULL
}; };
/* Provide for connection specfic authentication. */
struct mpd_cmd_ctx {
int authenticated;
};
struct output struct output
{ {
unsigned short shortid; unsigned short shortid;
@ -3197,6 +3202,38 @@ mpd_command_rescan(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
} }
*/ */
static int
mpd_command_password(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
char *required_password;
char *supplied_password = "";
int unrequired;
if (argc > 1)
{
supplied_password = argv[1];
}
required_password = cfg_getstr(cfg_getsec(cfg, "library"), "password");
unrequired = !required_password || required_password[0] == '\0';
if (unrequired || strcmp(supplied_password, required_password) == 0)
{
DPRINTF(E_DBG, L_MPD,
"Authentication succeeded with supplied password: %s%s\n",
supplied_password,
unrequired ? " although no password is required" : "");
return 0;
}
DPRINTF(E_LOG, L_MPD,
"Authentication failed with supplied password: %s"
" for required password: %s\n",
supplied_password, required_password);
*errmsg = safe_asprintf("Wrong password. Authentication failed.");
return ACK_ERROR_PASSWORD;
}
/* /*
* Callback function for the 'player_speaker_enumerate' function. * Callback function for the 'player_speaker_enumerate' function.
* Adds a new struct output to the given struct outputs in *arg for the given speaker (id, name, etc.). * Adds a new struct output to the given struct outputs in *arg for the given speaker (id, name, etc.).
@ -4213,11 +4250,11 @@ static struct mpd_command mpd_handlers[] =
.mpdcommand = "kill", .mpdcommand = "kill",
.handler = mpd_command_kill .handler = mpd_command_kill
}, },
*/
{ {
.mpdcommand = "password", .mpdcommand = "password",
.handler = mpd_command_password .handler = mpd_command_password
}, },
*/
{ {
.mpdcommand = "ping", .mpdcommand = "ping",
.handler = mpd_command_ignore .handler = mpd_command_ignore
@ -4357,7 +4394,7 @@ mpd_command_commands(struct evbuffer *evbuf, int argc, char **argv, char **errms
* (see mpd_input_filter function). * (see mpd_input_filter function).
* *
* @param bev the buffer event * @param bev the buffer event
* @param ctx (not used) * @param ctx used for authentication
*/ */
static void static void
mpd_read_cb(struct bufferevent *bev, void *ctx) mpd_read_cb(struct bufferevent *bev, void *ctx)
@ -4374,6 +4411,7 @@ mpd_read_cb(struct bufferevent *bev, void *ctx)
int close_cmd; int close_cmd;
char *argv[COMMAND_ARGV_MAX]; char *argv[COMMAND_ARGV_MAX];
int argc; int argc;
struct mpd_cmd_ctx *cmd_ctx = (struct mpd_cmd_ctx *)ctx;
/* Get the input evbuffer, contains the command sequence received from the client */ /* Get the input evbuffer, contains the command sequence received from the client */
input = bufferevent_get_input(bev); input = bufferevent_get_input(bev);
@ -4444,6 +4482,16 @@ mpd_read_cb(struct bufferevent *bev, void *ctx)
errmsg = safe_asprintf("Unsupported command '%s'", argv[0]); errmsg = safe_asprintf("Unsupported command '%s'", argv[0]);
ret = ACK_ERROR_UNKNOWN; ret = ACK_ERROR_UNKNOWN;
} }
else if (strcmp(command->mpdcommand, "password") == 0)
{
ret = command->handler(output, argc, argv, &errmsg);
cmd_ctx->authenticated = ret == 0;
}
else if (!cmd_ctx->authenticated)
{
errmsg = safe_asprintf("Not authenticated");
ret = ACK_ERROR_PERMISSION;
}
else else
ret = command->handler(output, argc, argv, &errmsg); ret = command->handler(output, argc, argv, &errmsg);
@ -4583,9 +4631,19 @@ mpd_accept_conn_cb(struct evconnlistener *listener,
*/ */
struct event_base *base = evconnlistener_get_base(listener); struct event_base *base = evconnlistener_get_base(listener);
struct bufferevent *bev = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE); struct bufferevent *bev = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);
struct mpd_cmd_ctx *cmd_ctx = (struct mpd_cmd_ctx *)malloc(sizeof(struct mpd_cmd_ctx));
bev = bufferevent_filter_new(bev, mpd_input_filter, NULL, BEV_OPT_CLOSE_ON_FREE, NULL, NULL); if (!cmd_ctx)
bufferevent_setcb(bev, mpd_read_cb, NULL, mpd_event_cb, bev); {
DPRINTF(E_LOG, L_MPD, "Out of memory for command context\n");
bufferevent_free(bev);
return;
}
cmd_ctx->authenticated = !cfg_getstr(cfg_getsec(cfg, "library"), "password");
bev = bufferevent_filter_new(bev, mpd_input_filter, NULL, BEV_OPT_CLOSE_ON_FREE, free, cmd_ctx);
bufferevent_setcb(bev, mpd_read_cb, NULL, mpd_event_cb, cmd_ctx);
bufferevent_enable(bev, EV_READ | EV_WRITE); bufferevent_enable(bev, EV_READ | EV_WRITE);
/* /*