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