Skip to content

Commit

Permalink
Services API: Channel/UpdateVideoSource hardening
Browse files Browse the repository at this point in the history
Require a SourceId parameter, add test for valid SourceId,
fix ConfigPath='' case (which must be set to NULL in the
DB) and only update parameters that were passed.
  • Loading branch information
Bill Meek committed Nov 28, 2019
1 parent cb9e307 commit 260a926
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 7 deletions.
23 changes: 21 additions & 2 deletions mythtv/libs/libmythtv/sourceutil.cpp
Expand Up @@ -364,6 +364,25 @@ bool SourceUtil::IsAnySourceScanable(void)
return false;
}

bool SourceUtil::IsSourceIDValid(uint sourceid)
{
MSqlQuery query(MSqlQuery::InitCon());
query.prepare(
"SELECT sourceid FROM videosource WHERE sourceid = :SOURCEID");
query.bindValue(":SOURCEID", sourceid);

if (!query.exec() || !query.isActive())
{
MythDB::DBError("SourceUtil::IsSourceIDValid", query);
return false;
}

if (!query.next())
return false;

return true;
}

bool SourceUtil::UpdateChannelsFromListings(uint sourceid, const QString& inputtype, bool wait)
{
if (wait)
Expand Down Expand Up @@ -427,7 +446,7 @@ bool SourceUtil::UpdateSource( uint sourceid, const QString& sourcename,
query.bindValue(":LINEUPID", lineupid);
query.bindValue(":PASSWORD", password);
query.bindValue(":USEEIT", useeit);
query.bindValue(":CONFIGPATH", configpath);
query.bindValue(":CONFIGPATH", configpath.isEmpty() ? nullptr : configpath);
query.bindValue(":NITID", nitid);
query.bindValue(":BOUQUETID", bouquetid);
query.bindValue(":REGIONID", regionid);
Expand Down Expand Up @@ -464,7 +483,7 @@ int SourceUtil::CreateSource( const QString& sourcename,
query.bindValue(":LINEUPID", lineupid);
query.bindValue(":PASSWORD", password);
query.bindValue(":USEEIT", useeit);
query.bindValue(":CONFIGPATH", configpath);
query.bindValue(":CONFIGPATH", configpath.isEmpty() ? nullptr : configpath);
query.bindValue(":NITID", nitid);
query.bindValue(":BOUQUETID", bouquetid);
query.bindValue(":REGIONID", regionid);
Expand Down
1 change: 1 addition & 0 deletions mythtv/libs/libmythtv/sourceutil.h
Expand Up @@ -30,6 +30,7 @@ class MTV_PUBLIC SourceUtil
static bool IsUnscanable(uint sourceid);
static bool IsCableCardPresent(uint sourceid);
static bool IsAnySourceScanable(void);
static bool IsSourceIDValid(uint sourceid);
static bool UpdateChannelsFromListings(
uint sourceid, const QString& inputtype = QString(), bool wait = false);

Expand Down
89 changes: 84 additions & 5 deletions mythtv/programs/mythbackend/services/channel.cpp
Expand Up @@ -316,7 +316,7 @@ DTC::VideoSource* Channel::GetVideoSource( uint nSourceID )
//
/////////////////////////////////////////////////////////////////////////////

bool Channel::UpdateVideoSource( uint nSourceId,
bool Channel::UpdateVideoSource( uint nSourceId,
const QString &sSourceName,
const QString &sGrabber,
const QString &sUserId,
Expand All @@ -330,11 +330,90 @@ bool Channel::UpdateVideoSource( uint nSourceId,
uint nRegionId,
uint nScanFrequency )
{
bool bResult = SourceUtil::UpdateSource(nSourceId, sSourceName, sGrabber, sUserId, sFreqTable,
sLineupId, sPassword, bUseEIT, sConfigPath,
nNITId, nBouquetId, nRegionId, nScanFrequency);

return bResult;
if (!HAS_PARAM("sourceid"))
{
LOG(VB_GENERAL, LOG_ERR, "SourceId is required");
return false;
}

if (!SourceUtil::IsSourceIDValid(nSourceId))
{
LOG(VB_GENERAL, LOG_ERR, QString("SourceId %1 doesn't exist")
.arg(nSourceId));
return false;
}

if (m_parsedParams.size() < 2 )
{
LOG(VB_GENERAL, LOG_ERR, "No changable parameters were passed");
return false;
}

MSqlBindings bindings;
MSqlBindings::const_iterator it;
QString settings;

if ( HAS_PARAM("sourcename") )
ADD_SQL(settings, bindings, "name", "SourceName", sSourceName)

if ( HAS_PARAM("grabber") )
ADD_SQL(settings, bindings, "xmltvgrabber", "Grabber", sGrabber)

if ( HAS_PARAM("userid") )
ADD_SQL(settings, bindings, "userid", "UserId", sUserId)

if ( HAS_PARAM("freqtable") )
ADD_SQL(settings, bindings, "freqtable", "FreqTable", sFreqTable)

if ( HAS_PARAM("lineupid") )
ADD_SQL(settings, bindings, "lineupid", "LineupId", sLineupId)

if ( HAS_PARAM("password") )
ADD_SQL(settings, bindings, "password", "Password", sPassword)

if ( HAS_PARAM("useeit") )
ADD_SQL(settings, bindings, "useeit", "UseEIT", bUseEIT)

if (HAS_PARAM("configpath"))
{
if (sConfigPath.isEmpty())
settings += "configpath=NULL, "; // mythfilldatabase grabber requirement
else
ADD_SQL(settings, bindings, "configpath", "ConfigPath", sConfigPath)
}

if ( HAS_PARAM("nitid") )
ADD_SQL(settings, bindings, "dvb_nit_id", "NITId", nNITId)

if ( HAS_PARAM("bouquetid") )
ADD_SQL(settings, bindings, "bouquet_id", "BouquetId", nBouquetId)

if ( HAS_PARAM("regionid") )
ADD_SQL(settings, bindings, "region_id", "RegionId", nRegionId)

if ( HAS_PARAM("scanfrequency") )
ADD_SQL(settings, bindings, "scanfrequency", "ScanFrequency", nScanFrequency)

settings.chop(2);

MSqlQuery query(MSqlQuery::InitCon());

query.prepare(QString("UPDATE videosource SET %1 WHERE sourceid=:SOURCEID")
.arg(settings));
bindings[":SOURCEID"] = nSourceId;

for (it = bindings.begin(); it != bindings.end(); ++it)
query.bindValue(it.key(), it.value());

if (!query.exec())
{
MythDB::DBError("MythAPI::UpdateVideoSource()", query);

throw( QString( "Database Error executing query." ));
}

return true;
}

/////////////////////////////////////////////////////////////////////////////
Expand Down
7 changes: 7 additions & 0 deletions mythtv/programs/mythbackend/services/serviceUtil.h
Expand Up @@ -46,6 +46,13 @@
#include "recordinginfo.h"
#include "musicmetadata.h"

#define ADD_SQL(settings_var, bindvar, col, api_param, val) { \
settings_var += QString("%1=:%2, ").arg(col).arg(api_param); \
bindvar[QString(":").append(api_param)] = val; \
}

#define HAS_PARAM(p) m_parsedParams.contains(p)

const QStringList KnownServices = { "Capture", "Channel", "Content", \
"Dvr", "Guide", "Music", \
"Myth", "Video" };
Expand Down

0 comments on commit 260a926

Please sign in to comment.