summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/rbac/rbac.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:35:32 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:35:32 +0000
commit5ea77a75dd2d2158401331879f3c8f47940a732c (patch)
treed89dc06e9f4850a900f161e25f84e922c4f86cc8 /contrib/slapd-modules/rbac/rbac.c
parentInitial commit. (diff)
downloadopenldap-upstream/2.5.13+dfsg.tar.xz
openldap-upstream/2.5.13+dfsg.zip
Adding upstream version 2.5.13+dfsg.upstream/2.5.13+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--contrib/slapd-modules/rbac/rbac.c2169
1 files changed, 2169 insertions, 0 deletions
diff --git a/contrib/slapd-modules/rbac/rbac.c b/contrib/slapd-modules/rbac/rbac.c
new file mode 100644
index 0000000..4d2cff5
--- /dev/null
+++ b/contrib/slapd-modules/rbac/rbac.c
@@ -0,0 +1,2169 @@
+/* rbac.c - RBAC main file */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2013-2022 The OpenLDAP Foundation.
+ * 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"
+
+#define RBAC_REQ 1
+
+static slap_overinst rbac;
+
+static struct berval slap_EXOP_CREATE_SESSION =
+ BER_BVC(LDAP_RBAC_EXOP_CREATE_SESSION);
+static struct berval slap_EXOP_CHECK_ACCESS =
+ BER_BVC(LDAP_RBAC_EXOP_CHECK_ACCESS);
+static struct berval slap_EXOP_ADD_ACTIVE_ROLE =
+ BER_BVC(LDAP_RBAC_EXOP_ADD_ACTIVE_ROLE);
+static struct berval slap_EXOP_DROP_ACTIVE_ROLE =
+ BER_BVC(LDAP_RBAC_EXOP_DROP_ACTIVE_ROLE);
+static struct berval slap_EXOP_DELETE_SESSION =
+ BER_BVC(LDAP_RBAC_EXOP_DELETE_SESSION);
+static struct berval slap_EXOP_SESSION_ROLES =
+ BER_BVC(LDAP_RBAC_EXOP_SESSION_ROLES);
+
+rbac_tenant_t rbac_tenants = {
+ {
+ .schema = &slap_rbac_jts_schema,
+ },
+ NULL
+};
+
+static ConfigDriver rbac_cf_gen;
+
+static ConfigTable rbaccfg[] = {
+ { "rbac-default-users-base-dn", "usersDN", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_DEFAULT_USERS_BASE_DN,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.1 NAME 'olcRBACDefaultUsersBaseDn' "
+ "DESC 'default Base DN for RBAC users ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-default-roles-base-dn", "rolesDN", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_DEFAULT_ROLES_BASE_DN,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.2 NAME 'olcRBACDefaultRolesBaseDn' "
+ "DESC 'default base DN for RBAC roles ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-default-permissions-base-dn", "permissionsDN", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_DEFAULT_PERMISSIONS_BASE_DN,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.3 NAME 'olcRBACDefaultPermissionsBaseDn' "
+ "DESC 'default base DN for RBAC permissions ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-default-sessions-base-dn", "sessionsDN", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_DEFAULT_SESSIONS_BASE_DN,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.4 NAME 'olcRBACDefaultSessionsBaseDn' "
+ "DESC 'default base DN for RBAC permissions ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-admin", "adminDN", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_ADMIN_DN,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.5 NAME 'olcRBACAdminDn' "
+ "DESC 'default admin DN for RBAC repository ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-pwd", "adminPwd", 2, 2, 0,
+ ARG_MAGIC|RBAC_ADMIN_PWD,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.6 NAME 'olcRBACAdminPwd' "
+ "DESC 'default admin pwd for RBAC repository ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-session-admin", "sessionAdminDN", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_SESSION_ADMIN_DN,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.7 NAME 'olcRBACSessionAdminDn' "
+ "DESC 'admin DN for RBAC session repository ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-session-admin-pwd", "sessionAdminPwd", 2, 2, 0,
+ ARG_MAGIC|RBAC_SESSION_ADMIN_PWD,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.8 NAME 'olcRBACSessionAdminPwd' "
+ "DESC 'admin pwd for RBAC session repository ' "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "tenant", "tenant", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_TENANT,
+ rbac_cf_gen, "(OLcfgCtAt:7.9 NAME 'olcRBACTenant' "
+ "DESC 'RBAC tenant ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-default-audit-base-dn", "auditDN", 2, 2, 0,
+ ARG_MAGIC|ARG_DN|RBAC_DEFAULT_AUDIT_BASE_DN,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.10 NAME 'olcRBACDefaultAuditBaseDn' "
+ "DESC 'default base DN for RBAC audit records ' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+ { "rbac-default-tenant-id", "tenantId", 2, 2, 0,
+ ARG_MAGIC|RBAC_DEFAULT_TENANT_ID,
+ rbac_cf_gen,
+ "(OLcfgCtAt:7.11 NAME 'olcRBACDefaultTenantId' "
+ "DESC 'default tenant id' "
+ "SYNTAX OMsDirectoryString "
+ "SINGLE-VALUE )",
+ NULL, NULL
+ },
+
+ { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs rbac_ocs[] = {
+ { "( OLcfgCtOc:7.1 "
+ "NAME 'olcRBACConfig' "
+ "DESC 'RBAC configuration' "
+ "SUP olcOverlayConfig "
+ "MAY ( olcRBACDefaultUsersBaseDn $ olcRBACDefaultRolesBaseDn $ "
+ "olcRBACDefaultPermissionsBaseDn $ olcRBACDefaultSessionsBaseDn $ "
+ "olcRBACAdminDn $ olcRBACAdminPwd $ olcRBACSessionAdminDn $ "
+ "olcRBACSessionAdminPwd) )",
+ Cft_Overlay, rbaccfg },
+
+ { NULL, 0, NULL }
+};
+
+static slap_verbmasks rbac_keys[] = {
+ { BER_BVC("default_users_base_dn"), RBAC_DEFAULT_USERS_BASE_DN },
+ { BER_BVC("default_roles_base_dn"), RBAC_DEFAULT_ROLES_BASE_DN },
+ { BER_BVC("default_permissions_base_dn"),
+ RBAC_DEFAULT_PERMISSIONS_BASE_DN },
+ { BER_BVC("tenant"), RBAC_TENANT },
+
+ { BER_BVNULL, 0 }
+};
+
+static slap_verbmasks rbac_tenant_keys[] = {
+ { BER_BVC("id"), RBAC_TENANT_ID },
+ { BER_BVC("users_base_dn"), RBAC_USERS_BASE_DN },
+ { BER_BVC("roles_base_dn"), RBAC_ROLES_BASE_DN },
+ { BER_BVC("permissions_base_dn"), RBAC_PERMISSIONS_BASE_DN },
+
+ { BER_BVNULL, 0 }
+};
+
+static void
+rbac_tenant_parse( char *tenent_info, tenant_info_t *tenants )
+{
+ return;
+}
+
+static int
+rbac_cf_gen( ConfigArgs *c )
+{
+ slap_overinst *on = (slap_overinst *)c->bi;
+ rbac_tenant_t *ri = &rbac_tenants;
+ int rc = 0;
+
+ if ( c->op == SLAP_CONFIG_EMIT ) {
+ switch ( c->type ) {
+ case RBAC_DEFAULT_USERS_BASE_DN:
+ value_add_one( &c->rvalue_vals, &ri->tenant_info.users_basedn );
+ break;
+ case RBAC_DEFAULT_ROLES_BASE_DN:
+ value_add_one( &c->rvalue_vals, &ri->tenant_info.roles_basedn );
+ break;
+ case RBAC_DEFAULT_PERMISSIONS_BASE_DN:
+ value_add_one(
+ &c->rvalue_vals, &ri->tenant_info.permissions_basedn );
+ break;
+ case RBAC_DEFAULT_SESSIONS_BASE_DN:
+ value_add_one(
+ &c->rvalue_vals, &ri->tenant_info.sessions_basedn );
+ break;
+ case RBAC_DEFAULT_AUDIT_BASE_DN:
+ value_add_one( &c->rvalue_vals, &ri->tenant_info.audit_basedn );
+ break;
+ case RBAC_ADMIN_DN:
+ value_add_one( &c->rvalue_vals, &ri->tenant_info.admin );
+ break;
+ case RBAC_ADMIN_PWD:
+ value_add_one( &c->rvalue_vals, &ri->tenant_info.pwd );
+ break;
+ case RBAC_SESSION_ADMIN_DN:
+ value_add_one(
+ &c->rvalue_vals, &ri->tenant_info.session_admin );
+ break;
+ case RBAC_DEFAULT_TENANT_ID:
+ value_add_one( &c->rvalue_vals, &ri->tenant_info.tid );
+ break;
+ default:
+ break;
+ }
+ return rc;
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ /* FIXME */
+ return 1;
+ }
+ switch ( c->type ) {
+ case RBAC_DEFAULT_USERS_BASE_DN: {
+ struct berval dn = BER_BVNULL;
+ ber_str2bv( c->argv[1], 0, 0, &dn );
+ rc = dnNormalize(
+ 0, NULL, NULL, &dn, &ri->tenant_info.users_basedn, NULL );
+ break;
+ }
+ case RBAC_DEFAULT_ROLES_BASE_DN: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.roles_basedn );
+ break;
+ }
+ case RBAC_DEFAULT_PERMISSIONS_BASE_DN: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.permissions_basedn );
+ break;
+ }
+ case RBAC_DEFAULT_SESSIONS_BASE_DN: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.sessions_basedn );
+ break;
+ }
+ case RBAC_DEFAULT_AUDIT_BASE_DN: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.audit_basedn );
+ break;
+ }
+ case RBAC_ADMIN_DN: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.admin );
+ break;
+ }
+ case RBAC_ADMIN_PWD: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.pwd );
+ break;
+ }
+ case RBAC_SESSION_ADMIN_DN: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.session_admin );
+ break;
+ }
+ case RBAC_SESSION_ADMIN_PWD: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.session_admin_pwd );
+ break;
+ }
+ case RBAC_DEFAULT_TENANT_ID: {
+ ber_str2bv( c->argv[1], 0, 1, &ri->tenant_info.tid );
+ break;
+ }
+ case RBAC_TENANT: {
+ rbac_tenant_parse( c->argv[1], &ri->tenant_info );
+ break;
+ }
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * rbac configuration
+ */
+
+tenant_info_t *
+rbac_tid2tenant( struct berval *tid )
+{
+ /* return the only tenant for now */
+ return &rbac_tenants.tenant_info;
+}
+
+//{ BER_BVC(LDAP_RBAC_EXOP_SESSION_ROLES), rbac_session_roles },
+
+static int
+slap_parse_rbac_session_roles(
+ struct berval *in,
+ rbac_req_t **reqpp,
+ const char **text,
+ void *ctx )
+{
+ int rc = LDAP_SUCCESS;
+ struct berval reqdata = BER_BVNULL;
+ rbac_req_t *reqp = NULL;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len = -1;
+
+ *text = NULL;
+
+ if ( in == NULL || in->bv_len == 0 ) {
+ *text = "empty request data field in rbac_session_roles exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ reqp = rbac_alloc_req( RBAC_REQ_SESSION_ROLES );
+
+ if ( !reqp ) {
+ *text = "unable to allocate memory for rbac_session_roles exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber_dupbv_x( &reqdata, in, ctx );
+
+ /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+ ber_init2( ber, &reqdata, 0 );
+
+ tag = ber_scanf( ber, "{" /*}*/ );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
+ "decoding error.\n" );
+ goto decoding_error;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID_SESS ) {
+ struct berval uid;
+ tag = ber_scanf( ber, "m", &uid );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
+ "user id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->uid, &uid, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ //tag = ber_peek_tag( ber, &len );
+ if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID_SESS ) {
+ struct berval sessid;
+ tag = ber_scanf( ber, "m", &sessid );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
+ "session id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->sessid, &sessid, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag != LBER_DEFAULT || len != 0 ) {
+decoding_error:;
+
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_session_roles: "
+ "decoding error, len=%ld\n",
+ (long)len );
+ rc = LDAP_PROTOCOL_ERROR;
+ *text = "data decoding error";
+ }
+
+ if ( rc == LDAP_SUCCESS ) {
+ *reqpp = reqp;
+ } else {
+ rbac_free_req( reqp );
+ *reqpp = NULL;
+ }
+
+ if ( !BER_BVISNULL( &reqdata ) ) {
+ ber_memfree_x( reqdata.bv_val, ctx );
+ }
+
+ return rc;
+}
+
+static int
+rbac_session_roles( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ const struct berval rbac_op = BER_BVC("SessionRoles");
+ rbac_req_t *reqp = NULL;
+ rbac_session_t *sessp;
+ int rc;
+
+ rs->sr_err = slap_parse_rbac_session_roles(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* checking whether the session is owned by the user */
+ if ( !rbac_is_session_owner( sessp, reqp ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
+ "session not owned by user\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ rc = rbac_int_delete_session( op, sessp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
+ "unable to delete session\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /*
+ * If we wanted to...
+ * load these roles into a response with a sequence nested within a
+ * sequence: (No, we're not actually doing this here.)
+ * 0x30 LL ber_printf( ber, "{" );
+ * 0x04 L1
+ * 0x04 L2 a b c d
+ * 0x04 L3 e f g h
+ * 0x04 L4 i j k l
+ * add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
+ * close it ber_printf( ber, "t{W}", LDAP_TAG_EXOP_RBAC_ROLES, roles );
+ */
+
+ /*
+ * Instead we are...
+ * loading these roles into the response within a sequence: (Yes, we are doing this here.)
+ * 0x30 LL ber_printf( ber, "{" );
+ * 0x04 L1 a b c d
+ * 0x04 L2 e f g h
+ * 0x04 L3 i j k l
+ * add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
+ * close it ber_printf( ber, "tW", LDAP_TAG_EXOP_RBAC_ROLES, roles );
+ */
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_init_w_nullc( ber, LBER_USE_DER );
+ BerVarray roles = NULL;
+ if ( sessp->roles ) {
+ struct berval tmpbv;
+ // open the sequence:
+ ber_printf( ber, "{" /*}*/ );
+ //char *role;
+ int i = 0;
+ //BerVarray roles = NULL;
+ for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
+ tmpbv.bv_val = sessp->roles[i].bv_val;
+ tmpbv.bv_len = sessp->roles[i].bv_len;
+ // add role name:
+ ber_bvarray_add_x( &roles, &tmpbv, NULL );
+
+ //LBER_F( int )
+ //ber_bvecadd_x LDAP_P(( struct berval ***bvec,
+ // struct berval *bv, void *ctx ));
+
+ // first attempt at sequence within a sequence...
+ // open another sequence:
+ /*
+ ber_printf( ber, "{" } );
+ // add role name (again):
+ ber_bvarray_add_x(&roles, &tmpbv, NULL);
+ // close the nested sequence:
+ ber_printf( ber, { "}" );
+*/
+ // end 2nd sequence
+ }
+ /*
+ * This is how we add several octet strings at one time. An array of struct berval's is supplied.
+ * The array is terminated by a struct berval with a NULL bv_val.
+ * Note that a construct like '{W}' is required to get an actual SEQUENCE OF octet strings.
+ * But here we are using 'tW' which allows passing a collection of octets w/out a nesting within a sequence.
+ */
+ ber_printf( ber, "tW",
+ LDAP_TAG_EXOP_RBAC_ROLES, roles);
+
+ // TODO: determine why free on roles array causes a seg fault:
+ //ber_bvarray_free_x(roles, NULL);
+
+ // close the sequence:
+ ber_printf( ber, /*{*/ "N}" );
+ }
+
+ if ( rc < 0 ) {
+ rs->sr_err = LDAP_OTHER;
+ rs->sr_text = "internal error";
+ } else {
+ (void)ber_flatten( ber, &rs->sr_rspdata );
+ rs->sr_err = LDAP_SUCCESS;
+ }
+ ber_free_buf( ber );
+ // END LOAD ROLES INTO RESPONSE
+
+done:;
+ rs->sr_err = rc;
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_SESSION_ROLES.bv_val );
+
+ /* generate audit log */
+ rbac_audit(
+ op, SessionRoles, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
+ rbac_free_session( sessp );
+ rbac_free_req( reqp );
+ return rs->sr_err;
+}
+
+static int
+rbac_session_rolesx( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ const struct berval rbac_op = BER_BVC("SessionRoles");
+ rbac_session_t *sessp = NULL;
+ rbac_req_t *reqp = NULL;
+ int rc;
+
+ rs->sr_err = slap_parse_rbac_session_roles(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* checking whether the session is owned by the user */
+ if ( !rbac_is_session_owner( sessp, reqp ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
+ "session not owned by user\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ rc = rbac_int_delete_session( op, sessp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_roles: "
+ "unable to delete session\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /*
+ * If we wanted to...
+ * load these roles into a response with a sequence nested within a
+ * sequence: (No, we're not actually doing this here.)
+ * 0x30 LL ber_printf( ber, "{" );
+ * 0x04 L1
+ * 0x04 L2 a b c d
+ * 0x04 L3 e f g h
+ * 0x04 L4 i j k l
+ * add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
+ * close it ber_printf( ber, "t{W}", LDAP_TAG_EXOP_RBAC_ROLES, roles );
+ */
+
+ /*
+ * Instead we are...
+ * loading these roles into the response within a sequence: (Yes, we are doing this here.)
+ * 0x30 LL ber_printf( ber, "{" );
+ * 0x04 L1 a b c d
+ * 0x04 L2 e f g h
+ * 0x04 L3 i j k l
+ * add all three ber_bvarray_add_x( &roles, &tmpbv, NULL );
+ * close it ber_printf( ber, "tW", LDAP_TAG_EXOP_RBAC_ROLES, roles );
+ */
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_init_w_nullc( ber, LBER_USE_DER );
+ BerVarray roles = NULL;
+ if ( sessp->roles ) {
+ struct berval tmpbv;
+ // open the sequence:
+ ber_printf( ber, "{" /*}*/ );
+ //char *role;
+ int i = 0;
+ //BerVarray roles = NULL;
+ for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
+ tmpbv.bv_val = sessp->roles[i].bv_val;
+ tmpbv.bv_len = sessp->roles[i].bv_len;
+ // add role name:
+ ber_bvarray_add_x( &roles, &tmpbv, NULL );
+
+ // first attempt at sequence within a sequence...
+ // open another sequence:
+ /*
+ ber_printf( ber, "{" } );
+ // add role name (again):
+ ber_bvarray_add_x(&roles, &tmpbv, NULL);
+ // close the nested sequence:
+ ber_printf( ber, { "}" );
+*/
+ // end 2nd sequence
+ }
+ /*
+ * This is how we add several octet strings at one time. An array of struct berval's is supplied.
+ * The array is terminated by a struct berval with a NULL bv_val.
+ * Note that a construct like '{W}' is required to get an actual SEQUENCE OF octet strings.
+ * But here we are using 'tW' which allows passing a collection of octets w/out a nesting within a sequence.
+ */
+ ber_printf( ber, "tW",
+ LDAP_TAG_EXOP_RBAC_ROLES, roles);
+
+ // TODO: determine why free on roles array causes a seg fault:
+ //ber_bvarray_free_x(roles, NULL);
+
+ // close the sequence:
+ ber_printf( ber, /*{*/ "N}" );
+ }
+
+ if ( rc < 0 ) {
+ rs->sr_err = LDAP_OTHER;
+ rs->sr_text = "internal error";
+ } else {
+ (void)ber_flatten( ber, &rs->sr_rspdata );
+ rs->sr_err = LDAP_SUCCESS;
+ }
+ ber_free_buf( ber );
+ // END LOAD ROLES INTO RESPONSE
+
+done:;
+ rs->sr_err = rc;
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_SESSION_ROLES.bv_val );
+
+ /* generate audit log */
+ rbac_audit(
+ op, SessionRoles, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
+ rbac_free_session( sessp );
+ rbac_free_req( reqp );
+ return rs->sr_err;
+}
+
+/*
+ * slap_parse_rbac_create_session
+ */
+static int
+slap_parse_rbac_create_session(
+ struct berval *in,
+ rbac_req_t **reqpp,
+ const char **text,
+ void *ctx )
+{
+ int rc = LDAP_SUCCESS;
+ struct berval reqdata = BER_BVNULL;
+ rbac_req_t *reqp = NULL;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len = -1;
+
+ *text = NULL;
+
+ if ( in == NULL || in->bv_len == 0 ) {
+ *text = "empty request data field in rbac_create_session exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ reqp = rbac_alloc_req( RBAC_REQ_CREATE_SESSION );
+
+ if ( !reqp ) {
+ *text = "unable to allocate memory for bac_create_session exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber_dupbv_x( &reqdata, in, ctx );
+
+ /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+ ber_init2( ber, &reqdata, 0 );
+
+ tag = ber_scanf( ber, "{" /*}*/ );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "decoding error.\n" );
+ goto decoding_error;
+ }
+
+ // Order: 1. sessionId, 2. tenantId, 3. userId, 4. password and 5. roles
+ /* must-have */
+ tag = ber_peek_tag( ber, &len );
+
+ // 1. SESSIONID
+ if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "session id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->sessid, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ // 2. TENANT ID
+ if ( tag == LDAP_TAG_EXOP_RBAC_TENANT_ID ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "tenant id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->tenantid, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ // 3. USERID
+ if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "user id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->uid, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ // 4. PASSWORD
+ if ( tag == LDAP_TAG_EXOP_RBAC_AUTHTOK ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv);
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "authtok parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->authtok, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ // 5. ROLES
+ if ( tag == LDAP_TAG_EXOP_RBAC_ACTIVE_ROLE ) {
+ tag = ber_scanf( ber, "W", &reqp->roles);
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "role parse failed.\n" );
+ goto decoding_error;
+ }
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag != LBER_DEFAULT || len != 0 ) {
+decoding_error:;
+
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "decoding error, len=%ld\n",
+ (long)len );
+ rc = LDAP_PROTOCOL_ERROR;
+ *text = "data decoding error";
+ }
+
+ if ( rc == LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_create_session: "
+ "SUCCESS\n" );
+
+ *reqpp = reqp;
+ } else {
+ Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_create_session: "
+ "NO SUCCESS RC=%d\n", rc );
+
+ rbac_free_req( reqp );
+ *reqpp = NULL;
+ }
+
+ if ( !BER_BVISNULL( &reqdata ) ) {
+ ber_memfree_x( reqdata.bv_val, ctx );
+ }
+
+ return rc;
+}
+
+/*
+ * rbac_create_session:
+ * 1. authenticate user
+ * 2. evaluate pwd policy
+ * 3. create session
+ */
+static int
+rbac_create_session( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ struct berval rbac_op = BER_BVC("CreateSession");
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ int rc = LDAP_SUCCESS;
+ rbac_session_t *sessp = NULL;
+ rbac_user_t *userp = NULL;
+ rbac_req_t *reqp = NULL;
+
+ rs->sr_err = slap_parse_rbac_create_session(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ /* read user entry */
+ userp = rbac_read_user( op, reqp );
+ if ( !userp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
+ "unable to read user entry\n" );
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ rs->sr_text = "rbac_create_session: unable to read user entry";
+ goto done;
+ }
+
+ if ( !BER_BVISNULL( &userp->password ) ) {
+ /* if request is with pwd, authenticate the user */
+ rc = rbac_authenticate_user( op, userp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
+ "rbac_authenticate_user failed!\n" );
+ rs->sr_err = LDAP_INVALID_CREDENTIALS;
+ rs->sr_text = "rbac_create_session: invalid credential";
+ goto done;
+ }
+ /*
+ rbac_user_t *ui = op->o_callback->sc_private;
+ int pVal = ui->authz;
+ printf("password reset val=%d", pVal );
+*/
+
+ } else {
+ /* no pwd is provided, check whether the requesting session */
+ /* id has the access privilege to create a session on behalf */
+ /* of the user */
+ rc = rbac_create_session_acl_check( &reqp->sessid, userp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
+ "rbac_authenticate_user failed!\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "rbac_create_session: session permission denied";
+ goto done;
+ }
+ }
+
+ /* check user temporal constraint */
+ rc = rbac_user_temporal_constraint( userp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
+ "rbac_user_temporal_constraint() failed!\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "rbac_create_session: temporal constraint violation";
+ goto done;
+ }
+
+ sessp = rbac_alloc_session();
+ if ( !sessp ) {
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "rbac_create_session: unable to allocate session";
+ goto done;
+ }
+
+ rc = activate_session_roles( sessp, reqp, userp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
+ "failed to activate roles to session!\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text =
+ "rbac_create_session: failed to activate roles into session";
+ goto done;
+ }
+
+ /* store uid and tenant id in session */
+ ber_dupbv( &sessp->userdn, &userp->dn );
+ ber_dupbv( &sessp->uid, &reqp->uid );
+ ber_dupbv( &sessp->tenantid, &reqp->tenantid );
+
+ /* register RBAC session */
+ rc = rbac_register_session( op, rs, sessp );
+ if ( rc != LDAP_SUCCESS ) {
+ goto done;
+ }
+
+ ber_init_w_nullc( ber, LBER_USE_DER );
+ rc = ber_printf( ber, "{tO}", LDAP_TAG_EXOP_RBAC_SESSION_ID,
+ &sessp->sessid );
+ if ( rc < 0 ) {
+ rs->sr_err = LDAP_OTHER;
+ rs->sr_text = "internal error";
+ } else {
+ (void)ber_flatten( ber, &rs->sr_rspdata );
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CREATE_SESSION.bv_val );
+ rs->sr_err = LDAP_SUCCESS;
+ }
+
+ ber_free_buf( ber );
+
+done:;
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CREATE_SESSION.bv_val );
+ /* generate audit log */
+ rbac_audit(
+ op, CreateSession, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
+
+ rbac_free_req( reqp );
+ rbac_free_session( sessp );
+
+ //if (rs->sr_err != LDAP_SUCCESS) {
+ //send_ldap_result( op, rs );
+ //}
+
+ return rs->sr_err;
+}
+
+/*
+ * slap_parse_rbac_check_access
+ */
+static int
+slap_parse_rbac_check_access(
+ struct berval *in,
+ rbac_req_t **reqpp,
+ const char **text,
+ void *ctx )
+{
+ int rc = LDAP_SUCCESS;
+ struct berval reqdata = BER_BVNULL;
+ rbac_req_t *reqp = NULL;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len;
+
+ *text = NULL;
+ reqp = rbac_alloc_req( RBAC_REQ_CHECK_ACCESS );
+
+ if ( !reqp ) {
+ *text = "unable to allocate memory for slap_parse_rbac_check_access";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( in == NULL || in->bv_len == 0 ) {
+ *text = "empty request data field in rbac_check_access exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber_dupbv_x( &reqdata, in, ctx );
+
+ /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+ ber_init2( ber, &reqdata, 0 );
+
+ tag = ber_scanf( ber, "{" /*}*/ );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "decoding error.\n" );
+ goto decoding_error;
+ }
+
+ // sessionId is required:
+ tag = ber_peek_tag( ber, &len );
+ if ( tag != LDAP_TAG_EXOP_RBAC_SESSION_ID ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "decoding error.\n" );
+ goto decoding_error;
+ } else {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "session id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->sessid, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ // operationName is required:
+ if ( tag != LDAP_TAG_EXOP_RBAC_OPNAME ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "decoding error.\n" );
+ goto decoding_error;
+ } else {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "opname parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->opname, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ // objectName is required:
+ if ( tag != LDAP_TAG_EXOP_RBAC_OBJNAME ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "decoding error.\n" );
+ goto decoding_error;
+ } else {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "objname parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->objname, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ // objectId is optional:
+ if ( tag == LDAP_TAG_EXOP_RBAC_OBJID ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "objid parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->objid, &bv, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag != LBER_DEFAULT || len != 0 ) {
+decoding_error:;
+
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_check_access: "
+ "decoding error, len=%ld\n",
+ (long)len );
+ rc = LDAP_PROTOCOL_ERROR;
+ *text = "data decoding error";
+ }
+
+ if ( rc == LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_check_access: "
+ "SUCCESS\n" );
+ *reqpp = reqp;
+ } else {
+ Debug( LDAP_DEBUG_ANY, "slap_parse_rbac_check_access: "
+ "FAIL\n" );
+ rbac_free_req( reqp );
+ }
+
+ if ( !BER_BVISNULL( &reqdata ) ) {
+ ber_memfree_x( reqdata.bv_val, ctx );
+ }
+
+ return rc;
+}
+
+// checkAcess F (ALL)
+static int
+rbac_check_access( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ rbac_session_t *sessp = NULL;
+ rbac_permission_t *permp = NULL;
+ rbac_constraint_t *cp = NULL;
+ rbac_req_t *reqp = NULL;
+ const struct berval rbac_op = BER_BVC("CheckAccess");
+ int rc = LDAP_SUCCESS;
+ int found = 0;
+
+ rs->sr_err = slap_parse_rbac_check_access(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ BER_BVZERO( &op->o_req_dn );
+ BER_BVZERO( &op->o_req_ndn );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* read the permission using objectName and OpName */
+ permp = rbac_read_permission( op, reqp );
+ if ( !permp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
+ "permission not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ // Convert the user-role constraint data from BerVarray to rbac_constraint_t format
+ cp = rbac_user_role_constraints( sessp->role_constraints );
+
+ // Now do the actual rbac checkAccess:
+ rc = rbac_check_session_permission( sessp, permp, cp );
+
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_user_permission: "
+ "failed\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+done:
+
+ rs->sr_err = rc;
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
+
+ /* generate audit log */
+ rbac_audit( op, CheckAccess, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
+
+ rbac_free_permission( permp );
+ rbac_free_req( reqp );
+ rbac_free_session( sessp );
+ rbac_free_constraints( cp );
+
+ return rs->sr_err;
+}
+
+// checkAcess A loop back
+static int
+rbac_check_accessA( Operation *op, SlapReply *rs )
+{
+ int rc = LDAP_SUCCESS;
+
+ //rs->sr_err = slap_parse_rbac_check_access(op->ore_reqdata,
+ // &reqp, &rs->sr_text, NULL);
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
+ rs->sr_err = rc;
+
+ return rc;
+}
+
+// checkAcess B parse
+static int
+rbac_check_accessB( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ rbac_req_t *reqp = NULL;
+ const struct berval rbac_op = BER_BVC("CheckAccess");
+ int rc = LDAP_SUCCESS;
+
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
+
+ rs->sr_err = slap_parse_rbac_check_access(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ BER_BVZERO( &op->o_req_dn );
+ BER_BVZERO( &op->o_req_ndn );
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
+ rs->sr_err = rc;
+
+ rbac_free_req( reqp );
+
+ return rc;
+}
+
+// checkAcess C - parse request & read session record
+static int
+rbac_check_accessC( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ rbac_session_t *sessp = NULL;
+ rbac_req_t *reqp = NULL;
+ const struct berval rbac_op = BER_BVC("CheckAccess");
+ int rc = LDAP_SUCCESS;
+
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
+
+ rs->sr_err = slap_parse_rbac_check_access(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ BER_BVZERO( &op->o_req_dn );
+ BER_BVZERO( &op->o_req_ndn );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+done:
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
+ rs->sr_err = rc;
+
+ rbac_free_req( reqp );
+ rbac_free_session( sessp );
+ return rc;
+}
+
+// checkAcess D, parse, read perm
+static int
+rbac_check_accessD( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ rbac_permission_t *permp = NULL;
+ rbac_req_t *reqp = NULL;
+ const struct berval rbac_op = BER_BVC("CheckAccess");
+ int rc = LDAP_SUCCESS;
+
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
+
+ rs->sr_err = slap_parse_rbac_check_access(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ BER_BVZERO( &op->o_req_dn );
+ BER_BVZERO( &op->o_req_ndn );
+
+ /* get the session using the session id */
+ /*
+ sessp = rbac_session_byid(op, reqp);
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+*/
+
+ /* read the permission using objectName and OpName */
+ permp = rbac_read_permission( op, reqp );
+ if ( !permp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
+ "permission not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+done:
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
+ rs->sr_err = rc;
+
+ rbac_free_permission( permp );
+ rbac_free_req( reqp );
+
+ return rc;
+}
+
+// checkAcess E everything but the audit insert
+static int
+rbac_check_accessE( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ rbac_session_t *sessp = NULL;
+ rbac_permission_t *permp = NULL;
+ rbac_constraint_t *cp = NULL;
+ rbac_req_t *reqp = NULL;
+ const struct berval rbac_op = BER_BVC("CheckAccess");
+ int rc = LDAP_SUCCESS;
+
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access\n" );
+
+ rs->sr_err = slap_parse_rbac_check_access(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ BER_BVZERO( &op->o_req_dn );
+ BER_BVZERO( &op->o_req_ndn );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* read the permission using objectName and OpName */
+ permp = rbac_read_permission( op, reqp );
+ if ( !permp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_access: "
+ "permission not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ // Convert the user-role constraint data from BerVarray to rbac_constraint_t format
+ cp = rbac_user_role_constraints( sessp->role_constraints );
+
+ // Now do the actual rbac checkAccess:
+ rc = rbac_check_session_permission( sessp, permp, cp );
+
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_check_user_permission: "
+ "failed\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+done:
+
+ rs->sr_err = rc;
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_CHECK_ACCESS.bv_val );
+
+ /* generate audit log */
+ //rbac_audit(op, CheckAccess, sessp, reqp, rs->sr_err,
+ // (char *) rs->sr_text);
+
+ rbac_free_permission( permp );
+ rbac_free_req( reqp );
+ rbac_free_session( sessp );
+ rbac_free_constraints( cp );
+
+ return rs->sr_err;
+}
+
+/* check whether role exists and role assigned to the user */
+static int
+rbac_check_user_role(
+ rbac_req_t *reqp,
+ rbac_session_t *sessp,
+ rbac_user_t *userp )
+{
+ int rc = 0;
+ int i;
+
+ //assert(!BER_BVISEMPTY(&reqp->roles[0]));
+ assert( !BER_BVISEMPTY( &reqp->role ) );
+
+ for ( i = 0; !BER_BVISNULL( &userp->roles[i] ); i++ ) {
+ //if (!ber_bvstrcasecmp(&userp->roles[i], &reqp->roles[0])) {
+ if ( !ber_bvstrcasecmp( &userp->roles[i], &reqp->role ) ) {
+ rc = 1; /* found the match */
+ goto done;
+ }
+ }
+
+done:;
+
+ return rc;
+}
+
+/* check whether role exists and role assigned to the session */
+static int
+rbac_check_session_role( rbac_req_t *reqp, rbac_session_t *sessp )
+{
+ int rc = 0;
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
+ //if (!ber_bvstrcasecmp(&sessp->roles[i], &reqp->roles[0])) {
+ if ( !ber_bvstrcasecmp( &sessp->roles[i], &reqp->role ) ) {
+ rc = 1; /* found the match */
+ goto done;
+ }
+ }
+
+done:;
+
+ return rc;
+}
+
+/* make sure user is the owner of the session */
+static int
+rbac_check_user_session( rbac_session_t *sessp, rbac_req_t *reqp )
+{
+ int rc = 0;
+
+ if ( BER_BVISNULL( &sessp->uid ) || BER_BVISNULL( &reqp->uid ) ||
+ sessp->uid.bv_len != reqp->uid.bv_len ) {
+ goto done;
+ }
+
+ if ( !strncasecmp(
+ sessp->uid.bv_val, reqp->uid.bv_val, reqp->uid.bv_len ) ) {
+ rc = 1;
+ goto done;
+ }
+
+done:;
+
+ return rc;
+}
+
+/*
+ * slap_parse_rbac_active_role
+ */
+static int
+slap_parse_rbac_active_role(
+ struct berval *in,
+ int add_or_drop_role,
+ rbac_req_t **reqpp,
+ const char **text,
+ void *ctx )
+{
+ int rc = LDAP_SUCCESS;
+ struct berval reqdata = BER_BVNULL;
+ rbac_req_t *reqp = NULL;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len = -1;
+
+ *text = NULL;
+
+ if ( in == NULL || in->bv_len == 0 ) {
+ *text = "empty request data field in rbac_create_session exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ reqp = rbac_alloc_req( add_or_drop_role );
+
+ if ( !reqp ) {
+ *text = "unable to allocate memory for rbac_add_drop_active_role exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber_dupbv_x( &reqdata, in, ctx );
+
+ /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+ ber_init2( ber, &reqdata, 0 );
+
+ tag = ber_scanf( ber, "{" /*}*/ );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_active_role: "
+ "decoding error.\n" );
+ goto decoding_error;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ //if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID ) {
+ if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID_SESS ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_active_role: "
+ "user id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv( &reqp->uid, &bv );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID_SESS ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_active_role: "
+ "session id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv( &reqp->sessid, &bv );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag == LDAP_TAG_EXOP_RBAC_ROLE_NM_SESS ) {
+ struct berval bv;
+ tag = ber_scanf( ber, "m", &bv );
+ //tag = ber_scanf( ber, "W", &reqp->roles);
+ //tag = ber_scanf( ber, "m", &reqp->roles);
+ //tag = ber_scanf( ber, "m", &reqp->roles[0]);
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "role parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv( &reqp->role, &bv );
+ //ber_dupbv(&reqp->roles[0], &bv);
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag != LBER_DEFAULT || len != 0 ) {
+decoding_error:;
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_create_session: "
+ "decoding error, len=%ld\n",
+ (long)len );
+ rc = LDAP_PROTOCOL_ERROR;
+ *text = "data decoding error";
+ }
+
+ if ( rc == LDAP_SUCCESS ) {
+ *reqpp = reqp;
+ } else {
+ rbac_free_req( reqp );
+ *reqpp = NULL;
+ }
+
+ if ( !BER_BVISNULL( &reqdata ) ) {
+ ber_memfree_x( reqdata.bv_val, ctx );
+ }
+
+ return rc;
+}
+
+static int
+rbac_add_active_role( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ struct berval rbac_op = BER_BVC("AddActiveRole");
+ rbac_req_t *reqp = NULL;
+ rbac_user_t *userp = NULL;
+ rbac_session_t *sessp;
+ int rc = LDAP_SUCCESS;
+
+ rs->sr_err = slap_parse_rbac_active_role( op->ore_reqdata,
+ RBAC_REQ_ADD_ACTIVE_ROLE, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
+ "session not found\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "rbac_add_active_role: session not found";
+ goto done;
+ }
+
+ /* read user entry */
+ userp = rbac_read_user( op, reqp );
+ if ( !userp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
+ "unable to read user entry\n" );
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ rs->sr_text = "rbac_add_active_role: unable to read user entry";
+ goto done;
+ }
+
+ /* make sure role exists and role assigned to the user */
+ if ( !rbac_check_user_role( reqp, sessp, userp ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
+ "role not assigned to the user\n" );
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ rs->sr_text = "rbac_add_active_role: role not assigned to the user";
+ goto done;
+ }
+
+ /* make sure user is the owner of the session */
+ if ( !rbac_check_user_session( sessp, reqp ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
+ "user not owner of session\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "rbac_add_active_role: user not owner of the session";
+ goto done;
+ }
+
+ /* add the role to the session */
+ rc = rbac_session_add_role( op, sessp, reqp );
+ if ( rc != LDAP_SUCCESS ) {
+ rs->sr_err = rc;
+ if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
+ rs->sr_text =
+ "rbac_add_active_role: role already activated in session";
+ Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
+ "role already activated in session\n" );
+ } else {
+ rs->sr_text = "rbac_add_active_role: unable to add role to session";
+ Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
+ "unable to add role to session\n" );
+ }
+ goto done;
+ }
+
+done:
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_ADD_ACTIVE_ROLE.bv_val );
+
+ /* generate audit log */
+ rbac_audit(
+ op, AddActiveRole, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
+
+ rbac_free_session( sessp );
+ rbac_free_user( userp );
+ rbac_free_req( reqp );
+
+ return rs->sr_err;
+}
+
+static int
+rbac_drop_active_role( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ const struct berval rbac_op = BER_BVC("DropActiveRole");
+ rbac_session_t *sessp;
+ rbac_req_t *reqp = NULL;
+ int rc = LDAP_SUCCESS;
+
+ rs->sr_err = slap_parse_rbac_active_role( op->ore_reqdata,
+ RBAC_REQ_DROP_ACTIVE_ROLE, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ if ( BER_BVISNULL( &reqp->role ) || !sessp->roles ||
+ BER_BVISNULL( &sessp->roles[0] ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
+ "unavailable role\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* make sure role exists and role assigned to the user */
+ if ( !rbac_check_session_role( reqp, sessp ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
+ "role not assigned to session\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* make sure user is the owner of the session */
+ if ( !rbac_check_user_session( sessp, reqp ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
+ "user not owner of session\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "rbac_drop_active_role: user not owner of the session";
+ goto done;
+ }
+
+ /* drop the role to the session */
+ rc = rbac_session_drop_role( op, sessp, reqp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_drop_active_role: "
+ "unable to drop active role from session\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "rbac_drop_active_role: unable to drop role from session";
+ goto done;
+ }
+
+done:
+ rs->sr_err = rc;
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_DROP_ACTIVE_ROLE.bv_val );
+
+ /* generate audit log */
+ rbac_audit(
+ op, DropActiveRole, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
+
+ rbac_free_session( sessp );
+ rbac_free_req( reqp );
+
+ return rs->sr_err;
+}
+
+/*
+ * slap_parse_rbac_delete_session
+ */
+static int
+slap_parse_rbac_delete_session(
+ struct berval *in,
+ rbac_req_t **reqpp,
+ const char **text,
+ void *ctx )
+{
+ int rc = LDAP_SUCCESS;
+ struct berval reqdata = BER_BVNULL;
+ rbac_req_t *reqp = NULL;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len = -1;
+
+ *text = NULL;
+
+ if ( in == NULL || in->bv_len == 0 ) {
+ *text = "empty request data field in rbac_delete_session exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ reqp = rbac_alloc_req( RBAC_REQ_DELETE_SESSION );
+
+ if ( !reqp ) {
+ *text = "unable to allocate memory for rbac_delete_session exop";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber_dupbv_x( &reqdata, in, ctx );
+
+ /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+ ber_init2( ber, &reqdata, 0 );
+
+ tag = ber_scanf( ber, "{" /*}*/ );
+
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
+ "decoding error.\n" );
+ goto decoding_error;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LDAP_TAG_EXOP_RBAC_USER_ID_SESS ) {
+ struct berval uid;
+ tag = ber_scanf( ber, "m", &uid );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
+ "user id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->uid, &uid, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ //tag = ber_peek_tag( ber, &len );
+ if ( tag == LDAP_TAG_EXOP_RBAC_SESSION_ID_SESS ) {
+ struct berval sessid;
+ tag = ber_scanf( ber, "m", &sessid );
+ if ( tag == LBER_ERROR ) {
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
+ "session id parse failed.\n" );
+ goto decoding_error;
+ }
+ ber_dupbv_x( &reqp->sessid, &sessid, ctx );
+ tag = ber_peek_tag( ber, &len );
+ }
+
+ if ( tag != LBER_DEFAULT || len != 0 ) {
+decoding_error:;
+
+ Debug( LDAP_DEBUG_TRACE, "slap_parse_rbac_delete_session: "
+ "decoding error, len=%ld\n",
+ (long)len );
+ rc = LDAP_PROTOCOL_ERROR;
+ *text = "data decoding error";
+ }
+
+ if ( rc == LDAP_SUCCESS ) {
+ *reqpp = reqp;
+ } else {
+ rbac_free_req( reqp );
+ *reqpp = NULL;
+ }
+
+ if ( !BER_BVISNULL( &reqdata ) ) {
+ ber_memfree_x( reqdata.bv_val, ctx );
+ }
+
+ return rc;
+}
+
+static int
+rbac_delete_session( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ const struct berval rbac_op = BER_BVC("DeleteSession");
+ rbac_session_t *sessp = NULL;
+ rbac_req_t *reqp = NULL;
+ int rc;
+
+ rs->sr_err = slap_parse_rbac_delete_session(
+ op->ore_reqdata, &reqp, &rs->sr_text, NULL );
+
+ assert( rs->sr_err == LDAP_SUCCESS );
+
+ /* get the session using the session id */
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_delete_session: "
+ "session not found\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* checking whether the session is owned by the user */
+ if ( !rbac_is_session_owner( sessp, reqp ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_delete_session: "
+ "session not owned by user\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ rc = rbac_int_delete_session( op, sessp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_int_delete_session: "
+ "unable to delete session\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+done:;
+
+ rs->sr_err = rc;
+
+ // always put the OID in the response:
+ rs->sr_rspoid = ch_strdup( slap_EXOP_DELETE_SESSION.bv_val );
+
+ /* generate audit log */
+ rbac_audit(
+ op, DeleteSession, sessp, reqp, rs->sr_err, (char *)rs->sr_text );
+
+ rbac_free_session( sessp );
+ rbac_free_req( reqp );
+
+ return rs->sr_err;
+}
+
+/* returns the permissions associated with a session */
+static int
+rbac_session_permissions( Operation *op, SlapReply *rs, rbac_req_t *reqp )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ const struct berval rbac_op = BER_BVC("SessionPermissions");
+ rbac_session_t *sessp;
+
+ sessp = rbac_session_byid( op, reqp );
+ if ( !sessp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_permissions: "
+ "session id not found\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ rs->sr_err = rbac_int_session_permissions( op, rs, reqp, sessp );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_session_permissions: "
+ "permissions not found\n" );
+ goto done;
+ }
+
+done:;
+ return rs->sr_err;
+}
+
+/* extract session permission info from op */
+int
+rbac_search_parse_session_permissions_req(
+ Operation *op,
+ rbac_req_t **reqpp,
+ const char **text,
+ void *ctx )
+{
+ int rc = LDAP_SUCCESS;
+ struct berval *sessid = NULL;
+ rbac_req_t *reqp = NULL;
+ *text = NULL;
+ struct berval rbac_session_id = BER_BVC("sessionID");
+ struct berval rbac_session_permissions_attr =
+ BER_BVC("sessionPermissions");
+ AttributeDescription *ad = NULL;
+ Filter *f;
+
+ /* check simple assertion (sessionID=<session id>) */
+ f = op->ors_filter;
+ ad = f->f_ava->aa_desc;
+ if ( !ad || ber_bvstrcasecmp( &rbac_session_id, &ad->ad_cname ) ) {
+ goto done;
+ }
+ sessid = &f->f_ava->aa_value;
+
+ if ( !rbac_is_valid_session_id( sessid ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_search_parse_session_permissions_req: "
+ "invalid session id\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* check requested attr */
+
+ if ( !op->oq_search.rs_attrs ||
+ BER_BVISNULL( &op->oq_search.rs_attrs[0].an_name ) ||
+ ber_bvstrcasecmp( &op->oq_search.rs_attrs[0].an_name,
+ &rbac_session_permissions_attr ) ||
+ !BER_BVISNULL( &op->oq_search.rs_attrs[1].an_name ) ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_search_parse_session_permissions_req: "
+ "only sessionPermissions allowed\n" );
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ reqp = rbac_alloc_req( RBAC_REQ_SESSION_PERMISSIONS );
+ if ( !reqp ) {
+ *text = "unable to allocate memory for rbac_session_permissions req";
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ /* retrieve session id from search filter */
+ ber_dupbv_x( &reqp->sessid, sessid, ctx );
+
+done:;
+
+ if ( rc == LDAP_SUCCESS ) {
+ *reqpp = reqp;
+ } else {
+ rbac_free_req( reqp );
+ *reqpp = NULL;
+ }
+
+ return rc;
+}
+
+static int
+rbac_search( Operation *op, SlapReply *rs )
+{
+ Debug( LDAP_DEBUG_ANY, "rbac_search entry\n" );
+
+ return SLAP_CB_CONTINUE;
+}
+
+/*
+static int
+rbac_search( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ rbac_req_t *reqp = NULL;
+ int rc = SLAP_CB_CONTINUE;
+
+ only session_permissions is implemented for now
+ rc = rbac_search_parse_session_permissions_req(
+ op, &reqp, &rs->sr_text, NULL );
+ if ( !reqp ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_search: "
+ "invalid search for session permissions\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ rc = rbac_session_permissions( op, rs, reqp );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_search: "
+ "session permissions failed\n" );
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+
+ rs->sr_err = LDAP_SUCCESS;
+
+done:;
+ send_ldap_result( op, rs );
+
+ return rc;
+}
+*/
+
+static struct exop {
+ struct berval oid;
+ BI_op_extended *extended;
+} rbac_exop_table[] = {
+ { BER_BVC(LDAP_RBAC_EXOP_CREATE_SESSION), rbac_create_session },
+ { BER_BVC(LDAP_RBAC_EXOP_CHECK_ACCESS), rbac_check_access },
+ { BER_BVC(LDAP_RBAC_EXOP_ADD_ACTIVE_ROLE), rbac_add_active_role },
+ { BER_BVC(LDAP_RBAC_EXOP_DROP_ACTIVE_ROLE), rbac_drop_active_role },
+ { BER_BVC(LDAP_RBAC_EXOP_DELETE_SESSION), rbac_delete_session },
+ { BER_BVC(LDAP_RBAC_EXOP_SESSION_ROLES), rbac_session_roles },
+
+ { BER_BVNULL, NULL }
+};
+
+static int
+rbac_add( Operation *op, SlapReply *rs )
+{
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+rbac_bind( Operation *op, SlapReply *rs )
+{
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+rbac_compare( Operation *op, SlapReply *rs )
+{
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+rbac_delete( Operation *op, SlapReply *rs )
+{
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+rbac_modify( Operation *op, SlapReply *rs )
+{
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+rbac_extended( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ int rc = SLAP_CB_CONTINUE;
+ int i;
+
+ for ( i = 0; rbac_exop_table[i].extended != NULL; i++ ) {
+ if ( bvmatch( &rbac_exop_table[i].oid, &op->oq_extended.rs_reqoid ) ) {
+ rc = rbac_exop_table[i].extended( op, rs );
+ switch ( rc ) {
+ case LDAP_SUCCESS:
+ break;
+ case SLAP_CB_CONTINUE:
+ case SLAPD_ABANDON:
+ return rc;
+ default:
+ send_ldap_result( op, rs );
+ return rc;
+ }
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static int
+rbac_db_init( BackendDB *be, ConfigReply *cr )
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+
+ return 0;
+}
+
+static int
+rbac_db_open( BackendDB *be, ConfigReply *cr )
+{
+ int rc = LDAP_SUCCESS;
+
+ rc = rbac_initialize_tenants( be, cr );
+
+ return rc;
+}
+
+static int
+rbac_db_close( BackendDB *be, ConfigReply *cr )
+{
+ return 0;
+}
+
+int
+rbac_initialize()
+{
+ int rc;
+
+ rc = load_extop2( (struct berval *)&slap_EXOP_CREATE_SESSION,
+ SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_create_session, 0 );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
+ "unable to register rbac_create_session exop: %d\n",
+ rc );
+ return rc;
+ }
+
+ rc = load_extop2( (struct berval *)&slap_EXOP_CHECK_ACCESS,
+ SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_check_access, 0 );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
+ "unable to register rbac_check_access exop: %d\n",
+ rc );
+ return rc;
+ }
+
+ rc = load_extop2( (struct berval *)&slap_EXOP_ADD_ACTIVE_ROLE,
+ SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_add_active_role, 0 );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
+ "unable to register rbac_add_active_role exop: %d\n",
+ rc );
+ return rc;
+ }
+
+ rc = load_extop2( (struct berval *)&slap_EXOP_DROP_ACTIVE_ROLE,
+ SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_drop_active_role, 0 );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
+ "unable to register rbac_drop_active_role exop: %d\n",
+ rc );
+ return rc;
+ }
+
+ rc = load_extop2( (struct berval *)&slap_EXOP_DELETE_SESSION,
+ SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_delete_session, 0 );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
+ "unable to register rbac_delete_session exop: %d\n",
+ rc );
+ return rc;
+ }
+
+ rc = load_extop2( (struct berval *)&slap_EXOP_SESSION_ROLES,
+ SLAP_EXOP_WRITES|SLAP_EXOP_HIDE, rbac_session_roles, 0 );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
+ "unable to register rbac_session_roles exop: %d\n",
+ rc );
+ return rc;
+ }
+
+ rbac.on_bi.bi_type = "rbac";
+ rbac.on_bi.bi_db_init = rbac_db_init;
+ rbac.on_bi.bi_db_open = rbac_db_open;
+ rbac.on_bi.bi_db_close = rbac_db_close;
+
+ rbac.on_bi.bi_op_add = rbac_add;
+ rbac.on_bi.bi_op_bind = rbac_bind;
+ rbac.on_bi.bi_op_compare = rbac_compare;
+ rbac.on_bi.bi_op_delete = rbac_delete;
+ rbac.on_bi.bi_op_modify = rbac_modify;
+ rbac.on_bi.bi_op_search = rbac_search;
+ rbac.on_bi.bi_extended = rbac_extended;
+ rbac.on_bi.bi_cf_ocs = rbac_ocs;
+
+ /* rbac.on_bi.bi_connection_destroy = rbac_connection_destroy; */
+
+ rc = config_register_schema( rbaccfg, rbac_ocs );
+ if ( rc ) return rc;
+
+ rc = rbac_initialize_repository();
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+
+ return overlay_register( &rbac );
+}
+
+int
+init_module( int argc, char *argv[] )
+{
+ return rbac_initialize();
+}