2 Unix SMB/CIFS implementation.
4 dsdb module schema utility functions
6 Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
7 Copyright (C) Andrew Tridgell 2010
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program 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
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "dsdb/common/util.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "dsdb/samdb/ldb_modules/util.h"
28 #include "lib/ldb/include/ldb_module.h"
29 #include "librpc/gen_ndr/ndr_drsuapi.h"
30 #include "librpc/gen_ndr/ndr_drsblobs.h"
31 #include "param/param.h"
34 * Reads schema_info structure from schemaInfo
35 * attribute on SCHEMA partition
37 * @param dsdb_flags DSDB_FLAG_... flag of 0
39 int dsdb_module_schema_info_blob_read(struct ldb_module *ldb_module,
42 struct ldb_val *schema_info_blob)
45 const struct ldb_val *blob_val;
46 struct ldb_dn *schema_dn;
47 struct ldb_result *schema_res = NULL;
48 static const char *schema_attrs[] = {
53 schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ldb_module));
55 DEBUG(0,("dsdb_module_schema_info_blob_read: no schema dn present!\n"));
56 return ldb_operr(ldb_module_get_ctx(ldb_module));
59 ldb_err = dsdb_module_search(ldb_module, mem_ctx, &schema_res, schema_dn,
60 LDB_SCOPE_BASE, schema_attrs, dsdb_flags, NULL);
61 if (ldb_err == LDB_ERR_NO_SUCH_OBJECT) {
62 DEBUG(0,("dsdb_module_schema_info_blob_read: Schema DN not found!\n"));
63 talloc_free(schema_res);
65 } else if (ldb_err != LDB_SUCCESS) {
66 DEBUG(0,("dsdb_module_schema_info_blob_read: failed to find schemaInfo attribute\n"));
67 talloc_free(schema_res);
71 blob_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
73 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
74 "dsdb_module_schema_info_blob_read: no schemaInfo attribute found");
75 talloc_free(schema_res);
76 return LDB_ERR_NO_SUCH_ATTRIBUTE;
79 /* transfer .data ownership to mem_ctx */
80 schema_info_blob->length = blob_val->length;
81 schema_info_blob->data = talloc_steal(mem_ctx, blob_val->data);
83 talloc_free(schema_res);
89 * Prepares ldb_msg to be used for updating schemaInfo value in DB
91 static int dsdb_schema_info_write_prepare(struct ldb_context *ldb,
92 struct ldb_val *schema_info_blob,
94 struct ldb_message **_msg)
97 struct ldb_message *msg;
98 struct ldb_dn *schema_dn;
99 struct ldb_message_element *return_el;
101 schema_dn = ldb_get_schema_basedn(ldb);
103 DEBUG(0,("dsdb_schema_info_write_prepare: no schema dn present\n"));
104 return ldb_operr(ldb);
107 /* prepare ldb_msg to update schemaInfo */
108 msg = ldb_msg_new(mem_ctx);
114 ldb_err = ldb_msg_add_value(msg, "schemaInfo", schema_info_blob, &return_el);
116 ldb_asprintf_errstring(ldb, "dsdb_schema_info_write_prepare: ldb_msg_add_value failed - %s\n",
117 ldb_strerror(ldb_err));
122 /* mark schemaInfo element for replacement */
123 return_el->flags = LDB_FLAG_MOD_REPLACE;
133 * Writes schema_info structure into schemaInfo
134 * attribute on SCHEMA partition
136 * @param dsdb_flags DSDB_FLAG_... flag of 0
138 int dsdb_module_schema_info_blob_write(struct ldb_module *ldb_module,
140 struct ldb_val *schema_info_blob)
143 struct ldb_message *msg;
144 TALLOC_CTX *temp_ctx;
146 temp_ctx = talloc_new(ldb_module);
147 if (temp_ctx == NULL) {
148 return ldb_module_oom(ldb_module);
151 /* write serialized schemaInfo into LDB */
152 ldb_err = dsdb_schema_info_write_prepare(ldb_module_get_ctx(ldb_module),
155 if (ldb_err != LDB_SUCCESS) {
156 talloc_free(temp_ctx);
161 ldb_err = dsdb_module_modify(ldb_module, msg, dsdb_flags);
163 talloc_free(temp_ctx);
165 if (ldb_err != LDB_SUCCESS) {
166 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
167 "dsdb_module_schema_info_blob_write: dsdb_replace failed: %s (%s)\n",
168 ldb_strerror(ldb_err),
169 ldb_errstring(ldb_module_get_ctx(ldb_module)));
178 * Reads schema_info structure from schemaInfo
179 * attribute on SCHEMA partition
181 static int dsdb_module_schema_info_read(struct ldb_module *ldb_module,
184 struct dsdb_schema_info **_schema_info)
188 TALLOC_CTX *temp_ctx;
191 temp_ctx = talloc_new(mem_ctx);
192 if (temp_ctx == NULL) {
193 return ldb_module_oom(ldb_module);
196 /* read serialized schemaInfo from LDB */
197 ret = dsdb_module_schema_info_blob_read(ldb_module, dsdb_flags, temp_ctx, &ndr_blob);
198 if (ret != LDB_SUCCESS) {
199 talloc_free(temp_ctx);
203 /* convert NDR blob to dsdb_schema_info object */
204 werr = dsdb_schema_info_from_blob(&ndr_blob,
207 talloc_free(temp_ctx);
209 if (W_ERROR_EQUAL(werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE)) {
210 return LDB_ERR_NO_SUCH_ATTRIBUTE;
213 if (!W_ERROR_IS_OK(werr)) {
214 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
215 return ldb_operr(ldb_module_get_ctx(ldb_module));
222 * Writes schema_info structure into schemaInfo
223 * attribute on SCHEMA partition
225 * @param dsdb_flags DSDB_FLAG_... flag of 0
227 static int dsdb_module_schema_info_write(struct ldb_module *ldb_module,
229 const struct dsdb_schema_info *schema_info)
234 TALLOC_CTX *temp_ctx;
236 temp_ctx = talloc_new(ldb_module);
237 if (temp_ctx == NULL) {
238 return ldb_module_oom(temp_ctx);
241 /* convert schema_info to a blob */
242 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
243 if (!W_ERROR_IS_OK(werr)) {
244 talloc_free(temp_ctx);
245 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
246 return ldb_operr(ldb_module_get_ctx(ldb_module));
249 /* write serialized schemaInfo into LDB */
250 ret = dsdb_module_schema_info_blob_write(ldb_module, dsdb_flags, &ndr_blob);
252 talloc_free(temp_ctx);
259 * Increments schemaInfo revision and save it to DB
260 * setting our invocationID in the process
261 * NOTE: this function should be called in a transaction
262 * much in the same way prefixMap update function is called
264 * @param ldb_module current module
265 * @param schema schema cache
266 * @param dsdb_flags DSDB_FLAG_... flag of 0
268 int dsdb_module_schema_info_update(struct ldb_module *ldb_module,
269 struct dsdb_schema *schema,
273 const struct GUID *invocation_id;
275 struct dsdb_schema_info *schema_info;
276 const char *schema_info_str;
278 TALLOC_CTX *temp_ctx = talloc_new(schema);
279 if (temp_ctx == NULL) {
280 return ldb_module_oom(ldb_module);
283 invocation_id = samdb_ntds_invocation_id(ldb_module_get_ctx(ldb_module));
284 if (!invocation_id) {
285 talloc_free(temp_ctx);
286 return ldb_operr(ldb_module_get_ctx(ldb_module));
289 /* read serialized schemaInfo from LDB */
290 ret = dsdb_module_schema_info_read(ldb_module, dsdb_flags, temp_ctx, &schema_info);
291 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
292 /* make default value in case
293 * we have no schemaInfo value yet */
294 werr = dsdb_schema_info_new(temp_ctx, &schema_info);
295 if (!W_ERROR_IS_OK(werr)) {
296 talloc_free(temp_ctx);
297 return ldb_module_oom(ldb_module);
301 if (ret != LDB_SUCCESS) {
302 talloc_free(temp_ctx);
306 /* update schemaInfo */
307 schema_info->revision++;
308 schema_info->invocation_id = *invocation_id;
310 ret = dsdb_module_schema_info_write(ldb_module, dsdb_flags, schema_info);
311 if (ret != LDB_SUCCESS) {
312 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
313 "dsdb_module_schema_info_update: failed to save schemaInfo - %s\n",
315 talloc_free(temp_ctx);
319 /* finally, update schema_info in the cache */
320 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
321 if (!W_ERROR_IS_OK(werr)) {
322 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), "Failed to get schema info");
323 talloc_free(temp_ctx);
324 return ldb_operr(ldb_module_get_ctx(ldb_module));
327 schema_info_str = hex_encode_talloc(schema, ndr_blob.data, ndr_blob.length);
328 if (!schema_info_str) {
329 talloc_free(temp_ctx);
330 return ldb_module_oom(ldb_module);
333 talloc_unlink(schema, discard_const(schema->schema_info));
334 schema->schema_info = schema_info_str;
336 talloc_free(temp_ctx);