Typos and security verification.

This commit is contained in:
stephb9959
2021-07-10 16:08:51 -07:00
parent db57cbacae
commit 9566d191b2
12 changed files with 242 additions and 61 deletions

View File

@@ -20,6 +20,8 @@
#include "KafkaManager.h"
#include "Kafka_topics.h"
#include "SMTPMailerService.h"
namespace uCentral {
class AuthService *AuthService::instance_ = nullptr;
@@ -278,6 +280,26 @@ namespace uCentral {
return uCentral::Utils::ToHex(SHA2_.digest());
}
bool AuthService::SendEmailToUser(const std::string &Email, EMAIL_REASON Reason) {
switch(Reason) {
case FORGOT_PASSWORD: {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = "stephane.bourque@gmail.com";
Attrs[LOGO] = "logo.jpg";
SMTPMailerService()->SendMessage("stephane.bourque@gmail.com", Attrs); }
break;
case EMAIL_VERIFICATION:
break;
default:
break;
}
return false;
}
bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) {
return true;
}

View File

@@ -44,6 +44,11 @@ namespace uCentral{
INTERNAL_ERROR
};
enum EMAIL_REASON {
FORGOT_PASSWORD,
EMAIL_VERIFICATION
};
static ACCESS_TYPE IntToAccessType(int C);
static int AccessTypeToInt(ACCESS_TYPE T);
@@ -75,6 +80,8 @@ namespace uCentral{
[[nodiscard]] bool UpdatePassword(const std::string &Admin, const std::string &UserName, const std::string & OldPassword, const std::string &NewPassword);
[[nodiscard]] std::string ResetPassword(const std::string &Admin, const std::string &UserName);
bool SendEmailToUser(const std::string &Email, EMAIL_REASON Reason);
private:
static AuthService *instance_;
bool Secure_ = false ;

View File

@@ -30,6 +30,19 @@ namespace uCentral {
auto password = GetS(uCentral::RESTAPI::Protocol::PASSWORD, Obj);
auto newPassword = GetS(uCentral::RESTAPI::Protocol::NEWPASSWORD, Obj);
ParseParameters(Request);
if(GetParameter("forgotPassword","false") == "true") {
// Send an email to the userId
SecurityObjects::UserInfoAndPolicy UInfo;
AuthService()->SendEmailToUser(userId,AuthService::FORGOT_PASSWORD);
UInfo.webtoken.userMustChangePassword=true;
Poco::JSON::Object ReturnObj;
UInfo.webtoken.to_json(ReturnObj);
ReturnObject(Request, ReturnObj, Response);
return;
}
Poco::toLowerInPlace(userId);
SecurityObjects::UserInfoAndPolicy UInfo;

View File

@@ -2,6 +2,7 @@
// Created by stephane bourque on 2021-06-17.
//
#include <iostream>
#include <fstream>
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/MailRecipient.h"
@@ -16,6 +17,7 @@
#include "Poco/Net/AcceptCertificateHandler.h"
#include "SMTPMailerService.h"
#include "Utils.h"
#include "Daemon.h"
namespace uCentral {
@@ -27,45 +29,98 @@ namespace uCentral {
SenderLoginUserName_ = Daemon()->ConfigGetString("mailer.username");
SenderLoginPassword_ = Daemon()->ConfigGetString("mailer.password");
LoginMethod_ = Daemon()->ConfigGetString("mailer.loginmethod");
MailHostPort_ = Daemon()->ConfigGetInt("mailer.port");
MailHostPort_ = (int)Daemon()->ConfigGetInt("mailer.port");
TemplateDir_ = Daemon()->ConfigPath("mailer.templates", Daemon()->DataDir());
SenderThr_.start(*this);
return 0;
}
void SMTPMailerService::Stop() {
Running_ = false;
SenderThr_.wakeUp();
SenderThr_.join();
}
bool SMTPMailerService::SendMessage(SMTPMailerService::MessageAttributes Attrs) {
bool SMTPMailerService::SendMessage(const std::string &Recipient, const MessageAttributes &Attrs) {
SubMutexGuard G(Mutex_);
uint64_t Now = std::time(nullptr);
auto CE = Cache_.find(Poco::toLower(Recipient));
if(CE!=Cache_.end()) {
// only allow messages to the same user within 2 minutes
if((CE->second.LastRequest-Now)<30)
return false;
if((CE->second.HowManyRequests>30))
return false;
}
Messages_.push_back(MessageEvent{.Posted=(uint64_t )std::time(nullptr),
.LastTry=0,
.Attrs=Attrs});
return false;
}
bool SMTPMailerService::SendIt() {
void SMTPMailerService::run() {
Running_ = true;
while(Running_) {
Poco::Thread::trySleep(2000);
{
SubMutexGuard G(Mutex_);
uint64_t Now = std::time(nullptr);
for(auto &i:Messages_) {
if(i.Sent==0 && (i.LastTry==0 || (Now-i.LastTry)>120)) {
if (SendIt(i.Attrs)) {
i.LastTry = i.Sent = std::time(nullptr);
} else
i.LastTry = std::time(nullptr);
}
}
// Clean the list
std::remove_if(Messages_.begin(),Messages_.end(),[Now](MessageEvent &E){ return (E.Sent!=0 || ((Now-E.LastTry)>(24*60*60)));});
}
}
}
bool SMTPMailerService::SendIt(const MessageAttributes & Attrs) {
try
{
Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> ptrHandler = new Poco::Net::AcceptCertificateHandler(false);
/*
Poco::Net::MailMessage message;
message.setSender(Sender_);
message.addRecipient(MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, recipient));
message.setSubject("Hello from the POCO C++ Libraries");
Poco::Net::MailMessage Message;
std::string Recipient = Attrs.find(RECIPIENT_EMAIL)->second;
Message.setSender(Sender_);
Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient));
Message.setSubject("Hello from the POCO C++ Libraries");
std::string content;
content += "Hello ";
content += recipient;
content += Recipient;
content += ",\r\n\r\n";
content += "This is a greeting from the POCO C++ Libraries.\r\n\r\n";
std::string logo(reinterpret_cast<const char*>(PocoLogo), sizeof(PocoLogo));
message.addContent(new Poco::Net::StringPartSource(content));
message.addAttachment("logo", new Poco::Net::StringPartSource(logo, "image/gif"));
Message.addContent(new Poco::Net::StringPartSource(content));
auto Logo = Attrs.find(LOGO);
if(Logo!=Attrs.end()) {
Poco::File LogoFile(TemplateDir_ + "/" + Logo->second);
std::ifstream IF(LogoFile.path());
std::ostringstream OS;
Poco::StreamCopier::copyStream(IF, OS);
Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/jpeg"));
}
Poco::Net::SecureSMTPClientSession session(MailHost_,MailHostPort_);
Poco::Net::Context::Params P;
auto ptrContext = new Poco::Net::Context( Poco::Net::Context::CLIENT_USE, "", "", "",
auto ptrContext = Poco::AutoPtr<Poco::Net::Context>
(new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "",
Poco::Net::Context::VERIFY_RELAXED, 9, true,
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"));
Poco::Net::SSLManager::instance().initializeClient(nullptr,
ptrHandler,
@@ -78,17 +133,15 @@ namespace uCentral {
SenderLoginUserName_,
SenderLoginPassword_
);
session.sendMessage(message);
session.sendMessage(Message);
session.close();
*/
return true;
}
catch (const Poco::Exception& exc)
catch (const Poco::Exception& E)
{
std::cerr << exc.displayText() << std::endl;
return 1;
Logger_.log(E);
}
return 0;
return false;
}
}

View File

@@ -8,50 +8,91 @@
#include "SubSystemServer.h"
namespace uCentral {
class SMTPMailerService : public SubSystemServer {
public:
enum MESSAGE_ATTRIBUTES {
RECIPIENT_EMAIL,
RECIPIENT_FIRST_NAME,
RECIPIENT_LAST_NAME,
RECIPIENT_INITIALS,
RECIPIENT_FULL_NAME,
RECIPIENT_SALUTATION,
SUBJECT,
SIGNATURE,
TEMPLATE,
LOGO
};
typedef std::map<MESSAGE_ATTRIBUTES, std::string> MessageAttributes;
enum MESSAGE_ATTRIBUTES {
RECIPIENT_EMAIL,
RECIPIENT_FIRST_NAME,
RECIPIENT_LAST_NAME,
RECIPIENT_INITIALS,
RECIPIENT_FULL_NAME,
RECIPIENT_SALUTATION,
ACTION_LINK,
SUBJECT,
TEMPLATE_TXT,
TEMPLATE_HTML,
LOGO
};
static SMTPMailerService *instance() {
if (instance_ == nullptr) {
instance_ = new SMTPMailerService;
static const std::map<MESSAGE_ATTRIBUTES,const std::string>
MessageAttributeMap{ { RECIPIENT_EMAIL,"RECIPIENT_EMAIL"},
{ RECIPIENT_FIRST_NAME, "RECIPIENT_FIRST_NAME"},
{ RECIPIENT_LAST_NAME, "RECIPIENT_LAST_NAME"},
{ RECIPIENT_INITIALS, "RECIPIENT_INITIALS"},
{ RECIPIENT_FULL_NAME, "RECIPIENT_FULL_NAME"},
{ RECIPIENT_SALUTATION, "RECIPIENT_SALUTATION"},
{ ACTION_LINK, "ACTION_LINK"},
{ SUBJECT, "SUBJECT"},
{ TEMPLATE_TXT, "TEMPLATE_TXT"},
{ TEMPLATE_HTML, "TEMPLATE_HTML"},
{ LOGO, "LOGO"}};
inline const std::string & MessageAttributeToVar(MESSAGE_ATTRIBUTES Attr) {
static const std::string EmptyString{};
auto E = MessageAttributeMap.find(Attr);
if(E == MessageAttributeMap.end())
return EmptyString;
return E->second;
}
typedef std::map<MESSAGE_ATTRIBUTES, std::string> MessageAttributes;
class SMTPMailerService : public SubSystemServer, Poco::Runnable {
public:
static SMTPMailerService *instance() {
if (instance_ == nullptr) {
instance_ = new SMTPMailerService;
}
return instance_;
}
return instance_;
}
int Start() override;
void Stop() override;
bool SendMessage(MessageAttributes Attrs);
bool SendIt();
struct MessageEvent {
uint64_t Posted=0;
uint64_t LastTry=0;
uint64_t Sent=0;
MessageAttributes Attrs;
};
private:
static SMTPMailerService * instance_;
std::string MailHost_;
std::string Sender_;
int MailHostPort_=25;
std::string SenderLoginUserName_;
std::string SenderLoginPassword_;
std::string LoginMethod_ = "login";
std::string LogoFileName_;
struct MessageCacheEntry {
uint64_t LastRequest=0;
uint64_t HowManyRequests=0;
};
SMTPMailerService() noexcept:
SubSystemServer("SMTPMailer", "MAILER-SVR", "smtpmailer")
{
std::string E{"SHA512"};
}
void run() override;
int Start() override;
void Stop() override;
bool SendMessage(const std::string &Recipient, const MessageAttributes &Attrs);
bool SendIt(const MessageAttributes &Attrs);
private:
static SMTPMailerService * instance_;
std::string MailHost_;
std::string Sender_;
int MailHostPort_=25;
std::string SenderLoginUserName_;
std::string SenderLoginPassword_;
std::string LoginMethod_ = "login";
std::string LogoFileName_;
std::string TemplateDir_;
std::list<MessageEvent> Messages_;
std::map<std::string,MessageCacheEntry> Cache_;
Poco::Thread SenderThr_;
std::atomic_bool Running_=false;
SMTPMailerService() noexcept:
SubSystemServer("SMTPMailer", "MAILER-SVR", "smtpmailer")
{
std::string E{"SHA512"};
}
};
inline SMTPMailerService * SMTPMailerService() { return SMTPMailerService::instance(); }

View File

@@ -442,4 +442,28 @@ namespace uCentral::Utils {
return "application/octet-stream";
}
std::string BinaryFileToHexString(const Poco::File &F) {
static const char hex[] = "0123456789abcdef";
std::string Result;
try {
std::ifstream IF(F.path());
int Count = 0;
while (IF.good()) {
if (Count)
Result += ", ";
if ((Count % 32) == 0)
Result += "\r\n";
Count++;
unsigned char C = IF.get();
Result += "0x";
Result += (char) (hex[(C & 0xf0) >> 4]);
Result += (char) (hex[(C & 0x0f)]);
}
} catch(...) {
}
return Result;
}
}

View File

@@ -57,5 +57,6 @@ namespace uCentral::Utils {
void ReplaceVariables( std::string & Content , const Types::StringPairVec & P);
[[nodiscard]] std::string FindMediaType(const Poco::File &F);
[[nodiscard]] std::string BinaryFileToHexString( const Poco::File &F);
}
#endif // UCENTRALGW_UTILS_H

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>

View File

BIN
templates/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>

View File