diff --git a/README.md b/README.md index 936b350..390fc12 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ Python library to convert Windows [SIDs](https://en.wikipedia.org/wiki/Security_Identifier) +## Install + +E.g: +`python3 setup.py install` + ## Example String input @@ -22,7 +27,7 @@ Base46 input import sid mysid = sid.sid('AQUAAAAAAAUVAAAAoGXPfnhLm1/nfIdwCRwBAA==', sid.SID_BASE64) -print mysid +print(mysid) ``` Output diff --git a/setup.py b/setup.py index a8be58c..f82842b 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -''' +""" The MIT License (MIT) Copyright (c) 2015 Sascha Spreitzer, Red Hat @@ -20,23 +20,23 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -''' +""" from setuptools import setup setup( - name = "sid", - version = "0.2", - author = "Sascha Spreitzer", - author_email = "sspreitz@redhat.com", - description = ("Python library to convert Windows SIDs"), - license = "MIT", - keywords = "windows sid", - url = "https://github.com/sspreitzer/python-sid", - package_dir = {'': 'src'}, - packages = ['sid'], + name="sid", + version="0.3", + author="Sascha Spreitzer", + author_email="sspreitz@redhat.com", + description=("Python library to convert Windows SIDs"), + license="MIT", + keywords="windows sid", + url="https://github.com/sspreitzer/python-sid", + package_dir={"": "src"}, + packages=["sid"], classifiers=[ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", diff --git a/src/sid/__init__.py b/src/sid/__init__.py index 2149a53..58ec992 100644 --- a/src/sid/__init__.py +++ b/src/sid/__init__.py @@ -1,4 +1,4 @@ -''' +""" A Python module to convert Windows SIDs @@ -6,7 +6,7 @@ s = sid.sid('S-1-5-21-2127521184-1604012920-1887927527-72713') print s.base64() -''' +""" from .lib import * diff --git a/src/sid/lib.py b/src/sid/lib.py index f7bbde6..d97bfef 100644 --- a/src/sid/lib.py +++ b/src/sid/lib.py @@ -1,4 +1,4 @@ -'''The lib contains exceptions, constants and the sid class''' +"""The lib contains exceptions, constants and the sid class""" import base64 import struct @@ -11,23 +11,25 @@ class sidException(Exception): - '''Base exception derived from Exception class''' + """Base exception derived from Exception class""" + pass class sidExceptionNoSuchType(sidException): - '''No such type exception. Used when class is not initialized properly.''' + """No such type exception. Used when class is not initialized properly.""" + pass class sid(object): - '''Class to manage Windows SIDs''' + """Class to manage Windows SIDs""" def __init__(self, data, sidtype=SID_STRING): - ''' + """ Initialize class with either a string, binary or base64 sid. For example, Anonymous user is string 'S-1-5-7' - ''' + """ if sidtype == SID_STRING: self._sid = data return @@ -39,120 +41,120 @@ def __init__(self, data, sidtype=SID_STRING): return else: raise sidExceptionNoSuchType() - + def ldap(self): - '''Return ldap filter version of sid''' + """Return ldap filter version of sid""" return self.byteldap(self._sid) - + def binary(self): - '''Return binary version of sid''' + """Return binary version of sid""" return self.byte(self._sid) def base64(self): - '''Return base64 encoded version of binary sid''' + """Return base64 encoded version of binary sid""" return self.byteB64(self._sid) - + def str(self): - '''Return sid as a string''' + """Return sid as a string""" return str(self) - + def __str__(self): - '''sid class can be used as a string''' + """sid class can be used as a string""" return self._sid - + def __repr__(self): - '''Return representation of sid''' - return repr( self._sid ) + """Return representation of sid""" + return repr(self._sid) @classmethod def longToByte(cls, integer, little_endian=True, size=4): - ''' + """ Convert a Python integer into bytes integer - integer to convert little_endian - True (default) or False for little or big endian size - size to be returned, default is 4 (thats 32bit) - ''' + """ if little_endian: - return struct.pack('q', integer)[8-size:] - + return struct.pack(">q", integer)[8 - size :] + @classmethod def byteToLong(cls, byte, little_endian=True): - ''' + """ Convert bytes into a Python integer byte - bytes to convert little_endian - True (default) or False for little or big endian - ''' + """ if len(byte) > 8: - raise Exception('Bytes too long. Needs to be <= 8 or 64bit') + raise Exception("Bytes too long. Needs to be <= 8 or 64bit") else: if little_endian: - a = byte.ljust(8, b'\x00') - return struct.unpack('q', a)[0] - + a = byte.rjust(8, b"\x00") + return struct.unpack(">q", a)[0] + @classmethod def strsid(cls, byte): - ''' + """ Convert bytes into a string SID byte - bytes to convert - ''' - ret = 'S' + """ + ret = "S" sid = [] sid.append(cls.byteToLong(byte[0:1])) - sid.append(cls.byteToLong(byte[2:2+6], False)) + sid.append(cls.byteToLong(byte[2 : 2 + 6], False)) for i in range(8, len(byte), 4): - sid.append(cls.byteToLong(byte[i:i+4])) + sid.append(cls.byteToLong(byte[i : i + 4])) for i in sid: - ret += '-' + str(i) + ret += "-" + str(i) return ret - + @classmethod def byte(cls, strsid): - ''' + """ Convert a SID into bytes strdsid - SID to convert into bytes - ''' - sid = str.split(strsid, '-') + """ + sid = str.split(strsid, "-") ret = bytearray() - sid.remove('S') + sid.remove("S") for i in range(len(sid)): sid[i] = int(sid[i]) - sid.insert(1, len(sid)-2) + sid.insert(1, len(sid) - 2) ret += cls.longToByte(sid[0], size=1) ret += cls.longToByte(sid[1], size=1) ret += cls.longToByte(sid[2], False, 6) for i in range(3, len(sid)): ret += cls.longToByte(sid[i]) return ret - + @classmethod def byteldap(cls, strsid): - ''' + """ Encode a sid into AD ldap search form strsid - SID to encode - ''' - ret = '' - a = binascii.hexlify(cls.byte(strsid)).decode('utf-8') + """ + ret = "" + a = binascii.hexlify(cls.byte(strsid)).decode("utf-8") for i in range(0, len(a), 2): - ret += '\\' + a[i:i+2] + ret += "\\" + a[i : i + 2] return ret - + @classmethod def byteB64(cls, strsid): - ''' + """ Encode a sid into base64 strsid - SID to encode - ''' + """ return base64.b64encode(cls.byte(strsid)) - + @classmethod def b64Strsid(cls, data): - ''' + """ Decode a base64 SID into string data - base64 encoded sid - ''' + """ return cls.strsid(base64.b64decode(data)) diff --git a/src/sid/test_lib.py b/src/sid/test_lib.py index 41db64a..fb3d5f4 100644 --- a/src/sid/test_lib.py +++ b/src/sid/test_lib.py @@ -5,14 +5,15 @@ class Testsid(unittest.TestCase): """Class for testing sid""" - sid_null = 'S-1-0-0' - sid_sample = 'S-1-5-21-2127521184-1604012920-1887927527-72713' - sid_null_bin = bytearray( - b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + + sid_null = "S-1-0-0" + sid_sample = "S-1-5-21-2127521184-1604012920-1887927527-72713" + sid_null_bin = bytearray(b"\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") sid_sample_bin = bytearray( - b'\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xa0e\xcf~xK\x9b_\xe7|\x87p\t\x1c\x01\x00') - sid_null_b64 = b'AQEAAAAAAAAAAAAA' - sid_sample_b64 = b'AQUAAAAAAAUVAAAAoGXPfnhLm1/nfIdwCRwBAA==' + b"\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xa0e\xcf~xK\x9b_\xe7|\x87p\t\x1c\x01\x00" + ) + sid_null_b64 = b"AQEAAAAAAAAAAAAA" + sid_sample_b64 = b"AQUAAAAAAAUVAAAAoGXPfnhLm1/nfIdwCRwBAA==" def test_init_string(self): """Test creating sids from strings""" @@ -21,37 +22,35 @@ def test_init_string(self): def test_init_base64(self): """Test creating sids from base64""" - self.assertEqual(self.sid_null, str( - sid.sid(self.sid_null_b64, sid.SID_BASE64))) - self.assertEqual(self.sid_sample, str( - sid.sid(self.sid_sample_b64, sid.SID_BASE64))) + self.assertEqual(self.sid_null, str(sid.sid(self.sid_null_b64, sid.SID_BASE64))) + self.assertEqual( + self.sid_sample, str(sid.sid(self.sid_sample_b64, sid.SID_BASE64)) + ) def test_init_binary(self): """Test creating sids from binary""" - self.assertEqual(self.sid_null, str( - sid.sid(self.sid_null_bin, sid.SID_BINARY))) - self.assertEqual(self.sid_sample, str( - sid.sid(self.sid_sample_bin, sid.SID_BINARY))) + self.assertEqual(self.sid_null, str(sid.sid(self.sid_null_bin, sid.SID_BINARY))) + self.assertEqual( + self.sid_sample, str(sid.sid(self.sid_sample_bin, sid.SID_BINARY)) + ) def test_ldap(self): """Test ldap filter form of sid""" - sid_null_ldap = '\\01\\01\\00\\00\\00\\00\\00\\00\\00\\00\\00\\00' - sid_sample_ldap = '\\01\\05\\00\\00\\00\\00\\00\\05\\15\\00\\00\\00\\a0\\65\\cf\\7e\\78\\4b\\9b\\5f\\e7\\7c\\87\\70\\09\\1c\\01\\00' + sid_null_ldap = "\\01\\01\\00\\00\\00\\00\\00\\00\\00\\00\\00\\00" + sid_sample_ldap = "\\01\\05\\00\\00\\00\\00\\00\\05\\15\\00\\00\\00\\a0\\65\\cf\\7e\\78\\4b\\9b\\5f\\e7\\7c\\87\\70\\09\\1c\\01\\00" self.assertEqual(sid_null_ldap, sid.sid(self.sid_null).ldap()) self.assertEqual(sid_sample_ldap, sid.sid(self.sid_sample).ldap()) def test_binary(self): """Test binary form of sid""" self.assertEqual(self.sid_null_bin, sid.sid(self.sid_null).binary()) - self.assertEqual(self.sid_sample_bin, - sid.sid(self.sid_sample).binary()) + self.assertEqual(self.sid_sample_bin, sid.sid(self.sid_sample).binary()) def test_base64(self): """Test base64 form of sid""" self.assertEqual(self.sid_null_b64, sid.sid(self.sid_null).base64()) - self.assertEqual(self.sid_sample_b64, - sid.sid(self.sid_sample).base64()) + self.assertEqual(self.sid_sample_b64, sid.sid(self.sid_sample).base64()) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main()