1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * util_ldap_cache.c: LDAP cache things 19 * 20 * Original code from auth_ldap module for Apache v1.3: 21 * Copyright 1998, 1999 Enbridge Pipelines Inc. 22 * Copyright 1999-2001 Dave Carrigan 23 */ 24 25#include "httpd.h" 26#include "util_ldap.h" 27#include "util_ldap_cache.h" 28#include <apr_strings.h> 29 30#if APR_HAS_LDAP 31 32/* ------------------------------------------------------------------ */ 33 34unsigned long util_ldap_url_node_hash(void *n) 35{ 36 util_url_node_t *node = n; 37 return util_ald_hash_string(1, node->url); 38} 39 40int util_ldap_url_node_compare(void *a, void *b) 41{ 42 util_url_node_t *na = a; 43 util_url_node_t *nb = b; 44 45 return (strcmp(na->url, nb->url) == 0); 46} 47 48void *util_ldap_url_node_copy(util_ald_cache_t *cache, void *c) 49{ 50 util_url_node_t *n = c; 51 util_url_node_t *node = util_ald_alloc(cache, sizeof *node); 52 53 if (node) { 54 if (!(node->url = util_ald_strdup(cache, n->url))) { 55 util_ald_free(cache, node); 56 return NULL; 57 } 58 node->search_cache = n->search_cache; 59 node->compare_cache = n->compare_cache; 60 node->dn_compare_cache = n->dn_compare_cache; 61 return node; 62 } 63 else { 64 return NULL; 65 } 66} 67 68void util_ldap_url_node_free(util_ald_cache_t *cache, void *n) 69{ 70 util_url_node_t *node = n; 71 72 util_ald_free(cache, node->url); 73 util_ald_destroy_cache(node->search_cache); 74 util_ald_destroy_cache(node->compare_cache); 75 util_ald_destroy_cache(node->dn_compare_cache); 76 util_ald_free(cache, node); 77} 78 79void util_ldap_url_node_display(request_rec *r, util_ald_cache_t *cache, void *n) 80{ 81 util_url_node_t *node = n; 82 char date_str[APR_CTIME_LEN]; 83 const char *type_str; 84 util_ald_cache_t *cache_node; 85 int x; 86 87 for (x=0;x<3;x++) { 88 switch (x) { 89 case 0: 90 cache_node = node->search_cache; 91 type_str = "Searches"; 92 break; 93 case 1: 94 cache_node = node->compare_cache; 95 type_str = "Compares"; 96 break; 97 case 2: 98 default: 99 cache_node = node->dn_compare_cache; 100 type_str = "DN Compares"; 101 break; 102 } 103 104 if (cache_node->marktime) { 105 apr_ctime(date_str, cache_node->marktime); 106 } 107 else 108 date_str[0] = 0; 109 110 ap_rprintf(r, 111 "<tr valign='top'>" 112 "<td nowrap>%s (%s)</td>" 113 "<td nowrap>%ld</td>" 114 "<td nowrap>%ld</td>" 115 "<td nowrap>%ld</td>" 116 "<td nowrap>%ld</td>" 117 "<td nowrap>%s</td>" 118 "</tr>", 119 node->url, 120 type_str, 121 cache_node->size, 122 cache_node->maxentries, 123 cache_node->numentries, 124 cache_node->fullmark, 125 date_str); 126 } 127 128} 129 130/* ------------------------------------------------------------------ */ 131 132/* Cache functions for search nodes */ 133unsigned long util_ldap_search_node_hash(void *n) 134{ 135 util_search_node_t *node = n; 136 return util_ald_hash_string(1, node->username); 137} 138 139int util_ldap_search_node_compare(void *a, void *b) 140{ 141 util_search_node_t *na = a; 142 util_search_node_t *nb = b; 143 144 return (strcmp(na->username, nb->username) == 0); 145} 146 147void *util_ldap_search_node_copy(util_ald_cache_t *cache, void *c) 148{ 149 util_search_node_t *node = c; 150 util_search_node_t *newnode = util_ald_alloc(cache, sizeof *newnode); 151 152 /* safety check */ 153 if (newnode) { 154 155 /* copy vals */ 156 if (node->vals) { 157 int k = node->numvals; 158 int i = 0; 159 if (!(newnode->vals = util_ald_alloc(cache, sizeof(char *) * (k+1)))) { 160 util_ldap_search_node_free(cache, newnode); 161 return NULL; 162 } 163 newnode->numvals = node->numvals; 164 for (;k;k--) { 165 if (node->vals[i]) { 166 if (!(newnode->vals[i] = util_ald_strdup(cache, node->vals[i]))) { 167 util_ldap_search_node_free(cache, newnode); 168 return NULL; 169 } 170 } 171 else 172 newnode->vals[i] = NULL; 173 i++; 174 } 175 } 176 else { 177 newnode->vals = NULL; 178 } 179 if (!(newnode->username = util_ald_strdup(cache, node->username)) || 180 !(newnode->dn = util_ald_strdup(cache, node->dn)) ) { 181 util_ldap_search_node_free(cache, newnode); 182 return NULL; 183 } 184 if(node->bindpw) { 185 if(!(newnode->bindpw = util_ald_strdup(cache, node->bindpw))) { 186 util_ldap_search_node_free(cache, newnode); 187 return NULL; 188 } 189 } else { 190 newnode->bindpw = NULL; 191 } 192 newnode->lastbind = node->lastbind; 193 194 } 195 return (void *)newnode; 196} 197 198void util_ldap_search_node_free(util_ald_cache_t *cache, void *n) 199{ 200 int i = 0; 201 util_search_node_t *node = n; 202 int k = node->numvals; 203 204 if (node->vals) { 205 for (;k;k--,i++) { 206 if (node->vals[i]) { 207 util_ald_free(cache, node->vals[i]); 208 } 209 } 210 util_ald_free(cache, node->vals); 211 } 212 util_ald_free(cache, node->username); 213 util_ald_free(cache, node->dn); 214 util_ald_free(cache, node->bindpw); 215 util_ald_free(cache, node); 216} 217 218void util_ldap_search_node_display(request_rec *r, util_ald_cache_t *cache, void *n) 219{ 220 util_search_node_t *node = n; 221 char date_str[APR_CTIME_LEN]; 222 223 apr_ctime(date_str, node->lastbind); 224 225 ap_rprintf(r, 226 "<tr valign='top'>" 227 "<td nowrap>%s</td>" 228 "<td nowrap>%s</td>" 229 "<td nowrap>%s</td>" 230 "</tr>", 231 node->username, 232 node->dn, 233 date_str); 234} 235 236/* ------------------------------------------------------------------ */ 237 238unsigned long util_ldap_compare_node_hash(void *n) 239{ 240 util_compare_node_t *node = n; 241 return util_ald_hash_string(3, node->dn, node->attrib, node->value); 242} 243 244int util_ldap_compare_node_compare(void *a, void *b) 245{ 246 util_compare_node_t *na = a; 247 util_compare_node_t *nb = b; 248 249 return (strcmp(na->dn, nb->dn) == 0 && 250 strcmp(na->attrib, nb->attrib) == 0 && 251 strcmp(na->value, nb->value) == 0); 252} 253 254void *util_ldap_compare_node_copy(util_ald_cache_t *cache, void *c) 255{ 256 util_compare_node_t *n = c; 257 util_compare_node_t *node = util_ald_alloc(cache, sizeof *node); 258 259 if (node) { 260 if (!(node->dn = util_ald_strdup(cache, n->dn)) || 261 !(node->attrib = util_ald_strdup(cache, n->attrib)) || 262 !(node->value = util_ald_strdup(cache, n->value)) || 263 ((n->subgroupList) && !(node->subgroupList = util_ald_sgl_dup(cache, n->subgroupList)))) { 264 util_ldap_compare_node_free(cache, node); 265 return NULL; 266 } 267 node->lastcompare = n->lastcompare; 268 node->result = n->result; 269 node->sgl_processed = n->sgl_processed; 270 return node; 271 } 272 else { 273 return NULL; 274 } 275} 276 277void util_ldap_compare_node_free(util_ald_cache_t *cache, void *n) 278{ 279 util_compare_node_t *node = n; 280 281 util_ald_sgl_free(cache, &(node->subgroupList)); 282 util_ald_free(cache, node->dn); 283 util_ald_free(cache, node->attrib); 284 util_ald_free(cache, node->value); 285 util_ald_free(cache, node); 286} 287 288void util_ldap_compare_node_display(request_rec *r, util_ald_cache_t *cache, void *n) 289{ 290 util_compare_node_t *node = n; 291 char date_str[APR_CTIME_LEN]; 292 char *cmp_result; 293 char *sub_groups_val; 294 char *sub_groups_checked; 295 296 apr_ctime(date_str, node->lastcompare); 297 298 if (node->result == LDAP_COMPARE_TRUE) { 299 cmp_result = "LDAP_COMPARE_TRUE"; 300 } 301 else if (node->result == LDAP_COMPARE_FALSE) { 302 cmp_result = "LDAP_COMPARE_FALSE"; 303 } 304 else { 305 cmp_result = apr_itoa(r->pool, node->result); 306 } 307 308 if(node->subgroupList) { 309 sub_groups_val = "Yes"; 310 } 311 else { 312 sub_groups_val = "No"; 313 } 314 315 if(node->sgl_processed) { 316 sub_groups_checked = "Yes"; 317 } 318 else { 319 sub_groups_checked = "No"; 320 } 321 322 ap_rprintf(r, 323 "<tr valign='top'>" 324 "<td nowrap>%s</td>" 325 "<td nowrap>%s</td>" 326 "<td nowrap>%s</td>" 327 "<td nowrap>%s</td>" 328 "<td nowrap>%s</td>" 329 "<td nowrap>%s</td>" 330 "<td nowrap>%s</td>" 331 "</tr>", 332 node->dn, 333 node->attrib, 334 node->value, 335 date_str, 336 cmp_result, 337 sub_groups_val, 338 sub_groups_checked); 339} 340 341/* ------------------------------------------------------------------ */ 342 343unsigned long util_ldap_dn_compare_node_hash(void *n) 344{ 345 util_dn_compare_node_t *node = n; 346 return util_ald_hash_string(1, node->reqdn); 347} 348 349int util_ldap_dn_compare_node_compare(void *a, void *b) 350{ 351 util_dn_compare_node_t *na = a; 352 util_dn_compare_node_t *nb = b; 353 354 return (strcmp(na->reqdn, nb->reqdn) == 0); 355} 356 357void *util_ldap_dn_compare_node_copy(util_ald_cache_t *cache, void *c) 358{ 359 util_dn_compare_node_t *n = c; 360 util_dn_compare_node_t *node = util_ald_alloc(cache, sizeof *node); 361 362 if (node) { 363 if (!(node->reqdn = util_ald_strdup(cache, n->reqdn)) || 364 !(node->dn = util_ald_strdup(cache, n->dn))) { 365 util_ldap_dn_compare_node_free(cache, node); 366 return NULL; 367 } 368 return node; 369 } 370 else { 371 return NULL; 372 } 373} 374 375void util_ldap_dn_compare_node_free(util_ald_cache_t *cache, void *n) 376{ 377 util_dn_compare_node_t *node = n; 378 util_ald_free(cache, node->reqdn); 379 util_ald_free(cache, node->dn); 380 util_ald_free(cache, node); 381} 382 383void util_ldap_dn_compare_node_display(request_rec *r, util_ald_cache_t *cache, void *n) 384{ 385 util_dn_compare_node_t *node = n; 386 387 ap_rprintf(r, 388 "<tr valign='top'>" 389 "<td nowrap>%s</td>" 390 "<td nowrap>%s</td>" 391 "</tr>", 392 node->reqdn, 393 node->dn); 394} 395 396 397/* ------------------------------------------------------------------ */ 398static apr_status_t util_ldap_cache_module_kill(void *data) 399{ 400 util_ldap_state_t *st = data; 401 402 util_ald_destroy_cache(st->util_ldap_cache); 403#if APR_HAS_SHARED_MEMORY 404 if (st->cache_rmm != NULL) { 405 apr_rmm_destroy (st->cache_rmm); 406 st->cache_rmm = NULL; 407 } 408 if (st->cache_shm != NULL) { 409 apr_status_t result = apr_shm_destroy(st->cache_shm); 410 st->cache_shm = NULL; 411 return result; 412 } 413#endif 414 return APR_SUCCESS; 415} 416 417apr_status_t util_ldap_cache_init(apr_pool_t *pool, util_ldap_state_t *st) 418{ 419#if APR_HAS_SHARED_MEMORY 420 apr_status_t result; 421 apr_size_t size; 422 423 if (st->cache_bytes > 0) { 424 if (st->cache_file) { 425 /* Remove any existing shm segment with this name. */ 426 apr_shm_remove(st->cache_file, st->pool); 427 } 428 429 size = APR_ALIGN_DEFAULT(st->cache_bytes); 430 431 result = apr_shm_create(&st->cache_shm, size, st->cache_file, st->pool); 432 if (result != APR_SUCCESS) { 433 return result; 434 } 435 436 /* Determine the usable size of the shm segment. */ 437 size = apr_shm_size_get(st->cache_shm); 438 439 /* This will create a rmm "handler" to get into the shared memory area */ 440 result = apr_rmm_init(&st->cache_rmm, NULL, 441 apr_shm_baseaddr_get(st->cache_shm), size, 442 st->pool); 443 if (result != APR_SUCCESS) { 444 return result; 445 } 446 } 447 448#endif 449 450 apr_pool_cleanup_register(st->pool, st , util_ldap_cache_module_kill, apr_pool_cleanup_null); 451 452 st->util_ldap_cache = 453 util_ald_create_cache(st, 454 st->search_cache_size, 455 util_ldap_url_node_hash, 456 util_ldap_url_node_compare, 457 util_ldap_url_node_copy, 458 util_ldap_url_node_free, 459 util_ldap_url_node_display); 460 return APR_SUCCESS; 461} 462 463 464#endif /* APR_HAS_LDAP */ 465