SNMP trap via Indy plus russian letters - c++builder

I send snmp traps from borland c++ application using indy components, (thanks Remy Lebeau for working example Implementing SNMP SendTrap using Indy components) But I have problem with russian letters.
void __fastcall TMainForm::QuickSendTrap()
{
String myEnterprise = _D("1.5.5.5.5.5.5.5");
String eventType = myEnterprise + _D(".1");
String eventDistance = myEnterprise + _D(".2");
String eventTitle1 = myEnterprise + _D(".3");
String eventTitle2 = myEnterprise + _D(".4");
String eventTitle3 = myEnterprise + _D(".5");
TStringList *names = new TStringList;
names->Add(eventType);
names->Add(eventDistance);
names->Add(eventTitle1);
names->Add(eventTitle2);
names->Add(eventTitle3);
TStringList *values = new TStringList;
values->AddObject(_D("ftCritical"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("2.357"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("АБВГД"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("абвгд"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("ОПРСТ"), (TObject*)ASN1_OCTSTR);
TIdSNMP *idSnmp = new TIdSNMP(NULL);
idSnmp->QuickSendTrap(edHost->Text, myEnterprise, _D("public"), 162, 6, 1, names, values);
delete idSnmp;
delete names;
delete values;
}
Instead of russian symbols Wireshark see "?"
0000 30 81 8b 02 01 00 04 06 70 75 62 6c 69 63 a4 7e 0.......public.~
0010 06 07 2d 05 05 05 05 05 05 40 04 c0 a8 64 56 02 ..-......#...dV.
0020 01 06 02 01 01 43 01 00 30 64 30 16 06 08 2d 05 .....C..0d0...-.
0030 05 05 05 05 05 01 04 0a 66 74 43 72 69 74 69 63 ........ftCritic
0040 61 6c 30 11 06 08 2d 05 05 05 05 05 05 02 04 05 al0...-.........
0050 32 2e 33 35 37 30 11 06 08 2d 05 05 05 05 05 05 2.3570...-......
0060 03 04 05 3f 3f 3f 3f 3f 30 11 06 08 2d 05 05 05 ...?????0...-...
0070 05 05 05 04 04 05 3f 3f 3f 3f 3f 30 11 06 08 2d ......?????0...-
0080 05 05 05 05 05 05 05 04 05 3f 3f 3f 3f 3f .........?????
The question is how to encode russian string for snmp properly?

Unfortunately, TIdSNMP does not support non-ASCII data at this time. This is because:
Indy's ASN.1 encode/decode functions have not been made encoding-aware yet so that strings can be converted to/from byte arrays using charsets.
TSNMPInfo encodes PDU data to a String first and then encodes that String to bytes using Indy's 8bit encoding when sending. Thus, any Unicode codepoints greater than #255 will get converted to ?. The Russian characters you are trying to send all have Unicode codepoint values greater than #255. There is no option to specify a different encoding, even though ASN.1 octet strings can technically carry character data encoded in any 8bit charset as long as both parties agree to the charset used.

In order to send cyrillic symbols via Indy's Snmp component I implemented functions which "hide" message in different encoding inside UnicodeString that used by TIdSnmp.
UnicodeString TMainForm::Windows1251ForSnmp(AnsiString str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
unsigned char cc = *(str.c_str()+i);
wchar_t buff = 0;
memcpy((char*)&buff, &cc, 1);
ustr = ustr + buff;
}
return ustr;
}
UnicodeString TMainForm::Utf8ForSnmp(UTF8String str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
unsigned char cc = *(str.c_str()+i);
wchar_t buff = 0;
memcpy((char*)&buff, &cc, 1);
ustr = ustr + buff;
}
return ustr;
}
UnicodeString TMainForm::Utf16ForSnmp(UnicodeString str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
unsigned int cc = *(str.c_str()+i);
byte a = cc / 256;
byte b = cc % 256;
ustr = ustr + char(a);
ustr = ustr + char(b);
}
return ustr;
}
After message conversion by one of these functions I gave result to Indy component TIdSnmp as usually and it will be send without problem.
UnicodeString ustr = Windows1251ForSnmp("Русский");
UTF8String param = _D("Русский");
UnicodeString ustr2 = Utf8ForSnmp(param);
UnicodeString ustr3 = Utf16ForSnmp("Русский");
values->AddObject(ustr, (TObject*)ASN1_OCTSTR);
values->AddObject(ustr2, (TObject*)ASN1_OCTSTR);
values->AddObject(ustr3, (TObject*)ASN1_OCTSTR);
So, on the "other side" I recieved russian messages in Windows1251, Utf8 and Utf16 encoding.

Related

Write python code in delphi AES MODE ECB

I translated two functions in delphi but i don't know if they are right, I need to write the def do_aes_encrypt(key2_t_xor) to know if I am right.
This is what I wrote in delphi:
function key_transform (old_key:string): string;
var
x :integer;
begin
result:='';
for x := 32 downto 0 do
result:= result + chr(ord(old_key[x-1])-( x mod $0C)) ;
end;
function key_xoring ( key2_t :string ; kilo_challenge :string) : string ;
var
i :integer;
begin
result := '';
i:=0 ;
while i <= 28 do begin
result := result + chr(ord(key2_t[i+1]) xor ord(kilo_challenge[3]));
result := result + chr(ord(key2_t[i+2]) xor ord(kilo_challenge[2])) ;
result := result+ chr(ord(key2_t[i+3]) xor ord (kilo_challenge[1])) ;
i := i + 4 ;
end;
end;
This is the original python code:
def key_transform(old_key):
new_key = ''
for x in range(32,0,-1):
new_key += chr(ord(old_key[x-1]) - (x % 0x0C))
return new_key
def key_xoring(key2_t, kilo_challenge):
key2_t_xor = ''
i = 0
while i <= 28:
key2_t_xor += chr(ord(key2_t[i]) ^ ord(kilo_challenge[3]))
key2_t_xor += chr(ord(key2_t[i+1]) ^ ord(kilo_challenge[2]))
key2_t_xor += chr(ord(key2_t[i+2]) ^ ord(kilo_challenge[1]))
key2_t_xor += chr(ord(key2_t[i+3]) ^ ord(kilo_challenge[0]))
i = i + 4
return key2_t_xor
def do_aes_encrypt(key2_t_xor):
plaintext = b''
for k in range(0,16):
plaintext += chr(k)
obj = AES.new(key2_t_xor, AES.MODE_ECB)
return obj.encrypt(plaintext)
/////////////////////////////////////////////////////////////////////////////
{
kilo_challenge = kilo_header[8:12]
chalstring = ":".join("{:02x}".format(ord(k)) for k in kilo_challenge)
key2 = 'qndiakxxuiemdklseqid~a~niq,zjuxl' # if this doesnt work try 'lgowvqnltpvtgogwswqn~n~mtjjjqxro'
kilo_response = do_aes_encrypt(key_xoring(key_transform(key2),kilo_challenge))}
this code is for calculate data line 16 byte to be send as an addition to 32 byte
before
look photo the marked line in blue is what i need to calculate by the 4 byte hex befor marked in porple
and this is the key
key2 = 'qndiakxxuiemdklseqid~a~niq,zjuxl'
in delphi
because python code is working perfect
look to the photo
how it work
this is for lg phones upgrading firmware when i receive the KILOCENT ANSOWER AS THE photo show`s
this below change every time phone connected
||
V
4b 49 4c 4f 43 45 4e 54 ([ac e5 b1 06]) 00 00 00 00 KILOCENT¬å±.....
00 00 00 00 00 00 00 00 30 d4 00 00 b4 b6 b3 b0 ........0Ô..´¶³°
i have to send KILOMETER REQUEST to phone the first and second line is fixed no change but the third i have to change it by the AES ECB MODE encryption look
4b 49 4c 4f 4d 45 54 52 00 00 00 00 02 00 00 00 KILOMETR........
00 00 00 00 10 00 00 00 85 b6 00 00 b4 b6 b3 b0 ........…¶..´¶³°
fc 21 d8 e5 5b aa fd 58 1e 33 58 fd e9 0b 65 38 ü!Øå[ªýX.3Xýé.e8 <==this
and this is old key
key2 = 'qndiakxxuiemdklseqid~a~niq,zjuxl'

Convert Hex to Byte array in Swift

I've a hardware which sends me a hex data and i need to convert it to byte array in swift. Here's example data;
01 01 02 0A 12 14 14 11 10 0D 0B 0A 09 09 08 08 08 07 06 06 06 06 06 06 05 05 06 05 05 04 04 04 04 03 03 03 04
03 03 02 03 02 03 02 02 03 02 02 02 01 02 01 01 01 01 01
Can you help me please?
If you got a bunch of hexes (UInt8), then you can create NSData like this:
NSData(bytes: [0xFF, 0xD9] as [UInt8], length: 2)
use this method it gives Byte Array
func getByte(data:NSData) -> Array<UInt8> {
let count = data.length / sizeof(Int8)
var array = [UInt8](count: count, repeatedValue: 0)
data.getBytes(&array, length:count * sizeof(UInt32))
return array
}

Constant TAO CORBA IOR

How to configure TAO corba server so that IOR string of this server generated from object_to_string is constant?
Each time the IOR string generated from object_to_string changes once server restarts. This is inconvenient since client has to update its cached server IOR string via reloading IOR file or namingservice accessing. As a result, it would be useful if server can generate a constant IOR string, no matter how many times it restarts.
My corba server is based on ACE+TAO and i do remember TAO supports constant IOR string: the IOR string each time it generates are same, and the solution is add some configurations for server. But i could not remember these configurations now.
=============================================
UPDATE:
In ACE_wrappers/TAO/tests/POA/Persistent_ID/server.cpp, i added a new function named testUniqe() which is similiar to creatPOA method. And the update file content is:
void testUniqu(CORBA::ORB_ptr orb_, PortableServer::POA_ptr poa_){
CORBA::PolicyList policies (2);
policies.length (2);
//IOR is the same even it is SYSTEM_ID
policies[0] = poa_->create_id_assignment_policy (PortableServer::USER_ID);
policies[1] = poa_->create_lifespan_policy (PortableServer::PERSISTENT);
PortableServer::POAManager_var poa_manager = poa_->the_POAManager ();
PortableServer::POA_ptr child_poa_ = poa_->create_POA ("childPOA", poa_manager.in (), policies);
// Destroy the policies
for (CORBA::ULong i = 0; i < policies.length (); ++i) {
policies[i]->destroy ();
}
test_i *servant = new test_i (orb_, child_poa_);
PortableServer::ObjectId_var oid = PortableServer::string_to_ObjectId("xushijie");
child_poa_->activate_object_with_id (oid, servant);
PortableServer::ObjectId_var id = poa_->activate_object (servant);
CORBA::Object_var object = poa_->id_to_reference (id.in ());
test_var test = test::_narrow (object.in ());
CORBA::String_var ior = orb_->object_to_string(test.in());
std::cout<<ior.in()<<std::endl;
poa_->the_POAManager()->activate();
orb_->run();
}
int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
try
{
CORBA::ORB_var orb =
CORBA::ORB_init (argc, argv);
int result = parse_args (argc, argv);
CORBA::Object_var obj =
orb->resolve_initial_references ("RootPOA");
PortableServer::POA_var root_poa =
PortableServer::POA::_narrow (obj.in ());
PortableServer::POAManager_var poa_manager =
root_poa->the_POAManager ();
testUniqu(orb.in(), root_poa.in());
orb->destroy ();
}
catch (const CORBA::Exception& ex)
{
ex._tao_print_exception ("Exception caught");
return -1;
}
return 0;
}
The problem is that the output server IORs are still different once restart. I also compared this code to the one in Page 412(Advance Corba Programming), but still fail..
///////////////////////////////////
UPDATE:
With "server -ORBListenEndpoints iiop://:1234 > /tmp/ior1", the generated two IORs are:
IOR:010000000d00000049444c3a746573743a312e300000000001000000000000007400000001010200150000007368696a69652d5468696e6b5061642d543431300000d2041b00000014010f0052535453f60054c6f80c000000000001000000010000000002000000000000000800000001000000004f41540100000018000000010000000100010001000000010001050901010000000000
IOR:010000000d00000049444c3a746573743a312e300000000001000000000000007400000001010200150000007368696a69652d5468696e6b5061642d543431300000d2041b00000014010f0052535468f60054da280a000000000001000000010000000002000000000000000800000001000000004f41540100000018000000010000000100010001000000010001050901010000000000
The result for tao_catior for ior1 and ior2:
ior1:
The Byte Order: Little Endian
The Type Id: "IDL:test:1.0"
Number of Profiles in IOR: 1
Profile number: 1
IIOP Version: 1.2
Host Name: **
Port Number: 1234
Object Key len: 27
Object Key as hex:
14 01 0f 00 52 53 54 53 f6 00 54 c6 f8 0c 00 00
00 00 00 01 00 00 00 01 00 00 00
The Object Key as string:
....RSTS..T................
The component <1> ID is 00 (TAG_ORB_TYPE)
ORB Type: 0x54414f00 (TAO)
The component <2> ID is 11 (TAG_CODE_SETS)
Component length: 24
Component byte order: Little Endian
Native CodeSet for char: Hex - 10001 Description - ISO8859_1
Number of CCS for char 1
Conversion Codesets for char are:
1) Hex - 5010001 Description - UTF-8
Native CodeSet for wchar: Hex - 10109 Description - UTF-16
Number of CCS for wchar 0
ecoding an IOR:
//ior2
The Byte Order: Little Endian
The Type Id: "IDL:test:1.0"
Number of Profiles in IOR: 1
Profile number: 1
IIOP Version: 1.2
Host Name: **
Port Number: 1234
Object Key len: 27
Object Key as hex:
14 01 0f 00 52 53 54 68 f6 00 54 da 28 0a 00 00
00 00 00 01 00 00 00 01 00 00 00
The Object Key as string:
....RSTh..T.(..............
The component <1> ID is 00 (TAG_ORB_TYPE)
ORB Type: 0x54414f00 (TAO)
The component <2> ID is 11 (TAG_CODE_SETS)
Component length: 24
Component byte order: Little Endian
Native CodeSet for char: Hex - 10001 Description - ISO8859_1
Number of CCS for char 1
Conversion Codesets for char are:
1) Hex - 5010001 Description - UTF-8
Native CodeSet for wchar: Hex - 10109 Description - UTF-16
Number of CCS for wchar 0
The diff result is:
< 14 01 0f 00 52 53 54 53 f6 00 54 c6 f8 0c 00 00
---
> 14 01 0f 00 52 53 54 68 f6 00 54 da 28 0a 00 00
19c19
< ....RSTS..T................
---
> ....RSTh..T.(..............
Similar diff result is:
< 14 01 0f 00 52 53 54 62 fd 00 54 2c 9a 0e 00 00
---
> 14 01 0f 00 52 53 54 02 fd 00 54 f9 a9 09 00 00
19c19
< ....RSTb..T,...............
---
> ....RST...T................
The difference is in ObjectKey.
============================================
update:
Instead of using above code, i find a better solution with helper TAO_ORB_Manager which is used NamingService and TAO/examples/Simple. TAO_ORB_Manager encapsulates API and generate persistent IORs, as example code in Simple.cpp:
if (this->orb_manager_.init_child_poa (argc, argv, "child_poa") == -1){
CORBA::String_var str =
this->orb_manager_.activate_under_child_poa (servant_name,
this->servant_.in ());
}
This is some description for TAO_ORB_Manager:
class TAO_UTILS_Export TAO_ORB_Manager
{
/**
* Creates a child poa under the root poa with PERSISTENT and
* USER_ID policies. Call this if you want a #a child_poa with the
* above policies, otherwise call init.
*
* #retval -1 Failure
* #retval 0 Success
*/
int init_child_poa (int &argc,
ACE_TCHAR *argv[],
const char *poa_name,
const char *orb_name = 0);
/**
* Precondition: init_child_poa has been called. Activate <servant>
* using the POA <activate_object_with_id> created from the string
* <object_name>. Users should call this to activate objects under
* the child_poa.
*
* #param object_name String name which will be used to create
* an Object ID for the servant.
* #param servant The servant to activate under the child POA.
*
* #return 0 on failure, a string representation of the object ID if
* successful. Caller of this method is responsible for
* memory deallocation of the string.
*/
char *activate_under_child_poa (const char *object_name,
PortableServer::Servant servant);
...................
}
After build, I can get what i want with -ORBListenEndpoints iiop://localhost:2809 option. Thanks #Johnny Willemsen help
You have to create the POA with a persistent lifespan policy, see ACE_wrappers/TAO/tests/POA/Persistent_ID as part of the TAO distribution.

Delphi StrToInt on Hex String WORD, UShort, 16 Bit hex fails

I currently use.
Here is a few outputs I formatted them they were all together like this.
E14802000003FA00014C0000031501A8
currentAttackCount := StrToInt('$' + Copy(CurHex, 17, 4));
Log('Packet = ' + CurHex + ' Count = ' + IntToStr(currentAttackCount) + ' STR = ' + '$' + Copy(CurHex, 17, 4));
Formatted outputs
Packet = E1 48 02 00 00 03 FA 00 [01 4C] 00 00 03 15 01 A8 [Count = 76] [STR = $014C]
Packet = E1 48 02 00 00 03 FA 00 [01 4D] 00 00 03 15 02 26 [Count = 77] [STR = $014D]
Packet = E1 48 02 00 00 03 FA 00 [01 4F] 00 00 03 15 02 26 [Count = 79] [STR = $014F]
As you can see the STR
output which is STR = $014C
code: 'STR = ' + '$' + Copy(CurHex, 17, 4));
Now if you look at the StrToInt
currentAttackCount := StrToInt('$' + Copy(CurHex, 17, 4));
It's pretty much the same as STR so shouldn't $014C aka 0x014C be represented as 332 instead of 76
The 76 seems to come from the $4C aka 0x4C of the $014C why does it ignore the first 2 Hex Characters
Ah I think I figured it out.
`currentAttackCount: Byte;`
I increased it to
currentAttackCount: Word;
hopefully that would solve the problem.. missed it because it's a global variable and there is soo much code.

Unable to convert NSData to NSString or any other format of informationElementData of CWNetwork

Friends,
It might look like familiar question but i really need help to convert NSData to any other understandable form. Basically i am using CoreWLAN framework and CWNetwork has properly called informationElement and it's data type is NSData. I have tried to convert it to any other readable format but not working. I have tried with all available string encoding. Below is sample code:
- (void) printNSData:(NSData *) dataToPrint forKey:(NSString *) key{
for(int i = 1 ; i < 16 ; i++){
size_t length = [dataToPrint length]+1;
unsigned char aBuffer[length];
[dataToPrint getBytes:aBuffer length:length];
aBuffer[length] = 0;
NSString *content = [[NSString alloc] initWithBytes:aBuffer
length:[dataToPrint length] encoding: i];
NSLog(#"%# : %# ", key,content);
}
/*
NSUTF16BigEndianStringEncoding = 0x90000100,
NSUTF16LittleEndianStringEncoding = 0x94000100,
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100,
NSProprietaryStringEncoding = 65536
*/
NSString *content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF16BigEndianStringEncoding];
NSLog(#"%# : %# ",key, content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF16LittleEndianStringEncoding];
NSLog(#"%# : %# ",key, content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF32StringEncoding];
NSLog(#"%# : %# ", key,content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF32BigEndianStringEncoding];
NSLog(#"%# : %# ", key,content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF32LittleEndianStringEncoding];
NSLog(#"%# : %# ", key,content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSProprietaryStringEncoding];
NSLog(#"%# : %#", key,content);
}
But i am getting either Null or empty response. Please please help.
Regards,
MP
You can't convert arbitrary data into a string. That only works for data that actually represents a string. Which is usually not the case if an API exposes a NSData object.
To get some meaning into the data you have to know what the data represents.
You might be able to get some structure into it by simply looking at it.
If I look at the first few bytes you have posted it looks like the data is well structured and not arbitrary.
The data seams to be split into packets. Each packet starts with a type identifier, which is followed by a $length byte. And then there will be $length bytes of data
The first packet contains the string "SYmantak"
00 08 53 79 6d 61 6e 74 61 6b
^^ Type Identifier
^^ Length
^^^^^^^^^^^^^^^^^^^^^^^ Data. In this case the ASCII string "SYmantak"
If you find a bunch of bytes that all lay between 0x20 and 0x7E you are probably looking at ASCII. That's basically how I figured out the payload of this packet. And because we have 8 bytes that are ASCII the 0x08 in front of the ASCII most likely means 8 bytes of data.
The next packets look like this:
01 08 82 84 0b 16 24 30 48 6c
^^ Type Identifier
^^ Length
^^^^^^^^^^^^^^^^^^^^^^^ Data. But not a ASCII string
03 01 06
2a 01 00
2f 01 00
30 14 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00 00 0f ac 02 0c 00
32 04 0c 12 18 60
2d 1a 6e 18 1b ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
and so on. The general packet structure is quite easy to parse.
Though it will be very hard to turn these bytes into meaningful data. As you can see from the other packets, it's not always as easy as with the first packet that contained ASCII.
But please don't take this quickly reverse engineered structure for granted. I might be completely wrong about the meaning of these fields.
You should try to find the specification of this data. It should be somewhere in the IEEE 802.11 documents.

Resources