1 /* $NetBSD: session.c,v 1.7 2021/08/14 16:14:58 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2000-2021 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
rewrite_cookie_cmp(const void * c1,const void * c2)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
rewrite_cookie_dup(void * c1,void * c2)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 *
rewrite_session_init(struct rewrite_info * info,const void * cookie)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 * )ldap_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 = ldap_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 *
rewrite_session_find(struct rewrite_info * info,const void * cookie)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 * )ldap_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
rewrite_session_return(struct rewrite_info * info,struct rewrite_session * session)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 #ifdef USE_REWRITE_LDAP_PVT_THREADS
191 ldap_pvt_thread_mutex_unlock( &session->ls_mutex );
192 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
193 }
194
195 /*
196 * Defines and inits a var with session scope
197 */
198 int
rewrite_session_var_set_f(struct rewrite_info * info,const void * cookie,const char * name,const char * value,int flags)199 rewrite_session_var_set_f(
200 struct rewrite_info *info,
201 const void *cookie,
202 const char *name,
203 const char *value,
204 int flags
205 )
206 {
207 struct rewrite_session *session;
208 struct rewrite_var *var;
209
210 assert( info != NULL );
211 assert( cookie != NULL );
212 assert( name != NULL );
213 assert( value != NULL );
214
215 session = rewrite_session_find( info, cookie );
216 if ( session == NULL ) {
217 session = rewrite_session_init( info, cookie );
218 if ( session == NULL ) {
219 return REWRITE_ERR;
220 }
221
222 #ifdef USE_REWRITE_LDAP_PVT_THREADS
223 ldap_pvt_thread_mutex_lock( &session->ls_mutex );
224 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
225 }
226
227 #ifdef USE_REWRITE_LDAP_PVT_THREADS
228 ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex );
229 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
230
231 var = rewrite_var_find( session->ls_vars, name );
232 if ( var != NULL ) {
233 assert( var->lv_value.bv_val != NULL );
234
235 (void)rewrite_var_replace( var, value, flags );
236
237 } else {
238 var = rewrite_var_insert_f( &session->ls_vars, name, value, flags );
239 if ( var == NULL ) {
240 #ifdef USE_REWRITE_LDAP_PVT_THREADS
241 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
242 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
243 rewrite_session_return( info, session );
244 return REWRITE_ERR;
245 }
246 }
247
248 #ifdef USE_REWRITE_LDAP_PVT_THREADS
249 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
250 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
251
252 rewrite_session_return( info, session );
253
254 return REWRITE_SUCCESS;
255 }
256
257 /*
258 * Gets a var with session scope
259 */
260 int
rewrite_session_var_get(struct rewrite_info * info,const void * cookie,const char * name,struct berval * value)261 rewrite_session_var_get(
262 struct rewrite_info *info,
263 const void *cookie,
264 const char *name,
265 struct berval *value
266 )
267 {
268 struct rewrite_session *session;
269 struct rewrite_var *var;
270 int rc = REWRITE_SUCCESS;
271
272 assert( info != NULL );
273 assert( cookie != NULL );
274 assert( name != NULL );
275 assert( value != NULL );
276
277 value->bv_val = NULL;
278 value->bv_len = 0;
279
280 if ( cookie == NULL ) {
281 return REWRITE_ERR;
282 }
283
284 session = rewrite_session_find( info, cookie );
285 if ( session == NULL ) {
286 return REWRITE_ERR;
287 }
288
289 #ifdef USE_REWRITE_LDAP_PVT_THREADS
290 ldap_pvt_thread_rdwr_rlock( &session->ls_vars_mutex );
291 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
292
293 var = rewrite_var_find( session->ls_vars, name );
294 if ( var != NULL ) {
295 value->bv_val = strdup( var->lv_value.bv_val );
296 value->bv_len = var->lv_value.bv_len;
297 }
298
299 if ( var == NULL || value->bv_val == NULL ) {
300 rc = REWRITE_ERR;
301 }
302
303 #ifdef USE_REWRITE_LDAP_PVT_THREADS
304 ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex );
305 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
306
307 rewrite_session_return( info, session );
308
309 return rc;
310 }
311
312 static void
rewrite_session_clean(void * v_session)313 rewrite_session_clean( void *v_session )
314 {
315 struct rewrite_session *session = (struct rewrite_session *)v_session;
316
317 #ifdef USE_REWRITE_LDAP_PVT_THREADS
318 ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex );
319 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
320
321 rewrite_var_delete( session->ls_vars );
322
323 #ifdef USE_REWRITE_LDAP_PVT_THREADS
324 ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
325 ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex );
326 ldap_pvt_thread_mutex_unlock( &session->ls_mutex );
327 ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
328 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
329 }
330
331 static void
rewrite_session_free(void * v_session)332 rewrite_session_free( void *v_session )
333 {
334 struct rewrite_session *session = (struct rewrite_session *)v_session;
335
336 #ifdef USE_REWRITE_LDAP_PVT_THREADS
337 ldap_pvt_thread_mutex_lock( &session->ls_mutex );
338 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
339 rewrite_session_clean( v_session );
340 free( v_session );
341 }
342
343 /*
344 * Deletes a session
345 */
346 int
rewrite_session_delete(struct rewrite_info * info,const void * cookie)347 rewrite_session_delete(
348 struct rewrite_info *info,
349 const void *cookie
350 )
351 {
352 struct rewrite_session *session, tmp = { 0 };
353
354 assert( info != NULL );
355 assert( cookie != NULL );
356
357 session = rewrite_session_find( info, cookie );
358
359 if ( session == NULL ) {
360 return REWRITE_SUCCESS;
361 }
362
363 if ( --session->ls_count > 0 ) {
364 rewrite_session_return( info, session );
365 return REWRITE_SUCCESS;
366 }
367
368 rewrite_session_clean( session );
369
370 #ifdef USE_REWRITE_LDAP_PVT_THREADS
371 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
372 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
373
374 assert( info->li_num_cookies > 0 );
375 info->li_num_cookies--;
376
377 /*
378 * There is nothing to delete in the return value
379 */
380 tmp.ls_cookie = ( void * )cookie;
381 ldap_avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp );
382
383 free( session );
384
385 #ifdef USE_REWRITE_LDAP_PVT_THREADS
386 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
387 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
388
389 return REWRITE_SUCCESS;
390 }
391
392 /*
393 * Destroys the cookie tree
394 */
395 int
rewrite_session_destroy(struct rewrite_info * info)396 rewrite_session_destroy(
397 struct rewrite_info *info
398 )
399 {
400 int count;
401
402 assert( info != NULL );
403
404 #ifdef USE_REWRITE_LDAP_PVT_THREADS
405 ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
406 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
407
408 /*
409 * Should call per-session destruction routine ...
410 */
411
412 count = ldap_avl_free( info->li_cookies, rewrite_session_free );
413 info->li_cookies = NULL;
414
415 #if 0
416 fprintf( stderr, "count = %d; num_cookies = %d\n",
417 count, info->li_num_cookies );
418 #endif
419
420 assert( count == info->li_num_cookies );
421 info->li_num_cookies = 0;
422
423 #ifdef USE_REWRITE_LDAP_PVT_THREADS
424 ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
425 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
426
427 return REWRITE_SUCCESS;
428 }
429
430