r17525: This is a merge from the Google Summer of Code 2006 project by Martin Kühl
[samba.git] / source / dsdb / samdb / ldb_modules / entryUUID.c
1 /* 
2    ldb database module
3
4    LDAP semantics mapping module
5
6    Copyright (C) Jelmer Vernooij 2005
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
8
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 2 of the License, or
12    (at your option) any later version.
13    
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.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /* 
25    This module relies on ldb_map to do all the real work, but performs
26    some of the trivial mappings between AD semantics and that provided
27    by OpenLDAP and similar servers.
28 */
29
30 #include "includes.h"
31 #include "ldb/include/ldb.h"
32 #include "ldb/include/ldb_private.h"
33 #include "ldb/include/ldb_errors.h"
34 #include "ldb/modules/ldb_map.h"
35
36 #include "librpc/gen_ndr/ndr_misc.h"
37 #include "librpc/ndr/libndr.h"
38
39 static struct ldb_val encode_guid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
40 {
41         struct GUID guid;
42         NTSTATUS status = GUID_from_string((char *)val->data, &guid);
43         struct ldb_val out = data_blob(NULL, 0);
44
45         if (!NT_STATUS_IS_OK(status)) {
46                 return out;
47         }
48         status = ndr_push_struct_blob(&out, ctx, &guid, 
49                                       (ndr_push_flags_fn_t)ndr_push_GUID);
50         if (!NT_STATUS_IS_OK(status)) {
51                 return out;
52         }
53
54         return out;
55 }
56
57 static struct ldb_val decode_guid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
58 {
59         struct GUID *guid;
60         NTSTATUS status;
61         struct ldb_val out = data_blob(NULL, 0);
62         
63         guid = talloc(ctx, struct GUID);
64         if (guid == NULL) {
65                 return out;
66         }
67         status = ndr_pull_struct_blob(val, guid, guid, 
68                                       (ndr_pull_flags_fn_t)ndr_pull_GUID);
69         if (!NT_STATUS_IS_OK(status)) {
70                 talloc_free(guid);
71                 return out;
72         }
73         out = data_blob_string_const(GUID_string(ctx, guid));
74         talloc_free(guid);
75         return out;
76 }
77
78 /* The backend holds binary sids, so just copy them back */
79 static struct ldb_val sid_copy(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
80 {
81         struct ldb_val out = data_blob(NULL, 0);
82         ldb_handler_copy(module->ldb, ctx, val, &out);
83
84         return out;
85 }
86
87 /* Ensure we always convert sids into binary, so the backend doesn't have to know about both forms */
88 static struct ldb_val sid_always_binary(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
89 {
90         struct ldb_val out = data_blob(NULL, 0);
91         const struct ldb_attrib_handler *handler = ldb_attrib_handler(module->ldb, "objectSid");
92         
93         if (handler->canonicalise_fn(module->ldb, ctx, val, &out) != LDB_SUCCESS) {
94                 return data_blob(NULL, 0);
95         }
96
97         return out;
98 }
99
100 const struct ldb_map_attribute entryUUID_attributes[] = 
101 {
102         /* objectGUID */
103         {
104                 .local_name = "objectGUID",
105                 .type = MAP_CONVERT,
106                 .u = {
107                         .convert = {
108                                 .remote_name = "entryUUID", 
109                                 .convert_local = decode_guid,
110                                 .convert_remote = encode_guid,
111                         },
112                 },
113         },
114         /* objectSid */
115         {
116                 .local_name = "objectSid",
117                 .type = MAP_CONVERT,
118                 .u = {
119                         .convert = {
120                                 .remote_name = "objectSid", 
121                                 .convert_local = sid_always_binary,
122                                 .convert_remote = sid_copy,
123                         },
124                 },
125         },
126         {
127                 .local_name = "whenCreated",
128                 .type = MAP_RENAME,
129                 .u = {
130                         .rename = {
131                                  .remote_name = "createTimestamp"
132                          }
133                 }
134         },
135         {
136                 .local_name = "whenChanged",
137                 .type = MAP_RENAME,
138                 .u = {
139                         .rename = {
140                                  .remote_name = "modifyTimestamp"
141                          }
142                 }
143         },
144         {
145                 .local_name = "*",
146                 .type = MAP_KEEP,
147         },
148         {
149                 .local_name = NULL,
150         }
151 };
152
153 /* the context init function */
154 static int entryUUID_init(struct ldb_module *module)
155 {
156         int ret;
157
158         ret = ldb_map_init(module, entryUUID_attributes, NULL, NULL);
159         if (ret != LDB_SUCCESS)
160                 return ret;
161
162         return ldb_next_init(module);
163 }
164
165 static struct ldb_module_ops entryUUID_ops = {
166         .name              = "entryUUID",
167         .init_context      = entryUUID_init,
168 };
169
170 /* the init function */
171 int ldb_entryUUID_module_init(void)
172 {
173         struct ldb_module_ops ops = ldb_map_get_ops();
174         entryUUID_ops.add       = ops.add;
175         entryUUID_ops.modify    = ops.modify;
176         entryUUID_ops.del       = ops.del;
177         entryUUID_ops.rename    = ops.rename;
178         entryUUID_ops.search    = ops.search;
179         entryUUID_ops.wait      = ops.wait;
180
181         return ldb_register_module(&entryUUID_ops);
182 }