1# Copyright (c) 2016 CORE Security Technologies 2# 3# This software is provided under under a slightly modified version 4# of the Apache Software License. See the accompanying LICENSE file 5# for more information. 6# 7# Authors: Alberto Solino (@agsolino) 8# Kacper Nowak (@kacpern) 9# 10# Description: 11# RFC 4511 Minimalistic implementation. We don't need much functionality yet 12# If we need more complex use cases we might opt to use a third party implementation 13# Keep in mind the APIs are still unstable, might require to re-write your scripts 14# as we change them. 15# Adding [MS-ADTS] specific functionality 16# 17 18from pyasn1.codec.ber import encoder, decoder 19from pyasn1.type import univ, namedtype, namedval, tag, constraint 20 21__all__ = [ 22 'CONTROL_PAGEDRESULTS', 'CONTROL_SDFLAGS', 'KNOWN_CONTROLS', 'NOTIFICATION_DISCONNECT', 'KNOWN_NOTIFICATIONS', 23 # classes 24 'ResultCode', 'Scope', 'DerefAliases', 'Operation', 'MessageID', 'LDAPString', 'LDAPOID', 'LDAPDN', 25 'RelativeLDAPDN', 'AttributeDescription', 'AttributeValue', 'AssertionValue', 'MatchingRuleID', 'URI', 26 'AttributeValueAssertion', 'PartialAttribute', 'PartialAttributeList', 'Attribute', 'AttributeList', 27 'AttributeSelection', 'Referral', 'LDAPResult', 'SaslCredentials', 'AuthenticationChoice', 'BindRequest', 28 'BindResponse', 'UnbindRequest', 'SubstringFilter', 'MatchingRuleAssertion', 'Filter', 'SearchRequest', 29 'SearchResultEntry', 'SearchResultReference', 'SearchResultDone', 'ModifyRequest', 'ModifyResponse', 'AddRequest', 30 'AddResponse', 'DelRequest', 'DelResponse', 'ModifyDNRequest', 'ModifyDNResponse', 'CompareRequest', 31 'CompareResponse', 'AbandonRequest', 'ExtendedRequest', 'ExtendedResponse', 'IntermediateResponse', 'Control', 32 'Controls', 'SimplePagedResultsControlValue', 'SimplePagedResultsControl', 'LDAPMessage' 33] 34 35# Controls 36CONTROL_PAGEDRESULTS = '1.2.840.113556.1.4.319' 37CONTROL_SDFLAGS = '1.2.840.113556.1.4.801' 38 39KNOWN_CONTROLS = {} 40 41# Unsolicited notifications 42NOTIFICATION_DISCONNECT = '1.3.6.1.4.1.1466.20036' 43 44KNOWN_NOTIFICATIONS = {NOTIFICATION_DISCONNECT: 'Notice of Disconnection'} 45 46maxInt = univ.Integer(2147483647) 47 48 49class DefaultSequenceAndSetBaseMixin: 50 def getComponentByPosition(self, idx, default=univ.noValue, instantiate=True): 51 for cls in self.__class__.__bases__: 52 if cls is not DefaultSequenceAndSetBaseMixin: 53 try: 54 component = cls.getComponentByPosition(self, idx)#, default, instantiate) 55 except AttributeError: 56 continue 57 if component is None: 58 return self.setComponentByPosition(idx).getComponentByPosition(idx)# , default, instantiate) 59 return component 60 61 62class ResultCode(univ.Enumerated): 63 namedValues = namedval.NamedValues( 64 ('success', 0), 65 ('operationsError', 1), 66 ('protocolError', 2), 67 ('timeLimitExceeded', 3), 68 ('sizeLimitExceeded', 4), 69 ('compareFalse', 5), 70 ('compareTrue', 6), 71 ('authMethodNotSupported', 7), 72 ('strongerAuthRequired', 8), 73 ('referral', 10), 74 ('adminLimitExceeded', 11), 75 ('unavailableCriticalExtension', 12), 76 ('confidentialityRequired', 13), 77 ('saslBindInProgress', 14), 78 ('noSuchAttribute', 16), 79 ('undefinedAttributeType', 17), 80 ('inappropriateMatching', 18), 81 ('constraintViolation', 19), 82 ('attributeOrValueExists', 20), 83 ('invalidAttributeSyntax', 21), 84 ('noSuchObject', 32), 85 ('aliasProblem', 33), 86 ('invalidDNSyntax', 34), 87 ('aliasDereferencingProblem', 36), 88 ('inappropriateAuthentication', 48), 89 ('invalidCredentials', 49), 90 ('insufficientAccessRights', 50), 91 ('busy', 51), 92 ('unavailable', 52), 93 ('unwillingToPerform', 53), 94 ('loopDetect', 54), 95 ('namingViolation', 64), 96 ('objectClassViolation', 65), 97 ('notAllowedOnNonLeaf', 66), 98 ('notAllowedOnRDN', 67), 99 ('entryAlreadyExists', 68), 100 ('objectClassModsProhibited', 69), 101 ('affectsMultipleDSAs', 71), 102 ('other', 80), 103 ) 104 105 106class Scope(univ.Enumerated): 107 namedValues = namedval.NamedValues( 108 ('baseObject', 0), 109 ('singleLevel', 1), 110 ('wholeSubtree', 2), 111 ) 112 113 114class DerefAliases(univ.Enumerated): 115 namedValues = namedval.NamedValues( 116 ('neverDerefAliases', 0), 117 ('derefInSearching', 1), 118 ('derefFindingBaseObj', 2), 119 ('derefAlways', 3), 120 ) 121 122 123class Operation(univ.Enumerated): 124 namedValues = namedval.NamedValues( 125 ('add', 0), 126 ('delete', 1), 127 ('replace', 2), 128 ) 129 130 131class MessageID(univ.Integer): 132 subtypeSpec = constraint.ValueRangeConstraint(0, maxInt) 133 134 135class LDAPString(univ.OctetString): 136 encoding = 'utf-8' 137 138 139class LDAPOID(univ.OctetString): 140 pass 141 142 143class LDAPDN(LDAPString): 144 pass 145 146 147class RelativeLDAPDN(LDAPString): 148 pass 149 150 151class AttributeDescription(LDAPString): 152 pass 153 154 155class AttributeValue(univ.OctetString): 156 pass 157 158 159class AssertionValue(univ.OctetString): 160 pass 161 162 163class MatchingRuleID(LDAPString): 164 pass 165 166 167class URI(LDAPString): 168 pass 169 170 171class AttributeValueAssertion(univ.Sequence): 172 componentType = namedtype.NamedTypes( 173 namedtype.NamedType('attributeDesc', AttributeDescription()), 174 namedtype.NamedType('assertionValue', AssertionValue()) 175 ) 176 177 178class PartialAttribute(univ.Sequence): 179 componentType = namedtype.NamedTypes( 180 namedtype.NamedType('type', AttributeDescription()), 181 namedtype.NamedType('vals', univ.SetOf(componentType=AttributeValue())) 182 ) 183 184 185class PartialAttributeList(univ.SequenceOf): 186 componentType = PartialAttribute() 187 188 189class Attribute(univ.Sequence): 190 componentType = namedtype.NamedTypes( 191 namedtype.NamedType('type', AttributeDescription()), 192 namedtype.NamedType( 193 'vals', 194 univ.SetOf(componentType=AttributeValue()).subtype(subtypeSpec=constraint.ValueSizeConstraint(1, maxInt)) 195 ) 196 ) 197 198 199class AttributeList(univ.SequenceOf): 200 componentType = Attribute() 201 202 203class AttributeSelection(univ.SequenceOf): 204 componentType = LDAPString() 205 206 207class Referral(univ.SequenceOf): 208 componentType = URI() 209 subtypeSpec = constraint.ValueSizeConstraint(1, maxInt) 210 211 212class LDAPResult(univ.Sequence): 213 componentType = namedtype.NamedTypes( 214 namedtype.NamedType('resultCode', ResultCode()), 215 namedtype.NamedType('matchedDN', LDAPDN()), 216 namedtype.NamedType('diagnosticMessage', LDAPString()), 217 namedtype.OptionalNamedType( 218 'referral', Referral().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) 219 ) 220 ) 221 222 223class SaslCredentials(univ.Sequence): 224 componentType = namedtype.NamedTypes( 225 namedtype.NamedType('mechanism', LDAPString()), 226 namedtype.OptionalNamedType('credentials', univ.OctetString()) 227 ) 228 229 230class AuthenticationChoice(DefaultSequenceAndSetBaseMixin, univ.Choice): 231 componentType = namedtype.NamedTypes( 232 namedtype.NamedType( 233 'simple', 234 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) 235 ), 236 namedtype.NamedType( 237 'sasl', 238 SaslCredentials().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) 239 ), 240 namedtype.NamedType( 241 'sicilyPackageDiscovery', 242 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 9)) 243 ), 244 namedtype.NamedType( 245 'sicilyNegotiate', 246 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)) 247 ), 248 namedtype.NamedType( 249 'sicilyResponse', 250 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11)) 251 ) 252 ) 253 254 255class BindRequest(DefaultSequenceAndSetBaseMixin, univ.Sequence): 256 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 0)) 257 componentType = namedtype.NamedTypes( 258 namedtype.NamedType('version', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, 127))), 259 namedtype.NamedType('name', LDAPDN()), 260 namedtype.NamedType('authentication', AuthenticationChoice()) 261 ) 262 263 264class BindResponse(univ.Sequence): 265 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 1)) 266 componentType = namedtype.NamedTypes( 267 namedtype.NamedType('resultCode', ResultCode()), 268 namedtype.NamedType('matchedDN', LDAPDN()), 269 namedtype.NamedType('diagnosticMessage', LDAPString()), 270 namedtype.OptionalNamedType( 271 'referral', 272 Referral().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) 273 ), 274 namedtype.OptionalNamedType( 275 'serverSaslCreds', 276 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7)) 277 ) 278 ) 279 280 281class UnbindRequest(univ.Null): 282 tagSet = univ.Null.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2)) 283 284 285class SubstringFilter(DefaultSequenceAndSetBaseMixin, univ.Sequence): 286 componentType = namedtype.NamedTypes( 287 namedtype.NamedType('type', AttributeDescription()), 288 namedtype.NamedType( 289 'substrings', 290 univ.SequenceOf(componentType=univ.Choice(componentType=namedtype.NamedTypes( 291 namedtype.NamedType( 292 'initial', 293 AssertionValue().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) 294 ), 295 namedtype.NamedType( 296 'any', 297 AssertionValue().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)) 298 ), 299 namedtype.NamedType( 300 'final', 301 AssertionValue().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)) 302 ) 303 ))) 304 ) 305 ) 306 307 308class MatchingRuleAssertion(univ.Sequence): 309 componentType = namedtype.NamedTypes( 310 namedtype.OptionalNamedType( 311 'matchingRule', 312 MatchingRuleID().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)) 313 ), 314 namedtype.OptionalNamedType( 315 'type', 316 AttributeDescription().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)) 317 ), 318 namedtype.NamedType( 319 'matchValue', 320 AssertionValue().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) 321 ), 322 namedtype.DefaultedNamedType( 323 'dnAttributes', 324 univ.Boolean().subtype(value=False, implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) 325 ) 326 ) 327 328 329class Filter(DefaultSequenceAndSetBaseMixin, univ.Choice): 330 pass 331 332 333Filter.componentType = namedtype.NamedTypes( 334 namedtype.NamedType( 335 'and', 336 univ.SetOf(componentType=Filter()).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) 337 ), 338 namedtype.NamedType( 339 'or', 340 univ.SetOf(componentType=Filter()).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)) 341 ), 342 namedtype.NamedType( 343 'not', 344 univ.SetOf(componentType=Filter()).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)) 345 #Filter().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2)) 346 ), 347 namedtype.NamedType( 348 'equalityMatch', 349 AttributeValueAssertion().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) 350 ), 351 namedtype.NamedType( 352 'substrings', 353 SubstringFilter().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4)) 354 ), 355 namedtype.NamedType( 356 'greaterOrEqual', 357 AttributeValueAssertion().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 5)) 358 ), 359 namedtype.NamedType( 360 'lessOrEqual', 361 AttributeValueAssertion().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 6)) 362 ), 363 namedtype.NamedType( 364 'present', 365 AttributeDescription().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7)) 366 ), 367 namedtype.NamedType( 368 'approxMatch', 369 AttributeValueAssertion().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 8)) 370 ), 371 namedtype.NamedType( 372 'extensibleMatch', 373 MatchingRuleAssertion().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 9)) 374 ) 375) 376 377 378class SearchRequest(DefaultSequenceAndSetBaseMixin, univ.Sequence): 379 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 3)) 380 componentType = namedtype.NamedTypes( 381 namedtype.NamedType('baseObject', LDAPDN()), 382 namedtype.NamedType('scope', Scope()), 383 namedtype.NamedType('derefAliases', DerefAliases()), 384 namedtype.NamedType( 385 'sizeLimit', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, maxInt)) 386 ), 387 namedtype.NamedType( 388 'timeLimit', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, maxInt)) 389 ), 390 namedtype.NamedType('typesOnly', univ.Boolean()), 391 namedtype.NamedType('filter', Filter()), 392 namedtype.NamedType('attributes', AttributeSelection()) 393 ) 394 395 396class SearchResultEntry(univ.Sequence): 397 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 4)) 398 componentType = namedtype.NamedTypes( 399 namedtype.NamedType('objectName', LDAPDN()), 400 namedtype.NamedType('attributes', PartialAttributeList()) 401 ) 402 403 404class SearchResultReference(univ.SequenceOf): 405 tagSet = univ.SequenceOf.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 19)) 406 componentType = URI() 407 subtypeSpec = constraint.ValueSizeConstraint(1, maxInt) 408 409 410class SearchResultDone(LDAPResult): 411 tagSet = LDAPResult.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 5)) 412 413 414class ModifyRequest(DefaultSequenceAndSetBaseMixin, univ.Sequence): 415 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 6)) 416 componentType = namedtype.NamedTypes( 417 namedtype.NamedType('object', LDAPDN()), 418 namedtype.NamedType( 419 'changes', 420 univ.SequenceOf(componentType=univ.Sequence(componentType=namedtype.NamedTypes( 421 namedtype.NamedType('operation', Operation()), 422 namedtype.NamedType('modification', PartialAttribute()) 423 ))) 424 ) 425 ) 426 427 428class ModifyResponse(LDAPResult): 429 tagSet = LDAPResult.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 7)) 430 431 432class AddRequest(DefaultSequenceAndSetBaseMixin, univ.Sequence): 433 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 8)) 434 componentType = namedtype.NamedTypes( 435 namedtype.NamedType('entry', LDAPDN()), 436 namedtype.NamedType('attributes', AttributeList()) 437 ) 438 439 440class AddResponse(LDAPResult): 441 tagSet = LDAPResult.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 9)) 442 443 444class DelRequest(LDAPDN): 445 tagSet = LDAPDN.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 10)) 446 447 448class DelResponse(LDAPResult): 449 tagSet = LDAPResult.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 11)) 450 451 452class ModifyDNRequest(univ.Sequence): 453 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 12)) 454 componentType = namedtype.NamedTypes( 455 namedtype.NamedType('entry', LDAPDN()), 456 namedtype.NamedType('newrdn', RelativeLDAPDN()), 457 namedtype.NamedType('deleteoldrdn', univ.Boolean()), 458 namedtype.OptionalNamedType( 459 'newSuperior', LDAPDN().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) 460 ) 461 ) 462 463 464class ModifyDNResponse(LDAPResult): 465 tagSet = LDAPResult.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 13)) 466 467 468class CompareRequest(DefaultSequenceAndSetBaseMixin, univ.Sequence): 469 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 14)) 470 componentType = namedtype.NamedTypes( 471 namedtype.NamedType('entry', LDAPDN()), 472 namedtype.NamedType('ava', AttributeValueAssertion()) 473 ) 474 475 476class CompareResponse(LDAPResult): 477 tagSet = LDAPResult.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 15)) 478 479 480class AbandonRequest(MessageID): 481 tagSet = MessageID.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 16)) 482 483 484class ExtendedRequest(univ.Sequence): 485 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 23)) 486 componentType = namedtype.NamedTypes( 487 namedtype.NamedType( 488 'requestName', LDAPOID().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) 489 ), 490 namedtype.OptionalNamedType( 491 'requestValue', univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)) 492 ) 493 ) 494 495 496class ExtendedResponse(univ.Sequence): 497 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 24)) 498 componentType = namedtype.NamedTypes( 499 namedtype.NamedType('resultCode', ResultCode()), 500 namedtype.NamedType('matchedDN', LDAPDN()), 501 namedtype.NamedType('diagnosticMessage', LDAPString()), 502 namedtype.OptionalNamedType( 503 'referral', 504 Referral().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) 505 ), 506 namedtype.OptionalNamedType( 507 'responseName', 508 LDAPOID().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)) 509 ), 510 namedtype.OptionalNamedType( 511 'responseValue', 512 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11)) 513 ) 514 ) 515 516 517class IntermediateResponse(univ.Sequence): 518 tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 25)) 519 componentType = namedtype.NamedTypes( 520 namedtype.OptionalNamedType( 521 'responseName', 522 LDAPOID().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) 523 ), 524 namedtype.OptionalNamedType( 525 'responseValue', 526 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)) 527 ) 528 ) 529 530 531class Control(univ.Sequence): 532 componentType = namedtype.NamedTypes( 533 namedtype.NamedType('controlType', LDAPOID()), 534 namedtype.DefaultedNamedType('criticality', univ.Boolean().subtype(value=False)), 535 namedtype.OptionalNamedType('controlValue', univ.OctetString()) 536 ) 537 538 def setComponentByPosition(self, idx, value=univ.noValue, 539 verifyConstraints=True, 540 matchTags=True, 541 matchConstraints=True): 542 if idx == 0: # controlType 543 try: 544 cls = KNOWN_CONTROLS[value] 545 if self.__class__ is not cls: 546 self.__class__ = cls 547 except KeyError: 548 pass 549 return univ.Sequence.setComponentByPosition(self, idx, value=value, 550 verifyConstraints=verifyConstraints, 551 matchTags=matchTags, 552 matchConstraints=matchConstraints) 553 554 def encodeControlValue(self): 555 pass 556 557 def decodeControlValue(self): 558 return 559 560 def prettyPrint(self, scope=0): 561 r = univ.Sequence.prettyPrint(self, scope) 562 decodedControlValue = self.decodeControlValue() 563 if decodedControlValue is not None: 564 r = r[:r.rindex('=') + 1] + '%s\n' % decodedControlValue.prettyPrint(scope + 1) 565 return r 566 567 568class Controls(univ.SequenceOf): 569 componentType = Control() 570 571 572class SDFlagsControlValue(univ.Sequence): 573 componentType = namedtype.NamedTypes( 574 namedtype.NamedType('flags', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, maxInt))), 575 ) 576 577class SDFlagsControl(Control): 578 def __init__(self, criticality=None, flags=0x00000007L, **kwargs): 579 Control.__init__(self, **kwargs) 580 self['controlType'] = CONTROL_SDFLAGS 581 if criticality is not None: 582 self['criticality'] = criticality 583 self.flags = flags 584 self.encodeControlValue() 585 586 def encodeControlValue(self): 587 self['controlValue'] = encoder.encode( 588 SDFlagsControlValue().setComponents(self.flags)) 589 590 def decodeControlValue(self): 591 decodedControlValue, _ = decoder.decode(self['controlValue'], asn1Spec=SDFlagsControlValue()) 592 self._flags = decodedControlValue[0] 593 return decodedControlValue 594 595 def getCriticality(self): 596 return self['criticality'] 597 598 def setCriticality(self, value): 599 self['criticality'] = value 600 601 def getFlags(self): 602 self.decodeControlValue() 603 return self._flags 604 605 def setFlags(self, value): 606 self._flags = value 607 self.encodeControlValue() 608 609class SimplePagedResultsControlValue(univ.Sequence): 610 componentType = namedtype.NamedTypes( 611 namedtype.NamedType('size', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, maxInt))), 612 namedtype.NamedType('cookie', univ.OctetString()), 613 ) 614 615 616class SimplePagedResultsControl(Control): 617 def __init__(self, criticality=None, size=1000, cookie='', **kwargs): 618 Control.__init__(self, **kwargs) 619 self['controlType'] = CONTROL_PAGEDRESULTS 620 if criticality is not None: 621 self['criticality'] = criticality 622 self._size = size 623 self._cookie = cookie 624 self.encodeControlValue() 625 626 def encodeControlValue(self): 627 self['controlValue'] = encoder.encode(SimplePagedResultsControlValue().setComponents(self._size, self._cookie)) 628 629 def decodeControlValue(self): 630 decodedControlValue, _ = decoder.decode(self['controlValue'], asn1Spec=SimplePagedResultsControlValue()) 631 self._size, self._cookie = decodedControlValue[0], decodedControlValue[1] 632 return decodedControlValue 633 634 def getCriticality(self): 635 return self['criticality'] 636 637 def setCriticality(self, value): 638 self['criticality'] = value 639 640 def getSize(self): 641 self.decodeControlValue() 642 return self._size 643 644 def setSize(self, value): 645 self._size = value 646 self.encodeControlValue() 647 648 def getCookie(self): 649 self.decodeControlValue() 650 return self._cookie 651 652 def setCookie(self, value): 653 self._cookie = value 654 self.encodeControlValue() 655 656 657KNOWN_CONTROLS[CONTROL_PAGEDRESULTS] = SimplePagedResultsControl 658KNOWN_CONTROLS[CONTROL_SDFLAGS] = SDFlagsControl 659 660class LDAPMessage(DefaultSequenceAndSetBaseMixin, univ.Sequence): 661 componentType = namedtype.NamedTypes( 662 namedtype.NamedType('messageID', MessageID()), 663 namedtype.NamedType('protocolOp', univ.Choice(componentType=namedtype.NamedTypes( 664 namedtype.NamedType('bindRequest', BindRequest()), 665 namedtype.NamedType('bindResponse', BindResponse()), 666 namedtype.NamedType('unbindRequest', UnbindRequest()), 667 namedtype.NamedType('searchRequest', SearchRequest()), 668 namedtype.NamedType('searchResEntry', SearchResultEntry()), 669 namedtype.NamedType('searchResDone', SearchResultDone()), 670 namedtype.NamedType('searchResRef', SearchResultReference()), 671 namedtype.NamedType('modifyRequest', ModifyRequest()), 672 namedtype.NamedType('modifyResponse', ModifyResponse()), 673 namedtype.NamedType('addRequest', AddRequest()), 674 namedtype.NamedType('addResponse', AddResponse()), 675 namedtype.NamedType('delRequest', DelRequest()), 676 namedtype.NamedType('delResponse', DelResponse()), 677 namedtype.NamedType('modDNRequest', ModifyDNRequest()), 678 namedtype.NamedType('modDNResponse', ModifyDNResponse()), 679 namedtype.NamedType('compareRequest', CompareRequest()), 680 namedtype.NamedType('compareResponse', CompareResponse()), 681 namedtype.NamedType('abandonRequest', AbandonRequest()), 682 namedtype.NamedType('extendedReq', ExtendedRequest()), 683 namedtype.NamedType('extendedResp', ExtendedResponse()), 684 namedtype.NamedType('intermediateResponse', IntermediateResponse()) 685 ))), 686 namedtype.OptionalNamedType( 687 'controls', 688 Controls().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)) 689 ), 690 # fix AD nonconforming to RFC4511 691 namedtype.OptionalNamedType( 692 'responseName', 693 LDAPOID().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)) 694 ), 695 namedtype.OptionalNamedType( 696 'responseValue', 697 univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11)) 698 ) 699 ) 700