move to wrapper

This commit is contained in:
Pliable Pixels 2019-05-03 11:40:35 -04:00
parent d252a8ba30
commit 72325d12b7
5 changed files with 123 additions and 34 deletions

3
.gitmodules vendored
View File

@ -5,9 +5,6 @@
[submodule "web/api/app/Plugin/CakePHP-Enum-Behavior"]
path = web/api/app/Plugin/CakePHP-Enum-Behavior
url = https://github.com/ZoneMinder/CakePHP-Enum-Behavior.git
[submodule "third_party/bcrypt"]
path = third_party/bcrypt
url = https://github.com/trusch/libbcrypt
[submodule "third_party/sha1"]
path = third_party/sha1
url = https://github.com/vog/sha1

View File

@ -4,7 +4,7 @@
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_crypt.cpp)
# includes and linkages to 3rd party libraries/src

74
src/zm_crypt.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "zm.h"
# include "zm_crypt.h"
#include <algorithm>
//https://stackoverflow.com/a/46403026/1361529
char char2int(char input) {
if (input >= '0' && input <= '9')
return input - '0';
else if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
else if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
else
return input; // this really should not happen
}
std::string hex2str(std::string &hex) {
std::string out;
out.resize(hex.size() / 2 + hex.size() % 2);
std::string::iterator it = hex.begin();
std::string::iterator out_it = out.begin();
if (hex.size() % 2 != 0) {
*out_it++ = char(char2int(*it++));
}
for (; it < hex.end() - 1; it++) {
*out_it++ = char2int(*it++) << 4 | char2int(*it);
};
return out;
}
bool verifyPassword(const char *input_password, const char *db_password_hash) {
bool password_correct = false;
if (strlen(db_password_hash ) < 4) {
// actually, shoud be more, but this is min. for next code
Error ("DB Password is too short or invalid to check");
return false;
}
if (db_password_hash[0] == '*') {
// MYSQL PASSWORD
Info ("%s is an MD5 encoded password", db_password_hash);
SHA1 checksum;
// next few lines do '*'+SHA1(raw(SHA1(password)))
// which is MYSQL >=4.1 PASSWORD algorithm
checksum.update(input_password);
std::string interim_hash = checksum.final();
std::string binary_hash = hex2str(interim_hash); // get interim hash
checksum.update(binary_hash);
interim_hash = checksum.final();
std::string final_hash = "*" + interim_hash;
std::transform(final_hash.begin(), final_hash.end(), final_hash.begin(), ::toupper);
Info ("Computed password_hash:%s, stored password_hash:%s", final_hash.c_str(), db_password_hash);
password_correct = (std::string(db_password_hash) == final_hash);
}
else if ((db_password_hash[0] == '$') && (db_password_hash[1]== '2')
&&(db_password_hash[3] == '$')) {
// BCRYPT
Info ("%s is a Bcrypt password", db_password_hash);
BCrypt bcrypt;
std::string input_hash = bcrypt.generateHash(std::string(input_password));
password_correct = bcrypt.validatePassword(std::string(input_password), std::string(db_password_hash));
}
else {
// plain
password_correct = (strcmp(input_password, db_password_hash) == 0);
}
return password_correct;
}

29
src/zm_crypt.h Normal file
View File

@ -0,0 +1,29 @@
//
// ZoneMinder General Utility Functions, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
//
// 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; either version 2
// of the License, or (at your option) any later version.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
#ifndef ZM_CRYPT_H
#define ZM_CRYPT_H
#include <string.h>
#include "BCrypt.hpp"
#include "sha1.hpp"
bool verifyPassword( const char *input_password, const char *db_password_hash);
#endif // ZM_CRYPT_H

View File

@ -26,10 +26,10 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "BCrypt.hpp"
#include "sha1.hpp"
#include "zm_utils.h"
#include "zm_crypt.h"
User::User() {
id = 0;
@ -97,34 +97,15 @@ User *zmLoadUser( const char *username, const char *password ) {
// According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator.
mysql_real_escape_string(&dbconn, safer_username, username, username_length );
BCrypt bcrypt;
std::string ptest = "test";
std::string hash = bcrypt.generateHash(ptest);
Info ("ZM_USER TEST: BCRYPT WORKED AND PRODUCED %s", hash.c_str());
SHA1 sha1_checksum;
sha1_checksum.update (ptest);
hash = sha1_checksum.final();
Info ("ZM_USER TEST: SHA1 WORKED AND PRODUCED %s", hash.c_str());
snprintf(sql, sizeof(sql),
"SELECT Id, Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds"
" FROM Users where Username = '%s' and Enabled = 1", safer_username );
if ( password ) {
int password_length = strlen(password);
char *safer_password = new char[(password_length * 2) + 1];
mysql_real_escape_string(&dbconn, safer_password, password, password_length);
snprintf(sql, sizeof(sql),
"SELECT Id, Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds"
" FROM Users WHERE Username = '%s' AND Password = password('%s') AND Enabled = 1",
safer_username, safer_password );
delete safer_password;
} else {
snprintf(sql, sizeof(sql),
"SELECT Id, Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds"
" FROM Users where Username = '%s' and Enabled = 1", safer_username );
}
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
exit(mysql_errno(&dbconn));
exit(mysql_errno(&dbconn));
}
MYSQL_RES *result = mysql_store_result(&dbconn);
@ -143,12 +124,20 @@ User *zmLoadUser( const char *username, const char *password ) {
MYSQL_ROW dbrow = mysql_fetch_row(result);
User *user = new User(dbrow);
Info("Authenticated user '%s'", user->getUsername());
Info ("Retrieved password for user:%s as %s", user->getUsername(), user->getPassword());
mysql_free_result(result);
delete safer_username;
return user;
if (verifyPassword(password, user->getPassword())) {
Info("Authenticated user '%s'", user->getUsername());
mysql_free_result(result);
delete safer_username;
return user;
}
else {
Warning("Unable to authenticate user %s", username);
mysql_free_result(result);
return NULL;
}
}
// Function to validate an authentication string