mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-18 12:54:09 -05:00
233 lines
5.7 KiB
C
233 lines
5.7 KiB
C
/* 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, ×tamp );
|
|
|
|
/* 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, ×tamp, 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;
|
|
}
|