Skip to content

Commit

Permalink
Merge pull request #30 from isi-mfurer/mf-integ
Browse files Browse the repository at this point in the history
Integrate 0.2.7
  • Loading branch information
isi-mfurer authored Mar 30, 2017
2 parents 7591302 + dac5ef0 commit 6e0affa
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 39 deletions.
2 changes: 1 addition & 1 deletion pike/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
'test',
'transport',
]
__version_info__ = (0, 2, 6)
__version_info__ = (0, 2, 7)
__version__ = "{0}.{1}.{2}".format(*__version_info__)
22 changes: 13 additions & 9 deletions pike/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ def __init__(self, client, server, port=445):
self.port = port
self.remote_addr = None
self.local_addr = None
self.verify_signature = True

self.error = None
self.traceback = None
Expand Down Expand Up @@ -613,8 +614,6 @@ def handle_read(self):
self.process_callbacks(EV_RES_PRE_RECV, remaining)
data = array.array('B', self.recv(remaining))
self.process_callbacks(EV_RES_POST_RECV, data)
if not data:
self.handle_error()
self._in_buffer.extend(data)
avail = len(self._in_buffer)
if avail >= 4:
Expand Down Expand Up @@ -791,7 +790,7 @@ def _dispatch_incoming(self, res):
# session setup responses are verified in SessionSetupContext
if not isinstance(smb_res[0], smb2.SessionSetupResponse):
key = self.signing_key(smb_res.session_id)
if key:
if key and self.verify_signature:
smb_res.verify(self.signing_digest(), key)

if smb_res.message_id == smb2.UNSOLICITED_MESSAGE_ID:
Expand Down Expand Up @@ -1823,11 +1822,11 @@ class Open(object):
def __init__(self, tree, smb_res, create_guid=None, prev=None):
object.__init__(self)

create_res = smb_res[0]
self.create_response = smb_res[0]

self.tree = tree
self.file_id = create_res.file_id
self.oplock_level = create_res.oplock_level
self.file_id = self.create_response.file_id
self.oplock_level = self.create_response.oplock_level
self.lease = None
self.durable_timeout = None
self.durable_flags = None
Expand All @@ -1839,12 +1838,17 @@ def __init__(self, tree, smb_res, create_guid=None, prev=None):

if self.oplock_level != smb2.SMB2_OPLOCK_LEVEL_NONE:
if self.oplock_level == smb2.SMB2_OPLOCK_LEVEL_LEASE:
lease_res = filter(lambda c: isinstance(c, smb2.LeaseResponse), create_res)[0]
lease_res = filter(
lambda c: isinstance(c, smb2.LeaseResponse),
self.create_response)[0]
self.lease = tree.session.client.lease(tree, lease_res)
else:
self.oplock_future = tree.session.client.oplock_break_future(self.file_id)
self.oplock_future = tree.session.client.oplock_break_future(
self.file_id)

durable_v2_res = filter(lambda c: isinstance(c, smb2.DurableHandleV2Response), create_res)
durable_v2_res = filter(
lambda c: isinstance(c, smb2.DurableHandleV2Response),
self.create_response)
if durable_v2_res != []:
self.durable_timeout = durable_v2_res[0].timeout
self.durable_flags = durable_v2_res[0].flags
Expand Down
41 changes: 37 additions & 4 deletions pike/nttime.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
# NT time format utility class
#
# Authors: Rafal Szczesniak ([email protected])
# Masen Furer ([email protected])
#

from datetime import datetime, timedelta
import math
import time

_unix_time_offset = 11644473600L
Expand All @@ -52,8 +54,24 @@ def _datetime_to_nt_time(t):
return _unix_time_to_nt_time(_datetime_to_unix_time(t))

def _nt_time_to_unix_time(t):
result = (t / _intervals_per_second) - _unix_time_offset
return result if result >= 0 else 0
"""
Converts "FILETIME" to Python's time library format.
routine borrowed from dist_shell: sys_ex/windows/file.py
"""

# This calculation below might seem rather complex for such time
# conversions, however, due to issues with floating point
# arithmetics precision, this HACK is required to compute the time
# in Python's time library format such that times like "12:59.59.1"
# don't turn into "01:00:00.0" when converted back. This
# calculation below makes use of Python's bigint capabilities.
py_time = (t << 32) / _intervals_per_second
py_time -= _unix_time_offset << 32
py_time_parts = divmod(py_time, 2**32)
py_time = float(py_time_parts[0])
py_time += math.copysign(py_time_parts[1], py_time) / 2**32
return py_time

def GMT_to_datetime(gmt_token):
dt_obj = datetime.strptime(
Expand All @@ -64,6 +82,12 @@ def GMT_to_datetime(gmt_token):
return dt_obj

class NtTime(long):
"""
NtTime may be initialized with any of the following values
* string in ISO format or @GMT- format (timewarp)
* datetime
* int/long indicating number of 100-nanosecond intervals since 1601-01-01
"""
def __new__(cls, value):
if isinstance(value, basestring):
if value.startswith("@GMT-"):
Expand All @@ -73,11 +97,20 @@ def __new__(cls, value):
value = _datetime_to_nt_time(dt)
elif isinstance(value, datetime):
value = _datetime_to_nt_time(value)

return super(NtTime, cls).__new__(cls, long(value))

def __repr__(self):
return str(self)

def __str__(self):
return datetime.fromtimestamp(_nt_time_to_unix_time(self)).strftime("%Y-%m-%d %H:%M:%S")
return self.to_datetime().isoformat(" ")

def to_datetime(self):
return datetime.fromtimestamp(_nt_time_to_unix_time(self))

def to_pytime(self):
return _nt_time_to_unix_time(self)

def to_unixtime(self):
return long(self.to_pytime())
53 changes: 29 additions & 24 deletions pike/smb2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,10 @@ def __init__(self, parent):
self.allocation_size = 0
self.end_of_file = 0
self.file_attributes = 0
self.reserved2 = 0
self.file_id = (0,0)
self.create_contexts_offset = 0
self.create_contexts_length = 0
self._create_contexts = []

def _children(self):
Expand All @@ -1101,14 +1104,14 @@ def _decode(self, cur):
self.end_of_file = cur.decode_uint64le()
self.file_attributes = FileAttributes(cur.decode_uint32le())
# Ignore Reserved2
cur.decode_uint32le()
self.reserved2 = cur.decode_uint32le()
self.file_id = (cur.decode_uint64le(),cur.decode_uint64le())
create_contexts_offset = cur.decode_uint32le()
create_contexts_length = cur.decode_uint32le()
self.create_contexts_offset = cur.decode_uint32le()
self.create_contexts_length = cur.decode_uint32le()

if create_contexts_length:
create_contexts_start = self.parent.start + create_contexts_offset
create_contexts_end = create_contexts_start + create_contexts_length
if self.create_contexts_length > 0:
create_contexts_start = self.parent.start + self.create_contexts_offset
create_contexts_end = create_contexts_start + self.create_contexts_length
next_cur = create_contexts_start

with cur.bounded(create_contexts_start, create_contexts_end):
Expand Down Expand Up @@ -2955,22 +2958,24 @@ class ReadResponse(Response):

def __init__(self, parent):
Response.__init__(self, parent)
self.offset = 0
self.length = 0
self.data = None
self.reserved = 0
self.data_remaining = 0
self.reserved2 = 0

def _decode(self, cur):
offset = cur.decode_uint8le()
# Ignore reserved
cur.decode_uint8le()
length = cur.decode_uint32le()
# Ignore DataRemaining
cur.decode_uint32le()
# Ignore reserved
cur.decode_uint32le()
self.offset = cur.decode_uint8le()
self.reserved = cur.decode_uint8le()
self.length = cur.decode_uint32le()
self.data_remaining = cur.decode_uint32le()
self.reserved2 = cur.decode_uint32le()

# Advance to data
cur.advanceto(self.parent.start + offset)
cur.advanceto(self.parent.start + self.offset)

self.data = cur.decode_bytes(length)
self.data = cur.decode_bytes(self.length)

# Flag constants
class WriteFlags(core.FlagEnum):
Expand Down Expand Up @@ -3033,17 +3038,17 @@ class WriteResponse(Response):
def __init__(self, parent):
Response.__init__(self, parent)
self.count = 0
self.reserved = 0
self.remaining = 0
self.write_channel_info_offset = 0
self.write_channel_info_length = 0

def _decode(self, cur):
# Ignore reserved
cur.decode_uint16le()
self.reserved = cur.decode_uint16le()
self.count = cur.decode_uint32le()
# Ignore Remaining
cur.decode_uint32le()
# Ignore WriteChannelInfoOffset
cur.decode_uint16le()
# Ignore WriteChannelInfoLength
cur.decode_uint16le()
self.remaining = cur.decode_uint32le()
self.write_channel_info_offset = cur.decode_uint16le()
self.write_channel_info_length = cur.decode_uint16le()

class LockFlags(core.FlagEnum):
SMB2_LOCKFLAG_SHARED_LOCK = 0x00000001
Expand Down
4 changes: 3 additions & 1 deletion pike/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ def recv(self, bufsize):
result = ''
try:
result = self.socket.recv(bufsize)
if result == '':
raise EOFError("Remote host closed connection")
except socket.error as err:
# raise non-retryable errors
if err.errno != EAGAIN:
Expand Down Expand Up @@ -377,7 +379,7 @@ class SelectPoller(BasePoller):
def poll(self):
non_connected = [t._fileno for t in self.connections.values() if not t.connected]
readers = self.connections.keys()
writers = non_connected + self.deferred_writers
writers = non_connected + list(self.deferred_writers)
readables, writables, _ = select.select(readers,
writers,
[], 0)
Expand Down

0 comments on commit 6e0affa

Please sign in to comment.