-- Copyright (c) 2019 Herbert Valerio Riedel -- -- This file is free software: you may copy, redistribute and/or modify it -- under the terms of the GNU General Public License as published by the -- Free Software Foundation, either version 2 of the License, or (at your -- option) any later version. -- -- This file is distributed in the hope that it will be useful, but -- WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program (see `LICENSE`). If not, see -- . {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE TypeOperators #-} #if !defined(HS_LDAPv3_ANNOTATED) {-# OPTIONS_GHC -fno-warn-dodgy-exports #-} #endif -- This module is compiled twice; once with ASN.1 type-annotating -- `newtype` wrappers; and a 2nd time with those newtypes made -- "transparent" by redefining them as `type` synonyms. The public API -- exposes the latter version; ASN.1 encoding/decoding goes via the -- former version. #if defined(HS_LDAPv3_ANNOTATED) # define MODULE_NAME LDAPv3.Message.Annotated #else # define MODULE_NAME LDAPv3.Message #endif -- | This module provides a pure Haskell implementation of the /Lightweight Directory Access Protocol (LDAP)/ version 3 as specified in . -- -- Serializing and deserializing to and from the wire encoding is provided via the 'Bin.Binary' instance of 'LDAPMessage'. For the purpose of implementing network clients and servers, the operations -- -- * 'Bin.encode' -- * 'Data.Binary.Get.runGetIncremental' -- -- are most useful. -- -- When using a streaming I\/O framework such a simple 'Data.Binary.Binary' adapter such as makes it easy to implement a LDAPv3 client. -- -- @since 0.1.0 module MODULE_NAME ( -- * LDAPv3 Protocol data structures -- -- | The Haskell data structures defined in this module closely follow the protocol specification as laid out in . -- -- For convenience, the normative definitions for each Haskell data type are quoted. -- ** Common Elements () -- 4.1.1. Message Envelope LDAPMessage(..) , MessageID(..) , MaxInt , ProtocolOp(..) -- 4.1.2. String Types , LDAPString , LDAPOID , OID(..) -- 4.1.3. Distinguished Name and Relative Distinguished Name , LDAPDN , RelativeLDAPDN -- 4.1.4. Attribute Descriptions , AttributeDescription(..) , KeyString , Option -- 4.1.5. Attribute Value , AttributeValue -- 4.1.6. Attribute Value Assertion , AttributeValueAssertion(..) , AssertionValue -- 4.1.7. Attribute and PartialAttribute , PartialAttribute(..) , Attribute(..) -- 4.1.8. Matching Rule Identifier , MatchingRuleId(..) -- 4.1.9. Result Message , LDAPResult(..) , ResultCode(..) -- 4.1.10. Referral , Referral , URI -- 4.1.11. Controls , Controls , Control(..) -- ** Bind Operation () , BindRequest(..) , AuthenticationChoice(..) , SaslCredentials(..) , BindResponse(..) -- ** Unbind Operation () , UnbindRequest -- ** Unsolicited Notification () -- -- | Unsolicited notifications are represented by an 'ExtendedResponse' message with its 'MessageID' set to @0@. -- ** Search Operation () , SearchRequest(..) , Scope(..) , DerefAliases(..) , AttributeSelection , Filter(..) , SubstringFilter(..) , Substring(..) , MatchingRuleAssertion(..) -- *** Search Result () , SearchResultEntry(..) , PartialAttributeList , SearchResultReference(..) , SearchResultDone -- ** Modify Operation () , ModifyRequest(..) , Change(..) , Operation(..) , ModifyResponse -- ** Add Operation () , AddRequest(..) , AttributeList , AddResponse -- ** Delete Operation () , DelRequest , DelResponse -- ** Modify DN Operation () , ModifyDNRequest(..) , ModifyDNResponse -- ** Compare Operation () , CompareRequest(..) , CompareResponse -- ** Abandon Operation () , AbandonRequest -- ** Extended Operation () , ExtendedRequest(..) , ExtendedResponse(..) -- ** Intermediate Response () , IntermediateResponse(..) -- * ASN.1 Helpers , NULL , OCTET_STRING , BOOLEAN_DEFAULT(..) , SET(..) , SET1(..) , COMPONENTS_OF(..) -- ** ASN.1 type-level tagging , EXPLICIT(..) , IMPLICIT(..) , ENUMERATED(..) , CHOICE(..) , TagK(..) -- * Unsigned integer sub-type , UIntBounds , UInt , fromUInt , toUInt ) where import Common hiding (Option) import Data.ASN1.Prim (TagK (..)) import Data.Int.Subtypes import LDAPv3.AttributeDescription import LDAPv3.Message.Types import LDAPv3.ResultCode import qualified Data.Binary as Bin import Data.ASN1 (Enumerated, NULL, OCTET_STRING, SET (..), SET1 (..)) #if defined(HS_LDAPv3_ANNOTATED) import Data.ASN1 (ASN1 (..), ASN1Constructed, BOOLEAN_DEFAULT (..), CHOICE (..), COMPONENTS_OF (..), ENUMERATED (..), EXPLICIT (..), IMPLICIT (..), gasn1decodeChoice, gasn1encodeChoice, toBinaryGet, toBinaryPut) import Data.ASN1.Prim (Tag (..)) #else /* defined(HS_LDAPv3_ANNOTATED) */ import qualified LDAPv3.Message.Annotated as Annotated (LDAPMessage) import Unsafe.Coerce (unsafeCoerce) -- | ASN.1 @IMPLICIT@ Annotation type IMPLICIT (tag :: TagK) x = x -- | ASN.1 @EXPLICIT@ Annotation type EXPLICIT (tag :: TagK) x = x -- | ASN.1 @ENUMERATED@ Annotation type ENUMERATED x = x -- | Helper representing a @BOOLEAN DEFAULT (TRUE|FALSE)@ ASN.1 type annotation type BOOLEAN_DEFAULT (def :: Bool) = Bool -- | ASN.1 @COMPONENTS OF@ Annotation type COMPONENTS_OF x = x -- | ASN.1 @CHOICE@ Annotation type CHOICE x = x #endif /* defined(HS_LDAPv3_ANNOTATED) */ ---------------------------------------------------------------------------- -- LDAPv3 protocol {- | Message Envelope () > LDAPMessage ::= SEQUENCE { > messageID MessageID, > protocolOp CHOICE { > bindRequest BindRequest, > bindResponse BindResponse, > unbindRequest UnbindRequest, > searchRequest SearchRequest, > searchResEntry SearchResultEntry, > searchResDone SearchResultDone, > searchResRef SearchResultReference, > modifyRequest ModifyRequest, > modifyResponse ModifyResponse, > addRequest AddRequest, > addResponse AddResponse, > delRequest DelRequest, > delResponse DelResponse, > modDNRequest ModifyDNRequest, > modDNResponse ModifyDNResponse, > compareRequest CompareRequest, > compareResponse CompareResponse, > abandonRequest AbandonRequest, > extendedReq ExtendedRequest, > extendedResp ExtendedResponse, > ..., > intermediateResponse IntermediateResponse }, > controls [0] Controls OPTIONAL } -} data LDAPMessage = LDAPMessage { _LDAPMessage'messageID :: MessageID , _LDAPMessage'protocolOp :: CHOICE ProtocolOp , _LDAPMessage'controls :: Maybe ('CONTEXTUAL 0 `IMPLICIT` Controls) } deriving (Generic,Show,Eq) -- | Encodes to\/from ASN.1 as per #if defined(HS_LDAPv3_ANNOTATED) instance Bin.Binary LDAPMessage where put = void . toBinaryPut . asn1encode get = toBinaryGet asn1decode #else instance Bin.Binary LDAPMessage where put = Bin.put . (unsafeCoerce :: LDAPMessage -> Annotated.LDAPMessage) get = (unsafeCoerce :: Annotated.LDAPMessage -> LDAPMessage) <$> Bin.get #endif #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 LDAPMessage instance ASN1Constructed LDAPMessage #endif -- | @CHOICE@ type inlined in @LDAPMessage.protocolOp@ () -- data ProtocolOp = ProtocolOp'bindRequest BindRequest | ProtocolOp'bindResponse BindResponse | ProtocolOp'unbindRequest UnbindRequest | ProtocolOp'searchRequest SearchRequest | ProtocolOp'searchResEntry SearchResultEntry | ProtocolOp'searchResDone SearchResultDone | ProtocolOp'searchResRef SearchResultReference | ProtocolOp'modifyRequest ModifyRequest | ProtocolOp'modifyResponse ModifyResponse | ProtocolOp'addRequest AddRequest | ProtocolOp'addResponse AddResponse | ProtocolOp'delRequest DelRequest | ProtocolOp'delResponse DelResponse | ProtocolOp'modDNRequest ModifyDNRequest | ProtocolOp'modDNResponse ModifyDNResponse | ProtocolOp'compareRequest CompareRequest | ProtocolOp'compareResponse CompareResponse | ProtocolOp'abandonRequest AbandonRequest | ProtocolOp'extendedReq ExtendedRequest | ProtocolOp'extendedResp ExtendedResponse | ProtocolOp'intermediateResponse IntermediateResponse deriving (Generic,Show,Eq) instance NFData ProtocolOp ---------------------------------------------------------------------------- {- | Controls () > Controls ::= SEQUENCE OF control Control -} type Controls = [Control] {- | Control Entry () > Control ::= SEQUENCE { > controlType LDAPOID, > criticality BOOLEAN DEFAULT FALSE, > controlValue OCTET STRING OPTIONAL } -} data Control = Control { _Control'controlType :: LDAPOID , _Control'criticality :: BOOLEAN_DEFAULT 'False , _Control'controlValue :: Maybe OCTET_STRING } deriving (Generic,Show,Eq) instance NFData Control #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 Control instance ASN1Constructed Control #endif {- | Object identifier () > LDAPOID ::= OCTET STRING -- Constrained to > -- [RFC4512] -} type LDAPOID = OID ---------------------------------------------------------------------------- {- | Bind Request () > BindRequest ::= [APPLICATION 0] SEQUENCE { > version INTEGER (1 .. 127), > name LDAPDN, > authentication AuthenticationChoice } -} data BindRequest = BindRequest { bindRequest'version :: UInt 1 127 Int8 , bindRequest'name :: LDAPDN , bindRequest'authentication :: AuthenticationChoice } deriving (Generic,Show,Eq) instance NFData BindRequest #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 BindRequest where asn1defTag _ = Application 0 instance ASN1Constructed BindRequest #endif ---------------------------------------------------------------------------- {- | See 'BindRequest' > AuthenticationChoice ::= CHOICE { > simple [0] OCTET STRING, > -- 1 and 2 reserved > sasl [3] SaslCredentials, > ... } -} data AuthenticationChoice = AuthenticationChoice'simple ('CONTEXTUAL 0 `IMPLICIT` OCTET_STRING) | AuthenticationChoice'sasl ('CONTEXTUAL 3 `IMPLICIT` SaslCredentials) deriving (Generic,Show,Eq) instance NFData AuthenticationChoice #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 AuthenticationChoice where asn1decode = gasn1decodeChoice asn1encode = gasn1encodeChoice #endif {- | See 'AuthenticationChoice' > SaslCredentials ::= SEQUENCE { > mechanism LDAPString, > credentials OCTET STRING OPTIONAL } -} data SaslCredentials = SaslCredentials { _SaslCredentials'mechanism :: LDAPString , _SaslCredentials'credentials :: Maybe OCTET_STRING } deriving (Generic,Show,Eq) instance NFData SaslCredentials #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 SaslCredentials instance ASN1Constructed SaslCredentials #endif ---------------------------------------------------------------------------- {- | Bind Response () > BindResponse ::= [APPLICATION 1] SEQUENCE { > COMPONENTS OF LDAPResult, > serverSaslCreds [7] OCTET STRING OPTIONAL } -} data BindResponse = BindResponse { _BindResponse'LDAPResult :: COMPONENTS_OF LDAPResult , _BindResponse'serverSaslCreds :: Maybe ('CONTEXTUAL 7 `IMPLICIT` OCTET_STRING) } deriving (Generic,Show,Eq) instance NFData BindResponse #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 BindResponse where asn1defTag _ = Application 1 instance ASN1Constructed BindResponse #endif ---------------------------------------------------------------------------- {- | Unbind Operation () > UnbindRequest ::= [APPLICATION 2] NULL -} type UnbindRequest = ('APPLICATION 2 `IMPLICIT` NULL) ---------------------------------------------------------------------------- {- | Search Request () > SearchRequest ::= [APPLICATION 3] SEQUENCE { > baseObject LDAPDN, > scope ENUMERATED { > baseObject (0), > singleLevel (1), > wholeSubtree (2), > ... }, > derefAliases ENUMERATED { > neverDerefAliases (0), > derefInSearching (1), > derefFindingBaseObj (2), > derefAlways (3) }, > sizeLimit INTEGER (0 .. maxInt), > timeLimit INTEGER (0 .. maxInt), > typesOnly BOOLEAN, > filter Filter, > attributes AttributeSelection } -} data SearchRequest = SearchRequest { _SearchRequest'baseObject :: LDAPDN , _SearchRequest'scope :: ENUMERATED Scope , _SearchRequest'derefAliases :: ENUMERATED DerefAliases , _SearchRequest'sizeLimit :: (UInt 0 MaxInt Int32) , _SearchRequest'timeLimit :: (UInt 0 MaxInt Int32) , _SearchRequest'typesOnly :: Bool , _SearchRequest'filter :: Filter , _SearchRequest'attributes :: AttributeSelection } deriving (Generic,Show,Eq) instance NFData SearchRequest {- | See 'SearchRequest' > AttributeSelection ::= SEQUENCE OF selector LDAPString > -- The LDAPString is constrained to > -- in Section 4.5.1.8 -} type AttributeSelection = [LDAPString] #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 SearchRequest where asn1defTag _ = Application 3 instance ASN1Constructed SearchRequest #endif -- | See 'SearchRequest' () data Scope = Scope'baseObject | Scope'singleLevel | Scope'wholeSubtree deriving (Generic,Bounded,Enum,Show,Eq) instance NFData Scope where rnf = rwhnf instance Enumerated Scope -- | See 'SearchRequest' () data DerefAliases = DerefAliases'neverDerefAliases | DerefAliases'derefInSearching | DerefAliases'derefFindingBaseObj | DerefAliases'derefAlways deriving (Generic,Bounded,Enum,Show,Eq) instance NFData DerefAliases where rnf = rwhnf instance Enumerated DerefAliases {- | Search Filter () > Filter ::= CHOICE { > and [0] SET SIZE (1..MAX) OF filter Filter, > or [1] SET SIZE (1..MAX) OF filter Filter, > not [2] Filter, > equalityMatch [3] AttributeValueAssertion, > substrings [4] SubstringFilter, > greaterOrEqual [5] AttributeValueAssertion, > lessOrEqual [6] AttributeValueAssertion, > present [7] AttributeDescription, > approxMatch [8] AttributeValueAssertion, > extensibleMatch [9] MatchingRuleAssertion, > ... } See also "LDAPv3.StringRepr" for converting 'Filter' to and from the /String Representation of Search Filters/ (). -} data Filter = Filter'and ('CONTEXTUAL 0 `IMPLICIT` SET1 Filter) | Filter'or ('CONTEXTUAL 1 `IMPLICIT` SET1 Filter) | Filter'not ('CONTEXTUAL 2 `EXPLICIT` Filter) | Filter'equalityMatch ('CONTEXTUAL 3 `IMPLICIT` AttributeValueAssertion) | Filter'substrings ('CONTEXTUAL 4 `IMPLICIT` SubstringFilter) | Filter'greaterOrEqual ('CONTEXTUAL 5 `IMPLICIT` AttributeValueAssertion) | Filter'lessOrEqual ('CONTEXTUAL 6 `IMPLICIT` AttributeValueAssertion) | Filter'present ('CONTEXTUAL 7 `IMPLICIT` AttributeDescription) | Filter'approxMatch ('CONTEXTUAL 8 `IMPLICIT` AttributeValueAssertion) | Filter'extensibleMatch ('CONTEXTUAL 9 `IMPLICIT` MatchingRuleAssertion) deriving (Generic,Show,Eq) instance NFData Filter #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 Filter where asn1decode = gasn1decodeChoice asn1encode = gasn1encodeChoice #endif {- Attribute Descriptions () > AttributeDescription ::= LDAPString > -- Constrained to > -- [RFC4512] @attributedescription@'s syntax is defined in ABNF () notation as > attributedescription = attributetype options > attributetype = oid > options = *( SEMI option ) > option = 1*keychar > oid = descr / numericoid > descr = keystring > numericoid = number 1*( DOT number ) > keystring = leadkeychar *keychar > leadkeychar = ALPHA > ALPHA = %x41-5A / %x61-7A ; "A"-"Z" / "a"-"z" > keychar = ALPHA / DIGIT / HYPHEN > number = DIGIT / ( LDIGIT 1*DIGIT ) > DIGIT = %x30 / LDIGIT ; "0"-"9" > LDIGIT = %x31-39 ; "1"-"9" > HYPHEN = %x2D ; hyphen ("-") See also for the definition of @attributedescription@. -} -- type AttributeDescription = LDAPString {- | Attribute Value () > AttributeValue ::= OCTET STRING -} type AttributeValue = OCTET_STRING {- | Attribute Value Assertion () > AttributeValueAssertion ::= SEQUENCE { > attributeDesc AttributeDescription, > assertionValue AssertionValue } -} data AttributeValueAssertion = AttributeValueAssertion { _AttributeValueAssertion'attributeDesc :: AttributeDescription , _AttributeValueAssertion'assertionValue :: AssertionValue } deriving (Generic,Show,Eq) instance NFData AttributeValueAssertion -- | > AssertionValue ::= OCTET STRING type AssertionValue = OCTET_STRING #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 AttributeValueAssertion instance ASN1Constructed AttributeValueAssertion #endif {- | Substring 'Filter' () > SubstringFilter ::= SEQUENCE { > type AttributeDescription, > substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE { > initial [0] AssertionValue, -- can occur at most once > any [1] AssertionValue, > final [2] AssertionValue } -- can occur at most once > } __NOTE__: The additional invariants imposed on the ordering and occurence counts of the @initial@ and @final@ entries MUST currently be enforced by the consumer of this library. Future versions of this library might change to enforce these invariants at the type-level. Specifically, the invariant stated by the specification is: /There SHALL be at most one @initial@ and at most one @final@ in the @substrings@ of a SubstringFilter. If @initial@ is present, it SHALL be the first element of @substrings@. If @final@ is present, it SHALL be the last element of @substrings@./ -} data SubstringFilter = SubstringFilter { _SubstringFilter'type :: AttributeDescription , _SubstringFilter'substrings :: NonEmpty (CHOICE Substring) } deriving (Generic,Show,Eq) instance NFData SubstringFilter #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 SubstringFilter instance ASN1Constructed SubstringFilter #endif -- | See 'SubstringFilter' data Substring = Substring'initial ('CONTEXTUAL 0 `IMPLICIT` AssertionValue) -- ^ may occur at most once; must be first element if present | Substring'any ('CONTEXTUAL 1 `IMPLICIT` AssertionValue) | Substring'final ('CONTEXTUAL 2 `IMPLICIT` AssertionValue) -- ^ may occur at most once; must be last element if present deriving (Generic,Show,Eq) instance NFData Substring {- | /Extensible Match/ 'SearchRequest' 'Filter' () > MatchingRuleAssertion ::= SEQUENCE { > matchingRule [1] MatchingRuleId OPTIONAL, > type [2] AttributeDescription OPTIONAL, > matchValue [3] AssertionValue, > dnAttributes [4] BOOLEAN DEFAULT FALSE } __NOTE__: The LDAPv3 specification imposes the additional invariant: /If the @matchingRule@ field is absent, the @type@ field MUST be present/ -} data MatchingRuleAssertion = MatchingRuleAssertion { _MatchingRuleAssertion'matchingRule :: Maybe ('CONTEXTUAL 1 `IMPLICIT` MatchingRuleId) , _MatchingRuleAssertion'type :: Maybe ('CONTEXTUAL 2 `IMPLICIT` AttributeDescription) , _MatchingRuleAssertion'matchValue :: ('CONTEXTUAL 3 `IMPLICIT` AssertionValue) , _MatchingRuleAssertion'dnAttributes :: ('CONTEXTUAL 4 `IMPLICIT` BOOLEAN_DEFAULT 'False) } deriving (Generic,Show,Eq) instance NFData MatchingRuleAssertion #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 MatchingRuleAssertion instance ASN1Constructed MatchingRuleAssertion #endif ---------------------------------------------------------------------------- {- | Search Result Continuation Reference () > SearchResultReference ::= [APPLICATION 19] SEQUENCE > SIZE (1..MAX) OF uri URI -} newtype SearchResultReference = SearchResultReference ('APPLICATION 19 `IMPLICIT` NonEmpty URI) deriving (Generic,NFData,Show,Eq) #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 SearchResultReference where asn1defTag _ = Application 19 -- not used asn1decode = SearchResultReference <$> asn1decode asn1encode (SearchResultReference v) = asn1encode v #endif ---------------------------------------------------------------------------- {- | Search Result Entry () > SearchResultEntry ::= [APPLICATION 4] SEQUENCE { > objectName LDAPDN, > attributes PartialAttributeList } -} data SearchResultEntry = SearchResultEntry { _SearchResultEntry'objectName :: LDAPDN , _SearchResultEntry'attributes :: PartialAttributeList } deriving (Generic,Show,Eq) instance NFData SearchResultEntry #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 SearchResultEntry where asn1defTag _ = Application 4 instance ASN1Constructed SearchResultEntry #endif {- | See 'SearchResultEntry' > PartialAttributeList ::= SEQUENCE OF > partialAttribute PartialAttribute -} type PartialAttributeList = [PartialAttribute] {- | Partial Attribute () > PartialAttribute ::= SEQUENCE { > type AttributeDescription, > vals SET OF value AttributeValue } -} data PartialAttribute = PartialAttribute { _PartialAttribute'type :: AttributeDescription , _PartialAttribute'vals :: SET AttributeValue } deriving (Generic,Show,Eq) instance NFData PartialAttribute #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 PartialAttribute instance ASN1Constructed PartialAttribute #endif {- | Attribute () > Attribute ::= PartialAttribute(WITH COMPONENTS { > ..., > vals (SIZE(1..MAX))}) -} data Attribute = Attribute { _Attribute'type :: AttributeDescription , _Attribute'vals :: SET1 AttributeValue } deriving (Generic,Show,Eq) instance NFData Attribute #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 Attribute instance ASN1Constructed Attribute #endif ---------------------------------------------------------------------------- {- | Search Result Done () > SearchResultDone ::= [APPLICATION 5] LDAPResult -} type SearchResultDone = ('APPLICATION 5 `IMPLICIT` LDAPResult) ---------------------------------------------------------------------------- {- | Result Message () > LDAPResult ::= SEQUENCE { > resultCode ENUMERATED { > success (0), > operationsError (1), > protocolError (2), > timeLimitExceeded (3), > sizeLimitExceeded (4), > compareFalse (5), > compareTrue (6), > authMethodNotSupported (7), > strongerAuthRequired (8), > -- 9 reserved -- > referral (10), > adminLimitExceeded (11), > unavailableCriticalExtension (12), > confidentialityRequired (13), > saslBindInProgress (14), > noSuchAttribute (16), > undefinedAttributeType (17), > inappropriateMatching (18), > constraintViolation (19), > attributeOrValueExists (20), > invalidAttributeSyntax (21), > -- 22-31 unused -- > noSuchObject (32), > aliasProblem (33), > invalidDNSyntax (34), > -- 35 reserved for undefined isLeaf -- > aliasDereferencingProblem (36), > -- 37-47 unused -- > inappropriateAuthentication (48), > invalidCredentials (49), > insufficientAccessRights (50), > busy (51), > unavailable (52), > unwillingToPerform (53), > loopDetect (54), > -- 55-63 unused -- > namingViolation (64), > objectClassViolation (65), > notAllowedOnNonLeaf (66), > notAllowedOnRDN (67), > entryAlreadyExists (68), > objectClassModsProhibited (69), > -- 70 reserved for CLDAP -- > affectsMultipleDSAs (71), > -- 72-79 unused -- > other (80), > ... }, > matchedDN LDAPDN, > diagnosticMessage LDAPString, > referral [3] Referral OPTIONAL } -} data LDAPResult = LDAPResult { _LDAPResult'resultCode :: ENUMERATED ResultCode , _LDAPResult'matchedDN :: LDAPDN , _LDAPResult'diagnosticMessage :: LDAPString , _LDAPResult'referral :: Maybe ('CONTEXTUAL 3 `IMPLICIT` Referral) } deriving (Generic,Show,Eq) instance NFData LDAPResult {- | Referral result code () > Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI -} type Referral = ('CONTEXTUAL 3 `IMPLICIT` NonEmpty URI) {- | > URI ::= LDAPString -- limited to characters permitted in > -- URIs -} type URI = LDAPString #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 LDAPResult instance ASN1Constructed LDAPResult #endif {- | String Type () > LDAPString ::= OCTET STRING -- UTF-8 encoded, > -- [ISO10646] characters -} type LDAPString = ShortText {- | Distinguished Name () > LDAPDN ::= LDAPString -- Constrained to > -- [RFC4514] -} type LDAPDN = LDAPString {- | Relative Distinguished Name () > RelativeLDAPDN ::= LDAPString -- Constrained to > -- [RFC4514] -} type RelativeLDAPDN = LDAPString {- | Modify Operation () > ModifyRequest ::= [APPLICATION 6] SEQUENCE { > object LDAPDN, > changes SEQUENCE OF change SEQUENCE { > operation ENUMERATED { > add (0), > delete (1), > replace (2), > ... }, > modification PartialAttribute } } -} data ModifyRequest = ModifyRequest { _ModifyRequest'object :: LDAPDN , _ModifyRequest'changes :: [Change] } deriving (Generic,Show,Eq) instance NFData ModifyRequest #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 ModifyRequest where asn1defTag _ = Application 6 instance ASN1Constructed ModifyRequest #endif -- | See 'ModifyRequest' data Change = Change { _Change'operation :: ENUMERATED Operation , _Change'modification :: PartialAttribute } deriving (Generic,Show,Eq) instance NFData Change #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 Change instance ASN1Constructed Change #endif -- | See 'ModifyRequest' and 'Change' data Operation = Operation'add | Operation'delete | Operation'replace deriving (Generic,Bounded,Enum,Show,Eq) instance NFData Operation where rnf = rwhnf instance Enumerated Operation {- | Modify Response () > ModifyResponse ::= [APPLICATION 7] LDAPResult -} type ModifyResponse = ('APPLICATION 7 `IMPLICIT` LDAPResult) {- | Add Operation () > AddRequest ::= [APPLICATION 8] SEQUENCE { > entry LDAPDN, > attributes AttributeList } -} data AddRequest = AddRequest { _AddRequest'entry :: LDAPDN , _AddRequest'attributes :: AttributeList } deriving (Generic,Show,Eq) instance NFData AddRequest #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 AddRequest where asn1defTag _ = Application 8 instance ASN1Constructed AddRequest #endif {- | Attribute List > AttributeList ::= SEQUENCE OF attribute Attribute -} type AttributeList = [Attribute] {- | Add Response () > AddResponse ::= [APPLICATION 9] LDAPResult -} type AddResponse = ('APPLICATION 9 `IMPLICIT` LDAPResult) {- | Delete Operation () > DelRequest ::= [APPLICATION 10] LDAPDN -} type DelRequest = ('APPLICATION 10 `IMPLICIT` LDAPDN) {- | Delete Response () > DelResponse ::= [APPLICATION 11] LDAPResult -} type DelResponse = ('APPLICATION 11 `IMPLICIT` LDAPResult) {- | Modify DN Operation () ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { entry LDAPDN, newrdn RelativeLDAPDN, deleteoldrdn BOOLEAN, newSuperior [0] LDAPDN OPTIONAL } -} data ModifyDNRequest = ModifyDNRequest { _ModifyDNRequest'entry :: LDAPDN , _ModifyDNRequest'newrdn :: RelativeLDAPDN , _ModifyDNRequest'deleteoldrdn :: Bool , _ModifyDNRequest'newSuperior :: Maybe ('CONTEXTUAL 0 `IMPLICIT` LDAPDN) } deriving (Generic,Show,Eq) instance NFData ModifyDNRequest #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 ModifyDNRequest where asn1defTag _ = Application 12 instance ASN1Constructed ModifyDNRequest #endif {- | Modify DN Response () > ModifyDNResponse ::= [APPLICATION 13] LDAPResult -} type ModifyDNResponse = ('APPLICATION 13 `IMPLICIT` LDAPResult) {- | Compare Operation () > CompareRequest ::= [APPLICATION 14] SEQUENCE { > entry LDAPDN, > ava AttributeValueAssertion } -} data CompareRequest = CompareRequest { _CompareRequest'entry :: LDAPDN , _CompareRequest'ava :: AttributeValueAssertion } deriving (Generic,Show,Eq) instance NFData CompareRequest #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 CompareRequest where asn1defTag _ = Application 14 instance ASN1Constructed CompareRequest #endif {- | Compare Response () > CompareResponse ::= [APPLICATION 15] LDAPResult -} type CompareResponse = ('APPLICATION 15 `IMPLICIT` LDAPResult) {- | Abandon Operation () > AbandonRequest ::= [APPLICATION 16] MessageID -} type AbandonRequest = ('APPLICATION 16 `IMPLICIT` MessageID) {- | Extended Request () > ExtendedRequest ::= [APPLICATION 23] SEQUENCE { > requestName [0] LDAPOID, > requestValue [1] OCTET STRING OPTIONAL } -} data ExtendedRequest = ExtendedRequest { _ExtendedRequest'responseName :: ('CONTEXTUAL 0 `IMPLICIT` LDAPOID) , _ExtendedRequest'responseValue :: Maybe ('CONTEXTUAL 1 `IMPLICIT` OCTET_STRING) } deriving (Generic,Show,Eq) instance NFData ExtendedRequest #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 ExtendedRequest where asn1defTag _ = Application 23 instance ASN1Constructed ExtendedRequest #endif {- | Extended Response () > ExtendedResponse ::= [APPLICATION 24] SEQUENCE { > COMPONENTS OF LDAPResult, > responseName [10] LDAPOID OPTIONAL, > responseValue [11] OCTET STRING OPTIONAL } -} data ExtendedResponse = ExtendedResponse { _ExtendedResponse'LDAPResult :: COMPONENTS_OF LDAPResult , _ExtendedResponse'responseName :: Maybe ('CONTEXTUAL 10 `IMPLICIT` LDAPOID) , _ExtendedResponse'responseValue :: Maybe ('CONTEXTUAL 11 `IMPLICIT` OCTET_STRING) } deriving (Generic,Show,Eq) instance NFData ExtendedResponse #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 ExtendedResponse where asn1defTag _ = Application 24 instance ASN1Constructed ExtendedResponse #endif {- | Intermediate Response () > IntermediateResponse ::= [APPLICATION 25] SEQUENCE { > responseName [0] LDAPOID OPTIONAL, > responseValue [1] OCTET STRING OPTIONAL } -} data IntermediateResponse = IntermediateResponse { _IntermediateResponse'responseName :: Maybe ('CONTEXTUAL 0 `IMPLICIT` LDAPOID) , _IntermediateResponse'responseValue :: Maybe ('CONTEXTUAL 1 `IMPLICIT` OCTET_STRING) } deriving (Generic,Show,Eq) instance NFData IntermediateResponse #if defined(HS_LDAPv3_ANNOTATED) instance ASN1 IntermediateResponse where asn1defTag _ = Application 25 instance ASN1Constructed IntermediateResponse #endif