From 09e239e65cb24c003b9ad94565f831ea701c852e Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 5 Apr 2011 05:51:52 -0700 Subject: [PATCH] core files for the example LDAP server --- COPYING | 26 ++ Lightweight-Directory-Access-Protocol-V3.asn1 | 308 ++++++++++++++++++ Makefile | 192 +++++++++++ avatar.jpg | Bin 0 -> 2928 bytes ldap-server.c | 190 +++++++++++ 5 files changed, 716 insertions(+) create mode 100644 COPYING create mode 100644 Lightweight-Directory-Access-Protocol-V3.asn1 create mode 100644 Makefile create mode 100644 avatar.jpg create mode 100644 ldap-server.c diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..f1bcc89 --- /dev/null +++ b/COPYING @@ -0,0 +1,26 @@ +/*- + * Copyright (c) 2003-2011 Lev Walkin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ diff --git a/Lightweight-Directory-Access-Protocol-V3.asn1 b/Lightweight-Directory-Access-Protocol-V3.asn1 new file mode 100644 index 0000000..861a3ab --- /dev/null +++ b/Lightweight-Directory-Access-Protocol-V3.asn1 @@ -0,0 +1,308 @@ + +-- +-- ASN.1 module found by /usr/local/bin/crfc2asn1.pl in - at line 2983 +-- + + Lightweight-Directory-Access-Protocol-V3 {1 3 6 1 1 18} + -- Copyright (C) The Internet Society (2006). This version of + -- this ASN.1 module is part of RFC 4511; see the RFC itself + -- for full legal notices. + DEFINITIONS + IMPLICIT TAGS + EXTENSIBILITY IMPLIED ::= + + BEGIN + + LDAPMessage ::= SEQUENCE { + messageID MessageID, + protocolOp CHOICE { + bindRequest BindRequest, + bindResponse BindResponse, + unbindRequest UnbindRequest, + searchRequest SearchRequest, + searchResEntry SearchResultEntry, + searchResDone SearchResultDone, + searchResRef SearchResultReference, + modifyRequest ModifyRequest, + modifyResponse ModifyResponse, + addRequest AddRequest, + addResponse AddResponse, + delRequest DelRequest, + delResponse DelResponse, + modDNRequest ModifyDNRequest, + modDNResponse ModifyDNResponse, + compareRequest CompareRequest, + compareResponse CompareResponse, + abandonRequest AbandonRequest, + extendedReq ExtendedRequest, + extendedResp ExtendedResponse, + ..., + intermediateResponse IntermediateResponse }, + controls [0] Controls OPTIONAL } + + MessageID ::= INTEGER (0 .. maxInt) + + maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) -- + + LDAPString ::= [UNIVERSAL 4] IMPLICIT UTF8String -- UTF-8 encoded, + -- [ISO10646] characters + + + + + + + LDAPOID ::= OCTET STRING -- Constrained to + -- [RFC4512] + + LDAPDN ::= LDAPString -- Constrained to + -- [RFC4514] + + RelativeLDAPDN ::= LDAPString -- Constrained to + -- [RFC4514] + + AttributeDescription ::= LDAPString + -- Constrained to + -- [RFC4512] + + AttributeValue ::= OCTET STRING + + AttributeValueAssertion ::= SEQUENCE { + attributeDesc AttributeDescription, + assertionValue AssertionValue } + + AssertionValue ::= OCTET STRING + + PartialAttribute ::= SEQUENCE { + type AttributeDescription, + vals SET OF value AttributeValue } + + Attribute ::= PartialAttribute(WITH COMPONENTS { + ..., + vals (SIZE(1..MAX))}) + + MatchingRuleId ::= LDAPString + + LDAPResult ::= SEQUENCE { + resultCode ENUMERATED { + success (0), + operationsError (1), + protocolError (2), + timeLimitExceeded (3), + sizeLimitExceeded (4), + compareFalse (5), + compareTrue (6), + authMethodNotSupported (7), + strongerAuthRequired (8), + -- 9 reserved -- + referral (10), + adminLimitExceeded (11), + unavailableCriticalExtension (12), + confidentialityRequired (13), + saslBindInProgress (14), + + + + + + noSuchAttribute (16), + undefinedAttributeType (17), + inappropriateMatching (18), + constraintViolation (19), + attributeOrValueExists (20), + invalidAttributeSyntax (21), + -- 22-31 unused -- + noSuchObject (32), + aliasProblem (33), + invalidDNSyntax (34), + -- 35 reserved for undefined isLeaf -- + aliasDereferencingProblem (36), + -- 37-47 unused -- + inappropriateAuthentication (48), + invalidCredentials (49), + insufficientAccessRights (50), + busy (51), + unavailable (52), + unwillingToPerform (53), + loopDetect (54), + -- 55-63 unused -- + namingViolation (64), + objectClassViolation (65), + notAllowedOnNonLeaf (66), + notAllowedOnRDN (67), + entryAlreadyExists (68), + objectClassModsProhibited (69), + -- 70 reserved for CLDAP -- + affectsMultipleDSAs (71), + -- 72-79 unused -- + other (80), + ... }, + matchedDN LDAPDN, + diagnosticMessage LDAPString, + referral [3] Referral OPTIONAL } + + Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI + + URI ::= LDAPString -- limited to characters permitted in + -- URIs + + Controls ::= SEQUENCE OF control Control + + Control ::= SEQUENCE { + controlType LDAPOID, + criticality BOOLEAN DEFAULT FALSE, + controlValue OCTET STRING OPTIONAL } + + + + + + + BindRequest ::= [APPLICATION 0] SEQUENCE { + version INTEGER (1 .. 127), + name LDAPDN, + authentication AuthenticationChoice } + + AuthenticationChoice ::= CHOICE { + simple [0] OCTET STRING, + -- 1 and 2 reserved + sasl [3] SaslCredentials, + ... } + + SaslCredentials ::= SEQUENCE { + mechanism LDAPString, + credentials OCTET STRING OPTIONAL } + + BindResponse ::= [APPLICATION 1] SEQUENCE { + COMPONENTS OF LDAPResult, + serverSaslCreds [7] OCTET STRING OPTIONAL } + + UnbindRequest ::= [APPLICATION 2] NULL + + SearchRequest ::= [APPLICATION 3] SEQUENCE { + baseObject LDAPDN, + scope ENUMERATED { + baseObject (0), + singleLevel (1), + wholeSubtree (2), + ... }, + derefAliases ENUMERATED { + neverDerefAliases (0), + derefInSearching (1), + derefFindingBaseObj (2), + derefAlways (3) }, + sizeLimit INTEGER (0 .. maxInt), + timeLimit INTEGER (0 .. maxInt), + typesOnly BOOLEAN, + filter Filter, + attributes AttributeSelection } + + AttributeSelection ::= SEQUENCE OF selector LDAPString + -- The LDAPString is constrained to + -- in Section 4.5.1.8 + + Filter ::= CHOICE { + and [0] SET SIZE (1..MAX) OF filter Filter, + or [1] SET SIZE (1..MAX) OF filter Filter, + not [2] Filter, + equalityMatch [3] AttributeValueAssertion, + + + + + + substrings [4] SubstringFilter, + greaterOrEqual [5] AttributeValueAssertion, + lessOrEqual [6] AttributeValueAssertion, + present [7] AttributeDescription, + approxMatch [8] AttributeValueAssertion, + extensibleMatch [9] MatchingRuleAssertion, + ... } + + SubstringFilter ::= SEQUENCE { + type AttributeDescription, + substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE { + initial [0] AssertionValue, -- can occur at most once + any [1] AssertionValue, + final [2] AssertionValue } -- can occur at most once + } + + MatchingRuleAssertion ::= SEQUENCE { + matchingRule [1] MatchingRuleId OPTIONAL, + type [2] AttributeDescription OPTIONAL, + matchValue [3] AssertionValue, + dnAttributes [4] BOOLEAN DEFAULT FALSE } + + SearchResultEntry ::= [APPLICATION 4] SEQUENCE { + objectName LDAPDN, + attributes PartialAttributeList } + + PartialAttributeList ::= SEQUENCE OF + partialAttribute PartialAttribute + + SearchResultReference ::= [APPLICATION 19] SEQUENCE + SIZE (1..MAX) OF uri URI + + SearchResultDone ::= [APPLICATION 5] LDAPResult + + ModifyRequest ::= [APPLICATION 6] SEQUENCE { + object LDAPDN, + changes SEQUENCE OF change SEQUENCE { + operation ENUMERATED { + add (0), + delete (1), + replace (2), + ... }, + modification PartialAttribute } } + + ModifyResponse ::= [APPLICATION 7] LDAPResult + + + + + + + + + AddRequest ::= [APPLICATION 8] SEQUENCE { + entry LDAPDN, + attributes AttributeList } + + AttributeList ::= SEQUENCE OF attribute Attribute + + AddResponse ::= [APPLICATION 9] LDAPResult + + DelRequest ::= [APPLICATION 10] LDAPDN + + DelResponse ::= [APPLICATION 11] LDAPResult + + ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { + entry LDAPDN, + newrdn RelativeLDAPDN, + deleteoldrdn BOOLEAN, + newSuperior [0] LDAPDN OPTIONAL } + + ModifyDNResponse ::= [APPLICATION 13] LDAPResult + + CompareRequest ::= [APPLICATION 14] SEQUENCE { + entry LDAPDN, + ava AttributeValueAssertion } + + CompareResponse ::= [APPLICATION 15] LDAPResult + + AbandonRequest ::= [APPLICATION 16] MessageID + + ExtendedRequest ::= [APPLICATION 23] SEQUENCE { + requestName [0] LDAPOID, + requestValue [1] OCTET STRING OPTIONAL } + + ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + COMPONENTS OF LDAPResult, + responseName [10] LDAPOID OPTIONAL, + responseValue [11] OCTET STRING OPTIONAL } + + IntermediateResponse ::= [APPLICATION 25] SEQUENCE { + responseName [0] LDAPOID OPTIONAL, + responseValue [1] OCTET STRING OPTIONAL } + + END diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d52ba8f --- /dev/null +++ b/Makefile @@ -0,0 +1,192 @@ +ASN_MODULE_SOURCES= \ + LDAPMessage.c \ + MessageID.c \ + LDAPString.c \ + LDAPOID.c \ + LDAPDN.c \ + RelativeLDAPDN.c \ + AttributeDescription.c \ + AttributeValue.c \ + AttributeValueAssertion.c \ + AssertionValue.c \ + PartialAttribute.c \ + Attribute.c \ + MatchingRuleId.c \ + LDAPResult.c \ + Referral.c \ + URI.c \ + Controls.c \ + Control.c \ + BindRequest.c \ + AuthenticationChoice.c \ + SaslCredentials.c \ + BindResponse.c \ + UnbindRequest.c \ + SearchRequest.c \ + AttributeSelection.c \ + Filter.c \ + SubstringFilter.c \ + MatchingRuleAssertion.c \ + SearchResultEntry.c \ + PartialAttributeList.c \ + SearchResultReference.c \ + SearchResultDone.c \ + ModifyRequest.c \ + ModifyResponse.c \ + AddRequest.c \ + AttributeList.c \ + AddResponse.c \ + DelRequest.c \ + DelResponse.c \ + ModifyDNRequest.c \ + ModifyDNResponse.c \ + CompareRequest.c \ + CompareResponse.c \ + AbandonRequest.c \ + ExtendedRequest.c \ + ExtendedResponse.c \ + IntermediateResponse.c + +ASN_MODULE_HEADERS= \ + LDAPMessage.h \ + MessageID.h \ + LDAPString.h \ + LDAPOID.h \ + LDAPDN.h \ + RelativeLDAPDN.h \ + AttributeDescription.h \ + AttributeValue.h \ + AttributeValueAssertion.h \ + AssertionValue.h \ + PartialAttribute.h \ + Attribute.h \ + MatchingRuleId.h \ + LDAPResult.h \ + Referral.h \ + URI.h \ + Controls.h \ + Control.h \ + BindRequest.h \ + AuthenticationChoice.h \ + SaslCredentials.h \ + BindResponse.h \ + UnbindRequest.h \ + SearchRequest.h \ + AttributeSelection.h \ + Filter.h \ + SubstringFilter.h \ + MatchingRuleAssertion.h \ + SearchResultEntry.h \ + PartialAttributeList.h \ + SearchResultReference.h \ + SearchResultDone.h \ + ModifyRequest.h \ + ModifyResponse.h \ + AddRequest.h \ + AttributeList.h \ + AddResponse.h \ + DelRequest.h \ + DelResponse.h \ + ModifyDNRequest.h \ + ModifyDNResponse.h \ + CompareRequest.h \ + CompareResponse.h \ + AbandonRequest.h \ + ExtendedRequest.h \ + ExtendedResponse.h \ + IntermediateResponse.h + +ASN_MODULE_HEADERS+=UTF8String.h +ASN_MODULE_HEADERS+=BOOLEAN.h +ASN_MODULE_SOURCES+=BOOLEAN.c +ASN_MODULE_HEADERS+=ENUMERATED.h +ASN_MODULE_SOURCES+=ENUMERATED.c +ASN_MODULE_HEADERS+=INTEGER.h +ASN_MODULE_HEADERS+=NativeEnumerated.h +ASN_MODULE_SOURCES+=INTEGER.c +ASN_MODULE_HEADERS+=NULL.h +ASN_MODULE_SOURCES+=NULL.c +ASN_MODULE_SOURCES+=NativeEnumerated.c +ASN_MODULE_HEADERS+=NativeInteger.h +ASN_MODULE_SOURCES+=NativeInteger.c +ASN_MODULE_SOURCES+=UTF8String.c +ASN_MODULE_HEADERS+=asn_SEQUENCE_OF.h +ASN_MODULE_SOURCES+=asn_SEQUENCE_OF.c +ASN_MODULE_HEADERS+=asn_SET_OF.h +ASN_MODULE_SOURCES+=asn_SET_OF.c +ASN_MODULE_HEADERS+=constr_CHOICE.h +ASN_MODULE_SOURCES+=constr_CHOICE.c +ASN_MODULE_HEADERS+=constr_SEQUENCE.h +ASN_MODULE_SOURCES+=constr_SEQUENCE.c +ASN_MODULE_HEADERS+=constr_SEQUENCE_OF.h +ASN_MODULE_SOURCES+=constr_SEQUENCE_OF.c +ASN_MODULE_HEADERS+=constr_SET_OF.h +ASN_MODULE_SOURCES+=constr_SET_OF.c +ASN_MODULE_HEADERS+=asn_application.h +ASN_MODULE_HEADERS+=asn_system.h +ASN_MODULE_HEADERS+=asn_codecs.h +ASN_MODULE_HEADERS+=asn_internal.h +ASN_MODULE_HEADERS+=OCTET_STRING.h +ASN_MODULE_SOURCES+=OCTET_STRING.c +ASN_MODULE_HEADERS+=BIT_STRING.h +ASN_MODULE_SOURCES+=BIT_STRING.c +ASN_MODULE_SOURCES+=asn_codecs_prim.c +ASN_MODULE_HEADERS+=asn_codecs_prim.h +ASN_MODULE_HEADERS+=ber_tlv_length.h +ASN_MODULE_SOURCES+=ber_tlv_length.c +ASN_MODULE_HEADERS+=ber_tlv_tag.h +ASN_MODULE_SOURCES+=ber_tlv_tag.c +ASN_MODULE_HEADERS+=ber_decoder.h +ASN_MODULE_SOURCES+=ber_decoder.c +ASN_MODULE_HEADERS+=der_encoder.h +ASN_MODULE_SOURCES+=der_encoder.c +ASN_MODULE_HEADERS+=constr_TYPE.h +ASN_MODULE_SOURCES+=constr_TYPE.c +ASN_MODULE_HEADERS+=constraints.h +ASN_MODULE_SOURCES+=constraints.c +ASN_MODULE_HEADERS+=xer_support.h +ASN_MODULE_SOURCES+=xer_support.c +ASN_MODULE_HEADERS+=xer_decoder.h +ASN_MODULE_SOURCES+=xer_decoder.c +ASN_MODULE_HEADERS+=xer_encoder.h +ASN_MODULE_SOURCES+=xer_encoder.c +ASN_MODULE_HEADERS+=per_support.h +ASN_MODULE_SOURCES+=per_support.c +ASN_MODULE_HEADERS+=per_decoder.h +ASN_MODULE_SOURCES+=per_decoder.c +ASN_MODULE_HEADERS+=per_encoder.h +ASN_MODULE_SOURCES+=per_encoder.c +ASN_MODULE_HEADERS+=per_opentype.h +ASN_MODULE_SOURCES+=per_opentype.c +ASN_CONVERTER_SOURCES+=ldap-server.c + + +lib_LTLIBRARIES=libsomething.la +libsomething_la_SOURCES=$(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS) + +# This file may be used as an input for make(3) +# Remove the lines below to convert it into a pure .am file +TARGET = ldap-server +CFLAGS += -I. -g +OBJS=${ASN_MODULE_SOURCES:.c=.o} ${ASN_CONVERTER_SOURCES:.c=.o} + +all: $(TARGET) + +$(TARGET): ${OBJS} + $(CC) $(CFLAGS) -o $(TARGET) ${OBJS} $(LDFLAGS) $(LIBS) + +.SUFFIXES: +.SUFFIXES: .c .o + +.c.o: + $(CC) $(CFLAGS) -o $@ -c $< + +clean: + rm -f $(TARGET) + rm -f $(OBJS) + +regen: regenerate-from-asn1-source + +regenerate-from-asn1-source: + asn1c -fcompound-names -fskeletons-copy Lightweight-Directory-Access-Protocol-V3.asn1 + diff --git a/avatar.jpg b/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..507cf9fe3583dd7138e6d092818eae0e67404f78 GIT binary patch literal 2928 zcmbW#c{J4h9tZH>Zw5ogGK8_0C>ixw##qJ}Q;aS9mbGljz6=t{7TK~rmPnF4LfNv_ zLu3%Lg^+!h(AXcDtLM4r-gE9>_ulvSd_VtuKj(Wsuk-yoEgE-j$ma)oa5%@;1?4SM_m*V6}^nUB6nF5FC{9fpre3S zQPb4Yyd0l=_GoCcmumTVe3Wd->X=!O_PP&6m&H)+(E!$a10v)@) z4NS=Ev{Y!)bNX{vUbk=<^lu7F+j@sFoZ{p{a`T9szaV;13@w9^m6KPvs-j9%Q`gWm zG%_|Zy>4c1XYX*!@wSsQ$;a34j{n_&@COl*52K=El7CN0O-p~Ak(ry9Ur<<7{Gz0? zs=B83O!kh-`wti5#08A^<$#7{eCip@ZQZH8UrK95J&5 z>!d!ln?W_Y7)36+c=f7VW^M0QsBCejLoBabTC^j^=Fi#HjZV!Ne;0Rfyo6|0bvxj5 zYo5Pv1h#x-v_M6hl}$Psfe z3Oy4~((iepe6ila6*9Ki#`DQC=kIz-7@MZyUT0Cvq;hGQcpVGX3X}$B{crr_-+jHk z8eB1>%+HZ1rTupOt2Y(!R?>`b4L$h$)vWwGdgp49xJg!cm~<8u!1q?(Y)b3VeS-Zc z9VbqRLLS;B^p;_sqss|N1xcnrPFK6abU^l(W!y3pGl~4R!R6Dv$xbQ3h^X!e?5w@x zOVIg@u1^0pJfZ@qOlm~Y#hlt|cV_wPk@T`P3aVEI1pt=!5qu3H!ozmvB~10C_mCJGI78;}&FEow0b*Bw7k$Edw?53s^@29R=gH5su zw8a_qUm`p#Jqdd+sX(*8s9YO3Img&qdhZ48AT^uf}L#aoQnG@7ArEo*8s z+>M%;pWHpKiVYS}FwNN~>2D5+ZPIvC>M!8=r-;Ld%;egQ2Hvp7 zn@QoX>rg}t@c>_9dbvM6wULfi?u_0_RPgQiG-Dv_#?ykUc0Z^iCL+3~x0Ny!7pvT! zUkw>l>6r4DY{!@BdOFq-Be4tq1YWzz(~|3C(uT627BrDra$VJ1iEk@^_TsgG*urRnDN#n#f zCkNQ~(Pm7L86{|vmZc9(Q~Z0U^oH-*IM@hjJJGI;c8CbdL(>_@LllM!6G*cx9G0Es zmd>&~*2&0Nt?NjXCb&xGmy*X@+E&S|jqfX}6}qs4e3(j)G>qKzwERjZ`QA^t9Oi`P zN$%qhwGCkgm2j5F%tgZUf6hTSOZOW147%-+OkoOM7HR8jsU0^E%+G~=;@XF$TrWYZ^8i&C63 z>WKzMtBF1fjMu&YwHV54++XgKuF`m5mXe(n1a6ppCK(TH_-a+j9IZ>o(|JM?lwpt; z@$XWA=TS)Hkuuu!s@rq3PROfzO2QU$&JQ@W_o4!8xgoe&4V5WJF;cWn@J8B8U4Av0 zPvMtc-8^qKWFomP6s{PN%qBVO-!%@KprvpPVFOtUTyZRIRN#@X?ACa5q1KDAyvhig zPzqBU={P_ShA+Pn{2rV0!Kr8rH%KgXbAjI#=^gAOc5Iw7Xzk&AZr;qsGO$b*K3{msm6W z+^Y1V2UNg@JSn*GoBk?G8Q?Rw;;@ub4M!= zKe8tMu~FFh)1~wH;%#&5i1P7A!onJg*h%0+Evxz`9JswJv+m;J$eY%_cma=1JHGW= z(WPkLnWFwF${gimSS#PcD8&AAaB8Io@LxtBq><|wX{pxq zK!i)!?|clfy8$)t^vGA=5=7iDG3h`LmL={~yowoFy(V7LVRNVJ+)^so0Kxi@ zulY#qKhgLB(RQVgB2y0BHT2%akQ3#XyOr@>OS%hvcx5!U0Vp{Fmp__N`2U% zIC%mE#7V~qNGb~$`y%6A+v$nCuROih54Nl-9yAf`obt;GOAvM@9zsNJI2|)Cs>kcj zd~9qK +#include +#include +#include +#include +#include +#include +#include +#include "LDAPMessage.h" + +static LDAPMessage_t *receive_ldap_message(); +static LDAPMessage_t *bind_response_ok(int messageId, LDAPDN_t *dn); +static LDAPMessage_t *search_result_entry(int messageId, char *name, char *email, char *jpegFilename); +static LDAPMessage_t *search_result_done(int messageId, LDAPDN_t *dn); +static void send_ldap_message(int fd, LDAPMessage_t *msg); +static int accept_single_connection(int port); + +int main() { + LDAPMessage_t *req_bind, *req_search, *req_unbind; + LDAPMessage_t *rsp_bind, *rsp_search1, *rsp_search2, *rsp_search_done; + + int sock = accept_single_connection(3389); + + fprintf(stderr, "Receiving LDAP message...\n"); + req_bind = receive_ldap_message(sock); + assert(req_bind); + assert(req_bind->protocolOp.present == LDAPMessage__protocolOp_PR_bindRequest); + assert(req_bind->protocolOp.choice.bindRequest.version == 3); + fprintf(stderr, "Received BindRequest...\n"); + asn_fprint(stderr, &asn_DEF_LDAPMessage, req_bind); + + fprintf(stderr, "Sending BindReply...\n"); + rsp_bind = bind_response_ok(req_bind->messageID, &req_bind->protocolOp.choice.bindRequest.name); + asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_bind); + send_ldap_message(sock, rsp_bind); + + req_search = receive_ldap_message(sock); + assert(req_search->protocolOp.present == LDAPMessage__protocolOp_PR_searchRequest); + fprintf(stderr, "Received SearchRequest...\n"); + xer_fprint(stderr, &asn_DEF_LDAPMessage, req_search); + + rsp_search1 = search_result_entry(req_search->messageID, "Lev Walkin", "vlm@fprog.ru", "avatar.jpg"); + asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_search1); + send_ldap_message(sock, rsp_search1); + + rsp_search2 = search_result_entry(req_search->messageID, "Olga Bobrova", "oley@fprog.ru", NULL); + asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_search2); + send_ldap_message(sock, rsp_search2); + + rsp_search_done = search_result_done(req_search->messageID, &req_search->protocolOp.choice.searchRequest.baseObject); + asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_search_done); + send_ldap_message(sock, rsp_search_done); + + req_unbind = receive_ldap_message(sock); + assert(req_unbind->protocolOp.present == LDAPMessage__protocolOp_PR_unbindRequest); + xer_fprint(stderr, &asn_DEF_LDAPMessage, req_unbind); + + ASN_STRUCT_FREE(asn_DEF_LDAPMessage, req_bind); + ASN_STRUCT_FREE(asn_DEF_LDAPMessage, req_search); + ASN_STRUCT_FREE(asn_DEF_LDAPMessage, req_unbind); + ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_bind); + ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_search1); + ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_search2); + ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_search_done); + + return 0; +} + +static int accept_single_connection(int port) { + struct sockaddr_in sin; + int err; + int lsock, sock; + int opt_true = ~0; + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(3389); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + lsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + setsockopt(lsock, SOL_SOCKET, SO_REUSEPORT, &opt_true, sizeof(opt_true)); + err = bind(lsock, (struct sockaddr *)&sin, sizeof sin); + assert(err == 0); + err = listen(lsock, 1); + assert(err == 0); + + sock = accept(lsock, 0, 0); + assert(sock > 0); + close(lsock); + + return sock; +} + +static LDAPMessage_t *bind_response_ok(int messageId, LDAPDN_t *dn) { + LDAPMessage_t *msg = calloc(1, sizeof *msg); + BindResponse_t *resp; + + msg->messageID = messageId; + msg->protocolOp.present = LDAPMessage__protocolOp_PR_bindResponse; + resp = &msg->protocolOp.choice.bindResponse; + asn_long2INTEGER(&resp->resultCode, BindResponse__resultCode_success); + OCTET_STRING_fromBuf(&resp->matchedDN, dn->buf, dn->size); + OCTET_STRING_fromString(&resp->diagnosticMessage, "OK"); + + return msg; +} + +static PartialAttribute_t *make_partial_attribute(char *key, char *value) { + PartialAttribute_t *pa = calloc(1, sizeof *pa); + + OCTET_STRING_fromString(&pa->type, key); + ASN_SEQUENCE_ADD(&pa->vals, + OCTET_STRING_new_fromBuf(&asn_DEF_AttributeValue, value, -1)); + + return pa; +} + +static PartialAttribute_t *make_partial_attribute_from_file(char *key, char *filename) { + PartialAttribute_t *pa = calloc(1, sizeof *pa); + char buffer[4096]; + size_t buflen; + + FILE *f = fopen(filename, "rb"); + assert(f); + buflen = fread(buffer, 1, sizeof buffer, f); + fclose(f); + + OCTET_STRING_fromString(&pa->type, key); + ASN_SEQUENCE_ADD(&pa->vals, + OCTET_STRING_new_fromBuf(&asn_DEF_AttributeValue, buffer, buflen)); + + return pa; +} + +static LDAPMessage_t *search_result_entry(int messageId, char *name, char *email, char *jpegFilename) { + LDAPMessage_t *msg = calloc(1, sizeof *msg); + SearchResultEntry_t *entry; + + msg->messageID = messageId; + msg->protocolOp.present = LDAPMessage__protocolOp_PR_searchResEntry; + entry = &msg->protocolOp.choice.searchResEntry; + OCTET_STRING_fromString(&entry->objectName, name); + + ASN_SEQUENCE_ADD(&entry->attributes, make_partial_attribute("cn", name)); + ASN_SEQUENCE_ADD(&entry->attributes, make_partial_attribute("mail", email)); + if(jpegFilename) + ASN_SEQUENCE_ADD(&entry->attributes, + make_partial_attribute_from_file("jpegPhoto", jpegFilename)); + + return msg; +} + +static LDAPMessage_t *search_result_done(int messageId, LDAPDN_t *dn) { + LDAPMessage_t *msg = calloc(1, sizeof *msg); + SearchResultDone_t *done; + + msg->messageID = messageId; + msg->protocolOp.present = LDAPMessage__protocolOp_PR_searchResDone; + done = &msg->protocolOp.choice.searchResDone; + asn_long2INTEGER(&done->resultCode, LDAPResult__resultCode_success); + OCTET_STRING_fromBuf(&done->matchedDN, dn->buf, dn->size); + OCTET_STRING_fromString(&done->diagnosticMessage, "OK"); + return msg; +} + +static int output_cb(const void *buffer, size_t size, void *key) { + return write(*(int *)key, buffer, size); +} + +static void send_ldap_message(int fd, LDAPMessage_t *msg) { + der_encode(&asn_DEF_LDAPMessage, msg, output_cb, &fd); +} + +static LDAPMessage_t *receive_ldap_message(int fd) { + char buffer[8192]; + ssize_t buffer_len = 0; + LDAPMessage_t *msg = 0; + asn_dec_rval_t rv; + + buffer_len = read(fd, buffer, sizeof(buffer)); + if(buffer_len <= 0) + return NULL; + + rv = ber_decode(0, &asn_DEF_LDAPMessage, (void **)&msg, buffer, buffer_len); + if(rv.code != RC_OK) + return NULL; + + assert(rv.consumed == buffer_len); + + return msg; +}