1/*	$NetBSD: init.c,v 1.2 2021/08/14 16:14:53 christos Exp $	*/
2
3/* init.c - RBAC initialization */
4/* $OpenLDAP$ */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18/* ACKNOWLEDGEMENTS:
19 */
20
21#include <sys/cdefs.h>
22__RCSID("$NetBSD: init.c,v 1.2 2021/08/14 16:14:53 christos Exp $");
23
24#include "portable.h"
25
26#include <stdio.h>
27
28#include <ac/string.h>
29
30#include "slap.h"
31#include "slap-config.h"
32#include "lutil.h"
33
34#include "rbac.h"
35
36static slap_callback nullsc = { NULL, NULL, NULL, NULL };
37
38struct slap_rbac_internal_schema slap_rbac_schema;
39
40extern rbac_tenant_t rbac_tenants;
41extern int initialize_jts( void );
42
43rbac_ad_t rbac_session_ads[] = {
44	{ RBAC_SESSION_ID,
45		BER_BVC("rbacSessid"), &slap_rbac_schema.ad_session_id },
46	{ RBAC_USER_DN,
47		BER_BVC("rbacUserDN"), &slap_rbac_schema.ad_session_user_dn },
48	{ RBAC_ROLES,
49		BER_BVC("rbacRoles"), &slap_rbac_schema.ad_session_roles },
50	{ RBAC_ROLE_CONSTRAINTS,
51		BER_BVC("rbacRoleConstraints"),
52		&slap_rbac_schema.ad_session_role_constraints },
53	{ RBAC_UID,
54		BER_BVC("uid"), &slap_rbac_schema.ad_uid},
55	{ RBAC_TENANT_ID,
56		BER_BVC("tenantid"), &slap_rbac_schema.ad_tenant_id },
57
58	{ RBAC_NONE, BER_BVNULL, NULL }
59};
60
61rbac_ad_t rbac_session_permission_ads[] = {
62	{ RBAC_OP_NAME,
63		BER_BVC("rbacOpName"), &slap_rbac_schema.ad_permission_opname },
64	{ RBAC_OBJ_NAME,
65		BER_BVC("rbacObjName"), &slap_rbac_schema.ad_permission_objname },
66	{ RBAC_ROLE_NAME,
67		BER_BVC("rbacRoleName"), &slap_rbac_schema.ad_permission_rolename },
68
69	{ RBAC_NONE, BER_BVNULL, NULL }
70};
71
72rbac_ad_t audit_ads[] = {
73	{ RBAC_AUDIT_OP,
74		BER_BVC("rbacAuditOp"), &slap_rbac_schema.ad_audit_op },
75	{ RBAC_AUDIT_ID,
76		BER_BVC("rbacAuditId"), &slap_rbac_schema.ad_audit_id },
77	{ RBAC_AUDIT_ROLES,
78		BER_BVC("rbacAuditRoles"), &slap_rbac_schema.ad_audit_roles },
79	{ RBAC_AUDIT_REQUESTED_ROLES,
80		BER_BVC("rbacAuditRequestedRoles"),
81		&slap_rbac_schema.ad_audit_requested_roles
82	},
83	{ RBAC_AUDIT_TIMESTAMP,
84		BER_BVC("rbacAuditTimestamp"), &slap_rbac_schema.ad_audit_timestamp },
85	{ RBAC_AUDIT_RESOURCES,
86		BER_BVC("rbacAuditResources"), &slap_rbac_schema.ad_audit_resources },
87	{ RBAC_AUDIT_OBJS,
88		BER_BVC("rbacAuditObjects"), &slap_rbac_schema.ad_audit_objects },
89	{ RBAC_AUDIT_OPS,
90		BER_BVC("rbacAuditOperations"), &slap_rbac_schema.ad_audit_operations },
91	{ RBAC_AUDIT_RESULT,
92		BER_BVC("rbacAuditResult"), &slap_rbac_schema.ad_audit_result },
93	{ RBAC_AUDIT_PROPERTIES,
94		BER_BVC("rbacAuditProperties"), &slap_rbac_schema.ad_audit_properties },
95	{ RBAC_AUDIT_MSGS,
96		BER_BVC("rbacAuditMessages"), &slap_rbac_schema.ad_audit_messages },
97
98	{ RBAC_NONE, BER_BVNULL, NULL }
99};
100
101/* initialize repository attribute descriptions */
102
103static int
104initialize_sessions()
105{
106	int i, nattrs, rc = LDAP_SUCCESS;
107	const char *text;
108
109	for ( nattrs = 0; !BER_BVISNULL( &rbac_session_ads[nattrs].attr );
110			nattrs++ )
111		; /* count the number of attrs */
112
113	slap_rbac_schema.session_attrs =
114			slap_sl_calloc( sizeof(AttributeName), nattrs + 1, NULL );
115
116	for ( i = 0; !BER_BVISNULL( &rbac_session_ads[i].attr ); i++ ) {
117		rc = slap_bv2ad(
118				&rbac_session_ads[i].attr, rbac_session_ads[i].ad, &text );
119		if ( rc != LDAP_SUCCESS ) {
120			goto done;
121		}
122		slap_rbac_schema.session_attrs[i].an_name = rbac_session_ads[i].attr;
123		slap_rbac_schema.session_attrs[i].an_desc = *rbac_session_ads[i].ad;
124	}
125
126	BER_BVZERO( &slap_rbac_schema.session_attrs[nattrs].an_name );
127
128done:;
129	return rc;
130}
131
132static int
133initialize_audit()
134{
135	int i, rc = LDAP_SUCCESS;
136	const char *text;
137
138	/* for audit */
139	for ( i = 0; !BER_BVISNULL( &audit_ads[i].attr ); i++ ) {
140		rc = slap_bv2ad( &audit_ads[i].attr, audit_ads[i].ad, &text );
141		if ( rc != LDAP_SUCCESS ) {
142			goto done;
143		}
144	}
145
146done:;
147	return rc;
148}
149
150static int
151initialize_tenant(
152		BackendDB *be,
153		ConfigReply *cr,
154		tenant_info_t *tenantp,
155		int init_op )
156{
157	int rc = LDAP_SUCCESS;
158	Entry *e = NULL;
159	OperationBuffer opbuf;
160	Operation *op2;
161	SlapReply rs2 = { REP_RESULT };
162	Connection conn = { 0 };
163	struct berval rbac_container_oc = BER_BVC("rbacContainer");
164	struct berval rbac_audit_container = BER_BVC("audit");
165	struct berval rbac_session_container = BER_BVC("rbac");
166	void *thrctx = ldap_pvt_thread_pool_context();
167
168	e = entry_alloc();
169
170	switch ( init_op ) {
171		case INIT_AUDIT_CONTAINER:
172			ber_dupbv( &e->e_name, &tenantp->audit_basedn );
173			ber_dupbv( &e->e_nname, &tenantp->audit_basedn );
174
175			/* container cn */
176			attr_merge_one(
177					e, slap_schema.si_ad_cn, &rbac_audit_container, NULL );
178			break;
179		case INIT_SESSION_CONTAINER:
180			ber_dupbv( &e->e_name, &tenantp->sessions_basedn );
181			ber_dupbv( &e->e_nname, &tenantp->sessions_basedn );
182
183			/* rendered dynmaicObject for session */
184			attr_merge_one( e, slap_schema.si_ad_objectClass,
185					&slap_schema.si_oc_dynamicObject->soc_cname, NULL );
186
187			/* container cn */
188			attr_merge_one(
189					e, slap_schema.si_ad_cn, &rbac_session_container, NULL );
190			break;
191		default:
192			break;
193	}
194
195	attr_merge_one(
196			e, slap_schema.si_ad_objectClass, &rbac_container_oc, NULL );
197	attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
198			&rbac_container_oc, NULL );
199
200	/* store RBAC session */
201	connection_fake_init2( &conn, &opbuf, thrctx, 0 );
202	op2 = &opbuf.ob_op;
203	op2->o_callback = &nullsc;
204	op2->o_tag = LDAP_REQ_ADD;
205	op2->o_protocol = LDAP_VERSION3;
206	op2->o_req_dn = e->e_name;
207	op2->o_req_ndn = e->e_nname;
208	op2->ora_e = e;
209	op2->o_bd = select_backend( &op2->o_req_ndn, 0 );
210	op2->o_dn = op2->o_bd->be_rootdn;
211	op2->o_ndn = op2->o_bd->be_rootndn;
212	rc = op2->o_bd->be_add( op2, &rs2 );
213
214	if ( e ) entry_free( e );
215
216	return rc;
217}
218
219int
220rbac_initialize_tenants( BackendDB *be, ConfigReply *cr )
221{
222	int rc = LDAP_SUCCESS;
223	rbac_tenant_t *tenantp = NULL;
224
225	for ( tenantp = &rbac_tenants; tenantp; tenantp = tenantp->next ) {
226		rc = initialize_tenant(
227				be, cr, &tenantp->tenant_info, INIT_AUDIT_CONTAINER );
228		if ( rc != LDAP_SUCCESS ) {
229			if ( rc == LDAP_ALREADY_EXISTS ) {
230				Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
231						"audit container exists, tenant (%s)\n",
232						tenantp->tenant_info.tid.bv_val ?
233								tenantp->tenant_info.tid.bv_val :
234								"NULL" );
235				rc = LDAP_SUCCESS;
236			} else {
237				Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
238						"failed to initialize (%s): rc (%d)\n",
239						tenantp->tenant_info.tid.bv_val ?
240								tenantp->tenant_info.tid.bv_val :
241								"NULL",
242						rc );
243				goto done;
244			}
245		} else {
246			Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
247					"created audit container for tenant (%s):\n",
248					tenantp->tenant_info.tid.bv_val ?
249							tenantp->tenant_info.tid.bv_val :
250							"NULL" );
251		}
252		rc = initialize_tenant(
253				be, cr, &tenantp->tenant_info, INIT_SESSION_CONTAINER );
254		if ( rc != LDAP_SUCCESS ) {
255			if ( rc == LDAP_ALREADY_EXISTS ) {
256				Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
257						"session container exists, tenant (%s)\n",
258						tenantp->tenant_info.tid.bv_val ?
259								tenantp->tenant_info.tid.bv_val :
260								"NULL" );
261				rc = LDAP_SUCCESS;
262			} else {
263				Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
264						"failed to initialize (%s): rc (%d)\n",
265						tenantp->tenant_info.tid.bv_val ?
266								tenantp->tenant_info.tid.bv_val :
267								"NULL",
268						rc );
269				goto done;
270			}
271		} else {
272			Debug( LDAP_DEBUG_ANY, "rbac_initialize: "
273					"created session container for tenant (%s):\n",
274					tenantp->tenant_info.tid.bv_val ?
275							tenantp->tenant_info.tid.bv_val :
276							"NULL" );
277		}
278	}
279
280done:;
281
282	return rc;
283}
284
285static int
286initialize_rbac_session_permissions()
287{
288	int i, rc = LDAP_SUCCESS;
289	const char *text;
290
291	for ( i = 0; !BER_BVISNULL( &rbac_session_permission_ads[i].attr ); i++ ) {
292		rc = slap_bv2ad( &rbac_session_permission_ads[i].attr,
293				rbac_session_permission_ads[i].ad, &text );
294		if ( rc != LDAP_SUCCESS ) {
295			goto done;
296		}
297	}
298
299done:;
300	return rc;
301}
302
303int
304rbac_initialize_repository()
305{
306	int rc = LDAP_SUCCESS;
307
308	rc = initialize_jts();
309	if ( rc != LDAP_SUCCESS ) {
310		return rc;
311	}
312
313	rc = initialize_rbac_session_permissions();
314	if ( rc != LDAP_SUCCESS ) {
315		return rc;
316	}
317
318	rc = initialize_sessions();
319	if ( rc != LDAP_SUCCESS ) {
320		return rc;
321	}
322
323	rc = initialize_audit();
324	if ( rc != LDAP_SUCCESS ) {
325		return rc;
326	}
327
328	return rc;
329}
330