mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-05-29 15:12:34 +02:00
2021-04-27 Fred Gleason <fredg@paravelsystems.com>
* Changed the 'RDAIRPLAY_EXIT_PASSWORD' field from 'varchar(41)' to 'varchar(48)'. * Incremented the database version to 349. * Renamed the 'RDSha1Hash()' function to 'RDSha1HashFile()'. * Added 'RDSha1HashPassword()' function in 'lib/rdhash.[cpp|h]'. * Added 'RDSha1HashCheckPassword()' function in 'lib/rdhash.[cpp|h]'. * Changed the hashing algorithm used for the Exit Password for rdairplay(1) to salted SHA1. Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
parent
05c35a208c
commit
9a65658267
@ -21631,3 +21631,12 @@
|
||||
* Fixed a regression in 'RDLog::create()' that threw SQL errors.
|
||||
2021-04-27 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Fixed a regression in 'RDLogModel' that threw SQL errors.
|
||||
2021-04-27 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Changed the 'RDAIRPLAY_EXIT_PASSWORD' field from 'varchar(41)'
|
||||
to 'varchar(48)'.
|
||||
* Incremented the database version to 349.
|
||||
* Renamed the 'RDSha1Hash()' function to 'RDSha1HashFile()'.
|
||||
* Added 'RDSha1HashPassword()' function in 'lib/rdhash.[cpp|h]'.
|
||||
* Added 'RDSha1HashCheckPassword()' function in 'lib/rdhash.[cpp|h]'.
|
||||
* Changed the hashing algorithm used for the Exit Password for
|
||||
rdairplay(1) to salted SHA1.
|
||||
|
@ -26,7 +26,7 @@ DEFAULT_SERVICE varchar(10) From SERVICES.NAME
|
||||
HOUR_SELECTOR_ENABLED enum('N','Y')
|
||||
EXIT_CODE int(11) 0=clean, 1=dirty
|
||||
VIRTUAL_EXIT_CODE int(11) 0=clean, 1=dirty
|
||||
EXIT_PASSWORD varchar(41)
|
||||
EXIT_PASSWORD varchar(48)
|
||||
SKIN_PATH varchar(191)
|
||||
SHOW_COUNTERS enum('N','Y')
|
||||
AUDITION_PREROLL int(11)
|
||||
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* Current Database Version
|
||||
*/
|
||||
#define RD_VERSION_DATABASE 348
|
||||
#define RD_VERSION_DATABASE 349
|
||||
|
||||
|
||||
#endif // DBVERSION_H
|
||||
|
@ -20,10 +20,11 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "rdairplay_conf.h"
|
||||
#include "rddb.h"
|
||||
#include "rdconf.h"
|
||||
#include "rdairplay_conf.h"
|
||||
#include "rdescape_string.h"
|
||||
#include "rdhash.h"
|
||||
|
||||
RDAirPlayConf::RDAirPlayConf(const QString &station,const QString &tablename)
|
||||
{
|
||||
@ -662,34 +663,40 @@ bool RDAirPlayConf::exitPasswordValid(const QString &passwd) const
|
||||
{
|
||||
QString sql;
|
||||
RDSqlQuery *q;
|
||||
bool ret=false;
|
||||
|
||||
sql=QString("select `EXIT_PASSWORD` from `")+air_tablename+"` where "+
|
||||
"STATION='"+RDEscapeString(air_station)+"' && "+
|
||||
"((`EXIT_PASSWORD`=PASSWORD('"+RDEscapeString(passwd)+"'))";
|
||||
if(passwd.isEmpty()) {
|
||||
sql+="||(`EXIT_PASSWORD` is null)";
|
||||
}
|
||||
sql+=")";
|
||||
sql=QString("select ")+
|
||||
"`EXIT_PASSWORD` "+ // 00
|
||||
"from `"+air_tablename+"` where "+
|
||||
"`STATION`='"+RDEscapeString(air_station)+"'";
|
||||
q=new RDSqlQuery(sql);
|
||||
if(q->size()>0) {
|
||||
delete q;
|
||||
return true;
|
||||
if(q->first()) {
|
||||
if(passwd.isEmpty()) {
|
||||
ret=q->value(0).isNull();
|
||||
}
|
||||
delete q;
|
||||
return false;
|
||||
else {
|
||||
ret=RDSha1HashCheckPassword(passwd,q->value(0).toString());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void RDAirPlayConf::setExitPassword(const QString &passwd) const
|
||||
{
|
||||
QString sql;
|
||||
RDSqlQuery *q;
|
||||
|
||||
if(passwd.isEmpty()) {
|
||||
sql=QString("update `")+air_tablename+"` set "+
|
||||
"`EXIT_PASSWORD`=PASSWORD('"+RDEscapeString(passwd)+"') where "+
|
||||
"`EXIT_PASSWORD`=null where "+
|
||||
"`STATION`='"+RDEscapeString(air_station)+"'";
|
||||
q=new RDSqlQuery(sql);
|
||||
delete q;
|
||||
}
|
||||
else {
|
||||
sql=QString("update `")+air_tablename+"` set "+
|
||||
"`EXIT_PASSWORD`='"+RDEscapeString(RDSha1HashPassword(passwd))+"' where "+
|
||||
"`STATION`='"+RDEscapeString(air_station)+"'";
|
||||
}
|
||||
RDSqlQuery::apply(sql);
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,9 +27,28 @@
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
#include "rdhash.h"
|
||||
|
||||
QString RDSha1Hash(const QString &filename,bool throttle)
|
||||
QString __RDSha1Hash_MakePasswordHash(const QString &secret,const QString &salt)
|
||||
{
|
||||
SHA_CTX ctx;
|
||||
unsigned char md[SHA_DIGEST_LENGTH];
|
||||
|
||||
SHA1_Init(&ctx);
|
||||
SHA1_Update(&ctx,salt.toUtf8(),salt.toUtf8().length());
|
||||
SHA1_Update(&ctx,secret.toUtf8(),secret.toUtf8().length());
|
||||
SHA1_Final(md,&ctx);
|
||||
QString ret=salt;
|
||||
for(int i=0;i<SHA_DIGEST_LENGTH;i++) {
|
||||
ret+=QString().sprintf("%02x",0xff&md[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString RDSha1HashFile(const QString &filename,bool throttle)
|
||||
{
|
||||
QString ret;
|
||||
SHA_CTX ctx;
|
||||
@ -57,3 +76,27 @@ QString RDSha1Hash(const QString &filename,bool throttle)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QString RDSha1HashPassword(const QString &secret)
|
||||
{
|
||||
|
||||
//
|
||||
// Create a salt value
|
||||
//
|
||||
srand(QDateTime::currentDateTime().toMSecsSinceEpoch());
|
||||
QString salt=QString().sprintf("%08x",rand());
|
||||
|
||||
//
|
||||
// Generate the hash
|
||||
//
|
||||
return __RDSha1Hash_MakePasswordHash(secret,salt);
|
||||
}
|
||||
|
||||
|
||||
bool RDSha1HashCheckPassword(const QString &secret,const QString &hash)
|
||||
{
|
||||
QString salt=secret.left(8);
|
||||
|
||||
return __RDSha1Hash_MakePasswordHash(secret,hash.left(8))==hash;
|
||||
}
|
||||
|
@ -23,7 +23,9 @@
|
||||
|
||||
#include <qstring.h>
|
||||
|
||||
QString RDSha1Hash(const QString &filename,bool throttle=false);
|
||||
QString RDSha1HashFile(const QString &filename,bool throttle=false);
|
||||
QString RDSha1HashPassword(const QString &secret);
|
||||
bool RDSha1HashCheckPassword(const QString &secret,const QString &hash);
|
||||
|
||||
|
||||
#endif // RD_H
|
||||
#endif // RDHASH_H
|
||||
|
@ -2334,7 +2334,7 @@ void MainObject::CheckInRecording(QString cutname,CatchEvent *evt,
|
||||
s->setChannels(evt->channels());
|
||||
cut->checkInRecording(rda->config()->stationName(),"",
|
||||
rda->config()->stationName(),s,msecs);
|
||||
cut->setSha1Hash(RDSha1Hash(RDCut::pathName(cut->cutName())));
|
||||
cut->setSha1Hash(RDSha1HashFile(RDCut::pathName(cut->cutName())));
|
||||
delete s;
|
||||
cut->autoTrim(RDCut::AudioBoth,-threshold);
|
||||
RDCart *cart=new RDCart(cut->cartNumber());
|
||||
|
@ -133,6 +133,7 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
|
||||
login_button=new QPushButton(this);
|
||||
login_button->setFont(buttonFont());
|
||||
login_button->setText(tr("Set User"));
|
||||
login_button->setDefault(true);
|
||||
connect(login_button,SIGNAL(clicked()),this,SLOT(loginData()));
|
||||
|
||||
//
|
||||
|
@ -32,6 +32,8 @@ MainObject::MainObject(QObject *parent)
|
||||
:QObject(parent)
|
||||
{
|
||||
QString filename="";
|
||||
QString password="";
|
||||
QString hash="";
|
||||
|
||||
//
|
||||
// Read Command Options
|
||||
@ -42,27 +44,58 @@ MainObject::MainObject(QObject *parent)
|
||||
filename=cmd->value(i);
|
||||
cmd->setProcessed(i,true);
|
||||
}
|
||||
if(cmd->key(i)=="--hash") {
|
||||
hash=cmd->value(i);
|
||||
cmd->setProcessed(i,true);
|
||||
}
|
||||
if(filename.isEmpty()) {
|
||||
fprintf(stderr,"test_hash: missing --filename\n");
|
||||
if(cmd->key(i)=="--password") {
|
||||
password=cmd->value(i);
|
||||
cmd->setProcessed(i,true);
|
||||
}
|
||||
}
|
||||
if(filename.isEmpty()&&password.isEmpty()) {
|
||||
fprintf(stderr,"test_hash: missing --filename or --password\n");
|
||||
exit(256);
|
||||
}
|
||||
if((!filename.isEmpty())&&(!password.isEmpty())) {
|
||||
fprintf(stderr,"test_hash: --filename and --password are mutually exclusive\n");
|
||||
exit(256);
|
||||
}
|
||||
|
||||
QString hash=RDSha1Hash(filename);
|
||||
if(!filename.isEmpty()) { // Hash the specified file
|
||||
hash=RDSha1HashFile(filename);
|
||||
if(hash.isEmpty()) {
|
||||
fprintf(stderr,"test_hash: unable to open \"%s\"\n",
|
||||
filename.toUtf8().constData());
|
||||
exit(256);
|
||||
}
|
||||
printf("%s\n",hash.toUtf8().constData());
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if((!hash.isEmpty())&&(!password.isEmpty())) { // Check the specified hash
|
||||
if( RDSha1HashCheckPassword(password,hash)) {
|
||||
printf("Match!\n");
|
||||
}
|
||||
else {
|
||||
printf("No Match!\n");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(!password.isEmpty()) { // Generate password hash
|
||||
printf("%s\n",RDSha1HashPassword(password).toUtf8().constData());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fprintf(stderr,"test_hash: inconsistent arguments given!\n");
|
||||
exit(256);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
QApplication a(argc,argv,false);
|
||||
QCoreApplication a(argc,argv);
|
||||
new MainObject();
|
||||
return a.exec();
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <rdcmd_switch.cpp>
|
||||
#include <rdhash.h>
|
||||
|
||||
#define TEST_HASH_USAGE "[options]\n\nTest SHA1 has generation\n\n--filename=<file-name>\n The name of the file for which to generate a hash.\n\n"
|
||||
#define TEST_HASH_USAGE "[options]\n\nTest SHA1 hash generation\n\n--filename=<file-name>\n The name of the file for which to generate a hash.\n\n--password=<secret>\n Generate a password hash from <secret>\n\n--hash=<hash>\n When given with --secret, verify <hash>\n\n"
|
||||
|
||||
class MainObject : public QObject
|
||||
{
|
||||
|
@ -211,7 +211,7 @@ void MainObject::CheckTableAttributes()
|
||||
printf(" Database uses default charset/collation %s/%s, should be utf8mb4/%s. Fix? (y/N) ",
|
||||
q->value(1).toString().toUtf8().constData(),
|
||||
q->value(2).toString().toUtf8().constData(),
|
||||
db_config->mysqlCollation());
|
||||
db_config->mysqlCollation().toUtf8().constData());
|
||||
fflush(NULL);
|
||||
if(UserResponse()) {
|
||||
sql=QString("alter database `")+db_mysql_database+"` "+
|
||||
@ -400,7 +400,7 @@ void MainObject::RelinkAudio(const QString &srcdir) const
|
||||
QStringList files=dir.entryList(QDir::Files|QDir::Readable|QDir::Hidden);
|
||||
for(int i=0;i<files.size();i++) {
|
||||
QString filename=dir.path()+"/"+files[i];
|
||||
QString hash=RDSha1Hash(filename);
|
||||
QString hash=RDSha1HashFile(filename);
|
||||
QString firstdest;
|
||||
bool delete_source=true;
|
||||
|
||||
@ -913,7 +913,7 @@ void MainObject::RehashCart(unsigned cartnum) const
|
||||
|
||||
void MainObject::RehashCut(const QString &cutnum) const
|
||||
{
|
||||
QString hash=RDSha1Hash(RDCut::pathName(cutnum),true);
|
||||
QString hash=RDSha1HashFile(RDCut::pathName(cutnum),true);
|
||||
if(hash.isEmpty()) {
|
||||
printf(" Unable to generate hash for \"%s\"\n",
|
||||
RDCut::pathName(cutnum).toUtf8().constData());
|
||||
|
@ -40,6 +40,19 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg)
|
||||
// NEW SCHEMA REVERSIONS GO HERE...
|
||||
|
||||
|
||||
//
|
||||
// Revert 349
|
||||
//
|
||||
if((cur_schema==349)&&(set_schema<cur_schema)) {
|
||||
sql=QString("alter table `RDAIRPLAY` ")+
|
||||
"modify column EXIT_PASSWORD varchar(41)";
|
||||
if(!RDSqlQuery::apply(sql,err_msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WriteSchemaVersion(--cur_schema);
|
||||
}
|
||||
|
||||
//
|
||||
// Revert 348
|
||||
//
|
||||
|
@ -159,7 +159,7 @@ void MainObject::InitializeSchemaMap() {
|
||||
global_version_map["3.3"]=314;
|
||||
global_version_map["3.4"]=317;
|
||||
global_version_map["3.5"]=346;
|
||||
global_version_map["4.0"]=348;
|
||||
global_version_map["4.0"]=349;
|
||||
}
|
||||
|
||||
|
||||
|
@ -10774,6 +10774,16 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg)
|
||||
WriteSchemaVersion(++cur_schema);
|
||||
}
|
||||
|
||||
if((cur_schema<349)&&(set_schema>cur_schema)) {
|
||||
sql=QString("alter table `RDAIRPLAY` ")+
|
||||
"modify column EXIT_PASSWORD varchar(48)";
|
||||
if(!RDSqlQuery::apply(sql,err_msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WriteSchemaVersion(++cur_schema);
|
||||
}
|
||||
|
||||
|
||||
// NEW SCHEMA UPDATES GO HERE...
|
||||
|
||||
|
@ -256,7 +256,7 @@ void Xport::Import()
|
||||
break;
|
||||
}
|
||||
if(resp_code==200) {
|
||||
cut->setSha1Hash(RDSha1Hash(RDCut::pathName(cut->cutName())));
|
||||
cut->setSha1Hash(RDSha1HashFile(RDCut::pathName(cut->cutName())));
|
||||
if(!title.isEmpty()) {
|
||||
cart->setTitle(title);
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ void Xport::SavePodcast()
|
||||
delete cast;
|
||||
XmlExit(err_msg.toUtf8(),500,"podcasts.cpp",LINE_NUMBER);
|
||||
}
|
||||
cast->setSha1Hash(RDSha1Hash(destpath));
|
||||
cast->setSha1Hash(RDSha1HashFile(destpath));
|
||||
|
||||
printf("Content-type: text/html; charset: UTF-8\n");
|
||||
printf("Status: 200\n\n");
|
||||
@ -172,7 +172,7 @@ void Xport::GetPodcast()
|
||||
data=new char[st.st_blksize];
|
||||
n=read(fd,data,st.st_blksize);
|
||||
while(n>0) {
|
||||
write(1,data,n);
|
||||
n=write(1,data,n);
|
||||
n=read(fd,data,st.st_blksize);
|
||||
}
|
||||
delete data;
|
||||
|
@ -59,7 +59,7 @@ void Xport::Rehash()
|
||||
delete cut;
|
||||
XmlExit("No such cut",404,"rdhash.cpp",LINE_NUMBER);
|
||||
}
|
||||
cut->setSha1Hash(RDSha1Hash(RDCut::pathName(cart_number,cut_number)));
|
||||
cut->setSha1Hash(RDSha1HashFile(RDCut::pathName(cart_number,cut_number)));
|
||||
delete cut;
|
||||
XmlExit("OK",200,"rdhash.cpp",LINE_NUMBER);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user