mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
synced 2026-01-27 10:23:15 +00:00
Typos and security verification.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
10
templates/email_verification.html
Normal file
10
templates/email_verification.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
0
templates/email_verification.txt
Normal file
0
templates/email_verification.txt
Normal file
BIN
templates/logo.jpg
Normal file
BIN
templates/logo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 263 KiB |
10
templates/password_reset.html
Normal file
10
templates/password_reset.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
0
templates/password_reset.txt
Normal file
0
templates/password_reset.txt
Normal file
Reference in New Issue
Block a user