s4-dsdb: simplify migration of old-style seqence numbers to metadata.tdb
[Samba.git] / source4 / dsdb / samdb / ldb_modules / schema_util.c
blob86c21f02c658fe637b57631ff8ca1c04b0dc64da
1 /*
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/>.
24 #include "includes.h"
25 #include "dsdb/common/util.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "dsdb/samdb/ldb_modules/util.h"
28 #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"
33 /**
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,
40 uint32_t dsdb_flags,
41 TALLOC_CTX *mem_ctx,
42 struct ldb_val *schema_info_blob,
43 struct ldb_request *parent)
45 int ldb_err;
46 const struct ldb_val *blob_val;
47 struct ldb_dn *schema_dn;
48 struct ldb_result *schema_res = NULL;
49 static const char *schema_attrs[] = {
50 "schemaInfo",
51 NULL
54 schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ldb_module));
55 if (!schema_dn) {
56 DEBUG(0,("dsdb_module_schema_info_blob_read: no schema dn present!\n"));
57 return ldb_operr(ldb_module_get_ctx(ldb_module));
60 ldb_err = dsdb_module_search(ldb_module, mem_ctx, &schema_res, schema_dn,
61 LDB_SCOPE_BASE, schema_attrs, dsdb_flags, parent,
62 NULL);
63 if (ldb_err == LDB_ERR_NO_SUCH_OBJECT) {
64 DEBUG(0,("dsdb_module_schema_info_blob_read: Schema DN not found!\n"));
65 talloc_free(schema_res);
66 return ldb_err;
67 } else if (ldb_err != LDB_SUCCESS) {
68 DEBUG(0,("dsdb_module_schema_info_blob_read: failed to find schemaInfo attribute\n"));
69 talloc_free(schema_res);
70 return ldb_err;
73 blob_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
74 if (!blob_val) {
75 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
76 "dsdb_module_schema_info_blob_read: no schemaInfo attribute found");
77 talloc_free(schema_res);
78 return LDB_ERR_NO_SUCH_ATTRIBUTE;
81 /* transfer .data ownership to mem_ctx */
82 schema_info_blob->length = blob_val->length;
83 schema_info_blob->data = talloc_steal(mem_ctx, blob_val->data);
85 talloc_free(schema_res);
87 return LDB_SUCCESS;
90 /**
91 * Prepares ldb_msg to be used for updating schemaInfo value in DB
93 static int dsdb_schema_info_write_prepare(struct ldb_context *ldb,
94 struct ldb_val *schema_info_blob,
95 TALLOC_CTX *mem_ctx,
96 struct ldb_message **_msg)
98 int ldb_err;
99 struct ldb_message *msg;
100 struct ldb_dn *schema_dn;
101 struct ldb_message_element *return_el;
103 schema_dn = ldb_get_schema_basedn(ldb);
104 if (!schema_dn) {
105 DEBUG(0,("dsdb_schema_info_write_prepare: no schema dn present\n"));
106 return ldb_operr(ldb);
109 /* prepare ldb_msg to update schemaInfo */
110 msg = ldb_msg_new(mem_ctx);
111 if (msg == NULL) {
112 return ldb_oom(ldb);
115 msg->dn = schema_dn;
116 ldb_err = ldb_msg_add_value(msg, "schemaInfo", schema_info_blob, &return_el);
117 if (ldb_err != 0) {
118 ldb_asprintf_errstring(ldb, "dsdb_schema_info_write_prepare: ldb_msg_add_value failed - %s\n",
119 ldb_strerror(ldb_err));
120 talloc_free(msg);
121 return ldb_err;
124 /* mark schemaInfo element for replacement */
125 return_el->flags = LDB_FLAG_MOD_REPLACE;
127 *_msg = msg;
129 return LDB_SUCCESS;
135 * Writes schema_info structure into schemaInfo
136 * attribute on SCHEMA partition
138 * @param dsdb_flags DSDB_FLAG_... flag of 0
140 int dsdb_module_schema_info_blob_write(struct ldb_module *ldb_module,
141 uint32_t dsdb_flags,
142 struct ldb_val *schema_info_blob,
143 struct ldb_request *parent)
145 int ldb_err;
146 struct ldb_message *msg;
147 TALLOC_CTX *temp_ctx;
149 temp_ctx = talloc_new(ldb_module);
150 if (temp_ctx == NULL) {
151 return ldb_module_oom(ldb_module);
154 /* write serialized schemaInfo into LDB */
155 ldb_err = dsdb_schema_info_write_prepare(ldb_module_get_ctx(ldb_module),
156 schema_info_blob,
157 temp_ctx, &msg);
158 if (ldb_err != LDB_SUCCESS) {
159 talloc_free(temp_ctx);
160 return ldb_err;
164 ldb_err = dsdb_module_modify(ldb_module, msg, dsdb_flags, parent);
166 talloc_free(temp_ctx);
168 if (ldb_err != LDB_SUCCESS) {
169 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
170 "dsdb_module_schema_info_blob_write: dsdb_replace failed: %s (%s)\n",
171 ldb_strerror(ldb_err),
172 ldb_errstring(ldb_module_get_ctx(ldb_module)));
173 return ldb_err;
176 return LDB_SUCCESS;
181 * Reads schema_info structure from schemaInfo
182 * attribute on SCHEMA partition
184 static int dsdb_module_schema_info_read(struct ldb_module *ldb_module,
185 uint32_t dsdb_flags,
186 TALLOC_CTX *mem_ctx,
187 struct dsdb_schema_info **_schema_info,
188 struct ldb_request *parent)
190 int ret;
191 DATA_BLOB ndr_blob;
192 TALLOC_CTX *temp_ctx;
193 WERROR werr;
195 temp_ctx = talloc_new(mem_ctx);
196 if (temp_ctx == NULL) {
197 return ldb_module_oom(ldb_module);
200 /* read serialized schemaInfo from LDB */
201 ret = dsdb_module_schema_info_blob_read(ldb_module, dsdb_flags, temp_ctx, &ndr_blob, parent);
202 if (ret != LDB_SUCCESS) {
203 talloc_free(temp_ctx);
204 return ret;
207 /* convert NDR blob to dsdb_schema_info object */
208 werr = dsdb_schema_info_from_blob(&ndr_blob,
209 mem_ctx,
210 _schema_info);
211 talloc_free(temp_ctx);
213 if (W_ERROR_EQUAL(werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE)) {
214 return LDB_ERR_NO_SUCH_ATTRIBUTE;
217 if (!W_ERROR_IS_OK(werr)) {
218 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
219 return ldb_operr(ldb_module_get_ctx(ldb_module));
222 return LDB_SUCCESS;
226 * Writes schema_info structure into schemaInfo
227 * attribute on SCHEMA partition
229 * @param dsdb_flags DSDB_FLAG_... flag of 0
231 static int dsdb_module_schema_info_write(struct ldb_module *ldb_module,
232 uint32_t dsdb_flags,
233 const struct dsdb_schema_info *schema_info,
234 struct ldb_request *parent)
236 WERROR werr;
237 int ret;
238 DATA_BLOB ndr_blob;
239 TALLOC_CTX *temp_ctx;
241 temp_ctx = talloc_new(ldb_module);
242 if (temp_ctx == NULL) {
243 return ldb_module_oom(temp_ctx);
246 /* convert schema_info to a blob */
247 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
248 if (!W_ERROR_IS_OK(werr)) {
249 talloc_free(temp_ctx);
250 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
251 return ldb_operr(ldb_module_get_ctx(ldb_module));
254 /* write serialized schemaInfo into LDB */
255 ret = dsdb_module_schema_info_blob_write(ldb_module, dsdb_flags, &ndr_blob, parent);
257 talloc_free(temp_ctx);
259 return ret;
264 * Increments schemaInfo revision and save it to DB
265 * setting our invocationID in the process
266 * NOTE: this function should be called in a transaction
267 * much in the same way prefixMap update function is called
269 * @param ldb_module current module
270 * @param schema schema cache
271 * @param dsdb_flags DSDB_FLAG_... flag of 0
273 int dsdb_module_schema_info_update(struct ldb_module *ldb_module,
274 struct dsdb_schema *schema,
275 int dsdb_flags, struct ldb_request *parent)
277 int ret;
278 const struct GUID *invocation_id;
279 DATA_BLOB ndr_blob;
280 struct dsdb_schema_info *schema_info;
281 const char *schema_info_str;
282 WERROR werr;
283 TALLOC_CTX *temp_ctx = talloc_new(schema);
284 if (temp_ctx == NULL) {
285 return ldb_module_oom(ldb_module);
288 invocation_id = samdb_ntds_invocation_id(ldb_module_get_ctx(ldb_module));
289 if (!invocation_id) {
290 talloc_free(temp_ctx);
291 return ldb_operr(ldb_module_get_ctx(ldb_module));
294 /* read serialized schemaInfo from LDB */
295 ret = dsdb_module_schema_info_read(ldb_module, dsdb_flags, temp_ctx, &schema_info, parent);
296 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
297 /* make default value in case
298 * we have no schemaInfo value yet */
299 werr = dsdb_schema_info_new(temp_ctx, &schema_info);
300 if (!W_ERROR_IS_OK(werr)) {
301 talloc_free(temp_ctx);
302 return ldb_module_oom(ldb_module);
304 ret = LDB_SUCCESS;
306 if (ret != LDB_SUCCESS) {
307 talloc_free(temp_ctx);
308 return ret;
311 /* update schemaInfo */
312 schema_info->revision++;
313 schema_info->invocation_id = *invocation_id;
315 ret = dsdb_module_schema_info_write(ldb_module, dsdb_flags, schema_info, parent);
316 if (ret != LDB_SUCCESS) {
317 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
318 "dsdb_module_schema_info_update: failed to save schemaInfo - %s\n",
319 ldb_strerror(ret));
320 talloc_free(temp_ctx);
321 return ret;
324 /* finally, update schema_info in the cache */
325 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
326 if (!W_ERROR_IS_OK(werr)) {
327 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), "Failed to get schema info");
328 talloc_free(temp_ctx);
329 return ldb_operr(ldb_module_get_ctx(ldb_module));
332 schema_info_str = hex_encode_talloc(schema, ndr_blob.data, ndr_blob.length);
333 if (!schema_info_str) {
334 talloc_free(temp_ctx);
335 return ldb_module_oom(ldb_module);
338 talloc_unlink(schema, discard_const(schema->schema_info));
339 schema->schema_info = schema_info_str;
341 talloc_free(temp_ctx);
342 return LDB_SUCCESS;