32
32
#include "includes.h"
33
33
#include "ldb_module.h"
34
#include "dsdb/samdb/samdb.h"
35
#include "dsdb/samdb/ldb_modules/util.h"
34
36
#include "librpc/gen_ndr/ndr_misc.h"
35
37
#include "param/param.h"
37
static struct ldb_message_element *objectguid_find_attribute(const struct ldb_message *msg, const char *name)
41
for (i = 0; i < msg->num_elements; i++) {
42
if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {
43
return &msg->elements[i];
51
40
add a time element to a record
55
44
struct ldb_message_element *el;
58
48
if (ldb_msg_find_element(msg, attr) != NULL) {
62
52
s = ldb_timestring(msg, t);
54
return LDB_ERR_OPERATIONS_ERROR;
67
if (ldb_msg_add_string(msg, attr, s) != 0) {
57
ret = ldb_msg_add_string(msg, attr, s);
58
if (ret != LDB_SUCCESS) {
71
62
el = ldb_msg_find_element(msg, attr);
74
65
el->flags = LDB_FLAG_MOD_REPLACE;
80
71
add a uint64_t element to a record
82
static int add_uint64_element(struct ldb_message *msg, const char *attr, uint64_t v)
73
static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg,
74
const char *attr, uint64_t v)
84
76
struct ldb_message_element *el;
86
79
if (ldb_msg_find_element(msg, attr) != NULL) {
90
if (ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)v) != 0) {
83
ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v);
84
if (ret != LDB_SUCCESS) {
94
88
el = ldb_msg_find_element(msg, attr);
104
98
struct ldb_request *req;
107
static int og_op_callback(struct ldb_request *req, struct ldb_reply *ares)
109
struct og_context *ac;
111
ac = talloc_get_type(req->context, struct og_context);
114
return ldb_module_done(ac->req, NULL, NULL,
115
LDB_ERR_OPERATIONS_ERROR);
117
if (ares->error != LDB_SUCCESS) {
118
return ldb_module_done(ac->req, ares->controls,
119
ares->response, ares->error);
122
if (ares->type != LDB_REPLY_DONE) {
124
return ldb_module_done(ac->req, NULL, NULL,
125
LDB_ERR_OPERATIONS_ERROR);
128
return ldb_module_done(ac->req, ares->controls,
129
ares->response, ares->error);
132
/* add_record: add objectGUID attribute */
101
/* add_record: add objectGUID and timestamp attributes */
133
102
static int objectguid_add(struct ldb_module *module, struct ldb_request *req)
135
104
struct ldb_context *ldb;
136
105
struct ldb_request *down_req;
137
struct ldb_message_element *attribute;
138
106
struct ldb_message *msg;
107
struct ldb_message_element *el;
140
108
struct GUID guid;
141
109
uint64_t seq_num;
142
enum ndr_err_code ndr_err;
144
111
time_t t = time(NULL);
145
112
struct og_context *ac;
153
120
return ldb_next_request(module, req);
156
if ((attribute = objectguid_find_attribute(req->op.add.message, "objectGUID")) != NULL ) {
157
return ldb_next_request(module, req);
123
el = ldb_msg_find_element(req->op.add.message, "objectGUID");
125
ldb_set_errstring(ldb,
126
"objectguid: objectGUID must not be specified!");
127
return LDB_ERR_UNWILLING_TO_PERFORM;
160
130
ac = talloc(req, struct og_context);
161
131
if (ac == NULL) {
162
return LDB_ERR_OPERATIONS_ERROR;
164
134
ac->module = module;
167
137
/* we have to copy the message as the caller might have it as a const */
168
138
msg = ldb_msg_copy_shallow(ac, req->op.add.message);
169
139
if (msg == NULL) {
170
talloc_free(down_req);
171
return LDB_ERR_OPERATIONS_ERROR;
141
return ldb_operr(ldb);
175
145
guid = GUID_random();
177
ndr_err = ndr_push_struct_blob(&v, msg,
178
lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
180
(ndr_push_flags_fn_t)ndr_push_GUID);
181
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
182
return LDB_ERR_OPERATIONS_ERROR;
185
ret = ldb_msg_add_value(msg, "objectGUID", &v, NULL);
147
ret = dsdb_msg_add_guid(msg, &guid, "objectGUID");
148
if (ret != LDB_SUCCESS) {
190
if (add_time_element(msg, "whenCreated", t) != 0 ||
191
add_time_element(msg, "whenChanged", t) != 0) {
192
return LDB_ERR_OPERATIONS_ERROR;
152
if (add_time_element(msg, "whenCreated", t) != LDB_SUCCESS ||
153
add_time_element(msg, "whenChanged", t) != LDB_SUCCESS) {
154
return ldb_operr(ldb);
195
157
/* Get a sequence number from the backend */
196
/* FIXME: ldb_sequence_number is a semi-async call,
197
* make sure this function is split and a callback is used */
198
158
ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
199
159
if (ret == LDB_SUCCESS) {
200
if (add_uint64_element(msg, "uSNCreated", seq_num) != 0 ||
201
add_uint64_element(msg, "uSNChanged", seq_num) != 0) {
202
return LDB_ERR_OPERATIONS_ERROR;
160
if (add_uint64_element(ldb, msg, "uSNCreated",
161
seq_num) != LDB_SUCCESS ||
162
add_uint64_element(ldb, msg, "uSNChanged",
163
seq_num) != LDB_SUCCESS) {
164
return ldb_operr(ldb);
206
168
ret = ldb_build_add_req(&down_req, ldb, ac,
171
req, dsdb_next_callback,
173
LDB_REQ_SET_LOCATION(down_req);
211
174
if (ret != LDB_SUCCESS) {
212
return LDB_ERR_OPERATIONS_ERROR;
215
178
/* go on with the call chain */
230
194
ldb = ldb_module_get_ctx(module);
232
ldb_debug(ldb, LDB_DEBUG_TRACE, "objectguid_add_record\n");
196
ldb_debug(ldb, LDB_DEBUG_TRACE, "objectguid_modify_record\n");
234
198
/* do not manipulate our control entries */
235
199
if (ldb_dn_is_special(req->op.add.message->dn)) {
236
200
return ldb_next_request(module, req);
203
el = ldb_msg_find_element(req->op.mod.message, "objectGUID");
205
ldb_set_errstring(ldb,
206
"objectguid: objectGUID must not be specified!");
207
return LDB_ERR_CONSTRAINT_VIOLATION;
239
210
ac = talloc(req, struct og_context);
240
211
if (ac == NULL) {
241
return LDB_ERR_OPERATIONS_ERROR;
243
214
ac->module = module;
246
217
/* we have to copy the message as the caller might have it as a const */
247
218
msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
248
219
if (msg == NULL) {
249
return LDB_ERR_OPERATIONS_ERROR;
220
return ldb_operr(ldb);
252
if (add_time_element(msg, "whenChanged", t) != 0) {
253
return LDB_ERR_OPERATIONS_ERROR;
223
if (add_time_element(msg, "whenChanged", t) != LDB_SUCCESS) {
224
return ldb_operr(ldb);
256
227
/* Get a sequence number from the backend */
257
228
ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
258
229
if (ret == LDB_SUCCESS) {
259
if (add_uint64_element(msg, "uSNChanged", seq_num) != 0) {
260
return LDB_ERR_OPERATIONS_ERROR;
230
if (add_uint64_element(ldb, msg, "uSNChanged",
231
seq_num) != LDB_SUCCESS) {
232
return ldb_operr(ldb);
264
236
ret = ldb_build_mod_req(&down_req, ldb, ac,
239
req, dsdb_next_callback,
241
LDB_REQ_SET_LOCATION(down_req);
269
242
if (ret != LDB_SUCCESS) {
270
return LDB_ERR_OPERATIONS_ERROR;
273
246
/* go on with the call chain */
274
247
return ldb_next_request(module, down_req);
277
_PUBLIC_ const struct ldb_module_ops ldb_objectguid_module_ops = {
250
static const struct ldb_module_ops ldb_objectguid_module_ops = {
278
251
.name = "objectguid",
279
252
.add = objectguid_add,
280
.modify = objectguid_modify,
253
.modify = objectguid_modify
256
int ldb_objectguid_module_init(const char *version)
258
LDB_MODULE_CHECK_VERSION(version);
259
return ldb_register_module(&ldb_objectguid_module_ops);