Merge branch 'master' of github.com:ZoneMinder/zoneminder

pull/3477/head
Isaac Connor 2022-04-28 17:14:12 -04:00
commit 4ff69c3156
5 changed files with 71 additions and 8 deletions

View File

@ -119,6 +119,8 @@ FfmpegCamera::FfmpegCamera(
hwaccel_name(p_hwaccel_name),
hwaccel_device(p_hwaccel_device)
{
mMaskedPath = mask_authentication(mPath);
mMaskedSecondPath = mask_authentication(mSecondPath);
if ( capture ) {
FFMPEGInit();
}
@ -161,12 +163,12 @@ FfmpegCamera::~FfmpegCamera() {
int FfmpegCamera::PrimeCapture() {
start_read_time = std::chrono::steady_clock::now();
if ( mCanCapture ) {
Debug(1, "Priming capture from %s, Closing", mPath.c_str());
Debug(1, "Priming capture from %s, Closing", mMaskedPath.c_str());
Close();
}
mVideoStreamId = -1;
mAudioStreamId = -1;
Debug(1, "Priming capture from %s", mPath.c_str());
Debug(1, "Priming capture from %s", mMaskedPath.c_str());
return OpenFfmpeg();
}
@ -294,7 +296,7 @@ int FfmpegCamera::OpenFfmpeg() {
mPath = mPath.substr(7);
} // end if RTSP
Debug(1, "Calling avformat_open_input for %s", mPath.c_str());
Debug(1, "Calling avformat_open_input for %s", mMaskedPath.c_str());
mFormatContext = avformat_alloc_context();
mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback;
@ -321,7 +323,7 @@ int FfmpegCamera::OpenFfmpeg() {
ret = avformat_find_stream_info(mFormatContext, nullptr);
if (ret < 0) {
Error("Unable to find stream info from %s due to: %s",
mPath.c_str(), av_make_error_string(ret).c_str());
mMaskedPath.c_str(), av_make_error_string(ret).c_str());
avformat_close_input(&mFormatContext);
return -1;
}
@ -374,7 +376,7 @@ int FfmpegCamera::OpenFfmpeg() {
mVideoCodec = avcodec_find_decoder(mVideoStream->codecpar->codec_id);
if (!mVideoCodec) {
// Try and get the codec from the codec context
Error("Can't find codec for video stream from %s", mPath.c_str());
Error("Can't find codec for video stream from %s", mMaskedPath.c_str());
return -1;
}
}
@ -483,7 +485,7 @@ int FfmpegCamera::OpenFfmpeg() {
Warning("Option %s not recognized by ffmpeg", e->key);
}
if (ret < 0) {
Error("Unable to open codec for video stream from %s", mPath.c_str());
Error("Unable to open codec for video stream from %s", mMaskedPath.c_str());
av_dict_free(&opts);
return -1;
}
@ -504,7 +506,7 @@ int FfmpegCamera::OpenFfmpeg() {
if ( mAudioStreamId >= 0 ) {
const AVCodec *mAudioCodec = nullptr;
if (!(mAudioCodec = avcodec_find_decoder(mAudioStream->codecpar->codec_id))) {
Debug(1, "Can't find codec for audio stream from %s", mPath.c_str());
Debug(1, "Can't find codec for audio stream from %s", mMaskedPath.c_str());
} else {
mAudioCodecContext = avcodec_alloc_context3(mAudioCodec);
avcodec_parameters_to_context(mAudioCodecContext, mAudioStream->codecpar);
@ -512,7 +514,7 @@ int FfmpegCamera::OpenFfmpeg() {
zm_dump_stream_format((mSecondFormatContext?mSecondFormatContext:mFormatContext), mAudioStreamId, 0, 0);
// Open the codec
if (avcodec_open2(mAudioCodecContext, mAudioCodec, nullptr) < 0) {
Error("Unable to open codec for audio stream from %s", mPath.c_str());
Error("Unable to open codec for audio stream from %s", mMaskedPath.c_str());
return -1;
} // end if opened
} // end if found decoder

View File

@ -36,7 +36,9 @@ typedef struct DecodeContext {
class FfmpegCamera : public Camera {
protected:
std::string mPath;
std::string mMaskedPath;
std::string mSecondPath;
std::string mMaskedSecondPath;
std::string mMethod;
std::string mOptions;

View File

@ -442,3 +442,32 @@ std::string QueryString::parseValue(std::istream &input) {
return UriDecode(url_encoded_value);
}
std::string mask_authentication(const std::string &url) {
std::string masked_url = url;
std::size_t at_at = masked_url.find("@");
if (at_at == std::string::npos) {
return masked_url;
}
std::size_t password_at = masked_url.rfind(":", at_at);
if (password_at == std::string::npos) {
// no : means no http:// either so something liek username@192.168.1.1
masked_url.replace(0, at_at, at_at, '*');
} else if (masked_url[password_at+1] == '/') {
// no password, something like http://username@192.168.1.1
masked_url.replace(password_at+3, at_at-(password_at+3), at_at-(password_at+3), '*');
} else {
// have username and password, something like http://username:password@192.168.1.1/
masked_url.replace(password_at+1, at_at - (password_at+1), at_at - (password_at+1), '*');
std::size_t username_at = masked_url.rfind("/", password_at);
if (username_at == std::string::npos) {
// Something like username:password@192.168.1.1
masked_url.replace(0, password_at, password_at, '*');
} else {
masked_url.replace(username_at+1, password_at-(username_at+1), password_at-(username_at+1), '*');
// something like http://username:password@192.168.1.1/
}
}
return masked_url;
}

View File

@ -127,6 +127,8 @@ template<typename T, std::size_t N>
constexpr std::size_t size(const T(&)[N]) noexcept { return N; }
}
std::string mask_authentication(const std::string &url);
std::string UriDecode(const std::string &encoded);
class QueryParameter {

View File

@ -250,3 +250,31 @@ TEST_CASE("QueryString") {
REQUIRE(p2->values()[0] == "value2");
}
}
TEST_CASE("mask_authentication") {
SECTION("no authentication") {
std::string url("http://192.168.1.1");
std::string result = mask_authentication(url);
REQUIRE(url == result);
}
SECTION("has username no password has scheme") {
std::string url("http://username@192.168.1.1");
std::string result = mask_authentication(url);
REQUIRE(result == "http://********@192.168.1.1");
}
SECTION("has username no password no scheme") {
std::string url("username@192.168.1.1");
std::string result = mask_authentication(url);
REQUIRE(result == "********@192.168.1.1");
}
SECTION("has username has password no scheme") {
std::string url("username:password@192.168.1.1");
std::string result = mask_authentication(url);
REQUIRE(result == "********:********@192.168.1.1");
}
SECTION("has username has password has scheme") {
std::string url("http://username:password@192.168.1.1");
std::string result = mask_authentication(url);
REQUIRE(result == "http://********:********@192.168.1.1");
}
}