diff --git a/pyghmi/ipmi/command.py b/pyghmi/ipmi/command.py index 6f217902..34fb358f 100644 --- a/pyghmi/ipmi/command.py +++ b/pyghmi/ipmi/command.py @@ -29,6 +29,11 @@ import pyghmi.ipmi.sdr as sdr import socket import struct +try: + xrange +except NameError: + xrange = range + boot_devices = { 'net': 4, @@ -1487,7 +1492,7 @@ class Command(object): data = response['data'] if len(data) == 16: # convert int array to string - n = ''.join(chr(data[i]) for i in range(0, len(data))) + n = ''.join(chr(data[i]) for i in xrange(0, len(data))) # remove padded \x00 chars n = n.rstrip("\x00") if len(n) > 0: @@ -1584,7 +1589,7 @@ class Command(object): channel = self.get_network_channel() uid_list = [] max_ids = self.get_channel_max_user_count(channel) - for uid in range(1, max_ids): + for uid in xrange(1, max_ids): if name == self.get_user_name(uid=uid): uid_list.append(uid) return uid_list @@ -1609,7 +1614,7 @@ class Command(object): channel = self.get_network_channel() names = {} max_ids = self.get_channel_max_user_count(channel) - for uid in range(1, max_ids+1): + for uid in xrange(1, max_ids+1): name = self.get_user_name(uid=uid) if name is not None: names[uid] = self.get_user(uid=uid, channel=channel) diff --git a/pyghmi/ipmi/events.py b/pyghmi/ipmi/events.py index d8cfb9d7..01a242c2 100644 --- a/pyghmi/ipmi/events.py +++ b/pyghmi/ipmi/events.py @@ -22,6 +22,11 @@ import pyghmi.ipmi.private.constants as ipmiconst import struct import time +try: + xrange +except NameError: + xrange = range + psucfg_errors = { 0: 'Vendor mismatch', diff --git a/pyghmi/ipmi/oem/lenovo/handler.py b/pyghmi/ipmi/oem/lenovo/handler.py index de4fcc38..6ef003cb 100755 --- a/pyghmi/ipmi/oem/lenovo/handler.py +++ b/pyghmi/ipmi/oem/lenovo/handler.py @@ -44,6 +44,10 @@ import pyghmi.util.webclient as wc import socket import struct import weakref +try: + xrange +except NameError: + xrange = range inventory.register_inventory_category(cpu) inventory.register_inventory_category(dimm) @@ -367,7 +371,7 @@ class OEMHandler(generic.OEMHandler): ) except Exception: # If we can't parse an inventory category, ignore it - print traceback.print_exc() + print(traceback.print_exc()) continue for item in items: @@ -377,7 +381,7 @@ class OEMHandler(generic.OEMHandler): self.oem_inventory_info[key] = item except Exception: # If we can't parse an inventory item, ignore it - print traceback.print_exc() + print(traceback.print_exc()) continue def get_leds(self): @@ -522,7 +526,7 @@ class OEMHandler(generic.OEMHandler): def get_oem_domain_name(self): if self.has_tsm: name = '' - for i in range(1, 5): + for i in xrange(1, 5): rsp = self.ipmicmd.xraw_command(netfn=0x32, command=0x6b, data=(4, i)) name += rsp['data'][:] @@ -536,7 +540,7 @@ class OEMHandler(generic.OEMHandler): # set the domain name content name = name.ljust(256, "\x00") - for i in range(0, 4): + for i in xrange(0, 4): data = [4, i+1] offset = i*64 data.extend([ord(x) for x in name[offset:offset+64]]) diff --git a/pyghmi/ipmi/oem/lenovo/nextscale.py b/pyghmi/ipmi/oem/lenovo/nextscale.py index 28ba747e..44ca16d9 100644 --- a/pyghmi/ipmi/oem/lenovo/nextscale.py +++ b/pyghmi/ipmi/oem/lenovo/nextscale.py @@ -18,6 +18,11 @@ import pyghmi.constants as pygconst import pyghmi.ipmi.sdr as sdr import struct +try: + xrange +except NameError: + xrange = range + def fpc_read_ac_input(ipmicmd): rsp = ipmicmd.xraw_command(netfn=0x32, command=0x90, data=(1,)) diff --git a/pyghmi/ipmi/private/serversession.py b/pyghmi/ipmi/private/serversession.py index 3ea6568d..f745b2f0 100644 --- a/pyghmi/ipmi/private/serversession.py +++ b/pyghmi/ipmi/private/serversession.py @@ -37,23 +37,23 @@ class ServerSession(ipmisession.Session): return object.__new__(cls) def create_open_session_response(self, request): - clienttag = ord(request[0]) + clienttag = request[0] # role = request[1] - self.clientsessionid = list(struct.unpack('4B', request[4:8])) + self.clientsessionid = request[4:8] # TODO(jbjohnso): intelligently handle integrity/auth/conf #for now, forcibly do cipher suite 3 - self.managedsessionid = list(struct.unpack('4B', os.urandom(4))) + self.managedsessionid = os.urandom(4) #table 13-17, 1 for now (hmac-sha1), 3 should also be supported #table 13-18, integrity, 1 for now is hmac-sha1-96, 4 is sha256 #confidentiality: 1 is aes-cbc-128, the only one self.privlevel = 4 - response = ([clienttag, 0, self.privlevel, 0] + + response = (bytearray([clienttag, 0, self.privlevel, 0]) + self.clientsessionid + self.managedsessionid + - [ + bytearray([ 0, 0, 0, 8, 1, 0, 0, 0, # auth 1, 0, 0, 8, 1, 0, 0, 0, # integrity 2, 0, 0, 8, 1, 0, 0, 0, # privacy - ]) + ])) return response def __init__(self, authdata, kg, clientaddr, netsocket, request, uuid, @@ -77,7 +77,7 @@ class ServerSession(ipmisession.Session): self.sockaddr = clientaddr self.pktqueue = collections.deque([]) ipmisession.Session.bmc_handlers[clientaddr] = self - response = self.create_open_session_response(request) + response = self.create_open_session_response(bytearray(request)) self.send_payload(response, constants.payload_types['rmcpplusopenresponse'], retry=False) @@ -98,31 +98,28 @@ class ServerSession(ipmisession.Session): if namepresent == 0: #ignore null username for now return - usernamebytes = data[28:] - self.username = struct.pack('%dB' % len(usernamebytes), *usernamebytes) - if self.username not in self.authdata: + self.username = bytes(data[28:]) + if self.username.decode('utf-8') not in self.authdata: # don't think about invalid usernames for now return uuidbytes = self.uuid.bytes - uuidbytes = list(struct.unpack('%dB' % len(uuidbytes), uuidbytes)) self.uuiddata = uuidbytes - self.Rc = list(struct.unpack('16B', os.urandom(16))) + self.Rc = os.urandom(16) hmacdata = (self.clientsessionid + self.managedsessionid + self.Rm + self.Rc + uuidbytes + - [self.rolem, len(self.username)]) - hmacdata = struct.pack('%dB' % len(hmacdata), *hmacdata) + bytearray([self.rolem, len(self.username)])) hmacdata += self.username - self.kuid = self.authdata[self.username] + self.kuid = self.authdata[self.username.decode('utf-8')].encode( + 'utf-8') if self.kg is None: self.kg = self.kuid authcode = hmac.new( self.kuid, hmacdata, hashlib.sha1).digest() - authcode = list(struct.unpack('%dB' % len(authcode), authcode)) # regretably, ipmi mandates the server send out an hmac first # akin to a leak of /etc/shadow, not too worrisome if the secret # is complex, but terrible for most likely passwords selected by # a human - newmessage = ([clienttag, 0, 0, 0] + self.clientsessionid + + newmessage = (bytearray([clienttag, 0, 0, 0]) + self.clientsessionid + self.Rc + uuidbytes + authcode) self.send_payload(newmessage, constants.payload_types['rakp2'], retry=False) @@ -136,17 +133,17 @@ class ServerSession(ipmisession.Session): # respond correctly a TODO(jjohnson2), since Kg being used # yet incorrect is a scenario why rakp3 could be bad # even if rakp2 was good - RmRc = struct.pack('B' * len(self.Rm + self.Rc), *(self.Rm + self.Rc)) + RmRc = self.Rm + self.Rc self.sik = hmac.new(self.kg, RmRc + struct.pack("2B", self.rolem, len(self.username)) + self.username, hashlib.sha1).digest() - self.k1 = hmac.new(self.sik, '\x01' * 20, hashlib.sha1).digest() - self.k2 = hmac.new(self.sik, '\x02' * 20, hashlib.sha1).digest() + self.k1 = hmac.new(self.sik, b'\x01' * 20, hashlib.sha1).digest() + self.k2 = hmac.new(self.sik, b'\x02' * 20, hashlib.sha1).digest() self.aeskey = self.k2[0:16] - hmacdata = struct.pack('B' * len(self.Rc), *self.Rc) +\ - struct.pack("4B", *self.clientsessionid) +\ + hmacdata = self.Rc +\ + self.clientsessionid +\ struct.pack("2B", self.rolem, len(self.username)) +\ self.username @@ -159,9 +156,7 @@ class ServerSession(ipmisession.Session): if data[1] != 0: # client did not like our response, so ignore the rakp3 return - self.localsid = struct.unpack('> 2 mylun = netfnlun & 0b11 if netfn == 6: # application request - if data[19] == '\x38': # cmd = get channel auth capabilities + if data[19] == 0x38: # cmd = get channel auth capabilities verchannel, level = struct.unpack('2B', data[20:22]) version = verchannel & 0b10000000 if version != 0b10000000: diff --git a/pyghmi/ipmi/private/session.py b/pyghmi/ipmi/private/session.py index e5aa6e5e..5c639a51 100644 --- a/pyghmi/ipmi/private/session.py +++ b/pyghmi/ipmi/private/session.py @@ -33,6 +33,15 @@ from Crypto.Cipher import AES import pyghmi.exceptions as exc from pyghmi.ipmi.private import constants +try: + dict.iteritems + + def dictitems(d): + return d.iteritems() +except AttributeError: + def dictitems(d): + return d.items() + initialtimeout = 0.5 # minimum timeout for first packet to retry in any given # session. This will be randomized to stagger out retries @@ -63,7 +72,7 @@ def define_worker(): Session._cleanup() self.running = False iosockets[0].sendto( - '\x01', (myself, iosockets[0].getsockname()[1])) + b'\x01', (myself, iosockets[0].getsockname()[1])) super(_IOWorker, self).join() def run(self): @@ -139,7 +148,7 @@ def _io_wait(timeout, myaddr=None, evq=None): # it piggy back on the select() in the io thread, which is a truly # lazy wait even with eventlet involvement if deadline < selectdeadline: - iosockets[0].sendto('\x01', (myself, iosockets[0].getsockname()[1])) + iosockets[0].sendto(b'\x01', (myself, iosockets[0].getsockname()[1])) evt.wait() @@ -308,7 +317,8 @@ class Session(object): @classmethod def _cleanup(cls): - for session in cls.bmc_handlers.itervalues(): + for sesskey in cls.bmc_handlers: + session = cls.bmc_handlers[sesskey] session.cleaningup = True session.logout() @@ -324,7 +334,7 @@ class Session(object): # slots to be recycled sorted_candidates = None if server is None: - sorted_candidates = sorted(cls.socketpool.iteritems(), + sorted_candidates = sorted(dictitems(cls.socketpool), key=operator.itemgetter(1)) if sorted_candidates and sorted_candidates[0][1] < MAX_BMCS_PER_SOCKET: cls.socketpool[sorted_candidates[0][0]] += 1 @@ -357,7 +367,7 @@ class Session(object): # be there try: iosockets[0].sendto( - '\x01', ('::1', iosockets[0].getsockname()[1])) + b'\x01', ('::1', iosockets[0].getsockname()[1])) myself = '::1' except socket.error: # AF_INET6, but no '::1', try the AF_INET6 version of 127 @@ -1034,7 +1044,7 @@ class Session(object): # no more time than that, so that whatever part(ies) need to service in # a deadline, will be honored if timeout != 0: - for session, parms in cls.waiting_sessions.iteritems(): + for session, parms in dictitems(cls.waiting_sessions): if parms['timeout'] <= curtime: timeout = 0 # exit after one guaranteed pass break @@ -1042,7 +1052,7 @@ class Session(object): timeout < parms['timeout'] - curtime): continue # timeout smaller than the current session needs timeout = parms['timeout'] - curtime # set new timeout value - for session, parms in cls.keepalive_sessions.iteritems(): + for session, parms in dictitems(cls.keepalive_sessions): if parms['timeout'] <= curtime: timeout = 0 break @@ -1069,7 +1079,7 @@ class Session(object): relsession.process_pktqueue() sessionstodel = [] sessionstokeepalive = [] - for session, parms in cls.keepalive_sessions.iteritems(): + for session, parms in dictitems(cls.keepalive_sessions): # if the session is busy inside a command, defer invoking keepalive # until incommand is no longer the case if parms['timeout'] < curtime and not session._isincommand(): @@ -1078,7 +1088,7 @@ class Session(object): sessionstokeepalive.append(session) for session in sessionstokeepalive: session._keepalive() - for session, parms in cls.waiting_sessions.iteritems(): + for session, parms in dictitems(cls.waiting_sessions): if parms['timeout'] < curtime: # timeout has expired, time to # give up on it and trigger timeout # response in the respective @@ -1151,8 +1161,9 @@ class Session(object): def process_pktqueue(self): while self.pktqueue: - pkt = self.pktqueue.popleft() - if not pkt[0][0] == '\x06' and pkt[0][2:4] == '\xff\x07': + pkt = list(self.pktqueue.popleft()) + pkt[0] = bytearray(pkt[0]) + if not (pkt[0][0] == 6 and pkt[0][2:4] == b'\xff\x07'): continue if pkt[1] in self.bmc_handlers: self._handle_ipmi_packet(pkt[0], sockaddr=pkt[1]) @@ -1180,24 +1191,24 @@ class Session(object): return # here, we might have sent an ipv4 and ipv6 packet to kick # things off ignore the second reply since we have one # satisfactory answer - if data[4] in ('\x00', '\x02'): # This is an ipmi 1.5 paylod - remsequencenumber = struct.unpack('