From 0cc0e54e0c47c10f7b0aceb5e8ad752c797109d4 Mon Sep 17 00:00:00 2001 From: jcorporation Date: Tue, 27 Nov 2018 17:22:45 +0000 Subject: [PATCH] Fix: copyright notices Fix: add user input validation in backend --- CMakeLists.txt | 1 + src/list.c | 20 ++++++++++++++++++ src/list.h | 20 ++++++++++++++++++ src/mpd_client.c | 29 ++++++++++++++++++------- src/validate.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ src/validate.h | 26 +++++++++++++++++++++++ 6 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 src/validate.c create mode 100644 src/validate.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8416f7d..208661b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ set(SOURCES src/mympd.c src/mpd_client.c src/list.c + src/validate.c dist/src/mongoose/mongoose.c dist/src/frozen/frozen.c dist/src/inih/ini.c diff --git a/src/list.c b/src/list.c index e68f707..f012012 100644 --- a/src/list.c +++ b/src/list.c @@ -1,3 +1,23 @@ +/* myMPD + (c) 2018 Juergen Mang + This project's homepage is: https://github.com/jcorporation/mympd + + This linked list implementation is based on: https://github.com/joshkunz/ashuffle + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + #include #include #include diff --git a/src/list.h b/src/list.h index 659be7d..e4c9ecf 100644 --- a/src/list.h +++ b/src/list.h @@ -1,3 +1,23 @@ +/* myMPD + (c) 2018 Juergen Mang + This project's homepage is: https://github.com/jcorporation/mympd + + This linked list implementation is based on: https://github.com/joshkunz/ashuffle + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + struct node { char *data; long value; diff --git a/src/mpd_client.c b/src/mpd_client.c index 654f41b..6a82bba 100644 --- a/src/mpd_client.c +++ b/src/mpd_client.c @@ -33,6 +33,7 @@ #include #include "mpd_client.h" +#include "validate.h" #include "config.h" #include "../dist/src/frozen/frozen.h" @@ -119,31 +120,31 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { int len = strlen(cols); if (len > 1) cols[len - 2] = '\0'; - if (strcmp(p_charbuf1,"colsQueueCurrent")==0) { + if (strcmp(p_charbuf1, "colsQueueCurrent")==0) { free(mympd_state.colsQueueCurrent); mympd_state.colsQueueCurrent = strdup(cols); } - else if (strcmp(p_charbuf1,"colsSearch")==0) { + else if (strcmp(p_charbuf1, "colsSearch")==0) { free(mympd_state.colsSearch); mympd_state.colsSearch = strdup(cols); } - else if (strcmp(p_charbuf1,"colsBrowseDatabase")==0) { + else if (strcmp(p_charbuf1, "colsBrowseDatabase")==0) { free(mympd_state.colsBrowseDatabase); mympd_state.colsBrowseDatabase = strdup(cols); } - else if (strcmp(p_charbuf1,"colsBrowsePlaylistsDetail")==0) { + else if (strcmp(p_charbuf1, "colsBrowsePlaylistsDetail")==0) { free(mympd_state.colsBrowsePlaylistsDetail); mympd_state.colsBrowsePlaylistsDetail = strdup(cols); } - else if (strcmp(p_charbuf1,"colsBrowseFilesystem")==0) { + else if (strcmp(p_charbuf1, "colsBrowseFilesystem")==0) { free(mympd_state.colsBrowseFilesystem); mympd_state.colsBrowseFilesystem = strdup(cols); } - else if (strcmp(p_charbuf1,"colsPlayback")==0) { + else if (strcmp(p_charbuf1, "colsPlayback")==0) { free(mympd_state.colsPlayback); mympd_state.colsPlayback = strdup(cols); } - else if (strcmp(p_charbuf1,"colsQueueLastPlayed")==0) { + else if (strcmp(p_charbuf1, "colsQueueLastPlayed")==0) { free(mympd_state.colsQueueLastPlayed); mympd_state.colsQueueLastPlayed = strdup(cols); } @@ -449,6 +450,8 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { //rename smart playlist char old_pl_file[400]; char new_pl_file[400]; + sanitize_string(p_charbuf1); + sanitize_string(p_charbuf2); snprintf(old_pl_file, 400, "%s/smartpls/%s", config.varlibdir, p_charbuf1); snprintf(new_pl_file, 400, "%s/smartpls/%s", config.varlibdir, p_charbuf2); if (access(old_pl_file, F_OK ) != -1) { @@ -465,7 +468,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"Renamed playlist %s to %s\"}", p_charbuf1, p_charbuf2); } free(p_charbuf1); - free(p_charbuf2); + free(p_charbuf2); } break; case MPD_API_PLAYLIST_LIST: @@ -623,6 +626,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { if (je == 1) { //remove smart playlist char pl_file[400]; + sanitize_string(p_charbuf1); snprintf(pl_file, 400, "%s/smartpls/%s", config.varlibdir, p_charbuf1); if (access(pl_file, F_OK ) != -1 ) unlink(pl_file); @@ -1353,6 +1357,7 @@ bool mympd_state_get(char *name, char *value) { size_t n = 0; ssize_t read; + sanitize_string(name); snprintf(cfgfile, 400, "%s/state/%s", config.varlibdir, name); FILE *fp = fopen(cfgfile, "r"); if (fp == NULL) { @@ -1374,6 +1379,8 @@ bool mympd_state_get(char *name, char *value) { bool mympd_state_set(const char *name, const char *value) { char tmpfile[400]; char cfgfile[400]; + + sanitize_string(name); snprintf(cfgfile, 400, "%s/state/%s", config.varlibdir, name); snprintf(tmpfile, 400, "%s/tmp/%s", config.varlibdir, name); @@ -1395,6 +1402,7 @@ int mympd_syscmd(char *buffer, char *cmd, int order) { size_t n = 0; ssize_t read; + sanitize_string(cmd); snprintf(filename, 400, "%s/syscmds/%d%s", config.etcdir, order, cmd); FILE *fp = fopen(filename, "r"); if (fp == NULL) { @@ -1878,6 +1886,7 @@ int mympd_put_browse(char *buffer, char *path, unsigned int offset, char *filter ) { if (entities_returned++) len += json_printf(&out, ","); + sanitize_string(plName); snprintf(smartpls_file, 400, "%s/smartpls/%s", config.varlibdir, plName); if (access(smartpls_file, F_OK ) != -1) smartpls = true; @@ -2050,6 +2059,7 @@ int mympd_put_playlists(char *buffer, unsigned int offset, char *filter) { if (entities_returned++) len += json_printf(&out, ", "); snprintf(smartpls_file, 400, "%s/smartpls/%s", config.varlibdir, plpath); + sanitize_string(plpath); if (access(smartpls_file, F_OK ) != -1) smartpls = true; else @@ -2116,6 +2126,7 @@ int mympd_put_playlist_list(char *buffer, char *uri, unsigned int offset, char * } mpd_entity_free(entity); } + sanitize_string(uri); snprintf(smartpls_file, 400, "%s/smartpls/%s", config.varlibdir, uri); if (access(smartpls_file, F_OK ) != -1) smartpls = true; @@ -2392,6 +2403,7 @@ int mympd_smartpls_put(char *buffer, char *playlist) { int len = 0; struct json_out out = JSON_OUT_BUF(buffer, MAX_SIZE); + sanitize_string(playlist); snprintf(pl_file, 400, "%s/smartpls/%s", config.varlibdir, playlist); char *content = json_fread(pl_file); je = json_scanf(content, strlen(content), "{type: %Q }", &smartpltype); @@ -2436,6 +2448,7 @@ int mympd_smartpls_put(char *buffer, char *playlist) { int mympd_smartpls_save(char *smartpltype, char *playlist, char *tag, char *searchstr, int maxentries, int timerange) { char tmp_file[400]; char pl_file[400]; + sanitize_string(playlist); snprintf(tmp_file, 400, "%s/tmp/%s", config.varlibdir, playlist); snprintf(pl_file, 400, "%s/smartpls/%s", config.varlibdir, playlist); if (strcmp(smartpltype, "sticker") == 0) { diff --git a/src/validate.c b/src/validate.c new file mode 100644 index 0000000..92b72bf --- /dev/null +++ b/src/validate.c @@ -0,0 +1,55 @@ +/* myMPD + (c) 2018 Juergen Mang + This project's homepage is: https://github.com/jcorporation/mympd + + myMPD ist fork of: + + ympd + (c) 2013-2014 Andrew Karpow + This project's homepage is: http://www.ympd.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include +#include "validate.h" + +void sanitize_string(const char *data) { + static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "1234567890_-. "; + char *cp = data; + const char *end = data + strlen(data); + for (cp += strspn(cp, ok_chars); cp != end; cp += strspn(cp, ok_chars)) + *cp = '_'; +} + +int validate_path(char *path, const char *basepath) { + char *rpath = NULL; + char *ptr; + ptr = realpath(path, rpath); + if (ptr == NULL) + return 1; + if (strncmp(basepath, ptr, strlen(basepath)) == 0) { + free(rpath); + return 0; + } + else { + free(rpath); + return 1; + } +} diff --git a/src/validate.h b/src/validate.h new file mode 100644 index 0000000..1a14d99 --- /dev/null +++ b/src/validate.h @@ -0,0 +1,26 @@ +/* myMPD + (c) 2018 Juergen Mang + This project's homepage is: https://github.com/jcorporation/mympd + + myMPD ist fork of: + + ympd + (c) 2013-2014 Andrew Karpow + This project's homepage is: http://www.ympd.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +void sanitize_string(const char *data); +int validate_path(char *path, const char *basepath);