Copyright (C) Andrew Tridgell 2004
Copyright (C) Stefan Metzmacher 2004
- Copyright (C) Simo Sorce 2005
+ Copyright (C) Simo Sorce 2005-2006
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/*
#define _LDB_H_ 1
/*! \endcond */
+#include <stdbool.h>
+#include "talloc.h"
+#include "tevent.h"
+#include "ldb_errors.h"
+
/*
major restrictions as compared to normal LDAP:
- - no async calls.
- each record must have a unique key field
- the key must be representable as a NULL terminated C string and may not
contain a comma or braces
major restrictions as compared to tdb:
- - no explicit locking calls
- UPDATE: we have transactions now, better than locking --SSS.
+ - no explicit locking calls, but we have transactions when using ldb_tdb
*/
};
#endif
-/**
- internal ldb exploded dn structures
-*/
-struct ldb_dn_component {
- char *name;
- struct ldb_val value;
-};
+/*! \cond DOXYGEN_IGNORE */
+#ifndef PRINTF_ATTRIBUTE
+#define PRINTF_ATTRIBUTE(a,b)
+#endif
+/*! \endcond */
-struct ldb_dn {
- int comp_num;
- struct ldb_dn_component *components;
-};
+/* opaque ldb_dn structures, see ldb_dn.c for internals */
+struct ldb_dn_component;
+struct ldb_dn;
/**
There are a number of flags that are used with ldap_modify() in
struct ldb_dn *dn;
unsigned int num_elements;
struct ldb_message_element *elements;
- void *private_data; /* private to the backend */
};
enum ldb_changetype {
LDB_SCOPE_SUBTREE=2};
struct ldb_context;
-
-/*
- the fuction type for the callback used in traversing the database
-*/
-typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *);
-
+struct tevent_context;
/* debugging uses one of the following levels */
enum ldb_debug_level {LDB_DEBUG_FATAL, LDB_DEBUG_ERROR,
*/
struct ldb_debug_ops {
void (*debug)(void *context, enum ldb_debug_level level,
- const char *fmt, va_list ap);
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
void *context;
};
*/
struct ldb_utf8_fns {
void *context;
- char *(*casefold)(void *context, void *mem_ctx, const char *s);
+ char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n);
};
/**
*/
#define LDB_FLG_RECONNECT 4
-/*! \cond DOXYGEN_IGNORE */
-#ifndef PRINTF_ATTRIBUTE
-#define PRINTF_ATTRIBUTE(a,b)
-#endif
-/*! \endcond */
+/**
+ Flag to tell backends not to use mmap
+*/
+#define LDB_FLG_NOMMAP 8
/*
structures for ldb_parse_tree handling code
} u;
};
-struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s);
-char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree);
+struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s);
+char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree);
/**
Encode a binary blob
2254 (Section 4). This function also escapes any non-printable
characters.
- \param ctx the memory context to allocate the return string in.
+ \param mem_ctx the memory context to allocate the return string in.
\param val the (potentially) binary data to be encoded
\return the encoded data as a null terminated string
\sa <a href="http://www.ietf.org/rfc/rfc2252.txt">RFC 2252</a>.
*/
-char *ldb_binary_encode(void *ctx, struct ldb_val val);
+char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val);
/**
Encode a string
\sa <a href="http://www.ietf.org/rfc/rfc2252.txt">RFC 2252</a>.
*/
-char *ldb_binary_encode_string(void *mem_ctx, const char *string);
+char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string);
/*
functions for controlling attribute handling
*/
-typedef int (*ldb_attr_handler_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, struct ldb_val *);
-typedef int (*ldb_attr_comparison_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, const struct ldb_val *);
+typedef int (*ldb_attr_handler_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, struct ldb_val *);
+typedef int (*ldb_attr_comparison_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, const struct ldb_val *);
-struct ldb_attrib_handler {
- const char *attr;
+/*
+ attribute handler structure
- /* LDB_ATTR_FLAG_* */
- unsigned flags;
+ attr -> The attribute name
+ ldif_read_fn -> convert from ldif to binary format
+ ldif_write_fn -> convert from binary to ldif format
+ canonicalise_fn -> canonicalise a value, for use by indexing and dn construction
+ comparison_fn -> compare two values
+*/
- /* convert from ldif to binary format */
+struct ldb_schema_syntax {
+ const char *name;
ldb_attr_handler_t ldif_read_fn;
-
- /* convert from binary to ldif format */
ldb_attr_handler_t ldif_write_fn;
-
- /* canonicalise a value, for use by indexing and dn construction */
ldb_attr_handler_t canonicalise_fn;
-
- /* compare two values */
ldb_attr_comparison_t comparison_fn;
};
+struct ldb_schema_attribute {
+ const char *name;
+ unsigned flags;
+ const struct ldb_schema_syntax *syntax;
+};
+
+const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
+ const char *name);
+
+struct ldb_dn_extended_syntax {
+ const char *name;
+ ldb_attr_handler_t read_fn;
+ ldb_attr_handler_t write_clear_fn;
+ ldb_attr_handler_t write_hex_fn;
+};
+
+const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_context *ldb,
+ const char *name);
+
/**
The attribute is not returned by default
*/
#define LDB_ATTR_FLAG_HIDDEN (1<<0)
+/* the attribute handler name should be freed when released */
+#define LDB_ATTR_FLAG_ALLOCATED (1<<1)
+
/**
- The attribute is constructed from other attributes
+ The attribute is supplied by the application and should not be removed
*/
-#define LDB_ATTR_FLAG_CONSTRUCTED (1<<1)
+#define LDB_ATTR_FLAG_FIXED (1<<2)
/**
LDAP attribute syntax for a DN
*/
#define LDB_CONTROL_PAGED_RESULTS_OID "1.2.840.113556.1.4.319"
+/**
+ OID for specifying the returned elements of the ntSecurityDescriptor
+
+ \sa <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/ldap_server_sd_flags_oid.asp">Microsoft documentation of this OID</a>
+*/
+#define LDB_CONTROL_SD_FLAGS_OID "1.2.840.113556.1.4.801"
+
+/**
+ OID for specifying an advanced scope for the search (one partition)
+
+ \sa <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/ldap_server_domain_scope_oid.asp">Microsoft documentation of this OID</a>
+*/
+#define LDB_CONTROL_DOMAIN_SCOPE_OID "1.2.840.113556.1.4.1339"
+
+/**
+ OID for specifying an advanced scope for a search
+
+ \sa <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/ldap_server_search_options_oid.asp">Microsoft documentation of this OID</a>
+*/
+#define LDB_CONTROL_SEARCH_OPTIONS_OID "1.2.840.113556.1.4.1340"
+
/**
OID for notification
*/
#define LDB_CONTROL_NOTIFICATION_OID "1.2.840.113556.1.4.528"
+/**
+ OID for getting deleted objects
+
+ \sa <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/ldap_server_show_deleted_oid.asp">Microsoft documentation of this OID</a>
+*/
+#define LDB_CONTROL_SHOW_DELETED_OID "1.2.840.113556.1.4.417"
+
/**
OID for extended DN
*/
#define LDB_CONTROL_VLV_RESP_OID "2.16.840.1.113730.3.4.10"
+/**
+ OID to let modifies don't give an error when adding an existing
+ attribute with the same value or deleting an nonexisting one attribute
+
+ \sa <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/ldap_server_permissive_modify_oid.asp">Microsoft documentation of this OID</a>
+*/
+#define LDB_CONTROL_PERMISSIVE_MODIFY_OID "1.2.840.113556.1.4.1413"
+
+/**
+ OID for LDAP Extended Operation START_TLS.
+
+ This Extended operation is used to start a new TLS
+ channel on top of a clear text channel.
+*/
+#define LDB_EXTENDED_START_TLS_OID "1.3.6.1.4.1.1466.20037"
+
+/**
+*/
+#define LDB_EXTENDED_DYNAMIC_OID "1.3.6.1.4.1.1466.101.119.1"
+
+/**
+*/
+#define LDB_EXTENDED_FAST_BIND_OID "1.2.840.113556.1.4.1781"
+
+struct ldb_sd_flags_control {
+ /*
+ * request the owner 0x00000001
+ * request the group 0x00000002
+ * request the DACL 0x00000004
+ * request the SACL 0x00000008
+ */
+ unsigned secinfo_flags;
+};
+
+/*
+ * DOMAIN_SCOPE 0x00000001
+ * this limits the search to one partition,
+ * and no referrals will be returned.
+ * (Note this doesn't limit the entries by there
+ * objectSid belonging to a domain! Builtin and Foreign Sids
+ * are still returned)
+ *
+ * PHANTOM_ROOT 0x00000002
+ * this search on the whole tree on a domain controller
+ * over multiple partitions without referrals.
+ * (This is the default behavior on the Global Catalog Port)
+ */
+
+#define LDB_SEARCH_OPTION_DOMAIN_SCOPE 0x00000001
+#define LDB_SEARCH_OPTION_PHANTOM_ROOT 0x00000002
+
+struct ldb_search_options_control {
+ unsigned search_options;
+};
+
struct ldb_paged_control {
int size;
int cookie_len;
void *data;
};
-struct ldb_credentials;
-
enum ldb_request_type {
- LDB_REQ_SEARCH,
- LDB_REQ_ADD,
- LDB_REQ_MODIFY,
- LDB_REQ_DELETE,
- LDB_REQ_RENAME,
- LDB_ASYNC_SEARCH,
- LDB_ASYNC_ADD,
- LDB_ASYNC_MODIFY,
- LDB_ASYNC_DELETE,
- LDB_ASYNC_RENAME,
-
- LDB_REQ_REGISTER
+ LDB_SEARCH,
+ LDB_ADD,
+ LDB_MODIFY,
+ LDB_DELETE,
+ LDB_RENAME,
+ LDB_EXTENDED,
+ LDB_REQ_REGISTER_CONTROL,
+ LDB_REQ_REGISTER_PARTITION
};
enum ldb_reply_type {
LDB_REPLY_DONE
};
-enum ldb_async_wait_type {
+enum ldb_wait_type {
LDB_WAIT_ALL,
LDB_WAIT_NONE
};
-enum ldb_async_state {
+enum ldb_state {
LDB_ASYNC_INIT,
LDB_ASYNC_PENDING,
LDB_ASYNC_DONE
};
+struct ldb_extended {
+ const char *oid;
+ void *data; /* NULL or a valid talloc pointer! talloc_get_type() will be used on it */
+};
+
+#define LDB_EXTENDED_SEQUENCE_NUMBER "1.3.6.1.4.1.7165.4.4.3"
+
+enum ldb_sequence_type {
+ LDB_SEQ_HIGHEST_SEQ,
+ LDB_SEQ_HIGHEST_TIMESTAMP,
+ LDB_SEQ_NEXT
+};
+
+#define LDB_SEQ_GLOBAL_SEQUENCE 0x01
+#define LDB_SEQ_TIMESTAMP_SEQUENCE 0x02
+
+struct ldb_seqnum_request {
+ enum ldb_sequence_type type;
+};
+
+struct ldb_seqnum_result {
+ uint64_t seq_num;
+ uint32_t flags;
+};
+
struct ldb_result {
unsigned int count;
struct ldb_message **msgs;
- char **refs;
+ struct ldb_extended *extended;
struct ldb_control **controls;
+ char **refs;
};
-struct ldb_async_result {
+struct ldb_reply {
+ int error;
enum ldb_reply_type type;
struct ldb_message *message;
- char *referral;
+ struct ldb_extended *response;
struct ldb_control **controls;
+ char *referral;
};
-struct ldb_async_handle {
- int status;
- enum ldb_async_state state;
- void *private_data;
- struct ldb_module *module;
-};
+struct ldb_request;
+struct ldb_handle;
struct ldb_search {
- const struct ldb_dn *base;
+ struct ldb_dn *base;
enum ldb_scope scope;
- const struct ldb_parse_tree *tree;
+ struct ldb_parse_tree *tree;
const char * const *attrs;
struct ldb_result *res;
};
const struct ldb_message *message;
};
-struct ldb_modify {
+struct ldb_modify {
const struct ldb_message *message;
};
struct ldb_delete {
- const struct ldb_dn *dn;
+ struct ldb_dn *dn;
};
struct ldb_rename {
- const struct ldb_dn *olddn;
- const struct ldb_dn *newdn;
+ struct ldb_dn *olddn;
+ struct ldb_dn *newdn;
};
struct ldb_register_control {
const char *oid;
};
+struct ldb_register_partition {
+ struct ldb_dn *dn;
+};
+
+typedef int (*ldb_request_callback_t)(struct ldb_request *, struct ldb_reply *);
+
struct ldb_request {
enum ldb_request_type operation;
struct ldb_modify mod;
struct ldb_delete del;
struct ldb_rename rename;
- struct ldb_register_control reg;
+ struct ldb_extended extended;
+ struct ldb_register_control reg_control;
+ struct ldb_register_partition reg_partition;
} op;
struct ldb_control **controls;
- struct ldb_credentials *creds;
- struct {
- void *context;
- int (*callback)(struct ldb_context *, void *, struct ldb_async_result *);
+ void *context;
+ ldb_request_callback_t callback;
- int timeout;
- struct ldb_async_handle *handle;
- } async;
+ int timeout;
+ time_t starttime;
+ struct ldb_handle *handle;
};
int ldb_request(struct ldb_context *ldb, struct ldb_request *request);
+int ldb_request_done(struct ldb_request *req, int status);
+bool ldb_request_is_done(struct ldb_request *req);
-int ldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type);
+int ldb_modules_wait(struct ldb_handle *handle);
+int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type);
+
+int ldb_set_timeout(struct ldb_context *ldb, struct ldb_request *req, int timeout);
+int ldb_set_timeout_from_prev_req(struct ldb_context *ldb, struct ldb_request *oldreq, struct ldb_request *newreq);
+void ldb_set_create_perms(struct ldb_context *ldb, unsigned int perms);
+void ldb_set_modules_dir(struct ldb_context *ldb, const char *path);
+struct tevent_context;
+void ldb_set_event_context(struct ldb_context *ldb, struct tevent_context *ev);
+struct tevent_context * ldb_get_event_context(struct ldb_context *ldb);
/**
Initialise ldbs' global information
\return pointer to ldb_context that should be free'd (using talloc_free())
at the end of the program.
*/
-struct ldb_context *ldb_init(void *mem_ctx);
+struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx);
/**
Connect to a database.
(that is, with LDB_FLG_RDONLY). However in read-write mode, the database will be
created if it does not exist.
*/
+
+typedef void (*ldb_async_timeout_fn) (void *);
+typedef bool (*ldb_async_callback_fn) (void *);
+typedef int (*ldb_async_ctx_add_op_fn)(void *, time_t, void *, ldb_async_timeout_fn, ldb_async_callback_fn);
+typedef int (*ldb_async_ctx_wait_op_fn)(void *);
+
+void ldb_async_ctx_set_private_data(struct ldb_context *ldb,
+ void *private_data);
+void ldb_async_ctx_set_add_op(struct ldb_context *ldb,
+ ldb_async_ctx_add_op_fn add_op);
+void ldb_async_ctx_set_wait_op(struct ldb_context *ldb,
+ ldb_async_ctx_wait_op_fn wait_op);
+
int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]);
+/*
+ return an automatic basedn from the rootDomainNamingContext of the rootDSE
+ This value have been set in an opaque pointer at connection time
+*/
+struct ldb_dn *ldb_get_root_basedn(struct ldb_context *ldb);
+
+/*
+ return an automatic basedn from the configurationNamingContext of the rootDSE
+ This value have been set in an opaque pointer at connection time
+*/
+struct ldb_dn *ldb_get_config_basedn(struct ldb_context *ldb);
+
+/*
+ return an automatic basedn from the schemaNamingContext of the rootDSE
+ This value have been set in an opaque pointer at connection time
+*/
+struct ldb_dn *ldb_get_schema_basedn(struct ldb_context *ldb);
+
+/*
+ return an automatic baseDN from the defaultNamingContext of the rootDSE
+ This value have been set in an opaque pointer at connection time
+*/
+struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb);
+
+/**
+ The default async search callback function
+
+ \param req the request we are callback of
+ \param ares a single reply from the async core
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+
+ \note this function expects req->context to always be an struct ldb_result pointer
+ AND a talloc context, this function will steal on the context each message
+ from the ares reply passed on by the async core so that in the end all the
+ messages will be in the context (ldb_result) memory tree.
+ Freeing the passed context (ldb_result tree) will free all the resources
+ (the request need to be freed separately and the result doe not depend on the
+ request that can be freed as sson as the search request is finished)
+*/
+
+int ldb_search_default_callback(struct ldb_request *req, struct ldb_reply *ares);
+
+/**
+ The default async extended operation callback function
+
+ \param req the request we are callback of
+ \param ares a single reply from the async core
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares);
+
+
+/**
+ Helper function to build a search request
+
+ \param ret_req the request structure is returned here (talloced on mem_ctx)
+ \param ldb the context associated with the database (from ldb_init())
+ \param mem_ctx a talloc memory context (used as parent of ret_req)
+ \param base the Base Distinguished Name for the query (use ldb_dn_new() for an empty one)
+ \param scope the search scope for the query
+ \param expression the search expression to use for this query
+ \param attrs the search attributes for the query (pass NULL if none required)
+ \param controls an array of controls
+ \param context the callback function context
+ \param the callback function to handle the async replies
+ \param the parent request if any
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_search_req(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *base,
+ enum ldb_scope scope,
+ const char *expression,
+ const char * const *attrs,
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent);
+
+int ldb_build_search_req_ex(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *base,
+ enum ldb_scope scope,
+ struct ldb_parse_tree *tree,
+ const char * const *attrs,
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent);
+
+/**
+ Helper function to build an add request
+
+ \param ret_req the request structure is returned here (talloced on mem_ctx)
+ \param ldb the context associated with the database (from ldb_init())
+ \param mem_ctx a talloc memory context (used as parent of ret_req)
+ \param message contains the entry to be added
+ \param controls an array of controls
+ \param context the callback function context
+ \param the callback function to handle the async replies
+ \param the parent request if any
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_add_req(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ const struct ldb_message *message,
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent);
+
+/**
+ Helper function to build a modify request
+
+ \param ret_req the request structure is returned here (talloced on mem_ctx)
+ \param ldb the context associated with the database (from ldb_init())
+ \param mem_ctx a talloc memory context (used as parent of ret_req)
+ \param message contains the entry to be modified
+ \param controls an array of controls
+ \param context the callback function context
+ \param the callback function to handle the async replies
+ \param the parent request if any
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_mod_req(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ const struct ldb_message *message,
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent);
+
+/**
+ Helper function to build a delete request
+
+ \param ret_req the request structure is returned here (talloced on mem_ctx)
+ \param ldb the context associated with the database (from ldb_init())
+ \param mem_ctx a talloc memory context (used as parent of ret_req)
+ \param dn the DN to be deleted
+ \param controls an array of controls
+ \param context the callback function context
+ \param the callback function to handle the async replies
+ \param the parent request if any
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_del_req(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *dn,
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent);
+
+/**
+ Helper function to build a rename request
+
+ \param ret_req the request structure is returned here (talloced on mem_ctx)
+ \param ldb the context associated with the database (from ldb_init())
+ \param mem_ctx a talloc memory context (used as parent of ret_req)
+ \param olddn the old DN
+ \param newdn the new DN
+ \param controls an array of controls
+ \param context the callback function context
+ \param the callback function to handle the async replies
+ \param the parent request if any
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_rename_req(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *olddn,
+ struct ldb_dn *newdn,
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent);
+
+/**
+ Add a ldb_control to a ldb_request
+
+ \param req the request struct where to add the control
+ \param oid the object identifier of the control as string
+ \param critical whether the control should be critical or not
+ \param data a talloc pointer to the control specific data
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data);
+
+/**
+ check if a control with the specified "oid" exist and return it
+ \param req the request struct where to add the control
+ \param oid the object identifier of the control as string
+
+ \return the control, NULL if not found
+*/
+struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid);
+
+/**
+ check if a control with the specified "oid" exist and return it
+ \param rep the reply struct where to add the control
+ \param oid the object identifier of the control as string
+
+ \return the control, NULL if not found
+*/
+struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid);
+
/**
Search the database
records that match an LDAP-like search expression
\param ldb the context associated with the database (from ldb_init())
- \param base the Base Distinguished Name for the query (pass NULL for root DN)
+ \param mem_ctx the memory context to use for the request and the results
+ \param result the return result
+ \param base the Base Distinguished Name for the query (use ldb_dn_new() for an empty one)
\param scope the search scope for the query
- \param expression the search expression to use for this query
\param attrs the search attributes for the query (pass NULL if none required)
- \param res the return result
+ \param exp_fmt the search expression to use for this query (printf like)
\return result code (LDB_SUCCESS on success, or a failure code)
\note use talloc_free() to free the ldb_result returned
*/
-int ldb_search(struct ldb_context *ldb,
- const struct ldb_dn *base,
- enum ldb_scope scope,
- const char *expression,
- const char * const *attrs, struct ldb_result **res);
-
-/*
- like ldb_search() but takes a parse tree
-*/
-int ldb_search_bytree(struct ldb_context *ldb,
- const struct ldb_dn *base,
- enum ldb_scope scope,
- struct ldb_parse_tree *tree,
- const char * const *attrs, struct ldb_result **res);
+int ldb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ struct ldb_result **result, struct ldb_dn *base,
+ enum ldb_scope scope, const char * const *attrs,
+ const char *exp_fmt, ...) PRINTF_ATTRIBUTE(7,8);
/**
Add a record to the database.
\return result code (LDB_SUCCESS if the record was renamed as
requested, otherwise a failure code)
*/
-int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn);
+int ldb_rename(struct ldb_context *ldb, struct ldb_dn *olddn, struct ldb_dn *newdn);
/**
Delete a record from the database
\return result code (LDB_SUCCESS if the record was deleted,
otherwise a failure code)
*/
-int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn);
+int ldb_delete(struct ldb_context *ldb, struct ldb_dn *dn);
+
+/**
+ The default async extended operation callback function
+
+ \param req the request we are callback of
+ \param ares a single reply from the async core
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+
+ \note this function expects req->context to always be an struct ldb_result pointer
+ AND a talloc context, this function will steal on the context each message
+ from the ares reply passed on by the async core so that in the end all the
+ messages will be in the context (ldb_result) memory tree.
+ Freeing the passed context (ldb_result tree) will free all the resources
+ (the request need to be freed separately and the result doe not depend on the
+ request that can be freed as sson as the search request is finished)
+*/
+
+int ldb_extended_default_callback(struct ldb_request *req, struct ldb_reply *ares);
+
+
+/**
+ Helper function to build a extended request
+
+ \param ret_req the request structure is returned here (talloced on mem_ctx)
+ \param ldb the context associated with the database (from ldb_init())
+ \param mem_ctx a talloc memory context (used as parent of ret_req)
+ \param oid the OID of the extended operation.
+ \param data a void pointer a the extended operation specific parameters,
+ it needs to be NULL or a valid talloc pointer! talloc_get_type() will be used on it
+ \param controls an array of controls
+ \param context the callback function context
+ \param the callback function to handle the async replies
+ \param the parent request if any
+
+ \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+int ldb_build_extended_req(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ const char *oid,
+ void *data,/* NULL or a valid talloc pointer! talloc_get_type() will be used on it */
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent);
+
+/**
+ call an extended operation
+
+ This function deletes a record from the database.
+
+ \param ldb the context associated with the database (from ldb_init())
+ \param oid the OID of the extended operation.
+ \param data a void pointer a the extended operation specific parameters,
+ it needs to be NULL or a valid talloc pointer! talloc_get_type() will be used on it
+ \param res the result of the extended operation
+
+ \return result code (LDB_SUCCESS if the extended operation returned fine,
+ otherwise a failure code)
+*/
+int ldb_extended(struct ldb_context *ldb,
+ const char *oid,
+ void *data,/* NULL or a valid talloc pointer! talloc_get_type() will be used on it */
+ struct ldb_result **res);
+
+/**
+ Obtain current/next database sequence number
+*/
+int ldb_sequence_number(struct ldb_context *ldb, enum ldb_sequence_type type, uint64_t *seq_num);
/**
start a transaction
\note The default function is not yet UTF8 aware. Provide your own
set of functions through ldb_set_utf8_fns()
*/
-char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s);
+char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n);
/**
Check the attribute name is valid according to rfc2251
- \param s tthe string to check
+ \param s the string to check
\return 1 if the name is ok
*/
/*
ldif manipulation functions
*/
+
/**
Write an LDIF message
\sa ldb_ldif_read for the reader equivalent to this function.
*/
int ldb_ldif_write(struct ldb_context *ldb,
- int (*fprintf_fn)(void *, const char *, ...),
+ int (*fprintf_fn)(void *, const char *, ...) PRINTF_ATTRIBUTE(2,3),
void *private_data,
const struct ldb_ldif *ldif);
\note The caller is responsible for freeing the result
*/
-char *ldb_base64_encode(void *mem_ctx, const char *buf, int len);
+char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len);
/**
Base64 decode a buffer
*/
int ldb_base64_decode(char *s);
-int ldb_attrib_add_handlers(struct ldb_context *ldb,
- const struct ldb_attrib_handler *handlers,
- unsigned num_handlers);
-
/* The following definitions come from lib/ldb/common/ldb_dn.c */
-int ldb_dn_is_special(const struct ldb_dn *dn);
-int ldb_dn_check_special(const struct ldb_dn *dn, const char *check);
-char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value);
-struct ldb_dn *ldb_dn_new(void *mem_ctx);
-struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn);
-struct ldb_dn *ldb_dn_explode_or_special(void *mem_ctx, const char *dn);
-char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn);
-char *ldb_dn_linearize_casefold(struct ldb_context *ldb, const struct ldb_dn *edn);
-int ldb_dn_compare_base(struct ldb_context *ldb, const struct ldb_dn *base, const struct ldb_dn *dn);
-int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1);
-struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn);
-struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn);
-struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el);
-struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn);
-struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn);
-struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr,
- const char *val);
-struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
- const char * value,
- const struct ldb_dn *base);
-struct ldb_dn *ldb_dn_make_child(void *mem_ctx,
- const struct ldb_dn_component *component,
- const struct ldb_dn *base);
-struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2);
-struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...) PRINTF_ATTRIBUTE(3,4);
-struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn);
-
-/* useful functions for ldb_message structure manipulation */
-int ldb_dn_cmp(struct ldb_context *ldb, const char *dn1, const char *dn2);
+/**
+ Get the linear form of a DN (without any extended components)
+
+ \param dn The DN to linearize
+*/
+
+const char *ldb_dn_get_linearized(struct ldb_dn *dn);
+
+/**
+ Allocate a copy of the linear form of a DN (without any extended components) onto the supplied memory context
+
+ \param dn The DN to linearize
+ \param mem_ctx TALLOC context to return result on
+*/
+
+char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
+
+/**
+ Get the linear form of a DN (with any extended components)
+
+ \param mem_ctx TALLOC context to return result on
+ \param dn The DN to linearize
+ \param mode Style of extended DN to return (0 is HEX representation of binary form, 1 is a string form)
+*/
+char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode);
+const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name);
+int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val);
+
+void ldb_dn_remove_extended_components(struct ldb_dn *dn);
+bool ldb_dn_has_extended(struct ldb_dn *dn);
+
+int ldb_dn_extended_add_syntax(struct ldb_context *ldb,
+ unsigned flags,
+ const struct ldb_dn_extended_syntax *syntax);
+
+/**
+ Allocate a new DN from a string
+
+ \param mem_ctx TALLOC context to return resulting ldb_dn structure on
+ \param dn The new DN
+
+ \note The DN will not be parsed at this time. Use ldb_dn_validate to tell if the DN is syntacticly correct
+*/
+
+struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *dn);
+/**
+ Allocate a new DN from a printf style format string and arguments
+
+ \param mem_ctx TALLOC context to return resulting ldb_dn structure on
+ \param new_fms The new DN as a format string (plus arguments)
+
+ \note The DN will not be parsed at this time. Use ldb_dn_validate to tell if the DN is syntacticly correct
+*/
+
+struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...) PRINTF_ATTRIBUTE(3,4);
+/**
+ Allocate a new DN from a struct ldb_val (useful to avoid buffer overrun)
+
+ \param mem_ctx TALLOC context to return resulting ldb_dn structure on
+ \param dn The new DN
+
+ \note The DN will not be parsed at this time. Use ldb_dn_validate to tell if the DN is syntacticly correct
+*/
+
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);
+
+/**
+ Determine if this DN is syntactically valid
+
+ \param dn The DN to validate
+*/
+
+bool ldb_dn_validate(struct ldb_dn *dn);
+
+char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value);
+const char *ldb_dn_get_casefold(struct ldb_dn *dn);
+char *ldb_dn_alloc_casefold(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
+
+int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn);
+int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1);
+
+bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base);
+bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...) PRINTF_ATTRIBUTE(2,3);
+bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child);
+bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...) PRINTF_ATTRIBUTE(2,3);
+bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num);
+bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num);
+
+struct ldb_dn *ldb_dn_copy(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
+struct ldb_dn *ldb_dn_get_parent(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
+char *ldb_dn_canonical_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
+char *ldb_dn_canonical_ex_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
+int ldb_dn_get_comp_num(struct ldb_dn *dn);
+const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num);
+const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num);
+const char *ldb_dn_get_rdn_name(struct ldb_dn *dn);
+const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn);
+int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val);
+
+bool ldb_dn_is_valid(struct ldb_dn *dn);
+bool ldb_dn_is_special(struct ldb_dn *dn);
+bool ldb_dn_check_special(struct ldb_dn *dn, const char *check);
+bool ldb_dn_is_null(struct ldb_dn *dn);
+
/**
Compare two attributes
This function compares to attribute names. Note that this is a
case-insensitive comparison.
- \param attr1 the first attribute name to compare
- \param attr2 the second attribute name to compare
+ \param a the first attribute name to compare
+ \param b the second attribute name to compare
\return 0 if the attribute names are the same, or only differ in
case; non-zero if there are any differences
+
+ attribute names are restricted by rfc2251 so using
+ strcasecmp and toupper here is ok.
+ return 0 for match
*/
-int ldb_attr_cmp(const char *attr1, const char *attr2);
-char *ldb_attr_casefold(void *mem_ctx, const char *s);
+#define ldb_attr_cmp(a, b) strcasecmp(a, b)
+char *ldb_attr_casefold(TALLOC_CTX *mem_ctx, const char *s);
int ldb_attr_dn(const char *attr);
/**
to get the top level context, however the ldb context (from
ldb_init()) may be a better choice
*/
-struct ldb_message *ldb_msg_new(void *mem_ctx);
+struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx);
/**
Find an element within an message
/**
add a new empty element to a ldb_message
*/
-int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags);
+int ldb_msg_add_empty(struct ldb_message *msg,
+ const char *attr_name,
+ int flags,
+ struct ldb_message_element **return_el);
/**
add a element to a ldb_message
const struct ldb_message_element *el,
int flags);
int ldb_msg_add_value(struct ldb_message *msg,
- const char *attr_name,
- const struct ldb_val *val);
+ const char *attr_name,
+ const struct ldb_val *val,
+ struct ldb_message_element **return_el);
int ldb_msg_add_steal_value(struct ldb_message *msg,
const char *attr_name,
struct ldb_val *val);
*/
int ldb_msg_element_compare(struct ldb_message_element *el1,
struct ldb_message_element *el2);
+int ldb_msg_element_compare_name(struct ldb_message_element *el1,
+ struct ldb_message_element *el2);
/**
Find elements in a message.
single valued.
*/
const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name);
-int ldb_msg_find_int(const struct ldb_message *msg,
- const char *attr_name,
- int default_value);
-unsigned int ldb_msg_find_uint(const struct ldb_message *msg,
- const char *attr_name,
- unsigned int default_value);
-int64_t ldb_msg_find_int64(const struct ldb_message *msg,
- const char *attr_name,
- int64_t default_value);
-uint64_t ldb_msg_find_uint64(const struct ldb_message *msg,
+int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
const char *attr_name,
- uint64_t default_value);
-double ldb_msg_find_double(const struct ldb_message *msg,
- const char *attr_name,
- double default_value);
-const char *ldb_msg_find_string(const struct ldb_message *msg,
- const char *attr_name,
- const char *default_value);
+ int default_value);
+unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
+ const char *attr_name,
+ unsigned int default_value);
+int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
+ const char *attr_name,
+ int64_t default_value);
+uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
+ const char *attr_name,
+ uint64_t default_value);
+double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
+ const char *attr_name,
+ double default_value);
+int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
+ const char *attr_name,
+ int default_value);
+const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
+ const char *attr_name,
+ const char *default_value);
+
+struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ const struct ldb_message *msg,
+ const char *attr_name);
void ldb_msg_sort_elements(struct ldb_message *msg);
-struct ldb_message *ldb_msg_copy_shallow(void *mem_ctx,
+struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
const struct ldb_message *msg);
-struct ldb_message *ldb_msg_copy(void *mem_ctx,
+struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
const struct ldb_message *msg);
struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
This function performs basic sanity / integrity checks on an
ldb_message.
+ \param ldb context in which to perform the checks
\param msg the message to check
\return LDB_SUCCESS if the message is OK, or a non-zero error code
LDB_ERR_INVALID_ATTRIBUTE_SYNTAX) if there is a problem with a
message.
*/
-int ldb_msg_sanity_check(const struct ldb_message *msg);
+int ldb_msg_sanity_check(struct ldb_context *ldb,
+ const struct ldb_message *msg);
/**
Duplicate an ldb_val structure
\return the duplicated ldb_val structure.
*/
-struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v);
+struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v);
/**
this allows the user to set a debug function for error reporting
*/
int ldb_set_debug(struct ldb_context *ldb,
void (*debug)(void *context, enum ldb_debug_level level,
- const char *fmt, va_list ap),
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0),
void *context);
/**
this allows the user to set custom utf8 function for error reporting
*/
void ldb_set_utf8_fns(struct ldb_context *ldb,
- void *context,
- char *(*casefold)(void *, void *, const char *));
+ void *context,
+ char *(*casefold)(void *, void *, const char *, size_t n));
/**
this sets up debug to print messages on stderr
int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value);
void *ldb_get_opaque(struct ldb_context *ldb, const char *name);
-const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb,
- const char *attrib);
-
-
-const char **ldb_attr_list_copy(void *mem_ctx, const char * const *attrs);
+const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs);
+const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr);
int ldb_attr_in_list(const char * const *attrs, const char *attr);
+int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace);
+int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace);
+void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr);
+void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el);
+
void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree,
const char *attr,
const char *replace);
-int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace);
-int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace);
-void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr);
/**
Convert a time structure to a string
- This function converts a time_t structure to an LDAP formatted time
- string.
-
+ This function converts a time_t structure to an LDAP formatted
+ GeneralizedTime string.
+
\param mem_ctx the memory context to allocate the return string in
\param t the time structure to convert
\return the formatted string, or NULL if the time structure could
not be converted
*/
-char *ldb_timestring(void *mem_ctx, time_t t);
+char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t);
/**
Convert a string to a time structure
- This function converts an LDAP formatted time string to a time_t
- structure.
+ This function converts an LDAP formatted GeneralizedTime string
+ to a time_t structure.
\param s the string to convert
*/
time_t ldb_string_to_time(const char *s);
-char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn);
-char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn);
+/**
+ Convert a time structure to a string
+
+ This function converts a time_t structure to an LDAP formatted
+ UTCTime string.
+
+ \param mem_ctx the memory context to allocate the return string in
+ \param t the time structure to convert
+
+ \return the formatted string, or NULL if the time structure could
+ not be converted
+*/
+char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t);
+
+/**
+ Convert a string to a time structure
+
+ This function converts an LDAP formatted UTCTime string
+ to a time_t structure.
+
+ \param s the string to convert
+
+ \return the time structure, or 0 if the string cannot be converted
+*/
+time_t ldb_string_utc_to_time(const char *s);
void ldb_qsort (void *const pbase, size_t total_elems, size_t size, void *opaque, ldb_qsort_cmp_fn_t cmp);
+
+
+/**
+ Convert an array of string represention of a control into an array of ldb_control structures
+
+ \param ldb LDB context
+ \param mem_ctx TALLOC context to return result on, and to allocate error_string on
+ \param control_strings Array of string-formatted controls
+
+ \return array of ldb_control elements
+*/
+struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings);
+
#endif