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