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 DEBUG(0,("dsdb_module_schema_info_blob_read: no schemaInfo attribute found\n"));
74 talloc_free(schema_res);
75 return ldb_operr(ldb_module_get_ctx(ldb_module));
78 /* transfer .data ownership to mem_ctx */
79 schema_info_blob->length = blob_val->length;
80 schema_info_blob->data = talloc_steal(mem_ctx, blob_val->data);
82 talloc_free(schema_res);
88 * Prepares ldb_msg to be used for updating schemaInfo value in DB
90 static int dsdb_schema_info_write_prepare(struct ldb_context *ldb,
91 struct ldb_val *schema_info_blob,
93 struct ldb_message **_msg)
96 struct ldb_message *msg;
97 struct ldb_dn *schema_dn;
98 struct ldb_message_element *return_el;
100 schema_dn = ldb_get_schema_basedn(ldb);
102 DEBUG(0,("dsdb_schema_info_write_prepare: no schema dn present\n"));
103 return ldb_operr(ldb);
106 /* prepare ldb_msg to update schemaInfo */
107 msg = ldb_msg_new(mem_ctx);
113 ldb_err = ldb_msg_add_value(msg, "schemaInfo", schema_info_blob, &return_el);
115 ldb_asprintf_errstring(ldb, "dsdb_schema_info_write_prepare: ldb_msg_add_value failed - %s\n",
116 ldb_strerror(ldb_err));
121 /* mark schemaInfo element for replacement */
122 return_el->flags = LDB_FLAG_MOD_REPLACE;
132 * Writes schema_info structure into schemaInfo
133 * attribute on SCHEMA partition
135 * @param dsdb_flags DSDB_FLAG_... flag of 0
137 int dsdb_module_schema_info_blob_write(struct ldb_module *ldb_module,
139 struct ldb_val *schema_info_blob)
142 struct ldb_message *msg;
143 TALLOC_CTX *temp_ctx;
145 temp_ctx = talloc_new(ldb_module);
146 if (temp_ctx == NULL) {
147 return ldb_module_oom(ldb_module);
150 /* write serialized schemaInfo into LDB */
151 ldb_err = dsdb_schema_info_write_prepare(ldb_module_get_ctx(ldb_module),
154 if (ldb_err != LDB_SUCCESS) {
155 talloc_free(temp_ctx);
160 ldb_err = dsdb_module_modify(ldb_module, msg, dsdb_flags);
162 talloc_free(temp_ctx);
164 if (ldb_err != LDB_SUCCESS) {
165 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
166 "dsdb_module_schema_info_blob_write: dsdb_replace failed: %s (%s)\n",
167 ldb_strerror(ldb_err),
168 ldb_errstring(ldb_module_get_ctx(ldb_module)));
177 * Reads schema_info structure from schemaInfo
178 * attribute on SCHEMA partition
180 static int dsdb_module_schema_info_read(struct ldb_module *ldb_module,
183 struct dsdb_schema_info **_schema_info)
187 TALLOC_CTX *temp_ctx;
190 temp_ctx = talloc_new(mem_ctx);
191 if (temp_ctx == NULL) {
192 return ldb_module_oom(ldb_module);
195 /* read serialized schemaInfo from LDB */
196 ret = dsdb_module_schema_info_blob_read(ldb_module, dsdb_flags, temp_ctx, &ndr_blob);
197 if (ret != LDB_SUCCESS) {
198 talloc_free(temp_ctx);
202 /* convert NDR blob to dsdb_schema_info object */
203 werr = dsdb_schema_info_from_blob(&ndr_blob,
206 talloc_free(temp_ctx);
208 if (W_ERROR_EQUAL(werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE)) {
209 return LDB_ERR_NO_SUCH_ATTRIBUTE;
212 if (!W_ERROR_IS_OK(werr)) {
213 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
214 return ldb_operr(ldb_module_get_ctx(ldb_module));
221 * Writes schema_info structure into schemaInfo
222 * attribute on SCHEMA partition
224 * @param dsdb_flags DSDB_FLAG_... flag of 0
226 static int dsdb_module_schema_info_write(struct ldb_module *ldb_module,
228 const struct dsdb_schema_info *schema_info)
233 TALLOC_CTX *temp_ctx;
235 temp_ctx = talloc_new(ldb_module);
236 if (temp_ctx == NULL) {
237 return ldb_module_oom(temp_ctx);
240 /* convert schema_info to a blob */
241 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
242 if (!W_ERROR_IS_OK(werr)) {
243 talloc_free(temp_ctx);
244 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
245 return ldb_operr(ldb_module_get_ctx(ldb_module));
248 /* write serialized schemaInfo into LDB */
249 ret = dsdb_module_schema_info_blob_write(ldb_module, dsdb_flags, &ndr_blob);
251 talloc_free(temp_ctx);
258 * Increments schemaInfo revision and save it to DB
259 * setting our invocationID in the process
260 * NOTE: this function should be called in a transaction
261 * much in the same way prefixMap update function is called
263 * @param ldb_module current module
264 * @param schema schema cache
265 * @param dsdb_flags DSDB_FLAG_... flag of 0
267 int dsdb_module_schema_info_update(struct ldb_module *ldb_module,
268 struct dsdb_schema *schema,
272 const struct GUID *invocation_id;
274 struct dsdb_schema_info *schema_info;
275 const char *schema_info_str;
277 TALLOC_CTX *temp_ctx = talloc_new(schema);
278 if (temp_ctx == NULL) {
279 return ldb_module_oom(ldb_module);
282 invocation_id = samdb_ntds_invocation_id(ldb_module_get_ctx(ldb_module));
283 if (!invocation_id) {
284 talloc_free(temp_ctx);
285 return ldb_operr(ldb_module_get_ctx(ldb_module));
288 /* read serialized schemaInfo from LDB */
289 ret = dsdb_module_schema_info_read(ldb_module, dsdb_flags, temp_ctx, &schema_info);
290 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
291 /* make default value in case
292 * we have no schemaInfo value yet */
293 werr = dsdb_schema_info_new(temp_ctx, &schema_info);
294 if (!W_ERROR_IS_OK(werr)) {
295 talloc_free(temp_ctx);
296 return ldb_module_oom(ldb_module);
300 if (ret != LDB_SUCCESS) {
301 talloc_free(temp_ctx);
305 /* update schemaInfo */
306 schema_info->revision++;
307 schema_info->invocation_id = *invocation_id;
309 ret = dsdb_module_schema_info_write(ldb_module, dsdb_flags, schema_info);
310 if (ret != LDB_SUCCESS) {
311 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
312 "dsdb_module_schema_info_update: failed to save schemaInfo - %s\n",
314 talloc_free(temp_ctx);
318 /* finally, update schema_info in the cache */
319 werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
320 if (!W_ERROR_IS_OK(werr)) {
321 ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), "Failed to get schema info");
322 talloc_free(temp_ctx);
323 return ldb_operr(ldb_module_get_ctx(ldb_module));
326 schema_info_str = hex_encode_talloc(schema, ndr_blob.data, ndr_blob.length);
327 if (!schema_info_str) {
328 talloc_free(temp_ctx);
329 return ldb_module_oom(ldb_module);
332 talloc_unlink(schema, discard_const(schema->schema_info));
333 schema->schema_info = schema_info_str;
335 talloc_free(temp_ctx);