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