r20771: add an ldb module which will force the Schema FSMO Role Owner
[kai/samba.git] / source4 / dsdb / samdb / ldb_modules / schema_fsmo.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 2007
8     
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22    
23 */
24
25 #include "includes.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "lib/ldb/include/ldb_errors.h"
28 #include "lib/ldb/include/ldb_private.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "librpc/gen_ndr/ndr_misc.h"
31 #include "librpc/gen_ndr/ndr_drsuapi.h"
32 #include "librpc/gen_ndr/ndr_drsblobs.h"
33 #include "lib/util/dlinklist.h"
34
35 static int schema_fsmo_init(struct ldb_module *module)
36 {
37         WERROR status;
38         TALLOC_CTX *mem_ctx;
39         struct ldb_dn *schema_dn;
40         struct dsdb_schema *schema;
41         struct ldb_result *schema_res;
42         const struct ldb_val *prefix_val;
43         const struct ldb_val *info_val;
44         struct ldb_result *a_res;
45         struct ldb_result *c_res;
46         uint32_t i;
47         int ret;
48         static const char *schema_attrs[] = {
49                 "prefixMap",
50                 "schemaInfo",
51                 NULL
52         };
53
54         schema_dn = samdb_schema_dn(module->ldb);
55         if (!schema_dn) {
56                 ldb_debug(module->ldb, LDB_DEBUG_TRACE,
57                           "schema_fsmo_init: no schema dn present: (skip schema loading)");
58                 return ldb_next_init(module);
59         }
60
61         mem_ctx = talloc_new(module);
62         if (!mem_ctx) {
63                 ldb_oom(module->ldb);
64                 return LDB_ERR_OPERATIONS_ERROR;
65         }
66
67         schema = talloc_zero(mem_ctx, struct dsdb_schema);
68         if (!schema) {
69                 ldb_oom(module->ldb);
70                 return LDB_ERR_OPERATIONS_ERROR;
71         }
72
73         /*
74          * setup the prefix mappings and schema info
75          */
76         ret = ldb_search(module->ldb, schema_dn,
77                          LDB_SCOPE_BASE,
78                          NULL, schema_attrs,
79                          &schema_res);
80         if (ret != LDB_SUCCESS) {
81                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
82                               "schema_fsmo_init: failed to search the schema head: %d:%s",
83                               ret, ldb_strerror(ret));
84                 talloc_free(mem_ctx);
85                 return ret;
86         }
87         talloc_steal(mem_ctx, schema_res);
88         if (schema_res->count == 0) {
89                 ldb_debug(module->ldb, LDB_DEBUG_TRACE,
90                           "schema_fsmo_init: no schema head present: (skip schema loading)");
91                 talloc_free(mem_ctx);
92                 return ldb_next_init(module);
93         } else if (schema_res->count > 1) {
94                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
95                               "schema_fsmo_init: [%u] schema heads found on a base search",
96                               schema_res->count);
97                 talloc_free(mem_ctx);
98                 return LDB_ERR_CONSTRAINT_VIOLATION;
99         }
100
101         prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
102         if (!prefix_val) {
103                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
104                               "schema_fsmo_init: no prefixMap attribute found");
105                 talloc_free(mem_ctx);
106                 return LDB_ERR_CONSTRAINT_VIOLATION;
107         }
108         info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
109         if (!info_val) {
110                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
111                               "schema_fsmo_init: no schemaInfo attribute found");
112                 talloc_free(mem_ctx);
113                 return LDB_ERR_CONSTRAINT_VIOLATION;
114         }
115
116         status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
117         if (!W_ERROR_IS_OK(status)) {
118                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
119                               "schema_fsmo_init: failed to load oid mappings: %s",
120                               win_errstr(status));
121                 talloc_free(mem_ctx);
122                 return LDB_ERR_CONSTRAINT_VIOLATION;
123         }
124
125         /*
126          * load the attribute definitions
127          */
128         ret = ldb_search(module->ldb, schema_dn,
129                          LDB_SCOPE_ONELEVEL,
130                          "(objectClass=attributeSchema)", NULL,
131                          &a_res);
132         if (ret != LDB_SUCCESS) {
133                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
134                               "schema_fsmo_init: failed to search attributeSchema objects: %d:%s",
135                               ret, ldb_strerror(ret));
136                 talloc_free(mem_ctx);
137                 return ret;
138         }
139         talloc_steal(mem_ctx, a_res);
140
141         for (i=0; i < a_res->count; i++) {
142                 struct dsdb_attribute *sa;
143
144                 sa = talloc_zero(schema, struct dsdb_attribute);
145                 if (!sa) {
146                         ldb_oom(module->ldb);
147                         return LDB_ERR_OPERATIONS_ERROR;
148                 }
149
150                 status = dsdb_attribute_from_ldb(schema, a_res->msgs[i], sa, sa);
151                 if (!W_ERROR_IS_OK(status)) {
152                         ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
153                                       "schema_fsmo_init: failed to load attriute definition: %s:%s",
154                                       ldb_dn_get_linearized(a_res->msgs[i]->dn),
155                                       win_errstr(status));
156                         talloc_free(mem_ctx);
157                         return LDB_ERR_CONSTRAINT_VIOLATION;
158                 }
159
160                 DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
161         }
162         talloc_free(a_res);
163
164         /*
165          * load the objectClass definitions
166          */
167         ret = ldb_search(module->ldb, schema_dn,
168                          LDB_SCOPE_ONELEVEL,
169                          "(objectClass=classSchema)", NULL,
170                          &c_res);
171         if (ret != LDB_SUCCESS) {
172                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
173                               "schema_fsmo_init: failed to search classSchema objects: %d:%s",
174                               ret, ldb_strerror(ret));
175                 talloc_free(mem_ctx);
176                 return ret;
177         }
178         talloc_steal(mem_ctx, c_res);
179
180         for (i=0; i < c_res->count; i++) {
181                 struct dsdb_class *sc;
182
183                 sc = talloc_zero(schema, struct dsdb_class);
184                 if (!sc) {
185                         ldb_oom(module->ldb);
186                         return LDB_ERR_OPERATIONS_ERROR;
187                 }
188
189                 status = dsdb_class_from_ldb(schema, c_res->msgs[i], sc, sc);
190                 if (!W_ERROR_IS_OK(status)) {
191                         ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
192                                       "schema_fsmo_init: failed to load class definition: %s:%s",
193                                       ldb_dn_get_linearized(c_res->msgs[i]->dn),
194                                       win_errstr(status));
195                         talloc_free(mem_ctx);
196                         return LDB_ERR_CONSTRAINT_VIOLATION;
197                 }
198
199                 DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
200         }
201         talloc_free(c_res);
202
203         ret = dsdb_set_schema(module->ldb, schema);
204         if (ret != LDB_SUCCESS) {
205                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
206                               "schema_fsmo_init: dsdb_set_schema() failed: %d:%s",
207                               ret, ldb_strerror(ret));
208                 talloc_free(mem_ctx);
209                 return ret;
210         }
211
212         talloc_steal(module, schema);
213         talloc_free(mem_ctx);
214         return ldb_next_init(module);
215 }
216
217 static const struct ldb_module_ops schema_fsmo_ops = {
218         .name           = "schema_fsmo",
219         .init_context   = schema_fsmo_init
220 };
221
222 int schema_fsmo_module_init(void)
223 {
224         return ldb_register_module(&schema_fsmo_ops);
225 }