s4/dsdb: remove unused dsdb_schema_info_create() function
[metze/samba/wip.git] / source4 / dsdb / schema / schema_info_attr.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    SCHEMA::schemaInfo implementation
5
6    Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
7
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.
12
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.
17
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/>.
20 */
21
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"
30
31
32 /**
33  * Creates and initializes new dsdb_schema_info value.
34  * Initial schemaInfo values is with:
35  *   revision = 0
36  *   invocationId = GUID_ZERO
37  */
38 WERROR dsdb_schema_info_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_info **_schema_info)
39 {
40         struct dsdb_schema_info *schema_info;
41
42         schema_info = talloc_zero(mem_ctx, struct dsdb_schema_info);
43         W_ERROR_HAVE_NO_MEMORY(schema_info);
44
45         *_schema_info = schema_info;
46
47         return WERR_OK;
48 }
49
50 /**
51  * Creates and initializes new dsdb_schema_info blob value.
52  * Initial schemaInfo values is with:
53  *   revision = 0
54  *   invocationId = GUID_ZERO
55  */
56 WERROR dsdb_schema_info_blob_new(TALLOC_CTX *mem_ctx, DATA_BLOB *_schema_info_blob)
57 {
58         DATA_BLOB blob;
59
60         blob = data_blob_talloc_zero(mem_ctx, 21);
61         W_ERROR_HAVE_NO_MEMORY(blob.data);
62
63         /* Set the schemaInfo marker to 0xFF */
64         blob.data[0] = 0xFF;
65
66         *_schema_info_blob = blob;
67
68         return WERR_OK;
69 }
70
71
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
77  */
78 WERROR dsdb_schema_info_from_blob(const DATA_BLOB *blob,
79                                   TALLOC_CTX *mem_ctx, struct dsdb_schema_info **_schema_info)
80 {
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;
85
86         if (!blob || !blob->data) {
87                 return WERR_INVALID_PARAMETER;
88         }
89
90         if (blob->length != 21) {
91                 return WERR_INVALID_PARAMETER;
92         }
93
94         /* schemaInfo blob should start with 0xFF */
95         if (blob->data[0] != 0xFF) {
96                 return WERR_INVALID_PARAMETER;
97         }
98
99         temp_ctx = talloc_new(mem_ctx);
100         W_ERROR_HAVE_NO_MEMORY(temp_ctx);
101
102         ndr_err = ndr_pull_struct_blob_all(blob, temp_ctx,
103                                            lp_iconv_convenience(NULL), &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);
109         }
110
111         schema_info = talloc(mem_ctx, struct dsdb_schema_info);
112         if (!schema_info) {
113                 talloc_free(temp_ctx);
114                 return WERR_NOMEM;
115         }
116
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;
122
123         talloc_free(temp_ctx);
124         return WERR_OK;
125 }
126
127 /**
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
131  */
132 WERROR dsdb_blob_from_schema_info(const struct dsdb_schema_info *schema_info,
133                                   TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
134 {
135         enum ndr_err_code ndr_err;
136         struct schemaInfoBlob schema_info_blob;
137
138         if (schema_info->revision < 1) {
139                 return WERR_INVALID_PARAMETER;
140         }
141
142         schema_info_blob.marker         = 0xFF;
143         schema_info_blob.revision       = schema_info->revision;
144         schema_info_blob.invocation_id  = schema_info->invocation_id;
145
146         ndr_err = ndr_push_struct_blob(blob, mem_ctx,
147                                        lp_iconv_convenience(NULL), &schema_info_blob,
148                                        (ndr_push_flags_fn_t)ndr_push_schemaInfoBlob);
149         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
150                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
151                 return ntstatus_to_werror(nt_status);
152         }
153
154         return WERR_OK;
155 }
156
157
158 /**
159  * Reads schema_info structure from schemaInfo
160  * attribute on SCHEMA partition
161  *
162  * @param dsdb_flags    DSDB_FLAG_... flag of 0
163  */
164 WERROR dsdb_module_schema_info_blob_read(struct ldb_module *ldb_module,
165                                          uint32_t dsdb_flags,
166                                          TALLOC_CTX *mem_ctx, DATA_BLOB *schema_info_blob)
167 {
168         int ldb_err;
169         const struct ldb_val *blob_val;
170         struct ldb_dn *schema_dn;
171         struct ldb_result *schema_res = NULL;
172         static const char *schema_attrs[] = {
173                 "schemaInfo",
174                 NULL
175         };
176
177         schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ldb_module));
178         if (!schema_dn) {
179                 DEBUG(0,("dsdb_module_schema_info_blob_read: no schema dn present!\n"));
180                 return WERR_INTERNAL_DB_CORRUPTION;
181         }
182
183         ldb_err = dsdb_module_search(ldb_module, mem_ctx, &schema_res, schema_dn,
184                                      LDB_SCOPE_BASE, schema_attrs, dsdb_flags, NULL);
185         if (ldb_err == LDB_ERR_NO_SUCH_OBJECT) {
186                 DEBUG(0,("dsdb_module_schema_info_blob_read: Schema DN not found!\n"));
187                 talloc_free(schema_res);
188                 return WERR_INTERNAL_DB_CORRUPTION;
189         } else if (ldb_err != LDB_SUCCESS) {
190                 DEBUG(0,("dsdb_module_schema_info_blob_read: failed to find schemaInfo attribute\n"));
191                 talloc_free(schema_res);
192                 return WERR_INTERNAL_DB_CORRUPTION;
193         }
194
195         blob_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
196         if (!blob_val) {
197                 DEBUG(0,("dsdb_module_schema_info_blob_read: no schemaInfo attribute found\n"));
198                 talloc_free(schema_res);
199                 return WERR_DS_NO_ATTRIBUTE_OR_VALUE;
200         }
201
202         /* transfer .data ownership to mem_ctx */
203         schema_info_blob->length = blob_val->length;
204         schema_info_blob->data = talloc_steal(mem_ctx, blob_val->data);
205
206         talloc_free(schema_res);
207
208         return WERR_OK;
209 }
210
211 /**
212  * Pepares ldb_msg to be used for updating schemaInfo value in DB
213  */
214 static WERROR _dsdb_schema_info_write_prepare(struct ldb_context *ldb,
215                                               DATA_BLOB *schema_info_blob,
216                                               TALLOC_CTX *mem_ctx,
217                                               struct ldb_message **_msg)
218 {
219         int ldb_err;
220         struct ldb_message *msg;
221         struct ldb_dn *schema_dn;
222         struct ldb_message_element *return_el;
223
224         schema_dn = ldb_get_schema_basedn(ldb);
225         if (!schema_dn) {
226                 DEBUG(0,("_dsdb_schema_info_write_prepare: no schema dn present\n"));
227                 return WERR_INTERNAL_DB_CORRUPTION;
228         }
229
230         /* prepare ldb_msg to update schemaInfo */
231         msg = ldb_msg_new(mem_ctx);
232         W_ERROR_HAVE_NO_MEMORY(msg);
233
234         msg->dn = schema_dn;
235         ldb_err = ldb_msg_add_value(msg, "schemaInfo", schema_info_blob, &return_el);
236         if (ldb_err != 0) {
237                 DEBUG(0,("_dsdb_schema_info_write_prepare: ldb_msg_add_value failed - %s\n",
238                          ldb_strerror(ldb_err)));
239                 talloc_free(msg);
240                 return WERR_INTERNAL_ERROR;
241         }
242
243         /* mark schemaInfo element for replacement */
244         return_el->flags = LDB_FLAG_MOD_REPLACE;
245
246         *_msg = msg;
247
248         return WERR_OK;
249 }
250
251 /**
252  * Writes schema_info structure into schemaInfo
253  * attribute on SCHEMA partition
254  *
255  * @param dsdb_flags    DSDB_FLAG_... flag of 0
256  */
257 WERROR dsdb_module_schema_info_blob_write(struct ldb_module *ldb_module,
258                                           uint32_t dsdb_flags,
259                                           DATA_BLOB *schema_info_blob)
260 {
261         int ldb_err;
262         WERROR werr;
263         struct ldb_message *msg;
264         TALLOC_CTX *temp_ctx;
265
266         temp_ctx = talloc_new(ldb_module);
267         W_ERROR_HAVE_NO_MEMORY(temp_ctx);
268
269         /* write serialized schemaInfo into LDB */
270         werr = _dsdb_schema_info_write_prepare(ldb_module_get_ctx(ldb_module),
271                                                schema_info_blob,
272                                                temp_ctx, &msg);
273         if (!W_ERROR_IS_OK(werr)) {
274                 talloc_free(temp_ctx);
275                 return werr;
276         }
277
278
279         ldb_err = dsdb_module_modify(ldb_module, msg, dsdb_flags);
280
281         talloc_free(temp_ctx);
282
283         if (ldb_err != 0) {
284                 DEBUG(0,("dsdb_module_schema_info_blob_write: dsdb_replace failed: %s (%s)\n",
285                          ldb_strerror(ldb_err),
286                          ldb_errstring(ldb_module_get_ctx(ldb_module))));
287                 return WERR_INTERNAL_DB_ERROR;
288         }
289
290         return WERR_OK;
291 }
292
293
294 /**
295  * Reads schema_info structure from schemaInfo
296  * attribute on SCHEMA partition
297  */
298 static WERROR dsdb_module_schema_info_read(struct ldb_module *ldb_module,
299                                            uint32_t dsdb_flags,
300                                            TALLOC_CTX *mem_ctx,
301                                            struct dsdb_schema_info **_schema_info)
302 {
303         WERROR werr;
304         DATA_BLOB ndr_blob;
305         TALLOC_CTX *temp_ctx;
306
307         temp_ctx = talloc_new(mem_ctx);
308         W_ERROR_HAVE_NO_MEMORY(temp_ctx);
309
310         /* read serialized schemaInfo from LDB  */
311         werr = dsdb_module_schema_info_blob_read(ldb_module, dsdb_flags, temp_ctx, &ndr_blob);
312         if (!W_ERROR_IS_OK(werr)) {
313                 talloc_free(temp_ctx);
314                 return werr;
315         }
316
317         /* convert NDR blob to dsdb_schema_info object */
318         werr = dsdb_schema_info_from_blob(&ndr_blob,
319                                           mem_ctx,
320                                           _schema_info);
321         talloc_free(temp_ctx);
322
323         return werr;
324 }
325
326 /**
327  * Writes schema_info structure into schemaInfo
328  * attribute on SCHEMA partition
329  *
330  * @param dsdb_flags    DSDB_FLAG_... flag of 0
331  */
332 static WERROR dsdb_module_schema_info_write(struct ldb_module *ldb_module,
333                                             uint32_t dsdb_flags,
334                                             const struct dsdb_schema_info *schema_info)
335 {
336         WERROR werr;
337         DATA_BLOB ndr_blob;
338         TALLOC_CTX *temp_ctx;
339
340         temp_ctx = talloc_new(ldb_module);
341         W_ERROR_HAVE_NO_MEMORY(temp_ctx);
342
343         /* convert schema_info to a blob */
344         werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
345         if (!W_ERROR_IS_OK(werr)) {
346                 talloc_free(temp_ctx);
347                 return werr;
348         }
349
350         /* write serialized schemaInfo into LDB */
351         werr = dsdb_module_schema_info_blob_write(ldb_module, dsdb_flags, &ndr_blob);
352
353         talloc_free(temp_ctx);
354
355         return werr;
356 }
357
358
359 /**
360  * Increments schemaInfo revision and save it to DB
361  * setting our invocationID in the process
362  * NOTE: this function should be called in a transaction
363  * much in the same way prefixMap update function is called
364  *
365  * @param ldb_module    current module
366  * @param schema        schema cache
367  * @param dsdb_flags    DSDB_FLAG_... flag of 0
368  */
369 WERROR dsdb_module_schema_info_update(struct ldb_module *ldb_module,
370                                       struct dsdb_schema *schema,
371                                       int dsdb_flags)
372 {
373         WERROR werr;
374         const struct GUID *invocation_id;
375         DATA_BLOB ndr_blob;
376         struct dsdb_schema_info *schema_info;
377         const char *schema_info_str;
378
379         TALLOC_CTX *temp_ctx = talloc_new(schema);
380         W_ERROR_HAVE_NO_MEMORY(temp_ctx);
381
382         invocation_id = samdb_ntds_invocation_id(ldb_module_get_ctx(ldb_module));
383         if (!invocation_id) {
384                 return WERR_INTERNAL_DB_CORRUPTION;
385         }
386
387         /* read serialized schemaInfo from LDB  */
388         werr = dsdb_module_schema_info_read(ldb_module, dsdb_flags, temp_ctx, &schema_info);
389         if (W_ERROR_EQUAL(werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE)) {
390                 /* make default value in case
391                  * we have no schemaInfo value yet */
392                 werr = dsdb_schema_info_new(temp_ctx, &schema_info);
393         }
394         if (!W_ERROR_IS_OK(werr)) {
395                 DEBUG(0,("dsdb_module_schema_info_update: failed to reload schemaInfo - %s\n",
396                          win_errstr(werr)));
397                 talloc_free(temp_ctx);
398                 return werr;
399         }
400
401         /* update schemaInfo */
402         schema_info->revision++;
403         schema_info->invocation_id = *invocation_id;
404
405         werr = dsdb_module_schema_info_write(ldb_module, dsdb_flags, schema_info);
406         if (!W_ERROR_IS_OK(werr)) {
407                 DEBUG(0,("dsdb_module_schema_info_update: failed to save schemaInfo - %s\n",
408                          win_errstr(werr)));
409                 talloc_free(temp_ctx);
410                 return werr;
411         }
412
413         /* finally, update schema_info in the cache */
414         werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
415         W_ERROR_NOT_OK_RETURN(werr);
416
417         schema_info_str = hex_encode_talloc(schema, ndr_blob.data, ndr_blob.length);
418         W_ERROR_HAVE_NO_MEMORY(schema_info_str);
419
420         talloc_unlink(schema, discard_const(schema->schema_info));
421         schema->schema_info = schema_info_str;
422
423         talloc_free(temp_ctx);
424         return WERR_OK;
425 }