s4-configure: Fix typo in comment.
[Samba/gbeck.git] / source4 / dsdb / schema / schema_info_attr.c
bloba9c5e932a1e800e3ca290f1da2a56816278fd5fc
1 /*
2 Unix SMB/CIFS implementation.
4 SCHEMA::schemaInfo implementation
6 Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "dsdb/common/util.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "dsdb/samdb/ldb_modules/util.h"
26 #include "lib/ldb/include/ldb_module.h"
27 #include "librpc/gen_ndr/ndr_drsuapi.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "param/param.h"
32 /**
33 * Creates and initializes new dsdb_schema_info value.
34 * Initial schemaInfo values is with:
35 * revision = 0
36 * invocationId = GUID_ZERO
38 WERROR dsdb_schema_info_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_info **_schema_info)
40 struct dsdb_schema_info *schema_info;
42 schema_info = talloc_zero(mem_ctx, struct dsdb_schema_info);
43 W_ERROR_HAVE_NO_MEMORY(schema_info);
45 *_schema_info = schema_info;
47 return WERR_OK;
50 /**
51 * Creates and initializes new dsdb_schema_info blob value.
52 * Initial schemaInfo values is with:
53 * revision = 0
54 * invocationId = GUID_ZERO
56 WERROR dsdb_schema_info_blob_new(TALLOC_CTX *mem_ctx, DATA_BLOB *_schema_info_blob)
58 DATA_BLOB blob;
60 blob = data_blob_talloc_zero(mem_ctx, 21);
61 W_ERROR_HAVE_NO_MEMORY(blob.data);
63 /* Set the schemaInfo marker to 0xFF */
64 blob.data[0] = 0xFF;
66 *_schema_info_blob = blob;
68 return WERR_OK;
72 /**
73 * Parse schemaInfo structure from a data_blob
74 * (DATA_BLOB or ldb_val).
75 * Suitable for parsing blobs that comes from
76 * DRS interface of from LDB database
78 WERROR dsdb_schema_info_from_blob(const DATA_BLOB *blob,
79 TALLOC_CTX *mem_ctx, struct dsdb_schema_info **_schema_info)
81 TALLOC_CTX *temp_ctx;
82 enum ndr_err_code ndr_err;
83 struct dsdb_schema_info *schema_info;
84 struct schemaInfoBlob schema_info_blob;
86 if (!blob || !blob->data) {
87 return WERR_INVALID_PARAMETER;
90 if (blob->length != 21) {
91 return WERR_INVALID_PARAMETER;
94 /* schemaInfo blob should start with 0xFF */
95 if (blob->data[0] != 0xFF) {
96 return WERR_INVALID_PARAMETER;
99 temp_ctx = talloc_new(mem_ctx);
100 W_ERROR_HAVE_NO_MEMORY(temp_ctx);
102 ndr_err = ndr_pull_struct_blob_all(blob, temp_ctx,
103 &schema_info_blob,
104 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob);
105 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
106 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
107 talloc_free(temp_ctx);
108 return ntstatus_to_werror(nt_status);
111 schema_info = talloc(mem_ctx, struct dsdb_schema_info);
112 if (!schema_info) {
113 talloc_free(temp_ctx);
114 return WERR_NOMEM;
117 /* note that we accept revision numbers of zero now - w2k8r2
118 sends a revision of zero on initial vampire */
119 schema_info->revision = schema_info_blob.revision;
120 schema_info->invocation_id = schema_info_blob.invocation_id;
121 *_schema_info = schema_info;
123 talloc_free(temp_ctx);
124 return WERR_OK;
128 * Creates a blob from schemaInfo structure
129 * Suitable for packing schemaInfo into a blob
130 * which is to be used in DRS interface of LDB database
132 WERROR dsdb_blob_from_schema_info(const struct dsdb_schema_info *schema_info,
133 TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
135 enum ndr_err_code ndr_err;
136 struct schemaInfoBlob schema_info_blob;
138 schema_info_blob.marker = 0xFF;
139 schema_info_blob.revision = schema_info->revision;
140 schema_info_blob.invocation_id = schema_info->invocation_id;
142 ndr_err = ndr_push_struct_blob(blob, mem_ctx,
143 &schema_info_blob,
144 (ndr_push_flags_fn_t)ndr_push_schemaInfoBlob);
145 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
146 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
147 return ntstatus_to_werror(nt_status);
150 return WERR_OK;
155 * Reads schema_info structure from schemaInfo
156 * attribute on SCHEMA partition
158 * @param dsdb_flags DSDB_FLAG_... flag of 0
160 WERROR dsdb_module_schema_info_blob_read(struct ldb_module *ldb_module,
161 uint32_t dsdb_flags,
162 TALLOC_CTX *mem_ctx, DATA_BLOB *schema_info_blob)
164 int ldb_err;
165 const struct ldb_val *blob_val;
166 struct ldb_dn *schema_dn;
167 struct ldb_result *schema_res = NULL;
168 static const char *schema_attrs[] = {
169 "schemaInfo",
170 NULL
173 schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ldb_module));
174 if (!schema_dn) {
175 DEBUG(0,("dsdb_module_schema_info_blob_read: no schema dn present!\n"));
176 return WERR_INTERNAL_DB_CORRUPTION;
179 ldb_err = dsdb_module_search(ldb_module, mem_ctx, &schema_res, schema_dn,
180 LDB_SCOPE_BASE, schema_attrs, dsdb_flags, NULL);
181 if (ldb_err == LDB_ERR_NO_SUCH_OBJECT) {
182 DEBUG(0,("dsdb_module_schema_info_blob_read: Schema DN not found!\n"));
183 talloc_free(schema_res);
184 return WERR_INTERNAL_DB_CORRUPTION;
185 } else if (ldb_err != LDB_SUCCESS) {
186 DEBUG(0,("dsdb_module_schema_info_blob_read: failed to find schemaInfo attribute\n"));
187 talloc_free(schema_res);
188 return WERR_INTERNAL_DB_CORRUPTION;
191 blob_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
192 if (!blob_val) {
193 DEBUG(0,("dsdb_module_schema_info_blob_read: no schemaInfo attribute found\n"));
194 talloc_free(schema_res);
195 return WERR_DS_NO_ATTRIBUTE_OR_VALUE;
198 /* transfer .data ownership to mem_ctx */
199 schema_info_blob->length = blob_val->length;
200 schema_info_blob->data = talloc_steal(mem_ctx, blob_val->data);
202 talloc_free(schema_res);
204 return WERR_OK;
208 * Prepares ldb_msg to be used for updating schemaInfo value in DB
210 static WERROR _dsdb_schema_info_write_prepare(struct ldb_context *ldb,
211 DATA_BLOB *schema_info_blob,
212 TALLOC_CTX *mem_ctx,
213 struct ldb_message **_msg)
215 int ldb_err;
216 struct ldb_message *msg;
217 struct ldb_dn *schema_dn;
218 struct ldb_message_element *return_el;
220 schema_dn = ldb_get_schema_basedn(ldb);
221 if (!schema_dn) {
222 DEBUG(0,("_dsdb_schema_info_write_prepare: no schema dn present\n"));
223 return WERR_INTERNAL_DB_CORRUPTION;
226 /* prepare ldb_msg to update schemaInfo */
227 msg = ldb_msg_new(mem_ctx);
228 W_ERROR_HAVE_NO_MEMORY(msg);
230 msg->dn = schema_dn;
231 ldb_err = ldb_msg_add_value(msg, "schemaInfo", schema_info_blob, &return_el);
232 if (ldb_err != 0) {
233 DEBUG(0,("_dsdb_schema_info_write_prepare: ldb_msg_add_value failed - %s\n",
234 ldb_strerror(ldb_err)));
235 talloc_free(msg);
236 return WERR_INTERNAL_ERROR;
239 /* mark schemaInfo element for replacement */
240 return_el->flags = LDB_FLAG_MOD_REPLACE;
242 *_msg = msg;
244 return WERR_OK;
248 * Writes schema_info structure into schemaInfo
249 * attribute on SCHEMA partition
251 * @param dsdb_flags DSDB_FLAG_... flag of 0
253 WERROR dsdb_module_schema_info_blob_write(struct ldb_module *ldb_module,
254 uint32_t dsdb_flags,
255 DATA_BLOB *schema_info_blob)
257 int ldb_err;
258 WERROR werr;
259 struct ldb_message *msg;
260 TALLOC_CTX *temp_ctx;
262 temp_ctx = talloc_new(ldb_module);
263 W_ERROR_HAVE_NO_MEMORY(temp_ctx);
265 /* write serialized schemaInfo into LDB */
266 werr = _dsdb_schema_info_write_prepare(ldb_module_get_ctx(ldb_module),
267 schema_info_blob,
268 temp_ctx, &msg);
269 if (!W_ERROR_IS_OK(werr)) {
270 talloc_free(temp_ctx);
271 return werr;
275 ldb_err = dsdb_module_modify(ldb_module, msg, dsdb_flags);
277 talloc_free(temp_ctx);
279 if (ldb_err != 0) {
280 DEBUG(0,("dsdb_module_schema_info_blob_write: dsdb_replace failed: %s (%s)\n",
281 ldb_strerror(ldb_err),
282 ldb_errstring(ldb_module_get_ctx(ldb_module))));
283 return WERR_INTERNAL_DB_ERROR;
286 return WERR_OK;
291 * Reads schema_info structure from schemaInfo
292 * attribute on SCHEMA partition
294 static WERROR dsdb_module_schema_info_read(struct ldb_module *ldb_module,
295 uint32_t dsdb_flags,
296 TALLOC_CTX *mem_ctx,
297 struct dsdb_schema_info **_schema_info)
299 WERROR werr;
300 DATA_BLOB ndr_blob;
301 TALLOC_CTX *temp_ctx;
303 temp_ctx = talloc_new(mem_ctx);
304 W_ERROR_HAVE_NO_MEMORY(temp_ctx);
306 /* read serialized schemaInfo from LDB */
307 werr = dsdb_module_schema_info_blob_read(ldb_module, dsdb_flags, temp_ctx, &ndr_blob);
308 if (!W_ERROR_IS_OK(werr)) {
309 talloc_free(temp_ctx);
310 return werr;
313 /* convert NDR blob to dsdb_schema_info object */
314 werr = dsdb_schema_info_from_blob(&ndr_blob,
315 mem_ctx,
316 _schema_info);
317 talloc_free(temp_ctx);
319 return werr;
323 * Writes schema_info structure into schemaInfo
324 * attribute on SCHEMA partition
326 * @param dsdb_flags DSDB_FLAG_... flag of 0
328 static WERROR dsdb_module_schema_info_write(struct ldb_module *ldb_module,
329 uint32_t dsdb_flags,
330 const struct dsdb_schema_info *schema_info)
332 WERROR werr;
333 DATA_BLOB ndr_blob;
334 TALLOC_CTX *temp_ctx;
336 temp_ctx = talloc_new(ldb_module);
337 W_ERROR_HAVE_NO_MEMORY(temp_ctx);
339 /* convert schema_info to a blob */
340 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
341 if (!W_ERROR_IS_OK(werr)) {
342 talloc_free(temp_ctx);
343 return werr;
346 /* write serialized schemaInfo into LDB */
347 werr = dsdb_module_schema_info_blob_write(ldb_module, dsdb_flags, &ndr_blob);
349 talloc_free(temp_ctx);
351 return werr;
356 * Increments schemaInfo revision and save it to DB
357 * setting our invocationID in the process
358 * NOTE: this function should be called in a transaction
359 * much in the same way prefixMap update function is called
361 * @param ldb_module current module
362 * @param schema schema cache
363 * @param dsdb_flags DSDB_FLAG_... flag of 0
365 WERROR dsdb_module_schema_info_update(struct ldb_module *ldb_module,
366 struct dsdb_schema *schema,
367 int dsdb_flags)
369 WERROR werr;
370 const struct GUID *invocation_id;
371 DATA_BLOB ndr_blob;
372 struct dsdb_schema_info *schema_info;
373 const char *schema_info_str;
375 TALLOC_CTX *temp_ctx = talloc_new(schema);
376 W_ERROR_HAVE_NO_MEMORY(temp_ctx);
378 invocation_id = samdb_ntds_invocation_id(ldb_module_get_ctx(ldb_module));
379 if (!invocation_id) {
380 return WERR_INTERNAL_DB_CORRUPTION;
383 /* read serialized schemaInfo from LDB */
384 werr = dsdb_module_schema_info_read(ldb_module, dsdb_flags, temp_ctx, &schema_info);
385 if (W_ERROR_EQUAL(werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE)) {
386 /* make default value in case
387 * we have no schemaInfo value yet */
388 werr = dsdb_schema_info_new(temp_ctx, &schema_info);
390 if (!W_ERROR_IS_OK(werr)) {
391 DEBUG(0,("dsdb_module_schema_info_update: failed to reload schemaInfo - %s\n",
392 win_errstr(werr)));
393 talloc_free(temp_ctx);
394 return werr;
397 /* update schemaInfo */
398 schema_info->revision++;
399 schema_info->invocation_id = *invocation_id;
401 werr = dsdb_module_schema_info_write(ldb_module, dsdb_flags, schema_info);
402 if (!W_ERROR_IS_OK(werr)) {
403 DEBUG(0,("dsdb_module_schema_info_update: failed to save schemaInfo - %s\n",
404 win_errstr(werr)));
405 talloc_free(temp_ctx);
406 return werr;
409 /* finally, update schema_info in the cache */
410 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
411 W_ERROR_NOT_OK_RETURN(werr);
413 schema_info_str = hex_encode_talloc(schema, ndr_blob.data, ndr_blob.length);
414 W_ERROR_HAVE_NO_MEMORY(schema_info_str);
416 talloc_unlink(schema, discard_const(schema->schema_info));
417 schema->schema_info = schema_info_str;
419 talloc_free(temp_ctx);
420 return WERR_OK;