summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/rbac/rbacaudit.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--contrib/slapd-modules/rbac/rbacaudit.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/contrib/slapd-modules/rbac/rbacaudit.c b/contrib/slapd-modules/rbac/rbacaudit.c
new file mode 100644
index 0000000..ef04ece
--- /dev/null
+++ b/contrib/slapd-modules/rbac/rbacaudit.c
@@ -0,0 +1,233 @@
+/* rbacaudit.c - RBAC Audit */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+
+#include "slap.h"
+#include "slap-config.h"
+#include "lutil.h"
+
+#include "rbac.h"
+
+static struct rbac_audit_op {
+ audit_op_t op;
+ struct berval op_bv;
+} rbac_audit_ops[] = {
+ { CreateSession, BER_BVC("CreateSession") },
+ { CheckAccess, BER_BVC("CheckAccess") },
+ { AddActiveRole, BER_BVC("AddActiveRole") },
+ { DropActiveRole, BER_BVC("DropActiveRole") },
+ { SessionPermissions, BER_BVC("SessionPermissions") },
+ { DeleteSession, BER_BVC("DeleteSession") },
+ { SessionRoles, BER_BVC("SessionRoles") },
+
+ { -1, BER_BVNULL }
+};
+
+static int
+rbac_audit_fake_cb( Operation *op, SlapReply *rs )
+{
+ Debug( LDAP_DEBUG_ANY, "rbac_audit_fake_cb\n" );
+
+ return 0;
+}
+
+void
+rbac_audit(
+ Operation *op,
+ audit_op_t rbac_op,
+ rbac_session_t *sessp,
+ rbac_req_t *reqp,
+ int result,
+ char *msg )
+{
+ int op_idx, rc = LDAP_SUCCESS;
+ int found = 0;
+ struct berval timestamp;
+ tenant_info_t *tenantp = rbac_tid2tenant( &sessp->tenantid );
+ slap_callback cb = { 0 };
+ SlapReply rs2 = { REP_RESULT };
+ Entry *e = NULL;
+ struct berval auditObjectClass = BER_BVC("rbacAudit");
+ struct berval auditResultSuccess = BER_BVC("success");
+ struct berval auditResultFailed = BER_BVC("failed");
+ struct berval bv, rdn, nrdn;
+ char rdnbuf[RBAC_BUFLEN];
+ time_t now;
+ char nowstr[LDAP_LUTIL_GENTIME_BUFSIZE];
+
+ for ( op_idx = 0; rbac_audit_ops[op_idx].op != -1; op_idx++ ) {
+ if ( rbac_op == rbac_audit_ops[op_idx].op ) {
+ /* legit audit op */
+ found = 1;
+ break;
+ }
+ }
+
+ if ( !found ) goto done;
+
+ e = entry_alloc();
+
+ /* audit timestamp */
+ now = slap_get_time(); /* stored for later consideration */
+ timestamp.bv_val = nowstr;
+ timestamp.bv_len = sizeof(nowstr);
+ slap_timestamp( &now, &timestamp );
+
+ /* construct audit record DN; FIXME: random() call */
+ sprintf( rdnbuf, "%s%d", RBAC_AUDIT_RDN_EQ, (int)op->o_tid );
+ strcat( rdnbuf, "-" );
+ strncat( rdnbuf, timestamp.bv_val, timestamp.bv_len );
+ bv.bv_val = &rdnbuf[0];
+ bv.bv_len = strlen( &rdnbuf[0] );
+
+ rc = dnPrettyNormal( NULL, &bv, &rdn, &nrdn, NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_audit: "
+ "unable to normalize audit rDN (rc=%d)\n", rc );
+ goto done;
+ }
+
+ /* FIXME: audit_basedn should have been normalized */
+ build_new_dn( &e->e_name, &tenantp->audit_basedn, &rdn, NULL );
+ build_new_dn( &e->e_nname, &tenantp->audit_basedn, &nrdn, NULL );
+
+ ch_free( rdn.bv_val );
+ ch_free( nrdn.bv_val );
+
+ /* add timestamp */
+ attr_merge_one( e, slap_rbac_schema.ad_audit_timestamp, &timestamp, NULL );
+
+ /* add rbac audit objectClass */
+
+ attr_merge_one( e, slap_schema.si_ad_objectClass, &auditObjectClass, NULL );
+ attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
+ &auditObjectClass, NULL );
+
+ /* audit op */
+ attr_merge_one( e, slap_rbac_schema.ad_audit_op,
+ &rbac_audit_ops[op_idx].op_bv, NULL );
+
+ /* userid */
+ if ( sessp && !BER_BVISNULL( &sessp->uid ) ) {
+ attr_merge_one( e, slap_schema.si_ad_uid, &sessp->uid, NULL );
+ }
+
+ /* session id */
+
+ if ( sessp && !BER_BVISNULL( &sessp->sessid ) ) {
+ AttributeDescription *ad = NULL;
+ const char *text = NULL;
+ struct berval sessid = BER_BVC("rbacSessid");
+
+ rc = slap_bv2ad( &sessid, &ad, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ goto done;
+ }
+ attr_merge_one( e, ad, &sessp->sessid, NULL );
+ }
+
+ /* audit result */
+ attr_merge_one( e, slap_rbac_schema.ad_audit_result,
+ result == LDAP_SUCCESS ? &auditResultSuccess : &auditResultFailed,
+ NULL );
+
+ switch ( rbac_op ) {
+ case CreateSession:
+ /* audit roles */
+ if ( sessp && sessp->roles ) {
+ attr_merge( e, slap_rbac_schema.ad_audit_roles, sessp->roles,
+ NULL );
+ }
+ if ( reqp && reqp->roles ) {
+ attr_merge( e, slap_rbac_schema.ad_audit_requested_roles,
+ reqp->roles, NULL );
+ }
+ break;
+
+ case CheckAccess:
+ if ( sessp && sessp->roles ) {
+ attr_merge( e, slap_rbac_schema.ad_audit_roles, sessp->roles,
+ NULL );
+ }
+ if ( reqp && !BER_BVISEMPTY( &reqp->opname ) ) {
+ attr_merge_one( e, slap_rbac_schema.ad_audit_operations,
+ &reqp->opname, NULL );
+ }
+ if ( reqp && !BER_BVISEMPTY( &reqp->objname ) ) {
+ attr_merge_one( e, slap_rbac_schema.ad_audit_objects,
+ &reqp->objname, NULL );
+ }
+ break;
+
+ case AddActiveRole:
+ if ( reqp && reqp->roles ) {
+ attr_merge( e, slap_rbac_schema.ad_audit_requested_roles,
+ reqp->roles, NULL );
+ }
+ break;
+
+ case DropActiveRole:
+ /* audit roles */
+ if ( reqp && reqp->roles ) {
+ attr_merge( e, slap_rbac_schema.ad_audit_requested_roles,
+ reqp->roles, NULL );
+ }
+ break;
+
+ case SessionPermissions:
+ if ( sessp && sessp->roles ) {
+ attr_merge( e, slap_rbac_schema.ad_audit_roles, sessp->roles,
+ NULL );
+ }
+ break;
+
+ case DeleteSession:
+ case SessionRoles:
+ default:
+ break;
+ }
+
+ /* record the audit record */
+ Operation op2 = *op;
+ rbac_callback_info_t rbac_cb;
+ cb.sc_private = &rbac_cb;
+ cb.sc_response = rbac_audit_fake_cb;
+ op2.o_callback = &cb;
+
+ op2.o_tag = LDAP_REQ_ADD;
+ op2.o_protocol = LDAP_VERSION3;
+ op2.o_req_dn = e->e_name;
+ op2.o_req_ndn = e->e_nname;
+ op2.ora_e = e;
+ op2.o_bd = select_backend( &op2.o_req_ndn, 0 );
+ op2.o_dn = op2.o_bd->be_rootdn;
+ op2.o_ndn = op2.o_bd->be_rootndn;
+
+ op2.ors_limit = NULL;
+ rc = op2.o_bd->be_add( &op2, &rs2 );
+
+done:
+ if ( e ) entry_free( e );
+
+ return;
+}