Handle schema reloading request.
[abartlet/samba.git/.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 <metze@samba.org> 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 3 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, see <http://www.gnu.org/licenses/>.
21    
22 */
23
24 #include "includes.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "lib/ldb/include/ldb_private.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "librpc/gen_ndr/ndr_misc.h"
30 #include "librpc/gen_ndr/ndr_drsuapi.h"
31 #include "librpc/gen_ndr/ndr_drsblobs.h"
32 #include "lib/util/dlinklist.h"
33 #include "param/param.h"
34
35 static int schema_fsmo_init(struct ldb_module *module)
36 {
37         TALLOC_CTX *mem_ctx;
38         struct ldb_dn *schema_dn;
39         struct dsdb_schema *schema;
40         char *error_string = NULL;
41         int ret;
42
43         if (dsdb_get_schema(module->ldb)) {
44                 return ldb_next_init(module);
45         }
46
47         schema_dn = samdb_schema_dn(module->ldb);
48         if (!schema_dn) {
49                 ldb_reset_err_string(module->ldb);
50                 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
51                           "schema_fsmo_init: no schema dn present: (skip schema loading)\n");
52                 return ldb_next_init(module);
53         }
54
55         mem_ctx = talloc_new(module);
56         if (!mem_ctx) {
57                 ldb_oom(module->ldb);
58                 return LDB_ERR_OPERATIONS_ERROR;
59         }
60
61         ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb,
62                                          lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
63                                          schema_dn, &schema, &error_string);
64
65         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
66                 ldb_reset_err_string(module->ldb);
67                 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
68                           "schema_fsmo_init: no schema head present: (skip schema loading)\n");
69                 talloc_free(mem_ctx);
70                 return ldb_next_init(module);
71         }
72
73         if (ret != LDB_SUCCESS) {
74                 ldb_asprintf_errstring(module->ldb, 
75                                        "schema_fsmo_init: dsdb_schema load failed: %s",
76                                        error_string);
77                 talloc_free(mem_ctx);
78         }
79
80         /* dsdb_set_schema() steal schema into the ldb_context */
81         ret = dsdb_set_schema(module->ldb, schema);
82         if (ret != LDB_SUCCESS) {
83                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
84                               "schema_fsmo_init: dsdb_set_schema() failed: %d:%s",
85                               ret, ldb_strerror(ret));
86                 talloc_free(mem_ctx);
87                 return ret;
88         }
89
90         talloc_free(mem_ctx);
91         return ldb_next_init(module);
92 }
93
94 static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
95 {
96         struct dsdb_schema *schema;
97         const char *attributeID = NULL;
98         const char *governsID = NULL;
99         const char *oid_attr = NULL;
100         const char *oid = NULL;
101         uint32_t id32;
102         WERROR status;
103
104         schema = dsdb_get_schema(module->ldb);
105         if (!schema) {
106                 return ldb_next_request(module, req);
107         }
108
109         if (!schema->fsmo.we_are_master) {
110                 ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
111                           "schema_fsmo_add: we are not master: reject request\n");
112                 return LDB_ERR_UNWILLING_TO_PERFORM;
113         }
114
115         attributeID = samdb_result_string(req->op.add.message, "attributeID", NULL);
116         governsID = samdb_result_string(req->op.add.message, "governsID", NULL);
117
118         if (attributeID) {
119                 oid_attr = "attributeID";
120                 oid = attributeID;
121         } else if (governsID) {
122                 oid_attr = "governsID";
123                 oid = governsID;
124         }
125
126         if (!oid) {
127                 return ldb_next_request(module, req);
128         }
129
130         status = dsdb_map_oid2int(schema, oid, &id32);
131         if (W_ERROR_IS_OK(status)) {
132                 return ldb_next_request(module, req);
133         } else if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID, status)) {
134                 ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
135                           "schema_fsmo_add: failed to map %s[%s]: %s\n",
136                           oid_attr, oid, win_errstr(status));
137                 return LDB_ERR_UNWILLING_TO_PERFORM;
138         }
139
140         status = dsdb_create_prefix_mapping(module->ldb, schema, oid);
141         if (!W_ERROR_IS_OK(status)) {
142                 ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
143                           "schema_fsmo_add: failed to create prefix mapping for %s[%s]: %s\n",
144                           oid_attr, oid, win_errstr(status));
145                 return LDB_ERR_UNWILLING_TO_PERFORM;
146         }
147
148         return ldb_next_request(module, req);
149 }
150
151 static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req)
152 {
153         WERROR status;
154         struct ldb_dn *schema_dn;
155         struct dsdb_schema *schema;
156         char *error_string = NULL;
157         int ret;
158         TALLOC_CTX *mem_ctx;
159         
160         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
161                 return ldb_next_request(module, req);
162         }
163         
164         schema_dn = samdb_schema_dn(module->ldb);
165         if (!schema_dn) {
166                 ldb_reset_err_string(module->ldb);
167                 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
168                           "schema_fsmo_extended: no schema dn present: (skip schema loading)\n");
169                 return ldb_next_request(module, req);
170         }
171         
172         mem_ctx = talloc_new(module);
173         if (!mem_ctx) {
174                 ldb_oom(module->ldb);
175                 return LDB_ERR_OPERATIONS_ERROR;
176         }
177         
178         ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb,
179                                          lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
180                                          schema_dn, &schema, &error_string);
181
182         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
183                 ldb_reset_err_string(module->ldb);
184                 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
185                           "schema_fsmo_extended: no schema head present: (skip schema loading)\n");
186                 talloc_free(mem_ctx);
187                 return ldb_next_request(module, req);
188         }
189
190         if (ret != LDB_SUCCESS) {
191                 ldb_asprintf_errstring(module->ldb, 
192                                        "schema_fsmo_extended: dsdb_schema load failed: %s",
193                                        error_string);
194                 talloc_free(mem_ctx);
195                 return ldb_next_request(module, req);
196         }
197
198         /* Replace the old schema*/
199         ret = dsdb_set_schema(module->ldb, schema);
200         if (ret != LDB_SUCCESS) {
201                 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
202                               "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s",
203                               ret, ldb_strerror(ret));
204                 talloc_free(mem_ctx);
205                 return ret;
206         }
207
208         talloc_free(mem_ctx);
209         return LDB_SUCCESS;
210 }
211
212 _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
213         .name           = "schema_fsmo",
214         .init_context   = schema_fsmo_init,
215         .add            = schema_fsmo_add,
216         .extended       = schema_fsmo_extended
217 };