andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: #include "pkix_pl_ldapt.h" andre@0: andre@0: SEC_ASN1_MKSUB(SEC_AnyTemplate) andre@0: SEC_ASN1_MKSUB(SEC_NullTemplate) andre@0: SEC_ASN1_MKSUB(SEC_OctetStringTemplate) andre@0: andre@0: /* andre@0: * CertificatePair ::= SEQUENCE { andre@0: * forward [0] Certificate OPTIONAL, andre@0: * reverse [1] Certificate OPTIONAL andre@0: * -- at least one of the pair shall be present -- andre@0: * } andre@0: */ andre@0: andre@0: const SEC_ASN1Template PKIX_PL_LDAPCrossCertPairTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(LDAPCertPair) }, andre@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 0, andre@0: offsetof(LDAPCertPair, forward), SEC_ASN1_SUB(SEC_AnyTemplate) }, andre@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 1, andre@0: offsetof(LDAPCertPair, reverse), SEC_ASN1_SUB(SEC_AnyTemplate) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: /* andre@0: * BindRequest ::= andre@0: * [APPLICATION 0] SEQUENCE { andre@0: * version INTEGER (1..127), andre@0: * name LDAPDN, andre@0: * authentication CHOICE { andre@0: * simple [0] OCTET STRING, andre@0: * krbv42LDAP [1] OCTET STRING, andre@0: * krbv42DSA [2] OCTET STRING andre@0: * } andre@0: * } andre@0: * andre@0: * LDAPDN ::= LDAPString andre@0: * andre@0: * LDAPString ::= OCTET STRING andre@0: */ andre@0: andre@0: #define LDAPStringTemplate SEC_ASN1_SUB(SEC_OctetStringTemplate) andre@0: andre@0: static const SEC_ASN1Template LDAPBindApplTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL }, andre@0: { SEC_ASN1_INTEGER, offsetof(LDAPBind, version) }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPBind, bindName) }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPBind, authentication) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPBindTemplate[] = { andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_BIND_TYPE, 0, andre@0: LDAPBindApplTemplate, sizeof (LDAPBind) } andre@0: }; andre@0: andre@0: /* andre@0: * BindResponse ::= [APPLICATION 1] LDAPResult andre@0: * andre@0: * LDAPResult ::= andre@0: * SEQUENCE { andre@0: * resultCode ENUMERATED { andre@0: * success (0), andre@0: * operationsError (1), andre@0: * protocolError (2), andre@0: * timeLimitExceeded (3), andre@0: * sizeLimitExceeded (4), andre@0: * compareFalse (5), andre@0: * compareTrue (6), andre@0: * authMethodNotSupported (7), andre@0: * strongAuthRequired (8), andre@0: * noSuchAttribute (16), andre@0: * undefinedAttributeType (17), andre@0: * inappropriateMatching (18), andre@0: * constraintViolation (19), andre@0: * attributeOrValueExists (20), andre@0: * invalidAttributeSyntax (21), andre@0: * noSuchObject (32), andre@0: * aliasProblem (33), andre@0: * invalidDNSyntax (34), andre@0: * isLeaf (35), andre@0: * aliasDereferencingProblem (36), andre@0: * inappropriateAuthentication (48), andre@0: * invalidCredentials (49), andre@0: * insufficientAccessRights (50), andre@0: * busy (51), andre@0: * unavailable (52), andre@0: * unwillingToPerform (53), andre@0: * loopDetect (54), andre@0: * namingViolation (64), andre@0: * objectClassViolation (65), andre@0: * notAllowedOnNonLeaf (66), andre@0: * notAllowedOnRDN (67), andre@0: * entryAlreadyExists (68), andre@0: * objectClassModsProhibited (69), andre@0: * other (80) andre@0: * }, andre@0: * matchedDN LDAPDN, andre@0: * errorMessage LDAPString andre@0: * } andre@0: */ andre@0: andre@0: static const SEC_ASN1Template LDAPResultTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL }, andre@0: { SEC_ASN1_ENUMERATED, offsetof(LDAPResult, resultCode) }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPResult, matchedDN) }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPResult, errorMessage) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPBindResponseTemplate[] = { andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_BINDRESPONSE_TYPE, 0, andre@0: LDAPResultTemplate, sizeof (LDAPBindResponse) } andre@0: }; andre@0: andre@0: /* andre@0: * UnbindRequest ::= [APPLICATION 2] NULL andre@0: */ andre@0: andre@0: static const SEC_ASN1Template LDAPUnbindTemplate[] = { andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | SEC_ASN1_XTRN | andre@0: LDAP_UNBIND_TYPE , 0, SEC_ASN1_SUB(SEC_NullTemplate) } andre@0: }; andre@0: andre@0: /* andre@0: * AttributeValueAssertion ::= andre@0: * SEQUENCE { andre@0: * attributeType AttributeType, andre@0: * attributeValue AttributeValue, andre@0: * } andre@0: * andre@0: * AttributeType ::= LDAPString andre@0: * -- text name of the attribute, or dotted andre@0: * -- OID representation andre@0: * andre@0: * AttributeValue ::= OCTET STRING andre@0: */ andre@0: andre@0: #define LDAPAttributeTypeTemplate LDAPStringTemplate andre@0: andre@0: /* andre@0: * SubstringFilter ::= andre@0: * SEQUENCE { andre@0: * type AttributeType, andre@0: * SEQUENCE OF CHOICE { andre@0: * initial [0] LDAPString, andre@0: * any [1] LDAPString, andre@0: * final [2] LDAPString, andre@0: * } andre@0: * } andre@0: */ andre@0: andre@0: #define LDAPSubstringFilterInitialTemplate LDAPStringTemplate andre@0: #define LDAPSubstringFilterAnyTemplate LDAPStringTemplate andre@0: #define LDAPSubstringFilterFinalTemplate LDAPStringTemplate andre@0: andre@0: static const SEC_ASN1Template LDAPSubstringFilterChoiceTemplate[] = { andre@0: { SEC_ASN1_CHOICE, offsetof(LDAPSubstring, selector), 0, andre@0: sizeof (LDAPFilter) }, andre@0: { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, andre@0: offsetof(LDAPSubstring, item), andre@0: LDAPSubstringFilterInitialTemplate, andre@0: LDAP_INITIALSUBSTRING_TYPE }, andre@0: { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, andre@0: offsetof(LDAPSubstring, item), andre@0: LDAPSubstringFilterAnyTemplate, andre@0: LDAP_ANYSUBSTRING_TYPE }, andre@0: { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, andre@0: offsetof(LDAPSubstring, item), andre@0: LDAPSubstringFilterFinalTemplate, andre@0: LDAP_FINALSUBSTRING_TYPE }, andre@0: { 0 } andre@0: }; andre@0: andre@0: /* andre@0: * Filter ::= andre@0: * CHOICE { andre@0: * and [0] SET OF Filter, andre@0: * or [1] SET OF Filter, andre@0: * not [2] Filter, andre@0: * equalityMatch [3] AttributeValueAssertion, andre@0: * substrings [4] SubstringFilter, andre@0: * greaterOrEqual [5] AttributeValueAssertion, andre@0: * lessOrEqual [6] AttributeValueAssertion, andre@0: * present [7] AttributeType, andre@0: * approxMatch [8] AttributeValueAssertion andre@0: } andre@0: */ andre@0: andre@0: static const SEC_ASN1Template LDAPSubstringFilterTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (LDAPSubstringFilter) }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPSubstringFilter, attrType) }, andre@0: { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSubstringFilter, strings), andre@0: LDAPSubstringFilterChoiceTemplate }, andre@0: { 0 } andre@0: }; andre@0: andre@0: const SEC_ASN1Template LDAPFilterTemplate[]; /* forward reference */ andre@0: andre@0: static const SEC_ASN1Template LDAPSetOfFiltersTemplate[] = { andre@0: { SEC_ASN1_SET_OF, 0, LDAPFilterTemplate } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPAVAFilterTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (LDAPAttributeValueAssertion) }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPAttributeValueAssertion, attrType) }, andre@0: { SEC_ASN1_OCTET_STRING, offsetof(LDAPAttributeValueAssertion, attrValue) }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPPresentFilterTemplate[] = { andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPPresentFilter, attrType) } andre@0: }; andre@0: andre@0: #define LDAPEqualFilterTemplate LDAPAVAFilterTemplate andre@0: #define LDAPGreaterOrEqualFilterTemplate LDAPAVAFilterTemplate andre@0: #define LDAPLessOrEqualFilterTemplate LDAPAVAFilterTemplate andre@0: #define LDAPApproxMatchFilterTemplate LDAPAVAFilterTemplate andre@0: andre@0: const SEC_ASN1Template LDAPFilterTemplate[] = { andre@0: { SEC_ASN1_CHOICE, offsetof(LDAPFilter, selector), 0, sizeof(LDAPFilter) }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_ANDFILTER_TYPE, andre@0: offsetof(LDAPFilter, filter.andFilter.filters), andre@0: LDAPSetOfFiltersTemplate, LDAP_ANDFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_ORFILTER_TYPE, andre@0: offsetof(LDAPFilter, filter.orFilter.filters), andre@0: LDAPSetOfFiltersTemplate, LDAP_ORFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_NOTFILTER_TYPE | SEC_ASN1_POINTER, andre@0: offsetof(LDAPFilter, filter.notFilter), andre@0: LDAPFilterTemplate, LDAP_NOTFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_EQUALFILTER_TYPE, andre@0: offsetof(LDAPFilter, filter.equalFilter), andre@0: LDAPEqualFilterTemplate, LDAP_EQUALFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_SUBSTRINGFILTER_TYPE, offsetof(LDAPFilter, filter.substringFilter), andre@0: LDAPSubstringFilterTemplate, LDAP_SUBSTRINGFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_GREATEROREQUALFILTER_TYPE, andre@0: offsetof(LDAPFilter, filter.greaterOrEqualFilter), andre@0: LDAPGreaterOrEqualFilterTemplate, LDAP_GREATEROREQUALFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_LESSOREQUALFILTER_TYPE, andre@0: offsetof(LDAPFilter, filter.lessOrEqualFilter), andre@0: LDAPLessOrEqualFilterTemplate, LDAP_LESSOREQUALFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_PRESENTFILTER_TYPE, andre@0: offsetof(LDAPFilter, filter.presentFilter), andre@0: LDAPPresentFilterTemplate, LDAP_PRESENTFILTER_TYPE }, andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | andre@0: LDAP_APPROXMATCHFILTER_TYPE, andre@0: offsetof(LDAPFilter, filter.approxMatchFilter), andre@0: LDAPApproxMatchFilterTemplate, LDAP_APPROXMATCHFILTER_TYPE }, andre@0: { 0 } andre@0: }; andre@0: andre@0: /* andre@0: * SearchRequest ::= andre@0: * [APPLICATION 3] SEQUENCE { andre@0: * baseObject LDAPDN, andre@0: * scope ENUMERATED { andre@0: * baseObject (0), andre@0: * singleLevel (1), andre@0: * wholeSubtree (2) andre@0: * }, andre@0: * derefAliases ENUMERATED { andre@0: * neverDerefAliases (0), andre@0: * derefInSearching (1), andre@0: * derefFindingBaseObj (2), andre@0: * alwaysDerefAliases (3) andre@0: * }, andre@0: * sizeLimit INTEGER (0 .. MAXINT), andre@0: * -- value of 0 implies no sizeLimit andre@0: * timeLimit INTEGER (0 .. MAXINT), andre@0: * -- value of 0 implies no timeLimit andre@0: * attrsOnly BOOLEAN, andre@0: * -- TRUE, if only attributes (without values) andre@0: * -- to be returned andre@0: * filter Filter, andre@0: * attributes SEQUENCE OF AttributeType andre@0: * } andre@0: */ andre@0: andre@0: static const SEC_ASN1Template LDAPAttributeTemplate[] = { andre@0: { SEC_ASN1_LDAP_STRING, 0, NULL, sizeof (SECItem) } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPSearchApplTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearch, baseObject) }, andre@0: { SEC_ASN1_ENUMERATED, offsetof(LDAPSearch, scope) }, andre@0: { SEC_ASN1_ENUMERATED, offsetof(LDAPSearch, derefAliases) }, andre@0: { SEC_ASN1_INTEGER, offsetof(LDAPSearch, sizeLimit) }, andre@0: { SEC_ASN1_INTEGER, offsetof(LDAPSearch, timeLimit) }, andre@0: { SEC_ASN1_BOOLEAN, offsetof(LDAPSearch, attrsOnly) }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPSearch, filter), LDAPFilterTemplate }, andre@0: { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSearch, attributes), LDAPAttributeTemplate }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPSearchTemplate[] = { andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_SEARCH_TYPE, 0, andre@0: LDAPSearchApplTemplate, sizeof (LDAPSearch) } andre@0: }; andre@0: andre@0: /* andre@0: * SearchResponse ::= andre@0: * CHOICE { andre@0: * entry [APPLICATION 4] SEQUENCE { andre@0: * objectName LDAPDN, andre@0: * attributes SEQUENCE OF SEQUENCE { andre@0: * AttributeType, andre@0: * SET OF AttributeValue andre@0: * } andre@0: * } andre@0: * resultCode [APPLICATION 5] LDAPResult andre@0: * } andre@0: */ andre@0: andre@0: static const SEC_ASN1Template LDAPSearchResponseAttrTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(LDAPSearchResponseAttr) }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearchResponseAttr, attrType) }, andre@0: { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(LDAPSearchResponseAttr, val), andre@0: LDAPStringTemplate }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPEntryTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL }, andre@0: { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearchResponseEntry, objectName) }, andre@0: { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSearchResponseEntry, attributes), andre@0: LDAPSearchResponseAttrTemplate }, andre@0: { 0 } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPSearchResponseEntryTemplate[] = { andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_SEARCHRESPONSEENTRY_TYPE, 0, andre@0: LDAPEntryTemplate, sizeof (LDAPSearchResponseEntry) } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPSearchResponseResultTemplate[] = { andre@0: { SEC_ASN1_APPLICATION | LDAP_SEARCHRESPONSERESULT_TYPE, 0, andre@0: LDAPResultTemplate, sizeof (LDAPSearchResponseResult) } andre@0: }; andre@0: andre@0: /* andre@0: * AbandonRequest ::= andre@0: * [APPLICATION 16] MessageID andre@0: */ andre@0: andre@0: static const SEC_ASN1Template LDAPAbandonTemplate[] = { andre@0: { SEC_ASN1_INTEGER, offsetof(LDAPAbandonRequest, messageID) } andre@0: }; andre@0: andre@0: static const SEC_ASN1Template LDAPAbandonRequestTemplate[] = { andre@0: { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_ABANDONREQUEST_TYPE, 0, andre@0: LDAPAbandonTemplate, sizeof (LDAPAbandonRequest) } andre@0: }; andre@0: andre@0: /* andre@0: * LDAPMessage ::= andre@0: * SEQUENCE { andre@0: * messageID MessageID, andre@0: * protocolOp CHOICE { andre@0: * bindRequest BindRequest, andre@0: * bindResponse BindResponse, andre@0: * unbindRequest UnbindRequest, andre@0: * searchRequest SearchRequest, andre@0: * searchResponse SearchResponse, andre@0: * abandonRequest AbandonRequest andre@0: * } andre@0: * } andre@0: * andre@0: * (other choices exist, not shown) andre@0: * andre@0: * MessageID ::= INTEGER (0 .. maxInt) andre@0: */ andre@0: andre@0: static const SEC_ASN1Template LDAPMessageProtocolOpTemplate[] = { andre@0: { SEC_ASN1_CHOICE, offsetof(LDAPProtocolOp, selector), 0, sizeof (LDAPProtocolOp) }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.bindMsg), andre@0: LDAPBindTemplate, LDAP_BIND_TYPE }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.bindResponseMsg), andre@0: LDAPBindResponseTemplate, LDAP_BINDRESPONSE_TYPE }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.unbindMsg), andre@0: LDAPUnbindTemplate, LDAP_UNBIND_TYPE }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchMsg), andre@0: LDAPSearchTemplate, LDAP_SEARCH_TYPE }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchResponseEntryMsg), andre@0: LDAPSearchResponseEntryTemplate, LDAP_SEARCHRESPONSEENTRY_TYPE }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchResponseResultMsg), andre@0: LDAPSearchResponseResultTemplate, LDAP_SEARCHRESPONSERESULT_TYPE }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.abandonRequestMsg), andre@0: LDAPAbandonRequestTemplate, LDAP_ABANDONREQUEST_TYPE }, andre@0: { 0 } andre@0: }; andre@0: andre@0: const SEC_ASN1Template PKIX_PL_LDAPMessageTemplate[] = { andre@0: { SEC_ASN1_SEQUENCE, 0, NULL }, andre@0: { SEC_ASN1_INTEGER, offsetof(LDAPMessage, messageID) }, andre@0: { SEC_ASN1_INLINE, offsetof(LDAPMessage, protocolOp), andre@0: LDAPMessageProtocolOpTemplate }, andre@0: { 0 } andre@0: }; andre@0: andre@0: /* This function simply returns the address of the message template. andre@0: * This is necessary for Windows DLLs. andre@0: */ andre@0: SEC_ASN1_CHOOSER_IMPLEMENT(PKIX_PL_LDAPMessageTemplate)