Hi!
Is it possible on server side?
I want connect to server with low auth and high auth from DLMSDirector. But OBIS 0.0.40.0.0.255 (CGXDLMSAssociationLogicalName) support only single secret.
I added CGXDLMSAssociationLogicalName with name 1.1.40.1.3.255 with secret "high_passwd"
void DLMS_Server::create_high_password()
{
std::string name = "1.1.40.1.3.255";
CGXDLMSAssociationLogicalName *high_pass = new CGXDLMSAssociationLogicalName(name);
CGXByteBuffer passwd;
passwd.AddString("high_passwd");
high_pass->SetSecret(passwd);
GetItems().push_back(high_pass);
}
but CGXDLMSServer::HandleAarqRequest() handle only 0.0.40.0.0.255.
Where can i see an example?
Thanks!
A low-level password is sent with AARQ and it's checked in CGXDLMSBase::ValidateAuthentication.
High-level password in send after the server has accepted the connection and reply AARE.
You must define two CGXDLMSAssociationLogicalName objects. One for Low level and one for High level.
For this reason, there is only one secret for each association. You might have multiple association views and each has a different password and access levels and COSEM objects.
Ok, thanks for reply!
Is CGXDLMSAssociationLogicalName objects has 0.0.40.0.0.255 name only?
std::string name = "0.0.40.0.0.255"; //"1.1.40.1.3.255";
CGXDLMSAssociationLogicalName *high_pass = new CGXDLMSAssociationLogicalName(name);
CGXByteBuffer passwd;
passwd.AddString("high_passwd");
high_pass->SetSecret(passwd);
m_Settings.GetObjects().push_back(high_pass); // now two objects with 0.0.40.0.0.255 and different passwords
0.0.40.0.0.255 is current association. Don't use that. Create 2 instances from CGXDLMSAssociationLogicalName with different logical names something like this:
CGXDLMSAssociationLogicalName *low_pass = new CGXDLMSAssociationLogicalName("0.0.40.0.1.255");
CGXDLMSAssociationLogicalName *high_pass = new CGXDLMSAssociationLogicalName("0.0.40.0.2.255");
Hi!
Thanks for you reply!
I made this:
class DLMS_Server : public QObject, public CGXDLMSSecureServer
{
Q_OBJECT
public:
DLMS_Server(CGXDLMSAssociationLogicalName* ln, CGXDLMSIecHdlcSetup* hdlc);
virtual ~DLMS_Server() override;
bool start_server();
void load_password(const std::string &passwd);
public slots:
void handle_recieved_data(const QByteArray &data);
unsigned long sn = 123456;
CGXDLMSData* ldn = AddLogicalDeviceName(GetItems(), sn);
AddFirmwareVersion(GetItems());
AddClock(GetItems());
AddAutoConnect(GetItems());
AddAutoAnswer(GetItems());
//Server must initialize after all objects are added.
int ret = Initialize();
if (ret != DLMS_ERROR_CODE_OK)
{
return res;
}
res=true;
return res;
}
DLMS_SOURCE_DIAGNOSTIC DLMS_Server::ValidateAuthentication(DLMS_AUTHENTICATION authentication, CGXByteBuffer &password)
{
qDebug() << "auth:" << authentication << "password:" << password.ToString().c_str();
if (authentication == DLMS_AUTHENTICATION_NONE)
{
//Uncomment this if authentication is always required.
//return DLMS_SOURCE_DIAGNOSTIC_AUTHENTICATION_MECHANISM_NAME_REQUIRED;
}
if (authentication == DLMS_AUTHENTICATION_LOW)
{
CGXByteBuffer expected;
std::string name = "0.0.40.0.2.255";
if (GetUseLogicalNameReferencing())
{
CGXDLMSAssociationLogicalName* ln =(CGXDLMSAssociationLogicalName*)GetItems().FindByLN(DLMS_OBJECT_TYPE_ASSOCIATION_LOGICAL_NAME, name);
expected = ln->GetSecret();
}
else
{
CGXDLMSAssociationShortName* sn =(CGXDLMSAssociationShortName*)GetItems().FindByLN(DLMS_OBJECT_TYPE_ASSOCIATION_SHORT_NAME, name);
expected = sn->GetSecret();
}
if (expected.GetSize() == password.GetSize() && expected.Compare(password.GetData(), password.GetSize()))
{
return DLMS_SOURCE_DIAGNOSTIC_NONE;
}
return DLMS_SOURCE_DIAGNOSTIC_AUTHENTICATION_FAILURE;
}
// Other authentication levels are check on phase two.
return DLMS_SOURCE_DIAGNOSTIC_NONE;
}
//main.cpp
DLMS_Server server_dlms(new CGXDLMSAssociationLogicalName(), new CGXDLMSIecHdlcSetup());
server_dlms.start_server();
In method void DLMS_Server::create_passwords() i create two instances for low and high passwords.
In ValidateAuthentication() method i check password from 0.0.40.0.2.255 when DLMS_AUTHENTICATION_LOW and it works OK.
But when i connect DLMSDirector with high password - fail. Wrong password.
If i in DLMSDirector password for high authentification set "Gurux" - OK.
What i'm doing wrong?
Thanks!
Hi,
Hi,
A low-level password is sent with AARQ and it's checked in CGXDLMSBase::ValidateAuthentication.
High-level password in send after the server has accepted the connection and reply AARE.
You must define two CGXDLMSAssociationLogicalName objects. One for Low level and one for High level.
For this reason, there is only one secret for each association. You might have multiple association views and each has a different password and access levels and COSEM objects.
Password is tight for the association view.
BR,
Mikko
Ok, thanks for reply!
Ok, thanks for reply!
Is CGXDLMSAssociationLogicalName objects has 0.0.40.0.0.255 name only?
std::string name = "0.0.40.0.0.255"; //"1.1.40.1.3.255";
CGXDLMSAssociationLogicalName *high_pass = new CGXDLMSAssociationLogicalName(name);
CGXByteBuffer passwd;
passwd.AddString("high_passwd");
high_pass->SetSecret(passwd);
m_Settings.GetObjects().push_back(high_pass); // now two objects with 0.0.40.0.0.255 and different passwords
Is it OK?
Hi,
Hi,
0.0.40.0.0.255 is current association. Don't use that. Create 2 instances from CGXDLMSAssociationLogicalName with different logical names something like this:
CGXDLMSAssociationLogicalName *low_pass = new CGXDLMSAssociationLogicalName("0.0.40.0.1.255");
CGXDLMSAssociationLogicalName *high_pass = new CGXDLMSAssociationLogicalName("0.0.40.0.2.255");
BR,
Mikko
Hi!
Hi!
Thanks for you reply!
I made this:
class DLMS_Server : public QObject, public CGXDLMSSecureServer
{
Q_OBJECT
public:
DLMS_Server(CGXDLMSAssociationLogicalName* ln, CGXDLMSIecHdlcSetup* hdlc);
virtual ~DLMS_Server() override;
bool start_server();
void load_password(const std::string &passwd);
public slots:
void handle_recieved_data(const QByteArray &data);
private:
CGXDLMSData* AddLogicalDeviceName(CGXDLMSObjectCollection& items, unsigned long sn);
void AddFirmwareVersion(CGXDLMSObjectCollection& items);
void AddAutoConnect(CGXDLMSObjectCollection& items);
void AddAutoAnswer(CGXDLMSObjectCollection& items);
void create_passwords();
signals:
void data_recieved(const QByteArray &rcvd_data);
void send(const QByteArray &data);
protected:
virtual bool IsTarget(unsigned long int serverAddress, unsigned long clientAddress) override;
virtual DLMS_SOURCE_DIAGNOSTIC ValidateAuthentication(DLMS_AUTHENTICATION authentication, CGXByteBuffer& password) override;
virtual void Connected(CGXDLMSConnectionEventArgs& connectionInfo) override;
virtual void InvalidConnection(CGXDLMSConnectionEventArgs& connectionInfo) override;
virtual void Disconnected(CGXDLMSConnectionEventArgs& connectionInfo) override;
virtual void PreGet(std::vector<CGXDLMSValueEventArg*>& args) override;
virtual void PostGet(std::vector<CGXDLMSValueEventArg*>& args) override;
virtual CGXDLMSObject* FindObject(DLMS_OBJECT_TYPE objectType, int sn, std::string& ln) override;
virtual DLMS_ACCESS_MODE GetAttributeAccess(CGXDLMSValueEventArg* arg) override;
virtual void PreRead(std::vector<CGXDLMSValueEventArg*>& args) override;
virtual void PostRead(std::vector<CGXDLMSValueEventArg*>& args) override;
virtual void PreWrite(std::vector<CGXDLMSValueEventArg*>& args) override;
virtual void PostWrite(std::vector<CGXDLMSValueEventArg*>& args) override;
virtual DLMS_METHOD_ACCESS_MODE GetMethodAccess(CGXDLMSValueEventArg* arg) override;
virtual void PreAction(std::vector<CGXDLMSValueEventArg*>& args) override;
virtual void PostAction(std::vector<CGXDLMSValueEventArg*>& args) override;
};
bool DLMS_Server::start_server()
{
bool res=false;
create_passwords();
unsigned long sn = 123456;
CGXDLMSData* ldn = AddLogicalDeviceName(GetItems(), sn);
AddFirmwareVersion(GetItems());
AddClock(GetItems());
AddAutoConnect(GetItems());
AddAutoAnswer(GetItems());
//Server must initialize after all objects are added.
int ret = Initialize();
if (ret != DLMS_ERROR_CODE_OK)
{
return res;
}
res=true;
return res;
}
void DLMS_Server::create_passwords()
{
CGXDLMSAssociationLogicalName *low_pass = new CGXDLMSAssociationLogicalName("0.0.40.0.2.255");
CGXByteBuffer low_passwd;
low_passwd.AddString("reader");
low_pass->SetSecret(low_passwd);
CGXDLMSAssociationLogicalName *high_pass = new CGXDLMSAssociationLogicalName("1.1.40.1.3.255");
CGXByteBuffer high_passwd;
high_passwd.AddString("high_passwd");
high_pass->SetSecret(high_passwd);
GetItems().push_back(low_pass);
GetItems().push_back(high_pass);
GetCiphering()->SetSecurity(DLMS_SECURITY::DLMS_SECURITY_AUTHENTICATION);
}
DLMS_SOURCE_DIAGNOSTIC DLMS_Server::ValidateAuthentication(DLMS_AUTHENTICATION authentication, CGXByteBuffer &password)
{
qDebug() << "auth:" << authentication << "password:" << password.ToString().c_str();
if (authentication == DLMS_AUTHENTICATION_NONE)
{
//Uncomment this if authentication is always required.
//return DLMS_SOURCE_DIAGNOSTIC_AUTHENTICATION_MECHANISM_NAME_REQUIRED;
}
if (authentication == DLMS_AUTHENTICATION_LOW)
{
CGXByteBuffer expected;
std::string name = "0.0.40.0.2.255";
if (GetUseLogicalNameReferencing())
{
CGXDLMSAssociationLogicalName* ln =(CGXDLMSAssociationLogicalName*)GetItems().FindByLN(DLMS_OBJECT_TYPE_ASSOCIATION_LOGICAL_NAME, name);
expected = ln->GetSecret();
}
else
{
CGXDLMSAssociationShortName* sn =(CGXDLMSAssociationShortName*)GetItems().FindByLN(DLMS_OBJECT_TYPE_ASSOCIATION_SHORT_NAME, name);
expected = sn->GetSecret();
}
if (expected.GetSize() == password.GetSize() && expected.Compare(password.GetData(), password.GetSize()))
{
return DLMS_SOURCE_DIAGNOSTIC_NONE;
}
return DLMS_SOURCE_DIAGNOSTIC_AUTHENTICATION_FAILURE;
}
// Other authentication levels are check on phase two.
return DLMS_SOURCE_DIAGNOSTIC_NONE;
}
//main.cpp
DLMS_Server server_dlms(new CGXDLMSAssociationLogicalName(), new CGXDLMSIecHdlcSetup());
server_dlms.start_server();
In method void DLMS_Server::create_passwords() i create two instances for low and high passwords.
In ValidateAuthentication() method i check password from 0.0.40.0.2.255 when DLMS_AUTHENTICATION_LOW and it works OK.
But when i connect DLMSDirector with high password - fail. Wrong password.
If i in DLMSDirector password for high authentification set "Gurux" - OK.
What i'm doing wrong?
Thanks!