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->url); 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+1]; 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+1]; 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 util_ldap_compare_node_free(cache, node); 264 return NULL; 265 } 266 node->lastcompare = n->lastcompare; 267 node->result = n->result; 268 return node; 269 } 270 else { 271 return NULL; 272 } 273} 274 275void util_ldap_compare_node_free(util_ald_cache_t *cache, void *n) 276{ 277 util_compare_node_t *node = n; 278 util_ald_free(cache, node->dn); 279 util_ald_free(cache, node->attrib); 280 util_ald_free(cache, node->value); 281 util_ald_free(cache, node); 282} 283 284void util_ldap_compare_node_display(request_rec *r, util_ald_cache_t *cache, void *n) 285{ 286 util_compare_node_t *node = n; 287 char date_str[APR_CTIME_LEN+1]; 288 char *cmp_result; 289 290 apr_ctime(date_str, node->lastcompare); 291 292 if (node->result == LDAP_COMPARE_TRUE) { 293 cmp_result = "LDAP_COMPARE_TRUE"; 294 } 295 else if (node->result == LDAP_COMPARE_FALSE) { 296 cmp_result = "LDAP_COMPARE_FALSE"; 297 } 298 else { 299 cmp_result = apr_itoa(r->pool, node->result); 300 } 301 302 ap_rprintf(r, 303 "<tr valign='top'>" 304 "<td nowrap>%s</td>" 305 "<td nowrap>%s</td>" 306 "<td nowrap>%s</td>" 307 "<td nowrap>%s</td>" 308 "<td nowrap>%s</td>" 309 "</tr>", 310 node->dn, 311 node->attrib, 312 node->value, 313 date_str, 314 cmp_result); 315} 316 317/* ------------------------------------------------------------------ */ 318 319unsigned long util_ldap_dn_compare_node_hash(void *n) 320{ 321 util_dn_compare_node_t *node = n; 322 return util_ald_hash_string(1, node->reqdn); 323} 324 325int util_ldap_dn_compare_node_compare(void *a, void *b) 326{ 327 util_dn_compare_node_t *na = a; 328 util_dn_compare_node_t *nb = b; 329 330 return (strcmp(na->reqdn, nb->reqdn) == 0); 331} 332 333void *util_ldap_dn_compare_node_copy(util_ald_cache_t *cache, void *c) 334{ 335 util_dn_compare_node_t *n = c; 336 util_dn_compare_node_t *node = util_ald_alloc(cache, sizeof *node); 337 338 if (node) { 339 if (!(node->reqdn = util_ald_strdup(cache, n->reqdn)) || 340 !(node->dn = util_ald_strdup(cache, n->dn))) { 341 util_ldap_dn_compare_node_free(cache, node); 342 return NULL; 343 } 344 return node; 345 } 346 else { 347 return NULL; 348 } 349} 350 351void util_ldap_dn_compare_node_free(util_ald_cache_t *cache, void *n) 352{ 353 util_dn_compare_node_t *node = n; 354 util_ald_free(cache, node->reqdn); 355 util_ald_free(cache, node->dn); 356 util_ald_free(cache, node); 357} 358 359void util_ldap_dn_compare_node_display(request_rec *r, util_ald_cache_t *cache, void *n) 360{ 361 util_dn_compare_node_t *node = n; 362 363 ap_rprintf(r, 364 "<tr valign='top'>" 365 "<td nowrap>%s</td>" 366 "<td nowrap>%s</td>" 367 "</tr>", 368 node->reqdn, 369 node->dn); 370} 371 372 373/* ------------------------------------------------------------------ */ 374static apr_status_t util_ldap_cache_module_kill(void *data) 375{ 376 util_ldap_state_t *st = data; 377 378 util_ald_destroy_cache(st->util_ldap_cache); 379#if APR_HAS_SHARED_MEMORY 380 if (st->cache_rmm != NULL) { 381 apr_rmm_destroy (st->cache_rmm); 382 st->cache_rmm = NULL; 383 } 384 if (st->cache_shm != NULL) { 385 apr_status_t result = apr_shm_destroy(st->cache_shm); 386 st->cache_shm = NULL; 387 return result; 388 } 389#endif 390 return APR_SUCCESS; 391} 392 393apr_status_t util_ldap_cache_init(apr_pool_t *pool, util_ldap_state_t *st) 394{ 395#if APR_HAS_SHARED_MEMORY 396 apr_status_t result; 397 apr_size_t size; 398 399 if (st->cache_file) { 400 /* Remove any existing shm segment with this name. */ 401 apr_shm_remove(st->cache_file, st->pool); 402 } 403 404 size = APR_ALIGN_DEFAULT(st->cache_bytes); 405 406 result = apr_shm_create(&st->cache_shm, size, st->cache_file, st->pool); 407 if (result != APR_SUCCESS) { 408 return result; 409 } 410 411 /* Determine the usable size of the shm segment. */ 412 size = apr_shm_size_get(st->cache_shm); 413 414 /* This will create a rmm "handler" to get into the shared memory area */ 415 result = apr_rmm_init(&st->cache_rmm, NULL, 416 apr_shm_baseaddr_get(st->cache_shm), size, 417 st->pool); 418 if (result != APR_SUCCESS) { 419 return result; 420 } 421 422#endif 423 424 apr_pool_cleanup_register(st->pool, st , util_ldap_cache_module_kill, apr_pool_cleanup_null); 425 426 st->util_ldap_cache = 427 util_ald_create_cache(st, 428 st->search_cache_size, 429 util_ldap_url_node_hash, 430 util_ldap_url_node_compare, 431 util_ldap_url_node_copy, 432 util_ldap_url_node_free, 433 util_ldap_url_node_display); 434 return APR_SUCCESS; 435} 436 437 438#endif /* APR_HAS_LDAP */ 439