Home | History | Annotate | Line # | Download | only in librewrite
      1 /*	$NetBSD: session.c,v 1.8 2025/09/05 21:16:23 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 2000-2024 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 * )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 *
    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
    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
    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
    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
    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
    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
    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
    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