dsdb: Log the transaction duraton.
[metze/samba/wip.git] / source4 / dsdb / samdb / ldb_modules / audit_log.c
1 /*
2    ldb database library
3
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21  * Provide an audit log of changes made to the database and at a
22  * higher level details of any password changes and resets.
23  *
24  */
25
26 #include "includes.h"
27 #include "ldb_module.h"
28 #include "lib/audit_logging/audit_logging.h"
29
30 #include "dsdb/samdb/samdb.h"
31 #include "dsdb/samdb/ldb_modules/util.h"
32 #include "libcli/security/dom_sid.h"
33 #include "auth/common_auth.h"
34 #include "param/param.h"
35
36 #define OPERATION_JSON_TYPE "dsdbChange"
37 #define OPERATION_HR_TAG "DSDB Change"
38 #define OPERATION_MAJOR 1
39 #define OPERATION_MINOR 0
40 #define OPERATION_LOG_LVL 5
41
42 #define PASSWORD_JSON_TYPE "passwordChange"
43 #define PASSWORD_HR_TAG "Password Change"
44 #define PASSWORD_MAJOR 1
45 #define PASSWORD_MINOR 0
46 #define PASSWORD_LOG_LVL 5
47
48 #define TRANSACTION_JSON_TYPE "dsdbTransaction"
49 #define TRANSACTION_HR_TAG "DSDB Transaction"
50 #define TRANSACTION_MAJOR 1
51 #define TRANSACTION_MINOR 0
52 #define TRANSACTION_LOG_FAILURE_LVL 5
53 #define TRANSACTION_LOG_COMPLETION_LVL 10
54
55 #define REPLICATION_JSON_TYPE "replicatedUpdate"
56 #define REPLICATION_HR_TAG "Replicated Update"
57 #define REPLICATION_MAJOR 1
58 #define REPLICATION_MINOR 0
59 #define REPLICATION_LOG_LVL 5
60 /*
61  * Attribute values are truncated in the logs if they are longer than
62  * MAX_LENGTH
63  */
64 #define MAX_LENGTH 1024
65
66 #define min(a, b) (((a)>(b))?(b):(a))
67
68 /*
69  * Private data for the module, stored in the ldb_module private data
70  */
71 struct audit_context {
72         /*
73          * Should details of database operations be sent over the
74          * messaging bus.
75          */
76         bool send_samdb_events;
77         /*
78          * Should details of password changes and resets be sent over
79          * the messaging bus.
80          */
81         bool send_password_events;
82         /*
83          * The messaging context to send the messages over.  Will only
84          * be set if send_samdb_events or send_password_events are
85          * true.
86          */
87         struct imessaging_context *msg_ctx;
88         /*
89          * Unique transaction id for the current transaction
90          */
91         struct GUID transaction_guid;
92         /*
93          * Transaction start time, used to calculate the transaction
94          * duration.
95          */
96         struct timeval transaction_start;
97 };
98
99 /*
100  * @brief Has the password changed.
101  *
102  * Does the message contain a change to one of the password attributes? The
103  * password attributes are defined in DSDB_PASSWORD_ATTRIBUTES
104  *
105  * @return true if the message contains a password attribute
106  *
107  */
108 static bool has_password_changed(const struct ldb_message *message)
109 {
110         int i;
111         if (message == NULL) {
112                 return false;
113         }
114         for (i=0;i<message->num_elements;i++) {
115                 if (dsdb_audit_is_password_attribute(
116                         message->elements[i].name)) {
117                         return true;
118                 }
119         }
120         return false;
121 }
122
123 /*
124  * @brief Is the request a password "Change" or a "Reset"
125  *
126  * Get a description of the action being performed on the user password.  This
127  * routine assumes that the request contains password attributes and that the
128  * password ACL checks have been performed by acl.c
129  *
130  * @param request the ldb_request to inspect
131  * @param reply the ldb_reply, will contain the password controls
132  *
133  * @return "Change" if the password is being changed.
134  *         "Reset"  if the password is being reset.
135  */
136 static const char *get_password_action(
137         const struct ldb_request *request,
138         const struct ldb_reply *reply)
139 {
140         if(request->operation == LDB_ADD) {
141                 return "Reset";
142         } else {
143                 struct ldb_control *pav_ctrl = NULL;
144                 struct dsdb_control_password_acl_validation *pav = NULL;
145
146                 pav_ctrl = ldb_reply_get_control(
147                         discard_const(reply),
148                         DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID);
149                 if (pav_ctrl == NULL) {
150                         return "Reset";
151                 }
152
153                 pav = talloc_get_type_abort(
154                         pav_ctrl->data,
155                         struct dsdb_control_password_acl_validation);
156
157                 if (pav->pwd_reset) {
158                         return "Reset";
159                 } else {
160                         return "Change";
161                 }
162         }
163 }
164
165
166 #ifdef HAVE_JANSSON
167 /*
168  * @brief generate a JSON object detailing an ldb operation.
169  *
170  * Generate a JSON object detailing an ldb operation.
171  *
172  * @param module the ldb module
173  * @param request the request
174  * @param reply the result of the operation.
175  *
176  * @return the generated JSON object, should be freed with json_free.
177  *
178  */
179 static struct json_object operation_json(
180         struct ldb_module *module,
181         const struct ldb_request *request,
182         const struct ldb_reply *reply)
183 {
184         struct ldb_context *ldb = NULL;
185         const struct dom_sid *sid = NULL;
186         bool as_system = false;
187         struct json_object wrapper;
188         struct json_object audit;
189         const struct tsocket_address *remote = NULL;
190         const char *dn = NULL;
191         const char* operation = NULL;
192         const struct GUID *unique_session_token = NULL;
193         const struct ldb_message *message = NULL;
194         struct audit_context *ac = talloc_get_type(
195                 ldb_module_get_private(module),
196                 struct audit_context);
197
198         ldb = ldb_module_get_ctx(module);
199
200         remote = dsdb_audit_get_remote_address(ldb);
201         if (remote != NULL && dsdb_audit_is_system_session(module)) {
202                 as_system = true;
203                 sid = dsdb_audit_get_actual_sid(ldb);
204                 unique_session_token =
205                         dsdb_audit_get_actual_unique_session_token(ldb);
206         } else {
207                 sid = dsdb_audit_get_user_sid(module);
208                 unique_session_token =
209                         dsdb_audit_get_unique_session_token(module);
210         }
211         dn = dsdb_audit_get_primary_dn(request);
212         operation = dsdb_audit_get_operation_name(request);
213
214         audit = json_new_object();
215         json_add_version(&audit, OPERATION_MAJOR, OPERATION_MINOR);
216         json_add_int(&audit, "statusCode", reply->error);
217         json_add_string(&audit, "status", ldb_strerror(reply->error));
218         json_add_string(&audit, "operation", operation);
219         json_add_address(&audit, "remoteAddress", remote);
220         json_add_bool(&audit, "performedAsSystem", as_system);
221         json_add_sid(&audit, "userSid", sid);
222         json_add_string(&audit, "dn", dn);
223         json_add_guid(&audit, "transactionId", &ac->transaction_guid);
224         json_add_guid(&audit, "sessionId", unique_session_token);
225
226         message = dsdb_audit_get_message(request);
227         if (message != NULL) {
228                 struct json_object attributes =
229                         dsdb_audit_attributes_json(
230                                 request->operation,
231                                 message);
232                 json_add_object(&audit, "attributes", &attributes);
233         }
234
235         wrapper = json_new_object();
236         json_add_timestamp(&wrapper);
237         json_add_string(&wrapper, "type", OPERATION_JSON_TYPE);
238         json_add_object(&wrapper, OPERATION_JSON_TYPE, &audit);
239         return wrapper;
240 }
241
242 /*
243  * @brief generate a JSON object detailing a replicated update.
244  *
245  * Generate a JSON object detailing a replicated update
246  *
247  * @param module the ldb module
248  * @param request the request
249  * @paran reply the result of the operation
250  *
251  * @return the generated JSON object, should be freed with json_free.
252  *
253  */
254 static struct json_object replicated_update_json(
255         struct ldb_module *module,
256         const struct ldb_request *request,
257         const struct ldb_reply *reply)
258 {
259         struct json_object wrapper;
260         struct json_object audit;
261         struct audit_context *ac = talloc_get_type(
262                 ldb_module_get_private(module),
263                 struct audit_context);
264         struct dsdb_extended_replicated_objects *ro = talloc_get_type(
265                 request->op.extended.data,
266                 struct dsdb_extended_replicated_objects);
267         const char *partition_dn = NULL;
268         const char *error = NULL;
269
270         partition_dn = ldb_dn_get_linearized(ro->partition_dn);
271         error = get_friendly_werror_msg(ro->error);
272
273         audit = json_new_object();
274         json_add_version(&audit, REPLICATION_MAJOR, REPLICATION_MINOR);
275         json_add_int(&audit, "statusCode", reply->error);
276         json_add_string(&audit, "status", ldb_strerror(reply->error));
277         json_add_guid(&audit, "transactionId", &ac->transaction_guid);
278         json_add_int(&audit, "objectCount", ro->num_objects);
279         json_add_int(&audit, "linkCount", ro->linked_attributes_count);
280         json_add_string(&audit, "partitionDN", partition_dn);
281         json_add_string(&audit, "error", error);
282         json_add_int(&audit, "errorCode", W_ERROR_V(ro->error));
283         json_add_guid(
284                 &audit,
285                 "sourceDsa",
286                 &ro->source_dsa->source_dsa_obj_guid);
287         json_add_guid(
288                 &audit,
289                 "invocationId",
290                 &ro->source_dsa->source_dsa_invocation_id);
291
292         wrapper = json_new_object();
293         json_add_timestamp(&wrapper);
294         json_add_string(&wrapper, "type", REPLICATION_JSON_TYPE);
295         json_add_object(&wrapper, REPLICATION_JSON_TYPE, &audit);
296         return wrapper;
297 }
298
299 /*
300  * @brief generate a JSON object detailing a password change.
301  *
302  * Generate a JSON object detailing a password change.
303  *
304  * @param module the ldb module
305  * @param request the request
306  * @param reply the result/response
307  * @param status the status code returned for the underlying ldb operation.
308  *
309  * @return the generated JSON object.
310  *
311  */
312 static struct json_object password_change_json(
313         struct ldb_module *module,
314         const struct ldb_request *request,
315         const struct ldb_reply *reply)
316 {
317         struct ldb_context *ldb = NULL;
318         const struct dom_sid *sid = NULL;
319         const char* dn = NULL;
320         struct json_object wrapper;
321         struct json_object audit;
322         const struct tsocket_address *remote = NULL;
323         const char* action = NULL;
324         const struct GUID *unique_session_token = NULL;
325         struct audit_context *ac = talloc_get_type(
326                 ldb_module_get_private(module),
327                 struct audit_context);
328
329
330         ldb = ldb_module_get_ctx(module);
331
332         remote = dsdb_audit_get_remote_address(ldb);
333         sid = dsdb_audit_get_user_sid(module);
334         dn = dsdb_audit_get_primary_dn(request);
335         action = get_password_action(request, reply);
336         unique_session_token = dsdb_audit_get_unique_session_token(module);
337
338         audit = json_new_object();
339         json_add_version(&audit, PASSWORD_MAJOR, PASSWORD_MINOR);
340         json_add_int(&audit, "statusCode", reply->error);
341         json_add_string(&audit, "status", ldb_strerror(reply->error));
342         json_add_address(&audit, "remoteAddress", remote);
343         json_add_sid(&audit, "userSid", sid);
344         json_add_string(&audit, "dn", dn);
345         json_add_string(&audit, "action", action);
346         json_add_guid(&audit, "transactionId", &ac->transaction_guid);
347         json_add_guid(&audit, "sessionId", unique_session_token);
348
349         wrapper = json_new_object();
350         json_add_timestamp(&wrapper);
351         json_add_string(&wrapper, "type", PASSWORD_JSON_TYPE);
352         json_add_object(&wrapper, PASSWORD_JSON_TYPE, &audit);
353
354         return wrapper;
355 }
356
357
358 /*
359  * @brief create a JSON object containing details of a transaction event.
360  *
361  * Create a JSON object detailing a transaction transaction life cycle events,
362  * i.e. begin, commit, roll back
363  *
364  * @param action a one word description of the event/action
365  * @param transaction_id the GUID identifying the current transaction.
366  * @param status the status code returned by the operation
367  * @param duration the duration of the operation.
368  *
369  * @return a JSON object detailing the event
370  */
371 static struct json_object transaction_json(
372         const char *action,
373         struct GUID *transaction_id,
374         const int64_t duration)
375 {
376         struct json_object wrapper;
377         struct json_object audit;
378
379         audit = json_new_object();
380         json_add_version(&audit, TRANSACTION_MAJOR, TRANSACTION_MINOR);
381         json_add_string(&audit, "action", action);
382         json_add_guid(&audit, "transactionId", transaction_id);
383         json_add_int(&audit, "duration", duration);
384
385
386         wrapper = json_new_object();
387         json_add_timestamp(&wrapper);
388         json_add_string(&wrapper, "type", TRANSACTION_JSON_TYPE);
389         json_add_object(&wrapper, TRANSACTION_JSON_TYPE, &audit);
390
391         return wrapper;
392 }
393
394
395 /*
396  * @brief generate a JSON object detailing a commit failure.
397  *
398  * Generate a JSON object containing details of a commit failure.
399  *
400  * @param action the commit action, "commit" or "prepare"
401  * @param status the status code returned by commit
402  * @param reason any extra failure information/reason available
403  * @param transaction_id the GUID identifying the current transaction.
404  */
405 static struct json_object commit_failure_json(
406         const char *action,
407         const int64_t duration,
408         int status,
409         const char *reason,
410         struct GUID *transaction_id)
411 {
412         struct json_object wrapper;
413         struct json_object audit;
414
415         audit = json_new_object();
416         json_add_version(&audit, TRANSACTION_MAJOR, TRANSACTION_MINOR);
417         json_add_string(&audit, "action", action);
418         json_add_guid(&audit, "transactionId", transaction_id);
419         json_add_int(&audit, "duration", duration);
420         json_add_int(&audit, "statusCode", status);
421         json_add_string(&audit, "status", ldb_strerror(status));
422         json_add_string(&audit, "reason", reason);
423
424         wrapper = json_new_object();
425         json_add_timestamp(&wrapper);
426         json_add_string(&wrapper, "type", TRANSACTION_JSON_TYPE);
427         json_add_object(&wrapper, TRANSACTION_JSON_TYPE, &audit);
428
429         return wrapper;
430 }
431
432 #endif
433 /*
434  * @brief Print a human readable log line for a password change event.
435  *
436  * Generate a human readable log line detailing a password change.
437  *
438  * @param mem_ctx The talloc context that will own the generated log line.
439  * @param module the ldb module
440  * @param request the request
441  * @param reply the result/response
442  * @param status the status code returned for the underlying ldb operation.
443  *
444  * @return the generated log line.
445  */
446 static char *password_change_human_readable(
447         TALLOC_CTX *mem_ctx,
448         struct ldb_module *module,
449         const struct ldb_request *request,
450         const struct ldb_reply *reply)
451 {
452         struct ldb_context *ldb = NULL;
453         const char *remote_host = NULL;
454         const struct dom_sid *sid = NULL;
455         const char *user_sid = NULL;
456         const char *timestamp = NULL;
457         char *log_entry = NULL;
458         const char *action = NULL;
459         const char *dn = NULL;
460
461         TALLOC_CTX *ctx = talloc_new(NULL);
462
463         ldb = ldb_module_get_ctx(module);
464
465         remote_host = dsdb_audit_get_remote_host(ldb, ctx);
466         sid = dsdb_audit_get_user_sid(module);
467         user_sid = dom_sid_string(ctx, sid);
468         timestamp = audit_get_timestamp(ctx);
469         action = get_password_action(request, reply);
470         dn = dsdb_audit_get_primary_dn(request);
471
472         log_entry = talloc_asprintf(
473                 mem_ctx,
474                 "[%s] at [%s] status [%s] "
475                 "remote host [%s] SID [%s] DN [%s]",
476                 action,
477                 timestamp,
478                 ldb_strerror(reply->error),
479                 remote_host,
480                 user_sid,
481                 dn);
482         TALLOC_FREE(ctx);
483         return log_entry;
484 }
485 /*
486  * @brief Generate a human readable string, detailing attributes in a message
487  *
488  * For modify operations each attribute is prefixed with the action.
489  * Normal values are enclosed in []
490  * Base64 values are enclosed in {}
491  * Truncated values are indicated by three trailing dots "..."
492  *
493  * @param ldb The ldb_context
494  * @param buffer The attributes will be appended to the buffer.
495  *               assumed to have been allocated via talloc.
496  * @param operation The operation type
497  * @param message the message to process
498  *
499  */
500 static char *log_attributes(
501         struct ldb_context *ldb,
502         char *buffer,
503         enum ldb_request_type operation,
504         const struct ldb_message *message)
505 {
506         int i, j;
507         for (i=0;i<message->num_elements;i++) {
508                 if (i > 0) {
509                         buffer = talloc_asprintf_append_buffer(buffer, " ");
510                 }
511
512                 if (message->elements[i].name == NULL) {
513                         ldb_debug(
514                                 ldb,
515                                 LDB_DEBUG_ERROR,
516                                 "Error: Invalid element name (NULL) at "
517                                 "position %d", i);
518                         return NULL;
519                 }
520
521                 if (operation == LDB_MODIFY) {
522                         const char *action =NULL;
523                         action = dsdb_audit_get_modification_action(
524                                 message->elements[i].flags);
525                         buffer = talloc_asprintf_append_buffer(
526                                 buffer,
527                                 "%s: %s ",
528                                 action,
529                                 message->elements[i].name);
530                 } else {
531                         buffer = talloc_asprintf_append_buffer(
532                                 buffer,
533                                 "%s ",
534                                 message->elements[i].name);
535                 }
536
537                 if (dsdb_audit_redact_attribute(message->elements[i].name)) {
538                         /*
539                          * Do not log the value of any secret or password
540                          * attributes
541                          */
542                         buffer = talloc_asprintf_append_buffer(
543                                 buffer,
544                                 "[REDACTED SECRET ATTRIBUTE]");
545                         continue;
546                 }
547
548                 for (j=0;j<message->elements[i].num_values;j++) {
549                         struct ldb_val v;
550                         bool use_b64_encode = false;
551                         int length;
552                         if (j > 0) {
553                                 buffer = talloc_asprintf_append_buffer(
554                                         buffer,
555                                         " ");
556                         }
557
558                         v = message->elements[i].values[j];
559                         length = min(MAX_LENGTH, v.length);
560                         use_b64_encode = ldb_should_b64_encode(ldb, &v);
561                         if (use_b64_encode) {
562                                 const char *encoded = ldb_base64_encode(
563                                         buffer,
564                                         (char *)v.data,
565                                         length);
566                                 buffer = talloc_asprintf_append_buffer(
567                                         buffer,
568                                         "{%s%s}",
569                                         encoded,
570                                         (v.length > MAX_LENGTH ? "..." : ""));
571                         } else {
572                                 buffer = talloc_asprintf_append_buffer(
573                                         buffer,
574                                         "[%*.*s%s]",
575                                         length,
576                                         length,
577                                         (char *)v.data,
578                                         (v.length > MAX_LENGTH ? "..." : ""));
579                         }
580                 }
581         }
582         return buffer;
583 }
584
585 /*
586  * @brief generate a human readable log entry detailing an ldb operation.
587  *
588  * Generate a human readable log entry detailing an ldb operation.
589  *
590  * @param mem_ctx The talloc context owning the returned string.
591  * @param module the ldb module
592  * @param request the request
593  * @param reply the result of the operation
594  *
595  * @return the log entry.
596  *
597  */
598 static char *operation_human_readable(
599         TALLOC_CTX *mem_ctx,
600         struct ldb_module *module,
601         const struct ldb_request *request,
602         const struct ldb_reply *reply)
603 {
604         struct ldb_context *ldb = NULL;
605         const char *remote_host = NULL;
606         const struct dom_sid *sid = NULL;
607         const char *user_sid = NULL;
608         const char *timestamp = NULL;
609         const char *op_name = NULL;
610         char *log_entry = NULL;
611         const char *dn = NULL;
612         const char *new_dn = NULL;
613         const struct ldb_message *message = NULL;
614
615         TALLOC_CTX *ctx = talloc_new(NULL);
616
617         ldb = ldb_module_get_ctx(module);
618
619         remote_host = dsdb_audit_get_remote_host(ldb, ctx);
620         if (remote_host != NULL && dsdb_audit_is_system_session(module)) {
621                 sid = dsdb_audit_get_actual_sid(ldb);
622         } else {
623                 sid = dsdb_audit_get_user_sid(module);
624         }
625         user_sid = dom_sid_string(ctx, sid);
626         timestamp = audit_get_timestamp(ctx);
627         op_name = dsdb_audit_get_operation_name(request);
628         dn = dsdb_audit_get_primary_dn(request);
629         new_dn = dsdb_audit_get_secondary_dn(request);
630
631         message = dsdb_audit_get_message(request);
632
633         log_entry = talloc_asprintf(
634                 mem_ctx,
635                 "[%s] at [%s] status [%s] "
636                 "remote host [%s] SID [%s] DN [%s]",
637                 op_name,
638                 timestamp,
639                 ldb_strerror(reply->error),
640                 remote_host,
641                 user_sid,
642                 dn);
643         if (new_dn != NULL) {
644                 log_entry = talloc_asprintf_append_buffer(
645                         log_entry,
646                         " New DN [%s]",
647                         new_dn);
648         }
649         if (message != NULL) {
650                 log_entry = talloc_asprintf_append_buffer(log_entry,
651                                                           " attributes [");
652                 log_entry = log_attributes(ldb,
653                                            log_entry,
654                                            request->operation,
655                                            message);
656                 log_entry = talloc_asprintf_append_buffer(log_entry, "]");
657         }
658         TALLOC_FREE(ctx);
659         return log_entry;
660 }
661
662 /*
663  * @brief generate a human readable log entry detailing a replicated update
664  *        operation.
665  *
666  * Generate a human readable log entry detailing a replicated update operation
667  *
668  * @param mem_ctx The talloc context owning the returned string.
669  * @param module the ldb module
670  * @param request the request
671  * @param reply the result of the operation.
672  *
673  * @return the log entry.
674  *
675  */
676 static char *replicated_update_human_readable(
677         TALLOC_CTX *mem_ctx,
678         struct ldb_module *module,
679         const struct ldb_request *request,
680         const struct ldb_reply *reply)
681 {
682         struct dsdb_extended_replicated_objects *ro = talloc_get_type(
683                 request->op.extended.data,
684                 struct dsdb_extended_replicated_objects);
685         const char *partition_dn = NULL;
686         const char *error = NULL;
687         char *log_entry = NULL;
688         char *timestamp = NULL;
689         struct GUID_txt_buf object_buf;
690         const char *object = NULL;
691         struct GUID_txt_buf invocation_buf;
692         const char *invocation = NULL;
693
694
695         TALLOC_CTX *ctx = talloc_new(NULL);
696
697         timestamp = audit_get_timestamp(ctx);
698         error = get_friendly_werror_msg(ro->error);
699         partition_dn = ldb_dn_get_linearized(ro->partition_dn);
700         object = GUID_buf_string(
701                 &ro->source_dsa->source_dsa_obj_guid,
702                 &object_buf);
703         invocation = GUID_buf_string(
704                 &ro->source_dsa->source_dsa_invocation_id,
705                 &invocation_buf);
706
707
708         log_entry = talloc_asprintf(
709                 mem_ctx,
710                 "at [%s] status [%s] error [%s] partition [%s] objects [%d] "
711                 "links [%d] object [%s] invocation [%s]",
712                 timestamp,
713                 ldb_strerror(reply->error),
714                 error,
715                 partition_dn,
716                 ro->num_objects,
717                 ro->linked_attributes_count,
718                 object,
719                 invocation);
720
721         TALLOC_FREE(ctx);
722         return log_entry;
723 }
724 /*
725  * @brief create a human readable log entry detailing a transaction event.
726  *
727  * Create a human readable log entry detailing a transaction event.
728  * i.e. begin, commit, roll back
729  *
730  * @param mem_ctx The talloc context owning the returned string.
731  * @param action a one word description of the event/action
732  * @param duration the duration of the transaction.
733  *
734  * @return the log entry
735  */
736 static char *transaction_human_readable(
737         TALLOC_CTX *mem_ctx,
738         const char* action,
739         const int64_t duration)
740 {
741         const char *timestamp = NULL;
742         char *log_entry = NULL;
743
744         TALLOC_CTX *ctx = talloc_new(NULL);
745
746         timestamp = audit_get_timestamp(ctx);
747
748         log_entry = talloc_asprintf(
749                 mem_ctx,
750                 "[%s] at [%s] duration [%ld]",
751                 action,
752                 timestamp,
753                 duration);
754
755         TALLOC_FREE(ctx);
756         return log_entry;
757 }
758
759 /*
760  * @brief generate a human readable log entry detailing a commit failure.
761  *
762  * Generate generate a human readable log entry detailing a commit failure.
763  *
764  * @param mem_ctx The talloc context owning the returned string.
765  * @param action the commit action, "prepare" or "commit"
766  * @param status the status code returned by commit
767  * @param reason any extra failure information/reason available
768  *
769  * @return the log entry
770  */
771 static char *commit_failure_human_readable(
772         TALLOC_CTX *mem_ctx,
773         const char *action,
774         const int64_t duration,
775         int status,
776         const char *reason)
777 {
778         const char *timestamp = NULL;
779         char *log_entry = NULL;
780
781         TALLOC_CTX *ctx = talloc_new(NULL);
782
783         timestamp = audit_get_timestamp(ctx);
784
785         log_entry = talloc_asprintf(
786                 mem_ctx,
787                 "[%s] at [%s] duration [%ld] status [%d] reason [%s]",
788                 action,
789                 timestamp,
790                 duration,
791                 status,
792                 reason);
793
794         TALLOC_FREE(ctx);
795         return log_entry;
796 }
797
798 /*
799  * @brief log details of a standard ldb operation.
800  *
801  * Log the details of an ldb operation in JSON and or human readable format
802  * and send over the message bus.
803  *
804  * @param module the ldb_module
805  * @param request the operation request.
806  * @param reply the operation result.
807  * @param the status code returned for the operation.
808  *
809  */
810 static void log_standard_operation(
811         struct ldb_module *module,
812         const struct ldb_request *request,
813         const struct ldb_reply *reply)
814 {
815
816         const struct ldb_message *message = dsdb_audit_get_message(request);
817         bool password_changed = has_password_changed(message);
818         struct audit_context *ac =
819                 talloc_get_type(ldb_module_get_private(module),
820                                 struct audit_context);
821
822         TALLOC_CTX *ctx = talloc_new(NULL);
823
824         if (CHECK_DEBUGLVLC(DBGC_DSDB_AUDIT, OPERATION_LOG_LVL)) {
825                 char *entry = NULL;
826                 entry = operation_human_readable(
827                         ctx,
828                         module,
829                         request,
830                         reply);
831                 audit_log_human_text(
832                         OPERATION_HR_TAG,
833                         entry,
834                         DBGC_DSDB_AUDIT,
835                         OPERATION_LOG_LVL);
836                 TALLOC_FREE(entry);
837         }
838         if (CHECK_DEBUGLVLC(DBGC_DSDB_PWD_AUDIT, PASSWORD_LOG_LVL)) {
839                 if (password_changed) {
840                         char *entry = NULL;
841                         entry = password_change_human_readable(
842                                 ctx,
843                                 module,
844                                 request,
845                                 reply);
846                         audit_log_human_text(
847                                 PASSWORD_HR_TAG,
848                                 entry,
849                                 DBGC_DSDB_PWD_AUDIT,
850                                 PASSWORD_LOG_LVL);
851                         TALLOC_FREE(entry);
852                 }
853         }
854 #ifdef HAVE_JANSSON
855         if (CHECK_DEBUGLVLC(DBGC_DSDB_AUDIT_JSON, OPERATION_LOG_LVL) ||
856                 (ac->msg_ctx && ac->send_samdb_events)) {
857                 struct json_object json;
858                 json = operation_json(module, request, reply);
859                 audit_log_json(
860                         OPERATION_JSON_TYPE,
861                         &json,
862                         DBGC_DSDB_AUDIT_JSON,
863                         OPERATION_LOG_LVL);
864                 if (ac->msg_ctx && ac->send_password_events) {
865                         audit_message_send(
866                                 ac->msg_ctx,
867                                 DSDB_EVENT_NAME,
868                                 MSG_DSDB_LOG,
869                                 &json);
870                 }
871                 json_free(&json);
872         }
873         if (CHECK_DEBUGLVLC(DBGC_DSDB_PWD_AUDIT_JSON, PASSWORD_LOG_LVL) ||
874                 (ac->msg_ctx && ac->send_password_events)) {
875                 if (password_changed) {
876                         struct json_object json;
877                         json = password_change_json(module, request, reply);
878                         audit_log_json(
879                                 PASSWORD_JSON_TYPE,
880                                 &json,
881                                 DBGC_DSDB_PWD_AUDIT_JSON,
882                                 PASSWORD_LOG_LVL);
883                         if (ac->send_password_events) {
884                                 audit_message_send(
885                                         ac->msg_ctx,
886                                         DSDB_PWD_EVENT_NAME,
887                                         MSG_DSDB_PWD_LOG,
888                                         &json);
889                         }
890                         json_free(&json);
891                 }
892         }
893 #endif
894         TALLOC_FREE(ctx);
895 }
896
897 /*
898  * @brief log details of a replicated update.
899  *
900  * Log the details of a replicated update in JSON and or human readable
901  * format and send over the message bus.
902  *
903  * @param module the ldb_module
904  * @param request the operation request
905  * @param reply the result of the operation.
906  *
907  */
908 static void log_replicated_operation(
909         struct ldb_module *module,
910         const struct ldb_request *request,
911         const struct ldb_reply *reply)
912 {
913
914         struct audit_context *ac =
915                 talloc_get_type(ldb_module_get_private(module),
916                                 struct audit_context);
917
918         TALLOC_CTX *ctx = talloc_new(NULL);
919
920         if (CHECK_DEBUGLVLC(DBGC_DSDB_AUDIT, REPLICATION_LOG_LVL)) {
921                 char *entry = NULL;
922                 entry = replicated_update_human_readable(
923                         ctx,
924                         module,
925                         request,
926                         reply);
927                 audit_log_human_text(
928                         REPLICATION_HR_TAG,
929                         entry,
930                         DBGC_DSDB_AUDIT,
931                         REPLICATION_LOG_LVL);
932                 TALLOC_FREE(entry);
933         }
934 #ifdef HAVE_JANSSON
935         if (CHECK_DEBUGLVLC(DBGC_DSDB_AUDIT_JSON, REPLICATION_LOG_LVL) ||
936                 (ac->msg_ctx && ac->send_samdb_events)) {
937                 struct json_object json;
938                 json = replicated_update_json(module, request, reply);
939                 audit_log_json(
940                         REPLICATION_JSON_TYPE,
941                         &json,
942                         DBGC_DSDB_AUDIT_JSON,
943                         REPLICATION_LOG_LVL);
944                 if (ac->send_samdb_events) {
945                         audit_message_send(
946                                 ac->msg_ctx,
947                                 DSDB_EVENT_NAME,
948                                 MSG_DSDB_LOG,
949                                 &json);
950                 }
951                 json_free(&json);
952         }
953 #endif
954         TALLOC_FREE(ctx);
955 }
956
957 /*
958  * @brief log details of an ldb operation.
959  *
960  * Log the details of an ldb operation in JSON and or human readable format
961  * and send over the message bus.
962  *
963  * @param module the ldb_module
964  * @param request the operation request
965  * @part reply the result of the operation
966  *
967  */
968 static void log_operation(
969         struct ldb_module *module,
970         const struct ldb_request *request,
971         const struct ldb_reply *reply)
972 {
973
974         if (request->operation == LDB_EXTENDED) {
975                 if (strcmp(
976                         request->op.extended.oid,
977                         DSDB_EXTENDED_REPLICATED_OBJECTS_OID) != 0) {
978
979                         log_replicated_operation(module, request, reply);
980                 }
981         } else {
982                 log_standard_operation(module, request, reply);
983         }
984 }
985
986 /*
987  * @brief log details of a transaction event.
988  *
989  * Log the details of a transaction event in JSON and or human readable format
990  * and send over the message bus.
991  *
992  * @param module the ldb_module
993  * @param action the transaction event i.e. begin, commit, roll back.
994  * @param log_level the logging level
995  *
996  */
997 static void log_transaction(
998         struct ldb_module *module,
999         const char *action,
1000         int log_level)
1001 {
1002
1003         struct audit_context *ac =
1004                 talloc_get_type(ldb_module_get_private(module),
1005                                 struct audit_context);
1006         const struct timeval now = timeval_current();
1007         const int64_t duration = usec_time_diff(&now, &ac->transaction_start);
1008
1009         TALLOC_CTX *ctx = talloc_new(NULL);
1010
1011         if (CHECK_DEBUGLVLC(DBGC_DSDB_TXN_AUDIT, log_level)) {
1012                 char* entry = NULL;
1013                 entry = transaction_human_readable(ctx, action, duration);
1014                 audit_log_human_text(
1015                         TRANSACTION_HR_TAG,
1016                         entry,
1017                         DBGC_DSDB_TXN_AUDIT,
1018                         log_level);
1019                 TALLOC_FREE(entry);
1020         }
1021 #ifdef HAVE_JANSSON
1022         if (CHECK_DEBUGLVLC(DBGC_DSDB_TXN_AUDIT_JSON, log_level) ||
1023                 (ac->msg_ctx && ac->send_samdb_events)) {
1024                 struct json_object json;
1025                 json = transaction_json(
1026                         action,
1027                         &ac->transaction_guid,
1028                         duration);
1029                 audit_log_json(
1030                         TRANSACTION_JSON_TYPE,
1031                         &json,
1032                         DBGC_DSDB_TXN_AUDIT_JSON,
1033                         log_level);
1034                 if (ac->send_samdb_events) {
1035                         audit_message_send(
1036                                 ac->msg_ctx,
1037                                 DSDB_EVENT_NAME,
1038                                 MSG_DSDB_LOG,
1039                                 &json);
1040                 }
1041                 json_free(&json);
1042         }
1043 #endif
1044         TALLOC_FREE(ctx);
1045 }
1046
1047 /*
1048  * @brief log details of a commit failure.
1049  *
1050  * Log the details of a commit failure in JSON and or human readable
1051  * format and send over the message bus.
1052  *
1053  * @param module the ldb_module
1054  * @param action the commit action "prepare" or "commit"
1055  * @param status the ldb status code returned by prepare commit.
1056  *
1057  */
1058 static void log_commit_failure(
1059         struct ldb_module *module,
1060         const char *action,
1061         int status)
1062 {
1063
1064         struct audit_context *ac =
1065                 talloc_get_type(ldb_module_get_private(module),
1066                                 struct audit_context);
1067         const char* reason = dsdb_audit_get_ldb_error_string(module, status);
1068         const int log_level = TRANSACTION_LOG_FAILURE_LVL;
1069         const struct timeval now = timeval_current();
1070         const int64_t duration = usec_time_diff(&now, &ac->transaction_start);
1071
1072         TALLOC_CTX *ctx = talloc_new(NULL);
1073
1074         if (CHECK_DEBUGLVLC(DBGC_DSDB_TXN_AUDIT, log_level)) {
1075
1076                 char* entry = NULL;
1077                 entry = commit_failure_human_readable(
1078                         ctx,
1079                         action,
1080                         duration,
1081                         status,
1082                         reason);
1083                 audit_log_human_text(
1084                         TRANSACTION_HR_TAG,
1085                         entry,
1086                         DBGC_DSDB_TXN_AUDIT,
1087                         TRANSACTION_LOG_FAILURE_LVL);
1088                 TALLOC_FREE(entry);
1089         }
1090 #ifdef HAVE_JANSSON
1091         if (CHECK_DEBUGLVLC(DBGC_DSDB_TXN_AUDIT_JSON, log_level) ||
1092                 (ac->msg_ctx && ac->send_samdb_events)) {
1093                 struct json_object json;
1094                 json = commit_failure_json(
1095                         action,
1096                         duration,
1097                         status,
1098                         reason,
1099                         &ac->transaction_guid);
1100                 audit_log_json(
1101                         TRANSACTION_JSON_TYPE,
1102                         &json,
1103                         DBGC_DSDB_TXN_AUDIT_JSON,
1104                         log_level);
1105                 if (ac->send_samdb_events) {
1106                         audit_message_send(ac->msg_ctx,
1107                                            DSDB_EVENT_NAME,
1108                                            MSG_DSDB_LOG,
1109                                            &json);
1110                 }
1111                 json_free(&json);
1112         }
1113 #endif
1114         TALLOC_FREE(ctx);
1115 }
1116
1117 /*
1118  * Context needed by audit_callback
1119  */
1120 struct audit_callback_context {
1121         struct ldb_request *request;
1122         struct ldb_module *module;
1123 };
1124
1125 /*
1126  * @brief call back function for the ldb_operations.
1127  *
1128  * As the LDB operations are async, and we wish to examine the results of
1129  * the operations, a callback needs to be registered to process the results
1130  * of the LDB operations.
1131  *
1132  * @param req the ldb request
1133  * @param res the result of the operation
1134  *
1135  * @return the LDB_STATUS
1136  */
1137 static int audit_callback(struct ldb_request *req, struct ldb_reply *ares)
1138 {
1139         struct audit_callback_context *ac = NULL;
1140
1141         ac = talloc_get_type(
1142                 req->context,
1143                 struct audit_callback_context);
1144
1145         if (!ares) {
1146                 return ldb_module_done(
1147                         ac->request,
1148                         NULL,
1149                         NULL,
1150                         LDB_ERR_OPERATIONS_ERROR);
1151         }
1152
1153         /* pass on to the callback */
1154         switch (ares->type) {
1155         case LDB_REPLY_ENTRY:
1156                 return ldb_module_send_entry(
1157                         ac->request,
1158                         ares->message,
1159                         ares->controls);
1160
1161         case LDB_REPLY_REFERRAL:
1162                 return ldb_module_send_referral(
1163                         ac->request,
1164                         ares->referral);
1165
1166         case LDB_REPLY_DONE:
1167                 /*
1168                  * Log the operation once DONE
1169                  */
1170                 log_operation(ac->module, ac->request, ares);
1171                 return ldb_module_done(
1172                         ac->request,
1173                         ares->controls,
1174                         ares->response,
1175                         ares->error);
1176
1177         default:
1178                 /* Can't happen */
1179                 return LDB_ERR_OPERATIONS_ERROR;
1180         }
1181 }
1182
1183 /*
1184  * @brief Add the current transaction identifier to the request.
1185  *
1186  * Add the current transaction identifier in the module private data,
1187  * to the request as a control.
1188  *
1189  * @param module
1190  * @param req the request.
1191  *
1192  * @return an LDB_STATUS code, LDB_SUCCESS if successful.
1193  */
1194 static int add_transaction_id(
1195         struct ldb_module *module,
1196         struct ldb_request *req)
1197 {
1198         struct audit_context *ac =
1199                 talloc_get_type(ldb_module_get_private(module),
1200                                 struct audit_context);
1201         struct dsdb_control_transaction_identifier *transaction_id;
1202         int ret;
1203
1204         transaction_id = talloc_zero(
1205                 req,
1206                 struct dsdb_control_transaction_identifier);
1207         if (transaction_id == NULL) {
1208                 struct ldb_context *ldb = ldb_module_get_ctx(module);
1209                 return ldb_oom(ldb);
1210         }
1211         transaction_id->transaction_guid = ac->transaction_guid;
1212         ret = ldb_request_add_control(req,
1213                                       DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID,
1214                                       false,
1215                                       transaction_id);
1216         return ret;
1217
1218 }
1219
1220 /*
1221  * @brief log details of an add operation.
1222  *
1223  * Log the details of an add operation.
1224  *
1225  * @param module the ldb_module
1226  * @param req the ldb_request
1227  *
1228  * @return ldb status code
1229  */
1230 static int log_add(
1231         struct ldb_module *module,
1232         struct ldb_request *req)
1233 {
1234         struct audit_callback_context *context = NULL;
1235         struct ldb_request *new_req = NULL;
1236         struct ldb_context *ldb = NULL;
1237         int ret;
1238
1239         ldb = ldb_module_get_ctx(module);
1240         context = talloc_zero(req, struct audit_callback_context);
1241
1242         if (context == NULL) {
1243                 return ldb_oom(ldb);
1244         }
1245         context->request = req;
1246         context->module  = module;
1247         /*
1248          * We want to log the return code status, so we need to register
1249          * a callback function to get the actual result.
1250          * We need to take a new copy so that we don't alter the callers copy
1251          */
1252         ret = ldb_build_add_req(
1253                 &new_req,
1254                 ldb,
1255                 req,
1256                 req->op.add.message,
1257                 req->controls,
1258                 context,
1259                 audit_callback,
1260                 req);
1261         if (ret != LDB_SUCCESS) {
1262                 return ret;
1263         }
1264         ret = add_transaction_id(module, new_req);
1265         if (ret != LDB_SUCCESS) {
1266                 return ret;
1267         }
1268         return ldb_next_request(module, new_req);
1269 }
1270
1271 /*
1272  * @brief log details of an delete operation.
1273  *
1274  * Log the details of an delete operation.
1275  *
1276  * @param module the ldb_module
1277  * @param req the ldb_request
1278  *
1279  * @return ldb status code
1280  */
1281 static int log_delete(
1282         struct ldb_module *module,
1283         struct ldb_request *req)
1284 {
1285         struct audit_callback_context *context = NULL;
1286         struct ldb_request *new_req = NULL;
1287         struct ldb_context *ldb = NULL;
1288         int ret;
1289
1290         ldb = ldb_module_get_ctx(module);
1291         context = talloc_zero(req, struct audit_callback_context);
1292
1293         if (context == NULL) {
1294                 return ldb_oom(ldb);
1295         }
1296         context->request = req;
1297         context->module  = module;
1298         /*
1299          * We want to log the return code status, so we need to register
1300          * a callback function to get the actual result.
1301          * We need to take a new copy so that we don't alter the callers copy
1302          */
1303         ret = ldb_build_del_req(&new_req,
1304                                 ldb,
1305                                 req,
1306                                 req->op.del.dn,
1307                                 req->controls,
1308                                 context,
1309                                 audit_callback,
1310                                 req);
1311         if (ret != LDB_SUCCESS) {
1312                 return ret;
1313         }
1314         ret = add_transaction_id(module, new_req);
1315         if (ret != LDB_SUCCESS) {
1316                 return ret;
1317         }
1318         return ldb_next_request(module, new_req);
1319 }
1320
1321 /*
1322  * @brief log details of a modify operation.
1323  *
1324  * Log the details of a modify operation.
1325  *
1326  * @param module the ldb_module
1327  * @param req the ldb_request
1328  *
1329  * @return ldb status code
1330  */
1331 static int log_modify(
1332         struct ldb_module *module,
1333         struct ldb_request *req)
1334 {
1335         struct audit_callback_context *context = NULL;
1336         struct ldb_request *new_req = NULL;
1337         struct ldb_context *ldb = NULL;
1338         int ret;
1339
1340         ldb = ldb_module_get_ctx(module);
1341         context = talloc_zero(req, struct audit_callback_context);
1342
1343         if (context == NULL) {
1344                 return ldb_oom(ldb);
1345         }
1346         context->request = req;
1347         context->module  = module;
1348         /*
1349          * We want to log the return code status, so we need to register
1350          * a callback function to get the actual result.
1351          * We need to take a new copy so that we don't alter the callers copy
1352          */
1353         ret = ldb_build_mod_req(
1354                 & new_req,
1355                 ldb,
1356                 req,
1357                 req->op.mod.message,
1358                 req->controls,
1359                 context,
1360                 audit_callback,
1361                 req);
1362         if (ret != LDB_SUCCESS) {
1363                 return ret;
1364         }
1365         ret = add_transaction_id(module, new_req);
1366         if (ret != LDB_SUCCESS) {
1367                 return ret;
1368         }
1369         return ldb_next_request(module, new_req);
1370 }
1371
1372 /*
1373  * @brief process a transaction start.
1374  *
1375  * process a transaction start, as we don't currently log transaction starts
1376  * just generate the new transaction_id.
1377  *
1378  * @param module the ldb_module
1379  * @param req the ldb_request
1380  *
1381  * @return ldb status code
1382  */
1383 static int log_start_transaction(struct ldb_module *module)
1384 {
1385         struct audit_context *ac =
1386                 talloc_get_type(ldb_module_get_private(module),
1387                                 struct audit_context);
1388
1389         /*
1390          * We do not log transaction begins
1391          * however we do generate a new transaction_id and record the start
1392          * time so that we can log the transaction duration.
1393          *
1394          */
1395         ac->transaction_guid = GUID_random();
1396         ac->transaction_start = timeval_current();
1397         return ldb_next_start_trans(module);
1398 }
1399
1400 /*
1401  * @brief log details of a prepare commit.
1402  *
1403  * Log the details of a prepare commit, currently only details of
1404  * failures are logged.
1405  *
1406  * @param module the ldb_module
1407  * @param req the ldb_request
1408  *
1409  * @return ldb status code
1410  */
1411 static int log_prepare_commit(struct ldb_module *module)
1412 {
1413
1414         int ret = ldb_next_prepare_commit(module);
1415         if (ret != LDB_SUCCESS) {
1416                 /*
1417                  * We currently only log prepare commit failures
1418                  */
1419                 log_commit_failure(module, "prepare", ret);
1420         }
1421         return ret;
1422 }
1423
1424 /*
1425  * @brief process a transaction end aka commit.
1426  *
1427  * process a transaction end, as we don't currently log transaction ends
1428  * just clear transaction_id.
1429  *
1430  * @param module the ldb_module
1431  * @param req the ldb_request
1432  *
1433  * @return ldb status code
1434  */
1435 static int log_end_transaction(struct ldb_module *module)
1436 {
1437         struct audit_context *ac =
1438                 talloc_get_type(ldb_module_get_private(module),
1439                                 struct audit_context);
1440         int ret = 0;
1441
1442
1443         ret = ldb_next_end_trans(module);
1444         if (ret == LDB_SUCCESS) {
1445                 log_transaction(
1446                         module,
1447                         "commit",
1448                         TRANSACTION_LOG_COMPLETION_LVL);
1449         } else {
1450                 log_commit_failure(module, "commit", ret);
1451         }
1452         /*
1453          * Clear the transaction id inserted by log_start_transaction
1454          */
1455         memset(&ac->transaction_guid, 0, sizeof(struct GUID));
1456         return ret;
1457 }
1458
1459 /*
1460  * @brief log details of a transaction delete aka roll back.
1461  *
1462  * Log details of a transaction roll back.
1463  *
1464  * @param module the ldb_module
1465  * @param req the ldb_request
1466  *
1467  * @return ldb status code
1468  */
1469 static int log_del_transaction(struct ldb_module *module)
1470 {
1471         struct audit_context *ac =
1472                 talloc_get_type(ldb_module_get_private(module),
1473                                 struct audit_context);
1474
1475         log_transaction(module, "rollback", TRANSACTION_LOG_FAILURE_LVL);
1476         memset(&ac->transaction_guid, 0, sizeof(struct GUID));
1477         return ldb_next_del_trans(module);
1478 }
1479
1480 /*
1481  * @brief log details of an extended operation.
1482  *
1483  * Log the details of an extended operation.
1484  *
1485  * @param module the ldb_module
1486  * @param req the ldb_request
1487  *
1488  * @return ldb status code
1489  */
1490 static int log_extended(
1491         struct ldb_module *module,
1492         struct ldb_request *req)
1493 {
1494         struct audit_callback_context *context = NULL;
1495         struct ldb_request *new_req = NULL;
1496         struct ldb_context *ldb = NULL;
1497         int ret;
1498
1499         /*
1500          * Currently we only log replication extended operations
1501          */
1502         if (strcmp(
1503                 req->op.extended.oid,
1504                 DSDB_EXTENDED_REPLICATED_OBJECTS_OID) != 0) {
1505
1506                 return ldb_next_request(module, req);
1507         }
1508         ldb = ldb_module_get_ctx(module);
1509         context = talloc_zero(req, struct audit_callback_context);
1510
1511         if (context == NULL) {
1512                 return ldb_oom(ldb);
1513         }
1514         context->request = req;
1515         context->module  = module;
1516         /*
1517          * We want to log the return code status, so we need to register
1518          * a callback function to get the actual result.
1519          * We need to take a new copy so that we don't alter the callers copy
1520          */
1521         ret = ldb_build_extended_req(
1522                 &new_req,
1523                 ldb,
1524                 req,
1525                 req->op.extended.oid,
1526                 req->op.extended.data,
1527                 req->controls,
1528                 context,
1529                 audit_callback,
1530                 req);
1531         if (ret != LDB_SUCCESS) {
1532                 return ret;
1533         }
1534         ret = add_transaction_id(module, new_req);
1535         if (ret != LDB_SUCCESS) {
1536                 return ret;
1537         }
1538         return ldb_next_request(module, new_req);
1539 }
1540
1541 /*
1542  * @brief module initialisation
1543  */
1544 static int log_init(struct ldb_module *module)
1545 {
1546
1547         struct ldb_context *ldb = ldb_module_get_ctx(module);
1548         struct audit_context *context = NULL;
1549         struct loadparm_context *lp_ctx
1550                 = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
1551                                         struct loadparm_context);
1552         struct tevent_context *ec = ldb_get_event_context(ldb);
1553         bool sdb_events = false;
1554         bool pwd_events = false;
1555
1556         context = talloc_zero(module, struct audit_context);
1557         if (context == NULL) {
1558                 return ldb_module_oom(module);
1559         }
1560
1561         if (lp_ctx != NULL) {
1562                 sdb_events = lpcfg_dsdb_event_notification(lp_ctx);
1563                 pwd_events = lpcfg_dsdb_password_event_notification(lp_ctx);
1564         }
1565         if (sdb_events || pwd_events) {
1566                 context->send_samdb_events = sdb_events;
1567                 context->send_password_events = pwd_events;
1568                 context->msg_ctx = imessaging_client_init(ec, lp_ctx, ec);
1569         }
1570
1571         ldb_module_set_private(module, context);
1572         return ldb_next_init(module);
1573 }
1574
1575 static const struct ldb_module_ops ldb_audit_log_module_ops = {
1576         .name              = "audit_log",
1577         .init_context      = log_init,
1578         .add               = log_add,
1579         .modify            = log_modify,
1580         .del               = log_delete,
1581         .start_transaction = log_start_transaction,
1582         .prepare_commit    = log_prepare_commit,
1583         .end_transaction   = log_end_transaction,
1584         .del_transaction   = log_del_transaction,
1585         .extended          = log_extended,
1586 };
1587
1588 int ldb_audit_log_module_init(const char *version)
1589 {
1590         LDB_MODULE_CHECK_VERSION(version);
1591         return ldb_register_module(&ldb_audit_log_module_ops);
1592 }