s4:dsdb/schema_load: add a TODO about schema reloading
[amitay/samba.git] / source4 / dsdb / samdb / ldb_modules / schema_load.c
1 /* 
2    Unix SMB/CIFS mplementation.
3
4    The module that handles the Schema FSMO Role Owner
5    checkings, it also loads the dsdb_schema.
6    
7    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
9     
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.
14    
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.
19    
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/>.
22    
23 */
24
25 #include "includes.h"
26 #include "ldb_module.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "librpc/gen_ndr/ndr_drsuapi.h"
30 #include "librpc/gen_ndr/ndr_drsblobs.h"
31 #include "param/param.h"
32 #include "dsdb/samdb/ldb_modules/util.h"
33
34 /*
35   Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
36 */
37
38 static int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_module *module,
39                                       struct smb_iconv_convenience *iconv_convenience, 
40                                       struct ldb_dn *schema_dn,
41                                       struct dsdb_schema **schema) 
42 {
43         TALLOC_CTX *tmp_ctx;
44         char *error_string;
45         int ret;
46         struct ldb_context *ldb = ldb_module_get_ctx(module);
47         struct ldb_result *schema_res;
48         struct ldb_result *a_res;
49         struct ldb_result *c_res;
50         static const char *schema_attrs[] = {
51                 "prefixMap",
52                 "schemaInfo",
53                 "fSMORoleOwner",
54                 NULL
55         };
56         unsigned flags;
57
58         tmp_ctx = talloc_new(mem_ctx);
59         if (!tmp_ctx) {
60                 ldb_oom(ldb);
61                 return LDB_ERR_OPERATIONS_ERROR;
62         }
63
64         /* we don't want to trace the schema load */
65         flags = ldb_get_flags(ldb);
66         ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
67
68         /*
69          * setup the prefix mappings and schema info
70          */
71         ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
72                                     schema_dn, schema_attrs, 0);
73         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
74                 goto failed;
75         } else if (ret != LDB_SUCCESS) {
76                 ldb_asprintf_errstring(ldb, 
77                                        "dsdb_schema: failed to search the schema head: %s",
78                                        ldb_errstring(ldb));
79                 goto failed;
80         }
81
82         /*
83          * load the attribute definitions
84          */
85         ret = dsdb_module_search(module, tmp_ctx, &a_res,
86                                  schema_dn, LDB_SCOPE_ONELEVEL, NULL,
87                                  0, 
88                                  "(objectClass=attributeSchema)");
89         if (ret != LDB_SUCCESS) {
90                 ldb_asprintf_errstring(ldb, 
91                                        "dsdb_schema: failed to search attributeSchema objects: %s",
92                                        ldb_errstring(ldb));
93                 goto failed;
94         }
95
96         /*
97          * load the objectClass definitions
98          */
99         ret = dsdb_module_search(module, tmp_ctx, &c_res,
100                                  schema_dn, LDB_SCOPE_ONELEVEL, NULL,
101                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
102                                  "(objectClass=classSchema)");
103         if (ret != LDB_SUCCESS) {
104                 ldb_asprintf_errstring(ldb, 
105                                        "dsdb_schema: failed to search classSchema objects: %s",
106                                        ldb_errstring(ldb));
107                 goto failed;
108         }
109
110         ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
111                                            lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
112                                            schema_res, a_res, c_res, schema, &error_string);
113         if (ret != LDB_SUCCESS) {
114                 ldb_asprintf_errstring(ldb, 
115                                                     "dsdb_schema load failed: %s",
116                                                     error_string);
117                 goto failed;
118         }
119         talloc_steal(mem_ctx, *schema);
120
121 failed:
122         if (flags & LDB_FLG_ENABLE_TRACING) {
123                 flags = ldb_get_flags(ldb);
124                 ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
125         }
126         talloc_free(tmp_ctx);
127         return ret;
128 }       
129
130
131 static int schema_load_init(struct ldb_module *module)
132 {
133         struct ldb_context *ldb;
134         TALLOC_CTX *mem_ctx;
135         struct ldb_dn *schema_dn;
136         struct dsdb_schema *schema;
137         int ret;
138
139         ret = ldb_next_init(module);
140         if (ret != LDB_SUCCESS) {
141                 return ret;
142         }
143
144         ldb = ldb_module_get_ctx(module);
145         schema_dn = samdb_schema_dn(ldb);
146         if (!schema_dn) {
147                 ldb_reset_err_string(ldb);
148                 ldb_debug(ldb, LDB_DEBUG_WARNING,
149                           "schema_load_init: no schema dn present: (skip schema loading)\n");
150                 return LDB_SUCCESS;
151         }
152
153         if (dsdb_get_schema(ldb)) {
154                 return LDB_SUCCESS;
155         }
156
157         mem_ctx = talloc_new(module);
158         if (!mem_ctx) {
159                 ldb_oom(ldb);
160                 return LDB_ERR_OPERATIONS_ERROR;
161         }
162
163         ret = dsdb_schema_from_schema_dn(mem_ctx, module,
164                                          lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
165                                          schema_dn, &schema);
166
167         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
168                 ldb_reset_err_string(ldb);
169                 ldb_debug(ldb, LDB_DEBUG_WARNING,
170                           "schema_load_init: no schema head present: (skip schema loading)\n");
171                 talloc_free(mem_ctx);
172                 return LDB_SUCCESS;
173         }
174
175         if (ret != LDB_SUCCESS) {
176                 talloc_free(mem_ctx);
177                 return ret;
178         }
179
180         /* dsdb_set_schema() steal schema into the ldb_context */
181         ret = dsdb_set_schema(ldb, schema);
182         if (ret != LDB_SUCCESS) {
183                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
184                               "schema_load_init: dsdb_set_schema() failed: %d:%s: %s",
185                               ret, ldb_strerror(ret), ldb_errstring(ldb));
186                 talloc_free(mem_ctx);
187                 return ret;
188         }
189
190         talloc_free(mem_ctx);
191         return LDB_SUCCESS;
192 }
193
194 static int schema_load_extended(struct ldb_module *module, struct ldb_request *req)
195 {
196         struct ldb_context *ldb;
197         struct ldb_dn *schema_dn;
198         struct dsdb_schema *schema;
199         int ret;
200         TALLOC_CTX *mem_ctx;
201
202         ldb = ldb_module_get_ctx(module);
203
204         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
205                 return ldb_next_request(module, req);
206         }
207
208         /*
209          * TODO:
210          *
211          * We should check "schemaInfo" if we really need to reload the schema!
212          *
213          * We should also for a new schema version at the start of each
214          * "write" (add/modify/rename/delete) operation. And have tests
215          * to prove that windows does the same.
216          */
217
218         schema_dn = samdb_schema_dn(ldb);
219         if (!schema_dn) {
220                 ldb_reset_err_string(ldb);
221                 ldb_debug(ldb, LDB_DEBUG_WARNING,
222                           "schema_load_extended: no schema dn present: (skip schema loading)\n");
223                 return ldb_next_request(module, req);
224         }
225         
226         mem_ctx = talloc_new(module);
227         if (!mem_ctx) {
228                 ldb_oom(ldb);
229                 return LDB_ERR_OPERATIONS_ERROR;
230         }
231         
232         ret = dsdb_schema_from_schema_dn(mem_ctx, module,
233                                          lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
234                                          schema_dn, &schema);
235
236         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
237                 ldb_reset_err_string(ldb);
238                 ldb_debug(ldb, LDB_DEBUG_WARNING,
239                           "schema_load_extended: no schema head present: (skip schema loading)\n");
240                 talloc_free(mem_ctx);
241                 return ldb_next_request(module, req);
242         }
243
244         if (ret != LDB_SUCCESS) {
245                 talloc_free(mem_ctx);
246                 return ldb_next_request(module, req);
247         }
248
249         /* Replace the old schema*/
250         ret = dsdb_set_schema(ldb, schema);
251         if (ret != LDB_SUCCESS) {
252                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
253                               "schema_load_extended: dsdb_set_schema() failed: %d:%s: %s",
254                               ret, ldb_strerror(ret), ldb_errstring(ldb));
255                 talloc_free(mem_ctx);
256                 return ret;
257         }
258
259         dsdb_make_schema_global(ldb);
260
261         talloc_free(mem_ctx);
262         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
263 }
264
265
266 _PUBLIC_ const struct ldb_module_ops ldb_schema_load_module_ops = {
267         .name           = "schema_load",
268         .init_context   = schema_load_init,
269         .extended       = schema_load_extended,
270 };