1158115Sume/*- 2158115Sume * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru> 3158115Sume * All rights reserved. 4158115Sume * 5158115Sume * Redistribution and use in source and binary forms, with or without 6158115Sume * modification, are permitted provided that the following conditions 7158115Sume * are met: 8158115Sume * 1. Redistributions of source code must retain the above copyright 9158115Sume * notice, this list of conditions and the following disclaimer. 10158115Sume * 2. Redistributions in binary form must reproduce the above copyright 11158115Sume * notice, this list of conditions and the following disclaimer in the 12158115Sume * documentation and/or other materials provided with the distribution. 13158115Sume * 14158115Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15158115Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16158115Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17158115Sume * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18158115Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19158115Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20158115Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21158115Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22158115Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23158115Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24158115Sume * SUCH DAMAGE. 25158115Sume * 26158115Sume */ 27158115Sume 28158115Sume#include <sys/cdefs.h> 29158115Sume__FBSDID("$FreeBSD$"); 30158115Sume 31158115Sume#include "namespace.h" 32288013Srodrigc#define _NS_PRIVATE 33158115Sume#include <nsswitch.h> 34158115Sume#include <stdlib.h> 35158115Sume#include <string.h> 36158115Sume#include "un-namespace.h" 37158115Sume#include "nscachedcli.h" 38158115Sume#include "nscache.h" 39158115Sume 40158115Sume#define NSS_CACHE_KEY_INITIAL_SIZE (256) 41158115Sume#define NSS_CACHE_KEY_SIZE_LIMIT (NSS_CACHE_KEY_INITIAL_SIZE << 4) 42158115Sume 43158115Sume#define NSS_CACHE_BUFFER_INITIAL_SIZE (1024) 44158115Sume#define NSS_CACHE_BUFFER_SIZE_LIMIT (NSS_CACHE_BUFFER_INITIAL_SIZE << 8) 45158115Sume 46172730Stmclaugh#define CACHED_SOCKET_PATH "/var/run/nscd" 47158115Sume 48158115Sumeint 49158115Sume__nss_cache_handler(void *retval, void *mdata, va_list ap) 50158115Sume{ 51158115Sume return (NS_UNAVAIL); 52158115Sume} 53158115Sume 54158115Sumeint 55158115Sume__nss_common_cache_read(void *retval, void *mdata, va_list ap) 56158115Sume{ 57158115Sume struct cached_connection_params params; 58158115Sume cached_connection connection; 59158115Sume 60158115Sume char *buffer; 61158115Sume size_t buffer_size, size; 62158115Sume 63158115Sume nss_cache_info const *cache_info; 64158115Sume nss_cache_data *cache_data; 65158115Sume va_list ap_new; 66158115Sume int res; 67158115Sume 68158115Sume cache_data = (nss_cache_data *)mdata; 69158115Sume cache_info = cache_data->info; 70158115Sume 71158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 72158115Sume params.socket_path = CACHED_SOCKET_PATH; 73158115Sume 74158115Sume cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE); 75158115Sume memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE); 76158115Sume cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE; 77158115Sume va_copy(ap_new, ap); 78158115Sume 79158115Sume do { 80158115Sume size = cache_data->key_size; 81158115Sume res = cache_info->id_func(cache_data->key, &size, ap_new, 82158115Sume cache_info->mdata); 83158115Sume va_end(ap_new); 84158115Sume if (res == NS_RETURN) { 85158115Sume if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT) 86158115Sume break; 87158115Sume 88158115Sume cache_data->key_size <<= 1; 89158115Sume cache_data->key = realloc(cache_data->key, 90158115Sume cache_data->key_size); 91158115Sume memset(cache_data->key, 0, cache_data->key_size); 92158115Sume va_copy(ap_new, ap); 93158115Sume } 94158115Sume } while (res == NS_RETURN); 95158115Sume 96158115Sume if (res != NS_SUCCESS) { 97158115Sume free(cache_data->key); 98158115Sume cache_data->key = NULL; 99158115Sume cache_data->key_size = 0; 100158115Sume return (res); 101158115Sume } else 102158115Sume cache_data->key_size = size; 103158115Sume 104158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 105158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 106158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 107158115Sume 108158115Sume do { 109158115Sume connection = __open_cached_connection(¶ms); 110158115Sume if (connection == NULL) { 111158115Sume res = -1; 112158115Sume break; 113158115Sume } 114158115Sume res = __cached_read(connection, cache_info->entry_name, 115158115Sume cache_data->key, cache_data->key_size, buffer, 116158115Sume &buffer_size); 117158115Sume __close_cached_connection(connection); 118158115Sume if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) { 119158115Sume buffer = (char *)realloc(buffer, buffer_size); 120158115Sume memset(buffer, 0, buffer_size); 121158115Sume } 122158115Sume } while (res == -2); 123158115Sume 124158115Sume if (res == 0) { 125158115Sume if (buffer_size == 0) { 126158115Sume free(buffer); 127158115Sume free(cache_data->key); 128158115Sume cache_data->key = NULL; 129158115Sume cache_data->key_size = 0; 130158115Sume return (NS_RETURN); 131158115Sume } 132158115Sume 133158115Sume va_copy(ap_new, ap); 134158115Sume res = cache_info->unmarshal_func(buffer, buffer_size, retval, 135158115Sume ap_new, cache_info->mdata); 136158115Sume va_end(ap_new); 137158115Sume 138158115Sume if (res != NS_SUCCESS) { 139158115Sume free(buffer); 140158115Sume free(cache_data->key); 141158115Sume cache_data->key = NULL; 142158115Sume cache_data->key_size = 0; 143158115Sume return (res); 144158115Sume } else 145158115Sume res = 0; 146158115Sume } 147158115Sume 148158115Sume if (res == 0) { 149158115Sume free(cache_data->key); 150158115Sume cache_data->key = NULL; 151158115Sume cache_data->key_size = 0; 152158115Sume } 153158115Sume 154158115Sume free(buffer); 155158115Sume return (res == 0 ? NS_SUCCESS : NS_NOTFOUND); 156158115Sume} 157158115Sume 158158115Sumeint 159158115Sume__nss_common_cache_write(void *retval, void *mdata, va_list ap) 160158115Sume{ 161158115Sume struct cached_connection_params params; 162158115Sume cached_connection connection; 163158115Sume 164158115Sume char *buffer; 165158115Sume size_t buffer_size; 166158115Sume 167158115Sume nss_cache_info const *cache_info; 168158115Sume nss_cache_data *cache_data; 169158115Sume va_list ap_new; 170158115Sume int res; 171158115Sume 172158115Sume cache_data = (nss_cache_data *)mdata; 173158115Sume cache_info = cache_data->info; 174158115Sume 175158115Sume if (cache_data->key == NULL) 176158115Sume return (NS_UNAVAIL); 177158115Sume 178158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 179158115Sume params.socket_path = CACHED_SOCKET_PATH; 180158115Sume 181158115Sume connection = __open_cached_connection(¶ms); 182158115Sume if (connection == NULL) { 183158115Sume free(cache_data->key); 184158115Sume return (NS_UNAVAIL); 185158115Sume } 186158115Sume 187158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 188158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 189158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 190158115Sume 191158115Sume do { 192158115Sume size_t size; 193158115Sume 194158115Sume size = buffer_size; 195158115Sume va_copy(ap_new, ap); 196158115Sume res = cache_info->marshal_func(buffer, &size, retval, ap_new, 197158115Sume cache_info->mdata); 198158115Sume va_end(ap_new); 199158115Sume 200158115Sume if (res == NS_RETURN) { 201158115Sume if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT) 202158115Sume break; 203158115Sume 204158115Sume buffer_size <<= 1; 205158115Sume buffer = (char *)realloc(buffer, buffer_size); 206158115Sume memset(buffer, 0, buffer_size); 207158115Sume } 208158115Sume } while (res == NS_RETURN); 209158115Sume 210158115Sume if (res != NS_SUCCESS) { 211158115Sume __close_cached_connection(connection); 212158115Sume free(cache_data->key); 213158115Sume free(buffer); 214158115Sume return (res); 215158115Sume } 216158115Sume 217158115Sume res = __cached_write(connection, cache_info->entry_name, 218158115Sume cache_data->key, cache_data->key_size, buffer, buffer_size); 219158115Sume __close_cached_connection(connection); 220158115Sume 221158115Sume free(cache_data->key); 222158115Sume free(buffer); 223158115Sume 224158115Sume return (res == 0 ? NS_SUCCESS : NS_UNAVAIL); 225158115Sume} 226158115Sume 227158115Sumeint 228158115Sume__nss_common_cache_write_negative(void *mdata) 229158115Sume{ 230158115Sume struct cached_connection_params params; 231158115Sume cached_connection connection; 232158115Sume int res; 233158115Sume 234158115Sume nss_cache_info const *cache_info; 235158115Sume nss_cache_data *cache_data; 236158115Sume 237158115Sume cache_data = (nss_cache_data *)mdata; 238158115Sume cache_info = cache_data->info; 239158115Sume 240158115Sume if (cache_data->key == NULL) 241158115Sume return (NS_UNAVAIL); 242158115Sume 243158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 244158115Sume params.socket_path = CACHED_SOCKET_PATH; 245158115Sume 246158115Sume connection = __open_cached_connection(¶ms); 247158115Sume if (connection == NULL) { 248158115Sume free(cache_data->key); 249158115Sume return (NS_UNAVAIL); 250158115Sume } 251158115Sume 252158115Sume res = __cached_write(connection, cache_info->entry_name, 253158115Sume cache_data->key, cache_data->key_size, NULL, 0); 254158115Sume __close_cached_connection(connection); 255158115Sume 256158115Sume free(cache_data->key); 257158115Sume return (res == 0 ? NS_SUCCESS : NS_UNAVAIL); 258158115Sume} 259158115Sume 260158115Sumeint 261158115Sume__nss_mp_cache_read(void *retval, void *mdata, va_list ap) 262158115Sume{ 263158115Sume struct cached_connection_params params; 264158115Sume cached_mp_read_session rs; 265158115Sume 266158115Sume char *buffer; 267158115Sume size_t buffer_size; 268158115Sume 269158115Sume nss_cache_info const *cache_info; 270158115Sume nss_cache_data *cache_data; 271158115Sume va_list ap_new; 272158115Sume int res; 273158115Sume 274158115Sume cache_data = (nss_cache_data *)mdata; 275158115Sume cache_info = cache_data->info; 276158115Sume 277158115Sume if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION) 278158115Sume return (NS_UNAVAIL); 279158115Sume 280158115Sume rs = cache_info->get_mp_rs_func(); 281158115Sume if (rs == INVALID_CACHED_MP_READ_SESSION) { 282158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 283158115Sume params.socket_path = CACHED_SOCKET_PATH; 284158115Sume 285158115Sume rs = __open_cached_mp_read_session(¶ms, 286158115Sume cache_info->entry_name); 287158115Sume if (rs == INVALID_CACHED_MP_READ_SESSION) 288158115Sume return (NS_UNAVAIL); 289158115Sume 290158115Sume cache_info->set_mp_rs_func(rs); 291158115Sume } 292158115Sume 293158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 294158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 295158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 296158115Sume 297158115Sume do { 298158115Sume res = __cached_mp_read(rs, buffer, &buffer_size); 299158115Sume if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) { 300158115Sume buffer = (char *)realloc(buffer, buffer_size); 301158115Sume memset(buffer, 0, buffer_size); 302158115Sume } 303158115Sume } while (res == -2); 304158115Sume 305158115Sume if (res == 0) { 306158115Sume va_copy(ap_new, ap); 307158115Sume res = cache_info->unmarshal_func(buffer, buffer_size, retval, 308158115Sume ap_new, cache_info->mdata); 309158115Sume va_end(ap_new); 310158115Sume 311158115Sume if (res != NS_SUCCESS) { 312158115Sume free(buffer); 313158115Sume return (res); 314158115Sume } else 315158115Sume res = 0; 316158115Sume } else { 317158115Sume free(buffer); 318158115Sume __close_cached_mp_read_session(rs); 319158115Sume rs = INVALID_CACHED_MP_READ_SESSION; 320158115Sume cache_info->set_mp_rs_func(rs); 321158115Sume return (res == -1 ? NS_RETURN : NS_UNAVAIL); 322158115Sume } 323158115Sume 324158115Sume free(buffer); 325158115Sume return (res == 0 ? NS_SUCCESS : NS_NOTFOUND); 326158115Sume} 327158115Sume 328158115Sumeint 329158115Sume__nss_mp_cache_write(void *retval, void *mdata, va_list ap) 330158115Sume{ 331158115Sume struct cached_connection_params params; 332158115Sume cached_mp_write_session ws; 333158115Sume 334158115Sume char *buffer; 335158115Sume size_t buffer_size; 336158115Sume 337158115Sume nss_cache_info const *cache_info; 338158115Sume nss_cache_data *cache_data; 339158115Sume va_list ap_new; 340158115Sume int res; 341158115Sume 342158115Sume cache_data = (nss_cache_data *)mdata; 343158115Sume cache_info = cache_data->info; 344158115Sume 345158115Sume ws = cache_info->get_mp_ws_func(); 346158115Sume if (ws == INVALID_CACHED_MP_WRITE_SESSION) { 347158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 348158115Sume params.socket_path = CACHED_SOCKET_PATH; 349158115Sume 350158115Sume ws = __open_cached_mp_write_session(¶ms, 351158115Sume cache_info->entry_name); 352158115Sume if (ws == INVALID_CACHED_MP_WRITE_SESSION) 353158115Sume return (NS_UNAVAIL); 354158115Sume 355158115Sume cache_info->set_mp_ws_func(ws); 356158115Sume } 357158115Sume 358158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 359158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 360158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 361158115Sume 362158115Sume do { 363158115Sume size_t size; 364158115Sume 365158115Sume size = buffer_size; 366158115Sume va_copy(ap_new, ap); 367158115Sume res = cache_info->marshal_func(buffer, &size, retval, ap_new, 368158115Sume cache_info->mdata); 369158115Sume va_end(ap_new); 370158115Sume 371158115Sume if (res == NS_RETURN) { 372158115Sume if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT) 373158115Sume break; 374158115Sume 375158115Sume buffer_size <<= 1; 376158115Sume buffer = (char *)realloc(buffer, buffer_size); 377158115Sume memset(buffer, 0, buffer_size); 378158115Sume } 379158115Sume } while (res == NS_RETURN); 380158115Sume 381158115Sume if (res != NS_SUCCESS) { 382158115Sume free(buffer); 383158115Sume return (res); 384158115Sume } 385158115Sume 386158115Sume res = __cached_mp_write(ws, buffer, buffer_size); 387158115Sume 388158115Sume free(buffer); 389158115Sume return (res == 0 ? NS_SUCCESS : NS_UNAVAIL); 390158115Sume} 391158115Sume 392158115Sumeint 393158115Sume__nss_mp_cache_write_submit(void *retval, void *mdata, va_list ap) 394158115Sume{ 395158115Sume cached_mp_write_session ws; 396158115Sume 397158115Sume nss_cache_info const *cache_info; 398158115Sume nss_cache_data *cache_data; 399158115Sume 400158115Sume cache_data = (nss_cache_data *)mdata; 401158115Sume cache_info = cache_data->info; 402158115Sume 403158115Sume ws = cache_info->get_mp_ws_func(); 404158115Sume if (ws != INVALID_CACHED_MP_WRITE_SESSION) { 405158115Sume __close_cached_mp_write_session(ws); 406158115Sume ws = INVALID_CACHED_MP_WRITE_SESSION; 407158115Sume cache_info->set_mp_ws_func(ws); 408158115Sume } 409158115Sume return (NS_UNAVAIL); 410158115Sume} 411158115Sume 412158115Sumeint 413158115Sume__nss_mp_cache_end(void *retval, void *mdata, va_list ap) 414158115Sume{ 415158115Sume cached_mp_write_session ws; 416158115Sume cached_mp_read_session rs; 417158115Sume 418158115Sume nss_cache_info const *cache_info; 419158115Sume nss_cache_data *cache_data; 420158115Sume 421158115Sume cache_data = (nss_cache_data *)mdata; 422158115Sume cache_info = cache_data->info; 423158115Sume 424158115Sume ws = cache_info->get_mp_ws_func(); 425158115Sume if (ws != INVALID_CACHED_MP_WRITE_SESSION) { 426158115Sume __abandon_cached_mp_write_session(ws); 427158115Sume ws = INVALID_CACHED_MP_WRITE_SESSION; 428158115Sume cache_info->set_mp_ws_func(ws); 429158115Sume } 430158115Sume 431158115Sume rs = cache_info->get_mp_rs_func(); 432158115Sume if (rs != INVALID_CACHED_MP_READ_SESSION) { 433158115Sume __close_cached_mp_read_session(rs); 434158115Sume rs = INVALID_CACHED_MP_READ_SESSION; 435158115Sume cache_info->set_mp_rs_func(rs); 436158115Sume } 437158115Sume 438158115Sume return (NS_UNAVAIL); 439158115Sume} 440