dsdb-acl: attr is not optional to acl_check_access_on_attribute()
[Samba/gebeck_regimport.git] / source4 / dsdb / samdb / ldb_modules / simple_ldap_map.c
blob91852f03adc3b3cb05a491c42527ccc12ccdb90e
1 /*
2 ldb database module
4 LDAP semantics mapping module
6 Copyright (C) Jelmer Vernooij 2005
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /*
24 This module relies on ldb_map to do all the real work, but performs
25 some of the trivial mappings between AD semantics and that provided
26 by OpenLDAP and similar servers.
29 #include "includes.h"
30 #include <ldb_module.h>
31 #include "ldb/ldb_map/ldb_map.h"
33 #include "librpc/gen_ndr/ndr_misc.h"
34 #include "librpc/ndr/libndr.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "dsdb/common/util.h"
37 #include <ldb_handlers.h>
39 struct entryuuid_private {
40 struct ldb_context *ldb;
41 struct ldb_dn **base_dns;
44 static struct ldb_val encode_guid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
46 struct GUID guid;
47 NTSTATUS status = GUID_from_data_blob(val, &guid);
48 struct ldb_val out = data_blob(NULL, 0);
50 if (!NT_STATUS_IS_OK(status)) {
51 return out;
53 status = GUID_to_ndr_blob(&guid, ctx, &out);
54 if (!NT_STATUS_IS_OK(status)) {
55 return data_blob(NULL, 0);
58 return out;
61 static struct ldb_val guid_always_string(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
63 struct ldb_val out = data_blob(NULL, 0);
64 struct GUID guid;
65 NTSTATUS status = GUID_from_data_blob(val, &guid);
66 if (!NT_STATUS_IS_OK(status)) {
67 return out;
69 return data_blob_string_const(GUID_string(ctx, &guid));
72 static struct ldb_val encode_ns_guid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
74 struct GUID guid;
75 NTSTATUS status = NS_GUID_from_string((char *)val->data, &guid);
76 struct ldb_val out = data_blob(NULL, 0);
78 if (!NT_STATUS_IS_OK(status)) {
79 return out;
81 status = GUID_to_ndr_blob(&guid, ctx, &out);
82 if (!NT_STATUS_IS_OK(status)) {
83 return data_blob(NULL, 0);
86 return out;
89 static struct ldb_val guid_ns_string(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
91 struct ldb_val out = data_blob(NULL, 0);
92 struct GUID guid;
93 NTSTATUS status = GUID_from_data_blob(val, &guid);
94 if (!NT_STATUS_IS_OK(status)) {
95 return out;
97 return data_blob_string_const(NS_GUID_string(ctx, &guid));
100 /* The backend holds binary sids, so just copy them back */
101 static struct ldb_val val_copy(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
103 struct ldb_val out = data_blob(NULL, 0);
104 out = ldb_val_dup(ctx, val);
106 return out;
109 /* Ensure we always convert sids into binary, so the backend doesn't have to know about both forms */
110 static struct ldb_val sid_always_binary(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
112 struct ldb_context *ldb = ldb_module_get_ctx(module);
113 struct ldb_val out = data_blob(NULL, 0);
114 const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, "objectSid");
116 if (a->syntax->canonicalise_fn(ldb, ctx, val, &out) != LDB_SUCCESS) {
117 return data_blob(NULL, 0);
120 return out;
123 /* Ensure we always convert sids into string, so the backend doesn't have to know about both forms */
124 static struct ldb_val sid_always_string(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
126 struct ldb_context *ldb = ldb_module_get_ctx(module);
127 struct ldb_val out = data_blob(NULL, 0);
129 if (ldif_comparision_objectSid_isString(val)) {
130 if (ldb_handler_copy(ldb, ctx, val, &out) != LDB_SUCCESS) {
131 return data_blob(NULL, 0);
134 } else {
135 if (ldif_write_objectSid(ldb, ctx, val, &out) != LDB_SUCCESS) {
136 return data_blob(NULL, 0);
139 return out;
142 /* Ensure we always convert objectCategory into a DN */
143 static struct ldb_val objectCategory_always_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
145 struct ldb_context *ldb = ldb_module_get_ctx(module);
146 struct ldb_dn *dn;
147 struct ldb_val out = data_blob(NULL, 0);
148 const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, "objectCategory");
150 dn = ldb_dn_from_ldb_val(ctx, ldb, val);
151 if (ldb_dn_validate(dn)) {
152 talloc_free(dn);
153 return val_copy(module, ctx, val);
155 talloc_free(dn);
157 if (a->syntax->canonicalise_fn(ldb, ctx, val, &out) != LDB_SUCCESS) {
158 return data_blob(NULL, 0);
161 return out;
164 static struct ldb_val normalise_to_signed32(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
166 struct ldb_val out;
167 /* We've to use "strtoll" here to have the intended overflows.
168 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
169 int32_t i = (int32_t) strtoll((char *)val->data, NULL, 0);
170 out = data_blob_string_const(talloc_asprintf(ctx, "%d", i));
171 return out;
174 static struct ldb_val usn_to_entryCSN(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
176 struct ldb_val out;
177 unsigned long long usn = strtoull((const char *)val->data, NULL, 10);
178 time_t t = (usn >> 24);
179 out = data_blob_string_const(talloc_asprintf(ctx, "%s#%06x#00#000000", ldb_timestring(ctx, t), (unsigned int)(usn & 0xFFFFFF)));
180 return out;
183 static unsigned long long entryCSN_to_usn_int(TALLOC_CTX *ctx, const struct ldb_val *val)
185 char *entryCSN = talloc_strndup(ctx, (const char *)val->data, val->length);
186 char *mod_per_sec;
187 time_t t;
188 unsigned long long usn;
189 char *p;
190 if (!entryCSN) {
191 return 0;
193 p = strchr(entryCSN, '#');
194 if (!p) {
195 return 0;
197 p[0] = '\0';
198 p++;
199 mod_per_sec = p;
201 p = strchr(p, '#');
202 if (!p) {
203 return 0;
205 p[0] = '\0';
206 p++;
208 usn = strtol(mod_per_sec, NULL, 16);
210 t = ldb_string_to_time(entryCSN);
212 usn = usn | ((unsigned long long)t <<24);
213 return usn;
216 static struct ldb_val entryCSN_to_usn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
218 struct ldb_val out;
219 unsigned long long usn = entryCSN_to_usn_int(ctx, val);
220 out = data_blob_string_const(talloc_asprintf(ctx, "%lld", usn));
221 return out;
224 static struct ldb_val usn_to_timestamp(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
226 struct ldb_val out;
227 unsigned long long usn = strtoull((const char *)val->data, NULL, 10);
228 time_t t = (usn >> 24);
229 out = data_blob_string_const(ldb_timestring(ctx, t));
230 return out;
233 static struct ldb_val timestamp_to_usn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
235 struct ldb_val out;
236 time_t t=0;
237 unsigned long long usn;
239 ldb_val_to_time(val, &t);
241 usn = ((unsigned long long)t <<24);
243 out = data_blob_string_const(talloc_asprintf(ctx, "%lld", usn));
244 return out;
248 static const struct ldb_map_attribute entryuuid_attributes[] =
250 /* objectGUID */
252 .local_name = "objectGUID",
253 .type = LDB_MAP_CONVERT,
254 .u = {
255 .convert = {
256 .remote_name = "entryUUID",
257 .convert_local = guid_always_string,
258 .convert_remote = encode_guid,
262 /* invocationId */
264 .local_name = "invocationId",
265 .type = LDB_MAP_CONVERT,
266 .u = {
267 .convert = {
268 .remote_name = "invocationId",
269 .convert_local = guid_always_string,
270 .convert_remote = encode_guid,
274 /* objectSid */
276 .local_name = "objectSid",
277 .type = LDB_MAP_CONVERT,
278 .u = {
279 .convert = {
280 .remote_name = "objectSid",
281 .convert_local = sid_always_binary,
282 .convert_remote = val_copy,
286 /* securityIdentifier */
288 .local_name = "securityIdentifier",
289 .type = LDB_MAP_CONVERT,
290 .u = {
291 .convert = {
292 .remote_name = "securityIdentifier",
293 .convert_local = sid_always_binary,
294 .convert_remote = val_copy,
299 .local_name = "name",
300 .type = LDB_MAP_RENAME,
301 .u = {
302 .rename = {
303 .remote_name = "rdnValue"
308 .local_name = "whenCreated",
309 .type = LDB_MAP_RENAME,
310 .u = {
311 .rename = {
312 .remote_name = "createTimestamp"
317 .local_name = "whenChanged",
318 .type = LDB_MAP_RENAME,
319 .u = {
320 .rename = {
321 .remote_name = "modifyTimestamp"
326 .local_name = "objectClasses",
327 .type = LDB_MAP_RENAME,
328 .u = {
329 .rename = {
330 .remote_name = "samba4ObjectClasses"
335 .local_name = "dITContentRules",
336 .type = LDB_MAP_RENAME,
337 .u = {
338 .rename = {
339 .remote_name = "samba4DITContentRules"
344 .local_name = "attributeTypes",
345 .type = LDB_MAP_RENAME,
346 .u = {
347 .rename = {
348 .remote_name = "samba4AttributeTypes"
353 .local_name = "objectCategory",
354 .type = LDB_MAP_CONVERT,
355 .u = {
356 .convert = {
357 .remote_name = "objectCategory",
358 .convert_local = objectCategory_always_dn,
359 .convert_remote = val_copy,
364 .local_name = "distinguishedName",
365 .type = LDB_MAP_RENAME,
366 .u = {
367 .rename = {
368 .remote_name = "entryDN"
373 .local_name = "primaryGroupID",
374 .type = LDB_MAP_CONVERT,
375 .u = {
376 .convert = {
377 .remote_name = "primaryGroupID",
378 .convert_local = normalise_to_signed32,
379 .convert_remote = val_copy,
384 .local_name = "groupType",
385 .type = LDB_MAP_CONVERT,
386 .u = {
387 .convert = {
388 .remote_name = "groupType",
389 .convert_local = normalise_to_signed32,
390 .convert_remote = val_copy,
395 .local_name = "userAccountControl",
396 .type = LDB_MAP_CONVERT,
397 .u = {
398 .convert = {
399 .remote_name = "userAccountControl",
400 .convert_local = normalise_to_signed32,
401 .convert_remote = val_copy,
406 .local_name = "sAMAccountType",
407 .type = LDB_MAP_CONVERT,
408 .u = {
409 .convert = {
410 .remote_name = "sAMAccountType",
411 .convert_local = normalise_to_signed32,
412 .convert_remote = val_copy,
417 .local_name = "systemFlags",
418 .type = LDB_MAP_CONVERT,
419 .u = {
420 .convert = {
421 .remote_name = "systemFlags",
422 .convert_local = normalise_to_signed32,
423 .convert_remote = val_copy,
428 .local_name = "usnChanged",
429 .type = LDB_MAP_CONVERT,
430 .u = {
431 .convert = {
432 .remote_name = "entryCSN",
433 .convert_local = usn_to_entryCSN,
434 .convert_remote = entryCSN_to_usn
439 .local_name = "usnCreated",
440 .type = LDB_MAP_CONVERT,
441 .u = {
442 .convert = {
443 .remote_name = "createTimestamp",
444 .convert_local = usn_to_timestamp,
445 .convert_remote = timestamp_to_usn,
450 .local_name = "*",
451 .type = LDB_MAP_KEEP,
454 .local_name = NULL,
458 /* This objectClass conflicts with builtin classes on OpenLDAP */
459 const struct ldb_map_objectclass entryuuid_objectclasses[] =
462 .local_name = "subSchema",
463 .remote_name = "samba4SubSchema"
466 .local_name = NULL
470 /* These things do not show up in wildcard searches in OpenLDAP, but
471 * we need them to show up in the AD-like view */
472 static const char * const entryuuid_wildcard_attributes[] = {
473 "objectGUID",
474 "whenCreated",
475 "whenChanged",
476 "usnCreated",
477 "usnChanged",
478 "memberOf",
479 NULL
482 static const struct ldb_map_attribute nsuniqueid_attributes[] =
484 /* objectGUID */
486 .local_name = "objectGUID",
487 .type = LDB_MAP_CONVERT,
488 .u = {
489 .convert = {
490 .remote_name = "nsuniqueid",
491 .convert_local = guid_ns_string,
492 .convert_remote = encode_ns_guid,
496 /* objectSid */
498 .local_name = "objectSid",
499 .type = LDB_MAP_CONVERT,
500 .u = {
501 .convert = {
502 .remote_name = "sambaSID",
503 .convert_local = sid_always_string,
504 .convert_remote = sid_always_binary,
508 /* securityIdentifier */
510 .local_name = "securityIdentifier",
511 .type = LDB_MAP_CONVERT,
512 .u = {
513 .convert = {
514 .remote_name = "securityIdentifier",
515 .convert_local = sid_always_binary,
516 .convert_remote = val_copy,
521 .local_name = "whenCreated",
522 .type = LDB_MAP_RENAME,
523 .u = {
524 .rename = {
525 .remote_name = "createTimestamp"
530 .local_name = "whenChanged",
531 .type = LDB_MAP_RENAME,
532 .u = {
533 .rename = {
534 .remote_name = "modifyTimestamp"
539 .local_name = "objectCategory",
540 .type = LDB_MAP_CONVERT,
541 .u = {
542 .convert = {
543 .remote_name = "objectCategory",
544 .convert_local = objectCategory_always_dn,
545 .convert_remote = val_copy,
550 .local_name = "distinguishedName",
551 .type = LDB_MAP_RENAME,
552 .u = {
553 .rename = {
554 .remote_name = "entryDN"
559 .local_name = "primaryGroupID",
560 .type = LDB_MAP_CONVERT,
561 .u = {
562 .convert = {
563 .remote_name = "primaryGroupID",
564 .convert_local = normalise_to_signed32,
565 .convert_remote = val_copy,
570 .local_name = "groupType",
571 .type = LDB_MAP_CONVERT,
572 .u = {
573 .convert = {
574 .remote_name = "sambaGroupType",
575 .convert_local = normalise_to_signed32,
576 .convert_remote = val_copy,
581 .local_name = "userAccountControl",
582 .type = LDB_MAP_CONVERT,
583 .u = {
584 .convert = {
585 .remote_name = "userAccountControl",
586 .convert_local = normalise_to_signed32,
587 .convert_remote = val_copy,
592 .local_name = "sAMAccountType",
593 .type = LDB_MAP_CONVERT,
594 .u = {
595 .convert = {
596 .remote_name = "sAMAccountType",
597 .convert_local = normalise_to_signed32,
598 .convert_remote = val_copy,
603 .local_name = "systemFlags",
604 .type = LDB_MAP_CONVERT,
605 .u = {
606 .convert = {
607 .remote_name = "systemFlags",
608 .convert_local = normalise_to_signed32,
609 .convert_remote = val_copy,
614 .local_name = "usnChanged",
615 .type = LDB_MAP_CONVERT,
616 .u = {
617 .convert = {
618 .remote_name = "modifyTimestamp",
619 .convert_local = usn_to_timestamp,
620 .convert_remote = timestamp_to_usn,
625 .local_name = "usnCreated",
626 .type = LDB_MAP_CONVERT,
627 .u = {
628 .convert = {
629 .remote_name = "createTimestamp",
630 .convert_local = usn_to_timestamp,
631 .convert_remote = timestamp_to_usn,
636 .local_name = "pwdLastSet",
637 .type = LDB_MAP_RENAME,
638 .u = {
639 .rename = {
640 .remote_name = "sambaPwdLastSet"
645 .local_name = "lastLogon",
646 .type = LDB_MAP_RENAME,
647 .u = {
648 .rename = {
649 .remote_name = "sambaLogonTime"
654 .local_name = "lastLogoff",
655 .type = LDB_MAP_RENAME,
656 .u = {
657 .rename = {
658 .remote_name = "sambaLogoffTime"
663 .local_name = "badPwdCount",
664 .type = LDB_MAP_RENAME,
665 .u = {
666 .rename = {
667 .remote_name = "sambaBadPasswordCount"
672 .local_name = "logonHours",
673 .type = LDB_MAP_RENAME,
674 .u = {
675 .rename = {
676 .remote_name = "sambaLogonHours"
681 .local_name = "homeDrive",
682 .type = LDB_MAP_RENAME,
683 .u = {
684 .rename = {
685 .remote_name = "sambaHomeDrive"
690 .local_name = "scriptPath",
691 .type = LDB_MAP_RENAME,
692 .u = {
693 .rename = {
694 .remote_name = "sambaLogonScript"
699 .local_name = "profilePath",
700 .type = LDB_MAP_RENAME,
701 .u = {
702 .rename = {
703 .remote_name = "sambaProfilePath"
708 .local_name = "userWorkstations",
709 .type = LDB_MAP_RENAME,
710 .u = {
711 .rename = {
712 .remote_name = "sambaUserWorkstations"
717 .local_name = "homeDirectory",
718 .type = LDB_MAP_RENAME,
719 .u = {
720 .rename = {
721 .remote_name = "sambaHomePath"
726 .local_name = "nextRid",
727 .type = LDB_MAP_RENAME,
728 .u = {
729 .rename = {
730 .remote_name = "sambaNextRid"
735 .local_name = "privilegeDisplayName",
736 .type = LDB_MAP_RENAME,
737 .u = {
738 .rename = {
739 .remote_name = "sambaPrivName"
744 .local_name = "*",
745 .type = LDB_MAP_KEEP,
748 .local_name = NULL,
752 /* This objectClass conflicts with builtin classes on FDS */
753 const struct ldb_map_objectclass nsuniqueid_objectclasses[] =
756 .local_name = NULL
760 /* These things do not show up in wildcard searches in OpenLDAP, but
761 * we need them to show up in the AD-like view */
762 static const char * const nsuniqueid_wildcard_attributes[] = {
763 "objectGUID",
764 "whenCreated",
765 "whenChanged",
766 "usnCreated",
767 "usnChanged",
768 NULL
771 /* the context init function */
772 static int entryuuid_init(struct ldb_module *module)
774 int ret;
775 ret = ldb_map_init(module, entryuuid_attributes, entryuuid_objectclasses, entryuuid_wildcard_attributes, "samba4Top", NULL);
776 if (ret != LDB_SUCCESS)
777 return ret;
779 return ldb_next_init(module);
782 /* the context init function */
783 static int nsuniqueid_init(struct ldb_module *module)
785 int ret;
786 ret = ldb_map_init(module, nsuniqueid_attributes, nsuniqueid_objectclasses, nsuniqueid_wildcard_attributes, "extensibleObject", NULL);
787 if (ret != LDB_SUCCESS)
788 return ret;
790 return ldb_next_init(module);
793 static int get_seq_callback(struct ldb_request *req,
794 struct ldb_reply *ares)
796 unsigned long long *seq = (unsigned long long *)req->context;
798 if (!ares) {
799 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
801 if (ares->error != LDB_SUCCESS) {
802 return ldb_request_done(req, ares->error);
805 if (ares->type == LDB_REPLY_ENTRY) {
806 struct ldb_message_element *el = ldb_msg_find_element(ares->message, "contextCSN");
807 if (el) {
808 *seq = entryCSN_to_usn_int(ares, &el->values[0]);
812 if (ares->type == LDB_REPLY_DONE) {
813 return ldb_request_done(req, LDB_SUCCESS);
816 talloc_free(ares);
817 return LDB_SUCCESS;
820 static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_request *req)
822 struct ldb_context *ldb;
823 int ret;
824 struct map_private *map_private;
825 struct entryuuid_private *entryuuid_private;
826 unsigned long long seq_num = 0;
827 struct ldb_request *search_req;
829 const struct ldb_control *partition_ctrl;
830 const struct dsdb_control_current_partition *partition;
832 static const char *contextCSN_attr[] = {
833 "contextCSN", NULL
836 struct ldb_seqnum_request *seq;
837 struct ldb_seqnum_result *seqr;
838 struct ldb_extended *ext;
840 ldb = ldb_module_get_ctx(module);
842 seq = talloc_get_type(req->op.extended.data, struct ldb_seqnum_request);
844 map_private = talloc_get_type(ldb_module_get_private(module), struct map_private);
846 entryuuid_private = talloc_get_type(map_private->caller_private, struct entryuuid_private);
848 /* All this to get the DN of the parition, so we can search the right thing */
849 partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
850 if (!partition_ctrl) {
851 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
852 "entryuuid_sequence_number: no current partition control found!");
853 return LDB_ERR_PROTOCOL_ERROR;
856 partition = talloc_get_type(partition_ctrl->data,
857 struct dsdb_control_current_partition);
858 if ((partition == NULL) || (partition->version != DSDB_CONTROL_CURRENT_PARTITION_VERSION)) {
859 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
860 "entryuuid_sequence_number: current partition control with wrong data!");
861 return LDB_ERR_PROTOCOL_ERROR;
864 ret = ldb_build_search_req(&search_req, ldb, req,
865 partition->dn, LDB_SCOPE_BASE,
866 NULL, contextCSN_attr, NULL,
867 &seq_num, get_seq_callback,
868 NULL);
869 LDB_REQ_SET_LOCATION(search_req);
870 if (ret != LDB_SUCCESS) {
871 return ret;
874 ret = ldb_next_request(module, search_req);
876 if (ret == LDB_SUCCESS) {
877 ret = ldb_wait(search_req->handle, LDB_WAIT_ALL);
880 talloc_free(search_req);
881 if (ret != LDB_SUCCESS) {
882 return ret;
885 ext = talloc_zero(req, struct ldb_extended);
886 if (!ext) {
887 return ldb_oom(ldb);
889 seqr = talloc_zero(req, struct ldb_seqnum_result);
890 if (seqr == NULL) {
891 talloc_free(ext);
892 return ldb_oom(ldb);
894 ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
895 ext->data = seqr;
897 switch (seq->type) {
898 case LDB_SEQ_HIGHEST_SEQ:
899 seqr->seq_num = seq_num;
900 break;
901 case LDB_SEQ_NEXT:
902 seqr->seq_num = seq_num;
903 seqr->seq_num++;
904 break;
905 case LDB_SEQ_HIGHEST_TIMESTAMP:
906 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, "LDB_SEQ_HIGHEST_TIMESTAMP not supported");
909 seqr->flags = 0;
910 seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
912 /* send request done */
913 return ldb_module_done(req, NULL, ext, LDB_SUCCESS);
916 static int entryuuid_extended(struct ldb_module *module, struct ldb_request *req)
918 if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
919 return entryuuid_sequence_number(module, req);
922 return ldb_next_request(module, req);
925 static const struct ldb_module_ops ldb_entryuuid_module_ops = {
926 .name = "entryuuid",
927 .init_context = entryuuid_init,
928 .extended = entryuuid_extended,
929 LDB_MAP_OPS
932 static const struct ldb_module_ops ldb_nsuniqueid_module_ops = {
933 .name = "nsuniqueid",
934 .init_context = nsuniqueid_init,
935 .extended = entryuuid_extended,
936 LDB_MAP_OPS
940 initialise the module
942 _PUBLIC_ int ldb_simple_ldap_map_module_init(const char *version)
944 int ret;
945 LDB_MODULE_CHECK_VERSION(version);
946 ret = ldb_register_module(&ldb_entryuuid_module_ops);
947 if (ret != LDB_SUCCESS) {
948 return ret;
950 ret = ldb_register_module(&ldb_nsuniqueid_module_ops);
951 if (ret != LDB_SUCCESS) {
952 return ret;
954 return LDB_SUCCESS;