Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update README.md - Fix Base46 input example #12

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -22,7 +27,7 @@ Base46 input
import sid

mysid = sid.sid('AQUAAAAAAAUVAAAAoGXPfnhLm1/nfIdwCRwBAA==', sid.SID_BASE64)
print mysid
print(mysid)
```

Output
Expand Down
24 changes: 12 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'''
"""
The MIT License (MIT)

Copyright (c) 2015 Sascha Spreitzer, Red Hat
Expand All @@ -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 = "[email protected]",
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="[email protected]",
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",
Expand Down
4 changes: 2 additions & 2 deletions src/sid/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'''
"""
A Python module to convert Windows SIDs


import sid

s = sid.sid('S-1-5-21-2127521184-1604012920-1887927527-72713')
print s.base64()
'''
"""


from .lib import *
112 changes: 57 additions & 55 deletions src/sid/lib.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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)[0:size]
return struct.pack("<q", integer)[0:size]
else:
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.ljust(8, b"\x00")
return struct.unpack("<q", a)[0]
else:
a = byte.rjust(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))
43 changes: 21 additions & 22 deletions src/sid/test_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""
Expand All @@ -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()