Skip to content

Commit 9892d4d

Browse files
sigmarisDirectXMan12
authored andcommitted
Support constructing OIDs from integers
This commit introduces support for constructing OIDs using integers (instead of having to pass the BER-encoded bytes to the constructor).
1 parent a5c8edd commit 9892d4d

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

gssapi/raw/oids.pyx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
GSSAPI="BASE" # This ensures that a full module is generated by Cython
22

3+
import six
4+
35
from libc.string cimport memcmp, memcpy
46
from libc.stdlib cimport free, malloc
57

@@ -61,6 +63,54 @@ cdef class OID:
6163
memcpy(self.raw_oid.elements, byte_str, self.raw_oid.length)
6264
return 0
6365

66+
@classmethod
67+
def from_int_seq(cls, integer_sequence):
68+
"""Create a OID from a sequence of integers
69+
70+
This method creates an OID from a sequence of integers.
71+
The sequence can either be in dotted form as a string,
72+
or in list form.
73+
74+
This method is not for BER-encoded byte strings, which
75+
can be passed directly to the OID constructor.
76+
77+
Args:
78+
integer_sequence: either a list of integers or
79+
a string in dotted form
80+
81+
Returns:
82+
OID: the OID represented by the given integer sequence
83+
84+
Raises:
85+
ValueError: the sequence is less than two elements long
86+
"""
87+
88+
if isinstance(integer_sequence, six.string_types):
89+
integer_sequence = integer_sequence.split('.')
90+
91+
oid_seq = [int(x) for x in integer_sequence]
92+
93+
elements = cls._encode_asn1ber(oid_seq)
94+
95+
return cls(elements=elements)
96+
97+
@staticmethod
98+
def _encode_asn1ber(oid_seq):
99+
if len(oid_seq) < 2:
100+
raise ValueError("Sequence must be 2 or more elements long.")
101+
102+
byte_seq = bytearray([oid_seq[0] * 40 + oid_seq[1]])
103+
for element in oid_seq[2:]:
104+
element_seq = [element & 0x7f]
105+
106+
while element > 127:
107+
element >>= 7
108+
element_seq.insert(0, (element & 0x7f) | 0x80)
109+
110+
byte_seq.extend(element_seq)
111+
112+
return bytes(byte_seq)
113+
64114
def __dealloc__(self):
65115
# NB(directxman12): MIT Kerberos has gss_release_oid
66116
# for this purpose, but it's not in the RFC

gssapi/tests/test_raw.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,3 +800,14 @@ def test_decode_from_bytes(self):
800800
o = gb.OID(elements=oid['bytes'])
801801
text = repr(o)
802802
text.should_be("<OID {0}>".format(oid['string']))
803+
804+
def test_encode_from_string(self):
805+
for oid in TEST_OIDS.values():
806+
o = gb.OID.from_int_seq(oid['string'])
807+
o.__bytes__().should_be(oid['bytes'])
808+
809+
def test_encode_from_int_seq(self):
810+
for oid in TEST_OIDS.values():
811+
int_seq = oid['string'].split('.')
812+
o = gb.OID.from_int_seq(int_seq)
813+
o.__bytes__().should_be(oid['bytes'])

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ def gssapi_modules(lst):
194194
keywords=['gssapi', 'security'],
195195
install_requires=[
196196
'enum34',
197-
'decorator'
197+
'decorator',
198+
'six'
198199
],
199200
tests_require=[
200201
'tox'

0 commit comments

Comments
 (0)