I need to control my xbee using data stored in mysql. Included in the database is the long address of the xbee that is used to identify which xbee I am communicating with on the network.
The following code works perfectly, but in this example I am not retrieving the address from the database. It is just an example of what does work.
addr3 = '\x00\x13\xa2\x00#\n!\x1c'
xbee.send('remote_at',
frame_id='\x01',
dest_addr_long=addr3, #<- this works!
command='D0',
parameter='\x04')
Now as soon as I retrieve \x00\x13\xa2\x00#\n!\x1c from the database (it is stored as a varchar), I get an error saying:
"% (field['name'], field['len']))
ValueError: The data provided for 'dest_addr_long' was not 8 bytes long"
Here is the code (I included the output of the six print lines below to help with debugging)
with con:
cur = con.cursor()
cur.execute("SELECT addrlong, pinStatus FROM deviceStatus WHERE addrlong <>''")
for i in range(cur.rowcount):
row = cur.fetchone()
addr1 = row[0]
Status = row[1]
addr2 = repr(addr1)
addr3 = '\x00\x13\xa2\x00#\n!\x1c'
print "Address1: %s" % addr1
print "Address2: %s" % addr2
print "Address3: %s" % addr3
print "Size of Addr1: %s" % sys.getsizeof(addr1)
print "Size of Addr2: %s" % sys.getsizeof(addr2)
print "Size of Addr3: %s" % sys.getsizeof(addr3)
if Status == 0: #turn off
xbee.send('remote_at',
frame_id='\x01',
dest_addr_long=addr2, #<-problem is here
command='D0',
parameter='\x04')
if Status == 1: #turn on
xbee.send('remote_at',
frame_id='\x01',
dest_addr_long=addr2, #<-problem is here
command='D0',
parameter='\x05')
and the output is
Address1: \x00\x13\xa2\x00#\n!\x1c
Address2: '\\x00\\x13\\xa2\\x00#\\n!\\x1c'
Address3: ?#
!
Size of Addr1: 45
Size of Addr2: 53
Size of Addr3: 29
I've obviously tried simply dest_addr_long=addr1, to no avail.
I have tried many combinations of string manipulation such as adding and removing the parenthesis and dozens of combinations of str and repr but I think I am on the wrong path completely.
I guess what I need to ask is why does
addr3 = '\x00\x13\xa2\x00#\n!\x1c'
print "Address3: %s" % addr3
output
Address3: ?#
!
and once I understand that, then how do I manipulate addr1 from the database to match addr3 because the line dest_addr_long=addr3, works perfectly.
That is an ASCII representation of a byte string. \x00, for example, means 00 ie NUL, and \x13 is ESC; # and ! are literal characters, but \n means a newline character. That's how it is 8 bytes long.
You can get the actual bytes back by decoding with 'string-escape':
>>> s='\x00\x13\xa2\x00#\n!\x1c'
>>> print s.decode('string-escape')
�#
!
(although the result of print will look different on a terminal).
Related
I have the Below python code which I'm using to determine the Linux bond/team status. This code works just fine. I am not good at aligning the output formatting thus getting little hiccup.
I wanted the Printing Format into a Certain format, would appreciate any help on the same.
Below is the code exercise:
#!/usr/bin/python
# Using below file to process the data
# cat /proc/net/bonding/bond0
import sys
import re
def usage():
print '''USAGE: %s [options] [bond_interface]
Options:
--help, -h This usage document
Arguments:
bond_interface The bonding interface to query, eg. 'bond0'. Default is 'bond0'.
''' % (sys.argv[0])
sys.exit(1)
# Parse arguments
try:
iface = sys.argv[1]
if iface in ('--help', '-h'):
usage()
except IndexError:
iface = 'bond0'
# Grab the inf0z from /proc
try:
bond = open('/proc/net/bonding/%s' % iface).read()
except IOError:
print "ERROR: Invalid interface %s\n" % iface
usage()
# Parse and output
active = 'NONE'
Link = 'NONE'
slaves = ''
state = 'OK'
links = ''
bond_status = ''
for line in bond.splitlines():
m = re.match('^Currently Active Slave: (.*)', line)
if m:
active = m.groups()[0]
m = re.match('^Slave Interface: (.*)', line)
if m:
s = m.groups()[0]
slaves += ', %s' % s
m = re.match('^Link Failure Count: (.*)', line)
if m:
l = m.groups()[0]
links += ', %s' % l
m = re.match('^MII Status: (.*)', line)
if m:
s = m.groups()[0]
if slaves == '':
bond_status = s
else:
slaves += ' %s' % s
if s != 'up':
state = 'FAULT'
print "%s %s (%s) %s %s %s" % (iface, state, bond_status, active, slaves, links)
Result:
$ ./bondCheck.py
bond0 OK (up) ens3f0 , ens3f0 up, ens3f1 up , 0, 0
Expected:
bond0: OK (up), Active Slave: ens3f0 , PriSlave: ens3f0(up), SecSlave: ens3f1(up) , LinkFailCountOnPriInt: 0, LinkFailCountOnSecInt: 0
I tried to format in a very basic way as shown below :
print "%s: %s (%s), Active Slave: %s, PriSlave: %s (%s), SecSlave: %s (%s), LinkFailCountOnPriInt: %s, LinkFailCountOnSecInt: %s" % (iface, state, bond_status, active, slaves.split(',')[1].split()[0], slaves.split(',')[1].split()[1], slaves.split(',')[2].split()[0], slaves.split(',')[2].split()[1], links.split(',')[1], links.split(',')[2])
RESULT:
bond0: OK (up), Active Slave: ens3f0, PriSlave: ens3f0 (up), SecSlave: ens3f1 (up), LinkFailCountOnPriInt: 1, LinkFailCountOnSecInt: 1
However, I would suggest to get the values into variables prior and then use them in the print statement so as to avoid "out of index" issues during print() , as in rare cases like bond with only one interface will report indexing error while splitting hence good to get the values in variable and suppress the out of index into exception for those cases.
Do not use the way with "/proc/net/bonding/%s' for querying bond status. It could trigger system panic. Try to use "/sys/class/net/bondX/bonding", it is more safe.
This block of code is loading a cryptoki.so library and retrieving slot info. This is getting a list of objects in slot num. 0. I don't need to access all the keys to perform a few functions, just a specific key pair. Is there a way to get a single desired token by using the label name, object ID, or handle?
pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load(lib)
pkcs11.initialize()
info = pkcs11.getInfo()
i = pkcs11.getSlotInfo(0)
pkcs11.openSession(0)
print "Library manufacturerID: " + info.manufacturerID
slots = pkcs11.getSlotList()
print "Available Slots:", len(slots)
for s in slots:
try:
i = pkcs11.getSlotInfo(s)
print "Slot no:", s
print format_normal % ("slotDescription", i.slotDescription.strip())
print format_normal % ("manufacturerID", i.manufacturerID.strip())
t = pkcs11.getTokenInfo(s)
print "TokenInfo"
print format_normal % ("label", t.label.strip())
print format_normal % ("manufacturerID", t.manufacturerID.strip())
print format_normal % ("model", t.model.strip())
session = pkcs11.openSession(s)
print "Opened session 0x%08X" % session.session.value()
if pin_available:
try:
session.login(pin=pin)
except:
print "login failed, exception:", str(sys.exc_info()[1])
objects = session.findObjects()
print
print "Found %d objects: %s" % (len(objects), [x.value() for x in objects])
The specific script i'm running only has a few commands defined, such as -pin --sign --decrypt --lib do i need to define a common pkcs11-tool such as --init-token or --token-label to pass it as an argument when executing my script ? Or can i directly assign a variable to the desired LabelName within the python script?
So from command line i'm running
$./Test.py --pin=pass and getting the following
Library manufacturerID: Safenet, Inc.
Available Slots: 4
Slot no: 0
slotDescription: ProtectServer K5E:00045
manufacturerID: SafeNet Inc.
TokenInfo
label: CKM
manufacturerID: SafeNet Inc.
model: K5E:PL25
Opened session 0x00000002
Found 52 objects: [5021, 5022, 5014, 5016, 4, 5, 6, 7, 8, 9, 16, 18, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 5313, 5314, 4982, 5325, 5326, 5328, 5329, 5331, 5332, 5335, 5018, 4962, 5020, 4963, 5357, 5358, 5360, 5361, 5363, 5364, 5366, 5367, 5369, 5370, 5372, 5373, 5375, 5376]
I'm ultimately trying to get only one of these objects to run some tests.For instance objectID = 201603040001 contains a private/cert file. I want to specify this particular handle. The actual label is something like 000103...3A0. How can I define this so I don't get the rest of the objects inside the library.
Here's the a list of just a couple of the HSM objects
HANDLE LABEL TYPE OBJECT-ID
5314 00000103000003A1 X509PublicKeyCertificate 201603040001
5313 00000103000003A1 RSAPrivateKey 201603040001
I'm trying to pull just one of the Labels.
Here's the defined usage
def usage():
print "Usage:", sys.argv[0],
print "[-p pin][--pin=pin]",
print "[-s slot][--slot=slot]",
print "[-c lib][--lib=lib]",
print "[-h][--help]",
print "[-o][--opensession]"
try:
opts, args = getopt.getopt(sys.argv[1:], "p:c:Sd:h:s", ["pin=", "lib=", "sign", "decrypt", "help","slot="])
except getopt.GetoptError:
# print help information and exit:
usage()
sys.exit(2)
I'm not aware of how I can add an argument so I can use --sign with just a specific label. End game I want to use $./Test.py --pin=pass --sign --label "00000103000003A4" or by handle $./Test.py --pin=pass --sign --handle=5313
UPDATED from suggested comments below. still having trouble getting attributes for rsa private key and cert. Using the specific token has worked but those objects inside of it are returning bad attribute types
t = pkcs11.getTokenInfo(s)
print "TokenInfo"
if 'CKM' == t.label.decode('ascii').strip():
tokenInfo = pkcs11.getTokenInfo(slot)
if '00000103000003A1' == tokenInfo.label.decode('ascii').strip():
print format_normal % ("label", t.label.strip())
print format_normal % ("manufacturerID", t.manufacturerID.strip())
print format_normal % ("model", t.model.strip())
session = pkcs11.openSession(s)
print("Opened session 0x%08X" % session.session.value())
if pin_available:
try:
if (pin is None) and \
(PyKCS11.CKF_PROTECTED_AUTHENTICATION_PATH & t.flags):
print("\nEnter your PIN for %s on the pinpad" % t.label.strip())
session.login(pin=pin)
except:
print("login failed, exception:", str(sys.exc_info()[1]))
break
objects = session.findObjects([(CKA_LABEL, "00000103000003A4")])
print()
print("Found %d objects: %s" % (len(objects), [x.value() for x in objects]))
all_attributes = list(PyKCS11.CKA.keys())
# only use the integer values and not the strings like 'CKM_RSA_PKCS'
all_attributes.remove(PyKCS11.CKA_PRIVATE_EXPONENT)
all_attributes.remove(PyKCS11.CKA_PRIME_1)
all_attributes.remove(PyKCS11.CKA_PRIME_2)
all_attributes.remove(PyKCS11.CKA_EXPONENT_1)
all_attributes.remove(PyKCS11.CKA_EXPONENT_2)
all_attributes.remove(PyKCS11.CKA_COEFFICIENT)
all_attributes = [e for e in all_attributes if isinstance(e, int)]
n_obj = 1
for o in objects:
print()
print((red + "==================== Object: %d ====================" + normal) % o.value())
n_obj += 1
try:
attributes = session.getAttributeValue(o, all_attributes)
except PyKCS11.PyKCS11Error as e:
continue
attrDict = dict(zip(all_attributes, attributes))
if attrDict[PyKCS11.CKA_CLASS] == PyKCS11.CKO_PRIVATE_KEY \
and attrDict[PyKCS11.CKA_KEY_TYPE] == PyKCS11.CKK_RSA:
m = attrDict[PyKCS11.CKA_MODULUS]
e = attrDict[PyKCS11.CKA_PUBLIC_EXPONENT]
if m and e:
mx = eval(b'0x' + ''.join("%02X" %c for c in m))
ex = eval(b'0x' + ''.join("%02X" %c for c in e))
if sign:
try:
toSign = "12345678901234567890123456789012" # 32 bytes, SHA256 digest
print("* Signing with object 0x%08X following data: %s" % (o.value(), toSign))
signature = session.sign(o, toSign)
sx = eval(b'0x' + ''.join("%02X" % c for c in signature))
print("Signature:")
print(dump(''.join(map(chr, signature))))
if m and e:
print("Verifying using following public key:")
print("Modulus:")
print(dump(''.join(map(chr, m))))
print("Exponent:")
print(dump(''.join(map(chr, e))))
decrypted = pow(sx, ex, mx) # RSA
print("Decrypted:")
d = binascii.unhexlify(hexx(decrypted))
print(dump(d))
if toSign == d[-20:]:
print("*** signature VERIFIED!\n")
the following is what prints. nothing seems to be working using the specific objects, there are no error messages
Slot no: 0
slotDescription: ProtectServer K5E:00045
manufacturerID: SafeNet Inc.
TokenInfo
Opened session 0x00000002
Found 2 objects: [5328, 5329]
==================== Object: 5328 ====================
==================== Object: 5329 ====================
You can work only with one token by checking its label before use, e.g.:
tokenInfo = pkcs11.getTokenInfo(slot)
if 'DesiredTokenLabel' == tokenInfo.label.decode('ascii').strip():
# Start working with this particular token
session = pkcs11.openSession(s)
You can enumerate only specific object using a template argument for the findObjects call, e.g.:
# get objects labelled "PRIV"
objects = session.findObjects([(CKA_LABEL, "PRIV")])
# get all private key objects
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY)])
# get all private key objects labelled "PRIV"
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY),(CKA_LABEL, "PRIV")])
# get all RSA private key objects labelled "PRIV"
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY),(CKA_KEY_TYPE, CKK_RSA),(CKA_LABEL, "PRIV")])
Below is an example code with hard-coded parameters:
from PyKCS11 import *
pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load("your module path...")
slots = pkcs11.getSlotList()
for s in slots:
t = pkcs11.getTokenInfo(s)
if 'CKM' == t.label.decode('ascii').strip():
session = pkcs11.openSession(s)
objects = session.findObjects([(CKA_LABEL, "00000103000003A1")])
print ("Found %d objects: %s" % (len(objects), [x.value() for x in objects]))
Please note that it is Python 3 as I can't use PyKCS11 in Python 2.x right now.
Soma additional (random) notes:
do not rely on handles -- they may (and will) be different for different program runs
your program's command line arguments are up to you -- you must decide yourself if your program needs arguments like --token-label
Disclaimer: I am not that into python so please do validate my thoughts
Good luck!
EDIT(Regarding you recent edit)>
No error is (most probably) shown because the exception is caught and ignored:
try:
attributes = session.getAttributeValue(o, all_attributes)
except PyKCS11.PyKCS11Error as e:
continue
I'm trying to do a SNMP-walk with PySNMP. I wrote the following script, which works, but for every device I "walk" the OIDs of only about ten rows can be resolved to a "real name".
from pysnmp.entity.rfc3413.oneliner import cmdgen
from os.path import exists
import sys
import os
# Turn on debugging
#debug.setLogger(debug.Debug('msgproc', 'secmod'))
# Enter parameters
target_IP = raw_input('Target IP (192.168.13.100): ') or '192.168.13.100'
target_port = raw_input('Target port (161): ') or 161
max_timeout = int(raw_input('Maximum timeout in seconds (1):')) or 1
max_retries = int(raw_input('Maximum number of retries (0):')) or 0
target_file_name = raw_input('Target filename (.txt is added): ') + '.txt'
# Check for already existing file
path = 'walks/'
if not os.path.exists(path):
os.makedirs(path)
if exists(path+target_file_name):
sys.exit("The file '%s' already exists. Try again." % target_file_name)
else:
target_file = open(path+target_file_name, 'w+')
# Initialize counter to zero
counter = 0
# Create command generator
cmdGen = cmdgen.CommandGenerator()
# Get data
errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
cmdgen.CommunityData('public'),
cmdgen.UdpTransportTarget((target_IP, target_port), timeout=max_timeout, retries=max_retries),
'1.3',
lexicographicMode=True,
#maxRows=1000,
ignoreNonIncreasingOid=True,
lookupNames=True
)
# Print errors and values to file
if errorIndication:
print(errorIndication)
else:
# Print error messages
if errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
)
)
else:
# Print values
for varBindTableRow in varBindTable:
for name, val in varBindTableRow:
counter += 1
target_file.write("(%s)\t %s value = \t%s\n" % (counter, name.prettyPrint(), val.prettyPrint()))
# Finish the operation
target_file.close()
print('Writing to %s successful. %d lines have been written' % (target_file_name, counter))
sys.exit(0)
The result is a file with very many rows.
the first entrys look like this:
(1) SNMPv2-MIB::sysDescr."0" value = Hirschmann MAR
(2) SNMPv2-MIB::sysObjectID."0" value = 1.5.6.9.1.1.248.4.10.90
(3) SNMPv2-MIB::sysUpTime."0" value = 2626357
(4) SNMPv2-MIB::sysContact."0" value = Hirschmann Automation and Control GmbH
(5) SNMPv2-MIB::sysName."0" value = mar1030.plc-s7-15000
(6) SNMPv2-MIB::sysLocation."0" value = Hirschmann MAR
(7) SNMPv2-MIB::sysServices."0" value = 2
(8) SNMPv2-MIB::sysORLastChange."0" value = 300
But then the OIDs are not resolved anymore:
(9) SNMPv2-SMI::mib-2."2.1.0" value = 27
(10) SNMPv2-SMI::mib-2."2.2.1.1.1" value = 1
(11) SNMPv2-SMI::mib-2."2.2.1.1.2" value = 2
(12) SNMPv2-SMI::mib-2."2.2.1.1.3" value = 3
.....
What causes this and what can I do about it?
To resolve MIBs with pysnmp you have to load them into pysnmp engine prior to make SNMP queries. Your script performs MIB resolution for SNMPv2-MIB because it is automatically loaded by pysnmp engine.
To make use of plain-text MIBs with pysnmp you have to convert them from plain text form (e.g. ASN.1) into pysnmp format (Python code). You could use the build-pysnmp-mib shell script (based on libsmi) or download and install a pre-compiled pack of common MIBs (pysnmp-mibs Python package).
To load some or all available MIBs you could use the MibVariable.loadMibs(*mibs) method. See this script for example.
I am trying to get some snmp variables from cisco routers using PySNMP but I am getting a hex output using prettyprint instead of the output I get from my normal snmp browser.
I have tried multiple encode (hex, utf-8 and ascii) and without encode, always not what I was expecting.
Any ideas?
Thanks
Start discovery of 10.148.8.15
1.3.6.1.2.1.1.1.0 = 0x436973636f20494f5320536f6674776172652c20494f532d584520536f66747761726520285838365f36345f4c494e55585f494f53442d554e4956455253414c4b392d4d292c2056657273696f6e2031352e3228342953352c2052454c4541534520534f4654574152452028666331290d0a546563686e6963616c20537570706f72743a20687474703a2f2f7777772e636973636f2e636f6d2f74656368737570706f72740d0a436f707972696768742028632920313938362d3230313420627920436973636f2053797374656d732c20496e632e0d0a436f6d70696c6564205475652032352d4665622d31342031313a3336206279206d63707265
result = {'error': 1, 'value': "default"}
cmdGen = cmdgen.CommandGenerator()
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData(community),
cmdgen.UdpTransportTarget((destination, 161)),
cmdgen.MibVariable(oid)
)
# Check for errors and print out results
if errorIndication:
print(errorIndication)
else:
if errorStatus:
result['error'] = 1
# print('%s at %s' % (
# errorStatus.prettyPrint(),
# errorIndex and varBinds[int(errorIndex)-1] or '?'
# )
# )
else:
result['error'] = 0
for name, val in varBinds:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
result['value'] = val.prettyPrint().encode("ascii")
That is because Cisco SNMP Agent reports control characters (\n) what may potentially screw your script's output. There are several ways to handle this:
Pass lookupMib=True like shown in this example. Then pysnmp would try to look up proper output format for this particular OID at MIB. For this to work pysnmp must be able to find and load pysnmp-formatted MIB file(s).
Add some code to trigger a hex string decoder when 0x prefix is seen:
s = '436973636f...06d63707265'
print(''.join([ chr(int(s[x:x+2], 16)) for x in range(0, len(s), 2) ]))
Cisco IOS Software, IOS-XE Software ...Compiled Tue 25-Feb-14 11:36 by mcpre
This is copy of the code in mining the social web book.
I am a new in this field and with redis too. I want to understand what does $ mean in this context. Also the print with %s, What does it mean?
This is the source code below (from: https://github.com/ptwobrussell/Mining-the-Social-Web):
import sys
import redis
from twitter__util import getRedisIdByScreenName
# A pretty-print function for numbers
from twitter__util import pp
r = redis.Redis()
screen_names=['user1','user2']
def friendsFollowersInCommon(screen_names):
r.sinterstore('temp$friends_in_common',
[getRedisIdByScreenName(screen_name, 'friend_ids')
for screen_name in screen_names]
)
r.sinterstore('temp$followers_in_common',
[getRedisIdByScreenName(screen_name, 'follower_ids')
for screen_name in screen_names]
)
print 'Friends in common for %s: %s' % (', '.join(screen_names),
pp(r.scard('temp$friends_in_common')))
print 'Followers in common for %s: %s' % (', '.join(screen_names),
pp(r.scard('temp$followers_in_common')))
# Clean up scratch workspace
r.delete('temp$friends_in_common')
r.delete('temp$followers_in_common')
if __name__ == "__main__":
if len(screen_names) < 2:
print >> sys.stderr, "Please supply at least two screen names."
sys.exit(1)
friendsFollowersInCommon(screen_names[1:])
$ symbol is just a part of key name. It separates name parts. I usually use : for the same purpose (e.g. users:123)
%s part is python's string formatting.