mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-16 03:44:58 -05:00
ITS#9471 Add RBAC overlay to contrib
This commit is contained in:
parent
fd39b726d8
commit
d594ffe902
14 changed files with 6097 additions and 0 deletions
50
contrib/slapd-modules/rbac/Makefile
Executable file
50
contrib/slapd-modules/rbac/Makefile
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
# $OpenLDAP$
|
||||
|
||||
LDAP_SRC = ../../..
|
||||
LDAP_BUILD = $(LDAP_SRC)
|
||||
LDAP_INC = -I$(LDAP_BUILD)/include -I$(LDAP_SRC)/include -I$(LDAP_SRC)/servers/slapd
|
||||
LDAP_LIB = $(LDAP_BUILD)/libraries/libldap/libldap.la \
|
||||
$(LDAP_BUILD)/libraries/liblber/liblber.la
|
||||
|
||||
LIBTOOL = $(LDAP_BUILD)/libtool
|
||||
CC = gcc
|
||||
OPT = -g -O2 -Wall
|
||||
DEFS = -DSLAPD_OVER_RBAC=SLAPD_MOD_DYNAMIC
|
||||
INCS = $(LDAP_INC)
|
||||
LIBS = $(LDAP_LIB)
|
||||
|
||||
PROGRAMS = rbac.la
|
||||
LTVER = 0:0:0
|
||||
|
||||
prefix=/usr/local
|
||||
exec_prefix=$(prefix)
|
||||
ldap_subdir=/openldap
|
||||
|
||||
libdir=$(exec_prefix)/lib
|
||||
libexecdir=$(exec_prefix)/libexec
|
||||
moduledir = $(libexecdir)$(ldap_subdir)
|
||||
|
||||
SRCS = rbac.c rbacperm.c rbacsess.c rbacuser.c rbacreq.c rbacaudit.c init.c rbacacl.c util.c jts.c
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
LOBJS = $(patsubst %.c,%.lo,$(SRCS))
|
||||
|
||||
.SUFFIXES: .c .lo
|
||||
|
||||
%.lo: %.c rbac.h
|
||||
$(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(INCS) -c $<
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
rbac.la: $(LOBJS)
|
||||
$(LIBTOOL) --mode=link $(CC) $(OPT) -version-info $(LTVER) \
|
||||
-rpath $(moduledir) -module -o $@ $^ $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.lo *.la .libs
|
||||
|
||||
install: $(PROGRAMS)
|
||||
mkdir -p $(DESTDIR)$(moduledir)
|
||||
for p in $(PROGRAMS) ; do \
|
||||
$(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(moduledir) ; \
|
||||
done
|
||||
|
||||
324
contrib/slapd-modules/rbac/init.c
Normal file
324
contrib/slapd-modules/rbac/init.c
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
/* init.c - RBAC initialization */
|
||||
/* $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 slap_callback nullsc = { NULL, NULL, NULL, NULL };
|
||||
|
||||
struct slap_rbac_internal_schema slap_rbac_schema;
|
||||
|
||||
extern rbac_tenant_t rbac_tenants;
|
||||
extern int initialize_jts( void );
|
||||
|
||||
rbac_ad_t rbac_session_ads[] = {
|
||||
{ RBAC_SESSION_ID,
|
||||
BER_BVC("rbacSessid"), &slap_rbac_schema.ad_session_id },
|
||||
{ RBAC_USER_DN,
|
||||
BER_BVC("rbacUserDN"), &slap_rbac_schema.ad_session_user_dn },
|
||||
{ RBAC_ROLES,
|
||||
BER_BVC("rbacRoles"), &slap_rbac_schema.ad_session_roles },
|
||||
{ RBAC_ROLE_CONSTRAINTS,
|
||||
BER_BVC("rbacRoleConstraints"),
|
||||
&slap_rbac_schema.ad_session_role_constraints },
|
||||
{ RBAC_UID,
|
||||
BER_BVC("uid"), &slap_rbac_schema.ad_uid},
|
||||
{ RBAC_TENANT_ID,
|
||||
BER_BVC("tenantid"), &slap_rbac_schema.ad_tenant_id },
|
||||
|
||||
{ RBAC_NONE, BER_BVNULL, NULL }
|
||||
};
|
||||
|
||||
rbac_ad_t rbac_session_permission_ads[] = {
|
||||
{ RBAC_OP_NAME,
|
||||
BER_BVC("rbacOpName"), &slap_rbac_schema.ad_permission_opname },
|
||||
{ RBAC_OBJ_NAME,
|
||||
BER_BVC("rbacObjName"), &slap_rbac_schema.ad_permission_objname },
|
||||
{ RBAC_ROLE_NAME,
|
||||
BER_BVC("rbacRoleName"), &slap_rbac_schema.ad_permission_rolename },
|
||||
|
||||
{ RBAC_NONE, BER_BVNULL, NULL }
|
||||
};
|
||||
|
||||
rbac_ad_t audit_ads[] = {
|
||||
{ RBAC_AUDIT_OP,
|
||||
BER_BVC("rbacAuditOp"), &slap_rbac_schema.ad_audit_op },
|
||||
{ RBAC_AUDIT_ID,
|
||||
BER_BVC("rbacAuditId"), &slap_rbac_schema.ad_audit_id },
|
||||
{ RBAC_AUDIT_ROLES,
|
||||
BER_BVC("rbacAuditRoles"), &slap_rbac_schema.ad_audit_roles },
|
||||
{ RBAC_AUDIT_REQUESTED_ROLES,
|
||||
BER_BVC("rbacAuditRequestedRoles"),
|
||||
&slap_rbac_schema.ad_audit_requested_roles
|
||||
},
|
||||
{ RBAC_AUDIT_TIMESTAMP,
|
||||
BER_BVC("rbacAuditTimestamp"), &slap_rbac_schema.ad_audit_timestamp },
|
||||
{ RBAC_AUDIT_RESOURCES,
|
||||
BER_BVC("rbacAuditResources"), &slap_rbac_schema.ad_audit_resources },
|
||||
{ RBAC_AUDIT_OBJS,
|
||||
BER_BVC("rbacAuditObjects"), &slap_rbac_schema.ad_audit_objects },
|
||||
{ RBAC_AUDIT_OPS,
|
||||
BER_BVC("rbacAuditOperations"), &slap_rbac_schema.ad_audit_operations },
|
||||
{ RBAC_AUDIT_RESULT,
|
||||
BER_BVC("rbacAuditResult"), &slap_rbac_schema.ad_audit_result },
|
||||
{ RBAC_AUDIT_PROPERTIES,
|
||||
BER_BVC("rbacAuditProperties"), &slap_rbac_schema.ad_audit_properties },
|
||||
{ RBAC_AUDIT_MSGS,
|
||||
BER_BVC("rbacAuditMessages"), &slap_rbac_schema.ad_audit_messages },
|
||||
|
||||
{ RBAC_NONE, BER_BVNULL, NULL }
|
||||
};
|
||||
|
||||
/* initialize repository attribute descriptions */
|
||||
|
||||
static int
|
||||
initialize_sessions()
|
||||
{
|
||||
int i, nattrs, rc = LDAP_SUCCESS;
|
||||
const char *text;
|
||||
|
||||
for ( nattrs = 0; !BER_BVISNULL( &rbac_session_ads[nattrs].attr );
|
||||
nattrs++ )
|
||||
; /* count the number of attrs */
|
||||
|
||||
slap_rbac_schema.session_attrs =
|
||||
slap_sl_calloc( sizeof(AttributeName), nattrs + 1, NULL );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &rbac_session_ads[i].attr ); i++ ) {
|
||||
rc = slap_bv2ad(
|
||||
&rbac_session_ads[i].attr, rbac_session_ads[i].ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
slap_rbac_schema.session_attrs[i].an_name = rbac_session_ads[i].attr;
|
||||
slap_rbac_schema.session_attrs[i].an_desc = *rbac_session_ads[i].ad;
|
||||
}
|
||||
|
||||
BER_BVZERO( &slap_rbac_schema.session_attrs[nattrs].an_name );
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
initialize_audit()
|
||||
{
|
||||
int i, rc = LDAP_SUCCESS;
|
||||
const char *text;
|
||||
|
||||
/* for audit */
|
||||
for ( i = 0; !BER_BVISNULL( &audit_ads[i].attr ); i++ ) {
|
||||
rc = slap_bv2ad( &audit_ads[i].attr, audit_ads[i].ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
initialize_tenant(
|
||||
BackendDB *be,
|
||||
ConfigReply *cr,
|
||||
tenant_info_t *tenantp,
|
||||
int init_op )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
Entry *e = NULL;
|
||||
OperationBuffer opbuf;
|
||||
Operation *op2;
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Connection conn = { 0 };
|
||||
struct berval rbac_container_oc = BER_BVC("rbacContainer");
|
||||
struct berval rbac_audit_container = BER_BVC("audit");
|
||||
struct berval rbac_session_container = BER_BVC("rbac");
|
||||
void *thrctx = ldap_pvt_thread_pool_context();
|
||||
|
||||
e = entry_alloc();
|
||||
|
||||
switch ( init_op ) {
|
||||
case INIT_AUDIT_CONTAINER:
|
||||
ber_dupbv( &e->e_name, &tenantp->audit_basedn );
|
||||
ber_dupbv( &e->e_nname, &tenantp->audit_basedn );
|
||||
|
||||
/* container cn */
|
||||
attr_merge_one(
|
||||
e, slap_schema.si_ad_cn, &rbac_audit_container, NULL );
|
||||
break;
|
||||
case INIT_SESSION_CONTAINER:
|
||||
ber_dupbv( &e->e_name, &tenantp->sessions_basedn );
|
||||
ber_dupbv( &e->e_nname, &tenantp->sessions_basedn );
|
||||
|
||||
/* rendered dynmaicObject for session */
|
||||
attr_merge_one( e, slap_schema.si_ad_objectClass,
|
||||
&slap_schema.si_oc_dynamicObject->soc_cname, NULL );
|
||||
|
||||
/* container cn */
|
||||
attr_merge_one(
|
||||
e, slap_schema.si_ad_cn, &rbac_session_container, NULL );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
attr_merge_one(
|
||||
e, slap_schema.si_ad_objectClass, &rbac_container_oc, NULL );
|
||||
attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
|
||||
&rbac_container_oc, NULL );
|
||||
|
||||
/* store RBAC session */
|
||||
connection_fake_init2( &conn, &opbuf, thrctx, 0 );
|
||||
op2 = &opbuf.ob_op;
|
||||
op2->o_callback = &nullsc;
|
||||
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;
|
||||
rc = op2->o_bd->be_add( op2, &rs2 );
|
||||
|
||||
if ( e ) entry_free( e );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_initialize_tenants( BackendDB *be, ConfigReply *cr )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
rbac_tenant_t *tenantp = NULL;
|
||||
|
||||
for ( tenantp = &rbac_tenants; tenantp; tenantp = tenantp->next ) {
|
||||
rc = initialize_tenant(
|
||||
be, cr, &tenantp->tenant_info, INIT_AUDIT_CONTAINER );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
if ( rc == LDAP_ALREADY_EXISTS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
|
||||
"audit container exists, tenant (%s)\n",
|
||||
tenantp->tenant_info.tid.bv_val ?
|
||||
tenantp->tenant_info.tid.bv_val :
|
||||
"NULL" );
|
||||
rc = LDAP_SUCCESS;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
|
||||
"failed to initialize (%s): rc (%d)\n",
|
||||
tenantp->tenant_info.tid.bv_val ?
|
||||
tenantp->tenant_info.tid.bv_val :
|
||||
"NULL",
|
||||
rc );
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
|
||||
"created audit container for tenant (%s):\n",
|
||||
tenantp->tenant_info.tid.bv_val ?
|
||||
tenantp->tenant_info.tid.bv_val :
|
||||
"NULL" );
|
||||
}
|
||||
rc = initialize_tenant(
|
||||
be, cr, &tenantp->tenant_info, INIT_SESSION_CONTAINER );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
if ( rc == LDAP_ALREADY_EXISTS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
|
||||
"session container exists, tenant (%s)\n",
|
||||
tenantp->tenant_info.tid.bv_val ?
|
||||
tenantp->tenant_info.tid.bv_val :
|
||||
"NULL" );
|
||||
rc = LDAP_SUCCESS;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
|
||||
"failed to initialize (%s): rc (%d)\n",
|
||||
tenantp->tenant_info.tid.bv_val ?
|
||||
tenantp->tenant_info.tid.bv_val :
|
||||
"NULL",
|
||||
rc );
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
|
||||
"created session container for tenant (%s):\n",
|
||||
tenantp->tenant_info.tid.bv_val ?
|
||||
tenantp->tenant_info.tid.bv_val :
|
||||
"NULL" );
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
initialize_rbac_session_permissions()
|
||||
{
|
||||
int i, rc = LDAP_SUCCESS;
|
||||
const char *text;
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &rbac_session_permission_ads[i].attr ); i++ ) {
|
||||
rc = slap_bv2ad( &rbac_session_permission_ads[i].attr,
|
||||
rbac_session_permission_ads[i].ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_initialize_repository()
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
rc = initialize_jts();
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = initialize_rbac_session_permissions();
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = initialize_sessions();
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = initialize_audit();
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
198
contrib/slapd-modules/rbac/jts.c
Normal file
198
contrib/slapd-modules/rbac/jts.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/* jts.c - RBAC JTS initialization */
|
||||
/* $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"
|
||||
|
||||
struct slap_rbac_tenant_schema slap_rbac_jts_schema;
|
||||
|
||||
/* to replace all JTS schema initialization */
|
||||
rbac_ad_t ft_ads[] = {
|
||||
{ RBAC_ROLE_ASSIGNMENT,
|
||||
BER_BVC("ftRA"), &slap_rbac_jts_schema.ad_role },
|
||||
{ RBAC_ROLE_CONSTRAINTS,
|
||||
BER_BVC("ftRC"), &slap_rbac_jts_schema.ad_role_constraint },
|
||||
{ RBAC_USER_CONSTRAINTS,
|
||||
BER_BVC("ftCstr"), &slap_rbac_jts_schema.ad_user_constraint },
|
||||
{ RBAC_UID,
|
||||
BER_BVC("uid"), &slap_rbac_jts_schema.ad_uid },
|
||||
{ RBAC_USERS,
|
||||
BER_BVC("ftUsers"), &slap_rbac_jts_schema.ad_permission_users },
|
||||
{ RBAC_ROLES,
|
||||
BER_BVC("ftRoles"), &slap_rbac_jts_schema.ad_permission_roles },
|
||||
{ RBAC_OBJ_NAME,
|
||||
BER_BVC("ftObjNm"), &slap_rbac_jts_schema.ad_permission_objname },
|
||||
{ RBAC_OP_NAME,
|
||||
BER_BVC("ftOpNm"), &slap_rbac_jts_schema.ad_permission_opname },
|
||||
|
||||
{ RBAC_NONE, BER_BVNULL, NULL }
|
||||
};
|
||||
|
||||
rbac_ad_t ft_user_ads[] = {
|
||||
{ RBAC_ROLE_ASSIGNMENT,
|
||||
BER_BVC("ftRA"), &slap_rbac_jts_schema.ad_role },
|
||||
{ RBAC_ROLE_CONSTRAINTS,
|
||||
BER_BVC("ftRC"), &slap_rbac_jts_schema.ad_role_constraint },
|
||||
{ RBAC_USER_CONSTRAINTS,
|
||||
BER_BVC("ftCstr"), &slap_rbac_jts_schema.ad_user_constraint },
|
||||
{ RBAC_UID,
|
||||
BER_BVC("uid"), &slap_rbac_jts_schema.ad_uid },
|
||||
|
||||
{ RBAC_NONE, BER_BVNULL, NULL }
|
||||
};
|
||||
|
||||
rbac_ad_t ft_perm_ads[] = {
|
||||
{ RBAC_USERS,
|
||||
BER_BVC("ftUsers"), &slap_rbac_jts_schema.ad_permission_users },
|
||||
{ RBAC_ROLES,
|
||||
BER_BVC("ftRoles"), &slap_rbac_jts_schema.ad_permission_roles },
|
||||
|
||||
{ RBAC_NONE, BER_BVNULL, NULL }
|
||||
};
|
||||
|
||||
rbac_ad_t ft_session_perm_ads[] = {
|
||||
{ RBAC_USERS,
|
||||
BER_BVC("ftUsers"), &slap_rbac_jts_schema.ad_permission_users },
|
||||
{ RBAC_ROLES,
|
||||
BER_BVC("ftRoles"), &slap_rbac_jts_schema.ad_permission_roles },
|
||||
{ RBAC_OBJ_NAME,
|
||||
BER_BVC("ftObjNm"), &slap_rbac_jts_schema.ad_permission_objname },
|
||||
{ RBAC_OP_NAME,
|
||||
BER_BVC("ftOpNm"), &slap_rbac_jts_schema.ad_permission_opname },
|
||||
|
||||
{ RBAC_NONE, BER_BVNULL, NULL }
|
||||
};
|
||||
|
||||
static int
|
||||
initialize_jts_session_permission_ads()
|
||||
{
|
||||
int i, nattrs, rc = LDAP_SUCCESS;
|
||||
|
||||
for ( nattrs = 0; !BER_BVISNULL( &ft_session_perm_ads[nattrs].attr );
|
||||
nattrs++ )
|
||||
; /* count the number of attrs */
|
||||
|
||||
slap_rbac_jts_schema.session_perm_attrs =
|
||||
slap_sl_calloc( sizeof(AttributeName), nattrs + 1, NULL );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &ft_session_perm_ads[i].attr ); i++ ) {
|
||||
slap_rbac_jts_schema.session_perm_attrs[i].an_name =
|
||||
ft_session_perm_ads[i].attr;
|
||||
slap_rbac_jts_schema.session_perm_attrs[i].an_desc =
|
||||
*ft_session_perm_ads[i].ad;
|
||||
}
|
||||
|
||||
BER_BVZERO( &slap_rbac_jts_schema.session_perm_attrs[nattrs].an_name );
|
||||
|
||||
slap_rbac_jts_schema.session_permissions_ads = ft_session_perm_ads;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
initialize_jts_permission_ads()
|
||||
{
|
||||
int i, nattrs, rc = LDAP_SUCCESS;
|
||||
|
||||
/* jts permissions configuration */
|
||||
|
||||
for ( nattrs = 0; !BER_BVISNULL( &ft_perm_ads[nattrs].attr ); nattrs++ )
|
||||
; /* count the number of attrs */
|
||||
|
||||
slap_rbac_jts_schema.perm_attrs =
|
||||
slap_sl_calloc( sizeof(AttributeName), nattrs + 1, NULL );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &ft_perm_ads[i].attr ); i++ ) {
|
||||
slap_rbac_jts_schema.perm_attrs[i].an_name = ft_perm_ads[i].attr;
|
||||
slap_rbac_jts_schema.perm_attrs[i].an_desc = *ft_perm_ads[i].ad;
|
||||
}
|
||||
|
||||
BER_BVZERO( &slap_rbac_jts_schema.perm_attrs[nattrs].an_name );
|
||||
|
||||
slap_rbac_jts_schema.permission_ads = ft_perm_ads;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
initialize_jts_user_ads()
|
||||
{
|
||||
int i, nattrs, rc = LDAP_SUCCESS;
|
||||
|
||||
/* jts user attribute descriptions */
|
||||
|
||||
/* jts user attributes */
|
||||
for ( nattrs = 0; !BER_BVISNULL( &ft_user_ads[nattrs].attr ); nattrs++ )
|
||||
; /* count the number of attrs */
|
||||
|
||||
slap_rbac_jts_schema.user_attrs =
|
||||
slap_sl_calloc( sizeof(AttributeName), nattrs + 1, NULL );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &ft_user_ads[i].attr ); i++ ) {
|
||||
slap_rbac_jts_schema.user_attrs[i].an_name = ft_user_ads[i].attr;
|
||||
slap_rbac_jts_schema.user_attrs[i].an_desc = *ft_user_ads[i].ad;
|
||||
}
|
||||
|
||||
BER_BVZERO( &slap_rbac_jts_schema.user_attrs[nattrs].an_name );
|
||||
|
||||
slap_rbac_jts_schema.user_ads = ft_user_ads;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
initialize_jts()
|
||||
{
|
||||
int i, rc;
|
||||
const char *text;
|
||||
|
||||
/* jts attributes */
|
||||
for ( i = 0; !BER_BVISNULL( &ft_ads[i].attr ); i++ ) {
|
||||
rc = slap_bv2ad( &ft_ads[i].attr, ft_ads[i].ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
rc = initialize_jts_user_ads();
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = initialize_jts_permission_ads();
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = initialize_jts_session_permission_ads();
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
55
contrib/slapd-modules/rbac/ldap_rbac.h
Normal file
55
contrib/slapd-modules/rbac/ldap_rbac.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef LDAP_RBAC_H
|
||||
#define LDAP_RBAC_H
|
||||
|
||||
/* extended operations for RBAC */
|
||||
#define LDAP_RBAC_EXOP_CREATE_SESSION "1.3.6.1.4.1.4203.555.1" /* RFC xxxx */
|
||||
#define LDAP_RBAC_EXOP_CHECK_ACCESS "1.3.6.1.4.1.4203.555.2"
|
||||
#define LDAP_RBAC_EXOP_ADD_ACTIVE_ROLE "1.3.6.1.4.1.4203.555.3"
|
||||
#define LDAP_RBAC_EXOP_DROP_ACTIVE_ROLE "1.3.6.1.4.1.4203.555.4"
|
||||
#define LDAP_RBAC_EXOP_DELETE_SESSION "1.3.6.1.4.1.4203.555.5"
|
||||
#define LDAP_RBAC_EXOP_SESSION_ROLES "1.3.6.1.4.1.4203.555.6"
|
||||
#define LDAP_RBAC_EXOP_SESSION_PERMISSIONS "1.3.6.1.4.1.4203.555.7"
|
||||
|
||||
#define LDAP_TAG_EXOP_RBAC_SESSION_ID ((ber_tag_t)0x80U)
|
||||
#define LDAP_TAG_EXOP_RBAC_TENANT_ID ((ber_tag_t)0x81U)
|
||||
#define LDAP_TAG_EXOP_RBAC_USER_ID ((ber_tag_t)0x82U)
|
||||
#define LDAP_TAG_EXOP_RBAC_USER ((ber_tag_t)0x80U)
|
||||
#define LDAP_TAG_EXOP_RBAC_AUTHTOK ((ber_tag_t)0x83U)
|
||||
#define LDAP_TAG_EXOP_RBAC_ACTIVE_ROLE ((ber_tag_t)0xA4U)
|
||||
#define LDAP_TAG_EXOP_RBAC_OPNAME ((ber_tag_t)0x81U)
|
||||
#define LDAP_TAG_EXOP_RBAC_OBJNAME ((ber_tag_t)0x82U)
|
||||
#define LDAP_TAG_EXOP_RBAC_OBJID ((ber_tag_t)0x83U)
|
||||
#define LDAP_TAG_EXOP_RBAC_PWPOLICY_STATE ((ber_tag_t)0x85U)
|
||||
#define LDAP_TAG_EXOP_RBAC_PWPOLICY_VALUE ((ber_tag_t)0x86U)
|
||||
#define LDAP_TAG_EXOP_RBAC_ROLES ((ber_tag_t)0x04U)
|
||||
|
||||
#define LDAP_TAG_EXOP_RBAC_USER_ID_SESS ((ber_tag_t)0x80U)
|
||||
#define LDAP_TAG_EXOP_RBAC_SESSION_ID_SESS ((ber_tag_t)0x81U)
|
||||
#define LDAP_TAG_EXOP_RBAC_ROLE_NM_SESS ((ber_tag_t)0x82U)
|
||||
|
||||
#define RBAC_REQ_CREATE_SESSION 0
|
||||
#define RBAC_REQ_CHECK_ACCESS 1
|
||||
#define RBAC_REQ_ADD_ACTIVE_ROLE 2
|
||||
#define RBAC_REQ_DROP_ACTIVE_ROLE 3
|
||||
#define RBAC_REQ_DELETE_SESSION 4
|
||||
#define RBAC_REQ_SESSION_PERMISSIONS 5
|
||||
#define RBAC_REQ_SESSION_ROLES 6
|
||||
|
||||
/* defines for password policy */
|
||||
#define RBAC_BIND_NEW_AUTHTOK_REQD 1
|
||||
|
||||
#define RBAC_PASSWORD_GOOD 0
|
||||
#define RBAC_PASSWORD_EXPIRATION_WARNING 11
|
||||
#define RBAC_PASSWORD_GRACE_WARNING 12
|
||||
#define RBAC_PASSWORD_HAS_EXPIRED 100
|
||||
#define RBAC_ACCOUNT_LOCKED 101
|
||||
#define RBAC_CHANGE_AFTER_RESET 102
|
||||
#define RBAC_NO_MODIFICATIONS 103
|
||||
#define RBAC_MUST_SUPPLY_OLD 104
|
||||
#define RBAC_INSUFFICIENT_QUALITY 105
|
||||
#define RBAC_PASSWORD_TOO_SHORT 106
|
||||
#define RBAC_PASSWORD_TOO_YOUNG 107
|
||||
#define RBAC_HISTORY_VIOLATION 108
|
||||
#define RBAC_ACCOUNT_LOCKED_CONSTRAINTS 109
|
||||
|
||||
#endif /* LDAP_RBAC_H */
|
||||
2169
contrib/slapd-modules/rbac/rbac.c
Normal file
2169
contrib/slapd-modules/rbac/rbac.c
Normal file
File diff suppressed because it is too large
Load diff
402
contrib/slapd-modules/rbac/rbac.h
Normal file
402
contrib/slapd-modules/rbac/rbac.h
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
/* rbac.h - */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1999-2021 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:
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RBAC_H
|
||||
#define RBAC_H
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
#include "ldap_rbac.h"
|
||||
|
||||
#define USE_NEW_THREAD_CONTEXT 1
|
||||
#define RBAC_BUFLEN 1024
|
||||
|
||||
/* tenant initialization op */
|
||||
#define INIT_AUDIT_CONTAINER 0x01
|
||||
#define INIT_SESSION_CONTAINER 0x02
|
||||
|
||||
typedef struct rbac_ad {
|
||||
int type;
|
||||
struct berval attr;
|
||||
AttributeDescription **ad;
|
||||
} rbac_ad_t;
|
||||
|
||||
/* RBAC AttributeDescriptions */
|
||||
struct slap_rbac_internal_schema {
|
||||
/* slapd schema */
|
||||
AttributeDescription *ad_uid;
|
||||
|
||||
/* RBAC tenant */
|
||||
AttributeDescription *ad_tenant_id;
|
||||
|
||||
/* RBAC sessions */
|
||||
AttributeDescription *ad_session_id;
|
||||
AttributeDescription *ad_session_user_dn;
|
||||
AttributeDescription *ad_session_roles;
|
||||
AttributeDescription *ad_session_role_constraints;
|
||||
|
||||
/* RBAC session permissions */
|
||||
AttributeDescription *ad_permission_opname;
|
||||
AttributeDescription *ad_permission_objname;
|
||||
AttributeDescription *ad_permission_rolename;
|
||||
|
||||
/* RBAC audit */
|
||||
AttributeDescription *ad_audit_op; /* rbac op: create_session */
|
||||
AttributeDescription *ad_audit_id;
|
||||
AttributeDescription *ad_audit_roles;
|
||||
AttributeDescription *ad_audit_requested_roles;
|
||||
AttributeDescription *ad_audit_timestamp;
|
||||
AttributeDescription *ad_audit_resources;
|
||||
AttributeDescription *ad_audit_objects;
|
||||
AttributeDescription *ad_audit_operations; /* resource ops */
|
||||
AttributeDescription *ad_audit_result;
|
||||
AttributeDescription *ad_audit_properties;
|
||||
AttributeDescription *ad_audit_messages;
|
||||
|
||||
/* RBAC session attributes */
|
||||
AttributeName *session_attrs;
|
||||
};
|
||||
|
||||
extern struct slap_rbac_internal_schema slap_rbac_schema;
|
||||
|
||||
/* attributes in tenant repository */
|
||||
struct slap_rbac_tenant_schema {
|
||||
/* user role assignments, role constraints, and user constraint */
|
||||
AttributeDescription *ad_role;
|
||||
AttributeDescription *ad_role_constraint;
|
||||
AttributeDescription *ad_user_constraint;
|
||||
AttributeDescription *ad_uid;
|
||||
|
||||
/* session permission */
|
||||
AttributeDescription *ad_permission_users;
|
||||
AttributeDescription *ad_permission_roles;
|
||||
AttributeDescription *ad_permission_objname;
|
||||
AttributeDescription *ad_permission_opname;
|
||||
|
||||
/* the list of attributes when doing searches in the jts repo */
|
||||
AttributeName *user_attrs;
|
||||
AttributeName *perm_attrs; /* attrs to retrieve for check access */
|
||||
AttributeName *session_perm_attrs; /* attrs for session permissions */
|
||||
|
||||
/* the corresponding list of attribute description mapping */
|
||||
rbac_ad_t *user_ads;
|
||||
rbac_ad_t *permission_ads;
|
||||
rbac_ad_t *session_permissions_ads;
|
||||
};
|
||||
|
||||
extern struct slap_rbac_tenant_schema slap_rbac_jts_schema;
|
||||
|
||||
/* types of RBAC requests */
|
||||
typedef struct rbac_request {
|
||||
int req_type;
|
||||
struct berval sessid;
|
||||
struct berval tenantid;
|
||||
|
||||
/* session creation */
|
||||
struct berval uid;
|
||||
struct berval authtok;
|
||||
BerVarray roles;
|
||||
struct berval role;
|
||||
|
||||
/* check access */
|
||||
struct berval opname;
|
||||
struct berval objname;
|
||||
struct berval objid;
|
||||
} rbac_req_t;
|
||||
|
||||
typedef struct rbac_constraint {
|
||||
struct berval name; /* user name or role name */
|
||||
int allowed_inactivity; /* secs */
|
||||
int begin_time; /* secs */
|
||||
int end_time; /* secs */
|
||||
lutil_timet begin_date;
|
||||
lutil_timet end_date;
|
||||
lutil_timet begin_lock_date;
|
||||
lutil_timet end_lock_date;
|
||||
int day_mask;
|
||||
struct rbac_constraint *next;
|
||||
} rbac_constraint_t;
|
||||
|
||||
/* holds RBAC info */
|
||||
typedef struct tenant_info {
|
||||
struct berval tid; /* tenant id */
|
||||
struct berval admin;
|
||||
struct berval pwd;
|
||||
struct berval users_basedn;
|
||||
struct berval roles_basedn;
|
||||
struct berval audit_basedn;
|
||||
struct berval permissions_basedn;
|
||||
struct berval sessions_basedn;
|
||||
struct berval session_admin;
|
||||
struct berval session_admin_pwd;
|
||||
struct slap_rbac_tenant_schema *schema;
|
||||
} tenant_info_t;
|
||||
|
||||
typedef struct rbac_tenant {
|
||||
tenant_info_t tenant_info;
|
||||
struct rbac_tenant *next;
|
||||
} rbac_tenant_t;
|
||||
|
||||
/* for RBAC callback */
|
||||
typedef struct rbac_callback_info {
|
||||
tenant_info_t *tenantp;
|
||||
void *private;
|
||||
} rbac_callback_info_t;
|
||||
|
||||
/* RBAC user */
|
||||
typedef struct rbac_user {
|
||||
struct berval tenantid;
|
||||
struct berval uid;
|
||||
struct berval dn;
|
||||
struct berval constraints;
|
||||
struct berval password;
|
||||
struct berval msg;
|
||||
int authz; /* flag for bind (pwd policy) info */
|
||||
BerVarray roles;
|
||||
BerVarray role_constraints;
|
||||
#if 0 /* additional parameters from Fortress */
|
||||
private String userId;
|
||||
@XmlElement(nillable = true)
|
||||
private char[] password;
|
||||
@XmlElement(nillable = true)
|
||||
private char[] newPassword;
|
||||
private String internalId;
|
||||
@XmlElement(nillable = true)
|
||||
private List<UserRole> roles;
|
||||
@XmlElement(nillable = true)
|
||||
private List<UserAdminRole> adminRoles;
|
||||
private String pwPolicy;
|
||||
private String cn;
|
||||
private String sn;
|
||||
private String dn;
|
||||
private String ou;
|
||||
private String description;
|
||||
private String beginTime;
|
||||
private String endTime;
|
||||
private String beginDate;
|
||||
private String endDate;
|
||||
private String beginLockDate;
|
||||
private String endLockDate;
|
||||
private String dayMask;
|
||||
private String name;
|
||||
private int timeout;
|
||||
private boolean reset;
|
||||
private boolean locked;
|
||||
private Boolean system;
|
||||
@XmlElement(nillable = true)
|
||||
private Props props = new Props();
|
||||
@XmlElement(nillable = true)
|
||||
private Address address;
|
||||
@XmlElement(nillable = true)
|
||||
private List<String> phones;
|
||||
@XmlElement(nillable = true)
|
||||
private List<String> mobiles;
|
||||
@XmlElement(nillable = true)
|
||||
private List<String> emails;
|
||||
#endif /* 0 */
|
||||
} rbac_user_t;
|
||||
|
||||
enum {
|
||||
RBAC_NONE = 0,
|
||||
RBAC_TENANT,
|
||||
RBAC_TENANT_ID,
|
||||
RBAC_USERS_BASE_DN,
|
||||
RBAC_ROLES_BASE_DN,
|
||||
RBAC_PERMISSIONS_BASE_DN,
|
||||
RBAC_ADMIN_DN,
|
||||
RBAC_ADMIN_PWD,
|
||||
RBAC_SESSIONS_BASE_DN,
|
||||
RBAC_SESSION_ADMIN_DN,
|
||||
RBAC_SESSION_ADMIN_PWD,
|
||||
RBAC_ROLE_ASSIGNMENT,
|
||||
RBAC_ROLE_CONSTRAINTS,
|
||||
RBAC_USER_CONSTRAINTS,
|
||||
RBAC_UID,
|
||||
RBAC_USERS,
|
||||
RBAC_ROLES,
|
||||
RBAC_OBJ_NAME,
|
||||
RBAC_OP_NAME,
|
||||
RBAC_ROLE_NAME,
|
||||
RBAC_SESSION_ID,
|
||||
RBAC_USER_DN,
|
||||
RBAC_AUDIT_ROLES,
|
||||
RBAC_AUDIT_RESOURCES,
|
||||
RBAC_AUDIT_RESULT,
|
||||
RBAC_AUDIT_TIMESTAMP,
|
||||
RBAC_AUDIT_PROPERTIES,
|
||||
RBAC_AUDIT_OP,
|
||||
RBAC_AUDIT_ID,
|
||||
RBAC_AUDIT_REQUESTED_ROLES,
|
||||
RBAC_AUDIT_OBJS,
|
||||
RBAC_AUDIT_OPS,
|
||||
RBAC_AUDIT_MSGS,
|
||||
RBAC_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
RBAC_DEFAULT_TENANT_ID = RBAC_LAST,
|
||||
RBAC_DEFAULT_USERS_BASE_DN,
|
||||
RBAC_DEFAULT_PERMISSIONS_BASE_DN,
|
||||
RBAC_DEFAULT_ROLES_BASE_DN,
|
||||
RBAC_DEFAULT_SESSIONS_BASE_DN,
|
||||
RBAC_DEFAULT_AUDIT_BASE_DN
|
||||
};
|
||||
|
||||
typedef struct rbac_user_idlist {
|
||||
char *user_id;
|
||||
struct rbac_user_idlist *next;
|
||||
} rbac_user_idlist_t;
|
||||
|
||||
/* RBAC sessions */
|
||||
#define RBAC_SESSION_RDN_EQ "rbacSessid="
|
||||
#define RBAC_AUDIT_RDN_EQ "rbacAuditId="
|
||||
|
||||
typedef struct rbac_session {
|
||||
rbac_user_t *user;
|
||||
struct berval tenantid;
|
||||
struct berval sessid;
|
||||
struct berval uid;
|
||||
struct berval userdn;
|
||||
char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
|
||||
struct berval sessdn;
|
||||
long last_access;
|
||||
int timeout;
|
||||
int warning_id;
|
||||
int error_id;
|
||||
int grace_logins;
|
||||
int expiration_secs;
|
||||
int is_authenticated; /* boolean */
|
||||
struct berval message;
|
||||
BerVarray roles;
|
||||
BerVarray role_constraints;
|
||||
} rbac_session_t;
|
||||
|
||||
/* RBAC roles */
|
||||
typedef struct rbac_role {
|
||||
char *name;
|
||||
char *description;
|
||||
struct rbac_role *parent;
|
||||
struct rbac_role *next;
|
||||
} rbac_role_t;
|
||||
|
||||
typedef struct rbac_role_list {
|
||||
char *name;
|
||||
struct rbac_role_list *next;
|
||||
} rbac_role_list_t;
|
||||
|
||||
/* RBAC permissions */
|
||||
typedef struct rbac_permission {
|
||||
struct berval dn;
|
||||
int admin; /* boolean */
|
||||
struct berval internalId;
|
||||
BerVarray opName;
|
||||
BerVarray objName;
|
||||
struct berval objectId;
|
||||
struct berval abstractName;
|
||||
struct berval type;
|
||||
BerVarray roles;
|
||||
BerVarray uids;
|
||||
struct rbac_permission *next;
|
||||
} rbac_permission_t;
|
||||
|
||||
/* RBAC Audit */
|
||||
typedef enum {
|
||||
CreateSession = 0,
|
||||
CheckAccess,
|
||||
AddActiveRole,
|
||||
DropActiveRole,
|
||||
SessionPermissions,
|
||||
DeleteSession,
|
||||
SessionRoles
|
||||
} audit_op_t;
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
int rbac_initialize_repository( void );
|
||||
int rbac_initialize_tenants( BackendDB *be, ConfigReply *cr );
|
||||
|
||||
/* RBAC tenant information */
|
||||
tenant_info_t *rbac_tid2tenant( struct berval *tid );
|
||||
|
||||
rbac_req_t *rbac_alloc_req( int type );
|
||||
void rbac_free_req( rbac_req_t *reqp );
|
||||
|
||||
rbac_user_t *rbac_read_user( Operation *op, rbac_req_t *rabc_reqp );
|
||||
int rbac_authenticate_user( Operation *op, rbac_user_t *user );
|
||||
int rbac_user_temporal_constraint( rbac_user_t *userp );
|
||||
void rbac_free_user( rbac_user_t *user );
|
||||
|
||||
rbac_session_t *rbac_alloc_session( void );
|
||||
int rbac_is_valid_session_id( struct berval *sessid );
|
||||
rbac_session_t *rbac_session_byid( Operation *op, rbac_req_t *reqp );
|
||||
int rbac_is_session_owner( rbac_session_t *sessp, rbac_req_t *reqp );
|
||||
int rbac_register_session( Operation *op, SlapReply *rs, rbac_session_t *sess );
|
||||
int rbac_int_delete_session( Operation *op, rbac_session_t *sessp );
|
||||
int rbac_session_add_role(
|
||||
Operation *op,
|
||||
rbac_session_t *sessp,
|
||||
rbac_req_t *reqp );
|
||||
int rbac_session_drop_role(
|
||||
Operation *op,
|
||||
rbac_session_t *sessp,
|
||||
rbac_req_t *reqp );
|
||||
int rbac_int_session_permissions(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
rbac_req_t *reqp,
|
||||
rbac_session_t *sessp );
|
||||
int activate_session_roles(
|
||||
rbac_session_t *sessp,
|
||||
rbac_req_t *reqp,
|
||||
rbac_user_t *userp );
|
||||
void rbac_free_session( rbac_session_t *sessp );
|
||||
|
||||
rbac_constraint_t *rbac_user_role_constraints( BerVarray values );
|
||||
rbac_constraint_t *rbac_role2constraint(
|
||||
struct berval *role,
|
||||
rbac_constraint_t *role_constraints );
|
||||
rbac_constraint_t *rbac_bv2constraint( struct berval *bv );
|
||||
int rbac_check_time_constraint( rbac_constraint_t *cp );
|
||||
void rbac_free_constraint( rbac_constraint_t *cp );
|
||||
void rbac_free_constraints( rbac_constraint_t *constraints );
|
||||
|
||||
rbac_permission_t *rbac_read_permission( Operation *op, rbac_req_t *rbac_reqp );
|
||||
int rbac_check_session_permission(
|
||||
rbac_session_t *sessp,
|
||||
rbac_permission_t *permp,
|
||||
rbac_constraint_t *role_constraints );
|
||||
void rbac_free_permission( rbac_permission_t *permp );
|
||||
|
||||
/* audit functions */
|
||||
void rbac_audit(
|
||||
Operation *op,
|
||||
audit_op_t rbac_op,
|
||||
rbac_session_t *sessp,
|
||||
rbac_req_t *reqp,
|
||||
int result,
|
||||
char *msg );
|
||||
|
||||
/* acl functions */
|
||||
int rbac_create_session_acl_check( struct berval *sessid, rbac_user_t *userp );
|
||||
|
||||
void rbac_to_lower( struct berval *bv );
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* RBAC_H */
|
||||
37
contrib/slapd-modules/rbac/rbacacl.c
Normal file
37
contrib/slapd-modules/rbac/rbacacl.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* rbacacl.c - RBAC ACL */
|
||||
/* $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"
|
||||
|
||||
int
|
||||
rbac_create_session_acl_check( struct berval *sessid, rbac_user_t *userp )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
233
contrib/slapd-modules/rbac/rbacaudit.c
Normal file
233
contrib/slapd-modules/rbac/rbacaudit.c
Normal file
|
|
@ -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, ×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;
|
||||
}
|
||||
233
contrib/slapd-modules/rbac/rbacperm.c
Normal file
233
contrib/slapd-modules/rbac/rbacperm.c
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/* rbacperm.c - RBAC permission */
|
||||
/* $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 int
|
||||
rbac_read_permission_cb( Operation *op, SlapReply *rs )
|
||||
{
|
||||
rbac_callback_info_t *cbp = op->o_callback->sc_private;
|
||||
rbac_ad_t *permission_ads;
|
||||
rbac_permission_t *permp;
|
||||
int i;
|
||||
|
||||
if ( rs->sr_type != REP_SEARCH ) return 0;
|
||||
|
||||
assert( cbp );
|
||||
|
||||
permp = ch_calloc( 1, sizeof(rbac_permission_t) );
|
||||
permission_ads = cbp->tenantp->schema->permission_ads;
|
||||
|
||||
ber_dupbv( &permp->dn, &rs->sr_entry->e_name );
|
||||
for ( i = 0; !BER_BVISNULL( &permission_ads[i].attr ); i++ ) {
|
||||
Attribute *attr = NULL;
|
||||
attr = attr_find( rs->sr_entry->e_attrs, *permission_ads[i].ad );
|
||||
if ( attr != NULL ) {
|
||||
switch ( permission_ads[i].type ) {
|
||||
case RBAC_USERS:
|
||||
ber_bvarray_dup_x( &permp->uids, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_ROLES:
|
||||
ber_bvarray_dup_x( &permp->roles, attr->a_nvals, NULL );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cbp->private = (void *)permp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether roles assigned to a user allows access to roles in
|
||||
* a permission, subject to role constraints
|
||||
*/
|
||||
int
|
||||
rbac_check_session_permission(
|
||||
rbac_session_t *sessp,
|
||||
rbac_permission_t *permp,
|
||||
rbac_constraint_t *role_constraints )
|
||||
{
|
||||
int rc = LDAP_INSUFFICIENT_ACCESS;
|
||||
rbac_constraint_t *cp = NULL;
|
||||
int i, j;
|
||||
|
||||
if ( !sessp->roles || !permp->roles ) goto done;
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &sessp->roles[i] ); i++ ) {
|
||||
for ( j = 0; !BER_BVISNULL( &permp->roles[j] ); j++ ) {
|
||||
if ( ber_bvstrcasecmp( &sessp->roles[i], &permp->roles[j] ) == 0 ) {
|
||||
/* role temporal constraint */
|
||||
cp = rbac_role2constraint( &permp->roles[j], role_constraints );
|
||||
if ( !cp || rbac_check_time_constraint( cp ) == LDAP_SUCCESS ) {
|
||||
rc = LDAP_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rbac_permission_t *
|
||||
rbac_read_permission( Operation *op, rbac_req_t *reqp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
rbac_callback_info_t rbac_cb;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char fbuf[1024];
|
||||
struct berval filter = { sizeof(fbuf), fbuf };
|
||||
char permbuf[1024];
|
||||
struct berval permdn = { sizeof(permbuf), permbuf };
|
||||
struct berval permndn = BER_BVNULL;
|
||||
char pcls[] = "(objectClass=ftOperation)";
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
slap_callback cb = { 0 };
|
||||
tenant_info_t *tenantp = rbac_tid2tenant( &reqp->tenantid );
|
||||
|
||||
#if 0 /* check valid object name and op name */
|
||||
if ( !is_valid_opname( &reqp->opname ) ||
|
||||
!is_valid_objname( &reqp->objname ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
|
||||
"invalid opname (%s) or objname (%s)\n",
|
||||
reqp->opname.bv_val, reqp->objname.bv_val );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !tenantp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
|
||||
"missing tenant information\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( reqp->objid.bv_val != NULL ) {
|
||||
permdn.bv_len = snprintf( permdn.bv_val, permdn.bv_len,
|
||||
"ftObjId=%s+ftOpNm=%s,ftObjNm=%s,%s", reqp->objid.bv_val,
|
||||
reqp->opname.bv_val, reqp->objname.bv_val,
|
||||
tenantp->permissions_basedn.bv_val );
|
||||
} else {
|
||||
permdn.bv_len = snprintf( permdn.bv_val, permdn.bv_len,
|
||||
"ftOpNm=%s,ftObjNm=%s,%s", reqp->opname.bv_val,
|
||||
reqp->objname.bv_val, tenantp->permissions_basedn.bv_val );
|
||||
}
|
||||
|
||||
rc = dnNormalize( 0, NULL, NULL, &permdn, &permndn, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
|
||||
"unable to normalize permission DN\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
filter.bv_val = pcls;
|
||||
filter.bv_len = strlen( pcls );
|
||||
rbac_cb.tenantp = tenantp;
|
||||
rbac_cb.private = NULL;
|
||||
|
||||
Operation op2 = *op;
|
||||
cb.sc_private = &rbac_cb;
|
||||
cb.sc_response = rbac_read_permission_cb;
|
||||
op2.o_callback = &cb;
|
||||
op2.o_tag = LDAP_REQ_SEARCH;
|
||||
op2.o_dn = tenantp->admin;
|
||||
op2.o_ndn = tenantp->admin;
|
||||
op2.o_req_dn = permdn;
|
||||
op2.o_req_ndn = permndn;
|
||||
op2.ors_filterstr = filter;
|
||||
op2.ors_filter = str2filter_x( &op2, filter.bv_val );
|
||||
op2.ors_scope = LDAP_SCOPE_BASE;
|
||||
op2.ors_attrs = tenantp->schema->perm_attrs;
|
||||
op2.ors_tlimit = SLAP_NO_LIMIT;
|
||||
op2.ors_slimit = SLAP_NO_LIMIT;
|
||||
op2.ors_attrsonly = 0;
|
||||
op2.ors_limit = NULL;
|
||||
op2.o_bd = frontendDB;
|
||||
rc = op2.o_bd->be_search( &op2, &rs2 );
|
||||
filter_free_x( &op2, op2.ors_filter, 1 );
|
||||
|
||||
done:;
|
||||
ch_free( permndn.bv_val );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
rbac_free_permission((rbac_permission_t *)rbac_cb.private);
|
||||
}
|
||||
|
||||
return (rbac_permission_t *)rbac_cb.private;
|
||||
}
|
||||
|
||||
void
|
||||
rbac_free_permission( rbac_permission_t *permp )
|
||||
{
|
||||
if ( !permp ) return;
|
||||
|
||||
if ( !BER_BVISNULL( &permp->dn ) ) {
|
||||
ber_memfree( permp->dn.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &permp->internalId ) ) {
|
||||
ber_memfree( permp->internalId.bv_val );
|
||||
}
|
||||
|
||||
if ( permp->opName ) {
|
||||
ber_bvarray_free( permp->opName );
|
||||
}
|
||||
|
||||
if ( permp->objName ) {
|
||||
ber_bvarray_free( permp->objName );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &permp->objectId ) ) {
|
||||
ber_memfree( permp->objectId.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &permp->abstractName ) ) {
|
||||
ber_memfree( permp->abstractName.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &permp->type ) ) {
|
||||
ber_memfree( permp->type.bv_val );
|
||||
}
|
||||
|
||||
if ( permp->roles ) {
|
||||
ber_bvarray_free( permp->roles );
|
||||
}
|
||||
|
||||
if ( permp->uids ) {
|
||||
ber_bvarray_free( permp->uids );
|
||||
}
|
||||
ch_free( permp );
|
||||
|
||||
return;
|
||||
}
|
||||
89
contrib/slapd-modules/rbac/rbacreq.c
Normal file
89
contrib/slapd-modules/rbac/rbacreq.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* rbacreq.c - RBAC requests */
|
||||
/* $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"
|
||||
|
||||
rbac_req_t *
|
||||
rbac_alloc_req( int type )
|
||||
{
|
||||
rbac_req_t *reqp = NULL;
|
||||
|
||||
reqp = ch_calloc( 1, sizeof(rbac_req_t) );
|
||||
|
||||
reqp->req_type = type;
|
||||
BER_BVZERO( &reqp->sessid );
|
||||
BER_BVZERO( &reqp->tenantid );
|
||||
/* session creation */
|
||||
BER_BVZERO( &reqp->uid );
|
||||
BER_BVZERO( &reqp->authtok );
|
||||
reqp->roles = NULL;
|
||||
/* check access */
|
||||
BER_BVZERO( &reqp->opname );
|
||||
BER_BVZERO( &reqp->objname );
|
||||
BER_BVZERO( &reqp->objid );
|
||||
/* add/drop role */
|
||||
BER_BVZERO( &reqp->role );
|
||||
|
||||
return reqp;
|
||||
}
|
||||
|
||||
void
|
||||
rbac_free_req( rbac_req_t *reqp )
|
||||
{
|
||||
if ( !reqp ) return;
|
||||
|
||||
if ( !BER_BVISNULL( &reqp->sessid ) )
|
||||
ber_memfree( reqp->sessid.bv_val );
|
||||
|
||||
if ( !BER_BVISNULL( &reqp->tenantid ) )
|
||||
ber_memfree( reqp->tenantid.bv_val );
|
||||
|
||||
/* session creation */
|
||||
if ( !BER_BVISNULL( &reqp->uid ) )
|
||||
ber_memfree( reqp->uid.bv_val );
|
||||
|
||||
if ( !BER_BVISNULL( &reqp->authtok ) )
|
||||
ber_memfree( reqp->authtok.bv_val );
|
||||
|
||||
if ( reqp->roles )
|
||||
ber_bvarray_free( reqp->roles );
|
||||
|
||||
/* check access */
|
||||
if ( !BER_BVISNULL( &reqp->opname ) )
|
||||
ber_memfree( reqp->opname.bv_val );
|
||||
|
||||
if ( !BER_BVISNULL( &reqp->objname ) )
|
||||
ber_memfree( reqp->objname.bv_val );
|
||||
|
||||
if ( !BER_BVISNULL( &reqp->objid ) )
|
||||
ber_memfree( reqp->objid.bv_val );
|
||||
|
||||
ch_free( reqp );
|
||||
|
||||
return;
|
||||
}
|
||||
999
contrib/slapd-modules/rbac/rbacsess.c
Normal file
999
contrib/slapd-modules/rbac/rbacsess.c
Normal file
|
|
@ -0,0 +1,999 @@
|
|||
/* rbacsess.c - RBAC session */
|
||||
/* $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 slap_callback nullsc = { NULL, NULL, NULL, NULL };
|
||||
|
||||
extern rbac_ad_t rbac_session_permission_ads[];
|
||||
extern rbac_ad_t rbac_session_ads[];
|
||||
|
||||
struct berval slapo_session_oc = BER_BVC("rbacSession");
|
||||
|
||||
typedef struct session_perm_req {
|
||||
Operation *op;
|
||||
SlapReply *rs;
|
||||
struct berval *sessid;
|
||||
struct berval permdn;
|
||||
tenant_info_t *tenantp;
|
||||
} session_perm_req_t;
|
||||
|
||||
static int
|
||||
rbac_sess_fake_cb( Operation *op, SlapReply *rs )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_sess_fake_cb\n" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rbac_send_session_permission(
|
||||
session_perm_req_t *sess_perm_reqp,
|
||||
rbac_permission_t *perm )
|
||||
{
|
||||
int i, rc = LDAP_SUCCESS;
|
||||
Operation *op = sess_perm_reqp->op;
|
||||
SlapReply *rs = sess_perm_reqp->rs;
|
||||
struct berval *sessidp = sess_perm_reqp->sessid;
|
||||
struct berval *permdnp = &sess_perm_reqp->permdn;
|
||||
|
||||
Entry *e = entry_alloc();
|
||||
e->e_attrs = NULL;
|
||||
ber_dupbv( &e->e_name, permdnp );
|
||||
ber_dupbv( &e->e_nname, permdnp );
|
||||
e->e_private = NULL;
|
||||
attr_merge_one( e, slap_rbac_schema.ad_session_id, sessidp, NULL );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &rbac_session_permission_ads[i].attr ); i++ ) {
|
||||
switch ( rbac_session_permission_ads[i].type ) {
|
||||
case RBAC_OP_NAME:
|
||||
attr_merge_one( e, *rbac_session_permission_ads[i].ad,
|
||||
&perm->opName[0], NULL );
|
||||
break;
|
||||
case RBAC_OBJ_NAME:
|
||||
attr_merge_one( e, *rbac_session_permission_ads[i].ad,
|
||||
&perm->objName[0], NULL );
|
||||
break;
|
||||
case RBAC_ROLE_NAME:
|
||||
attr_merge( e, *rbac_session_permission_ads[i].ad, perm->roles,
|
||||
NULL );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rs->sr_entry = e;
|
||||
rs->sr_flags = REP_ENTRY_MUSTRELEASE;
|
||||
rc = send_search_entry( op, rs );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
rbac_session_permissions_cb( Operation *op, SlapReply *rs )
|
||||
{
|
||||
session_perm_req_t *sess_perm_reqp = op->o_callback->sc_private;
|
||||
tenant_info_t *tenantp = NULL;
|
||||
rbac_permission_t *permp = NULL;
|
||||
rbac_ad_t *session_permissions_ads;
|
||||
int i;
|
||||
|
||||
if ( rs->sr_type != REP_SEARCH ) return 0;
|
||||
|
||||
assert( sess_perm_reqp );
|
||||
|
||||
tenantp = sess_perm_reqp->tenantp;
|
||||
session_permissions_ads = tenantp->schema->session_permissions_ads;
|
||||
|
||||
permp = ch_calloc( 1, sizeof(rbac_permission_t) );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &session_permissions_ads[i].attr ); i++ ) {
|
||||
Attribute *attr = NULL;
|
||||
|
||||
attr = attr_find(
|
||||
rs->sr_entry->e_attrs, *session_permissions_ads[i].ad );
|
||||
if ( attr != NULL ) {
|
||||
switch ( session_permissions_ads[i].type ) {
|
||||
case RBAC_USERS:
|
||||
ber_bvarray_dup_x( &permp->uids, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_ROLES:
|
||||
ber_bvarray_dup_x( &permp->roles, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_OBJ_NAME:
|
||||
ber_bvarray_dup_x( &permp->objName, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_OP_NAME:
|
||||
ber_bvarray_dup_x( &permp->opName, attr->a_nvals, NULL );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rbac_send_session_permission( sess_perm_reqp, permp );
|
||||
rbac_free_permission( permp );
|
||||
permp = NULL;
|
||||
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
rbac_read_session_cb( Operation *op, SlapReply *rs )
|
||||
{
|
||||
rbac_session_t *sessp = op->o_callback->sc_private;
|
||||
int i;
|
||||
|
||||
if ( rs->sr_type != REP_SEARCH ) return 0;
|
||||
|
||||
ber_dupbv( &sessp->sessdn, &rs->sr_entry->e_name );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &rbac_session_ads[i].attr ); i++ ) {
|
||||
Attribute *attr = NULL;
|
||||
attr = attr_find( rs->sr_entry->e_attrs, *rbac_session_ads[i].ad );
|
||||
if ( attr != NULL ) {
|
||||
switch ( rbac_session_ads[i].type ) {
|
||||
case RBAC_SESSION_ID:
|
||||
ber_dupbv( &sessp->sessid, &attr->a_vals[0] );
|
||||
break;
|
||||
case RBAC_USER_DN:
|
||||
ber_dupbv( &sessp->userdn, &attr->a_vals[0] );
|
||||
break;
|
||||
case RBAC_ROLES:
|
||||
ber_bvarray_dup_x( &sessp->roles, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_ROLE_CONSTRAINTS:
|
||||
ber_bvarray_dup_x(
|
||||
&sessp->role_constraints, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_UID:
|
||||
ber_dupbv( &sessp->uid, &attr->a_vals[0] );
|
||||
break;
|
||||
case RBAC_TENANT_ID:
|
||||
ber_dupbv( &sessp->tenantid, &attr->a_vals[0] );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return SLAP_CB_CONTINUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check whether the session is owned by the user */
|
||||
int
|
||||
rbac_is_session_owner( rbac_session_t *sessp, rbac_req_t *reqp )
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if ( BER_BVISEMPTY( &sessp->uid ) || BER_BVISEMPTY( &reqp->uid ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "session not owned by user\n" );
|
||||
rc = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !ber_bvstrcasecmp( &sessp->uid, &reqp->uid ) ) {
|
||||
rc = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_session_add_role( Operation *op, rbac_session_t *sessp, rbac_req_t *reqp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
slap_callback cb = { 0 };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
rbac_callback_info_t rbac_cb;
|
||||
tenant_info_t *tenantp = NULL;
|
||||
struct berval vals[2];
|
||||
Modifications mod;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
tenantp = rbac_tid2tenant( &reqp->tenantid );
|
||||
if ( !tenantp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_session_add_role: "
|
||||
"no tenant info with the req\n" );
|
||||
goto done;
|
||||
}
|
||||
|
||||
// convert the role name to lower case:
|
||||
rbac_to_lower( &reqp->role );
|
||||
|
||||
//ber_dupbv( &vals[0], &reqp->roles[0]);
|
||||
ber_dupbv( &vals[0], &reqp->role );
|
||||
BER_BVZERO( &vals[1] );
|
||||
|
||||
/* create mod list */
|
||||
mod.sml_op = LDAP_MOD_ADD;
|
||||
mod.sml_flags = 0;
|
||||
mod.sml_type = slap_rbac_schema.ad_session_roles->ad_cname;
|
||||
mod.sml_desc = slap_rbac_schema.ad_session_roles;
|
||||
mod.sml_numvals = 1;
|
||||
mod.sml_values = vals;
|
||||
mod.sml_nvalues = NULL;
|
||||
mod.sml_next = NULL;
|
||||
|
||||
cb.sc_private = &rbac_cb;
|
||||
cb.sc_response = rbac_sess_fake_cb;
|
||||
op2.o_callback = &cb;
|
||||
|
||||
op2.o_tag = LDAP_REQ_MODIFY;
|
||||
op2.orm_modlist = &mod;
|
||||
op2.o_req_dn = sessp->sessdn;
|
||||
op2.o_req_ndn = sessp->sessdn;
|
||||
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_rootdn;
|
||||
op2.ors_limit = NULL;
|
||||
rc = op2.o_bd->be_modify( &op2, &rs2 );
|
||||
ch_free( vals[0].bv_val );
|
||||
|
||||
done:;
|
||||
if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_add_active_role: "
|
||||
"role already activated in session\n" );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_session_drop_role( Operation *op, rbac_session_t *sessp, rbac_req_t *reqp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
slap_callback cb = { 0 };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
rbac_callback_info_t rbac_cb;
|
||||
tenant_info_t *tenantp = NULL;
|
||||
Modifications *m = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
tenantp = rbac_tid2tenant( &reqp->tenantid );
|
||||
if ( !tenantp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_session_drop_role: "
|
||||
"no tenant info with the req\n" );
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* create mod list */
|
||||
m = ch_calloc( sizeof(Modifications), 1 );
|
||||
m->sml_op = LDAP_MOD_DELETE;
|
||||
m->sml_flags = 0;
|
||||
m->sml_type = slap_rbac_schema.ad_session_roles->ad_cname;
|
||||
m->sml_desc = slap_rbac_schema.ad_session_roles;
|
||||
m->sml_numvals = 1;
|
||||
m->sml_values = ch_calloc( sizeof(struct berval), 2 );
|
||||
m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 );
|
||||
//ber_dupbv( &m->sml_values[0], &reqp->roles[0]);
|
||||
|
||||
// convert the role name to lower case:
|
||||
rbac_to_lower( &reqp->role );
|
||||
|
||||
ber_dupbv( &m->sml_values[0], &reqp->role );
|
||||
|
||||
// todo: determine if this needs to be done:
|
||||
//BER_BVZERO(&m->sml_values[1]);
|
||||
|
||||
ber_dupbv( &m->sml_nvalues[0], &reqp->role );
|
||||
BER_BVZERO( &m->sml_nvalues[1] );
|
||||
|
||||
//ber_dupbv( &m->sml_nvalues[0], &reqp->roles[0]);
|
||||
//ber_dupbv( &m->sml_nvalues[0], &reqp->role);
|
||||
//BER_BVZERO(&m->sml_nvalues[1]);
|
||||
|
||||
m->sml_next = NULL;
|
||||
|
||||
cb.sc_private = &rbac_cb;
|
||||
cb.sc_response = rbac_sess_fake_cb;
|
||||
op2.o_callback = &cb;
|
||||
|
||||
op2.o_dn = tenantp->session_admin;
|
||||
op2.o_ndn = tenantp->session_admin;
|
||||
op2.o_tag = LDAP_REQ_MODIFY;
|
||||
op2.orm_modlist = m;
|
||||
op2.o_req_dn = sessp->sessdn;
|
||||
op2.o_req_ndn = sessp->sessdn;
|
||||
op2.o_bd = select_backend( &op2.o_req_ndn, 0 );
|
||||
|
||||
op2.ors_limit = NULL;
|
||||
rc = op2.o_bd->be_modify( &op2, &rs2 );
|
||||
|
||||
done:;
|
||||
if ( m ) {
|
||||
slap_mods_free( m, 1 );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* delete the session */
|
||||
int
|
||||
rbac_int_delete_session( Operation *op, rbac_session_t *sessp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
slap_callback cb = { 0 };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
rbac_callback_info_t rbac_cb;
|
||||
tenant_info_t *tenantp = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
tenantp = rbac_tid2tenant( &sessp->tenantid );
|
||||
if ( !tenantp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_session_drop_role: "
|
||||
"no tenant info with the req\n" );
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* delete RBAC session */
|
||||
cb.sc_private = &rbac_cb;
|
||||
cb.sc_response = rbac_sess_fake_cb;
|
||||
op2.o_callback = &cb;
|
||||
|
||||
op2.o_dn = tenantp->session_admin;
|
||||
op2.o_ndn = tenantp->session_admin;
|
||||
op2.o_tag = LDAP_REQ_DELETE;
|
||||
op2.o_req_dn = sessp->sessdn;
|
||||
op2.o_req_ndn = sessp->sessdn;
|
||||
op2.o_bd = select_backend( &op2.o_req_ndn, 0 );
|
||||
rc = op2.o_bd->be_delete( &op2, &rs2 );
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rbac_session_t *
|
||||
rbac_alloc_session()
|
||||
{
|
||||
rbac_session_t *sessp = NULL;
|
||||
|
||||
sessp = ch_malloc( sizeof(rbac_session_t) );
|
||||
sessp->sessid.bv_len =
|
||||
lutil_uuidstr( sessp->uuidbuf, sizeof(sessp->uuidbuf) );
|
||||
sessp->sessid.bv_val = sessp->uuidbuf;
|
||||
|
||||
sessp->user = NULL;
|
||||
BER_BVZERO( &sessp->tenantid );
|
||||
BER_BVZERO( &sessp->uid );
|
||||
BER_BVZERO( &sessp->userdn );
|
||||
BER_BVZERO( &sessp->sessdn );
|
||||
BER_BVZERO( &sessp->message );
|
||||
|
||||
sessp->last_access = 0;
|
||||
sessp->timeout = 0;
|
||||
sessp->warning_id = 0;
|
||||
sessp->error_id = 0;
|
||||
sessp->grace_logins = 0;
|
||||
sessp->expiration_secs = 0;
|
||||
sessp->is_authenticated = 0;
|
||||
|
||||
sessp->roles = NULL;
|
||||
sessp->role_constraints = NULL;
|
||||
|
||||
return sessp;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_register_session( Operation *op, SlapReply *rs, rbac_session_t *sessp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
struct berval rdn, nrdn;
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
OperationBuffer opbuf;
|
||||
Operation *op2;
|
||||
Connection conn = { 0 };
|
||||
Entry *e = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char rdnbuf[
|
||||
STRLENOF(RBAC_SESSION_RDN_EQ) + LDAP_LUTIL_UUIDSTR_BUFSIZE + 1];
|
||||
tenant_info_t *tenantp = rbac_tid2tenant( &sessp->tenantid );
|
||||
#ifdef USE_NEW_THREAD_CONTEXT
|
||||
void *thrctx = ldap_pvt_thread_pool_context();
|
||||
#else
|
||||
void *thrctx = op->o_tmpmemctx;
|
||||
#endif
|
||||
|
||||
if ( !sessp ) {
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* dynamic objects */
|
||||
e = entry_alloc();
|
||||
|
||||
strcpy( rdnbuf, RBAC_SESSION_RDN_EQ );
|
||||
strncat( rdnbuf, sessp->sessid.bv_val, sessp->sessid.bv_len );
|
||||
rdn.bv_val = rdnbuf;
|
||||
rdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
|
||||
nrdn.bv_val = rdnbuf;
|
||||
nrdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
|
||||
|
||||
build_new_dn( &e->e_name, &tenantp->sessions_basedn, &rdn, NULL );
|
||||
build_new_dn( &e->e_nname, &tenantp->sessions_basedn, &nrdn, NULL );
|
||||
|
||||
attr_merge_one( e, slap_schema.si_ad_objectClass, &slapo_session_oc, NULL );
|
||||
attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
|
||||
&slapo_session_oc, NULL );
|
||||
attr_merge_one( e, slap_rbac_schema.ad_session_id, &sessp->sessid, NULL );
|
||||
|
||||
if ( !BER_BVISNULL( &sessp->uid ) ) {
|
||||
attr_merge_one( e, slap_schema.si_ad_uid, &sessp->uid, NULL );
|
||||
}
|
||||
|
||||
/* add tenant id */
|
||||
if ( !BER_BVISNULL( &sessp->tenantid ) ) {
|
||||
attr_merge_one(
|
||||
e, slap_rbac_schema.ad_tenant_id, &sessp->tenantid, NULL );
|
||||
}
|
||||
|
||||
/* add the userdn */
|
||||
if ( !BER_BVISNULL( &sessp->userdn ) ) {
|
||||
attr_merge_one(
|
||||
e, slap_rbac_schema.ad_session_user_dn, &sessp->userdn, NULL );
|
||||
}
|
||||
|
||||
if ( sessp->roles ) {
|
||||
attr_merge( e, slap_rbac_schema.ad_session_roles, sessp->roles, NULL );
|
||||
}
|
||||
|
||||
// TODO: ensure this is correct way to store constraints in session:
|
||||
if ( sessp->role_constraints ) {
|
||||
attr_merge( e, slap_rbac_schema.ad_session_role_constraints,
|
||||
sessp->role_constraints, NULL );
|
||||
}
|
||||
/* rendered dynmaicObject */
|
||||
attr_merge_one( e, slap_schema.si_ad_objectClass,
|
||||
&slap_schema.si_oc_dynamicObject->soc_cname, NULL );
|
||||
|
||||
/* store RBAC session */
|
||||
connection_fake_init2( &conn, &opbuf, thrctx, 0 );
|
||||
op2 = &opbuf.ob_op;
|
||||
//Operation op2 = *op;
|
||||
//op2.o_callback = &nullsc;
|
||||
//rbac_callback_info_t rbac_cb;
|
||||
//cb.sc_private = &rbac_cb;
|
||||
//cb.sc_response = rbac_sess_fake_cb;
|
||||
//op2.o_callback = &cb;
|
||||
//op2.ors_limit = NULL;
|
||||
op->o_callback = &nullsc;
|
||||
op2->o_dn = tenantp->session_admin;
|
||||
op2->o_ndn = tenantp->session_admin;
|
||||
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 = frontendDB;
|
||||
|
||||
rc = op2->o_bd->be_add( op2, &rs2 );
|
||||
|
||||
done:;
|
||||
if ( e ) entry_free( e );
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_register_session2( Operation *op, SlapReply *rs, rbac_session_t *sessp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
struct berval rdn, nrdn;
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
rbac_callback_info_t rbac_cb;
|
||||
//OperationBuffer opbuf;
|
||||
//Connection conn = {0};
|
||||
Entry *e = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char rdnbuf[STRLENOF(RBAC_SESSION_RDN_EQ) + LDAP_LUTIL_UUIDSTR_BUFSIZE +
|
||||
1];
|
||||
tenant_info_t *tenantp = rbac_tid2tenant( &sessp->tenantid );
|
||||
slap_callback cb = { 0 };
|
||||
//#ifdef USE_NEW_THREAD_CONTEXT
|
||||
// void *thrctx = ldap_pvt_thread_pool_context();
|
||||
//#else
|
||||
// void *thrctx = op->o_tmpmemctx;
|
||||
//#endif
|
||||
|
||||
if ( !sessp ) {
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* dynamic objects */
|
||||
e = entry_alloc();
|
||||
|
||||
strcpy( rdnbuf, RBAC_SESSION_RDN_EQ );
|
||||
strncat( rdnbuf, sessp->sessid.bv_val, sessp->sessid.bv_len );
|
||||
rdn.bv_val = rdnbuf;
|
||||
rdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
|
||||
nrdn.bv_val = rdnbuf;
|
||||
nrdn.bv_len = STRLENOF(RBAC_SESSION_RDN_EQ) + sessp->sessid.bv_len;
|
||||
|
||||
build_new_dn( &e->e_name, &tenantp->sessions_basedn, &rdn, NULL );
|
||||
build_new_dn( &e->e_nname, &tenantp->sessions_basedn, &nrdn, NULL );
|
||||
|
||||
attr_merge_one( e, slap_schema.si_ad_objectClass, &slapo_session_oc, NULL );
|
||||
attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
|
||||
&slapo_session_oc, NULL );
|
||||
attr_merge_one( e, slap_rbac_schema.ad_session_id, &sessp->sessid, NULL );
|
||||
|
||||
if ( !BER_BVISNULL( &sessp->uid ) ) {
|
||||
attr_merge_one( e, slap_schema.si_ad_uid, &sessp->uid, NULL );
|
||||
}
|
||||
|
||||
/* add tenant id */
|
||||
if ( !BER_BVISNULL( &sessp->tenantid ) ) {
|
||||
attr_merge_one(
|
||||
e, slap_rbac_schema.ad_tenant_id, &sessp->tenantid, NULL );
|
||||
}
|
||||
|
||||
/* add the userdn */
|
||||
if ( !BER_BVISNULL( &sessp->userdn ) ) {
|
||||
attr_merge_one(
|
||||
e, slap_rbac_schema.ad_session_user_dn, &sessp->userdn, NULL );
|
||||
}
|
||||
|
||||
if ( sessp->roles ) {
|
||||
attr_merge( e, slap_rbac_schema.ad_session_roles, sessp->roles, NULL );
|
||||
}
|
||||
|
||||
// TODO: ensure this is correct way to store constraints in session:
|
||||
if ( sessp->role_constraints ) {
|
||||
attr_merge( e, slap_rbac_schema.ad_session_role_constraints,
|
||||
sessp->role_constraints, NULL );
|
||||
}
|
||||
/* rendered dynmaicObject */
|
||||
attr_merge_one( e, slap_schema.si_ad_objectClass,
|
||||
&slap_schema.si_oc_dynamicObject->soc_cname, NULL );
|
||||
|
||||
/* store RBAC session */
|
||||
//connection_fake_init2( &conn, &opbuf, thrctx, 0 );
|
||||
//op2 = &opbuf.ob_op;
|
||||
//op2.o_ctrlflag = op->o_ctrlflag;
|
||||
// todo this ain't right"
|
||||
//op2.o_ctrlflag = 0;
|
||||
//OperationBuffer *opbuf;
|
||||
//memset( opbuf, 0, sizeof(OperationBuffer));
|
||||
//op2.o_hdr = &opbuf->ob_hdr;
|
||||
//op2.o_controls = opbuf->ob_controls;
|
||||
|
||||
// fails on modify.c:353 with segfault
|
||||
|
||||
//op2.o_callback = &nullsc;
|
||||
cb.sc_private = &rbac_cb;
|
||||
cb.sc_response = rbac_sess_fake_cb;
|
||||
op2.o_callback = &cb;
|
||||
op2.o_dn = tenantp->session_admin;
|
||||
op2.o_ndn = tenantp->session_admin;
|
||||
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 = frontendDB;
|
||||
//op2.ors_limit = NULL;
|
||||
|
||||
rc = op2.o_bd->be_add( &op2, &rs2 );
|
||||
|
||||
done:;
|
||||
if ( e ) entry_free( e );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_is_valid_session_id( struct berval *sessid )
|
||||
{
|
||||
/* TODO: simple test */
|
||||
if ( !sessid || sessid->bv_len != 36 ) {
|
||||
if ( !sessid ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_is_valid_session_id: "
|
||||
"null sessid\n" );
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_is_valid_session_id: "
|
||||
"len (%lu)\n",
|
||||
sessid->bv_len );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* create an rbac request with the session ID */
|
||||
rbac_req_t *
|
||||
rbac_is_search_session_permissions( Operation *op )
|
||||
{
|
||||
rbac_req_t *reqp = NULL;
|
||||
|
||||
/* check whether the search for sessionPermissions and *
|
||||
* with a valid sessionID */
|
||||
|
||||
return reqp;
|
||||
}
|
||||
|
||||
rbac_session_t *
|
||||
rbac_session_byid_fake( Operation *op, rbac_req_t *reqp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
rbac_session_t *sessp = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char fbuf[RBAC_BUFLEN];
|
||||
struct berval filter = { sizeof(fbuf), fbuf };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
rbac_callback_info_t rbac_cb;
|
||||
slap_callback cb = { 0 };
|
||||
tenant_info_t *tenantp = NULL;
|
||||
|
||||
if ( !rbac_is_valid_session_id( &reqp->sessid ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
|
||||
"invalid session id (%s)\n",
|
||||
reqp->sessid.bv_val );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
sessp = rbac_alloc_session();
|
||||
if ( !sessp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
|
||||
"unable to allocate session memory\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
tenantp = rbac_tid2tenant( &reqp->tenantid );
|
||||
|
||||
/* session id filter */
|
||||
memset( fbuf, 0, sizeof(fbuf) );
|
||||
strcpy( fbuf, RBAC_SESSION_RDN_EQ );
|
||||
strncpy( &fbuf[0] + sizeof(RBAC_SESSION_RDN_EQ) - 1, reqp->sessid.bv_val,
|
||||
reqp->sessid.bv_len );
|
||||
filter.bv_val = fbuf;
|
||||
filter.bv_len = strlen( fbuf );
|
||||
|
||||
//cb.sc_private = sessp;
|
||||
//cb.sc_response = rbac_read_session_cb;
|
||||
cb.sc_private = &rbac_cb;
|
||||
cb.sc_response = rbac_sess_fake_cb;
|
||||
op2.o_callback = &cb;
|
||||
op2.o_tag = LDAP_REQ_SEARCH;
|
||||
op2.o_dn = tenantp->session_admin;
|
||||
op2.o_ndn = tenantp->session_admin;
|
||||
op2.o_req_dn = tenantp->sessions_basedn;
|
||||
op2.o_req_ndn = tenantp->sessions_basedn;
|
||||
op2.ors_filterstr = filter;
|
||||
op2.ors_filter = str2filter_x( &op2, filter.bv_val );
|
||||
op2.ors_scope = LDAP_SCOPE_SUBTREE;
|
||||
op2.ors_attrs = slap_rbac_schema.session_attrs;
|
||||
op2.ors_tlimit = SLAP_NO_LIMIT;
|
||||
op2.ors_slimit = SLAP_NO_LIMIT;
|
||||
op2.o_bd = frontendDB;
|
||||
// hyc change to fix seg fault:
|
||||
op2.ors_limit = NULL;
|
||||
|
||||
rc = op2.o_bd->be_search( &op2, &rs2 );
|
||||
filter_free_x( &op2, op2.ors_filter, 1 );
|
||||
|
||||
done:
|
||||
// TODO: find equivilant way of check nentries (broke with fake connection fix)
|
||||
//if ( rc != LDAP_SUCCESS || rs2.sr_nentries <= 0 ) {
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
rbac_free_session( sessp );
|
||||
sessp = NULL;
|
||||
}
|
||||
|
||||
return sessp;
|
||||
}
|
||||
|
||||
rbac_session_t *
|
||||
rbac_session_byid( Operation *op, rbac_req_t *reqp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
rbac_session_t *sessp = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char fbuf[RBAC_BUFLEN];
|
||||
struct berval filter = { sizeof(fbuf), fbuf };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
slap_callback cb = { 0 };
|
||||
tenant_info_t *tenantp = NULL;
|
||||
|
||||
if ( !rbac_is_valid_session_id( &reqp->sessid ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
|
||||
"invalid session id (%s)\n",
|
||||
reqp->sessid.bv_val );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
sessp = rbac_alloc_session();
|
||||
if ( !sessp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_session_byid: "
|
||||
"unable to allocate session memory\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
tenantp = rbac_tid2tenant( &reqp->tenantid );
|
||||
|
||||
/* session id filter */
|
||||
memset( fbuf, 0, sizeof(fbuf) );
|
||||
strcpy( fbuf, RBAC_SESSION_RDN_EQ );
|
||||
strncpy( &fbuf[0] + sizeof(RBAC_SESSION_RDN_EQ) - 1, reqp->sessid.bv_val,
|
||||
reqp->sessid.bv_len );
|
||||
filter.bv_val = fbuf;
|
||||
filter.bv_len = strlen( fbuf );
|
||||
|
||||
cb.sc_private = sessp;
|
||||
cb.sc_response = rbac_read_session_cb;
|
||||
op2.o_callback = &cb;
|
||||
op2.o_tag = LDAP_REQ_SEARCH;
|
||||
op2.o_dn = tenantp->session_admin;
|
||||
op2.o_ndn = tenantp->session_admin;
|
||||
op2.o_req_dn = tenantp->sessions_basedn;
|
||||
op2.o_req_ndn = tenantp->sessions_basedn;
|
||||
op2.ors_filterstr = filter;
|
||||
op2.ors_filter = str2filter_x( &op2, filter.bv_val );
|
||||
op2.ors_scope = LDAP_SCOPE_SUBTREE;
|
||||
op2.ors_attrs = slap_rbac_schema.session_attrs;
|
||||
op2.ors_tlimit = SLAP_NO_LIMIT;
|
||||
op2.ors_slimit = SLAP_NO_LIMIT;
|
||||
op2.o_bd = frontendDB;
|
||||
// hyc change to fix seg fault:
|
||||
op2.ors_limit = NULL;
|
||||
|
||||
rc = op2.o_bd->be_search( &op2, &rs2 );
|
||||
filter_free_x( &op2, op2.ors_filter, 1 );
|
||||
|
||||
done:
|
||||
// TODO: find equivalent way of check nentries (broke with fake connection fix)
|
||||
//if ( rc != LDAP_SUCCESS || rs2.sr_nentries <= 0 ) {
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
rbac_free_session( sessp );
|
||||
sessp = NULL;
|
||||
}
|
||||
|
||||
return sessp;
|
||||
}
|
||||
|
||||
static char *
|
||||
rbac_int_session_permissions_filterstr( Operation *op, rbac_session_t *sessp )
|
||||
{
|
||||
char filterbuf[RBAC_BUFLEN];
|
||||
int i;
|
||||
|
||||
memset( filterbuf, 0, sizeof(filterbuf) );
|
||||
|
||||
strcat( filterbuf, "(&(objectClass=ftOperation)(|" );
|
||||
strcat( filterbuf, "(ftUsers=" );
|
||||
strcat( filterbuf, sessp->uid.bv_val );
|
||||
strcat( filterbuf, ")" );
|
||||
|
||||
/* add ftRoles filters */
|
||||
for ( i = 0; !BER_BVISEMPTY( &sessp->roles[i] ); i++ ) {
|
||||
strcat( filterbuf, "(ftRoles=" );
|
||||
strncat( filterbuf, sessp->roles[i].bv_val, sessp->roles[i].bv_len );
|
||||
strcat( filterbuf, ")" );
|
||||
}
|
||||
strcat( filterbuf, "))" );
|
||||
return strdup( filterbuf );
|
||||
}
|
||||
|
||||
int
|
||||
rbac_int_session_permissions(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
rbac_req_t *reqp,
|
||||
rbac_session_t *sessp )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
tenant_info_t *tenantp = NULL;
|
||||
int rc;
|
||||
struct berval filter;
|
||||
char *filterstr;
|
||||
struct berval permndn = BER_BVNULL;
|
||||
OperationBuffer opbuf;
|
||||
Connection conn = { 0 };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation *op2;
|
||||
slap_callback cb = { 0 };
|
||||
char permbuf[1024];
|
||||
session_perm_req_t sess_perm_req;
|
||||
#ifdef USE_NEW_THREAD_CONTEXT
|
||||
void *thrctx = ldap_pvt_thread_pool_context();
|
||||
#else
|
||||
void *thrctx = op->o_tmpmemctx;
|
||||
#endif
|
||||
|
||||
tenantp = rbac_tid2tenant( &reqp->tenantid );
|
||||
|
||||
/* construct session permissions dn */
|
||||
memset( permbuf, 0, sizeof(permbuf) );
|
||||
strcat( permbuf, "rbacSessid=" );
|
||||
strncat( permbuf, sessp->sessid.bv_val, sessp->sessid.bv_len );
|
||||
strcat( permbuf, ",dc=rbac" );
|
||||
sess_perm_req.op = op;
|
||||
sess_perm_req.rs = rs;
|
||||
sess_perm_req.permdn.bv_val = permbuf;
|
||||
sess_perm_req.permdn.bv_len = strlen( permbuf );
|
||||
sess_perm_req.sessid = &reqp->sessid;
|
||||
sess_perm_req.tenantp = tenantp;
|
||||
|
||||
filterstr = rbac_int_session_permissions_filterstr( op, sessp );
|
||||
if ( !filterstr ) {
|
||||
Debug( LDAP_DEBUG_ANY, "unable to construct filter for session permissions\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
filter.bv_val = filterstr;
|
||||
filter.bv_len = strlen( filterstr );
|
||||
|
||||
rc = dnNormalize(
|
||||
0, NULL, NULL, &tenantp->permissions_basedn, &permndn, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_permission: "
|
||||
"unable to normalize permission DN\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
connection_fake_init2( &conn, &opbuf, thrctx, 0 );
|
||||
op2 = &opbuf.ob_op;
|
||||
//Operation op2 = *op;
|
||||
cb.sc_private = &sess_perm_req;
|
||||
cb.sc_response = rbac_session_permissions_cb;
|
||||
op2->o_callback = &cb;
|
||||
op2->o_tag = LDAP_REQ_SEARCH;
|
||||
op2->o_dn = tenantp->admin;
|
||||
op2->o_ndn = tenantp->admin;
|
||||
op2->o_req_dn = tenantp->permissions_basedn;
|
||||
op2->o_req_ndn = permndn;
|
||||
op2->ors_filterstr = filter;
|
||||
op2->ors_filter = str2filter_x( op, filter.bv_val );
|
||||
op2->ors_scope = LDAP_SCOPE_SUB;
|
||||
op2->ors_attrs = tenantp->schema->session_perm_attrs;
|
||||
op2->ors_tlimit = SLAP_NO_LIMIT;
|
||||
op2->ors_slimit = SLAP_NO_LIMIT;
|
||||
op2->ors_attrsonly = 0;
|
||||
op2->o_bd = frontendDB;
|
||||
//op2.ors_limit = NULL;
|
||||
rc = op2->o_bd->be_search( op2, &rs2 );
|
||||
filter_free_x( op, op2->ors_filter, 1 );
|
||||
|
||||
done:;
|
||||
/* generate audit log */
|
||||
rbac_audit( op, SessionPermissions, sessp, reqp, rc, (char *)rs->sr_text );
|
||||
|
||||
rs->sr_err = rc;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
void
|
||||
rbac_free_session( rbac_session_t *sessp )
|
||||
{
|
||||
if ( !sessp ) return;
|
||||
|
||||
if ( sessp->user ) {
|
||||
rbac_free_user( sessp->user );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &sessp->uid ) ) {
|
||||
ber_memfree( sessp->uid.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &sessp->tenantid ) ) {
|
||||
ber_memfree( sessp->tenantid.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &sessp->userdn ) ) {
|
||||
ber_memfree( sessp->userdn.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &sessp->sessdn ) ) {
|
||||
ber_memfree( sessp->sessdn.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &sessp->message ) ) {
|
||||
ber_memfree( sessp->message.bv_val );
|
||||
}
|
||||
|
||||
if ( sessp->roles ) {
|
||||
ber_bvarray_free( sessp->roles );
|
||||
}
|
||||
|
||||
if ( sessp->role_constraints ) {
|
||||
ber_bvarray_free( sessp->role_constraints );
|
||||
}
|
||||
|
||||
ch_free( sessp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* roles included from request are activated into a session only when
|
||||
* they exist and have been assigned to the user. If no roles included in request, all
|
||||
* roles assigned to the user are activated into the rbac session.
|
||||
*/
|
||||
int
|
||||
activate_session_roles(
|
||||
rbac_session_t *sessp,
|
||||
rbac_req_t *reqp,
|
||||
rbac_user_t *userp )
|
||||
{
|
||||
int i, j, rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
if ( !sessp || !reqp || !userp ) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* no role requested, assign all roles from the user to the session. */
|
||||
if ( reqp->roles == NULL || BER_BVISNULL( &reqp->roles[0] ) ) {
|
||||
//if (!reqp->roles || BER_BVISNULL(&reqp->roles[0])) {
|
||||
/* no roles assigned to the user */
|
||||
if ( !userp->roles || BER_BVISNULL( &userp->roles[0] ) ) goto done;
|
||||
for ( i = 0; !BER_BVISNULL( &userp->roles[i] ); i++ ) {
|
||||
struct berval role;
|
||||
ber_dupbv_x( &role, &userp->roles[i], NULL );
|
||||
ber_bvarray_add( &sessp->roles, &role );
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
// TODO: smm 20141218 - make sure this is correct way to add constraints to user session.
|
||||
for ( i = 0; !BER_BVISNULL( &userp->role_constraints[i] ); i++ ) {
|
||||
struct berval roleconstraint;
|
||||
ber_dupbv_x( &roleconstraint, &userp->role_constraints[i], NULL );
|
||||
ber_bvarray_add( &sessp->role_constraints, &roleconstraint );
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
} else {
|
||||
for ( i = 0; !BER_BVISNULL( &reqp->roles[i] ); i++ ) {
|
||||
for ( j = 0; !BER_BVISNULL( &userp->roles[j] ); j++ ) {
|
||||
if ( !ber_bvstrcasecmp( &reqp->roles[i], &userp->roles[j] ) ) {
|
||||
/* requested role is assigned to the user */
|
||||
struct berval role;
|
||||
ber_dupbv_x( &role, &userp->roles[i], NULL );
|
||||
ber_bvarray_add( &sessp->roles, &role );
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
620
contrib/slapd-modules/rbac/rbacuser.c
Normal file
620
contrib/slapd-modules/rbac/rbacuser.c
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
/* rbacuser.c - RBAC users */
|
||||
/* $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 int ppolicy_cid = -1;
|
||||
|
||||
static rbac_user_t *
|
||||
rbac_alloc_user()
|
||||
{
|
||||
rbac_user_t *userp = ch_calloc( 1, sizeof(rbac_user_t) );
|
||||
|
||||
BER_BVZERO( &userp->tenantid );
|
||||
BER_BVZERO( &userp->uid );
|
||||
BER_BVZERO( &userp->dn );
|
||||
BER_BVZERO( &userp->password );
|
||||
BER_BVZERO( &userp->constraints );
|
||||
BER_BVZERO( &userp->msg );
|
||||
userp->roles = NULL;
|
||||
userp->role_constraints = NULL;
|
||||
|
||||
return userp;
|
||||
}
|
||||
|
||||
static int
|
||||
rbac_read_user_cb( Operation *op, SlapReply *rs )
|
||||
{
|
||||
rbac_callback_info_t *cbp = op->o_callback->sc_private;
|
||||
rbac_ad_t *user_ads;
|
||||
rbac_user_t *userp = NULL;
|
||||
int rc = 0, i;
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_user_cb\n" );
|
||||
|
||||
if ( rs->sr_type != REP_SEARCH ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_user_cb: "
|
||||
"sr_type != REP_SEARCH\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert( cbp );
|
||||
|
||||
user_ads = cbp->tenantp->schema->user_ads;
|
||||
|
||||
userp = rbac_alloc_user();
|
||||
if ( !userp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_user_cb: "
|
||||
"rbac_alloc_user failed\n" );
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
ber_dupbv( &userp->dn, &rs->sr_entry->e_name );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "DEBUG rbac_read_user_cb (%s): "
|
||||
"rc (%d)\n",
|
||||
userp->dn.bv_val, rc );
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &user_ads[i].attr ); i++ ) {
|
||||
Attribute *attr = NULL;
|
||||
|
||||
attr = attr_find( rs->sr_entry->e_attrs, *user_ads[i].ad );
|
||||
if ( attr != NULL ) {
|
||||
switch ( user_ads[i].type ) {
|
||||
case RBAC_ROLE_ASSIGNMENT:
|
||||
ber_bvarray_dup_x( &userp->roles, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_ROLE_CONSTRAINTS:
|
||||
ber_bvarray_dup_x(
|
||||
&userp->role_constraints, attr->a_nvals, NULL );
|
||||
break;
|
||||
case RBAC_USER_CONSTRAINTS:
|
||||
ber_dupbv_x( &userp->constraints, &attr->a_nvals[0], NULL );
|
||||
break;
|
||||
case RBAC_UID:
|
||||
ber_dupbv_x( &userp->uid, &attr->a_nvals[0], NULL );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
cbp->private = userp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rbac_bind_cb( Operation *op, SlapReply *rs )
|
||||
{
|
||||
rbac_user_t *ui = op->o_callback->sc_private;
|
||||
|
||||
LDAPControl *ctrl = ldap_control_find(
|
||||
LDAP_CONTROL_PASSWORDPOLICYRESPONSE, rs->sr_ctrls, NULL );
|
||||
if ( ctrl ) {
|
||||
LDAP *ld;
|
||||
ber_int_t expire, grace;
|
||||
LDAPPasswordPolicyError error;
|
||||
|
||||
ldap_create( &ld );
|
||||
if ( ld ) {
|
||||
int rc = ldap_parse_passwordpolicy_control(
|
||||
ld, ctrl, &expire, &grace, &error );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
ui->authz = RBAC_PASSWORD_GOOD;
|
||||
if ( grace > 0 ) {
|
||||
//ui->msg.bv_len = sprintf(ui->msg.bv_val,
|
||||
// "Password expired; %d grace logins remaining",
|
||||
// grace);
|
||||
ui->authz = RBAC_BIND_NEW_AUTHTOK_REQD;
|
||||
} else if ( error != PP_noError ) {
|
||||
ber_str2bv( ldap_passwordpolicy_err2txt( error ), 0, 0,
|
||||
&ui->msg );
|
||||
|
||||
switch ( error ) {
|
||||
case PP_passwordExpired:
|
||||
ui->authz = RBAC_PASSWORD_EXPIRATION_WARNING;
|
||||
|
||||
if ( expire >= 0 ) {
|
||||
char *unit = "seconds";
|
||||
if ( expire > 60 ) {
|
||||
expire /= 60;
|
||||
unit = "minutes";
|
||||
}
|
||||
if ( expire > 60 ) {
|
||||
expire /= 60;
|
||||
unit = "hours";
|
||||
}
|
||||
if ( expire > 24 ) {
|
||||
expire /= 24;
|
||||
unit = "days";
|
||||
}
|
||||
#if 0 /* Who warns about expiration so far in advance? */
|
||||
if (expire > 7) {
|
||||
expire /= 7;
|
||||
unit = "weeks";
|
||||
}
|
||||
if (expire > 4) {
|
||||
expire /= 4;
|
||||
unit = "months";
|
||||
}
|
||||
if (expire > 12) {
|
||||
expire /= 12;
|
||||
unit = "years";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_accountLocked:
|
||||
ui->authz = RBAC_ACCOUNT_LOCKED;
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_changeAfterReset:
|
||||
ui->authz = RBAC_CHANGE_AFTER_RESET;
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
break;
|
||||
case PP_passwordModNotAllowed:
|
||||
ui->authz = RBAC_NO_MODIFICATIONS;
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_mustSupplyOldPassword:
|
||||
ui->authz = RBAC_MUST_SUPPLY_OLD;
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_insufficientPasswordQuality:
|
||||
ui->authz = RBAC_INSUFFICIENT_QUALITY;
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_passwordTooShort:
|
||||
ui->authz = RBAC_PASSWORD_TOO_SHORT;
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_passwordTooYoung:
|
||||
ui->authz = RBAC_PASSWORD_TOO_YOUNG;
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_passwordInHistory:
|
||||
ui->authz = RBAC_HISTORY_VIOLATION;
|
||||
//rs->sr_err = ;
|
||||
break;
|
||||
case PP_noError:
|
||||
default:
|
||||
// do nothing
|
||||
//ui->authz = RBAC_PASSWORD_GOOD;
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
// switch (error) {
|
||||
// case PP_passwordExpired:
|
||||
/* report this during authz */
|
||||
// rs->sr_err = LDAP_SUCCESS;
|
||||
/* fallthru */
|
||||
// case PP_changeAfterReset:
|
||||
// ui->authz = RBAC_BIND_NEW_AUTHTOK_REQD;
|
||||
// }
|
||||
}
|
||||
}
|
||||
ldap_unbind_ext( ld, NULL, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* exported user functions */
|
||||
int
|
||||
rbac_authenticate_user( Operation *op, rbac_user_t *userp )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
slap_callback cb = { 0 };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
LDAPControl *sctrls[4];
|
||||
LDAPControl sctrl[3];
|
||||
int nsctrls = 0;
|
||||
LDAPControl c;
|
||||
struct berval ber_bvnull = BER_BVNULL;
|
||||
struct berval dn, ndn;
|
||||
|
||||
rc = dnPrettyNormal( 0, &userp->dn, &dn, &ndn, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
cb.sc_response = rbac_bind_cb;
|
||||
cb.sc_private = userp;
|
||||
op2.o_callback = &cb;
|
||||
op2.o_dn = ber_bvnull;
|
||||
op2.o_ndn = ber_bvnull;
|
||||
op2.o_tag = LDAP_REQ_BIND;
|
||||
op2.o_protocol = LDAP_VERSION3;
|
||||
op2.orb_method = LDAP_AUTH_SIMPLE;
|
||||
op2.orb_cred = userp->password;
|
||||
op2.o_req_dn = dn;
|
||||
op2.o_req_ndn = ndn;
|
||||
|
||||
// loading the ldap pw policy controls loaded into here, added by smm:
|
||||
c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
|
||||
c.ldctl_value.bv_val = NULL;
|
||||
c.ldctl_value.bv_len = 0;
|
||||
c.ldctl_iscritical = 0;
|
||||
sctrl[nsctrls] = c;
|
||||
sctrls[nsctrls] = &sctrl[nsctrls];
|
||||
sctrls[++nsctrls] = NULL;
|
||||
op2.o_ctrls = sctrls;
|
||||
|
||||
if ( ppolicy_cid < 0 ) {
|
||||
rc = slap_find_control_id( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
|
||||
&ppolicy_cid );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
// smm - need to set the control flag too:
|
||||
op2.o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_CRITICAL;
|
||||
|
||||
slap_op_time( &op2.o_time, &op2.o_tincr );
|
||||
op2.o_bd = frontendDB;
|
||||
rc = op2.o_bd->be_bind( &op2, &rs2 );
|
||||
if ( userp->authz > 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_authenticate_user (%s): "
|
||||
"password policy violation (%d)\n",
|
||||
userp->dn.bv_val ? userp->dn.bv_val : "NULL", userp->authz );
|
||||
}
|
||||
|
||||
done:;
|
||||
ch_free( dn.bv_val );
|
||||
ch_free( ndn.bv_val );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_authenticate_user (%s): "
|
||||
"rc (%d)\n",
|
||||
userp->dn.bv_val ? userp->dn.bv_val : "NULL", rc );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
isvalidusername(): from OpenLDAP ~/contrib/slapd-modules/nssov/passwd.c
|
||||
Checks to see if the specified name is a valid user name.
|
||||
|
||||
This test is based on the definition from POSIX (IEEE Std 1003.1, 2004, 3.426 User Name
|
||||
and 3.276 Portable Filename Character Set):
|
||||
http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_426
|
||||
http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276
|
||||
|
||||
The standard defines user names valid if they contain characters from
|
||||
the set [A-Za-z0-9._-] where the hyphen should not be used as first
|
||||
character. As an extension this test allows the dolar '$' sign as the last
|
||||
character to support Samba special accounts.
|
||||
*/
|
||||
static int
|
||||
isvalidusername( struct berval *bv )
|
||||
{
|
||||
int i;
|
||||
char *name = bv->bv_val;
|
||||
if ( (name == NULL) || ( name[0] == '\0' ) ) return 0;
|
||||
/* check first character */
|
||||
if ( !( ( name[0] >= 'A' && name[0] <= 'Z' ) ||
|
||||
( name[0] >= 'a' && name[0] <= 'z' ) ||
|
||||
( name[0] >= '0' && name[0] <= '9' ) || name[0] == '.' ||
|
||||
name[0] == '_' ) )
|
||||
return 0;
|
||||
/* check other characters */
|
||||
for ( i = 1; i < bv->bv_len; i++ ) {
|
||||
if ( name[i] == '$' ) {
|
||||
/* if the char is $ we require it to be the last char */
|
||||
if ( name[i + 1] != '\0' ) return 0;
|
||||
} else if ( !( ( name[i] >= 'A' && name[i] <= 'Z' ) ||
|
||||
( name[i] >= 'a' && name[i] <= 'z' ) ||
|
||||
( name[i] >= '0' && name[i] <= '9' ) ||
|
||||
name[i] == '.' || name[i] == '_' ||
|
||||
name[i] == '-' ) )
|
||||
return 0;
|
||||
}
|
||||
/* no test failed so it must be good */
|
||||
return -1;
|
||||
}
|
||||
|
||||
rbac_user_t *
|
||||
rbac_read_user( Operation *op, rbac_req_t *reqp )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
tenant_info_t *tenantp = rbac_tid2tenant( &reqp->tenantid );
|
||||
rbac_user_t *userp = NULL;
|
||||
char fbuf[RBAC_BUFLEN];
|
||||
struct berval filter = { sizeof(fbuf), fbuf };
|
||||
SlapReply rs2 = { REP_RESULT };
|
||||
Operation op2 = *op;
|
||||
slap_callback cb = { 0 };
|
||||
rbac_callback_info_t rbac_cb;
|
||||
|
||||
if ( !tenantp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_user: "
|
||||
"missing tenant information\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* uid is a pre-requisite for reading the user information */
|
||||
if ( BER_BVISNULL( &reqp->uid ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_user: "
|
||||
"missing uid, unable to read user entry\n" );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !isvalidusername( &reqp->uid ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_read_user: "
|
||||
"invalid user id\n" );
|
||||
rc = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rbac_cb.tenantp = tenantp;
|
||||
rbac_cb.private = NULL;
|
||||
|
||||
memset( fbuf, 0, sizeof(fbuf) );
|
||||
strcpy( fbuf, "uid=" );
|
||||
strncat( fbuf, reqp->uid.bv_val, reqp->uid.bv_len );
|
||||
filter.bv_val = fbuf;
|
||||
filter.bv_len = strlen( fbuf );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_create_session: "
|
||||
"invalid DN syntax\n" );
|
||||
goto done;
|
||||
}
|
||||
|
||||
cb.sc_private = &rbac_cb;
|
||||
cb.sc_response = rbac_read_user_cb;
|
||||
op2.o_callback = &cb;
|
||||
op2.o_tag = LDAP_REQ_SEARCH;
|
||||
op2.o_dn = tenantp->admin;
|
||||
op2.o_ndn = tenantp->admin;
|
||||
op2.o_req_dn = tenantp->users_basedn;
|
||||
op2.o_req_ndn = tenantp->users_basedn;
|
||||
op2.ors_filterstr = filter;
|
||||
op2.ors_filter = str2filter_x( &op2, filter.bv_val );
|
||||
op2.ors_scope = LDAP_SCOPE_SUBTREE;
|
||||
op2.ors_attrs = tenantp->schema->user_attrs;
|
||||
op2.ors_tlimit = SLAP_NO_LIMIT;
|
||||
op2.ors_slimit = SLAP_NO_LIMIT;
|
||||
op2.ors_attrsonly = 0;
|
||||
op2.o_bd = frontendDB;
|
||||
op2.ors_limit = NULL;
|
||||
rc = op2.o_bd->be_search( &op2, &rs2 );
|
||||
filter_free_x( &op2, op2.ors_filter, 1 );
|
||||
|
||||
done:;
|
||||
if ( rc == LDAP_SUCCESS && rbac_cb.private ) {
|
||||
userp = (rbac_user_t *)rbac_cb.private;
|
||||
if ( !BER_BVISNULL( &reqp->authtok ) )
|
||||
ber_dupbv( &userp->password, &reqp->authtok );
|
||||
rbac_cb.private = NULL;
|
||||
return userp;
|
||||
} else {
|
||||
userp = (rbac_user_t *)rbac_cb.private;
|
||||
rbac_free_user( userp );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* evaluate temporal constraints for the user */
|
||||
int
|
||||
rbac_user_temporal_constraint( rbac_user_t *userp )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
rbac_constraint_t *cp = NULL;
|
||||
|
||||
if ( BER_BVISNULL( &userp->constraints ) ) {
|
||||
/* no temporal constraint */
|
||||
goto done;
|
||||
}
|
||||
|
||||
cp = rbac_bv2constraint( &userp->constraints );
|
||||
if ( !cp ) {
|
||||
Debug( LDAP_DEBUG_ANY, "rbac_user_temporal_constraint: "
|
||||
"invalid user constraint \n" );
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = rbac_check_time_constraint( cp );
|
||||
|
||||
done:;
|
||||
rbac_free_constraint( cp );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
rbac_constraint_t *
|
||||
rbac_user_role_constraintsx(rbac_user_t *userp)
|
||||
{
|
||||
rbac_constraint_t *tmp, *cp = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (!userp || !userp->role_constraints)
|
||||
goto done;
|
||||
|
||||
while (!BER_BVISNULL(&userp->role_constraints[i])) {
|
||||
tmp = rbac_bv2constraint(&userp->role_constraints[i++]);
|
||||
if (tmp) {
|
||||
if (!cp) {
|
||||
cp = tmp;
|
||||
} else {
|
||||
tmp->next = cp;
|
||||
cp = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
return cp;
|
||||
}
|
||||
*/
|
||||
|
||||
rbac_constraint_t *
|
||||
rbac_user_role_constraints( BerVarray values )
|
||||
{
|
||||
rbac_constraint_t *curr, *head = NULL;
|
||||
int i = 0;
|
||||
|
||||
if ( values ) {
|
||||
while ( !BER_BVISNULL( &values[i] ) ) {
|
||||
curr = rbac_bv2constraint( &values[i++] );
|
||||
if ( curr ) {
|
||||
curr->next = head;
|
||||
head = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
void main() {
|
||||
item * curr, * head;
|
||||
int i;
|
||||
|
||||
head = NULL;
|
||||
|
||||
for(i=1;i<=10;i++) {
|
||||
curr = (item *)malloc(sizeof(item));
|
||||
curr->val = i;
|
||||
curr->next = head;
|
||||
head = curr;
|
||||
}
|
||||
|
||||
curr = head;
|
||||
|
||||
while(curr) {
|
||||
printf("%d\n", curr->val);
|
||||
curr = curr->next ;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
rbac_user_role_constraints2(BerVarray values)
|
||||
{
|
||||
rbac_constraint_t *tmp, *cp = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (!values)
|
||||
goto done;
|
||||
|
||||
while (!BER_BVISNULL(&values[i])) {
|
||||
tmp = rbac_bv2constraint(&values[i++]);
|
||||
if (tmp) {
|
||||
if (!cp) {
|
||||
cp = tmp;
|
||||
} else {
|
||||
tmp->next = cp;
|
||||
cp = tmp;
|
||||
//cp->next = tmp;
|
||||
//cp = tmp->next;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
return cp;
|
||||
}
|
||||
|
||||
|
||||
rbac_user_role_constraints3(rbac_constraint_t *values)
|
||||
{
|
||||
rbac_constraint_t *tmp, *cp = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (!values)
|
||||
goto done;
|
||||
|
||||
while (!BER_BVISNULL(values[i])) {
|
||||
tmp = rbac_bv2constraint(&values[i++]);
|
||||
if (tmp) {
|
||||
if (!cp) {
|
||||
cp = tmp;
|
||||
} else {
|
||||
tmp->next = cp;
|
||||
cp = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
return cp;
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
rbac_free_user( rbac_user_t *userp )
|
||||
{
|
||||
if ( !userp ) return;
|
||||
|
||||
if ( !BER_BVISNULL( &userp->tenantid ) ) {
|
||||
ber_memfree( userp->tenantid.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &userp->uid ) ) {
|
||||
ber_memfree( userp->uid.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &userp->dn ) ) {
|
||||
ber_memfree( userp->dn.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &userp->constraints ) ) {
|
||||
ber_memfree( userp->constraints.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &userp->password ) ) {
|
||||
ber_memfree( userp->password.bv_val );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &userp->msg ) ) {
|
||||
ber_memfree( userp->msg.bv_val );
|
||||
}
|
||||
|
||||
if ( userp->roles ) ber_bvarray_free( userp->roles );
|
||||
|
||||
if ( userp->role_constraints ) ber_bvarray_free( userp->role_constraints );
|
||||
|
||||
ch_free( userp );
|
||||
}
|
||||
157
contrib/slapd-modules/rbac/slapo-rbac.5
Normal file
157
contrib/slapd-modules/rbac/slapo-rbac.5
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
.TH SLAPO_RBAC 5 "RELEASEDATE" "OpenLDAP LDVERSION"
|
||||
.\" Copyright 1999-2021 SYMAS Corporation All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.\" $OpenLDAP$
|
||||
.SH NAME
|
||||
slapo\-rbac \- RBAC0 overlay to slapd
|
||||
.SH SYNOPSIS
|
||||
ETCDIR/slapd.conf
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
The
|
||||
.B slapo-rbac
|
||||
overlay
|
||||
is an implementation of the ANSI INCITS 359 Role-Based Access Control (RBAC) Core.
|
||||
When instantiated, it intercepts, decodes and enforces specific RBAC policies per the Apache Fortress RBAC data formats.
|
||||
.P
|
||||
The overlay provides a set of extended operations.
|
||||
They include session create/delete, checkAccess, addActiveRole, dropActiveRole and sessionRoles.
|
||||
.P
|
||||
|
||||
.SH CONFIGURATION
|
||||
These
|
||||
.B slapd.conf
|
||||
configuration options apply to the slapo-rbac overlay.
|
||||
|
||||
.TP
|
||||
.B overlay rbac
|
||||
This tag gets applied to the RBAC configuration db (see example below).
|
||||
.TP
|
||||
.B rbac-default-users-base-dn "ou=People,dc=example,dc=com"
|
||||
Points to the container that contains the Apache Fortress users.
|
||||
.TP
|
||||
.B rbac-default-roles-base-dn "ou=Roles,ou=RBAC,dc=example,dc=com"
|
||||
Points to the container that contains the Apache Fortress roles.
|
||||
.TP
|
||||
.B rbac-default-permissions-base-dn "ou=Permissions,ou=RBAC,dc=example,dc=com"
|
||||
Points to the container that contains the Apache Fortress perms.
|
||||
.TP
|
||||
.B rbac-default-sessions-base-dn "cn=rbac"
|
||||
Points to the suffix of the RBAC sessions.
|
||||
.TP
|
||||
.B rbac-default-audit-base-dn "cn=audit"
|
||||
Points to the suffix where the audit records are stored.
|
||||
.TP
|
||||
.B rbac-admin "cn=manager,dc=example,dc=com"
|
||||
A service account that has read access to the entire Apache Fortress DIT.
|
||||
.TP
|
||||
.B rbac-pwd "{SSHA}pSOV2TpCxj2NMACijkcMko4fGrFopctU"
|
||||
The password according to the service account.
|
||||
.TP
|
||||
.B rbac-session-admin "cn=manager,cn=rbac"
|
||||
The root dn of the RBAC sessions database.
|
||||
.TP
|
||||
.B rbac-session-admin-pwd {SSHA}pSOV2TpCxj2NMACijkcMko4fGrFopctU
|
||||
The password corresponding with the session database.
|
||||
.TP
|
||||
.RE
|
||||
|
||||
.SH EXAMPLES
|
||||
.LP
|
||||
.RS
|
||||
.nf
|
||||
|
||||
This overlay requires the
|
||||
.B rbac.schema
|
||||
loaded and three additional database config sections, one to store rbac
|
||||
sessions, second to store the audit records and third to hold the overlay's
|
||||
config parameters. They should appear after the existing Apache Fortress db
|
||||
config.
|
||||
|
||||
.TP
|
||||
1. Session Database: Used to store the RBAC sessions corresponding to a logged in user.
|
||||
.B database mdb
|
||||
.B suffix "cn=rbac"
|
||||
.B rootdn "cn=manager,cn=rbac"
|
||||
.B rootpw {SSHA}pSOV2TpCxj2NMACijkcMko4fGrFopctU
|
||||
.B index rbacSessid eq
|
||||
.B directory "/var/openldap/rbacsess"
|
||||
.B overlay dds
|
||||
.B dds-default-ttl 3600
|
||||
.B dds-max-dynamicObjects 100000
|
||||
.B dbnosync
|
||||
.B checkpoint 64 5
|
||||
.PP
|
||||
|
||||
.TP
|
||||
2. Audit Database: Stores records that track user's activities.
|
||||
.B database mdb
|
||||
.B suffix "cn=audit"
|
||||
.B rootdn "cn=manager,cn=audit"
|
||||
.B rootpw {SSHA}pSOV2TpCxj2NMACijkcMko4fGrFopctU
|
||||
.B directory "/var/openldap/rbacaudit"
|
||||
.B dbnosync
|
||||
.B checkpoint 64 5
|
||||
|
||||
.PP
|
||||
|
||||
.TP
|
||||
3. Config Database: Stores the parameters needed for this overlay to work.
|
||||
.B database mdb
|
||||
.B suffix "dc=rbac"
|
||||
.B rootdn "cn=manager,dc=rbac"
|
||||
.B rootpw {SSHA}pSOV2TpCxj2NMACijkcMko4fGrFopctU
|
||||
.B directory "/var/openldap/rbacoverlay"
|
||||
.B overlay rbac
|
||||
.B rbac-default-tenant-id "example"
|
||||
.B rbac-default-users-base-dn "ou=People,dc=example,dc=com"
|
||||
.B rbac-default-roles-base-dn "ou=Roles,ou=RBAC,dc=example,dc=com"
|
||||
.B rbac-default-permissions-base-dn "ou=Permissions,ou=RBAC,dc=example,dc=com"
|
||||
.B rbac-default-sessions-base-dn "cn=rbac"
|
||||
.B rbac-default-audit-base-dn "cn=audit"
|
||||
.B rbac-admin "cn=manager,dc=example,dc=com"
|
||||
.B rbac-pwd "{SSHA}pSOV2TpCxj2NMACijkcMko4fGrFopctU"
|
||||
.B rbac-session-admin "cn=manager,cn=rbac"
|
||||
.B rbac-session-admin-pwd {SSHA}pSOV2TpCxj2NMACijkcMko4fGrFopctU
|
||||
|
||||
.fi
|
||||
.RE
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR ldap (3),
|
||||
.BR slapd.conf (5),
|
||||
.BR slapd\-config (5),
|
||||
.BR slapo\-chain (5).
|
||||
.LP
|
||||
"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
|
||||
.LP
|
||||
|
||||
.BR ldap (3),
|
||||
.BR slapd.conf (5),
|
||||
.BR slapd\-config (5),
|
||||
.BR slapo\-chain (5).
|
||||
.LP
|
||||
"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
|
||||
.LP
|
||||
|
||||
.UR https://profsandhu.com/journals/tissec/ANSI+INCITS+359-2004.pdf
|
||||
.UE ANSI INCITS 359 Role-Based Access Control specification
|
||||
|
||||
.UR https://github.com/apache/directory-fortress-core/blob/master/README.md
|
||||
.UE Apache Fortress README
|
||||
|
||||
.UR https://github.com/apache/directory-fortress-core/blob/master/README-QUICKSTART-SLAPD.md
|
||||
.UE Apache Fortress OpenLDAP Quickstart
|
||||
|
||||
.UR https://github.com/apache/directory-fortress-core/blob/master/ldap/schema/fortress.schema
|
||||
.UE Apache Fortress RBAC schema
|
||||
|
||||
.SH BUGS
|
||||
This overlay is experimental.
|
||||
|
||||
.SH ACKNOWLEDGEMENTS
|
||||
.P
|
||||
This module was written in 2013 by Ted Cheng of Symas Corporation
|
||||
with a little help from Matt Hardin, Howard Chu, Shawn McKinney.
|
||||
.P
|
||||
.so ../Project
|
||||
531
contrib/slapd-modules/rbac/util.c
Normal file
531
contrib/slapd-modules/rbac/util.c
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
/* util.c - RBAC utility */
|
||||
/* $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/ctype.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "slap-config.h"
|
||||
#include "lutil.h"
|
||||
|
||||
#include "rbac.h"
|
||||
|
||||
#define DELIMITER '$'
|
||||
|
||||
#define SUNDAY 0x01
|
||||
#define MONDAY 0x02
|
||||
#define TUESDAY 0x04
|
||||
#define WEDNESDAY 0x08
|
||||
#define THURSDAY 0x10
|
||||
#define FRIDAY 0x20
|
||||
#define SATURDAY 0x40
|
||||
|
||||
#define ALL_WEEK "all"
|
||||
|
||||
void
|
||||
rbac_free_constraint( rbac_constraint_t *cp )
|
||||
{
|
||||
if ( !cp ) return;
|
||||
|
||||
if ( !BER_BVISNULL( &cp->name ) ) {
|
||||
ch_free( cp->name.bv_val );
|
||||
}
|
||||
|
||||
ch_free( cp );
|
||||
}
|
||||
|
||||
void
|
||||
rbac_free_constraints( rbac_constraint_t *constraints )
|
||||
{
|
||||
rbac_constraint_t *cp, *tmp;
|
||||
|
||||
if ( !constraints ) return;
|
||||
|
||||
tmp = constraints;
|
||||
while ( tmp ) {
|
||||
cp = tmp->next;
|
||||
rbac_free_constraint( tmp );
|
||||
tmp = cp;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rbac_constraint_t *
|
||||
rbac_alloc_constraint()
|
||||
{
|
||||
rbac_constraint_t *cp = NULL;
|
||||
|
||||
cp = ch_calloc( 1, sizeof(rbac_constraint_t) );
|
||||
return cp;
|
||||
}
|
||||
|
||||
static int
|
||||
is_well_formed_constraint( struct berval *bv )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
/* assume well-formed role/user-constraints, for the moment */
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "is_well_formed_constraint: "
|
||||
"rbac role/user constraint not well-formed: %s\n",
|
||||
bv->bv_val );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* input contains 4 digits, representing time */
|
||||
/* in hhmm format */
|
||||
static int
|
||||
constraint_parse_time( char *input )
|
||||
{
|
||||
int btime;
|
||||
char *ptr = input;
|
||||
|
||||
btime = ( *ptr++ - '0' ) * 12;
|
||||
btime += ( *ptr++ - '0' );
|
||||
btime *= 60; /* turning into mins */
|
||||
btime += ( *ptr++ - '0' ) * 10;
|
||||
btime += ( *ptr++ - '0' );
|
||||
btime *= 60; /* turning into secs */
|
||||
|
||||
return btime;
|
||||
}
|
||||
|
||||
/* input contains 4 digits, representing year */
|
||||
/* in yyyy format */
|
||||
static int
|
||||
constraint_parse_year( char *input )
|
||||
{
|
||||
int i;
|
||||
int year = 0;
|
||||
char *ptr = input;
|
||||
|
||||
for ( i = 0; i <= 3; i++, ptr++ ) {
|
||||
year = year * 10 + *ptr - '0';
|
||||
}
|
||||
|
||||
return year;
|
||||
}
|
||||
|
||||
/* input contains 2 digits, representing month */
|
||||
/* in mm format */
|
||||
static int
|
||||
constraint_parse_month( char *input )
|
||||
{
|
||||
int i;
|
||||
int month = 0;
|
||||
char *ptr = input;
|
||||
|
||||
for ( i = 0; i < 2; i++, ptr++ ) {
|
||||
month = month * 10 + *ptr - '0';
|
||||
}
|
||||
|
||||
return month;
|
||||
}
|
||||
|
||||
/* input contains 2 digits, representing day in month */
|
||||
/* in dd format */
|
||||
static int
|
||||
constraint_parse_day_in_month( char *input )
|
||||
{
|
||||
int i;
|
||||
int day_in_month = 0;
|
||||
char *ptr = input;
|
||||
|
||||
for ( i = 0; i < 2; i++, ptr++ ) {
|
||||
day_in_month = day_in_month * 10 + *ptr - '0';
|
||||
}
|
||||
|
||||
return day_in_month;
|
||||
}
|
||||
|
||||
rbac_constraint_t *
|
||||
rbac_bv2constraint( struct berval *bv )
|
||||
{
|
||||
rbac_constraint_t *cp = NULL;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char *ptr, *endp = NULL;
|
||||
int len = 0;
|
||||
int year, month, mday;
|
||||
|
||||
if ( !bv || BER_BVISNULL( bv ) ) goto done;
|
||||
|
||||
rc = is_well_formed_constraint( bv );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
cp = rbac_alloc_constraint();
|
||||
if ( !cp ) {
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* constraint name */
|
||||
ptr = bv->bv_val;
|
||||
endp = ptr;
|
||||
while ( *endp != DELIMITER ) {
|
||||
endp++;
|
||||
len++;
|
||||
}
|
||||
|
||||
if ( len > 0 ) {
|
||||
cp->name.bv_val = ch_malloc( len + 1 );
|
||||
strncpy( cp->name.bv_val, ptr, len );
|
||||
cp->name.bv_val[len] = '\0';
|
||||
cp->name.bv_len = len;
|
||||
} else {
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* allowed inactivity period */
|
||||
ptr = endp;
|
||||
endp++;
|
||||
if ( isdigit( *endp ) ) {
|
||||
int secs = 0;
|
||||
while ( isdigit( *endp ) ) {
|
||||
secs = secs * 10 + *endp - '0';
|
||||
endp++;
|
||||
}
|
||||
cp->allowed_inactivity = secs;
|
||||
} else if ( *endp != DELIMITER ) {
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ptr = endp;
|
||||
endp = ptr + 1;
|
||||
|
||||
/* begin time */
|
||||
if ( isdigit( *endp ) ) {
|
||||
cp->begin_time = constraint_parse_time( endp );
|
||||
while ( isdigit( *endp ) )
|
||||
endp++;
|
||||
}
|
||||
|
||||
ptr = endp;
|
||||
while ( *ptr != DELIMITER )
|
||||
ptr++;
|
||||
endp = ptr + 1;
|
||||
|
||||
/* end time */
|
||||
if ( isdigit( *endp ) ) {
|
||||
cp->end_time = constraint_parse_time( endp );
|
||||
while ( isdigit( *endp ) )
|
||||
endp++;
|
||||
}
|
||||
|
||||
ptr = endp;
|
||||
while ( *ptr != DELIMITER )
|
||||
ptr++;
|
||||
endp = ptr + 1;
|
||||
|
||||
/* begin year/month/day_in_month */
|
||||
if ( isdigit( *endp ) ) {
|
||||
lutil_tm tm;
|
||||
year = constraint_parse_year( endp );
|
||||
endp += 4;
|
||||
month = constraint_parse_month( endp );
|
||||
endp += 2;
|
||||
mday = constraint_parse_day_in_month( endp );
|
||||
endp += 2;
|
||||
|
||||
tm.tm_year = year - 1900;
|
||||
tm.tm_mon = month - 1;
|
||||
tm.tm_mday = mday;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_hour = 0;
|
||||
|
||||
lutil_tm2time( &tm, &cp->begin_date );
|
||||
}
|
||||
|
||||
ptr = endp;
|
||||
while ( *ptr != DELIMITER )
|
||||
ptr++;
|
||||
endp = ptr + 1;
|
||||
|
||||
/* end year/month/day_in_month */
|
||||
if ( isdigit( *endp ) ) {
|
||||
lutil_tm tm;
|
||||
year = constraint_parse_year( endp );
|
||||
endp += 4;
|
||||
month = constraint_parse_month( endp );
|
||||
endp += 2;
|
||||
mday = constraint_parse_day_in_month( endp );
|
||||
endp += 2;
|
||||
|
||||
tm.tm_year = year - 1900;
|
||||
tm.tm_mon = month - 1;
|
||||
tm.tm_mday = mday;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_hour = 0;
|
||||
|
||||
lutil_tm2time( &tm, &cp->end_date );
|
||||
}
|
||||
|
||||
ptr = endp;
|
||||
while ( *ptr != DELIMITER )
|
||||
ptr++;
|
||||
endp = ptr + 1;
|
||||
|
||||
/* begin lock year/month/day_in_month */
|
||||
if ( isdigit( *endp ) ) {
|
||||
lutil_tm tm;
|
||||
year = constraint_parse_year( endp );
|
||||
endp += 4;
|
||||
month = constraint_parse_month( endp );
|
||||
endp += 2;
|
||||
mday = constraint_parse_day_in_month( endp );
|
||||
endp += 2;
|
||||
|
||||
tm.tm_year = year - 1900;
|
||||
tm.tm_mon = month - 1;
|
||||
tm.tm_mday = mday;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_hour = 0;
|
||||
|
||||
lutil_tm2time( &tm, &cp->begin_lock_date );
|
||||
}
|
||||
|
||||
ptr = endp;
|
||||
while ( *ptr != DELIMITER )
|
||||
ptr++;
|
||||
endp = ptr + 1;
|
||||
|
||||
/* end lock year/month/day_in_month */
|
||||
if ( isdigit( *endp ) ) {
|
||||
lutil_tm tm;
|
||||
|
||||
year = constraint_parse_year( endp );
|
||||
endp += 4;
|
||||
month = constraint_parse_month( endp );
|
||||
endp += 2;
|
||||
mday = constraint_parse_day_in_month( endp );
|
||||
endp += 2;
|
||||
|
||||
tm.tm_year = year - 1900;
|
||||
tm.tm_mon = month - 1;
|
||||
tm.tm_mday = mday;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_hour = 0;
|
||||
|
||||
lutil_tm2time( &tm, &cp->end_lock_date );
|
||||
}
|
||||
|
||||
ptr = endp;
|
||||
while ( *ptr != DELIMITER )
|
||||
ptr++;
|
||||
endp = ptr + 1;
|
||||
|
||||
/* dayMask */
|
||||
|
||||
/* allow "all" to mean the entire week */
|
||||
if ( strncasecmp( endp, ALL_WEEK, strlen( ALL_WEEK ) ) == 0 ) {
|
||||
cp->day_mask = SUNDAY | MONDAY | TUESDAY | WEDNESDAY | THURSDAY |
|
||||
FRIDAY | SATURDAY;
|
||||
}
|
||||
|
||||
while ( *endp && isdigit( *endp ) ) {
|
||||
switch ( *endp - '0' ) {
|
||||
case 1:
|
||||
cp->day_mask |= SUNDAY;
|
||||
break;
|
||||
case 2:
|
||||
cp->day_mask |= MONDAY;
|
||||
break;
|
||||
case 3:
|
||||
cp->day_mask |= TUESDAY;
|
||||
break;
|
||||
case 4:
|
||||
cp->day_mask |= WEDNESDAY;
|
||||
break;
|
||||
case 5:
|
||||
cp->day_mask |= THURSDAY;
|
||||
break;
|
||||
case 6:
|
||||
cp->day_mask |= FRIDAY;
|
||||
break;
|
||||
case 7:
|
||||
cp->day_mask |= SATURDAY;
|
||||
break;
|
||||
default:
|
||||
/* should not be here */
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
}
|
||||
endp++;
|
||||
}
|
||||
|
||||
done:;
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
rbac_free_constraint( cp );
|
||||
cp = NULL;
|
||||
}
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
static int
|
||||
constraint_day_of_week( rbac_constraint_t *cp, int wday )
|
||||
{
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
|
||||
/* assumption: Monday is 1st day of a week */
|
||||
switch ( wday ) {
|
||||
case 1:
|
||||
if ( !(cp->day_mask & MONDAY) ) goto done;
|
||||
break;
|
||||
case 2:
|
||||
if ( !(cp->day_mask & TUESDAY) ) goto done;
|
||||
break;
|
||||
case 3:
|
||||
if ( !(cp->day_mask & WEDNESDAY) ) goto done;
|
||||
break;
|
||||
case 4:
|
||||
if ( !(cp->day_mask & THURSDAY) ) goto done;
|
||||
break;
|
||||
case 5:
|
||||
if ( !(cp->day_mask & FRIDAY) ) goto done;
|
||||
break;
|
||||
case 6:
|
||||
if ( !(cp->day_mask & SATURDAY) ) goto done;
|
||||
break;
|
||||
case 0:
|
||||
case 7:
|
||||
if ( !(cp->day_mask & SUNDAY) ) goto done;
|
||||
break;
|
||||
default:
|
||||
/* should not be here */
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
rbac_check_time_constraint( rbac_constraint_t *cp )
|
||||
{
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
time_t now;
|
||||
struct tm result, *resultp;
|
||||
|
||||
now = slap_get_time();
|
||||
|
||||
/*
|
||||
* does slapd support day-of-week (wday)?
|
||||
* using native routine for now.
|
||||
* Win32's gmtime call is already thread-safe, to the _r
|
||||
* decorator is unneeded.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
resultp = gmtime( &now );
|
||||
#else
|
||||
resultp = gmtime_r( &now, &result );
|
||||
#endif
|
||||
if ( !resultp ) goto done;
|
||||
#if 0
|
||||
timestamp.bv_val = timebuf;
|
||||
timestamp.bv_len = sizeof(timebuf);
|
||||
slap_timestamp(&now, ×tamp);
|
||||
lutil_parsetime(timestamp.bv_val, &now_tm);
|
||||
lutil_tm2time(&now_tm, &now_tt);
|
||||
#endif
|
||||
|
||||
if ( ( cp->begin_date.tt_sec > 0 && cp->begin_date.tt_sec > now ) ||
|
||||
( cp->end_date.tt_sec > 0 && cp->end_date.tt_sec < now ) ) {
|
||||
/* not within allowed time period */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* allowed time period during a day */
|
||||
if ( cp->begin_time > 0 && cp->end_time > 0 ) {
|
||||
int timeofday = ( resultp->tm_hour * 60 + resultp->tm_min ) * 60 +
|
||||
resultp->tm_sec;
|
||||
if ( timeofday < cp->begin_time || timeofday > cp->end_time ) {
|
||||
/* not withing allowed time period in a day */
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* allowed day in a week */
|
||||
if ( cp->day_mask > 0 ) {
|
||||
rc = constraint_day_of_week( cp, resultp->tm_wday );
|
||||
if ( rc != LDAP_SUCCESS ) goto done;
|
||||
}
|
||||
|
||||
/* during lock-out period? */
|
||||
if ( ( cp->begin_lock_date.tt_sec > 0 &&
|
||||
cp->begin_lock_date.tt_sec < now ) &&
|
||||
( cp->end_lock_date.tt_sec > 0 &&
|
||||
cp->end_lock_date.tt_sec > now ) ) {
|
||||
/* within locked out period */
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* passed all tests */
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
done:;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rbac_constraint_t *
|
||||
rbac_role2constraint( struct berval *role, rbac_constraint_t *role_constraints )
|
||||
{
|
||||
rbac_constraint_t *cp = NULL;
|
||||
|
||||
if ( !role_constraints || !role ) goto done;
|
||||
|
||||
cp = role_constraints;
|
||||
while ( cp ) {
|
||||
if ( ber_bvstrcasecmp( role, &cp->name ) == 0 ) {
|
||||
/* found the role constraint */
|
||||
goto done;
|
||||
}
|
||||
cp = cp->next;
|
||||
}
|
||||
|
||||
done:;
|
||||
return cp;
|
||||
}
|
||||
|
||||
void
|
||||
rbac_to_lower( struct berval *bv )
|
||||
{
|
||||
// convert the berval to lower case:
|
||||
int i;
|
||||
for ( i = 0; i < bv->bv_len; i++ ) {
|
||||
bv->bv_val[i] = tolower( bv->bv_val[i] );
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue