xref: /netbsd-src/external/bsd/openldap/dist/libraries/librewrite/session.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*	$NetBSD: session.c,v 1.6 2020/08/11 13:15:39 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2000-2020 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENT:
18  * This work was initially developed by Pierangelo Masarati for
19  * inclusion in OpenLDAP Software.
20  */
21 
22 #include <portable.h>
23 
24 #include "rewrite-int.h"
25 
26 /*
27  * Compares two cookies
28  */
29 static int
30 rewrite_cookie_cmp(
31                 const void *c1,
32                 const void *c2
33 )
34 {
35 	const struct rewrite_session *s1, *s2;
36 
37 	s1 = ( const struct rewrite_session * )c1;
38 	s2 = ( const struct rewrite_session * )c2;
39 
40 	assert( s1 != NULL );
41 	assert( s2 != NULL );
42 	assert( s1->ls_cookie != NULL );
43 	assert( s2->ls_cookie != NULL );
44 
45         return ( ( s1->ls_cookie < s2->ls_cookie ) ? -1 :
46 			( ( s1->ls_cookie > s2->ls_cookie ) ? 1 : 0 ) );
47 }
48 
49 /*
50  * Duplicate cookies?
51  */
52 static int
53 rewrite_cookie_dup(
54                 void *c1,
55                 void *c2
56 )
57 {
58 	struct rewrite_session *s1, *s2;
59 
60 	s1 = ( struct rewrite_session * )c1;
61 	s2 = ( struct rewrite_session * )c2;
62 
63 	assert( s1 != NULL );
64 	assert( s2 != NULL );
65 	assert( s1->ls_cookie != NULL );
66 	assert( s2->ls_cookie != NULL );
67 
68 	assert( s1->ls_cookie != s2->ls_cookie );
69 
70         return ( ( s1->ls_cookie == s2->ls_cookie ) ? -1 : 0 );
71 }
72 
73 /*
74  * Inits a session
75  */
76 struct rewrite_session *
77 rewrite_session_init(
78 		struct rewrite_info *info,
79 		const void *cookie
80 )
81 {
82 	struct rewrite_session 	*session, tmp;
83 	int			rc;
84 
85 	assert( info != NULL );
86 	assert( cookie != NULL );
87 
88 #ifdef USE_REWRITE_LDAP_PVT_THREADS
89 	ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
90 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
91 
92 	tmp.ls_cookie = ( void * )cookie;
93 	session = ( struct rewrite_session * )avl_find( info->li_cookies,
94 			( caddr_t )&tmp, rewrite_cookie_cmp );
95 	if ( session ) {
96 		session->ls_count++;
97 #ifdef USE_REWRITE_LDAP_PVT_THREADS
98 		ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
99 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
100 		return session;
101 	}
102 
103 	session = calloc( sizeof( struct rewrite_session ), 1 );
104 	if ( session == NULL ) {
105 #ifdef USE_REWRITE_LDAP_PVT_THREADS
106 		ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
107 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
108 		return NULL;
109 	}
110 	session->ls_cookie = ( void * )cookie;
111 	session->ls_count = 1;
112 
113 #ifdef USE_REWRITE_LDAP_PVT_THREADS
114 	if ( ldap_pvt_thread_mutex_init( &session->ls_mutex ) ) {
115 		free( session );
116 		ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
117 		return NULL;
118 	}
119 	if ( ldap_pvt_thread_rdwr_init( &session->ls_vars_mutex ) ) {
120 		ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
121 		free( session );
122 		ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
123 		return NULL;
124 	}
125 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
126 
127 	rc = avl_insert( &info->li_cookies, ( caddr_t )session,
128 			rewrite_cookie_cmp, rewrite_cookie_dup );
129 	info->li_num_cookies++;
130 
131 #ifdef USE_REWRITE_LDAP_PVT_THREADS
132 	ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
133 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
134 
135 	if ( rc != 0 ) {
136 #ifdef USE_REWRITE_LDAP_PVT_THREADS
137 		ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex );
138 		ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
139 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
140 
141 		free( session );
142 		return NULL;
143 	}
144 
145 	return session;
146 }
147 
148 /*
149  * Fetches a session
150  */
151 struct rewrite_session *
152 rewrite_session_find(
153 		struct rewrite_info *info,
154 		const void *cookie
155 )
156 {
157 	struct rewrite_session *session, tmp;
158 
159 	assert( info != NULL );
160 	assert( cookie != NULL );
161 
162 	tmp.ls_cookie = ( void * )cookie;
163 #ifdef USE_REWRITE_LDAP_PVT_THREADS
164 	ldap_pvt_thread_rdwr_rlock( &info->li_cookies_mutex );
165 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
166 	session = ( struct rewrite_session * )avl_find( info->li_cookies,
167 			( caddr_t )&tmp, rewrite_cookie_cmp );
168 #ifdef USE_REWRITE_LDAP_PVT_THREADS
169 	if ( session ) {
170 		ldap_pvt_thread_mutex_lock( &session->ls_mutex );
171 		session->ls_count++;
172 	}
173 	ldap_pvt_thread_rdwr_runlock( &info->li_cookies_mutex );
174 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
175 
176 	return session;
177 }
178 
179 /*
180  * Returns a session
181  */
182 void
183 rewrite_session_return(
184 		struct rewrite_info *info,
185 		struct rewrite_session *session
186 )
187 {
188 	assert( session != NULL );
189 	session->ls_count--;
190 	ldap_pvt_thread_mutex_unlock( &session->ls_mutex );
191 }
192 
193 /*
194  * Defines and inits a var with session scope
195  */
196 int
197 rewrite_session_var_set_f(
198 		struct rewrite_info *info,
199 		const void *cookie,
200 		const char *name,
201 		const char *value,
202 		int flags
203 )
204 {
205 	struct rewrite_session *session;
206 	struct rewrite_var *var;
207 
208 	assert( info != NULL );
209 	assert( cookie != NULL );
210 	assert( name != NULL );
211 	assert( value != NULL );
212 
213 	session = rewrite_session_find( info, cookie );
214 	if ( session == NULL ) {
215 		session = rewrite_session_init( info, cookie );
216 		if ( session == NULL ) {
217 			return REWRITE_ERR;
218 		}
219 
220 #ifdef USE_REWRITE_LDAP_PVT_THREADS
221 		ldap_pvt_thread_mutex_lock( &session->ls_mutex );
222 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
223 	}
224 
225 #ifdef USE_REWRITE_LDAP_PVT_THREADS
226 	ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex );
227 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
228 
229 	var = rewrite_var_find( session->ls_vars, name );
230 	if ( var != NULL ) {
231 		assert( var->lv_value.bv_val != NULL );
232 
233 		(void)rewrite_var_replace( var, value, flags );
234 
235 	} else {
236 		var = rewrite_var_insert_f( &session->ls_vars, name, value, flags );
237 		if ( var == NULL ) {
238 #ifdef USE_REWRITE_LDAP_PVT_THREADS
239 			ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
240 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
241 			rewrite_session_return( info, session );
242 			return REWRITE_ERR;
243 		}
244 	}
245 
246 #ifdef USE_REWRITE_LDAP_PVT_THREADS
247 	ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
248 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
249 
250 	rewrite_session_return( info, session );
251 
252 	return REWRITE_SUCCESS;
253 }
254 
255 /*
256  * Gets a var with session scope
257  */
258 int
259 rewrite_session_var_get(
260 		struct rewrite_info *info,
261 		const void *cookie,
262 		const char *name,
263 		struct berval *value
264 )
265 {
266 	struct rewrite_session *session;
267 	struct rewrite_var *var;
268 	int rc = REWRITE_SUCCESS;
269 
270 	assert( info != NULL );
271 	assert( cookie != NULL );
272 	assert( name != NULL );
273 	assert( value != NULL );
274 
275 	value->bv_val = NULL;
276 	value->bv_len = 0;
277 
278 	if ( cookie == NULL ) {
279 		return REWRITE_ERR;
280 	}
281 
282 	session = rewrite_session_find( info, cookie );
283 	if ( session == NULL ) {
284 		return REWRITE_ERR;
285 	}
286 
287 #ifdef USE_REWRITE_LDAP_PVT_THREADS
288 	ldap_pvt_thread_rdwr_rlock( &session->ls_vars_mutex );
289 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
290 
291 	var = rewrite_var_find( session->ls_vars, name );
292 	if ( var != NULL ) {
293 		value->bv_val = strdup( var->lv_value.bv_val );
294 		value->bv_len = var->lv_value.bv_len;
295 	}
296 
297 	if ( var == NULL || value->bv_val == NULL ) {
298 		rc = REWRITE_ERR;
299 	}
300 
301 #ifdef USE_REWRITE_LDAP_PVT_THREADS
302         ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex );
303 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
304 
305 	rewrite_session_return( info, session );
306 
307 	return rc;
308 }
309 
310 static void
311 rewrite_session_clean( void *v_session )
312 {
313 	struct rewrite_session	*session = (struct rewrite_session *)v_session;
314 
315 #ifdef USE_REWRITE_LDAP_PVT_THREADS
316 	ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex );
317 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
318 
319 	rewrite_var_delete( session->ls_vars );
320 
321 #ifdef USE_REWRITE_LDAP_PVT_THREADS
322 	ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
323 	ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex );
324 	ldap_pvt_thread_mutex_unlock( &session->ls_mutex );
325 	ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
326 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
327 }
328 
329 static void
330 rewrite_session_free( void *v_session )
331 {
332 	struct rewrite_session	*session = (struct rewrite_session *)v_session;
333 
334 	ldap_pvt_thread_mutex_lock( &session->ls_mutex );
335 	rewrite_session_clean( v_session );
336 	free( v_session );
337 }
338 
339 /*
340  * Deletes a session
341  */
342 int
343 rewrite_session_delete(
344 		struct rewrite_info *info,
345 		const void *cookie
346 )
347 {
348 	struct rewrite_session *session, tmp = { 0 };
349 
350 	assert( info != NULL );
351 	assert( cookie != NULL );
352 
353 	session = rewrite_session_find( info, cookie );
354 
355 	if ( session == NULL ) {
356 		return REWRITE_SUCCESS;
357 	}
358 
359 	if ( --session->ls_count > 0 ) {
360 		rewrite_session_return( info, session );
361 		return REWRITE_SUCCESS;
362 	}
363 
364 	rewrite_session_clean( session );
365 
366 #ifdef USE_REWRITE_LDAP_PVT_THREADS
367 	ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
368 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
369 
370 	assert( info->li_num_cookies > 0 );
371 	info->li_num_cookies--;
372 
373 	/*
374 	 * There is nothing to delete in the return value
375 	 */
376 	tmp.ls_cookie = ( void * )cookie;
377 	avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp );
378 
379 	free( session );
380 
381 #ifdef USE_REWRITE_LDAP_PVT_THREADS
382 	ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
383 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
384 
385 	return REWRITE_SUCCESS;
386 }
387 
388 /*
389  * Destroys the cookie tree
390  */
391 int
392 rewrite_session_destroy(
393 		struct rewrite_info *info
394 )
395 {
396 	int count;
397 
398 	assert( info != NULL );
399 
400 #ifdef USE_REWRITE_LDAP_PVT_THREADS
401 	ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
402 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
403 
404 	/*
405 	 * Should call per-session destruction routine ...
406 	 */
407 
408 	count = avl_free( info->li_cookies, rewrite_session_free );
409 	info->li_cookies = NULL;
410 
411 #if 0
412 	fprintf( stderr, "count = %d; num_cookies = %d\n",
413 			count, info->li_num_cookies );
414 #endif
415 
416 	assert( count == info->li_num_cookies );
417 	info->li_num_cookies = 0;
418 
419 #ifdef USE_REWRITE_LDAP_PVT_THREADS
420 	ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
421 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
422 
423 	return REWRITE_SUCCESS;
424 }
425 
426