4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb ldap backend
30 * Description: core files for LDAP backend
32 * Author: Andrew Tridgell
36 #include "ldb/ldb_ldap/ldb_ldap.h"
40 we don't need this right now, but will once we add some backend
45 find an option in an option list (a null terminated list of strings)
47 this assumes the list is short. If it ever gets long then we really
48 should do this in some smarter way
50 static const char *lldb_option_find(const struct lldb_private
*lldb
, const char *name
)
53 size_t len
= strlen(name
);
55 if (!lldb
->options
) return NULL
;
57 for (i
=0;lldb
->options
[i
];i
++) {
58 if (strncmp(lldb
->options
[i
], name
, len
) == 0 &&
59 lldb
->options
[i
][len
] == '=') {
60 return &lldb
->options
[i
][len
+1];
69 close/free the connection
71 static int lldb_close(struct ldb_module
*module
)
74 struct ldb_context
*ldb
= module
->ldb
;
75 struct lldb_private
*lldb
= module
->private_data
;
77 if (ldap_unbind(lldb
->ldap
) != LDAP_SUCCESS
) {
81 ldb_set_alloc(ldb
, NULL
, NULL
);
84 for (i
=0;lldb
->options
[i
];i
++) {
85 ldb_free(ldb
, lldb
->options
[i
]);
87 ldb_free(ldb
, lldb
->options
);
98 static int lldb_rename(struct ldb_module
*module
, const char *olddn
, const char *newdn
)
100 struct ldb_context
*ldb
= module
->ldb
;
101 struct lldb_private
*lldb
= module
->private_data
;
104 const char *parentdn
= "";
106 /* ignore ltdb specials */
107 if (olddn
[0] == '@' ||newdn
[0] == '@') {
111 newrdn
= ldb_strdup(ldb
, newdn
);
116 p
= strchr(newrdn
, ',');
122 lldb
->last_rc
= ldap_rename_s(lldb
->ldap
, olddn
, newrdn
, parentdn
, 1, NULL
, NULL
);
123 ldb_free(ldb
, newrdn
);
124 if (lldb
->last_rc
!= LDAP_SUCCESS
) {
134 static int lldb_delete(struct ldb_module
*module
, const char *dn
)
136 struct lldb_private
*lldb
= module
->private_data
;
139 /* ignore ltdb specials */
144 lldb
->last_rc
= ldap_delete_s(lldb
->ldap
, dn
);
145 if (lldb
->last_rc
!= LDAP_SUCCESS
) {
153 free a search message
155 static int lldb_msg_free(struct ldb_context
*ldb
, struct ldb_message
*msg
)
158 ldb_free(ldb
, msg
->dn
);
159 for (i
=0;i
<msg
->num_elements
;i
++) {
160 ldb_free(ldb
, msg
->elements
[i
].name
);
161 for (j
=0;j
<msg
->elements
[i
].num_values
;j
++) {
162 if (msg
->elements
[i
].values
[j
].data
) {
163 ldb_free(ldb
, msg
->elements
[i
].values
[j
].data
);
166 ldb_free(ldb
, msg
->elements
[i
].values
);
168 if (msg
->elements
) ldb_free(ldb
, msg
->elements
);
176 static int lldb_search_free(struct ldb_module
*module
, struct ldb_message
**res
)
178 struct ldb_context
*ldb
= module
->ldb
;
180 for (i
=0;res
[i
];i
++) {
181 if (lldb_msg_free(ldb
, res
[i
]) != 0) {
191 add a single set of ldap message values to a ldb_message
193 static int lldb_add_msg_attr(struct ldb_context
*ldb
,
194 struct ldb_message
*msg
,
195 const char *attr
, struct berval
**bval
)
198 struct ldb_message_element
*el
;
200 count
= ldap_count_values_len(bval
);
206 el
= ldb_realloc_p(ldb
, msg
->elements
, struct ldb_message_element
,
207 msg
->num_elements
+ 1);
215 el
= &msg
->elements
[msg
->num_elements
];
217 el
->name
= ldb_strdup(ldb
, attr
);
225 el
->values
= ldb_malloc_array_p(ldb
, struct ldb_val
, count
);
231 for (i
=0;i
<count
;i
++) {
232 el
->values
[i
].data
= ldb_malloc(ldb
, bval
[i
]->bv_len
);
233 if (!el
->values
[i
].data
) {
236 memcpy(el
->values
[i
].data
, bval
[i
]->bv_val
, bval
[i
]->bv_len
);
237 el
->values
[i
].length
= bval
[i
]->bv_len
;
247 search for matching records
249 static int lldb_search(struct ldb_module
*module
, const char *base
,
250 enum ldb_scope scope
, const char *expression
,
251 const char * const *attrs
, struct ldb_message
***res
)
253 struct ldb_context
*ldb
= module
->ldb
;
254 struct lldb_private
*lldb
= module
->private_data
;
255 int count
, msg_count
;
256 LDAPMessage
*ldapres
, *msg
;
262 lldb
->last_rc
= ldap_search_s(lldb
->ldap
, base
, (int)scope
,
264 discard_const_p(char *, attrs
),
266 if (lldb
->last_rc
!= LDAP_SUCCESS
) {
270 count
= ldap_count_entries(lldb
->ldap
, ldapres
);
271 if (count
== -1 || count
== 0) {
272 ldap_msgfree(ldapres
);
276 (*res
) = ldb_malloc_array_p(ldb
, struct ldb_message
*, count
+1);
278 ldap_msgfree(ldapres
);
287 /* loop over all messages */
288 for (msg
=ldap_first_entry(lldb
->ldap
, ldapres
);
290 msg
=ldap_next_entry(lldb
->ldap
, msg
)) {
291 BerElement
*berptr
= NULL
;
294 if (msg_count
== count
) {
295 /* hmm, got too many? */
296 ldb_debug(ldb
, LDB_DEBUG_FATAL
, "Fatal: ldap message count inconsistent\n");
300 (*res
)[msg_count
] = ldb_malloc_p(ldb
, struct ldb_message
);
301 if (!(*res
)[msg_count
]) {
304 (*res
)[msg_count
+1] = NULL
;
306 dn
= ldap_get_dn(lldb
->ldap
, msg
);
311 (*res
)[msg_count
]->dn
= ldb_strdup(ldb
, dn
);
313 if (!(*res
)[msg_count
]->dn
) {
318 (*res
)[msg_count
]->num_elements
= 0;
319 (*res
)[msg_count
]->elements
= NULL
;
320 (*res
)[msg_count
]->private_data
= NULL
;
322 /* loop over all attributes */
323 for (attr
=ldap_first_attribute(lldb
->ldap
, msg
, &berptr
);
325 attr
=ldap_next_attribute(lldb
->ldap
, msg
, berptr
)) {
326 struct berval
**bval
;
327 bval
= ldap_get_values_len(lldb
->ldap
, msg
, attr
);
330 lldb_add_msg_attr(ldb
, (*res
)[msg_count
], attr
, bval
);
331 ldap_value_free_len(bval
);
336 if (berptr
) ber_free(berptr
, 0);
341 ldap_msgfree(ldapres
);
346 if (*res
) lldb_search_free(module
, *res
);
352 free a set of mods from lldb_msg_to_mods()
354 static void lldb_mods_free(struct ldb_context
*ldb
, LDAPMod
**mods
)
360 for (i
=0;mods
[i
];i
++) {
361 if (mods
[i
]->mod_vals
.modv_bvals
) {
362 for (j
=0;mods
[i
]->mod_vals
.modv_bvals
[j
];j
++) {
363 ldb_free(ldb
, mods
[i
]->mod_vals
.modv_bvals
[j
]);
365 ldb_free(ldb
, mods
[i
]->mod_vals
.modv_bvals
);
367 ldb_free(ldb
, mods
[i
]);
374 convert a ldb_message structure to a list of LDAPMod structures
375 ready for ldap_add() or ldap_modify()
377 static LDAPMod
**lldb_msg_to_mods(struct ldb_context
*ldb
,
378 const struct ldb_message
*msg
, int use_flags
)
384 /* allocate maximum number of elements needed */
385 mods
= ldb_malloc_array_p(ldb
, LDAPMod
*, msg
->num_elements
+1);
392 for (i
=0;i
<msg
->num_elements
;i
++) {
393 const struct ldb_message_element
*el
= &msg
->elements
[i
];
395 mods
[num_mods
] = ldb_malloc_p(ldb
, LDAPMod
);
396 if (!mods
[num_mods
]) {
399 mods
[num_mods
+1] = NULL
;
400 mods
[num_mods
]->mod_op
= LDAP_MOD_BVALUES
;
402 switch (el
->flags
& LDB_FLAG_MOD_MASK
) {
403 case LDB_FLAG_MOD_ADD
:
404 mods
[num_mods
]->mod_op
|= LDAP_MOD_ADD
;
406 case LDB_FLAG_MOD_DELETE
:
407 mods
[num_mods
]->mod_op
|= LDAP_MOD_DELETE
;
409 case LDB_FLAG_MOD_REPLACE
:
410 mods
[num_mods
]->mod_op
|= LDAP_MOD_REPLACE
;
414 mods
[num_mods
]->mod_type
= el
->name
;
415 mods
[num_mods
]->mod_vals
.modv_bvals
= ldb_malloc_array_p(ldb
,
418 if (!mods
[num_mods
]->mod_vals
.modv_bvals
) {
422 for (j
=0;j
<el
->num_values
;j
++) {
423 mods
[num_mods
]->mod_vals
.modv_bvals
[j
] = ldb_malloc_p(ldb
, struct berval
);
424 if (!mods
[num_mods
]->mod_vals
.modv_bvals
[j
]) {
427 mods
[num_mods
]->mod_vals
.modv_bvals
[j
]->bv_val
= el
->values
[j
].data
;
428 mods
[num_mods
]->mod_vals
.modv_bvals
[j
]->bv_len
= el
->values
[j
].length
;
430 mods
[num_mods
]->mod_vals
.modv_bvals
[j
] = NULL
;
437 lldb_mods_free(ldb
, mods
);
445 static int lldb_add(struct ldb_module
*module
, const struct ldb_message
*msg
)
447 struct ldb_context
*ldb
= module
->ldb
;
448 struct lldb_private
*lldb
= module
->private_data
;
452 /* ignore ltdb specials */
453 if (msg
->dn
[0] == '@') {
457 mods
= lldb_msg_to_mods(ldb
, msg
, 0);
459 lldb
->last_rc
= ldap_add_s(lldb
->ldap
, msg
->dn
, mods
);
460 if (lldb
->last_rc
!= LDAP_SUCCESS
) {
464 lldb_mods_free(ldb
, mods
);
473 static int lldb_modify(struct ldb_module
*module
, const struct ldb_message
*msg
)
475 struct ldb_context
*ldb
= module
->ldb
;
476 struct lldb_private
*lldb
= module
->private_data
;
480 /* ignore ltdb specials */
481 if (msg
->dn
[0] == '@') {
485 mods
= lldb_msg_to_mods(ldb
, msg
, 1);
487 lldb
->last_rc
= ldap_modify_s(lldb
->ldap
, msg
->dn
, mods
);
488 if (lldb
->last_rc
!= LDAP_SUCCESS
) {
492 lldb_mods_free(ldb
, mods
);
499 return extended error information
501 static const char *lldb_errstring(struct ldb_module
*module
)
503 struct lldb_private
*lldb
= module
->private_data
;
504 return ldap_err2string(lldb
->last_rc
);
508 static const struct ldb_module_ops lldb_ops
= {
522 connect to the database
524 struct ldb_context
*lldb_connect(const char *url
,
526 const char *options
[])
528 struct ldb_context
*ldb
= NULL
;
529 struct lldb_private
*lldb
= NULL
;
532 ldb
= calloc(1, sizeof(struct ldb_context
));
538 lldb
= ldb_malloc_p(ldb
, struct lldb_private
);
546 lldb
->options
= NULL
;
548 lldb
->last_rc
= ldap_initialize(&lldb
->ldap
, url
);
549 if (lldb
->last_rc
!= LDAP_SUCCESS
) {
553 lldb
->last_rc
= ldap_set_option(lldb
->ldap
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
554 if (lldb
->last_rc
!= LDAP_SUCCESS
) {
558 ldb
->modules
= ldb_malloc_p(ldb
, struct ldb_module
);
564 ldb
->modules
->ldb
= ldb
;
565 ldb
->modules
->prev
= ldb
->modules
->next
= NULL
;
566 ldb
->modules
->private_data
= lldb
;
567 ldb
->modules
->ops
= &lldb_ops
;
570 /* take a copy of the options array, so we don't have to rely
571 on the caller keeping it around (it might be dynamic) */
572 for (i
=0;options
[i
];i
++) ;
574 lldb
->options
= ldb_malloc_array_p(ldb
, char *, i
+1);
575 if (!lldb
->options
) {
579 for (i
=0;options
[i
];i
++) {
580 lldb
->options
[i
+1] = NULL
;
581 lldb
->options
[i
] = ldb_strdup(ldb
, options
[i
]);
582 if (!lldb
->options
[i
]) {
591 if (lldb
&& lldb
->options
) {
592 for (i
=0;lldb
->options
[i
];i
++) {
593 ldb_free(ldb
, lldb
->options
[i
]);
595 ldb_free(ldb
, lldb
->options
);
597 if (lldb
&& lldb
->ldap
) {
598 ldap_unbind(lldb
->ldap
);