mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
142 lines
4.7 KiB
Python
142 lines
4.7 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
|
|
See the file 'LICENSE' for copying permission
|
|
"""
|
|
|
|
# Minimal, dependency-free ASN.1 DER codec covering exactly the constructs Kerberos (RFC 4120) uses:
|
|
# INTEGER, OCTET STRING, GeneralString, GeneralizedTime, BIT STRING, SEQUENCE / SEQUENCE OF, EXPLICIT
|
|
# context tags [n] and [APPLICATION n]. All Kerberos tag numbers are <= 30, so only the low-tag-number
|
|
# form is needed. Encoders return bytes; decoders accept bytes/bytearray. Python 2.7 / 3.x.
|
|
|
|
# universal tag bytes
|
|
INTEGER = 0x02
|
|
BIT_STRING = 0x03
|
|
OCTET_STRING = 0x04
|
|
GENERAL_STRING = 0x1b
|
|
GENERALIZED_TIME = 0x18
|
|
SEQUENCE = 0x30 # 0x10 | constructed(0x20)
|
|
|
|
def _encodeLength(length):
|
|
if length < 0x80:
|
|
return bytearray([length])
|
|
out = bytearray()
|
|
while length:
|
|
out.insert(0, length & 0xff)
|
|
length >>= 8
|
|
return bytearray([0x80 | len(out)]) + out
|
|
|
|
def _tlv(tag, value):
|
|
value = bytearray(value)
|
|
return bytes(bytearray([tag]) + _encodeLength(len(value)) + value)
|
|
|
|
# ---- context / application tags (EXPLICIT) --------------------------------------------------------
|
|
def contextTag(number):
|
|
return 0x80 | 0x20 | number # context-specific, constructed
|
|
|
|
def applicationTag(number):
|
|
return 0x40 | 0x20 | number # application, constructed
|
|
|
|
def tagged(number, innerTLV):
|
|
"""EXPLICIT [n] wrapper around an already-encoded inner TLV."""
|
|
|
|
return _tlv(contextTag(number), innerTLV)
|
|
|
|
def application(number, innerTLV):
|
|
"""[APPLICATION n] wrapper around an already-encoded inner TLV."""
|
|
|
|
return _tlv(applicationTag(number), innerTLV)
|
|
|
|
# ---- primitive encoders ---------------------------------------------------------------------------
|
|
def integer(value):
|
|
content = bytearray()
|
|
if value == 0:
|
|
content = bytearray([0])
|
|
elif value > 0:
|
|
n = value
|
|
while n:
|
|
content.insert(0, n & 0xff)
|
|
n >>= 8
|
|
if content[0] & 0x80: # keep the sign bit clear for a positive value
|
|
content.insert(0, 0x00)
|
|
else:
|
|
n = value
|
|
while True:
|
|
content.insert(0, n & 0xff)
|
|
n >>= 8
|
|
if n == -1 and (content[0] & 0x80):
|
|
break
|
|
return _tlv(INTEGER, content)
|
|
|
|
def octetString(value):
|
|
return _tlv(OCTET_STRING, value)
|
|
|
|
def generalString(value):
|
|
return _tlv(GENERAL_STRING, value if isinstance(value, bytes) else value.encode("utf-8"))
|
|
|
|
def generalizedTime(value):
|
|
"""'value' is a 'YYYYMMDDHHMMSSZ' UTC string."""
|
|
|
|
return _tlv(GENERALIZED_TIME, value if isinstance(value, bytes) else value.encode("ascii"))
|
|
|
|
def bitString(value, unusedBits=0):
|
|
return _tlv(BIT_STRING, bytearray([unusedBits]) + bytearray(value))
|
|
|
|
def sequence(*elements):
|
|
return _tlv(SEQUENCE, b"".join(bytes(_) for _ in elements))
|
|
|
|
def sequenceOf(elements):
|
|
return _tlv(SEQUENCE, b"".join(bytes(_) for _ in elements))
|
|
|
|
# ---- decoding -------------------------------------------------------------------------------------
|
|
def peel(data, offset=0):
|
|
"""Parse one TLV at 'offset'; return (tag, content_bytearray, next_offset). Raises ValueError on
|
|
truncated or indefinite-length input (the data may come from the network, so fail predictably)."""
|
|
|
|
data = bytearray(data)
|
|
if offset + 2 > len(data):
|
|
raise ValueError("truncated DER header")
|
|
tag = data[offset]
|
|
first = data[offset + 1]
|
|
offset += 2
|
|
if first < 0x80:
|
|
length = first
|
|
elif first == 0x80:
|
|
raise ValueError("indefinite-length DER is not permitted")
|
|
else:
|
|
count = first & 0x7f
|
|
if offset + count > len(data):
|
|
raise ValueError("truncated DER length")
|
|
length = 0
|
|
for _ in range(count):
|
|
length = (length << 8) | data[offset]
|
|
offset += 1
|
|
if offset + length > len(data):
|
|
raise ValueError("truncated DER content")
|
|
return tag, data[offset:offset + length], offset + length
|
|
|
|
def children(content):
|
|
"""Iterate the TLVs contained in a constructed value; yields (tag, content_bytearray)."""
|
|
|
|
content = bytearray(content)
|
|
offset = 0
|
|
out = []
|
|
while offset < len(content):
|
|
tag, inner, offset = peel(content, offset)
|
|
out.append((tag, inner))
|
|
return out
|
|
|
|
def decodeInteger(content):
|
|
content = bytearray(content)
|
|
if not content:
|
|
return 0
|
|
value = 0
|
|
for b in content:
|
|
value = (value << 8) | b
|
|
if content[0] & 0x80: # negative (two's complement)
|
|
value -= 1 << (8 * len(content))
|
|
return value
|
|
|
|
def decodeGeneralString(content):
|
|
return bytes(bytearray(content)).decode("utf-8", "replace")
|