Internet DRAFT - draft-hollstein-embedded-ldif-c

draft-hollstein-embedded-ldif-c



Independent Submission                               Christian Hollstein
INTERNET-DRAFT                                                TeraCortex
Intended Status: Proposed Standard                         November 2013
Expires 2014/05/26
draft-hollstein-embedded-ldif-c-01.txt


   The Embedded LDAP Data Interchange Format for C (EMLDIF-C)


Status of This Memo

   This document is not an Internet Standards Track specification.
   It is published for examination, experimental implementation, and
   evaluation. Distribution of this memo is unlimited.



Abstract

   EMLDIF specifies how LDAP operations can be encoded in EXLDIF and
   embedded in high level programming languages. EMLDIF is is the
   common basis for language - dependant specifications. This document
   specifies Embedded LDIF for the programming language C. In order to
   make EMLDIF-C source files interoperable across vendor specific
   implementations the specification goes into detail about data
   structures and API.



Copyright Notice

   Copyright (c) 2013 IETF Trust and the persons identified as the
   document authors. All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents
   (http://trustee.ietf.org/license-info) in effect on the date of
   publication of this document. Please review these documents
   carefully, as they describe your rights and restrictions with
   respect to this document.

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF). Note that other groups may also distribute
   working documents as Internet-Drafts. The list of current
   Internet-Drafts is at http://datatracker.ietf.org/drafts/current.

   Internet-Drafts are draft documents valid for a maximum of six
   months and may be updated, replaced, or obsoleted by other
   documents at any time. It is inappropriate to use Internet-
   Drafts as reference material or to cite them other than as
   "work in progress."

Hollstein                                                       [Page 1]

                   Embedded LDIF for C (EMLDIF-C)          November 2013

Table of Contents

   1.  Overview .......................................................3
   1.1.  Conventions and Terminology ..................................3
   2.  The ELDC File ..................................................4
   2.1.  General Layout ...............................................4
   2.2.  Header File Inclusion ........................................4
   2.3.  Exported Functions ...........................................5
   2.4.  Internal Functions ...........................................6
   2.5.  Result Structures ............................................7
   2.6.  Result Handling API  .........................................8
   3.  Examples .......................................................8
   3.1.  Basic Operations .............................................9
   3.2.  Transactions ................................................10
   3.3.  Source Code Parametrisation with Static Value Replacement ...12
   3.4.  Mass Data Creation with Dynamic Value Replacement ...........13
   3.5.  Search Result Handling ......................................15
   3.6.  Asynchronous Mode ...........................................16
   4.  Security Considerations .......................................18
   5.  IANA Considerations ...........................................18
   6.  Acknowledgments ...............................................18
   7.  References ....................................................18
   7.1.  Normative References ........................................18
   7.2.  Informative References ......................................19






























Hollstein                                                       [Page 2]

                   Embedded LDIF for C (EMLDIF-C)          November 2013



1.  Overview

   This document specfies how EXLDIF can be embedded and used in the
   high level programming language C. Based on [EMLDIF] this handles
   the following issues:

   - Use of static functions

   - Export of global functions for dynamic attachment

   - Multi Threading

   - Application Programmer Interface (API)

   - Result Handling

   - Examples


   The chapters 2 through 5 give a formal specification of the language
   elements.



1.1.  Conventions and Terminology

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
   document are to be interpreted as described in [RFC2119].


1.2. Implementation Types

   As specified in [EMLDIF] there are two types of implementations:

   Type I uses generates shared libraries from EMLDIF-C source files and
   uses dynamic linking to attach them to the running process.

   Type II generates executable binaries from EMLDIF-C source files and
   executes them on the fly or leaves them for later execution.

   Any implemantation SHOULD be able to handle more than one EMLDIF-C
   source file upon each invocation. 









Hollstein                                                       [Page 3]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


2.  The EMLDIF-C File

2.1.  General Layout

   An EMLDIF-C file is a text file with source code of the programming
   language "C". In this file EXLDIF records MAY appear inside of
   blocks.  A block is opened with "{" and closed with "}". EXLDIF
   records MUST NOT appear outside of blocks.


2.2.  Header File Inclusion

   Each EMLDIF-C file must contain the following inclusion statement
   near the top of the file:

   <CODE BEGINS>
   #include <eldc_exec.h>

   The content of this file is specified as follows:


   #define ELDC_EXPORT(fname, farg)  void *fname(void *farg)
   #define ELDC_FUNCTION(fname)      fname
   #define ELDC_INSTANCE(iname)      int iname = 0;
   #define ELDC_ARGUMENT(farg)       void *farg
   
   
   typedef struct EldcAva    {          /* Attribute - Value assertions
                                           "value" is a null terminated
                                           list of character pointers.
                                           It is NULL, if there is only
                                           an attribute name
                                        */
     char                 *aname;       /* Attribute name             */
     char                 **value;      /* List of NULL terminated
                                           value(s)
                                        */
   } EldcAva;
   
   
   typedef struct EldcObject {          /* Describes a searched object
                                           "ava" is a null terminaed
                                           list of EldcAva pointers
                                        */
     char                 *dn;          /* Distinguished name         */
     EldcAva              **ava;        /* List of AVAs               */
   } EldcObject;






Hollstein                                                       [Page 4]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


   typedef struct EldcResult {          /* Describes an operation result
                                           "object" is a null terminated
                                           list of EldcObject pointers
                                        */
     unsigned long long   sent;         /* Bytes sent by client       */
     unsigned long long   recd;         /* Bytes received by client   */
     unsigned int         operations;   /* Number of operations       */
     unsigned int         errcnt;       /* Number of errors           */
     unsigned int         entries;      /* Number of received search
                                           entries
                                        */
   
     int                  rcode;        /* Response code received from
                                           server
                                        */
     int                  rescnt;       /* Number of results in array */
     int                  msgid;        /* Server message ID          */
     int                  restype;      /* Result message type        */
     char                 *rmessage;    /* NULL terminated server result
                                           message
                                        */
     EldcObject           **object;     /* List of searched objects   */
   } EldcResult;
   
   
   typedef struct EldcThread {          /* Describes the current thread
                                           executing the toplevel
                                           function
                                        */
     int                  fileno;       /* Input file number 0 ... N  */
     int                  threadno;     /* Thread number 0 ... N      */
     unsigned int         *random;      /* Global random array   */
     int                  randcnt;      /* Number of values in random */
     int                  randsd;       /* File descriptor random file*/

   } EldcThread;
   
   
   int eldc_result_free(EldcResult ***result);
   <CODE ENDS>



2.3.  Exported Functions

  This chapter is only relevant for type I implementations.

  A collection of EMLDIF-C source code files MUST contain at least one
  exported function. "Exported" means: It is recognized by the parser,
  added to a "jump table" and is explicitely looked up in the jump
  table when the generated library is attached to the running process.
  During exection the function will be called from the executive binary
  as entry point of Embedded LDIF operations. Exported functions MUST
  be defined as follows:



Hollstein                                                       [Page 5]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


   eldc-export = FILL "ELDC_EXPORT" FILL "(" FILL
                 export-name
                 FILL ","
                 eldc-thread
                 FILL ")" FILL


   export-name = 1*( ALPHA / DIGIT / "-" / "_" )

                 This is the function name by which the exported
                 function will be looked up during dynamic linking.


   eldc-thread = 1*( ALPHA / DIGIT / "-" / "_" )

                 This is a variable name. The variable gives access
                 to the data structures representing the Embedded
                 LDIF records.


   Exported functions are of type "void *", thus must return a pointer.


2.4.  Internal Functions

   EMLDIF-C MAY contain arbitrary definitions of C functions. They MAY
   be local (defined static) to the respective source code file or
   global because they are called from within other source files. In
   any case they are not exported in the sense of chapter 2.3.

   If a function contains Embedded LDIF records the function header
   MUST be defined as follows:


   eldc-function = data-type 1*SPACE "ELDC_FUNCTION"
                                     FILL "(" FILL
                                     function-name
                                     FILL ")" FILL "(" FILL
                                     "ELDC_ARGUMENT"
                                     FILL "(" FILL
                                     eldc-thread
                                     FILL ")" FILL
                                     *parameter-list FILL ")"










Hollstein                                                       [Page 6]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


   These properties are at the choice of the programmer:

   data-type        The data type the function shall return

   function-name    The name by which the function will be called

   eldc-thread   =  1*( ALPHA / DIGIT / "-" / "_" )

                    This is a variable name. The variable gives access
                    to the data structures representing the Embedded
                    LDIF records.

   parameter-list   List of function parameters according to the syntax
                    of C function parameters. If present it MUST begin
                    with a comma ",".



2.5.  Result Structures

   Results of LDAP operations are returned as NULL terminated array
   of pointers to structures of type EldcResult. Each such structure
   contains:

   - A result code

   - A message ID

   - A result message type

   - An optional NULL terminated result message if received from the
     server

   - An optional NULL terminated array list of pointers to structures
     of type EldcObject if returned from a SEARCH operation.


   Implementations MAY add other fields to this structure, for
   example statistics related ones like:

   - The number of bytes sent and received so far

   - The number of executed operations

   - The number of errors

   - The number of received entries from search requests






Hollstein                                                       [Page 7]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


   If the array of objects is present each object contains:

   - A NULL terminated distinguished name. The distinguished name
     MAY have zero length if the SEARCH operation targeted the
     LDAP server top level object.

   - A NULL terminated array of pointers to structures of type EldcAva.


   Each EldcAva element contains:

   - A NULL terminated attribute name

   - An optional NULL terminated array of pointers to "char *". Each
     element of this array points to NULL terminated value string.



2.6.  Result Handling API

   Results are delivered in lists of EldcResults. They are allocated
   in heap memory. The programmer of the EMLDIF-C source file is
   responsible to free the used memory using an API call. The API
   function is declared here:

   int eldc_result_free(EldcResult ***result);

   The parameter has the following meaning:

   - result   This is the name of a variable that was defined with
              in the EMLDIF-C source file using the RESULT directive
              (see chapter 4.3 of [EMLDIF].



3.  Examples

   The examples below assume a LDAP server running on the localhost
   at port 389. The bind DN is:

   cn=Manager,dc=my-domain,dc=com

   The password is:

   secret

   The following object exists:

   dc=my-domain,dc=com




Hollstein                                                       [Page 8]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


   All examples are self - cleaning. At the end they remove any
   objects created to leave the directory in the same state as
   before.


3.1.  Basic Operations

   Use ADD to create an object, MODIFY to replace a value, SEARCH the
   result, COMPARE the result with your expectation, RENAME the object
   and DELETE the renamed object. The example shows also the handling
   of comments in the MODIFY record and indentation in the ADD record.


   <CODE BEGINS>
   #include <eldc_exec.h>

   ELDC_EXPORT(test_01, ct)
   {

     /* Connect to the server
     */
     dn:
     changetype: connect
     connection: ldap://localhost:389

     /* Authenticate
     */
     dn: cn=Manager,dc=my-domain,dc=com
     changetype: bind connectionId(test_01.eldc:0:test_01:0:0:0)
     passwd: secret

     /* Add an object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: add
     objectClass: inetOrgPerson
     commonName: 0000
     sn: Valcourt-Zywiel
     mail: N.Valcourt.Zywiel@test.co.uk
     userPassword: some
      thing


     /* Modify the object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: modify
     replace: mail
     mail: myaddress@my-domain.com
     #-
     #replace: userPassword
      userPassword: otherthing

Hollstein                                                       [Page 9]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     /* Search for results
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: search
     scope: base
     deref: never
     sizelimit: 0
     timelimit: 0
     attrsonly: 0
     filter: (objectClass=*)

     /* Compare an attribute
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: compare
     mail: myaddress@my-domain.com

     /* Rename the entry
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: moddn
     newrdn: commonName=0001
     deleteoldrdn: true

     /* Delete the renamed entry
     */
     dn: commonName=0001,dc=my-domain,dc=com
     changetype: delete
 
     dn:
     changetype: unbind

     return NULL;
   }
   <CODE ENDS>



3.2.  Transactions

   The example below shows a LDAP transaction according to [RFC5805]:


   <CODE BEGINS>
   #include <eldc_exec.h>
   
   
   ELDC_EXPORT(test_02, ct)
   {
   



Hollstein                                                      [Page 10]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     /* Connect to the server
     */
     dn:
     changetype: connect
     connection: ldap://localhost:389
   
     /* Authenticate
     */
     dn: cn=Manager,dc=my-domain,dc=com
     changetype: bind connectionId(test_02.eldc:0:test_02:0:0:0)
     passwd: secret
   
     /* Start a transaction
     */
     dn:
     changetype: extended
     oid: 1.3.6.1.1.21.1
     value:
     responses: 1
   
     /* Add an object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     control: 1.3.6.1.1.21.2 true:transactionId
      (test_02.eldc::test_02:2:0:0)
     changetype: add
     objectClass: inetOrgPerson
     commonName: 0000
     sn: Valcourt-Zywiel
     mail: N.Valcourt.Zywiel@test.co.uk
   
     /* Modify the object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     control: 1.3.6.1.1.21.2 true:transactionId
      (test_02.eldc::test_02:2:0:0)
     changetype: modify
     replace: mail
     mail: myaddress@my-domain.com
   
     /* Rename the object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     control: 1.3.6.1.1.21.2 true:transactionId
      (test_02.eldc::test_02:2:0:0)
     changetype: moddn
     newrdn: commonName=0001
     deleteoldrdn: true
   




Hollstein                                                      [Page 11]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     /* Delete the renamed object
     */
     dn: commonName=0001,dc=my-domain,dc=com
     control: 1.3.6.1.1.21.2 true:transactionId
      (test_02.eldc::test_02:2:0:0)
     changetype: delete
   

     /* Stop the transaction
     */
     dn:
     control: 1.3.6.1.1.21.2 true:transactionId
      (test_02.eldc::test_02:2:0:0)
     changetype: extended
     oid: 1.3.6.1.1.21.3
     value: transactionId(test_02.eldc::test_02:2:0:0)
     responses: 1
   
     dn:
     changetype: unbind
   
     return NULL;
   }
   <CODE ENDS>


3.3.  Source Code Parametrisation with Static Value Replacement

   This example shows how source code can be parameterized by use of
   the following environment variables:

   LDAP_HOST   Target LDAP server host name

   LDAP_HOST   Target LDAP server port number

   LDAP_ADMIN  Target LDAP server bind DN

   The variables must have been set and exported on operating system
   level.


   <CODE BEGINS>
   #include <eldc_exec.h>

   ELDC_EXPORT(test_03, ct)
   {

     /* Connect to the server
     */
     dn:
     changetype: connect
     connection: ldap://$LDAP_HOST:$LDAP_PORT

Hollstein                                                      [Page 12]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     /* Authenticate
     */
     dn: $LDAP_ADMIN
     changetype: bind connectionId(test_03.eldc:0:test_03:0:0:0)
     passwd: secret


     /* Search an object
     */
     dn: dc=my-domain,dc=com
     changetype: search
     scope: base
     deref: never
     sizelimit: 0
     timelimit: 0
     attrsonly: 0
     filter: (objectClass=*)

     dn: 
     changetype: unbind

     return NULL;
   }
   <CODE ENDS>



3.4.  Mass Data Creation with Dynamic Value Replacement

   This example shows how values inside of EXLDIF records can be
   replaced with local variables of the embedding program. The code
   employs also the definition of internal functions and uses an
   environment variable to get the number of operations to execute.

   <CODE BEGINS>
   #include <eldc_exec.h>

   static int ELDC_FUNCTION(test_04a)(ELDC_ARGUMENT(ct), int cnt)
   {
     int i;

     /* The loop below adds the objects

     commonName=0000,dc=my-domain,dc=com
     commonName=0001,dc=my-domain,dc=com
     commonName=0002,dc=my-domain,dc=com
     ...
     */





Hollstein                                                      [Page 13]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     for ( i = 0; i < cnt; i++ ) {

       /* Add an object
       */
       dn: commonName=%04d:i%,dc=my-domain,dc=com
       changetype: add connectionId(test_04.eldc:0:test_04:0:0:0)
       objectClass: inetOrgPerson
       sn: Valcourt-Zywiel
       mail: N.Valcourt.Zywiel@test.co.uk

     }

     return 0;
   }


   static int ELDC_FUNCTION(test_04b)(ELDC_ARGUMENT(ct), int cnt)
   {
     int i;

     /* The loop below deletes the objects

     commonName=0000,dc=my-domain,dc=com
     commonName=0001,dc=my-domain,dc=com
     commonName=0002,dc=my-domain,dc=com
     ...
     */
     for ( i = 0; i < cnt; i++ ) {

       /* Delete an object
       */
       dn: commonName=%04d:i%,dc=my-domain,dc=com
       changetype: delete connectionId(test_04.eldc:0:test_04:0:0:0)

     }

     return 0;
   }


   ELDC_EXPORT(test_04, ct)
   {
     int cnt;


     /* Connect to the server
     */
     dn:
     changetype: connect
     connection: ldap://localhost:389



Hollstein                                                      [Page 14]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     /* Authenticate
     */
     dn: cn=Manager,dc=my-domain,dc=com
     changetype: bind connectionId(test_04.eldc:0:test_04:0:0:0)
     passwd: secret

     /* Get the number of operations to execute
     */
     cnt = $OPCNT;

     test_04a(ct, cnt);
     test_04b(ct, cnt);

     dn:
     changetype: unbind

     return NULL;
   }
   <CODE ENDS>



3.5.  Search Result Handling


   <CODE BEGINS>
   #include <eldc_exec.h>

   ELDC_EXPORT(test_06, ct)
   {
     /* Connect to the server
     */
     dn:
     changetype: connect
     connection: ldap://localhost:389

     /* Authenticate
     */
     dn: cn=Manager,dc=my-domain,dc=com
     changetype: bind connectionId(test_06.eldc:0:test_06:0:0:0)
     passwd: secret


     /* Add an object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: add
     objectClass: inetOrgPerson
     commonName: 0000
     sn: Valcourt-Zywiel
     mail: N.Valcourt.Zywiel@test.co.uk


Hollstein                                                      [Page 15]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     /* Search the sub tree. Store results in the variable
        "myresult"
     */
     dn: dc=my-domain,dc=com
     changetype: search result(myresult:3:0)
     scope: sub
     deref: find
     sizelimit: 0
     timelimit: 0
     attrsonly: 0
     filter: (objectClass=*)

     /*
       Do something useful with the results
       ....
     */

     /* Free the memory allocated for the results
     */
     eldc_result_free(&myresult);

     return NULL;
   }
   <CODE ENDS>



3.6.  Asynchronous Mode


   <CODE BEGINS>
   #include <eldc_exec.h>

   ELDC_EXPORT(test_06, ct)
   {
     /* Connect to the server
     */
     dn:
     changetype: connect
     connection: ldap://localhost:389

     /* Authenticate
     */
     dn: cn=Manager,dc=my-domain,dc=com
     changetype: bind connectionId(test_06.eldc:0:test_06:0:0:0)
     passwd: secret







Hollstein                                                      [Page 16]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


     /* Add an object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: add
     objectClass: inetOrgPerson
     commonName: 0000
     sn: Valcourt-Zywiel
     mail: N.Valcourt.Zywiel@test.co.uk

     /* Search the sub tree. Send three requests in asynchronous
        mode.
     */
     dn: dc=my-domain,dc=com
     control: 1.3.6.1.4.1.30275.7.6 true:3
     changetype: search
     scope: sub
     deref: find
     sizelimit: 0
     timelimit: 0
     attrsonly: 0
     filter: (objectClass=*)

     /* Compare the added object
     */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: compare
     sn: Valcourt-Zywiel

     /* Abandon the search request */
     dn:
     changetype: abandon
     messageId: messageId(test_06.eldc::test_06:3:0:0)

     /* Expect just one response for the compare request.
        The search request is abandoned and the abandon
        request has no response
     */
     dn:
     changetype: response
     responses: 1

     /* Cleanup */
     dn: commonName=0000,dc=my-domain,dc=com
     changetype: delete

     dn:
     changetype: unbind

     return NULL;
   }
   <CODE ENDS>


Hollstein                                                      [Page 17]

                   Embedded LDIF for C (EMLDIF-C)          November 2013


4.  Security Considerations

   In addition to the security issues of LDIF files [RFC2849] Extended
   LDIF may contain authentication information used for BIND operations.
   This sensitive data MUST NOT be displayed to unauthorized people.

   In Embedded LDIF it is pretty easy to create a program firing
   millions of requests to a LDAP server in short time frame. Such
   denial of service attacks are illegal. Their prevention is not in
   scope of this specification.

   General security considerations [RFC4510], especially those
   associated with update operations [RFC4511], apply to this extension.



5. IANA Considerations

   There are no new object identifiers associated with this
   specification.



6.  Acknowledgments

   The author gratefully acknowledges the contributions made by
   Internet Engineering Task Force participants.


7.  References

7.1.  Normative References

   [RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
                 Requirement Levels", RFC 2119, March 1997.

   [RFC2849]     Good, G., "The LDAP Data Interchange Format (LDIF) -
                 Technical Specification", RFC 2849, June 2000.

   [RFC4510]     Zeilenga, K., Ed., "Lightweight Directory Access
                 Protocol (LDAP): Technical Specification Road Map", RFC
                 4510, June 2006.

   [RFC4511]     Sermersheim, J., Ed., "Lightweight Directory Access
                 Protocol (LDAP): The Protocol", RFC 4511, June 2006.








Hollstein                                                      [Page 18]

                   Embedded LDIF for C (EMLDIF-C)          November 2013



7.2.  Informative References

   [RFC5805]     Zeilenga, K., "Lightweight Directory Access Protocol
                 (LDAP) Transactions", RFC 5805, March 2010.

   [EMLDIF]      Hollstein, C., "The Embedded LDAP Data Interchange
                 Format (EMLDIF)",
                 draft-hollstein-embedded-ldif-01.txt, November 2013.




Author's Address

   Christian Hollstein
   TeraCortex

   EMail: eldif@teracortex.com