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 <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,
43
struct ldb_request *parent)
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[] = {
54
schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ldb_module));
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,
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);
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);
73
blob_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
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);
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,
96
struct ldb_message **_msg)
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);
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);
116
ldb_err = ldb_msg_add_value(msg, "schemaInfo", schema_info_blob, &return_el);
118
ldb_asprintf_errstring(ldb, "dsdb_schema_info_write_prepare: ldb_msg_add_value failed - %s\n",
119
ldb_strerror(ldb_err));
124
/* mark schemaInfo element for replacement */
125
return_el->flags = LDB_FLAG_MOD_REPLACE;
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,
142
struct ldb_val *schema_info_blob,
143
struct ldb_request *parent)
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),
158
if (ldb_err != LDB_SUCCESS) {
159
talloc_free(temp_ctx);
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)));
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,
187
struct dsdb_schema_info **_schema_info,
188
struct ldb_request *parent)
192
TALLOC_CTX *temp_ctx;
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);
207
/* convert NDR blob to dsdb_schema_info object */
208
werr = dsdb_schema_info_from_blob(&ndr_blob,
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));
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,
233
const struct dsdb_schema_info *schema_info,
234
struct ldb_request *parent)
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);
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)
278
const struct GUID *invocation_id;
280
struct dsdb_schema_info *schema_info;
281
const char *schema_info_str;
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);
306
if (ret != LDB_SUCCESS) {
307
talloc_free(temp_ctx);
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",
320
talloc_free(temp_ctx);
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);