@@ -208,7 +208,7 @@ class ASN1_Class_LDAP(ASN1_Class):
208
208
209
209
210
210
# Bind operation
211
- # https://datatracker.ietf.org/doc/html/rfc1777 #section-4.1
211
+ # https://datatracker.ietf.org/doc/html/rfc4511 #section-4.2
212
212
213
213
214
214
class ASN1_Class_LDAP_Authentication (ASN1_Class ):
@@ -397,7 +397,7 @@ def serverSaslCredsData(self):
397
397
398
398
399
399
# Unbind operation
400
- # https://datatracker.ietf.org/doc/html/rfc1777 #section-4.2
400
+ # https://datatracker.ietf.org/doc/html/rfc4511 #section-4.3
401
401
402
402
403
403
class LDAP_UnbindRequest (ASN1_Packet ):
@@ -409,7 +409,7 @@ class LDAP_UnbindRequest(ASN1_Packet):
409
409
410
410
411
411
# Search operation
412
- # https://datatracker.ietf.org/doc/html/rfc1777 #section-4.3
412
+ # https://datatracker.ietf.org/doc/html/rfc4511 #section-4.5
413
413
414
414
415
415
class LDAP_SubstringFilterInitial (ASN1_Packet ):
@@ -759,16 +759,16 @@ class LDAP_SearchRequest(ASN1_Packet):
759
759
)
760
760
761
761
762
- class LDAP_SearchResponseEntryAttributeValue (ASN1_Packet ):
762
+ class LDAP_AttributeValue (ASN1_Packet ):
763
763
ASN1_codec = ASN1_Codecs .BER
764
764
ASN1_root = AttributeValue ("value" , "" )
765
765
766
766
767
- class LDAP_SearchResponseEntryAttribute (ASN1_Packet ):
767
+ class LDAP_PartialAttribute (ASN1_Packet ):
768
768
ASN1_codec = ASN1_Codecs .BER
769
769
ASN1_root = ASN1F_SEQUENCE (
770
770
AttributeType ("type" , "" ),
771
- ASN1F_SET_OF ("values" , [], LDAP_SearchResponseEntryAttributeValue ),
771
+ ASN1F_SET_OF ("values" , [], LDAP_AttributeValue ),
772
772
)
773
773
774
774
@@ -778,8 +778,8 @@ class LDAP_SearchResponseEntry(ASN1_Packet):
778
778
LDAPDN ("objectName" , "" ),
779
779
ASN1F_SEQUENCE_OF (
780
780
"attributes" ,
781
- LDAP_SearchResponseEntryAttribute (),
782
- LDAP_SearchResponseEntryAttribute ,
781
+ LDAP_PartialAttribute (),
782
+ LDAP_PartialAttribute ,
783
783
),
784
784
implicit_tag = ASN1_Class_LDAP .SearchResultEntry ,
785
785
)
@@ -793,14 +793,6 @@ class LDAP_SearchResponseResultDone(ASN1_Packet):
793
793
)
794
794
795
795
796
- class LDAP_AbandonRequest (ASN1_Packet ):
797
- ASN1_codec = ASN1_Codecs .BER
798
- ASN1_root = ASN1F_SEQUENCE (
799
- ASN1F_INTEGER ("messageID" , 0 ),
800
- implicit_tag = ASN1_Class_LDAP .AbandonRequest ,
801
- )
802
-
803
-
804
796
class LDAP_SearchResponseReference (ASN1_Packet ):
805
797
ASN1_codec = ASN1_Codecs .BER
806
798
ASN1_root = ASN1F_SEQUENCE_OF (
@@ -811,6 +803,106 @@ class LDAP_SearchResponseReference(ASN1_Packet):
811
803
)
812
804
813
805
806
+ # Modify Operation
807
+ # https://datatracker.ietf.org/doc/html/rfc4511#section-4.6
808
+
809
+
810
+ class LDAP_ModifyRequestChange (ASN1_Packet ):
811
+ ASN1_codec = ASN1_Codecs .BER
812
+ ASN1_root = ASN1F_SEQUENCE (
813
+ ASN1F_ENUMERATED (
814
+ "operation" ,
815
+ 0 ,
816
+ {
817
+ 0 : "add" ,
818
+ 1 : "delete" ,
819
+ 2 : "replace" ,
820
+ },
821
+ ),
822
+ ASN1F_PACKET ("modification" , LDAP_PartialAttribute (), LDAP_PartialAttribute ),
823
+ )
824
+
825
+
826
+ class LDAP_ModifyRequest (ASN1_Packet ):
827
+ ASN1_codec = ASN1_Codecs .BER
828
+ ASN1_root = ASN1F_SEQUENCE (
829
+ LDAPDN ("object" , "" ),
830
+ ASN1F_SEQUENCE_OF ("changes" , [], LDAP_ModifyRequestChange ),
831
+ implicit_tag = ASN1_Class_LDAP .ModifyRequest ,
832
+ )
833
+
834
+
835
+ class LDAP_ModifyResponse (ASN1_Packet ):
836
+ ASN1_codec = ASN1_Codecs .BER
837
+ ASN1_root = ASN1F_SEQUENCE (
838
+ * LDAPResult ,
839
+ implicit_tag = ASN1_Class_LDAP .ModifyResponse ,
840
+ )
841
+
842
+
843
+ # Add Operation
844
+ # https://datatracker.ietf.org/doc/html/rfc4511#section-4.7
845
+
846
+
847
+ class LDAP_Attribute (ASN1_Packet ):
848
+ ASN1_codec = ASN1_Codecs .BER
849
+ ASN1_root = LDAP_PartialAttribute .ASN1_root
850
+
851
+
852
+ class LDAP_AddRequest (ASN1_Packet ):
853
+ ASN1_codec = ASN1_Codecs .BER
854
+ ASN1_root = ASN1F_SEQUENCE (
855
+ LDAPDN ("entry" , "" ),
856
+ ASN1F_SEQUENCE_OF (
857
+ "attributes" ,
858
+ LDAP_Attribute (),
859
+ LDAP_Attribute ,
860
+ ),
861
+ implicit_tag = ASN1_Class_LDAP .AddRequest ,
862
+ )
863
+
864
+
865
+ class LDAP_AddResponse (ASN1_Packet ):
866
+ ASN1_codec = ASN1_Codecs .BER
867
+ ASN1_root = ASN1F_SEQUENCE (
868
+ * LDAPResult ,
869
+ implicit_tag = ASN1_Class_LDAP .AddResponse ,
870
+ )
871
+
872
+
873
+ # Delete Operation
874
+ # https://datatracker.ietf.org/doc/html/rfc4511#section-4.8
875
+
876
+
877
+ class LDAP_DelRequest (ASN1_Packet ):
878
+ ASN1_codec = ASN1_Codecs .BER
879
+ ASN1_root = LDAPDN (
880
+ "entry" ,
881
+ "" ,
882
+ implicit_tag = ASN1_Class_LDAP .DelRequest ,
883
+ )
884
+
885
+
886
+ class LDAP_DelResponse (ASN1_Packet ):
887
+ ASN1_codec = ASN1_Codecs .BER
888
+ ASN1_root = ASN1F_SEQUENCE (
889
+ * LDAPResult ,
890
+ implicit_tag = ASN1_Class_LDAP .DelResponse ,
891
+ )
892
+
893
+
894
+ # Abandon Operation
895
+ # https://datatracker.ietf.org/doc/html/rfc4511#section-4.11
896
+
897
+
898
+ class LDAP_AbandonRequest (ASN1_Packet ):
899
+ ASN1_codec = ASN1_Codecs .BER
900
+ ASN1_root = ASN1F_SEQUENCE (
901
+ ASN1F_INTEGER ("messageID" , 0 ),
902
+ implicit_tag = ASN1_Class_LDAP .AbandonRequest ,
903
+ )
904
+
905
+
814
906
# LDAP v3
815
907
816
908
# RFC 4511 sect 4.12 - Extended Operation
@@ -926,6 +1018,12 @@ class LDAP(ASN1_Packet):
926
1018
LDAP_SearchResponseResultDone ,
927
1019
LDAP_AbandonRequest ,
928
1020
LDAP_SearchResponseReference ,
1021
+ LDAP_ModifyRequest ,
1022
+ LDAP_ModifyResponse ,
1023
+ LDAP_AddRequest ,
1024
+ LDAP_AddResponse ,
1025
+ LDAP_DelRequest ,
1026
+ LDAP_DelResponse ,
929
1027
LDAP_UnbindRequest ,
930
1028
LDAP_ExtendedResponse ,
931
1029
),
@@ -966,8 +1064,8 @@ def tcp_reassemble(cls, data, *args, **kwargs):
966
1064
pkt = cls (data )
967
1065
# Packet can be a whole response yet still miss some content.
968
1066
if (
969
- LDAP_SearchResponseEntry in pkt and
970
- LDAP_SearchResponseResultDone not in pkt
1067
+ LDAP_SearchResponseEntry in pkt
1068
+ and LDAP_SearchResponseResultDone not in pkt
971
1069
):
972
1070
return None
973
1071
return pkt
@@ -1242,9 +1340,9 @@ def make_reply(self, req):
1242
1340
/ CLDAP (
1243
1341
protocolOp = LDAP_SearchResponseEntry (
1244
1342
attributes = [
1245
- LDAP_SearchResponseEntryAttribute (
1343
+ LDAP_PartialAttribute (
1246
1344
values = [
1247
- LDAP_SearchResponseEntryAttributeValue (
1345
+ LDAP_AttributeValue (
1248
1346
value = ASN1_STRING (
1249
1347
val = bytes (
1250
1348
NETLOGON_SAM_LOGON_RESPONSE_EX (
@@ -2146,6 +2244,34 @@ def _ssafe(x):
2146
2244
break
2147
2245
return entries
2148
2246
2247
+ def modify (
2248
+ self ,
2249
+ object : str ,
2250
+ changes : List [LDAP_ModifyRequestChange ],
2251
+ controls : List [LDAP_Control ] = [],
2252
+ ) -> None :
2253
+ """
2254
+ Perform a LDAP modify request.
2255
+
2256
+ :returns:
2257
+ """
2258
+ resp = self .sr1 (
2259
+ LDAP_ModifyRequest (
2260
+ object = object ,
2261
+ changes = changes ,
2262
+ ),
2263
+ controls = controls ,
2264
+ timeout = 3 ,
2265
+ )
2266
+ if (
2267
+ LDAP_ModifyResponse not in resp .protocolOp
2268
+ or resp .protocolOp .resultCode != 0
2269
+ ):
2270
+ raise LDAP_Exception (
2271
+ "LDAP modify failed !" ,
2272
+ resp = resp ,
2273
+ )
2274
+
2149
2275
def close (self ):
2150
2276
if self .verb :
2151
2277
print ("X Connection closed\n " )
0 commit comments