Created
January 18, 2011 07:32
-
-
Save chao/784095 to your computer and use it in GitHub Desktop.
Patch CouchDB to add LDAP authentication support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git LICENSE LICENSE | |
| index 20a425b..6a5c617 100644 | |
| --- LICENSE | |
| +++ LICENSE | |
| @@ -369,3 +369,25 @@ For the src/etap component: | |
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| OTHER DEALINGS IN THE SOFTWARE. | |
| +For the src/eldap component: | |
| + | |
| + Copyright (c) 2010, Torbjorn Tornkvist | |
| + | |
| + Permission is hereby granted, free of charge, to any person obtaining a | |
| + copy of this software and associated documentation files (the "Software"), | |
| + to deal | |
| + in the Software without restriction, including without limitation the rights | |
| + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| + copies of the Software, and to permit persons to whom the Software is | |
| + furnished to do so, subject to the following conditions: | |
| + | |
| + The above copyright notice and this permission notice shall be included in | |
| + all copies or substantial portions of the Software. | |
| + | |
| + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| + IN THE SOFTWARE. | |
| diff --git NOTICE NOTICE | |
| index d547e55..cbaef4d 100644 | |
| --- NOTICE | |
| +++ NOTICE | |
| @@ -30,6 +30,10 @@ This product also includes the following third-party components: | |
| Copyright 2009, Chandrashekhar Mullaparthi | |
| + * Eldap (http://github.com/etnt/eldap/tree/master) | |
| + | |
| + Copyright 2009, Torbjorn Tornkvist <etnt@redhoterlang.com> | |
| + | |
| * Erlang OAuth (http://github.com/tim/erlang-oauth/tree/master) | |
| Copyright 2009, Tim Fletcher <http://tfletcher.com/> | |
| diff --git configure.ac configure.ac | |
| index c609a08..a43b79e 100644 | |
| --- configure.ac | |
| +++ configure.ac | |
| @@ -398,6 +398,7 @@ AC_CONFIG_FILES([src/Makefile]) | |
| AC_CONFIG_FILES([src/couchdb/couch.app.tpl]) | |
| AC_CONFIG_FILES([src/couchdb/Makefile]) | |
| AC_CONFIG_FILES([src/couchdb/priv/Makefile]) | |
| +AC_CONFIG_FILES([src/eldap/Makefile]) | |
| AC_CONFIG_FILES([src/erlang-oauth/Makefile]) | |
| AC_CONFIG_FILES([src/etap/Makefile]) | |
| AC_CONFIG_FILES([src/ibrowse/Makefile]) | |
| diff --git license.skip license.skip | |
| index a7aa6ec..66ea237 100644 | |
| --- license.skip | |
| +++ license.skip | |
| @@ -82,6 +82,7 @@ | |
| ^src/couchdb/priv/couchjs | |
| ^src/couchdb/priv/couchspawnkillable | |
| ^src/couchdb/priv/stat_descriptions.cfg | |
| +^src/eldap/* | |
| ^src/erlang-oauth/* | |
| ^src/etap/* | |
| ^src/ibrowse/* | |
| diff --git src/Makefile.am src/Makefile.am | |
| index b9529f9..525be09 100644 | |
| --- src/Makefile.am | |
| +++ src/Makefile.am | |
| @@ -10,4 +10,4 @@ | |
| ## License for the specific language governing permissions and limitations under | |
| ## the License. | |
| -SUBDIRS = couchdb erlang-oauth etap ibrowse mochiweb | |
| +SUBDIRS = couchdb eldap erlang-oauth etap ibrowse mochiweb | |
| diff --git src/couchdb/couch_httpd_auth.erl src/couchdb/couch_httpd_auth.erl | |
| index 7023e7f..4472435 100644 | |
| --- src/couchdb/couch_httpd_auth.erl | |
| +++ src/couchdb/couch_httpd_auth.erl | |
| @@ -14,6 +14,7 @@ | |
| -include("couch_db.hrl"). | |
| -export([default_authentication_handler/1,special_test_authentication_handler/1]). | |
| +-export ([ldap_authentication_handler/1]). | |
| -export([cookie_authentication_handler/1]). | |
| -export([null_authentication_handler/1]). | |
| -export([proxy_authentification_handler/1]). | |
| @@ -347,3 +348,100 @@ to_int(Value) when is_integer(Value) -> | |
| make_cookie_time() -> | |
| {NowMS, NowS, _} = erlang:now(), | |
| NowMS * 1000000 + NowS. | |
| + | |
| +ldap_authentication_handler(Req) -> | |
| + LDAPUrl = couch_config:get | |
| + ("couch_httpd_auth", "auth_ldap_url", | |
| + "false"), | |
| + case LDAPUrl of | |
| + "false" -> | |
| + throw({error, "No auth_ldap_url defined."}); | |
| + _ -> | |
| + case basic_name_pw(Req) of | |
| + {User, Pass} -> | |
| + try eldap:parse_ldap_url(LDAPUrl) of | |
| + {ok, LDAPServer, LDAPBindname, {attributes, [Attrdesc]}} -> | |
| + {LDAPHost, LDAPPort} = LDAPServer, | |
| + case length(LDAPBindname) of | |
| + 0-> | |
| + throw({error, "LDAP URL is not correct."}); | |
| + _-> | |
| + BaseDN = concat_bindname(LDAPBindname), | |
| + %?LOG_INFO("Host:~p, Port:~p ~n BaseDN: ~p ~n LDAPAttributes: ~p ~n", [LDAPHost, LDAPPort, BaseDN, Attrdesc]), | |
| + case eldap:open([LDAPHost], [{port, LDAPPort}]) of | |
| + {ok, LDAPHandler} -> | |
| + UserDNList = lists:append([Attrdesc ++ "=" ++ User], BaseDN), | |
| + UserDN = string_join(",", UserDNList), | |
| + %?LOG_INFO("UserDN : ~p ~n", [UserDN]), | |
| + case eldap:simple_bind(LDAPHandler, UserDN, Pass) of | |
| + ok -> | |
| + StrBaseDN = string_join(",", BaseDN), | |
| + %?LOG_INFO("Connected to LDAP Server with UserDN: ~p, Pass: ~p", [UserDN, Pass]), | |
| + {ok, {eldap_search_result, LDAPSearchResult, []}} = eldap:search(LDAPHandler, | |
| + [{base, StrBaseDN}, | |
| + {filter, eldap:equalityMatch("member", UserDN)}, | |
| + {attributes, [Attrdesc]}]), | |
| + %?LOG_INFO("LDAPSearchResult: ~p", [LDAPSearchResult]), | |
| + case length(LDAPSearchResult) of | |
| + 0 -> | |
| + Req#httpd{user_ctx=#user_ctx{name=?l2b(User)}}; | |
| + _ -> | |
| + Roles = ldap_groups(LDAPSearchResult, []), | |
| + %?LOG_INFO("User: ~p Roles:~p", [User, Roles]), | |
| + Req#httpd{user_ctx=#user_ctx{name=?l2b(User), roles=Roles}} | |
| + end; | |
| + {error,invalidCredentials} -> | |
| + throw({unauthorized, <<"Name or password is incorrect.">>}); | |
| + _ -> | |
| + throw({error, "Unable to validate user on LDAP server."}) | |
| + end; | |
| + _-> | |
| + ?LOG_ERROR("Unable to connect to LDAP, Host: ~p Port: ~p", [LDAPHost, LDAPPort]), | |
| + throw({error, "Unable to bind to LDAP server."}) | |
| + end | |
| + end | |
| + catch | |
| + error: _ -> | |
| + throw({error, "LDAP URL parse error."}) | |
| + end; | |
| + nil -> | |
| + case couch_server:has_admins() of | |
| + true -> | |
| + %?LOG_INFO("has admins",[]), | |
| + Req; | |
| + false -> | |
| + %?LOG_INFO("has no admin",[]), | |
| + case couch_config:get("couch_httpd_auth", "require_valid_user", "false") of | |
| + "true" -> | |
| + %?LOG_INFO("require valid user",[]), | |
| + Req; | |
| + _ -> | |
| + %?LOG_INFO("don't require valid user",[]), | |
| + Req#httpd{user_ctx=#user_ctx{roles=[<<"_admin">>]}} | |
| + end | |
| + end | |
| + end | |
| + end. | |
| +ldap_groups([], Acc) -> | |
| + [list_to_binary(R) || R<-Acc]; | |
| +ldap_groups([C | Rest], Acc) -> | |
| + {eldap_entry,LDAPRecord, [{_, [GroupAttr]}]} = C, | |
| + ldap_groups(Rest, [GroupAttr | Acc]). | |
| + | |
| +concat_bindname(Bindname) -> | |
| + concat_bindname(Bindname, []). | |
| +concat_bindname([], Acc) -> lists:reverse(Acc); | |
| + %[list_to_binary(R) || R<-lists:reverse(Acc)]; | |
| +concat_bindname([C | Rest], Acc) -> | |
| + [{attribute_type_and_value, Name, Value}] = C, | |
| + concat_bindname(Rest, [Name ++ "=" ++ Value | Acc]). | |
| + | |
| +string_join(Join, L) -> | |
| + string_join(Join, L, fun(E) -> E end). | |
| + | |
| +string_join(_Join, L=[], _Conv) -> | |
| + L; | |
| +string_join(Join, [H|Q], Conv) -> | |
| + lists:flatten(lists:concat( | |
| + [Conv(H)|lists:map(fun(E) -> [Join, Conv(E)] end, Q)] | |
| + )). | |
| \ No newline at end of file | |
| diff --git src/eldap/ELDAPv3.erl src/eldap/ELDAPv3.erl | |
| new file mode 100644 | |
| index 0000000..e18ee38 | |
| --- /dev/null | |
| +++ src/eldap/ELDAPv3.erl | |
| @@ -0,0 +1,3011 @@ | |
| +%% Generated by the Erlang ASN.1 BER-compiler version:1.6.15 | |
| +%% Purpose: encoder and decoder to the types in mod ELDAPv3 | |
| + | |
| +-module('ELDAPv3'). | |
| +-include("ELDAPv3.hrl"). | |
| +-define('RT_BER',asn1rt_ber_bin). | |
| +-asn1_info([{vsn,'1.6.15'}, | |
| + {module,'ELDAPv3'}, | |
| + {options,[ber,report_errors,{cwd,[47,85,115,101,114,115,47,99,104,97,111,47,80,114,111,106,101,99,116,115,47,106,117,110,103,101,114,108,47,108,105,98,47,101,108,100,97,112,47,115,114,99]},{outdir,[47,85,115,101,114,115,47,99,104,97,111,47,80,114,111,106,101,99,116,115,47,106,117,110,103,101,114,108,47,108,105,98,47,101,108,100,97,112,47,115,114,99]},{i,[46]},{i,[47,85,115,101,114,115,47,99,104,97,111,47,80,114,111,106,101,99,116,115,47,106,117,110,103,101,114,108,47,108,105,98,47,101,108,100,97,112,47,115,114,99]}]}]). | |
| + | |
| +-export([encoding_rule/0]). | |
| +-export([ | |
| +'enc_LDAPMessage'/2, | |
| +'enc_MessageID'/2, | |
| +'enc_LDAPString'/2, | |
| +'enc_LDAPOID'/2, | |
| +'enc_LDAPDN'/2, | |
| +'enc_RelativeLDAPDN'/2, | |
| +'enc_AttributeType'/2, | |
| +'enc_AttributeDescription'/2, | |
| +'enc_AttributeDescriptionList'/2, | |
| +'enc_AttributeValue'/2, | |
| +'enc_AttributeValueAssertion'/2, | |
| +'enc_AssertionValue'/2, | |
| +'enc_Attribute'/2, | |
| +'enc_MatchingRuleId'/2, | |
| +'enc_LDAPResult'/2, | |
| +'enc_Referral'/2, | |
| +'enc_LDAPURL'/2, | |
| +'enc_Controls'/2, | |
| +'enc_Control'/2, | |
| +'enc_BindRequest'/2, | |
| +'enc_AuthenticationChoice'/2, | |
| +'enc_SaslCredentials'/2, | |
| +'enc_BindResponse'/2, | |
| +'enc_UnbindRequest'/2, | |
| +'enc_SearchRequest'/2, | |
| +'enc_Filter'/2, | |
| +'enc_SubstringFilter'/2, | |
| +'enc_MatchingRuleAssertion'/2, | |
| +'enc_SearchResultEntry'/2, | |
| +'enc_PartialAttributeList'/2, | |
| +'enc_SearchResultReference'/2, | |
| +'enc_SearchResultDone'/2, | |
| +'enc_ModifyRequest'/2, | |
| +'enc_AttributeTypeAndValues'/2, | |
| +'enc_ModifyResponse'/2, | |
| +'enc_AddRequest'/2, | |
| +'enc_AttributeList'/2, | |
| +'enc_AddResponse'/2, | |
| +'enc_DelRequest'/2, | |
| +'enc_DelResponse'/2, | |
| +'enc_ModifyDNRequest'/2, | |
| +'enc_ModifyDNResponse'/2, | |
| +'enc_CompareRequest'/2, | |
| +'enc_CompareResponse'/2, | |
| +'enc_AbandonRequest'/2, | |
| +'enc_ExtendedRequest'/2, | |
| +'enc_ExtendedResponse'/2 | |
| +]). | |
| + | |
| +-export([ | |
| +'dec_LDAPMessage'/2, | |
| +'dec_MessageID'/2, | |
| +'dec_LDAPString'/2, | |
| +'dec_LDAPOID'/2, | |
| +'dec_LDAPDN'/2, | |
| +'dec_RelativeLDAPDN'/2, | |
| +'dec_AttributeType'/2, | |
| +'dec_AttributeDescription'/2, | |
| +'dec_AttributeDescriptionList'/2, | |
| +'dec_AttributeValue'/2, | |
| +'dec_AttributeValueAssertion'/2, | |
| +'dec_AssertionValue'/2, | |
| +'dec_Attribute'/2, | |
| +'dec_MatchingRuleId'/2, | |
| +'dec_LDAPResult'/2, | |
| +'dec_Referral'/2, | |
| +'dec_LDAPURL'/2, | |
| +'dec_Controls'/2, | |
| +'dec_Control'/2, | |
| +'dec_BindRequest'/2, | |
| +'dec_AuthenticationChoice'/2, | |
| +'dec_SaslCredentials'/2, | |
| +'dec_BindResponse'/2, | |
| +'dec_UnbindRequest'/2, | |
| +'dec_SearchRequest'/2, | |
| +'dec_Filter'/2, | |
| +'dec_SubstringFilter'/2, | |
| +'dec_MatchingRuleAssertion'/2, | |
| +'dec_SearchResultEntry'/2, | |
| +'dec_PartialAttributeList'/2, | |
| +'dec_SearchResultReference'/2, | |
| +'dec_SearchResultDone'/2, | |
| +'dec_ModifyRequest'/2, | |
| +'dec_AttributeTypeAndValues'/2, | |
| +'dec_ModifyResponse'/2, | |
| +'dec_AddRequest'/2, | |
| +'dec_AttributeList'/2, | |
| +'dec_AddResponse'/2, | |
| +'dec_DelRequest'/2, | |
| +'dec_DelResponse'/2, | |
| +'dec_ModifyDNRequest'/2, | |
| +'dec_ModifyDNResponse'/2, | |
| +'dec_CompareRequest'/2, | |
| +'dec_CompareResponse'/2, | |
| +'dec_AbandonRequest'/2, | |
| +'dec_ExtendedRequest'/2, | |
| +'dec_ExtendedResponse'/2 | |
| +]). | |
| + | |
| +-export([ | |
| +'dec_LDAPMessage'/3, | |
| +'dec_MessageID'/3, | |
| +'dec_LDAPString'/3, | |
| +'dec_LDAPOID'/3, | |
| +'dec_LDAPDN'/3, | |
| +'dec_RelativeLDAPDN'/3, | |
| +'dec_AttributeType'/3, | |
| +'dec_AttributeDescription'/3, | |
| +'dec_AttributeDescriptionList'/3, | |
| +'dec_AttributeValue'/3, | |
| +'dec_AttributeValueAssertion'/3, | |
| +'dec_AssertionValue'/3, | |
| +'dec_Attribute'/3, | |
| +'dec_MatchingRuleId'/3, | |
| +'dec_LDAPResult'/3, | |
| +'dec_Referral'/3, | |
| +'dec_LDAPURL'/3, | |
| +'dec_Controls'/3, | |
| +'dec_Control'/3, | |
| +'dec_BindRequest'/3, | |
| +'dec_AuthenticationChoice'/3, | |
| +'dec_SaslCredentials'/3, | |
| +'dec_BindResponse'/3, | |
| +'dec_UnbindRequest'/3, | |
| +'dec_SearchRequest'/3, | |
| +'dec_Filter'/3, | |
| +'dec_SubstringFilter'/3, | |
| +'dec_MatchingRuleAssertion'/3, | |
| +'dec_SearchResultEntry'/3, | |
| +'dec_PartialAttributeList'/3, | |
| +'dec_SearchResultReference'/3, | |
| +'dec_SearchResultDone'/3, | |
| +'dec_ModifyRequest'/3, | |
| +'dec_AttributeTypeAndValues'/3, | |
| +'dec_ModifyResponse'/3, | |
| +'dec_AddRequest'/3, | |
| +'dec_AttributeList'/3, | |
| +'dec_AddResponse'/3, | |
| +'dec_DelRequest'/3, | |
| +'dec_DelResponse'/3, | |
| +'dec_ModifyDNRequest'/3, | |
| +'dec_ModifyDNResponse'/3, | |
| +'dec_CompareRequest'/3, | |
| +'dec_CompareResponse'/3, | |
| +'dec_AbandonRequest'/3, | |
| +'dec_ExtendedRequest'/3, | |
| +'dec_ExtendedResponse'/3 | |
| +]). | |
| + | |
| +-export([ | |
| +'maxInt'/0 | |
| +]). | |
| + | |
| +-export([info/0]). | |
| + | |
| + | |
| +-export([encode/2,decode/2,encode_disp/2,decode_disp/2]). | |
| + | |
| +encoding_rule() -> | |
| + ber. | |
| + | |
| +encode(Type,Data) -> | |
| +case catch encode_disp(Type,Data) of | |
| + {'EXIT',{error,Reason}} -> | |
| + {error,Reason}; | |
| + {'EXIT',Reason} -> | |
| + {error,{asn1,Reason}}; | |
| + {Bytes,_Len} -> | |
| + {ok,wrap_encode(Bytes)}; | |
| + Bytes -> | |
| + {ok,wrap_encode(Bytes)} | |
| +end. | |
| + | |
| +decode(Type,Data) -> | |
| +case catch decode_disp(Type,wrap_decode(Data)) of | |
| + {'EXIT',{error,Reason}} -> | |
| + {error,Reason}; | |
| + {'EXIT',Reason} -> | |
| + {error,{asn1,Reason}}; | |
| + {X,_Rest} -> | |
| + {ok,X}; | |
| + {X,_Rest,_Len} -> | |
| + {ok,X} | |
| +end. | |
| + | |
| +encode_disp('LDAPMessage',Data) -> 'enc_LDAPMessage'(Data,[]); | |
| +encode_disp('MessageID',Data) -> 'enc_MessageID'(Data,[]); | |
| +encode_disp('LDAPString',Data) -> 'enc_LDAPString'(Data,[]); | |
| +encode_disp('LDAPOID',Data) -> 'enc_LDAPOID'(Data,[]); | |
| +encode_disp('LDAPDN',Data) -> 'enc_LDAPDN'(Data,[]); | |
| +encode_disp('RelativeLDAPDN',Data) -> 'enc_RelativeLDAPDN'(Data,[]); | |
| +encode_disp('AttributeType',Data) -> 'enc_AttributeType'(Data,[]); | |
| +encode_disp('AttributeDescription',Data) -> 'enc_AttributeDescription'(Data,[]); | |
| +encode_disp('AttributeDescriptionList',Data) -> 'enc_AttributeDescriptionList'(Data,[]); | |
| +encode_disp('AttributeValue',Data) -> 'enc_AttributeValue'(Data,[]); | |
| +encode_disp('AttributeValueAssertion',Data) -> 'enc_AttributeValueAssertion'(Data,[]); | |
| +encode_disp('AssertionValue',Data) -> 'enc_AssertionValue'(Data,[]); | |
| +encode_disp('Attribute',Data) -> 'enc_Attribute'(Data,[]); | |
| +encode_disp('MatchingRuleId',Data) -> 'enc_MatchingRuleId'(Data,[]); | |
| +encode_disp('LDAPResult',Data) -> 'enc_LDAPResult'(Data,[]); | |
| +encode_disp('Referral',Data) -> 'enc_Referral'(Data,[]); | |
| +encode_disp('LDAPURL',Data) -> 'enc_LDAPURL'(Data,[]); | |
| +encode_disp('Controls',Data) -> 'enc_Controls'(Data,[]); | |
| +encode_disp('Control',Data) -> 'enc_Control'(Data,[]); | |
| +encode_disp('BindRequest',Data) -> 'enc_BindRequest'(Data,[]); | |
| +encode_disp('AuthenticationChoice',Data) -> 'enc_AuthenticationChoice'(Data,[]); | |
| +encode_disp('SaslCredentials',Data) -> 'enc_SaslCredentials'(Data,[]); | |
| +encode_disp('BindResponse',Data) -> 'enc_BindResponse'(Data,[]); | |
| +encode_disp('UnbindRequest',Data) -> 'enc_UnbindRequest'(Data,[]); | |
| +encode_disp('SearchRequest',Data) -> 'enc_SearchRequest'(Data,[]); | |
| +encode_disp('Filter',Data) -> 'enc_Filter'(Data,[]); | |
| +encode_disp('SubstringFilter',Data) -> 'enc_SubstringFilter'(Data,[]); | |
| +encode_disp('MatchingRuleAssertion',Data) -> 'enc_MatchingRuleAssertion'(Data,[]); | |
| +encode_disp('SearchResultEntry',Data) -> 'enc_SearchResultEntry'(Data,[]); | |
| +encode_disp('PartialAttributeList',Data) -> 'enc_PartialAttributeList'(Data,[]); | |
| +encode_disp('SearchResultReference',Data) -> 'enc_SearchResultReference'(Data,[]); | |
| +encode_disp('SearchResultDone',Data) -> 'enc_SearchResultDone'(Data,[]); | |
| +encode_disp('ModifyRequest',Data) -> 'enc_ModifyRequest'(Data,[]); | |
| +encode_disp('AttributeTypeAndValues',Data) -> 'enc_AttributeTypeAndValues'(Data,[]); | |
| +encode_disp('ModifyResponse',Data) -> 'enc_ModifyResponse'(Data,[]); | |
| +encode_disp('AddRequest',Data) -> 'enc_AddRequest'(Data,[]); | |
| +encode_disp('AttributeList',Data) -> 'enc_AttributeList'(Data,[]); | |
| +encode_disp('AddResponse',Data) -> 'enc_AddResponse'(Data,[]); | |
| +encode_disp('DelRequest',Data) -> 'enc_DelRequest'(Data,[]); | |
| +encode_disp('DelResponse',Data) -> 'enc_DelResponse'(Data,[]); | |
| +encode_disp('ModifyDNRequest',Data) -> 'enc_ModifyDNRequest'(Data,[]); | |
| +encode_disp('ModifyDNResponse',Data) -> 'enc_ModifyDNResponse'(Data,[]); | |
| +encode_disp('CompareRequest',Data) -> 'enc_CompareRequest'(Data,[]); | |
| +encode_disp('CompareResponse',Data) -> 'enc_CompareResponse'(Data,[]); | |
| +encode_disp('AbandonRequest',Data) -> 'enc_AbandonRequest'(Data,[]); | |
| +encode_disp('ExtendedRequest',Data) -> 'enc_ExtendedRequest'(Data,[]); | |
| +encode_disp('ExtendedResponse',Data) -> 'enc_ExtendedResponse'(Data,[]); | |
| +encode_disp(Type,_Data) -> exit({error,{asn1,{undefined_type,Type}}}). | |
| + | |
| + | |
| +decode_disp('LDAPMessage',Data) -> 'dec_LDAPMessage'(Data,mandatory); | |
| +decode_disp('MessageID',Data) -> 'dec_MessageID'(Data,mandatory); | |
| +decode_disp('LDAPString',Data) -> 'dec_LDAPString'(Data,mandatory); | |
| +decode_disp('LDAPOID',Data) -> 'dec_LDAPOID'(Data,mandatory); | |
| +decode_disp('LDAPDN',Data) -> 'dec_LDAPDN'(Data,mandatory); | |
| +decode_disp('RelativeLDAPDN',Data) -> 'dec_RelativeLDAPDN'(Data,mandatory); | |
| +decode_disp('AttributeType',Data) -> 'dec_AttributeType'(Data,mandatory); | |
| +decode_disp('AttributeDescription',Data) -> 'dec_AttributeDescription'(Data,mandatory); | |
| +decode_disp('AttributeDescriptionList',Data) -> 'dec_AttributeDescriptionList'(Data,mandatory); | |
| +decode_disp('AttributeValue',Data) -> 'dec_AttributeValue'(Data,mandatory); | |
| +decode_disp('AttributeValueAssertion',Data) -> 'dec_AttributeValueAssertion'(Data,mandatory); | |
| +decode_disp('AssertionValue',Data) -> 'dec_AssertionValue'(Data,mandatory); | |
| +decode_disp('Attribute',Data) -> 'dec_Attribute'(Data,mandatory); | |
| +decode_disp('MatchingRuleId',Data) -> 'dec_MatchingRuleId'(Data,mandatory); | |
| +decode_disp('LDAPResult',Data) -> 'dec_LDAPResult'(Data,mandatory); | |
| +decode_disp('Referral',Data) -> 'dec_Referral'(Data,mandatory); | |
| +decode_disp('LDAPURL',Data) -> 'dec_LDAPURL'(Data,mandatory); | |
| +decode_disp('Controls',Data) -> 'dec_Controls'(Data,mandatory); | |
| +decode_disp('Control',Data) -> 'dec_Control'(Data,mandatory); | |
| +decode_disp('BindRequest',Data) -> 'dec_BindRequest'(Data,mandatory); | |
| +decode_disp('AuthenticationChoice',Data) -> 'dec_AuthenticationChoice'(Data,mandatory); | |
| +decode_disp('SaslCredentials',Data) -> 'dec_SaslCredentials'(Data,mandatory); | |
| +decode_disp('BindResponse',Data) -> 'dec_BindResponse'(Data,mandatory); | |
| +decode_disp('UnbindRequest',Data) -> 'dec_UnbindRequest'(Data,mandatory); | |
| +decode_disp('SearchRequest',Data) -> 'dec_SearchRequest'(Data,mandatory); | |
| +decode_disp('Filter',Data) -> 'dec_Filter'(Data,mandatory); | |
| +decode_disp('SubstringFilter',Data) -> 'dec_SubstringFilter'(Data,mandatory); | |
| +decode_disp('MatchingRuleAssertion',Data) -> 'dec_MatchingRuleAssertion'(Data,mandatory); | |
| +decode_disp('SearchResultEntry',Data) -> 'dec_SearchResultEntry'(Data,mandatory); | |
| +decode_disp('PartialAttributeList',Data) -> 'dec_PartialAttributeList'(Data,mandatory); | |
| +decode_disp('SearchResultReference',Data) -> 'dec_SearchResultReference'(Data,mandatory); | |
| +decode_disp('SearchResultDone',Data) -> 'dec_SearchResultDone'(Data,mandatory); | |
| +decode_disp('ModifyRequest',Data) -> 'dec_ModifyRequest'(Data,mandatory); | |
| +decode_disp('AttributeTypeAndValues',Data) -> 'dec_AttributeTypeAndValues'(Data,mandatory); | |
| +decode_disp('ModifyResponse',Data) -> 'dec_ModifyResponse'(Data,mandatory); | |
| +decode_disp('AddRequest',Data) -> 'dec_AddRequest'(Data,mandatory); | |
| +decode_disp('AttributeList',Data) -> 'dec_AttributeList'(Data,mandatory); | |
| +decode_disp('AddResponse',Data) -> 'dec_AddResponse'(Data,mandatory); | |
| +decode_disp('DelRequest',Data) -> 'dec_DelRequest'(Data,mandatory); | |
| +decode_disp('DelResponse',Data) -> 'dec_DelResponse'(Data,mandatory); | |
| +decode_disp('ModifyDNRequest',Data) -> 'dec_ModifyDNRequest'(Data,mandatory); | |
| +decode_disp('ModifyDNResponse',Data) -> 'dec_ModifyDNResponse'(Data,mandatory); | |
| +decode_disp('CompareRequest',Data) -> 'dec_CompareRequest'(Data,mandatory); | |
| +decode_disp('CompareResponse',Data) -> 'dec_CompareResponse'(Data,mandatory); | |
| +decode_disp('AbandonRequest',Data) -> 'dec_AbandonRequest'(Data,mandatory); | |
| +decode_disp('ExtendedRequest',Data) -> 'dec_ExtendedRequest'(Data,mandatory); | |
| +decode_disp('ExtendedResponse',Data) -> 'dec_ExtendedResponse'(Data,mandatory); | |
| +decode_disp(Type,_Data) -> exit({error,{asn1,{undefined_type,Type}}}). | |
| + | |
| + | |
| + | |
| +wrap_encode(Bytes) when is_list(Bytes) -> | |
| + binary_to_list(list_to_binary(Bytes)); | |
| +wrap_encode(Bytes) when is_binary(Bytes) -> | |
| + binary_to_list(Bytes); | |
| +wrap_encode(Bytes) -> Bytes. | |
| + | |
| +wrap_decode(Bytes) when is_list(Bytes) -> | |
| + list_to_binary(Bytes); | |
| +wrap_decode(Bytes) -> Bytes. | |
| + | |
| + | |
| +info() -> | |
| + case ?MODULE:module_info() of | |
| + MI when is_list(MI) -> | |
| + case lists:keysearch(attributes,1,MI) of | |
| + {value,{_,Attributes}} when is_list(Attributes) -> | |
| + case lists:keysearch(asn1_info,1,Attributes) of | |
| + {value,{_,Info}} when is_list(Info) -> | |
| + Info; | |
| + _ -> | |
| + [] | |
| + end; | |
| + _ -> | |
| + [] | |
| + end | |
| + end. | |
| + | |
| + | |
| +%%================================ | |
| +%% LDAPMessage | |
| +%%================================ | |
| +'enc_LDAPMessage'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_integer([], ?RT_BER:cindex(2,Val,messageID), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type CHOICE | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_LDAPMessage_protocolOp'(?RT_BER:cindex(3,Val,protocolOp), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 External ELDAPv3:Controls OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = case ?RT_BER:cindex(4,Val,controls) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + 'enc_Controls'(?RT_BER:cindex(4,Val,controls), [{tag,128,0,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% LDAPMessage_protocolOp | |
| +%%================================ | |
| + | |
| +'enc_LDAPMessage_protocolOp'({'LDAPMessage_protocolOp',Val}, TagIn) -> | |
| + 'enc_LDAPMessage_protocolOp'(Val, TagIn); | |
| + | |
| +'enc_LDAPMessage_protocolOp'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = case element(1,Val) of | |
| + bindRequest -> | |
| + 'enc_BindRequest'(element(2,Val), []); | |
| + bindResponse -> | |
| + 'enc_BindResponse'(element(2,Val), []); | |
| + unbindRequest -> | |
| + ?RT_BER:encode_null(element(2,Val), [{tag,64,2,'IMPLICIT',32}]); | |
| + searchRequest -> | |
| + 'enc_SearchRequest'(element(2,Val), []); | |
| + searchResEntry -> | |
| + 'enc_SearchResultEntry'(element(2,Val), []); | |
| + searchResDone -> | |
| + 'enc_SearchResultDone'(element(2,Val), []); | |
| + searchResRef -> | |
| + 'enc_SearchResultReference'(element(2,Val), []); | |
| + modifyRequest -> | |
| + 'enc_ModifyRequest'(element(2,Val), []); | |
| + modifyResponse -> | |
| + 'enc_ModifyResponse'(element(2,Val), []); | |
| + addRequest -> | |
| + 'enc_AddRequest'(element(2,Val), []); | |
| + addResponse -> | |
| + 'enc_AddResponse'(element(2,Val), []); | |
| + delRequest -> | |
| + ?RT_BER:encode_octet_string([], element(2,Val), [{tag,64,10,'IMPLICIT',32}]); | |
| + delResponse -> | |
| + 'enc_DelResponse'(element(2,Val), []); | |
| + modDNRequest -> | |
| + 'enc_ModifyDNRequest'(element(2,Val), []); | |
| + modDNResponse -> | |
| + 'enc_ModifyDNResponse'(element(2,Val), []); | |
| + compareRequest -> | |
| + 'enc_CompareRequest'(element(2,Val), []); | |
| + compareResponse -> | |
| + 'enc_CompareResponse'(element(2,Val), []); | |
| + abandonRequest -> | |
| + ?RT_BER:encode_integer([], element(2,Val), [{tag,64,16,'IMPLICIT',32}]); | |
| + extendedReq -> | |
| + 'enc_ExtendedRequest'(element(2,Val), []); | |
| + extendedResp -> | |
| + 'enc_ExtendedResponse'(element(2,Val), []); | |
| + Else -> | |
| + exit({error,{asn1,{invalid_choice_type,Else}}}) | |
| + end, | |
| + | |
| +?RT_BER:encode_tags(TagIn ++[], EncBytes, EncLen). | |
| + | |
| + | |
| +'dec_LDAPMessage_protocolOp'(Bytes, OptOrMand, TagIn) -> | |
| + {{_,Len},Bytes1, RbExp} = ?RT_BER:check_tags(TagIn++[], Bytes, OptOrMand), | |
| + IndefEndBytes = fun(indefinite,<<0,0,R/binary>>)-> R; (_,B)-> B end, | |
| + IndefEndRb = fun(indefinite,<<0,0,_R/binary>>)-> 2; (_,_)-> 0 end, | |
| + case Bytes1 of | |
| + | |
| +%% 'bindRequest' | |
| + <<1:2,_:1,0:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_BindRequest'(Bytes1, mandatory, []), | |
| + {{bindRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'bindResponse' | |
| + <<1:2,_:1,1:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_BindResponse'(Bytes1, mandatory, []), | |
| + {{bindResponse, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'unbindRequest' | |
| + <<1:2,_:1,2:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_null(Bytes1,[{tag,64,2,'IMPLICIT',32}], mandatory), | |
| + {{unbindRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'searchRequest' | |
| + <<1:2,_:1,3:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_SearchRequest'(Bytes1, mandatory, []), | |
| + {{searchRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'searchResEntry' | |
| + <<1:2,_:1,4:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_SearchResultEntry'(Bytes1, mandatory, []), | |
| + {{searchResEntry, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'searchResDone' | |
| + <<1:2,_:1,5:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_SearchResultDone'(Bytes1, mandatory, []), | |
| + {{searchResDone, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'searchResRef' | |
| + <<1:2,_:1,19:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_SearchResultReference'(Bytes1, mandatory, []), | |
| + {{searchResRef, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'modifyRequest' | |
| + <<1:2,_:1,6:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_ModifyRequest'(Bytes1, mandatory, []), | |
| + {{modifyRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'modifyResponse' | |
| + <<1:2,_:1,7:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_ModifyResponse'(Bytes1, mandatory, []), | |
| + {{modifyResponse, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'addRequest' | |
| + <<1:2,_:1,8:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_AddRequest'(Bytes1, mandatory, []), | |
| + {{addRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'addResponse' | |
| + <<1:2,_:1,9:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_AddResponse'(Bytes1, mandatory, []), | |
| + {{addResponse, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'delRequest' | |
| + <<1:2,_:1,10:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_octet_string(Bytes1,[],[{tag,64,10,'IMPLICIT',32}], no_length, mandatory), | |
| + {{delRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'delResponse' | |
| + <<1:2,_:1,11:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_DelResponse'(Bytes1, mandatory, []), | |
| + {{delResponse, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'modDNRequest' | |
| + <<1:2,_:1,12:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_ModifyDNRequest'(Bytes1, mandatory, []), | |
| + {{modDNRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'modDNResponse' | |
| + <<1:2,_:1,13:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_ModifyDNResponse'(Bytes1, mandatory, []), | |
| + {{modDNResponse, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'compareRequest' | |
| + <<1:2,_:1,14:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_CompareRequest'(Bytes1, mandatory, []), | |
| + {{compareRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'compareResponse' | |
| + <<1:2,_:1,15:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_CompareResponse'(Bytes1, mandatory, []), | |
| + {{compareResponse, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'abandonRequest' | |
| + <<1:2,_:1,16:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_integer(Bytes1,{0,2147483647},[{tag,64,16,'IMPLICIT',32}], mandatory), | |
| + {{abandonRequest, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'extendedReq' | |
| + <<1:2,_:1,23:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_ExtendedRequest'(Bytes1, mandatory, []), | |
| + {{extendedReq, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'extendedResp' | |
| + <<1:2,_:1,24:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_ExtendedResponse'(Bytes1, mandatory, []), | |
| + {{extendedResp, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + Else -> | |
| + case OptOrMand of | |
| + mandatory ->exit({error,{asn1,{invalid_choice_tag,Else}}}); | |
| + _ ->exit({error,{asn1,{no_optional_tag,Else}}}) | |
| + end | |
| + end. | |
| + | |
| + | |
| +'dec_LDAPMessage'(Bytes, OptOrMand) -> | |
| + 'dec_LDAPMessage'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_LDAPMessage'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_integer(Bytes2,{0,2147483647},[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type CHOICE | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_LDAPMessage_protocolOp'(Bytes3, mandatory, []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 External ELDAPv3:Controls OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = case Bytes4 of | |
| +<<2:2,_:1,0:5,_/binary>> -> | |
| +'dec_Controls'(Bytes4, opt_or_default, [{tag,128,0,'IMPLICIT',32}]); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes4, 0 } | |
| +end, | |
| + | |
| + {Bytes6,Rb5} = ?RT_BER:restbytes2(RemBytes, Bytes5,noext), | |
| + {{'LDAPMessage', Term1, Term2, Term3}, Bytes6, Rb1+Rb2+Rb3+Rb4+Rb5}. | |
| + | |
| + | |
| +%%================================ | |
| +%% MessageID | |
| +%%================================ | |
| + | |
| +'enc_MessageID'({'MessageID',Val}, TagIn) -> | |
| + 'enc_MessageID'(Val, TagIn); | |
| + | |
| +'enc_MessageID'(Val, TagIn) -> | |
| +?RT_BER:encode_integer([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_MessageID'(Bytes, OptOrMand) -> | |
| + 'dec_MessageID'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_MessageID'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_integer(Bytes,{0,2147483647},TagIn++[], OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% LDAPString | |
| +%%================================ | |
| + | |
| +'enc_LDAPString'({'LDAPString',Val}, TagIn) -> | |
| + 'enc_LDAPString'(Val, TagIn); | |
| + | |
| +'enc_LDAPString'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_LDAPString'(Bytes, OptOrMand) -> | |
| + 'dec_LDAPString'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_LDAPString'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% LDAPOID | |
| +%%================================ | |
| + | |
| +'enc_LDAPOID'({'LDAPOID',Val}, TagIn) -> | |
| + 'enc_LDAPOID'(Val, TagIn); | |
| + | |
| +'enc_LDAPOID'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_LDAPOID'(Bytes, OptOrMand) -> | |
| + 'dec_LDAPOID'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_LDAPOID'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% LDAPDN | |
| +%%================================ | |
| + | |
| +'enc_LDAPDN'({'LDAPDN',Val}, TagIn) -> | |
| + 'enc_LDAPDN'(Val, TagIn); | |
| + | |
| +'enc_LDAPDN'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_LDAPDN'(Bytes, OptOrMand) -> | |
| + 'dec_LDAPDN'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_LDAPDN'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% RelativeLDAPDN | |
| +%%================================ | |
| + | |
| +'enc_RelativeLDAPDN'({'RelativeLDAPDN',Val}, TagIn) -> | |
| + 'enc_RelativeLDAPDN'(Val, TagIn); | |
| + | |
| +'enc_RelativeLDAPDN'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_RelativeLDAPDN'(Bytes, OptOrMand) -> | |
| + 'dec_RelativeLDAPDN'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_RelativeLDAPDN'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeType | |
| +%%================================ | |
| + | |
| +'enc_AttributeType'({'AttributeType',Val}, TagIn) -> | |
| + 'enc_AttributeType'(Val, TagIn); | |
| + | |
| +'enc_AttributeType'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_AttributeType'(Bytes, OptOrMand) -> | |
| + 'dec_AttributeType'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AttributeType'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeDescription | |
| +%%================================ | |
| + | |
| +'enc_AttributeDescription'({'AttributeDescription',Val}, TagIn) -> | |
| + 'enc_AttributeDescription'(Val, TagIn); | |
| + | |
| +'enc_AttributeDescription'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_AttributeDescription'(Bytes, OptOrMand) -> | |
| + 'dec_AttributeDescription'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AttributeDescription'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeDescriptionList | |
| +%%================================ | |
| + | |
| +'enc_AttributeDescriptionList'({'AttributeDescriptionList',Val}, TagIn) -> | |
| + 'enc_AttributeDescriptionList'(Val, TagIn); | |
| + | |
| +'enc_AttributeDescriptionList'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_AttributeDescriptionList_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_AttributeDescriptionList_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_AttributeDescriptionList_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = ?RT_BER:encode_octet_string([], H, []), | |
| + 'enc_AttributeDescriptionList_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| +'dec_AttributeDescriptionList'(Bytes, OptOrMand) -> | |
| + 'dec_AttributeDescriptionList'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AttributeDescriptionList'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun(FBytes,_,_)-> | |
| +?RT_BER:decode_octet_string(FBytes,[],[], no_length, mandatory) | |
| +end, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeValue | |
| +%%================================ | |
| + | |
| +'enc_AttributeValue'({'AttributeValue',Val}, TagIn) -> | |
| + 'enc_AttributeValue'(Val, TagIn); | |
| + | |
| +'enc_AttributeValue'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_AttributeValue'(Bytes, OptOrMand) -> | |
| + 'dec_AttributeValue'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AttributeValue'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeValueAssertion | |
| +%%================================ | |
| +'enc_AttributeValueAssertion'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,attributeDesc), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,assertionValue), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_AttributeValueAssertion'(Bytes, OptOrMand) -> | |
| + 'dec_AttributeValueAssertion'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AttributeValueAssertion'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = ?RT_BER:decode_octet_string(Bytes3,[],[], no_length, mandatory), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'AttributeValueAssertion', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% AssertionValue | |
| +%%================================ | |
| + | |
| +'enc_AssertionValue'({'AssertionValue',Val}, TagIn) -> | |
| + 'enc_AssertionValue'(Val, TagIn); | |
| + | |
| +'enc_AssertionValue'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_AssertionValue'(Bytes, OptOrMand) -> | |
| + 'dec_AssertionValue'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AssertionValue'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% Attribute | |
| +%%================================ | |
| +'enc_Attribute'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,type), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_Attribute_vals'(?RT_BER:cindex(3,Val,vals), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% Attribute_vals | |
| +%%================================ | |
| + | |
| +'enc_Attribute_vals'({'Attribute_vals',Val}, TagIn) -> | |
| + 'enc_Attribute_vals'(Val, TagIn); | |
| + | |
| +'enc_Attribute_vals'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_Attribute_vals_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_Attribute_vals_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_Attribute_vals_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = ?RT_BER:encode_octet_string([], H, []), | |
| + 'enc_Attribute_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| +'dec_Attribute_vals'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun(FBytes,_,_)-> | |
| +?RT_BER:decode_octet_string(FBytes,[],[], no_length, mandatory) | |
| +end, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +'dec_Attribute'(Bytes, OptOrMand) -> | |
| + 'dec_Attribute'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_Attribute'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_Attribute_vals'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'Attribute', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% MatchingRuleId | |
| +%%================================ | |
| + | |
| +'enc_MatchingRuleId'({'MatchingRuleId',Val}, TagIn) -> | |
| + 'enc_MatchingRuleId'(Val, TagIn); | |
| + | |
| +'enc_MatchingRuleId'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_MatchingRuleId'(Bytes, OptOrMand) -> | |
| + 'dec_MatchingRuleId'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_MatchingRuleId'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% LDAPResult | |
| +%%================================ | |
| +'enc_LDAPResult'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = case (case ?RT_BER:cindex(2,Val,resultCode) of {_,Enumval1}->Enumval1;_->?RT_BER:cindex(2,Val,resultCode) end) of | |
| +success -> ?RT_BER:encode_enumerated(0,[]); | |
| +operationsError -> ?RT_BER:encode_enumerated(1,[]); | |
| +protocolError -> ?RT_BER:encode_enumerated(2,[]); | |
| +timeLimitExceeded -> ?RT_BER:encode_enumerated(3,[]); | |
| +sizeLimitExceeded -> ?RT_BER:encode_enumerated(4,[]); | |
| +compareFalse -> ?RT_BER:encode_enumerated(5,[]); | |
| +compareTrue -> ?RT_BER:encode_enumerated(6,[]); | |
| +authMethodNotSupported -> ?RT_BER:encode_enumerated(7,[]); | |
| +strongAuthRequired -> ?RT_BER:encode_enumerated(8,[]); | |
| +referral -> ?RT_BER:encode_enumerated(10,[]); | |
| +adminLimitExceeded -> ?RT_BER:encode_enumerated(11,[]); | |
| +unavailableCriticalExtension -> ?RT_BER:encode_enumerated(12,[]); | |
| +confidentialityRequired -> ?RT_BER:encode_enumerated(13,[]); | |
| +saslBindInProgress -> ?RT_BER:encode_enumerated(14,[]); | |
| +noSuchAttribute -> ?RT_BER:encode_enumerated(16,[]); | |
| +undefinedAttributeType -> ?RT_BER:encode_enumerated(17,[]); | |
| +inappropriateMatching -> ?RT_BER:encode_enumerated(18,[]); | |
| +constraintViolation -> ?RT_BER:encode_enumerated(19,[]); | |
| +attributeOrValueExists -> ?RT_BER:encode_enumerated(20,[]); | |
| +invalidAttributeSyntax -> ?RT_BER:encode_enumerated(21,[]); | |
| +noSuchObject -> ?RT_BER:encode_enumerated(32,[]); | |
| +aliasProblem -> ?RT_BER:encode_enumerated(33,[]); | |
| +invalidDNSyntax -> ?RT_BER:encode_enumerated(34,[]); | |
| +aliasDereferencingProblem -> ?RT_BER:encode_enumerated(36,[]); | |
| +inappropriateAuthentication -> ?RT_BER:encode_enumerated(48,[]); | |
| +invalidCredentials -> ?RT_BER:encode_enumerated(49,[]); | |
| +insufficientAccessRights -> ?RT_BER:encode_enumerated(50,[]); | |
| +busy -> ?RT_BER:encode_enumerated(51,[]); | |
| +unavailable -> ?RT_BER:encode_enumerated(52,[]); | |
| +unwillingToPerform -> ?RT_BER:encode_enumerated(53,[]); | |
| +loopDetect -> ?RT_BER:encode_enumerated(54,[]); | |
| +namingViolation -> ?RT_BER:encode_enumerated(64,[]); | |
| +objectClassViolation -> ?RT_BER:encode_enumerated(65,[]); | |
| +notAllowedOnNonLeaf -> ?RT_BER:encode_enumerated(66,[]); | |
| +notAllowedOnRDN -> ?RT_BER:encode_enumerated(67,[]); | |
| +entryAlreadyExists -> ?RT_BER:encode_enumerated(68,[]); | |
| +objectClassModsProhibited -> ?RT_BER:encode_enumerated(69,[]); | |
| +affectsMultipleDSAs -> ?RT_BER:encode_enumerated(71,[]); | |
| +other -> ?RT_BER:encode_enumerated(80,[]); | |
| +Enumval2 -> exit({error,{asn1, {enumerated_not_in_range,Enumval2}}}) | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,matchedDN), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(4,Val,errorMessage), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 External ELDAPv3:Referral OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes4,EncLen4} = case ?RT_BER:cindex(5,Val,referral) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + 'enc_Referral'(?RT_BER:cindex(5,Val,referral), [{tag,128,3,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_LDAPResult'(Bytes, OptOrMand) -> | |
| + 'dec_LDAPResult'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_LDAPResult'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_enumerated(Bytes2,[],[{success,0},{operationsError,1},{protocolError,2},{timeLimitExceeded,3},{sizeLimitExceeded,4},{compareFalse,5},{compareTrue,6},{authMethodNotSupported,7},{strongAuthRequired,8},{referral,10},{adminLimitExceeded,11},{unavailableCriticalExtension,12},{confidentialityRequired,13},{saslBindInProgress,14},{noSuchAttribute,16},{undefinedAttributeType,17},{inappropriateMatching,18},{constraintViolation,19},{attributeOrValueExists,20},{invalidAttributeSyntax,21},{noSuchObject,32},{aliasProblem,33},{invalidDNSyntax,34},{aliasDereferencingProblem,36},{inappropriateAuthentication,48},{invalidCredentials,49},{insufficientAccessRights,50},{busy,51},{unavailable,52},{unwillingToPerform,53},{loopDetect,54},{namingViolation,64},{objectClassViolation,65},{notAllowedOnNonLeaf,66},{notAllowedOnRDN,67},{entryAlreadyExists,68},{objectClassModsProhibited,69},{affectsMultipleDSAs,71},{other,80}],[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = ?RT_BER:decode_octet_string(Bytes3,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = ?RT_BER:decode_octet_string(Bytes4,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 External ELDAPv3:Referral OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term4,Bytes6,Rb5} = case Bytes5 of | |
| +<<2:2,_:1,3:5,_/binary>> -> | |
| +'dec_Referral'(Bytes5, opt_or_default, [{tag,128,3,'IMPLICIT',32}]); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes5, 0 } | |
| +end, | |
| + | |
| + {Bytes7,Rb6} = ?RT_BER:restbytes2(RemBytes, Bytes6,noext), | |
| + {{'LDAPResult', Term1, Term2, Term3, Term4}, Bytes7, Rb1+Rb2+Rb3+Rb4+Rb5+Rb6}. | |
| + | |
| + | |
| +%%================================ | |
| +%% Referral | |
| +%%================================ | |
| + | |
| +'enc_Referral'({'Referral',Val}, TagIn) -> | |
| + 'enc_Referral'(Val, TagIn); | |
| + | |
| +'enc_Referral'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_Referral_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_Referral_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_Referral_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = ?RT_BER:encode_octet_string([], H, []), | |
| + 'enc_Referral_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| +'dec_Referral'(Bytes, OptOrMand) -> | |
| + 'dec_Referral'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_Referral'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun(FBytes,_,_)-> | |
| +?RT_BER:decode_octet_string(FBytes,[],[], no_length, mandatory) | |
| +end, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% LDAPURL | |
| +%%================================ | |
| + | |
| +'enc_LDAPURL'({'LDAPURL',Val}, TagIn) -> | |
| + 'enc_LDAPURL'(Val, TagIn); | |
| + | |
| +'enc_LDAPURL'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ []). | |
| + | |
| + | |
| +'dec_LDAPURL'(Bytes, OptOrMand) -> | |
| + 'dec_LDAPURL'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_LDAPURL'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% Controls | |
| +%%================================ | |
| + | |
| +'enc_Controls'({'Controls',Val}, TagIn) -> | |
| + 'enc_Controls'(Val, TagIn); | |
| + | |
| +'enc_Controls'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_Controls_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_Controls_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_Controls_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = 'enc_Control'(H, []), | |
| + 'enc_Controls_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| +'dec_Controls'(Bytes, OptOrMand) -> | |
| + 'dec_Controls'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_Controls'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun 'dec_Control'/3, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% Control | |
| +%%================================ | |
| +'enc_Control'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,controlType), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type BOOLEAN DEFAULT = false | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = case ?RT_BER:cindex(3,Val,criticality) of | |
| + asn1_DEFAULT -> {<<>>,0}; | |
| + false -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_boolean(?RT_BER:cindex(3,Val,criticality), []) | |
| + end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = case ?RT_BER:cindex(4,Val,controlValue) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(4,Val,controlValue), []) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_Control'(Bytes, OptOrMand) -> | |
| + 'dec_Control'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_Control'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type BOOLEAN DEFAULT = false | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = case Bytes3 of | |
| +<<0:2,_:1,1:5,_/binary>> -> | |
| +?RT_BER:decode_boolean(Bytes3,[], mandatory); | |
| +_ -> | |
| +{false,Bytes3, 0 } | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = case Bytes4 of | |
| +<<0:2,_:1,4:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes4,[],[], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes4, 0 } | |
| +end, | |
| + | |
| + {Bytes6,Rb5} = ?RT_BER:restbytes2(RemBytes, Bytes5,noext), | |
| + {{'Control', Term1, Term2, Term3}, Bytes6, Rb1+Rb2+Rb3+Rb4+Rb5}. | |
| + | |
| + | |
| +%%================================ | |
| +%% BindRequest | |
| +%%================================ | |
| +'enc_BindRequest'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_integer([], ?RT_BER:cindex(2,Val,version), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,name), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 External ELDAPv3:AuthenticationChoice | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = 'enc_AuthenticationChoice'(?RT_BER:cindex(4,Val,authentication), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,0,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_BindRequest'(Bytes, OptOrMand) -> | |
| + 'dec_BindRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_BindRequest'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,0,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_integer(Bytes2,{1,127},[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = ?RT_BER:decode_octet_string(Bytes3,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 External ELDAPv3:AuthenticationChoice | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = 'dec_AuthenticationChoice'(Bytes4, mandatory, []), | |
| + | |
| + {Bytes6,Rb5} = ?RT_BER:restbytes2(RemBytes, Bytes5,noext), | |
| + {{'BindRequest', Term1, Term2, Term3}, Bytes6, Rb1+Rb2+Rb3+Rb4+Rb5}. | |
| + | |
| + | |
| +%%================================ | |
| +%% AuthenticationChoice | |
| +%%================================ | |
| + | |
| +'enc_AuthenticationChoice'({'AuthenticationChoice',Val}, TagIn) -> | |
| + 'enc_AuthenticationChoice'(Val, TagIn); | |
| + | |
| +'enc_AuthenticationChoice'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = case element(1,Val) of | |
| + simple -> | |
| + ?RT_BER:encode_octet_string([], element(2,Val), [{tag,128,0,'IMPLICIT',32}]); | |
| + sasl -> | |
| + 'enc_SaslCredentials'(element(2,Val), [{tag,128,3,'IMPLICIT',32}]); | |
| + Else -> | |
| + exit({error,{asn1,{invalid_choice_type,Else}}}) | |
| + end, | |
| + | |
| +?RT_BER:encode_tags(TagIn ++[], EncBytes, EncLen). | |
| + | |
| + | |
| + | |
| + | |
| +'dec_AuthenticationChoice'(Bytes, OptOrMand) -> | |
| + 'dec_AuthenticationChoice'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AuthenticationChoice'(Bytes, OptOrMand, TagIn) -> | |
| + {{_,Len},Bytes1, RbExp} = ?RT_BER:check_tags(TagIn++[], Bytes, OptOrMand), | |
| + IndefEndBytes = fun(indefinite,<<0,0,R/binary>>)-> R; (_,B)-> B end, | |
| + IndefEndRb = fun(indefinite,<<0,0,_R/binary>>)-> 2; (_,_)-> 0 end, | |
| + case Bytes1 of | |
| + | |
| +%% 'simple' | |
| + <<2:2,_:1,0:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_octet_string(Bytes1,[],[{tag,128,0,'IMPLICIT',32}], no_length, mandatory), | |
| + {{simple, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'sasl' | |
| + <<2:2,_:1,3:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_SaslCredentials'(Bytes1, mandatory, [{tag,128,3,'IMPLICIT',32}]), | |
| + {{sasl, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + Else -> | |
| + case OptOrMand of | |
| + mandatory ->exit({error,{asn1,{invalid_choice_tag,Else}}}); | |
| + _ ->exit({error,{asn1,{no_optional_tag,Else}}}) | |
| + end | |
| + end. | |
| + | |
| + | |
| +%%================================ | |
| +%% SaslCredentials | |
| +%%================================ | |
| +'enc_SaslCredentials'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,mechanism), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = case ?RT_BER:cindex(3,Val,credentials) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,credentials), []) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_SaslCredentials'(Bytes, OptOrMand) -> | |
| + 'dec_SaslCredentials'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_SaslCredentials'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = case Bytes3 of | |
| +<<0:2,_:1,4:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes3,[],[], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes3, 0 } | |
| +end, | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'SaslCredentials', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% BindResponse | |
| +%%================================ | |
| +'enc_BindResponse'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = case (case ?RT_BER:cindex(2,Val,resultCode) of {_,Enumval1}->Enumval1;_->?RT_BER:cindex(2,Val,resultCode) end) of | |
| +success -> ?RT_BER:encode_enumerated(0,[]); | |
| +operationsError -> ?RT_BER:encode_enumerated(1,[]); | |
| +protocolError -> ?RT_BER:encode_enumerated(2,[]); | |
| +timeLimitExceeded -> ?RT_BER:encode_enumerated(3,[]); | |
| +sizeLimitExceeded -> ?RT_BER:encode_enumerated(4,[]); | |
| +compareFalse -> ?RT_BER:encode_enumerated(5,[]); | |
| +compareTrue -> ?RT_BER:encode_enumerated(6,[]); | |
| +authMethodNotSupported -> ?RT_BER:encode_enumerated(7,[]); | |
| +strongAuthRequired -> ?RT_BER:encode_enumerated(8,[]); | |
| +referral -> ?RT_BER:encode_enumerated(10,[]); | |
| +adminLimitExceeded -> ?RT_BER:encode_enumerated(11,[]); | |
| +unavailableCriticalExtension -> ?RT_BER:encode_enumerated(12,[]); | |
| +confidentialityRequired -> ?RT_BER:encode_enumerated(13,[]); | |
| +saslBindInProgress -> ?RT_BER:encode_enumerated(14,[]); | |
| +noSuchAttribute -> ?RT_BER:encode_enumerated(16,[]); | |
| +undefinedAttributeType -> ?RT_BER:encode_enumerated(17,[]); | |
| +inappropriateMatching -> ?RT_BER:encode_enumerated(18,[]); | |
| +constraintViolation -> ?RT_BER:encode_enumerated(19,[]); | |
| +attributeOrValueExists -> ?RT_BER:encode_enumerated(20,[]); | |
| +invalidAttributeSyntax -> ?RT_BER:encode_enumerated(21,[]); | |
| +noSuchObject -> ?RT_BER:encode_enumerated(32,[]); | |
| +aliasProblem -> ?RT_BER:encode_enumerated(33,[]); | |
| +invalidDNSyntax -> ?RT_BER:encode_enumerated(34,[]); | |
| +aliasDereferencingProblem -> ?RT_BER:encode_enumerated(36,[]); | |
| +inappropriateAuthentication -> ?RT_BER:encode_enumerated(48,[]); | |
| +invalidCredentials -> ?RT_BER:encode_enumerated(49,[]); | |
| +insufficientAccessRights -> ?RT_BER:encode_enumerated(50,[]); | |
| +busy -> ?RT_BER:encode_enumerated(51,[]); | |
| +unavailable -> ?RT_BER:encode_enumerated(52,[]); | |
| +unwillingToPerform -> ?RT_BER:encode_enumerated(53,[]); | |
| +loopDetect -> ?RT_BER:encode_enumerated(54,[]); | |
| +namingViolation -> ?RT_BER:encode_enumerated(64,[]); | |
| +objectClassViolation -> ?RT_BER:encode_enumerated(65,[]); | |
| +notAllowedOnNonLeaf -> ?RT_BER:encode_enumerated(66,[]); | |
| +notAllowedOnRDN -> ?RT_BER:encode_enumerated(67,[]); | |
| +entryAlreadyExists -> ?RT_BER:encode_enumerated(68,[]); | |
| +objectClassModsProhibited -> ?RT_BER:encode_enumerated(69,[]); | |
| +affectsMultipleDSAs -> ?RT_BER:encode_enumerated(71,[]); | |
| +other -> ?RT_BER:encode_enumerated(80,[]); | |
| +Enumval2 -> exit({error,{asn1, {enumerated_not_in_range,Enumval2}}}) | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,matchedDN), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(4,Val,errorMessage), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 External ELDAPv3:Referral OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes4,EncLen4} = case ?RT_BER:cindex(5,Val,referral) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + 'enc_Referral'(?RT_BER:cindex(5,Val,referral), [{tag,128,3,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 5 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes5,EncLen5} = case ?RT_BER:cindex(6,Val,serverSaslCreds) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(6,Val,serverSaslCreds), [{tag,128,7,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,1,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_BindResponse'(Bytes, OptOrMand) -> | |
| + 'dec_BindResponse'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_BindResponse'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,1,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_enumerated(Bytes2,[],[{success,0},{operationsError,1},{protocolError,2},{timeLimitExceeded,3},{sizeLimitExceeded,4},{compareFalse,5},{compareTrue,6},{authMethodNotSupported,7},{strongAuthRequired,8},{referral,10},{adminLimitExceeded,11},{unavailableCriticalExtension,12},{confidentialityRequired,13},{saslBindInProgress,14},{noSuchAttribute,16},{undefinedAttributeType,17},{inappropriateMatching,18},{constraintViolation,19},{attributeOrValueExists,20},{invalidAttributeSyntax,21},{noSuchObject,32},{aliasProblem,33},{invalidDNSyntax,34},{aliasDereferencingProblem,36},{inappropriateAuthentication,48},{invalidCredentials,49},{insufficientAccessRights,50},{busy,51},{unavailable,52},{unwillingToPerform,53},{loopDetect,54},{namingViolation,64},{objectClassViolation,65},{notAllowedOnNonLeaf,66},{notAllowedOnRDN,67},{entryAlreadyExists,68},{objectClassModsProhibited,69},{affectsMultipleDSAs,71},{other,80}],[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = ?RT_BER:decode_octet_string(Bytes3,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = ?RT_BER:decode_octet_string(Bytes4,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 External ELDAPv3:Referral OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term4,Bytes6,Rb5} = case Bytes5 of | |
| +<<2:2,_:1,3:5,_/binary>> -> | |
| +'dec_Referral'(Bytes5, opt_or_default, [{tag,128,3,'IMPLICIT',32}]); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes5, 0 } | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 5 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term5,Bytes7,Rb6} = case Bytes6 of | |
| +<<2:2,_:1,7:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes6,[],[{tag,128,7,'IMPLICIT',32}], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes6, 0 } | |
| +end, | |
| + | |
| + {Bytes8,Rb7} = ?RT_BER:restbytes2(RemBytes, Bytes7,noext), | |
| + {{'BindResponse', Term1, Term2, Term3, Term4, Term5}, Bytes8, Rb1+Rb2+Rb3+Rb4+Rb5+Rb6+Rb7}. | |
| + | |
| + | |
| +%%================================ | |
| +%% UnbindRequest | |
| +%%================================ | |
| + | |
| +'enc_UnbindRequest'({'UnbindRequest',Val}, TagIn) -> | |
| + 'enc_UnbindRequest'(Val, TagIn); | |
| + | |
| +'enc_UnbindRequest'(Val, TagIn) -> | |
| +?RT_BER:encode_null(Val, TagIn ++ [{tag,64,2,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_UnbindRequest'(Bytes, OptOrMand) -> | |
| + 'dec_UnbindRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_UnbindRequest'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_null(Bytes,TagIn++[{tag,64,2,'IMPLICIT',32}], OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% SearchRequest | |
| +%%================================ | |
| +'enc_SearchRequest'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,baseObject), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = case (case ?RT_BER:cindex(3,Val,scope) of {_,Enumval2}->Enumval2;_->?RT_BER:cindex(3,Val,scope) end) of | |
| +baseObject -> ?RT_BER:encode_enumerated(0,[]); | |
| +singleLevel -> ?RT_BER:encode_enumerated(1,[]); | |
| +wholeSubtree -> ?RT_BER:encode_enumerated(2,[]); | |
| +Enumval3 -> exit({error,{asn1, {enumerated_not_in_range,Enumval3}}}) | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = case (case ?RT_BER:cindex(4,Val,derefAliases) of {_,Enumval4}->Enumval4;_->?RT_BER:cindex(4,Val,derefAliases) end) of | |
| +neverDerefAliases -> ?RT_BER:encode_enumerated(0,[]); | |
| +derefInSearching -> ?RT_BER:encode_enumerated(1,[]); | |
| +derefFindingBaseObj -> ?RT_BER:encode_enumerated(2,[]); | |
| +derefAlways -> ?RT_BER:encode_enumerated(3,[]); | |
| +Enumval5 -> exit({error,{asn1, {enumerated_not_in_range,Enumval5}}}) | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {EncBytes4,EncLen4} = ?RT_BER:encode_integer([], ?RT_BER:cindex(5,Val,sizeLimit), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 5 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {EncBytes5,EncLen5} = ?RT_BER:encode_integer([], ?RT_BER:cindex(6,Val,timeLimit), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 6 with type BOOLEAN | |
| +%%------------------------------------------------- | |
| + {EncBytes6,EncLen6} = ?RT_BER:encode_boolean(?RT_BER:cindex(7,Val,typesOnly), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 7 External ELDAPv3:Filter | |
| +%%------------------------------------------------- | |
| + {EncBytes7,EncLen7} = 'enc_Filter'(?RT_BER:cindex(8,Val,filter), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 8 External ELDAPv3:AttributeDescriptionList | |
| +%%------------------------------------------------- | |
| + {EncBytes8,EncLen8} = 'enc_AttributeDescriptionList'(?RT_BER:cindex(9,Val,attributes), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5, EncBytes6, EncBytes7, EncBytes8], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5 + EncLen6 + EncLen7 + EncLen8, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,3,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_SearchRequest'(Bytes, OptOrMand) -> | |
| + 'dec_SearchRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_SearchRequest'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,3,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = ?RT_BER:decode_enumerated(Bytes3,[],[{baseObject,0},{singleLevel,1},{wholeSubtree,2}],[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = ?RT_BER:decode_enumerated(Bytes4,[],[{neverDerefAliases,0},{derefInSearching,1},{derefFindingBaseObj,2},{derefAlways,3}],[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {Term4,Bytes6,Rb5} = ?RT_BER:decode_integer(Bytes5,{0,2147483647},[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 5 with type INTEGER | |
| +%%------------------------------------------------- | |
| + {Term5,Bytes7,Rb6} = ?RT_BER:decode_integer(Bytes6,{0,2147483647},[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 6 with type BOOLEAN | |
| +%%------------------------------------------------- | |
| + {Term6,Bytes8,Rb7} = ?RT_BER:decode_boolean(Bytes7,[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 7 External ELDAPv3:Filter | |
| +%%------------------------------------------------- | |
| + {Term7,Bytes9,Rb8} = 'dec_Filter'(Bytes8, mandatory, []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 8 External ELDAPv3:AttributeDescriptionList | |
| +%%------------------------------------------------- | |
| + {Term8,Bytes10,Rb9} = 'dec_AttributeDescriptionList'(Bytes9, mandatory, []), | |
| + | |
| + {Bytes11,Rb10} = ?RT_BER:restbytes2(RemBytes, Bytes10,noext), | |
| + {{'SearchRequest', Term1, Term2, Term3, Term4, Term5, Term6, Term7, Term8}, Bytes11, Rb1+Rb2+Rb3+Rb4+Rb5+Rb6+Rb7+Rb8+Rb9+Rb10}. | |
| + | |
| + | |
| +%%================================ | |
| +%% Filter | |
| +%%================================ | |
| + | |
| +'enc_Filter'({'Filter',Val}, TagIn) -> | |
| + 'enc_Filter'(Val, TagIn); | |
| + | |
| +'enc_Filter'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = case element(1,Val) of | |
| + 'and' -> | |
| + 'enc_Filter_and'(element(2,Val), [{tag,128,0,'IMPLICIT',32}]); | |
| + 'or' -> | |
| + 'enc_Filter_or'(element(2,Val), [{tag,128,1,'IMPLICIT',32}]); | |
| + 'not' -> | |
| + 'enc_Filter'(element(2,Val), [{tag,128,2,'EXPLICIT',32}]); | |
| + equalityMatch -> | |
| + 'enc_AttributeValueAssertion'(element(2,Val), [{tag,128,3,'IMPLICIT',32}]); | |
| + substrings -> | |
| + 'enc_SubstringFilter'(element(2,Val), [{tag,128,4,'IMPLICIT',32}]); | |
| + greaterOrEqual -> | |
| + 'enc_AttributeValueAssertion'(element(2,Val), [{tag,128,5,'IMPLICIT',32}]); | |
| + lessOrEqual -> | |
| + 'enc_AttributeValueAssertion'(element(2,Val), [{tag,128,6,'IMPLICIT',32}]); | |
| + present -> | |
| + ?RT_BER:encode_octet_string([], element(2,Val), [{tag,128,7,'IMPLICIT',32}]); | |
| + approxMatch -> | |
| + 'enc_AttributeValueAssertion'(element(2,Val), [{tag,128,8,'IMPLICIT',32}]); | |
| + extensibleMatch -> | |
| + 'enc_MatchingRuleAssertion'(element(2,Val), [{tag,128,9,'IMPLICIT',32}]); | |
| + Else -> | |
| + exit({error,{asn1,{invalid_choice_type,Else}}}) | |
| + end, | |
| + | |
| +?RT_BER:encode_tags(TagIn ++[], EncBytes, EncLen). | |
| + | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% Filter_and | |
| +%%================================ | |
| + | |
| +'enc_Filter_and'({'Filter_and',Val}, TagIn) -> | |
| + 'enc_Filter_and'(Val, TagIn); | |
| + | |
| +'enc_Filter_and'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_Filter_and_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_Filter_and_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_Filter_and_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = 'enc_Filter'(H, []), | |
| + 'enc_Filter_and_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| +'dec_Filter_and'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun 'dec_Filter'/3, [], []). | |
| + | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% Filter_or | |
| +%%================================ | |
| + | |
| +'enc_Filter_or'({'Filter_or',Val}, TagIn) -> | |
| + 'enc_Filter_or'(Val, TagIn); | |
| + | |
| +'enc_Filter_or'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_Filter_or_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_Filter_or_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_Filter_or_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = 'enc_Filter'(H, []), | |
| + 'enc_Filter_or_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| +'dec_Filter_or'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun 'dec_Filter'/3, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +'dec_Filter'(Bytes, OptOrMand) -> | |
| + 'dec_Filter'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_Filter'(Bytes, OptOrMand, TagIn) -> | |
| + {{_,Len},Bytes1, RbExp} = ?RT_BER:check_tags(TagIn++[], Bytes, OptOrMand), | |
| + IndefEndBytes = fun(indefinite,<<0,0,R/binary>>)-> R; (_,B)-> B end, | |
| + IndefEndRb = fun(indefinite,<<0,0,_R/binary>>)-> 2; (_,_)-> 0 end, | |
| + case Bytes1 of | |
| + | |
| +%% 'and' | |
| + <<2:2,_:1,0:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_Filter_and'(Bytes1, mandatory, [{tag,128,0,'IMPLICIT',32}]), | |
| + {{'and', Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'or' | |
| + <<2:2,_:1,1:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_Filter_or'(Bytes1, mandatory, [{tag,128,1,'IMPLICIT',32}]), | |
| + {{'or', Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'not' | |
| + <<2:2,_:1,2:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_Filter'(Bytes1, mandatory, [{tag,128,2,'EXPLICIT',32}]), | |
| + {{'not', Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'equalityMatch' | |
| + <<2:2,_:1,3:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_AttributeValueAssertion'(Bytes1, mandatory, [{tag,128,3,'IMPLICIT',32}]), | |
| + {{equalityMatch, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'substrings' | |
| + <<2:2,_:1,4:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_SubstringFilter'(Bytes1, mandatory, [{tag,128,4,'IMPLICIT',32}]), | |
| + {{substrings, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'greaterOrEqual' | |
| + <<2:2,_:1,5:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_AttributeValueAssertion'(Bytes1, mandatory, [{tag,128,5,'IMPLICIT',32}]), | |
| + {{greaterOrEqual, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'lessOrEqual' | |
| + <<2:2,_:1,6:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_AttributeValueAssertion'(Bytes1, mandatory, [{tag,128,6,'IMPLICIT',32}]), | |
| + {{lessOrEqual, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'present' | |
| + <<2:2,_:1,7:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_octet_string(Bytes1,[],[{tag,128,7,'IMPLICIT',32}], no_length, mandatory), | |
| + {{present, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'approxMatch' | |
| + <<2:2,_:1,8:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_AttributeValueAssertion'(Bytes1, mandatory, [{tag,128,8,'IMPLICIT',32}]), | |
| + {{approxMatch, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'extensibleMatch' | |
| + <<2:2,_:1,9:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = 'dec_MatchingRuleAssertion'(Bytes1, mandatory, [{tag,128,9,'IMPLICIT',32}]), | |
| + {{extensibleMatch, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + Else -> | |
| + case OptOrMand of | |
| + mandatory ->exit({error,{asn1,{invalid_choice_tag,Else}}}); | |
| + _ ->exit({error,{asn1,{no_optional_tag,Else}}}) | |
| + end | |
| + end. | |
| + | |
| + | |
| +%%================================ | |
| +%% SubstringFilter | |
| +%%================================ | |
| +'enc_SubstringFilter'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,type), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SEQUENCE OF | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_SubstringFilter_substrings'(?RT_BER:cindex(3,Val,substrings), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% SubstringFilter_substrings | |
| +%%================================ | |
| + | |
| +'enc_SubstringFilter_substrings'({'SubstringFilter_substrings',Val}, TagIn) -> | |
| + 'enc_SubstringFilter_substrings'(Val, TagIn); | |
| + | |
| +'enc_SubstringFilter_substrings'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_SubstringFilter_substrings_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_SubstringFilter_substrings_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_SubstringFilter_substrings_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = 'enc_SubstringFilter_substrings_SEQOF'(H, []), | |
| + 'enc_SubstringFilter_substrings_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% SubstringFilter_substrings_SEQOF | |
| +%%================================ | |
| + | |
| +'enc_SubstringFilter_substrings_SEQOF'({'SubstringFilter_substrings_SEQOF',Val}, TagIn) -> | |
| + 'enc_SubstringFilter_substrings_SEQOF'(Val, TagIn); | |
| + | |
| +'enc_SubstringFilter_substrings_SEQOF'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = case element(1,Val) of | |
| + initial -> | |
| + ?RT_BER:encode_octet_string([], element(2,Val), [{tag,128,0,'IMPLICIT',32}]); | |
| + any -> | |
| + ?RT_BER:encode_octet_string([], element(2,Val), [{tag,128,1,'IMPLICIT',32}]); | |
| + final -> | |
| + ?RT_BER:encode_octet_string([], element(2,Val), [{tag,128,2,'IMPLICIT',32}]); | |
| + Else -> | |
| + exit({error,{asn1,{invalid_choice_type,Else}}}) | |
| + end, | |
| + | |
| +?RT_BER:encode_tags(TagIn ++[], EncBytes, EncLen). | |
| + | |
| + | |
| +'dec_SubstringFilter_substrings_SEQOF'(Bytes, OptOrMand, TagIn) -> | |
| + {{_,Len},Bytes1, RbExp} = ?RT_BER:check_tags(TagIn++[], Bytes, OptOrMand), | |
| + IndefEndBytes = fun(indefinite,<<0,0,R/binary>>)-> R; (_,B)-> B end, | |
| + IndefEndRb = fun(indefinite,<<0,0,_R/binary>>)-> 2; (_,_)-> 0 end, | |
| + case Bytes1 of | |
| + | |
| +%% 'initial' | |
| + <<2:2,_:1,0:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_octet_string(Bytes1,[],[{tag,128,0,'IMPLICIT',32}], no_length, mandatory), | |
| + {{initial, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'any' | |
| + <<2:2,_:1,1:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_octet_string(Bytes1,[],[{tag,128,1,'IMPLICIT',32}], no_length, mandatory), | |
| + {{any, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + | |
| +%% 'final' | |
| + <<2:2,_:1,2:5,_/binary>> -> | |
| + {Dec, Rest, RbCho} = ?RT_BER:decode_octet_string(Bytes1,[],[{tag,128,2,'IMPLICIT',32}], no_length, mandatory), | |
| + {{final, Dec}, IndefEndBytes(Len,Rest), RbExp + RbCho + IndefEndRb(Len,Rest)}; | |
| + | |
| + Else -> | |
| + case OptOrMand of | |
| + mandatory ->exit({error,{asn1,{invalid_choice_tag,Else}}}); | |
| + _ ->exit({error,{asn1,{no_optional_tag,Else}}}) | |
| + end | |
| + end. | |
| +'dec_SubstringFilter_substrings'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun 'dec_SubstringFilter_substrings_SEQOF'/3, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +'dec_SubstringFilter'(Bytes, OptOrMand) -> | |
| + 'dec_SubstringFilter'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_SubstringFilter'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SEQUENCE OF | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_SubstringFilter_substrings'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'SubstringFilter', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% MatchingRuleAssertion | |
| +%%================================ | |
| +'enc_MatchingRuleAssertion'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = case ?RT_BER:cindex(2,Val,matchingRule) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,matchingRule), [{tag,128,1,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = case ?RT_BER:cindex(3,Val,type) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,type), [{tag,128,2,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(4,Val,matchValue), [{tag,128,3,'IMPLICIT',32}]), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 with type BOOLEAN DEFAULT = false | |
| +%%------------------------------------------------- | |
| + {EncBytes4,EncLen4} = case ?RT_BER:cindex(5,Val,dnAttributes) of | |
| + asn1_DEFAULT -> {<<>>,0}; | |
| + false -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_boolean(?RT_BER:cindex(5,Val,dnAttributes), [{tag,128,4,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_MatchingRuleAssertion'(Bytes, OptOrMand) -> | |
| + 'dec_MatchingRuleAssertion'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_MatchingRuleAssertion'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = case Bytes2 of | |
| +<<2:2,_:1,1:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes2,[],[{tag,128,1,'IMPLICIT',32}], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes2, 0 } | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = case Bytes3 of | |
| +<<2:2,_:1,2:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes3,[],[{tag,128,2,'IMPLICIT',32}], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes3, 0 } | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = ?RT_BER:decode_octet_string(Bytes4,[],[{tag,128,3,'IMPLICIT',32}], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 with type BOOLEAN DEFAULT = false | |
| +%%------------------------------------------------- | |
| + {Term4,Bytes6,Rb5} = case Bytes5 of | |
| +<<2:2,_:1,4:5,_/binary>> -> | |
| +?RT_BER:decode_boolean(Bytes5,[{tag,128,4,'IMPLICIT',32}], mandatory); | |
| +_ -> | |
| +{false,Bytes5, 0 } | |
| +end, | |
| + | |
| + {Bytes7,Rb6} = ?RT_BER:restbytes2(RemBytes, Bytes6,noext), | |
| + {{'MatchingRuleAssertion', Term1, Term2, Term3, Term4}, Bytes7, Rb1+Rb2+Rb3+Rb4+Rb5+Rb6}. | |
| + | |
| + | |
| +%%================================ | |
| +%% SearchResultEntry | |
| +%%================================ | |
| +'enc_SearchResultEntry'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,objectName), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:PartialAttributeList | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_PartialAttributeList'(?RT_BER:cindex(3,Val,attributes), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,4,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_SearchResultEntry'(Bytes, OptOrMand) -> | |
| + 'dec_SearchResultEntry'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_SearchResultEntry'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,4,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:PartialAttributeList | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_PartialAttributeList'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'SearchResultEntry', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% PartialAttributeList | |
| +%%================================ | |
| + | |
| +'enc_PartialAttributeList'({'PartialAttributeList',Val}, TagIn) -> | |
| + 'enc_PartialAttributeList'(Val, TagIn); | |
| + | |
| +'enc_PartialAttributeList'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_PartialAttributeList_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_PartialAttributeList_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_PartialAttributeList_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = 'enc_PartialAttributeList_SEQOF'(H, []), | |
| + 'enc_PartialAttributeList_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% PartialAttributeList_SEQOF | |
| +%%================================ | |
| +'enc_PartialAttributeList_SEQOF'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,type), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_PartialAttributeList_SEQOF_vals'(?RT_BER:cindex(3,Val,vals), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% PartialAttributeList_SEQOF_vals | |
| +%%================================ | |
| + | |
| +'enc_PartialAttributeList_SEQOF_vals'({'PartialAttributeList_SEQOF_vals',Val}, TagIn) -> | |
| + 'enc_PartialAttributeList_SEQOF_vals'(Val, TagIn); | |
| + | |
| +'enc_PartialAttributeList_SEQOF_vals'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_PartialAttributeList_SEQOF_vals_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_PartialAttributeList_SEQOF_vals_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_PartialAttributeList_SEQOF_vals_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = ?RT_BER:encode_octet_string([], H, []), | |
| + 'enc_PartialAttributeList_SEQOF_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| +'dec_PartialAttributeList_SEQOF_vals'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun(FBytes,_,_)-> | |
| +?RT_BER:decode_octet_string(FBytes,[],[], no_length, mandatory) | |
| +end, [], []). | |
| + | |
| + | |
| +'dec_PartialAttributeList_SEQOF'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_PartialAttributeList_SEQOF_vals'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'PartialAttributeList_SEQOF', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +'dec_PartialAttributeList'(Bytes, OptOrMand) -> | |
| + 'dec_PartialAttributeList'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_PartialAttributeList'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun 'dec_PartialAttributeList_SEQOF'/3, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% SearchResultReference | |
| +%%================================ | |
| + | |
| +'enc_SearchResultReference'({'SearchResultReference',Val}, TagIn) -> | |
| + 'enc_SearchResultReference'(Val, TagIn); | |
| + | |
| +'enc_SearchResultReference'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_SearchResultReference_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,19,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_SearchResultReference_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_SearchResultReference_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = ?RT_BER:encode_octet_string([], H, []), | |
| + 'enc_SearchResultReference_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| +'dec_SearchResultReference'(Bytes, OptOrMand) -> | |
| + 'dec_SearchResultReference'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_SearchResultReference'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,19,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun(FBytes,_,_)-> | |
| +?RT_BER:decode_octet_string(FBytes,[],[], no_length, mandatory) | |
| +end, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% SearchResultDone | |
| +%%================================ | |
| + | |
| +'enc_SearchResultDone'({'SearchResultDone',Val}, TagIn) -> | |
| + 'enc_SearchResultDone'(Val, TagIn); | |
| + | |
| +'enc_SearchResultDone'(Val, TagIn) -> | |
| + 'enc_LDAPResult'(Val, TagIn ++ [{tag,64,5,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_SearchResultDone'(Bytes, OptOrMand) -> | |
| + 'dec_SearchResultDone'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_SearchResultDone'(Bytes, OptOrMand, TagIn) -> | |
| +'dec_LDAPResult'(Bytes, OptOrMand, TagIn++[{tag,64,5,'IMPLICIT',32}]). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% ModifyRequest | |
| +%%================================ | |
| +'enc_ModifyRequest'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,object), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SEQUENCE OF | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_ModifyRequest_modification'(?RT_BER:cindex(3,Val,modification), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,6,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% ModifyRequest_modification | |
| +%%================================ | |
| + | |
| +'enc_ModifyRequest_modification'({'ModifyRequest_modification',Val}, TagIn) -> | |
| + 'enc_ModifyRequest_modification'(Val, TagIn); | |
| + | |
| +'enc_ModifyRequest_modification'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_ModifyRequest_modification_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_ModifyRequest_modification_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_ModifyRequest_modification_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = 'enc_ModifyRequest_modification_SEQOF'(H, []), | |
| + 'enc_ModifyRequest_modification_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% ModifyRequest_modification_SEQOF | |
| +%%================================ | |
| +'enc_ModifyRequest_modification_SEQOF'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = case (case ?RT_BER:cindex(2,Val,operation) of {_,Enumval1}->Enumval1;_->?RT_BER:cindex(2,Val,operation) end) of | |
| +add -> ?RT_BER:encode_enumerated(0,[]); | |
| +delete -> ?RT_BER:encode_enumerated(1,[]); | |
| +replace -> ?RT_BER:encode_enumerated(2,[]); | |
| +Enumval2 -> exit({error,{asn1, {enumerated_not_in_range,Enumval2}}}) | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:AttributeTypeAndValues | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_AttributeTypeAndValues'(?RT_BER:cindex(3,Val,modification), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| +'dec_ModifyRequest_modification_SEQOF'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_enumerated(Bytes2,[],[{add,0},{delete,1},{replace,2}],[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:AttributeTypeAndValues | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_AttributeTypeAndValues'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'ModifyRequest_modification_SEQOF', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| +'dec_ModifyRequest_modification'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun 'dec_ModifyRequest_modification_SEQOF'/3, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +'dec_ModifyRequest'(Bytes, OptOrMand) -> | |
| + 'dec_ModifyRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_ModifyRequest'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,6,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SEQUENCE OF | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_ModifyRequest_modification'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'ModifyRequest', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeTypeAndValues | |
| +%%================================ | |
| +'enc_AttributeTypeAndValues'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,type), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_AttributeTypeAndValues_vals'(?RT_BER:cindex(3,Val,vals), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeTypeAndValues_vals | |
| +%%================================ | |
| + | |
| +'enc_AttributeTypeAndValues_vals'({'AttributeTypeAndValues_vals',Val}, TagIn) -> | |
| + 'enc_AttributeTypeAndValues_vals'(Val, TagIn); | |
| + | |
| +'enc_AttributeTypeAndValues_vals'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_AttributeTypeAndValues_vals_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_AttributeTypeAndValues_vals_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_AttributeTypeAndValues_vals_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = ?RT_BER:encode_octet_string([], H, []), | |
| + 'enc_AttributeTypeAndValues_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| +'dec_AttributeTypeAndValues_vals'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun(FBytes,_,_)-> | |
| +?RT_BER:decode_octet_string(FBytes,[],[], no_length, mandatory) | |
| +end, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +'dec_AttributeTypeAndValues'(Bytes, OptOrMand) -> | |
| + 'dec_AttributeTypeAndValues'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AttributeTypeAndValues'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_AttributeTypeAndValues_vals'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'AttributeTypeAndValues', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% ModifyResponse | |
| +%%================================ | |
| + | |
| +'enc_ModifyResponse'({'ModifyResponse',Val}, TagIn) -> | |
| + 'enc_ModifyResponse'(Val, TagIn); | |
| + | |
| +'enc_ModifyResponse'(Val, TagIn) -> | |
| + 'enc_LDAPResult'(Val, TagIn ++ [{tag,64,7,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_ModifyResponse'(Bytes, OptOrMand) -> | |
| + 'dec_ModifyResponse'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_ModifyResponse'(Bytes, OptOrMand, TagIn) -> | |
| +'dec_LDAPResult'(Bytes, OptOrMand, TagIn++[{tag,64,7,'IMPLICIT',32}]). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AddRequest | |
| +%%================================ | |
| +'enc_AddRequest'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,entry), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:AttributeList | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_AttributeList'(?RT_BER:cindex(3,Val,attributes), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,8,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_AddRequest'(Bytes, OptOrMand) -> | |
| + 'dec_AddRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AddRequest'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,8,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:AttributeList | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_AttributeList'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'AddRequest', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeList | |
| +%%================================ | |
| + | |
| +'enc_AttributeList'({'AttributeList',Val}, TagIn) -> | |
| + 'enc_AttributeList'(Val, TagIn); | |
| + | |
| +'enc_AttributeList'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_AttributeList_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_AttributeList_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_AttributeList_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = 'enc_AttributeList_SEQOF'(H, []), | |
| + 'enc_AttributeList_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeList_SEQOF | |
| +%%================================ | |
| +'enc_AttributeList_SEQOF'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,type), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_AttributeList_SEQOF_vals'(?RT_BER:cindex(3,Val,vals), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AttributeList_SEQOF_vals | |
| +%%================================ | |
| + | |
| +'enc_AttributeList_SEQOF_vals'({'AttributeList_SEQOF_vals',Val}, TagIn) -> | |
| + 'enc_AttributeList_SEQOF_vals'(Val, TagIn); | |
| + | |
| +'enc_AttributeList_SEQOF_vals'(Val, TagIn) -> | |
| + {EncBytes,EncLen} = 'enc_AttributeList_SEQOF_vals_components'(Val,[],0), | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], EncBytes, EncLen). | |
| + | |
| +'enc_AttributeList_SEQOF_vals_components'([], AccBytes, AccLen) -> | |
| + {lists:reverse(AccBytes),AccLen}; | |
| + | |
| +'enc_AttributeList_SEQOF_vals_components'([H|T],AccBytes, AccLen) -> | |
| + {EncBytes,EncLen} = ?RT_BER:encode_octet_string([], H, []), | |
| + 'enc_AttributeList_SEQOF_vals_components'(T,[EncBytes|AccBytes], AccLen + EncLen). | |
| + | |
| +'dec_AttributeList_SEQOF_vals'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,17,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun(FBytes,_,_)-> | |
| +?RT_BER:decode_octet_string(FBytes,[],[], no_length, mandatory) | |
| +end, [], []). | |
| + | |
| + | |
| +'dec_AttributeList_SEQOF'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type SET OF | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_AttributeList_SEQOF_vals'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'AttributeList_SEQOF', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +'dec_AttributeList'(Bytes, OptOrMand) -> | |
| + 'dec_AttributeList'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AttributeList'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| + ?RT_BER:decode_components(Rb1, Len, Bytes1, fun 'dec_AttributeList_SEQOF'/3, [], []). | |
| + | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AddResponse | |
| +%%================================ | |
| + | |
| +'enc_AddResponse'({'AddResponse',Val}, TagIn) -> | |
| + 'enc_AddResponse'(Val, TagIn); | |
| + | |
| +'enc_AddResponse'(Val, TagIn) -> | |
| + 'enc_LDAPResult'(Val, TagIn ++ [{tag,64,9,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_AddResponse'(Bytes, OptOrMand) -> | |
| + 'dec_AddResponse'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AddResponse'(Bytes, OptOrMand, TagIn) -> | |
| +'dec_LDAPResult'(Bytes, OptOrMand, TagIn++[{tag,64,9,'IMPLICIT',32}]). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% DelRequest | |
| +%%================================ | |
| + | |
| +'enc_DelRequest'({'DelRequest',Val}, TagIn) -> | |
| + 'enc_DelRequest'(Val, TagIn); | |
| + | |
| +'enc_DelRequest'(Val, TagIn) -> | |
| +?RT_BER:encode_octet_string([], Val, TagIn ++ [{tag,64,10,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_DelRequest'(Bytes, OptOrMand) -> | |
| + 'dec_DelRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_DelRequest'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_octet_string(Bytes,[],TagIn++[{tag,64,10,'IMPLICIT',32}], no_length, OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% DelResponse | |
| +%%================================ | |
| + | |
| +'enc_DelResponse'({'DelResponse',Val}, TagIn) -> | |
| + 'enc_DelResponse'(Val, TagIn); | |
| + | |
| +'enc_DelResponse'(Val, TagIn) -> | |
| + 'enc_LDAPResult'(Val, TagIn ++ [{tag,64,11,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_DelResponse'(Bytes, OptOrMand) -> | |
| + 'dec_DelResponse'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_DelResponse'(Bytes, OptOrMand, TagIn) -> | |
| +'dec_LDAPResult'(Bytes, OptOrMand, TagIn++[{tag,64,11,'IMPLICIT',32}]). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% ModifyDNRequest | |
| +%%================================ | |
| +'enc_ModifyDNRequest'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,entry), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,newrdn), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type BOOLEAN | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = ?RT_BER:encode_boolean(?RT_BER:cindex(4,Val,deleteoldrdn), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes4,EncLen4} = case ?RT_BER:cindex(5,Val,newSuperior) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(5,Val,newSuperior), [{tag,128,0,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,12,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_ModifyDNRequest'(Bytes, OptOrMand) -> | |
| + 'dec_ModifyDNRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_ModifyDNRequest'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,12,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = ?RT_BER:decode_octet_string(Bytes3,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type BOOLEAN | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = ?RT_BER:decode_boolean(Bytes4,[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term4,Bytes6,Rb5} = case Bytes5 of | |
| +<<2:2,_:1,0:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes5,[],[{tag,128,0,'IMPLICIT',32}], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes5, 0 } | |
| +end, | |
| + | |
| + {Bytes7,Rb6} = ?RT_BER:restbytes2(RemBytes, Bytes6,noext), | |
| + {{'ModifyDNRequest', Term1, Term2, Term3, Term4}, Bytes7, Rb1+Rb2+Rb3+Rb4+Rb5+Rb6}. | |
| + | |
| + | |
| +%%================================ | |
| +%% ModifyDNResponse | |
| +%%================================ | |
| + | |
| +'enc_ModifyDNResponse'({'ModifyDNResponse',Val}, TagIn) -> | |
| + 'enc_ModifyDNResponse'(Val, TagIn); | |
| + | |
| +'enc_ModifyDNResponse'(Val, TagIn) -> | |
| + 'enc_LDAPResult'(Val, TagIn ++ [{tag,64,13,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_ModifyDNResponse'(Bytes, OptOrMand) -> | |
| + 'dec_ModifyDNResponse'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_ModifyDNResponse'(Bytes, OptOrMand, TagIn) -> | |
| +'dec_LDAPResult'(Bytes, OptOrMand, TagIn++[{tag,64,13,'IMPLICIT',32}]). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% CompareRequest | |
| +%%================================ | |
| +'enc_CompareRequest'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,entry), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:AttributeValueAssertion | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = 'enc_AttributeValueAssertion'(?RT_BER:cindex(3,Val,ava), []), | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,14,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_CompareRequest'(Bytes, OptOrMand) -> | |
| + 'dec_CompareRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_CompareRequest'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,14,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 External ELDAPv3:AttributeValueAssertion | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = 'dec_AttributeValueAssertion'(Bytes3, mandatory, []), | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'CompareRequest', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% CompareResponse | |
| +%%================================ | |
| + | |
| +'enc_CompareResponse'({'CompareResponse',Val}, TagIn) -> | |
| + 'enc_CompareResponse'(Val, TagIn); | |
| + | |
| +'enc_CompareResponse'(Val, TagIn) -> | |
| + 'enc_LDAPResult'(Val, TagIn ++ [{tag,64,15,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_CompareResponse'(Bytes, OptOrMand) -> | |
| + 'dec_CompareResponse'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_CompareResponse'(Bytes, OptOrMand, TagIn) -> | |
| +'dec_LDAPResult'(Bytes, OptOrMand, TagIn++[{tag,64,15,'IMPLICIT',32}]). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% AbandonRequest | |
| +%%================================ | |
| + | |
| +'enc_AbandonRequest'({'AbandonRequest',Val}, TagIn) -> | |
| + 'enc_AbandonRequest'(Val, TagIn); | |
| + | |
| +'enc_AbandonRequest'(Val, TagIn) -> | |
| +?RT_BER:encode_integer([], Val, TagIn ++ [{tag,64,16,'IMPLICIT',32}]). | |
| + | |
| + | |
| +'dec_AbandonRequest'(Bytes, OptOrMand) -> | |
| + 'dec_AbandonRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_AbandonRequest'(Bytes, OptOrMand, TagIn) -> | |
| +?RT_BER:decode_integer(Bytes,{0,2147483647},TagIn++[{tag,64,16,'IMPLICIT',32}], OptOrMand). | |
| + | |
| + | |
| + | |
| +%%================================ | |
| +%% ExtendedRequest | |
| +%%================================ | |
| +'enc_ExtendedRequest'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(2,Val,requestName), [{tag,128,0,'IMPLICIT',32}]), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = case ?RT_BER:cindex(3,Val,requestValue) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,requestValue), [{tag,128,1,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2], | |
| + LenSoFar = EncLen1 + EncLen2, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,23,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_ExtendedRequest'(Bytes, OptOrMand) -> | |
| + 'dec_ExtendedRequest'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_ExtendedRequest'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,23,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_octet_string(Bytes2,[],[{tag,128,0,'IMPLICIT',32}], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = case Bytes3 of | |
| +<<2:2,_:1,1:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes3,[],[{tag,128,1,'IMPLICIT',32}], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes3, 0 } | |
| +end, | |
| + | |
| + {Bytes5,Rb4} = ?RT_BER:restbytes2(RemBytes, Bytes4,noext), | |
| + {{'ExtendedRequest', Term1, Term2}, Bytes5, Rb1+Rb2+Rb3+Rb4}. | |
| + | |
| + | |
| +%%================================ | |
| +%% ExtendedResponse | |
| +%%================================ | |
| +'enc_ExtendedResponse'(Val, TagIn) -> | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {EncBytes1,EncLen1} = case (case ?RT_BER:cindex(2,Val,resultCode) of {_,Enumval1}->Enumval1;_->?RT_BER:cindex(2,Val,resultCode) end) of | |
| +success -> ?RT_BER:encode_enumerated(0,[]); | |
| +operationsError -> ?RT_BER:encode_enumerated(1,[]); | |
| +protocolError -> ?RT_BER:encode_enumerated(2,[]); | |
| +timeLimitExceeded -> ?RT_BER:encode_enumerated(3,[]); | |
| +sizeLimitExceeded -> ?RT_BER:encode_enumerated(4,[]); | |
| +compareFalse -> ?RT_BER:encode_enumerated(5,[]); | |
| +compareTrue -> ?RT_BER:encode_enumerated(6,[]); | |
| +authMethodNotSupported -> ?RT_BER:encode_enumerated(7,[]); | |
| +strongAuthRequired -> ?RT_BER:encode_enumerated(8,[]); | |
| +referral -> ?RT_BER:encode_enumerated(10,[]); | |
| +adminLimitExceeded -> ?RT_BER:encode_enumerated(11,[]); | |
| +unavailableCriticalExtension -> ?RT_BER:encode_enumerated(12,[]); | |
| +confidentialityRequired -> ?RT_BER:encode_enumerated(13,[]); | |
| +saslBindInProgress -> ?RT_BER:encode_enumerated(14,[]); | |
| +noSuchAttribute -> ?RT_BER:encode_enumerated(16,[]); | |
| +undefinedAttributeType -> ?RT_BER:encode_enumerated(17,[]); | |
| +inappropriateMatching -> ?RT_BER:encode_enumerated(18,[]); | |
| +constraintViolation -> ?RT_BER:encode_enumerated(19,[]); | |
| +attributeOrValueExists -> ?RT_BER:encode_enumerated(20,[]); | |
| +invalidAttributeSyntax -> ?RT_BER:encode_enumerated(21,[]); | |
| +noSuchObject -> ?RT_BER:encode_enumerated(32,[]); | |
| +aliasProblem -> ?RT_BER:encode_enumerated(33,[]); | |
| +invalidDNSyntax -> ?RT_BER:encode_enumerated(34,[]); | |
| +aliasDereferencingProblem -> ?RT_BER:encode_enumerated(36,[]); | |
| +inappropriateAuthentication -> ?RT_BER:encode_enumerated(48,[]); | |
| +invalidCredentials -> ?RT_BER:encode_enumerated(49,[]); | |
| +insufficientAccessRights -> ?RT_BER:encode_enumerated(50,[]); | |
| +busy -> ?RT_BER:encode_enumerated(51,[]); | |
| +unavailable -> ?RT_BER:encode_enumerated(52,[]); | |
| +unwillingToPerform -> ?RT_BER:encode_enumerated(53,[]); | |
| +loopDetect -> ?RT_BER:encode_enumerated(54,[]); | |
| +namingViolation -> ?RT_BER:encode_enumerated(64,[]); | |
| +objectClassViolation -> ?RT_BER:encode_enumerated(65,[]); | |
| +notAllowedOnNonLeaf -> ?RT_BER:encode_enumerated(66,[]); | |
| +notAllowedOnRDN -> ?RT_BER:encode_enumerated(67,[]); | |
| +entryAlreadyExists -> ?RT_BER:encode_enumerated(68,[]); | |
| +objectClassModsProhibited -> ?RT_BER:encode_enumerated(69,[]); | |
| +affectsMultipleDSAs -> ?RT_BER:encode_enumerated(71,[]); | |
| +other -> ?RT_BER:encode_enumerated(80,[]); | |
| +Enumval2 -> exit({error,{asn1, {enumerated_not_in_range,Enumval2}}}) | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes2,EncLen2} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(3,Val,matchedDN), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {EncBytes3,EncLen3} = ?RT_BER:encode_octet_string([], ?RT_BER:cindex(4,Val,errorMessage), []), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 External ELDAPv3:Referral OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes4,EncLen4} = case ?RT_BER:cindex(5,Val,referral) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + 'enc_Referral'(?RT_BER:cindex(5,Val,referral), [{tag,128,3,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 5 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes5,EncLen5} = case ?RT_BER:cindex(6,Val,responseName) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(6,Val,responseName), [{tag,128,10,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 6 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {EncBytes6,EncLen6} = case ?RT_BER:cindex(7,Val,response) of | |
| + asn1_NOVALUE -> {<<>>,0}; | |
| + _ -> | |
| + ?RT_BER:encode_octet_string([], ?RT_BER:cindex(7,Val,response), [{tag,128,11,'IMPLICIT',32}]) | |
| + end, | |
| + | |
| + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5, EncBytes6], | |
| + LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5 + EncLen6, | |
| + ?RT_BER:encode_tags(TagIn ++ [{tag,64,24,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], BytesSoFar, LenSoFar). | |
| + | |
| + | |
| +'dec_ExtendedResponse'(Bytes, OptOrMand) -> | |
| + 'dec_ExtendedResponse'(Bytes, OptOrMand, []). | |
| + | |
| +'dec_ExtendedResponse'(Bytes, OptOrMand, TagIn) -> | |
| + %%------------------------------------------------- | |
| + %% decode tag and length | |
| + %%------------------------------------------------- | |
| + {{_,Len},Bytes1,Rb1} = ?RT_BER:check_tags(TagIn ++ [{tag,64,24,'IMPLICIT',32},{tag,0,16,'IMPLICIT',32}], Bytes, OptOrMand), | |
| +{Bytes2,RemBytes} = ?RT_BER:split_list(Bytes1,Len), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 1 with type ENUMERATED | |
| +%%------------------------------------------------- | |
| + {Term1,Bytes3,Rb2} = ?RT_BER:decode_enumerated(Bytes2,[],[{success,0},{operationsError,1},{protocolError,2},{timeLimitExceeded,3},{sizeLimitExceeded,4},{compareFalse,5},{compareTrue,6},{authMethodNotSupported,7},{strongAuthRequired,8},{referral,10},{adminLimitExceeded,11},{unavailableCriticalExtension,12},{confidentialityRequired,13},{saslBindInProgress,14},{noSuchAttribute,16},{undefinedAttributeType,17},{inappropriateMatching,18},{constraintViolation,19},{attributeOrValueExists,20},{invalidAttributeSyntax,21},{noSuchObject,32},{aliasProblem,33},{invalidDNSyntax,34},{aliasDereferencingProblem,36},{inappropriateAuthentication,48},{invalidCredentials,49},{insufficientAccessRights,50},{busy,51},{unavailable,52},{unwillingToPerform,53},{loopDetect,54},{namingViolation,64},{objectClassViolation,65},{notAllowedOnNonLeaf,66},{notAllowedOnRDN,67},{entryAlreadyExists,68},{objectClassModsProhibited,69},{affectsMultipleDSAs,71},{other,80}],[], mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 2 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term2,Bytes4,Rb3} = ?RT_BER:decode_octet_string(Bytes3,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 3 with type OCTET STRING | |
| +%%------------------------------------------------- | |
| + {Term3,Bytes5,Rb4} = ?RT_BER:decode_octet_string(Bytes4,[],[], no_length, mandatory), | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 4 External ELDAPv3:Referral OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term4,Bytes6,Rb5} = case Bytes5 of | |
| +<<2:2,_:1,3:5,_/binary>> -> | |
| +'dec_Referral'(Bytes5, opt_or_default, [{tag,128,3,'IMPLICIT',32}]); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes5, 0 } | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 5 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term5,Bytes7,Rb6} = case Bytes6 of | |
| +<<2:2,_:1,10:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes6,[],[{tag,128,10,'IMPLICIT',32}], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes6, 0 } | |
| +end, | |
| + | |
| +%%------------------------------------------------- | |
| +%% attribute number 6 with type OCTET STRING OPTIONAL | |
| +%%------------------------------------------------- | |
| + {Term6,Bytes8,Rb7} = case Bytes7 of | |
| +<<2:2,_:1,11:5,_/binary>> -> | |
| +?RT_BER:decode_octet_string(Bytes7,[],[{tag,128,11,'IMPLICIT',32}], no_length, mandatory); | |
| +_ -> | |
| +{ asn1_NOVALUE, Bytes7, 0 } | |
| +end, | |
| + | |
| + {Bytes9,Rb8} = ?RT_BER:restbytes2(RemBytes, Bytes8,noext), | |
| + {{'ExtendedResponse', Term1, Term2, Term3, Term4, Term5, Term6}, Bytes9, Rb1+Rb2+Rb3+Rb4+Rb5+Rb6+Rb7+Rb8}. | |
| +'maxInt'() -> | |
| +2147483647. | |
| + | |
| diff --git src/eldap/ELDAPv3.hrl src/eldap/ELDAPv3.hrl | |
| new file mode 100644 | |
| index 0000000..d3fe60c | |
| --- /dev/null | |
| +++ src/eldap/ELDAPv3.hrl | |
| @@ -0,0 +1,74 @@ | |
| +%% Generated by the Erlang ASN.1 compiler version:1.6.15 | |
| +%% Purpose: Erlang record definitions for each named and unnamed | |
| +%% SEQUENCE and SET, and macro definitions for each value | |
| +%% definition,in module ELDAPv3 | |
| + | |
| + | |
| + | |
| +-record('LDAPMessage',{ | |
| +messageID, protocolOp, controls = asn1_NOVALUE}). | |
| + | |
| +-record('AttributeValueAssertion',{ | |
| +attributeDesc, assertionValue}). | |
| + | |
| +-record('Attribute',{ | |
| +type, vals}). | |
| + | |
| +-record('LDAPResult',{ | |
| +resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE}). | |
| + | |
| +-record('Control',{ | |
| +controlType, criticality = asn1_DEFAULT, controlValue = asn1_NOVALUE}). | |
| + | |
| +-record('BindRequest',{ | |
| +version, name, authentication}). | |
| + | |
| +-record('SaslCredentials',{ | |
| +mechanism, credentials = asn1_NOVALUE}). | |
| + | |
| +-record('BindResponse',{ | |
| +resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE, serverSaslCreds = asn1_NOVALUE}). | |
| + | |
| +-record('SearchRequest',{ | |
| +baseObject, scope, derefAliases, sizeLimit, timeLimit, typesOnly, filter, attributes}). | |
| + | |
| +-record('SubstringFilter',{ | |
| +type, substrings}). | |
| + | |
| +-record('MatchingRuleAssertion',{ | |
| +matchingRule = asn1_NOVALUE, type = asn1_NOVALUE, matchValue, dnAttributes = asn1_DEFAULT}). | |
| + | |
| +-record('SearchResultEntry',{ | |
| +objectName, attributes}). | |
| + | |
| +-record('PartialAttributeList_SEQOF',{ | |
| +type, vals}). | |
| + | |
| +-record('ModifyRequest',{ | |
| +object, modification}). | |
| + | |
| +-record('ModifyRequest_modification_SEQOF',{ | |
| +operation, modification}). | |
| + | |
| +-record('AttributeTypeAndValues',{ | |
| +type, vals}). | |
| + | |
| +-record('AddRequest',{ | |
| +entry, attributes}). | |
| + | |
| +-record('AttributeList_SEQOF',{ | |
| +type, vals}). | |
| + | |
| +-record('ModifyDNRequest',{ | |
| +entry, newrdn, deleteoldrdn, newSuperior = asn1_NOVALUE}). | |
| + | |
| +-record('CompareRequest',{ | |
| +entry, ava}). | |
| + | |
| +-record('ExtendedRequest',{ | |
| +requestName, requestValue = asn1_NOVALUE}). | |
| + | |
| +-record('ExtendedResponse',{ | |
| +resultCode, matchedDN, errorMessage, referral = asn1_NOVALUE, responseName = asn1_NOVALUE, response = asn1_NOVALUE}). | |
| + | |
| +-define('maxInt', 2147483647). | |
| diff --git src/eldap/Makefile.am src/eldap/Makefile.am | |
| new file mode 100644 | |
| index 0000000..948c037 | |
| --- /dev/null | |
| +++ src/eldap/Makefile.am | |
| @@ -0,0 +1,35 @@ | |
| +## Licensed under the Apache License, Version 2.0 (the "License"); you may not | |
| +## use this file except in compliance with the License. You may obtain a copy of | |
| +## the License at | |
| +## | |
| +## http://www.apache.org/licenses/LICENSE-2.0 | |
| +## | |
| +## Unless required by applicable law or agreed to in writing, software | |
| +## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
| +## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
| +## License for the specific language governing permissions and limitations under | |
| +## the License. | |
| + | |
| +eldapebindir = $(localerlanglibdir)/eldap/ebin | |
| + | |
| +eldap_file_collection = \ | |
| + eldap.erl \ | |
| + ELDAPv3.erl | |
| + | |
| +eldapebin_make_generated_file_list = \ | |
| + eldap.beam \ | |
| + ELDAPv3.beam | |
| + | |
| +eldapebin_DATA = \ | |
| + $(eldapebin_make_generated_file_list) | |
| + | |
| +EXTRA_DIST = \ | |
| + $(eldap_file_collection) \ | |
| + eldap.hrl \ | |
| + ELDAPv3.hrl | |
| + | |
| +CLEANFILES = \ | |
| + $(eldapebin_make_generated_file_list) | |
| + | |
| +%.beam: %.erl | |
| + $(ERLC) $(ERLC_FLAGS) $< | |
| diff --git src/eldap/eldap.erl src/eldap/eldap.erl | |
| new file mode 100644 | |
| index 0000000..ae2aca5 | |
| --- /dev/null | |
| +++ src/eldap/eldap.erl | |
| @@ -0,0 +1,1082 @@ | |
| +-module(eldap). | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Created: 12 Oct 2000 by Tobbe <tnt@home.se> | |
| +%%% Function: Erlang client LDAP implementation according RFC 2251,2253 | |
| +%%% and 2255. The interface is based on RFC 1823, and | |
| +%%% draft-ietf-asid-ldap-c-api-00.txt | |
| +%%% -------------------------------------------------------------------- | |
| +-vc('$Id$ '). | |
| +-export([open/1,open/2,simple_bind/3,controlling_process/2, | |
| + baseObject/0,singleLevel/0,wholeSubtree/0,close/1, | |
| + equalityMatch/2,greaterOrEqual/2,lessOrEqual/2, | |
| + approxMatch/2,search/2,substrings/2,present/1, | |
| + 'and'/1,'or'/1,'not'/1,modify/3, mod_add/2, mod_delete/2, | |
| + mod_replace/2, add/3, delete/2, modify_dn/5,parse_dn/1, | |
| + parse_ldap_url/1]). | |
| + | |
| +-import(lists,[concat/1]). | |
| + | |
| +-include("ELDAPv3.hrl"). | |
| +-include("eldap.hrl"). | |
| + | |
| +-define(LDAP_VERSION, 3). | |
| +-define(LDAP_PORT, 389). | |
| +-define(LDAPS_PORT, 636). | |
| + | |
| +-record(eldap, {version = ?LDAP_VERSION, | |
| + host, % Host running LDAP server | |
| + port = ?LDAP_PORT, % The LDAP server port | |
| + fd, % Socket filedescriptor. | |
| + binddn = "", % Name of the entry to bind as | |
| + passwd, % Password for (above) entry | |
| + id = 0, % LDAP Request ID | |
| + log, % User provided log function | |
| + timeout = infinity, % Request timeout | |
| + anon_auth = false, % Allow anonymous authentication | |
| + use_tls = false % LDAP/LDAPS | |
| + }). | |
| + | |
| +%%% For debug purposes | |
| +%%-define(PRINT(S, A), io:fwrite("~w(~w): " ++ S, [?MODULE,?LINE|A])). | |
| +-define(PRINT(S, A), true). | |
| + | |
| +-define(elog(S, A), error_logger:info_msg("~w(~w): "++S,[?MODULE,?LINE|A])). | |
| + | |
| +%%% ==================================================================== | |
| +%%% Exported interface | |
| +%%% ==================================================================== | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% open(Hosts [,Opts] ) | |
| +%%% -------------------- | |
| +%%% Setup a connection to on of the Hosts in the argument | |
| +%%% list. Stop at the first successful connection attempt. | |
| +%%% Valid Opts are: Where: | |
| +%%% | |
| +%%% {port, Port} - Port is the port number | |
| +%%% {log, F} - F(LogLevel, FormatString, ListOfArgs) | |
| +%%% {timeout, milliSec} - request timeout | |
| +%%% | |
| +%%% -------------------------------------------------------------------- | |
| +open(Hosts) -> | |
| + open(Hosts, []). | |
| + | |
| +open(Hosts, Opts) when list(Hosts), list(Opts) -> | |
| + Self = self(), | |
| + Pid = spawn_link(fun() -> init(Hosts, Opts, Self) end), | |
| + recv(Pid). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Shutdown connection (and process) asynchronous. | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +close(Handle) when pid(Handle) -> | |
| + send(Handle, close). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Set who we should link ourselves to | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +controlling_process(Handle, Pid) when pid(Handle),pid(Pid) -> | |
| + link(Pid), | |
| + send(Handle, {cnt_proc, Pid}), | |
| + recv(Handle). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Authenticate ourselves to the Directory | |
| +%%% using simple authentication. | |
| +%%% | |
| +%%% Dn - The name of the entry to bind as | |
| +%%% Passwd - The password to be used | |
| +%%% | |
| +%%% Returns: ok | {error, Error} | |
| +%%% -------------------------------------------------------------------- | |
| +simple_bind(Handle, Dn, Passwd) when pid(Handle) -> | |
| + send(Handle, {simple_bind, Dn, Passwd}), | |
| + recv(Handle). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Add an entry. The entry field MUST NOT exist for the AddRequest | |
| +%%% to succeed. The parent of the entry MUST exist. | |
| +%%% Example: | |
| +%%% | |
| +%%% add(Handle, | |
| +%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", | |
| +%%% [{"objectclass", ["person"]}, | |
| +%%% {"cn", ["Bill Valentine"]}, | |
| +%%% {"sn", ["Valentine"]}, | |
| +%%% {"telephoneNumber", ["545 555 00"]}] | |
| +%%% ) | |
| +%%% -------------------------------------------------------------------- | |
| +add(Handle, Entry, Attributes) when pid(Handle),list(Entry),list(Attributes) -> | |
| + send(Handle, {add, Entry, add_attrs(Attributes)}), | |
| + recv(Handle). | |
| + | |
| +%%% Do sanity check ! | |
| +add_attrs(Attrs) -> | |
| + F = fun({Type,Vals}) when list(Type),list(Vals) -> | |
| + %% Confused ? Me too... :-/ | |
| + {'AddRequest_attributes',Type, Vals} | |
| + end, | |
| + case catch lists:map(F, Attrs) of | |
| + {'EXIT', _} -> throw({error, attribute_values}); | |
| + Else -> Else | |
| + end. | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Delete an entry. The entry consists of the DN of | |
| +%%% the entry to be deleted. | |
| +%%% Example: | |
| +%%% | |
| +%%% delete(Handle, | |
| +%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com" | |
| +%%% ) | |
| +%%% -------------------------------------------------------------------- | |
| +delete(Handle, Entry) when pid(Handle), list(Entry) -> | |
| + send(Handle, {delete, Entry}), | |
| + recv(Handle). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Modify an entry. Given an entry a number of modification | |
| +%%% operations can be performed as one atomic operation. | |
| +%%% Example: | |
| +%%% | |
| +%%% modify(Handle, | |
| +%%% "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", | |
| +%%% [replace("telephoneNumber", ["555 555 00"]), | |
| +%%% add("description", ["LDAP hacker"])] | |
| +%%% ) | |
| +%%% -------------------------------------------------------------------- | |
| +modify(Handle, Object, Mods) when pid(Handle), list(Object), list(Mods) -> | |
| + send(Handle, {modify, Object, Mods}), | |
| + recv(Handle). | |
| + | |
| +%%% | |
| +%%% Modification operations. | |
| +%%% Example: | |
| +%%% replace("telephoneNumber", ["555 555 00"]) | |
| +%%% | |
| +mod_add(Type, Values) when list(Type), list(Values) -> m(add, Type, Values). | |
| +mod_delete(Type, Values) when list(Type), list(Values) -> m(delete, Type, Values). | |
| +mod_replace(Type, Values) when list(Type), list(Values) -> m(replace, Type, Values). | |
| + | |
| +m(Operation, Type, Values) -> | |
| + #'ModifyRequest_modification_SEQOF'{ | |
| + operation = Operation, | |
| + modification = #'AttributeTypeAndValues'{ | |
| + type = Type, | |
| + vals = Values}}. | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Modify an entry. Given an entry a number of modification | |
| +%%% operations can be performed as one atomic operation. | |
| +%%% Example: | |
| +%%% | |
| +%%% modify_dn(Handle, | |
| +%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", | |
| +%%% "cn=Ben Emerson", | |
| +%%% true, | |
| +%%% "" | |
| +%%% ) | |
| +%%% -------------------------------------------------------------------- | |
| +modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) | |
| + when pid(Handle),list(Entry),list(NewRDN),atom(DelOldRDN),list(NewSup) -> | |
| + send(Handle, {modify_dn, Entry, NewRDN, | |
| + bool_p(DelOldRDN), optional(NewSup)}), | |
| + recv(Handle). | |
| + | |
| +%%% Sanity checks ! | |
| + | |
| +bool_p(Bool) when Bool==true;Bool==false -> Bool. | |
| + | |
| +optional([]) -> asn1_NOVALUE; | |
| +optional(Value) -> Value. | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Synchronous search of the Directory returning a | |
| +%%% requested set of attributes. | |
| +%%% | |
| +%%% Example: | |
| +%%% | |
| +%%% Filter = eldap:substrings("sn", [{any,"o"}]), | |
| +%%% eldap:search(S, [{base, "dc=bluetail, dc=com"}, | |
| +%%% {filter, Filter}, | |
| +%%% {attributes,["cn"]}])), | |
| +%%% | |
| +%%% Returned result: {ok, #eldap_search_result{}} | |
| +%%% | |
| +%%% Example: | |
| +%%% | |
| +%%% {ok,{eldap_search_result, | |
| +%%% [{eldap_entry, | |
| +%%% "cn=Magnus Froberg, dc=bluetail, dc=com", | |
| +%%% [{"cn",["Magnus Froberg"]}]}, | |
| +%%% {eldap_entry, | |
| +%%% "cn=Torbjorn Tornkvist, dc=bluetail, dc=com", | |
| +%%% [{"cn",["Torbjorn Tornkvist"]}]}], | |
| +%%% []}} | |
| +%%% | |
| +%%% -------------------------------------------------------------------- | |
| +search(Handle, A) when pid(Handle), record(A, eldap_search) -> | |
| + call_search(Handle, A); | |
| +search(Handle, L) when pid(Handle), list(L) -> | |
| + case catch parse_search_args(L) of | |
| + {error, Emsg} -> {error, Emsg}; | |
| + A when record(A, eldap_search) -> call_search(Handle, A) | |
| + end. | |
| + | |
| +call_search(Handle, A) -> | |
| + send(Handle, {search, A}), | |
| + recv(Handle). | |
| + | |
| +parse_search_args(Args) -> | |
| + parse_search_args(Args, #eldap_search{scope = wholeSubtree}). | |
| + | |
| +parse_search_args([{base, Base}|T],A) -> | |
| + parse_search_args(T,A#eldap_search{base = Base}); | |
| +parse_search_args([{filter, Filter}|T],A) -> | |
| + parse_search_args(T,A#eldap_search{filter = Filter}); | |
| +parse_search_args([{scope, Scope}|T],A) -> | |
| + parse_search_args(T,A#eldap_search{scope = Scope}); | |
| +parse_search_args([{attributes, Attrs}|T],A) -> | |
| + parse_search_args(T,A#eldap_search{attributes = Attrs}); | |
| +parse_search_args([{types_only, TypesOnly}|T],A) -> | |
| + parse_search_args(T,A#eldap_search{types_only = TypesOnly}); | |
| +parse_search_args([{timeout, Timeout}|T],A) when integer(Timeout) -> | |
| + parse_search_args(T,A#eldap_search{timeout = Timeout}); | |
| +parse_search_args([H|_],_) -> | |
| + throw({error,{unknown_arg, H}}); | |
| +parse_search_args([],A) -> | |
| + A. | |
| + | |
| +%%% | |
| +%%% The Scope parameter | |
| +%%% | |
| +baseObject() -> baseObject. | |
| +singleLevel() -> singleLevel. | |
| +wholeSubtree() -> wholeSubtree. | |
| + | |
| +%%% | |
| +%%% Boolean filter operations | |
| +%%% | |
| +'and'(ListOfFilters) when list(ListOfFilters) -> {'and',ListOfFilters}. | |
| +'or'(ListOfFilters) when list(ListOfFilters) -> {'or', ListOfFilters}. | |
| +'not'(Filter) when tuple(Filter) -> {'not',Filter}. | |
| + | |
| +%%% | |
| +%%% The following Filter parameters consist of an attribute | |
| +%%% and an attribute value. Example: F("uid","tobbe") | |
| +%%% | |
| +equalityMatch(Desc, Value) -> {equalityMatch, av_assert(Desc, Value)}. | |
| +greaterOrEqual(Desc, Value) -> {greaterOrEqual, av_assert(Desc, Value)}. | |
| +lessOrEqual(Desc, Value) -> {lessOrEqual, av_assert(Desc, Value)}. | |
| +approxMatch(Desc, Value) -> {approxMatch, av_assert(Desc, Value)}. | |
| + | |
| +av_assert(Desc, Value) -> | |
| + #'AttributeValueAssertion'{attributeDesc = Desc, | |
| + assertionValue = Value}. | |
| + | |
| +%%% | |
| +%%% Filter to check for the presence of an attribute | |
| +%%% | |
| +present(Attribute) when list(Attribute) -> | |
| + {present, Attribute}. | |
| + | |
| + | |
| +%%% | |
| +%%% A substring filter seem to be based on a pattern: | |
| +%%% | |
| +%%% InitValue*AnyValue*FinalValue | |
| +%%% | |
| +%%% where all three parts seem to be optional (at least when | |
| +%%% talking with an OpenLDAP server). Thus, the arguments | |
| +%%% to substrings/2 looks like this: | |
| +%%% | |
| +%%% Type ::= string( <attribute> ) | |
| +%%% SubStr ::= listof( {initial,Value} | {any,Value}, {final,Value}) | |
| +%%% | |
| +%%% Example: substrings("sn",[{initial,"To"},{any,"kv"},{final,"st"}]) | |
| +%%% will match entries containing: 'sn: Tornkvist' | |
| +%%% | |
| +substrings(Type, SubStr) when list(Type), list(SubStr) -> | |
| + Ss = {'SubstringFilter_substrings',v_substr(SubStr)}, | |
| + {substrings,#'SubstringFilter'{type = Type, | |
| + substrings = Ss}}. | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Worker process. We keep track of a controlling process to | |
| +%%% be able to terminate together with it. | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +init(Hosts, Opts, Cpid) -> | |
| + Data = parse_args(Opts, Cpid, #eldap{}), | |
| + case try_connect(Hosts, Data) of | |
| + {ok,Data2} -> | |
| + send(Cpid, {ok,self()}), | |
| + put(req_timeout, Data#eldap.timeout), % kludge... | |
| + loop(Cpid, Data2); | |
| + Else -> | |
| + send(Cpid, Else), | |
| + unlink(Cpid), | |
| + exit(Else) | |
| + end. | |
| + | |
| +parse_args([{port, Port}|T], Cpid, Data) when integer(Port) -> | |
| + parse_args(T, Cpid, Data#eldap{port = Port}); | |
| +parse_args([{timeout, Timeout}|T], Cpid, Data) when integer(Timeout),Timeout>0 -> | |
| + parse_args(T, Cpid, Data#eldap{timeout = Timeout}); | |
| +parse_args([{anon_auth, true}|T], Cpid, Data) -> | |
| + parse_args(T, Cpid, Data#eldap{anon_auth = false}); | |
| +parse_args([{anon_auth, _}|T], Cpid, Data) -> | |
| + parse_args(T, Cpid, Data); | |
| +parse_args([{ssl, true}|T], Cpid, Data) -> | |
| + parse_args(T, Cpid, Data#eldap{use_tls = true}); | |
| +parse_args([{ssl, _}|T], Cpid, Data) -> | |
| + parse_args(T, Cpid, Data); | |
| +parse_args([{log, F}|T], Cpid, Data) when function(F) -> | |
| + parse_args(T, Cpid, Data#eldap{log = F}); | |
| +parse_args([{log, _}|T], Cpid, Data) -> | |
| + parse_args(T, Cpid, Data); | |
| +parse_args([H|_], Cpid, _) -> | |
| + send(Cpid, {error,{wrong_option,H}}), | |
| + exit(wrong_option); | |
| +parse_args([], _, Data) -> | |
| + Data. | |
| + | |
| +%%% Try to connect to the hosts in the listed order, | |
| +%%% and stop with the first one to which a successful | |
| +%%% connection is made. | |
| + | |
| +try_connect([Host|Hosts], Data) -> | |
| + TcpOpts = [{packet, asn1}, {active,false}], | |
| + case do_connect(Host, Data, TcpOpts) of | |
| + {ok,Fd} -> {ok,Data#eldap{host = Host, fd = Fd}}; | |
| + _ -> try_connect(Hosts, Data) | |
| + end; | |
| +try_connect([],_) -> | |
| + {error,"connect failed"}. | |
| + | |
| +do_connect(Host, Data, Opts) when Data#eldap.use_tls == false -> | |
| + gen_tcp:connect(Host, Data#eldap.port, Opts, Data#eldap.timeout); | |
| +do_connect(Host, Data, Opts) when Data#eldap.use_tls == true -> | |
| + Vsn = erlang:system_info(version), | |
| + if Vsn >= "5.3" -> | |
| + %% In R9C, but not in R9B | |
| + {_,_,X} = erlang:now(), | |
| + ssl:seed("bkrlnateqqo" ++ integer_to_list(X)); | |
| + true -> true | |
| + end, | |
| + ssl:connect(Host, Data#eldap.port, [{verify,0}|Opts]). | |
| + | |
| + | |
| +loop(Cpid, Data) -> | |
| + receive | |
| + | |
| + {From, {search, A}} -> | |
| + {Res,NewData} = do_search(Data, A), | |
| + send(From,Res), | |
| + loop(Cpid, NewData); | |
| + | |
| + {From, {modify, Obj, Mod}} -> | |
| + {Res,NewData} = do_modify(Data, Obj, Mod), | |
| + send(From,Res), | |
| + loop(Cpid, NewData); | |
| + | |
| + {From, {modify_dn, Obj, NewRDN, DelOldRDN, NewSup}} -> | |
| + {Res,NewData} = do_modify_dn(Data, Obj, NewRDN, DelOldRDN, NewSup), | |
| + send(From,Res), | |
| + loop(Cpid, NewData); | |
| + | |
| + {From, {add, Entry, Attrs}} -> | |
| + {Res,NewData} = do_add(Data, Entry, Attrs), | |
| + send(From,Res), | |
| + loop(Cpid, NewData); | |
| + | |
| + {From, {delete, Entry}} -> | |
| + {Res,NewData} = do_delete(Data, Entry), | |
| + send(From,Res), | |
| + loop(Cpid, NewData); | |
| + | |
| + {From, {simple_bind, Dn, Passwd}} -> | |
| + {Res,NewData} = do_simple_bind(Data, Dn, Passwd), | |
| + send(From,Res), | |
| + loop(Cpid, NewData); | |
| + | |
| + {From, {cnt_proc, NewCpid}} -> | |
| + unlink(Cpid), | |
| + send(From,ok), | |
| + ?PRINT("New Cpid is: ~p~n",[NewCpid]), | |
| + loop(NewCpid, Data); | |
| + | |
| + {From, close} -> | |
| + unlink(Cpid), | |
| + exit(closed); | |
| + | |
| + {Cpid, 'EXIT', Reason} -> | |
| + ?PRINT("Got EXIT from Cpid, reason=~p~n",[Reason]), | |
| + exit(Reason); | |
| + | |
| + _XX -> | |
| + ?PRINT("loop got: ~p~n",[_XX]), | |
| + loop(Cpid, Data) | |
| + | |
| + end. | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% bindRequest | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +%%% Authenticate ourselves to the directory using | |
| +%%% simple authentication. | |
| + | |
| +do_simple_bind(Data, anon, anon) -> %% For testing | |
| + do_the_simple_bind(Data, "", ""); | |
| +do_simple_bind(Data, Dn, _Passwd) when Dn=="",Data#eldap.anon_auth==false -> | |
| + {{error,anonymous_auth},Data}; | |
| +do_simple_bind(Data, _Dn, Passwd) when Passwd=="",Data#eldap.anon_auth==false -> | |
| + {{error,anonymous_auth},Data}; | |
| +do_simple_bind(Data, Dn, Passwd) -> | |
| + do_the_simple_bind(Data, Dn, Passwd). | |
| + | |
| +do_the_simple_bind(Data, Dn, Passwd) -> | |
| + case catch exec_simple_bind(Data#eldap{binddn = Dn, | |
| + passwd = Passwd, | |
| + id = bump_id(Data)}) of | |
| + {ok,NewData} -> {ok,NewData}; | |
| + {error,Emsg} -> {{error,Emsg},Data}; | |
| + Else -> {{error,Else},Data} | |
| + end. | |
| + | |
| +exec_simple_bind(Data) -> | |
| + Req = #'BindRequest'{version = Data#eldap.version, | |
| + name = Data#eldap.binddn, | |
| + authentication = {simple, Data#eldap.passwd}}, | |
| + log2(Data, "bind request = ~p~n", [Req]), | |
| + Reply = request(Data#eldap.fd, Data, Data#eldap.id, {bindRequest, Req}), | |
| + log2(Data, "bind reply = ~p~n", [Reply]), | |
| + exec_simple_bind_reply(Data, Reply). | |
| + | |
| +exec_simple_bind_reply(Data, {ok,Msg}) when | |
| + Msg#'LDAPMessage'.messageID == Data#eldap.id -> | |
| + case Msg#'LDAPMessage'.protocolOp of | |
| + {bindResponse, Result} -> | |
| + case Result#'BindResponse'.resultCode of | |
| + success -> {ok,Data}; | |
| + Error -> {error, Error} | |
| + end; | |
| + Other -> {error, Other} | |
| + end; | |
| +exec_simple_bind_reply(_, Error) -> | |
| + {error, Error}. | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% searchRequest | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +do_search(Data, A) -> | |
| + case catch do_search_0(Data, A) of | |
| + {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; | |
| + {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; | |
| + {ok,Res,Ref,NewData} -> {{ok,polish(Res, Ref)},NewData}; | |
| + Else -> {ldap_closed_p(Data, Else),Data} | |
| + end. | |
| + | |
| +%%% | |
| +%%% Polish the returned search result | |
| +%%% | |
| + | |
| +polish(Res, Ref) -> | |
| + R = polish_result(Res), | |
| + %%% No special treatment of referrals at the moment. | |
| + #eldap_search_result{entries = R, | |
| + referrals = Ref}. | |
| + | |
| +polish_result([H|T]) when record(H, 'SearchResultEntry') -> | |
| + ObjectName = H#'SearchResultEntry'.objectName, | |
| + F = fun({_,A,V}) -> {A,V} end, | |
| + Attrs = lists:map(F, H#'SearchResultEntry'.attributes), | |
| + [#eldap_entry{object_name = ObjectName, | |
| + attributes = Attrs}| | |
| + polish_result(T)]; | |
| +polish_result([]) -> | |
| + []. | |
| + | |
| +do_search_0(Data, A) -> | |
| + Req = #'SearchRequest'{baseObject = A#eldap_search.base, | |
| + scope = v_scope(A#eldap_search.scope), | |
| + derefAliases = neverDerefAliases, | |
| + sizeLimit = 0, % no size limit | |
| + timeLimit = v_timeout(A#eldap_search.timeout), | |
| + typesOnly = v_bool(A#eldap_search.types_only), | |
| + filter = v_filter(A#eldap_search.filter), | |
| + attributes = v_attributes(A#eldap_search.attributes) | |
| + }, | |
| + Id = bump_id(Data), | |
| + collect_search_responses(Data#eldap{id=Id}, Req, Id). | |
| + | |
| +%%% The returned answers cames in one packet per entry | |
| +%%% mixed with possible referals | |
| + | |
| +collect_search_responses(Data, Req, ID) -> | |
| + S = Data#eldap.fd, | |
| + log2(Data, "search request = ~p~n", [Req]), | |
| + send_request(S, Data, ID, {searchRequest, Req}), | |
| + Resp = recv_response(S, Data), | |
| + log2(Data, "search reply = ~p~n", [Resp]), | |
| + collect_search_responses(Data, S, ID, Resp, [], []). | |
| + | |
| +collect_search_responses(Data, S, ID, {ok,Msg}, Acc, Ref) | |
| + when record(Msg,'LDAPMessage') -> | |
| + case Msg#'LDAPMessage'.protocolOp of | |
| + {'searchResDone',R} when R#'LDAPResult'.resultCode == success -> | |
| + log2(Data, "search reply = searchResDone ~n", []), | |
| + {ok,Acc,Ref,Data}; | |
| + {'searchResEntry',R} when record(R,'SearchResultEntry') -> | |
| + Resp = recv_response(S, Data), | |
| + log2(Data, "search reply = ~p~n", [Resp]), | |
| + collect_search_responses(Data, S, ID, Resp, [R|Acc], Ref); | |
| + {'searchResRef',R} -> | |
| + %% At the moment we don't do anyting sensible here since | |
| + %% I haven't been able to trigger the server to generate | |
| + %% a response like this. | |
| + Resp = recv_response(S, Data), | |
| + log2(Data, "search reply = ~p~n", [Resp]), | |
| + collect_search_responses(Data, S, ID, Resp, Acc, [R|Ref]); | |
| + Else -> | |
| + throw({error,Else}) | |
| + end; | |
| +collect_search_responses(_, _, _, Else, _, _) -> | |
| + throw({error,Else}). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% addRequest | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +do_add(Data, Entry, Attrs) -> | |
| + case catch do_add_0(Data, Entry, Attrs) of | |
| + {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; | |
| + {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; | |
| + {ok,NewData} -> {ok,NewData}; | |
| + Else -> {ldap_closed_p(Data, Else),Data} | |
| + end. | |
| + | |
| +do_add_0(Data, Entry, Attrs) -> | |
| + Req = #'AddRequest'{entry = Entry, | |
| + attributes = Attrs}, | |
| + S = Data#eldap.fd, | |
| + Id = bump_id(Data), | |
| + log2(Data, "add request = ~p~n", [Req]), | |
| + Resp = request(S, Data, Id, {addRequest, Req}), | |
| + log2(Data, "add reply = ~p~n", [Resp]), | |
| + check_reply(Data#eldap{id = Id}, Resp, addResponse). | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% deleteRequest | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +do_delete(Data, Entry) -> | |
| + case catch do_delete_0(Data, Entry) of | |
| + {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; | |
| + {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; | |
| + {ok,NewData} -> {ok,NewData}; | |
| + Else -> {ldap_closed_p(Data, Else),Data} | |
| + end. | |
| + | |
| +do_delete_0(Data, Entry) -> | |
| + S = Data#eldap.fd, | |
| + Id = bump_id(Data), | |
| + log2(Data, "del request = ~p~n", [Entry]), | |
| + Resp = request(S, Data, Id, {delRequest, Entry}), | |
| + log2(Data, "del reply = ~p~n", [Resp]), | |
| + check_reply(Data#eldap{id = Id}, Resp, delResponse). | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% modifyRequest | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +do_modify(Data, Obj, Mod) -> | |
| + case catch do_modify_0(Data, Obj, Mod) of | |
| + {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; | |
| + {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; | |
| + {ok,NewData} -> {ok,NewData}; | |
| + Else -> {ldap_closed_p(Data, Else),Data} | |
| + end. | |
| + | |
| +do_modify_0(Data, Obj, Mod) -> | |
| + v_modifications(Mod), | |
| + Req = #'ModifyRequest'{object = Obj, | |
| + modification = Mod}, | |
| + S = Data#eldap.fd, | |
| + Id = bump_id(Data), | |
| + log2(Data, "modify request = ~p~n", [Req]), | |
| + Resp = request(S, Data, Id, {modifyRequest, Req}), | |
| + log2(Data, "modify reply = ~p~n", [Resp]), | |
| + check_reply(Data#eldap{id = Id}, Resp, modifyResponse). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% modifyDNRequest | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +do_modify_dn(Data, Entry, NewRDN, DelOldRDN, NewSup) -> | |
| + case catch do_modify_dn_0(Data, Entry, NewRDN, DelOldRDN, NewSup) of | |
| + {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; | |
| + {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; | |
| + {ok,NewData} -> {ok,NewData}; | |
| + Else -> {ldap_closed_p(Data, Else),Data} | |
| + end. | |
| + | |
| +do_modify_dn_0(Data, Entry, NewRDN, DelOldRDN, NewSup) -> | |
| + Req = #'ModifyDNRequest'{entry = Entry, | |
| + newrdn = NewRDN, | |
| + deleteoldrdn = DelOldRDN, | |
| + newSuperior = NewSup}, | |
| + S = Data#eldap.fd, | |
| + Id = bump_id(Data), | |
| + log2(Data, "modify DN request = ~p~n", [Req]), | |
| + Resp = request(S, Data, Id, {modDNRequest, Req}), | |
| + log2(Data, "modify DN reply = ~p~n", [Resp]), | |
| + check_reply(Data#eldap{id = Id}, Resp, modDNResponse). | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Send an LDAP request and receive the answer | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +request(S, Data, ID, Request) -> | |
| + send_request(S, Data, ID, Request), | |
| + recv_response(S, Data). | |
| + | |
| +send_request(S, Data, ID, Request) -> | |
| + Message = #'LDAPMessage'{messageID = ID, | |
| + protocolOp = Request}, | |
| + {ok,Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message), | |
| + case do_send(S, Data, Bytes) of | |
| + {error,Reason} -> throw({gen_tcp_error,Reason}); | |
| + Else -> Else | |
| + end. | |
| + | |
| +do_send(S, Data, Bytes) when Data#eldap.use_tls == false -> | |
| + gen_tcp:send(S, Bytes); | |
| +do_send(S, Data, Bytes) when Data#eldap.use_tls == true -> | |
| + ssl:send(S, Bytes). | |
| + | |
| +do_recv(S, Data, Len, Timeout) when Data#eldap.use_tls == false -> | |
| + gen_tcp:recv(S, Len, Timeout); | |
| +do_recv(S, Data, Len, Timeout) when Data#eldap.use_tls == true -> | |
| + ssl:recv(S, Len, Timeout). | |
| + | |
| +recv_response(S, Data) -> | |
| + Timeout = get(req_timeout), % kludge... | |
| + case do_recv(S, Data, 0, Timeout) of | |
| + {ok, Packet} -> | |
| + check_tag(Packet), | |
| + case asn1rt:decode('ELDAPv3', 'LDAPMessage', Packet) of | |
| + {ok,Resp} -> {ok,Resp}; | |
| + Error -> throw(Error) | |
| + end; | |
| + {error,Reason} -> | |
| + throw({gen_tcp_error, Reason}); | |
| + Error -> | |
| + throw(Error) | |
| + end. | |
| + | |
| +%%% Sanity check of received packet | |
| +check_tag(Data) -> | |
| + case asn1rt_ber_bin:decode_tag(b2l(Data)) of | |
| + {_Tag, Data1, _Rb} -> | |
| + case asn1rt_ber_bin:decode_length(b2l(Data1)) of | |
| + {{_Len, _Data2}, _Rb2} -> ok; | |
| + _ -> throw({error,decoded_tag_length}) | |
| + end; | |
| + _ -> throw({error,decoded_tag}) | |
| + end. | |
| + | |
| +%%% Check for expected kind of reply | |
| +check_reply(Data, {ok,Msg}, Op) when | |
| + Msg#'LDAPMessage'.messageID == Data#eldap.id -> | |
| + case Msg#'LDAPMessage'.protocolOp of | |
| + {Op, Result} -> | |
| + case Result#'LDAPResult'.resultCode of | |
| + success -> {ok,Data}; | |
| + Error -> {error, Error} | |
| + end; | |
| + Other -> {error, Other} | |
| + end; | |
| +check_reply(_, Error, _) -> | |
| + {error, Error}. | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Verify the input data | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +v_filter({'and',L}) -> {'and',L}; | |
| +v_filter({'or', L}) -> {'or',L}; | |
| +v_filter({'not',L}) -> {'not',L}; | |
| +v_filter({equalityMatch,AV}) -> {equalityMatch,AV}; | |
| +v_filter({greaterOrEqual,AV}) -> {greaterOrEqual,AV}; | |
| +v_filter({lessOrEqual,AV}) -> {lessOrEqual,AV}; | |
| +v_filter({approxMatch,AV}) -> {approxMatch,AV}; | |
| +v_filter({present,A}) -> {present,A}; | |
| +v_filter({substrings,S}) when record(S,'SubstringFilter') -> {substrings,S}; | |
| +v_filter(_Filter) -> throw({error,concat(["unknown filter: ",_Filter])}). | |
| + | |
| +v_modifications(Mods) -> | |
| + F = fun({_,Op,_}) -> | |
| + case lists:member(Op,[add,delete,replace]) of | |
| + true -> true; | |
| + _ -> throw({error,{mod_operation,Op}}) | |
| + end | |
| + end, | |
| + lists:foreach(F, Mods). | |
| + | |
| +v_substr([{Key,Str}|T]) when list(Str),Key==initial;Key==any;Key==final -> | |
| + [{Key,Str}|v_substr(T)]; | |
| +v_substr([H|_]) -> | |
| + throw({error,{substring_arg,H}}); | |
| +v_substr([]) -> | |
| + []. | |
| +v_scope(baseObject) -> baseObject; | |
| +v_scope(singleLevel) -> singleLevel; | |
| +v_scope(wholeSubtree) -> wholeSubtree; | |
| +v_scope(_Scope) -> throw({error,concat(["unknown scope: ",_Scope])}). | |
| + | |
| +v_bool(true) -> true; | |
| +v_bool(false) -> false; | |
| +v_bool(_Bool) -> throw({error,concat(["not Boolean: ",_Bool])}). | |
| + | |
| +v_timeout(I) when integer(I), I>=0 -> I; | |
| +v_timeout(_I) -> throw({error,concat(["timeout not positive integer: ",_I])}). | |
| + | |
| +v_attributes(Attrs) -> | |
| + F = fun(A) when list(A) -> A; | |
| + (A) -> throw({error,concat(["attribute not String: ",A])}) | |
| + end, | |
| + lists:map(F,Attrs). | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Log routines. Call a user provided log routine F. | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +log1(Data, Str, Args) -> log(Data, Str, Args, 1). | |
| +log2(Data, Str, Args) -> log(Data, Str, Args, 2). | |
| + | |
| +log(Data, Str, Args, Level) when function(Data#eldap.log) -> | |
| + catch (Data#eldap.log)(Level, Str, Args); | |
| +log(_, _, _, _) -> | |
| + ok. | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Misc. routines | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +send(To,Msg) -> To ! {self(),Msg}. | |
| +recv(From) -> receive {From,Msg} -> Msg end. | |
| + | |
| +ldap_closed_p(Data, Emsg) when Data#eldap.use_tls == true -> | |
| + %% Check if the SSL socket seems to be alive or not | |
| + case catch ssl:sockname(Data#eldap.fd) of | |
| + {error, _} -> | |
| + ssl:close(Data#eldap.fd), | |
| + {error, ldap_closed}; | |
| + {ok, _} -> | |
| + {error, Emsg}; | |
| + _ -> | |
| + %% sockname crashes if the socket pid is not alive | |
| + {error, ldap_closed} | |
| + end; | |
| +ldap_closed_p(Data, Emsg) -> | |
| + %% non-SSL socket | |
| + case inet:port(Data#eldap.fd) of | |
| + {error,_} -> {error, ldap_closed}; | |
| + _ -> {error,Emsg} | |
| + end. | |
| + | |
| +bump_id(Data) -> Data#eldap.id + 1. | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% parse_dn/1 - Implementation of RFC 2253: | |
| +%%% | |
| +%%% "UTF-8 String Representation of Distinguished Names" | |
| +%%% | |
| +%%% Test cases: | |
| +%%% | |
| +%%% The simplest case: | |
| +%%% | |
| +%%% 1> eldap:parse_dn("CN=Steve Kille,O=Isode Limited,C=GB"). | |
| +%%% {ok,[[{attribute_type_and_value,"CN","Steve Kille"}], | |
| +%%% [{attribute_type_and_value,"O","Isode Limited"}], | |
| +%%% [{attribute_type_and_value,"C","GB"}]]} | |
| +%%% | |
| +%%% The first RDN is multi-valued: | |
| +%%% | |
| +%%% 2> eldap:parse_dn("OU=Sales+CN=J. Smith,O=Widget Inc.,C=US"). | |
| +%%% {ok,[[{attribute_type_and_value,"OU","Sales"}, | |
| +%%% {attribute_type_and_value,"CN","J. Smith"}], | |
| +%%% [{attribute_type_and_value,"O","Widget Inc."}], | |
| +%%% [{attribute_type_and_value,"C","US"}]]} | |
| +%%% | |
| +%%% Quoting a comma: | |
| +%%% | |
| +%%% 3> eldap:parse_dn("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB"). | |
| +%%% {ok,[[{attribute_type_and_value,"CN","L. Eagle"}], | |
| +%%% [{attribute_type_and_value,"O","Sue\\, Grabbit and Runn"}], | |
| +%%% [{attribute_type_and_value,"C","GB"}]]} | |
| +%%% | |
| +%%% A value contains a carriage return: | |
| +%%% | |
| +%%% 4> eldap:parse_dn("CN=Before | |
| +%%% 4> After,O=Test,C=GB"). | |
| +%%% {ok,[[{attribute_type_and_value,"CN","Before\nAfter"}], | |
| +%%% [{attribute_type_and_value,"O","Test"}], | |
| +%%% [{attribute_type_and_value,"C","GB"}]]} | |
| +%%% | |
| +%%% 5> eldap:parse_dn("CN=Before\\0DAfter,O=Test,C=GB"). | |
| +%%% {ok,[[{attribute_type_and_value,"CN","Before\\0DAfter"}], | |
| +%%% [{attribute_type_and_value,"O","Test"}], | |
| +%%% [{attribute_type_and_value,"C","GB"}]]} | |
| +%%% | |
| +%%% An RDN in OID form: | |
| +%%% | |
| +%%% 6> eldap:parse_dn("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB"). | |
| +%%% {ok,[[{attribute_type_and_value,"1.3.6.1.4.1.1466.0","#04024869"}], | |
| +%%% [{attribute_type_and_value,"O","Test"}], | |
| +%%% [{attribute_type_and_value,"C","GB"}]]} | |
| +%%% | |
| +%%% | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +parse_dn("") -> % empty DN string | |
| + {ok,[]}; | |
| +parse_dn([H|_] = Str) when H=/=$, -> % 1:st name-component ! | |
| + case catch parse_name(Str,[]) of | |
| + {'EXIT',Reason} -> {parse_error,internal_error,Reason}; | |
| + Else -> Else | |
| + end. | |
| + | |
| +parse_name("",Acc) -> | |
| + {ok,lists:reverse(Acc)}; | |
| +parse_name([$,|T],Acc) -> % N:th name-component ! | |
| + parse_name(T,Acc); | |
| +parse_name(Str,Acc) -> | |
| + {Rest,NameComponent} = parse_name_component(Str), | |
| + parse_name(Rest,[NameComponent|Acc]). | |
| + | |
| +parse_name_component(Str) -> | |
| + parse_name_component(Str,[]). | |
| + | |
| +parse_name_component(Str,Acc) -> | |
| + case parse_attribute_type_and_value(Str) of | |
| + {[$+|Rest], ATV} -> | |
| + parse_name_component(Rest,[ATV|Acc]); | |
| + {Rest,ATV} -> | |
| + {Rest,lists:reverse([ATV|Acc])} | |
| + end. | |
| + | |
| +parse_attribute_type_and_value(Str) -> | |
| + case parse_attribute_type(Str) of | |
| + {Rest,[]} -> | |
| + error(expecting_attribute_type,Str); | |
| + {Rest,Type} -> | |
| + Rest2 = parse_equal_sign(Rest), | |
| + {Rest3,Value} = parse_attribute_value(Rest2), | |
| + {Rest3,{attribute_type_and_value,Type,Value}} | |
| + end. | |
| + | |
| +-define(IS_ALPHA(X) , X>=$a,X=<$z;X>=$A,X=<$Z ). | |
| +-define(IS_DIGIT(X) , X>=$0,X=<$9 ). | |
| +-define(IS_SPECIAL(X) , X==$,;X==$=;X==$+;X==$<;X==$>;X==$#;X==$; ). | |
| +-define(IS_QUOTECHAR(X) , X=/=$\\,X=/=$" ). | |
| +-define(IS_STRINGCHAR(X) , | |
| + X=/=$,,X=/=$=,X=/=$+,X=/=$<,X=/=$>,X=/=$#,X=/=$;,?IS_QUOTECHAR(X) ). | |
| +-define(IS_HEXCHAR(X) , ?IS_DIGIT(X);X>=$a,X=<$f;X>=$A,X=<$F ). | |
| + | |
| +parse_attribute_type([H|T]) when ?IS_ALPHA(H) -> | |
| + %% NB: It must be an error in the RFC in the definition | |
| + %% of 'attributeType', should be: (ALPHA *keychar) | |
| + {Rest,KeyChars} = parse_keychars(T), | |
| + {Rest,[H|KeyChars]}; | |
| +parse_attribute_type([H|_] = Str) when ?IS_DIGIT(H) -> | |
| + parse_oid(Str); | |
| +parse_attribute_type(Str) -> | |
| + error(invalid_attribute_type,Str). | |
| + | |
| + | |
| + | |
| +%%% Is a hexstring ! | |
| +parse_attribute_value([$#,X,Y|T]) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> | |
| + {Rest,HexString} = parse_hexstring(T), | |
| + {Rest,[$#,X,Y|HexString]}; | |
| +%%% Is a "quotation-sequence" ! | |
| +parse_attribute_value([$"|T]) -> | |
| + {Rest,Quotation} = parse_quotation(T), | |
| + {Rest,[$"|Quotation]}; | |
| +%%% Is a stringchar , pair or Empty ! | |
| +parse_attribute_value(Str) -> | |
| + parse_string(Str). | |
| + | |
| +parse_hexstring(Str) -> | |
| + parse_hexstring(Str,[]). | |
| + | |
| +parse_hexstring([X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> | |
| + parse_hexstring(T,[Y,X|Acc]); | |
| +parse_hexstring(T,Acc) -> | |
| + {T,lists:reverse(Acc)}. | |
| + | |
| +parse_quotation([$"|T]) -> % an empty: "" is ok ! | |
| + {T,[$"]}; | |
| +parse_quotation(Str) -> | |
| + parse_quotation(Str,[]). | |
| + | |
| +%%% Parse to end of quotation | |
| +parse_quotation([$"|T],Acc) -> | |
| + {T,lists:reverse([$"|Acc])}; | |
| +parse_quotation([X|T],Acc) when ?IS_QUOTECHAR(X) -> | |
| + parse_quotation(T,[X|Acc]); | |
| +parse_quotation([$\\,X|T],Acc) when ?IS_SPECIAL(X) -> | |
| + parse_quotation(T,[X,$\\|Acc]); | |
| +parse_quotation([$\\,$\\|T],Acc) -> | |
| + parse_quotation(T,[$\\,$\\|Acc]); | |
| +parse_quotation([$\\,$"|T],Acc) -> | |
| + parse_quotation(T,[$",$\\|Acc]); | |
| +parse_quotation([$\\,X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> | |
| + parse_quotation(T,[Y,X,$\\|Acc]); | |
| +parse_quotation(T,_) -> | |
| + error(expecting_double_quote_mark,T). | |
| + | |
| +parse_string(Str) -> | |
| + parse_string(Str,[]). | |
| + | |
| +parse_string("",Acc) -> | |
| + {"",lists:reverse(Acc)}; | |
| +parse_string([H|T],Acc) when ?IS_STRINGCHAR(H) -> | |
| + parse_string(T,[H|Acc]); | |
| +parse_string([$\\,X|T],Acc) when ?IS_SPECIAL(X) -> % is a pair ! | |
| + parse_string(T,[X,$\\|Acc]); | |
| +parse_string([$\\,$\\|T],Acc) -> % is a pair ! | |
| + parse_string(T,[$\\,$\\|Acc]); | |
| +parse_string([$\\,$" |T],Acc) -> % is a pair ! | |
| + parse_string(T,[$" ,$\\|Acc]); | |
| +parse_string([$\\,X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> % is a pair! | |
| + parse_string(T,[Y,X,$\\|Acc]); | |
| +parse_string(T,Acc) -> | |
| + {T,lists:reverse(Acc)}. | |
| + | |
| +parse_equal_sign([$=|T]) -> T; | |
| +parse_equal_sign(T) -> error(expecting_equal_sign,T). | |
| + | |
| +parse_keychars(Str) -> parse_keychars(Str,[]). | |
| + | |
| +parse_keychars([H|T],Acc) when ?IS_ALPHA(H) -> parse_keychars(T,[H|Acc]); | |
| +parse_keychars([H|T],Acc) when ?IS_DIGIT(H) -> parse_keychars(T,[H|Acc]); | |
| +parse_keychars([$-|T],Acc) -> parse_keychars(T,[$-|Acc]); | |
| +parse_keychars(T,Acc) -> {T,lists:reverse(Acc)}. | |
| + | |
| +parse_oid(Str) -> parse_oid(Str,[]). | |
| + | |
| +parse_oid([H,$.|T], Acc) when ?IS_DIGIT(H) -> | |
| + parse_oid(T,[$.,H|Acc]); | |
| +parse_oid([H|T], Acc) when ?IS_DIGIT(H) -> | |
| + parse_oid(T,[H|Acc]); | |
| +parse_oid(T, Acc) -> | |
| + {T,lists:reverse(Acc)}. | |
| + | |
| +error(Emsg,Rest) -> | |
| + throw({parse_error,Emsg,Rest}). | |
| + | |
| + | |
| +%%% -------------------------------------------------------------------- | |
| +%%% Parse LDAP url according to RFC 2255 | |
| +%%% | |
| +%%% Test case: | |
| +%%% | |
| +%%% 2> eldap:parse_ldap_url("ldap://10.42.126.33:389/cn=Administrative%20CA,o=Post%20Danmark,c=DK?certificateRevokationList;binary"). | |
| +%%% {ok,{{10,42,126,33},389}, | |
| +%%% [[{attribute_type_and_value,"cn","Administrative%20CA"}], | |
| +%%% [{attribute_type_and_value,"o","Post%20Danmark"}], | |
| +%%% [{attribute_type_and_value,"c","DK"}]], | |
| +%%% {attributes,["certificateRevokationList;binary"]}} | |
| +%%% | |
| +%%% -------------------------------------------------------------------- | |
| + | |
| +parse_ldap_url("ldap://" ++ Rest1 = Str) -> | |
| + {Rest2,HostPort} = parse_hostport(Rest1), | |
| + %% Split the string into DN and Attributes+etc | |
| + {Sdn,Rest3} = split_string(rm_leading_slash(Rest2),$?), | |
| + case parse_dn(Sdn) of | |
| + {parse_error,internal_error,_Reason} -> | |
| + {parse_error,internal_error,{Str,[]}}; | |
| + {parse_error,Emsg,Tail} -> | |
| + Head = get_head(Str,Tail), | |
| + {parse_error,Emsg,{Head,Tail}}; | |
| + {ok,DN} -> | |
| + %% We stop parsing here for now and leave | |
| + %% 'scope', 'filter' and 'extensions' to | |
| + %% be implemented later if needed. | |
| + {_Rest4,Attributes} = parse_attributes(Rest3), | |
| + {ok,HostPort,DN,Attributes} | |
| + end. | |
| + | |
| +rm_leading_slash([$/|Tail]) -> Tail; | |
| +rm_leading_slash(Tail) -> Tail. | |
| + | |
| +parse_attributes([$?|Tail]) -> | |
| + case split_string(Tail,$?) of | |
| + {[],Attributes} -> | |
| + {[],{attributes,string:tokens(Attributes,",")}}; | |
| + {Attributes,Rest} -> | |
| + {Rest,{attributes,string:tokens(Attributes,",")}} | |
| + end. | |
| + | |
| +parse_hostport(Str) -> | |
| + {HostPort,Rest} = split_string(Str,$/), | |
| + case split_string(HostPort,$:) of | |
| + {Shost,[]} -> | |
| + {Rest,{parse_host(Rest,Shost),?LDAP_PORT}}; | |
| + {Shost,[$:|Sport]} -> | |
| + {Rest,{parse_host(Rest,Shost), | |
| + parse_port(Rest,Sport)}} | |
| + end. | |
| + | |
| +parse_port(Rest,Sport) -> | |
| + case list_to_integer(Sport) of | |
| + Port when integer(Port) -> Port; | |
| + _ -> error(parsing_port,Rest) | |
| + end. | |
| + | |
| +parse_host(Rest,Shost) -> | |
| + case catch validate_host(Shost) of | |
| + {parse_error,Emsg,_} -> error(Emsg,Rest); | |
| + Host -> Host | |
| + end. | |
| + | |
| +validate_host(Shost) -> | |
| + case inet_parse:address(Shost) of | |
| + {ok,Host} -> Host; | |
| + _ -> | |
| + case inet_parse:domain(Shost) of | |
| + true -> Shost; | |
| + _ -> error(parsing_host,Shost) | |
| + end | |
| + end. | |
| + | |
| + | |
| +split_string(Str,Key) -> | |
| + Pred = fun(X) when X==Key -> false; (_) -> true end, | |
| + lists:splitwith(Pred, Str). | |
| + | |
| +get_head(Str,Tail) -> | |
| + get_head(Str,Tail,[]). | |
| + | |
| +%%% Should always succeed ! | |
| +get_head([H|Tail],Tail,Rhead) -> lists:reverse([H|Rhead]); | |
| +get_head([H|Rest],Tail,Rhead) -> get_head(Rest,Tail,[H|Rhead]). | |
| + | |
| +b2l(B) when binary(B) -> B; | |
| +b2l(L) when list(L) -> list_to_binary(L). | |
| + | |
| diff --git src/eldap/eldap.hrl src/eldap/eldap.hrl | |
| new file mode 100644 | |
| index 0000000..ee5ad2f | |
| --- /dev/null | |
| +++ src/eldap/eldap.hrl | |
| @@ -0,0 +1,32 @@ | |
| +-ifndef( _ELDAP_HRL ). | |
| +-define( _ELDAP_HRL , 1 ). | |
| + | |
| +%%% | |
| +%%% Search input parameters | |
| +%%% | |
| +-record(eldap_search, { | |
| + base = [], % Baseobject | |
| + filter = [], % Search conditions | |
| + scope, % Search scope | |
| + attributes = [], % Attributes to be returned | |
| + types_only = false, % Return types+values or types | |
| + timeout = 0 % Timelimit for search | |
| + }). | |
| + | |
| +%%% | |
| +%%% Returned search result | |
| +%%% | |
| +-record(eldap_search_result, { | |
| + entries = [], % List of #eldap_entry{} records | |
| + referrals = [] % List of referrals | |
| + }). | |
| + | |
| +%%% | |
| +%%% LDAP entry | |
| +%%% | |
| +-record(eldap_entry, { | |
| + object_name = "", % The DN for the entry | |
| + attributes = [] % List of {Attribute, Value} pairs | |
| + }). | |
| + | |
| +-endif. | |
| diff --git utils/Makefile.am utils/Makefile.am | |
| index 379c1eb..ed2ecff 100644 | |
| --- utils/Makefile.am | |
| +++ utils/Makefile.am | |
| @@ -25,6 +25,7 @@ run: ../bin/couchdb.tpl | |
| -e "s|%localini%|local_dev.ini|g" \ | |
| -e "s|%localerlanglibdir%|foo \ | |
| -pa $(abs_top_builddir)\/src\/couchdb \ | |
| + -pa $(abs_top_builddir)\/src\/eldap \ | |
| -pa $(abs_top_builddir)\/src\/erlang-oauth \ | |
| -pa $(abs_top_builddir)\/src\/ibrowse \ | |
| -pa $(abs_top_builddir)\/src\/mochiweb|g" \ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment