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