How to set DateAndTime for HrSystemDate MIB object using PySNMP - snmp

I can't set the dateAndTime in the standard mib HrSystemDate when using the pysnmp setCmd. I have no problems setting other mibs with octetstring, the only problem is for the date/time setting which is also an octetstring format.
I am not sure what I am missing.
Please advise how to set the date/time via pysnmp setCmd.
I can set the date and time using snmpset in windows command by using this value format '2019-04-04,09:18:32.0,+13:0',
e.g. snmpset -v3 -l authPriv -u snmpAdmin -a SHA -A "password" -x AES -X "password" -n terminal 192.168.0.5 .1.3.6.1.2.1.25.1.2.0 = 2019-04-04,09:18:32.0,+13:0
In ireasoning I can also set it on both format, dateandtime and octetstring
I can't post a picture yet so here's the link.
ireasoning
Snippet
code
def setSnmpV3string(ip, context='terminal', oid='.1.3.6.1.4.1.2509.8.29.2.15.1.2.1',value=''):
errorIndication, errorStatus, errorIndex, varBinds = next(
setCmd(SnmpEngine(),
UsmUserData('snmpAdmin', 'password', 'password',
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb128Protocol),
UdpTransportTarget((ip, 161),),
ContextData(contextName=context),
ObjectType(ObjectIdentity(oid), OctetString(value) ))
)
values = ' = '
if errorIndication:
print(errorIndication)
elif errorStatus:
print('%s at %s' % (errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
else:
for varBind in varBinds:
values = ' = '.join([x.prettyPrint() for x in varBind])
print(values)
return values.split(' = ')[1]
Console output
OctetString(value)
<OctetString value object at 0x615ba90 tagSet <TagSet object at 0x502ca70 tags 0:0:4> subtypeSpec <ConstraintsIntersection object at 0x4fef090 consts <ValueSizeConstraint object at 0x4fe0b70 consts 0, 65535>> encoding iso-8859-1 payload [2019-04-04,10:27:41.0,+12:0]>
errorStatus
<Integer value object at 0x6106970 tagSet <TagSet object at 0x4ff59b0 tags 0:0:2> namedValues <NamedValues object 0x54d36b0 enums noError=0, tooBig=1, noSuchName=...Writable=17, inconsistentName=18> payload [commitFailed]>
I am assuming that pySnmp will need the same input type as iReasoning but I am running out of clue on how to do it. Thanks!

You have to get pysnmp taking the time stamp in human-friendly form and turn it into the series of octets. The format information is contained in the SNMPv2-TC::DateAndTime TEXTUAL-CONVENTION:
DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
For pysnmp to use this you can pass MIB object name (HOST-RESOURCES-MIB::hrSystemDate) instead of OID when preparing SNMP command:
...
ObjectType(ObjectIdentity('HOST-RESOURCES-MIB', 'hrSystemDate'), value)
It works similarly, but in reverse, for SNMP GET.

For a simple solution to the date/time octet string only, I did the following:
I have to use strut pack to convert the date-time string into bytes. something like this, struct.pack('>HBBBBBBcBB', 'yyyy', 'mm','dd','H','M','S',0,b'+',time_offset,0) which will be b'\x07\xe3\x04\x04\x0b\x02!\x07+\r\x00' and can be sent to the above snmpV3string function

Related

Passing xml vallues from windows events as a variables

I appreciate any advice from Powershell wizards out there.
I am trying to setup an email alert that will be triggered on event but having problems passing values as a variable so I can use it later in the body and subject of an email.
I have a few lines of script that pulls an event and stores it as XML but have no luck converting the value to variable to call it later.
$event = wevtutil qe 'Microsoft-Windows-Base-Filtering-Engine-Connections/Operational' /rd:true /c:1 /q:"*[System[(EventID=2000)]]" /f:renderedxml
$xmlresults = [xml]$event
$eventDate = $xmlresults.event.system.timecreated.systemtime
$eventTime = get-date $eventDate -Format ('dd-MM-yyyy hh:mm:ss')
Now when calling $xmlresults.event.eventdata.data I can see all values in a table:
PS C:\Windows\system32> $xmlresults.Event.EventData.Data
Name #text
---- -----
ConnectionId 1324000000003942
MachineAuthenticationMethod 2
RemoteMachineAccount DOMAIN\COMPUTERNAME$
UserAuthenticationMethod 2
RemoteUserAcount DOMAIN\USERNAME$
RemoteIPAddress XXXX:XXXXX:XXXX:XXXX:XXXXX:XXX:XXXX
LocalIPAddress XXXXX:XXXX:XXXX:XXXX::1
TechnologyProviderKey {XXXXXX-XXXX-XXXXX-XXXX-XXXXXXXXXX}
IPsecTrafficMode 1
DHGroup 0
StartTime 2021-05-17T13:52:38.103Z
How do I store the values of RemoteMachineAccount and RemoteUserAccount as a variable so I can call upon it later in the script when composing email alert and log input by simply using something along the lines of $computer and $user?
Any help greatly appreciated.
If you just need a few specifically named properties, you can use the .Where({}) method to filter the nodes returned by the XML provider and grab the text from that specific property:
$RemoteMachineAccount = $xmlresults.Event.EventData.Data.Where({$_.Name -eq 'RemoteMachineAccount'}).InnerText
$RemoteUserAccount = $xmlresults.Event.EventData.Data.Where({$_.Name -eq 'RemoteUserAccount'}).InnerText
If you need to discover/use them dynamically, another option is to convert the node list into a hashtable:
$eventData = #{}
$xmlresults.Event.EventData.Data.ForEach({ $eventData[$_.Name] = $_.InnerText })
At which point you can dereference the individual property values by name:
$eventData["RemoteUserAccount"]

How to configure NiFi InvokeHTTP to post insert in Clickhouse

I've in a NiFi attribute the full INSERT command that works with CURL:
echo "INSERT INTO default.PERFTEST_BUFFER VALUES (1, '2020-04-09 19:06:02', 48.8644, 'A')" \
| curl 'http://xxx.xxx.xxx.xxx:8123/?' --data-binary #-
Insert in Attribut :
INSERT INTO default.PERFTEST_BUFFER
VALUES (1, '2020-04-09 19:06:02', 48.8644, 'A')
I can't figure out what should be all the parameters of the InvokeHTTP processor.
I've used for the first two :
POST
http://xxx.xxx.xxx.xxx:8123/
then I'm lost.
Any idea how to configure it ?
If your query is static you can pass it in the query string in the encoded format:
# GET
curl 'http://xxx.xxx.xxx.xxx:8123/?query=INSERT%20INTO%20default.PERFTEST_BUFFER%20VALUES%20%281%2C%20%272020-04-09%2019%3A06%3A02%27%2C%2048.8644%2C%20%27A%27%29'
# POST
curl -d '' 'http://xxx.xxx.xxx.xxx:8123/?query=INSERT%20INTO%20default.PERFTEST_BUFFER%20VALUES%20%281%2C%20%272020-04-09%2019%3A06%3A02%27%2C%2048.8644%2C%20%27A%27%29'
It needs to pass the required values to just two params: HTTP Method and Remote URL of InvokeHTTP-processor.
The way I made it work thanks to daggett and and example here :
https://github.com/zezutom/NiFiByExample
Use before the InvokeHTTP a processor ReplaceText that replace the flowfile content by the variable "Insert" value that have the full Insert command
Search Value (?s)(^.*$)
Replacement Value ${Insert}
So the flow file content is
INSERT INTO default.PERFTEST_BUFFER VALUES (1, '2020-04-09 19:06:02', 48.8644, 'A')
Follow by a processor InvokeHTTP the following parameters
HTTP Method POST
Remote URL http://xxx.xxx.xxx.xxx:8123/
SSL Context Service No value set
Connection Timeout 5 secs
Read Timeout 15 secs
Include Date Header True
Follow Redirects True
Attributes to Send No value set
Basic Authentication Username No value set
Basic Authentication Password No value set
Proxy Configuration Service No value set
Proxy Host No value set
Proxy Port No value set
Proxy Type http
Proxy Username No value set
Proxy Password No value set
Put Response Body In Attribute No value set
Max Length To Put In Attribute 256
Use Digest Authentication false
Always Output Response true
Add Response Headers to Request false
Content-Type ${mime.type}
Send Message Body true
Use Chunked Encoding false
Penalize on "No Retry" false
Use HTTP ETag false
Maximum ETag Cache Size 10MB

Decryption using AES

Using AES library i am trying to send encrypted data from arduino side to raspberry pi side.The encrypted data that is being printed on the arduino serial monitor is not the same as what is being printed on the raspberry side.
Maybe it is the decoding problem.
Also while decrypting on the raspberry pi side it gives an error saying "the input text must be multiple of 16 in length", when i pad the input( temperature data) with zeroes it still gives the same error message.
I have tried using 'utf-8' and 'iso-8859-1' for decoding but still it doesnt show the same decrypted data.
PYTHON CODE :
from Crypto.Cipher import AES
ser=serial.Serial(' /dev/ttyS0',9600)
st=ser.readline()
st1=st.decode('utf-8')
obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
ciphertext = obj.encrypt(message)
obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
obj2.decrypt(ciphertext)
ARDUINO CODE :
void aesTest (int bits)
{
aes.iv_inc();
byte iv [N_BLOCK] ;
int plainPaddedLength = sizeof(chartemp) + (N_BLOCK - ((sizeof(chartemp)-1) % 16));
byte cipher [plainPaddedLength];
byte check [plainPaddedLength];
aes.set_IV(myIv);
aes.get_IV(iv);
aes.do_aes_encrypt(chartemp,sizeof(chartemp),cipher,key,bits,iv);
aes.set_IV(myIv);
aes.get_IV(iv);
aes.printArray(cipher,(bool)false); //print cipher with padding
String cipher1=String((char*)cipher);
myserial.println(cipher1);
}
HERE chartemp is the temperature that from LM35 IC converted to characted array.
I expect the output on the raspberry pi side to be decrypted properly
Encrypted data is a sequence of pseudo-random bytes. It is not a valid UTF-8 string.
This line is a bit dodgy, but probably technically "works:"
String cipher1=String((char*)cipher);
But this line is incorrect:
st1=st.decode('utf-8')
You can't take random data and decode it as utf-8. You either need to send and receive the data as just a string of bytes, or encode the data into a string, such as with Base64. I suspect you'll be more comfortable with the latter, so look at Base64 in Java and base64 in Python.

Obtain the DFS path of a network location in Python

I want to obtain a ping-like response from a Windows network location that has a Distributed File System architecture e.g.
path = r'\\path\to\some\shared\folder_x'
delay = ping_func(path)
print delay # return response in milliseconds ?
234
Once I have host computer I can easily ping the location.
I can determine the host name for folder_x by looking at the DFS tab in the windows explorer which will look like e.g.
\\hostcomputer.server.uk\shared$\folder_x
How can I do this programmatically in Python?
Since you are using Windows, your always install pywin32 and WMI to get the WMI functions. And below should help you connect to remote DFS. Can't test it as I don't have Windows or DFS
import wmi
c = wmi.WMI (ip, user="user", password="pwd")
for share in c.Win32_Share (Type=0):
print share.Caption, share.Path
for session in share.associators (
wmi_result_class="Win32_ServerConnection"
):
print " ", session.UserName, session.ActiveTime
I've been able to directly call the NetDfsGetInfo function using Python's "ctypes" module.
Some stumbling points I had was understanding the C++/Python interface and variable marshalling - that's what the dfs.argtypes helps with.
The C++ calls return their structures by placing pointers into a buffer you supply to the call. Using byref you are matching the function prototype LPBYTE *Buffer
Processing the output requires defining a "Structure" that matches the function return, in this case DFS_INFO_3. The python "buffer" variable is cast as a pointer to DFS_INFO_3 and ctypes.Structure defines the field names and the types the struct is build from. Then you can access them via attribute name, eg, dfs_info.EntryPath
There was a pointer to a variable-length array (DFS_STORAGE_INFO) returned too, which is able to be accessed via normal Python storage[i] syntax.
import ctypes as ct
from ctypes import wintypes as win
dfs = ct.windll.netapi32.NetDfsGetInfo
dfs.argtypes = [
win.LPWSTR,
win.LPWSTR,
win.LPWSTR,
win.DWORD,
ct.POINTER(win.LPBYTE),
]
class DFS_STORAGE_INFO(ct.Structure):
"""Contains information about a DFS root or link target in a DFS namespace."""
_fields_ = [ # noqa: WPS120
("State", win.ULONG),
("ServerName", win.LPWSTR),
("ShareName", win.LPWSTR),
]
class DFS_INFO_3(ct.Structure): # noqa: WPS114
"""Contains information about a Distributed File System (DFS) root or link."""
_fields_ = [ # noqa: WPS120
("EntryPath", win.LPWSTR),
("Comment", win.LPWSTR),
("State", win.DWORD),
("NumberOfStorages", win.DWORD),
("Storage", ct.POINTER(DFS_STORAGE_INFO)),
]
# ----- Function call -----
buffer = win.LPBYTE() # allocate a LPBYTE type buffer to be used for return pointer
dret = dfs(r"\\something.else\here", None, None, 3, ct.byref(buffer))
# specify that buffer now points to a DFS_INFO_3 struct
dfs_info = ct.cast(buffer, ct.POINTER(DFS_INFO_3)).contents
print(dfs_info.EntryPath)
for i in range(dfs_info.NumberOfStorages):
storage = dfs_info.Storage[i]
print(
f"{storage.ServerName=}",
f"{storage.ShareName=}",
)

Get the text of a RichEdit50W window using TWAPI

I would like to retrieve the text of a specific window. Using
twapi::get_window_text $handle
I get the caption of the window. But how can I get the actual content ? In C++ I was using
EM_GETLINE
How can I use these raw Windows API functions from TCL? For EM_GETLINE for example I have to define the numbers of lines to be fetched and the buffer where they shall be stored.
Could someone show me how to use raw Windows API functions from TCL or point me to a site where I can find examples? Thanks
You can send messages with Twapi's raw-API. I'm not fammilar with the the exact details how this message works, but you know that probably better than me:
package require twapi
proc get_richedit_text {hwnd line} {
set MAX_LEN 0x0100
# You have to lookup this value in the header.
set EM_GETLINE 0x00C4
set bufsize [expr {2 * ($MAX_LEN + 1)}]
# yes, twapi has malloc.
set szbuf [twapi::malloc $bufsize]
# catch everything, so we can free the buffer.
catch {
# set the first word to the size. Whatever a word is.
# I assume it is an int (type 1), but if it is a int64, use type 5, wchar is 3.
# arguments to Twapi_WriteMemory: type pointer(void*) offset bufferlen value
twapi::Twapi_WriteMemory 1 $szbuf 0 $bufsize $MAX_LEN
# send the message. You don't have SendMessage, only SendMessageTimeout
set ressize [twapi::SendMessageTimeout $hwnd $EM_GETLINE $line [twapi::pointer_to_address $szbuf] 0x0008 1000]
return [twapi::Twapi_ReadMemory 3 $szbuf 0 [expr {$ressize * 2}]]
} res opt
# free the buffer.
twapi::free $szbuf
return -options $opt $res
}
I used some internal/undocumented twapi API, the only documentation is twapi's source code.

Resources