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: releng/11.0/usr.sbin/nscd/query.c 272668 2014-10-06 18:16:45Z jhb $"); 30158115Sume 31158115Sume#include <sys/types.h> 32194089Sdes#include <sys/event.h> 33158115Sume#include <sys/socket.h> 34158115Sume#include <sys/time.h> 35194089Sdes 36158115Sume#include <assert.h> 37158115Sume#include <errno.h> 38158115Sume#include <nsswitch.h> 39158115Sume#include <stdio.h> 40158115Sume#include <stdlib.h> 41158115Sume#include <string.h> 42194089Sdes#include <unistd.h> 43194089Sdes 44158115Sume#include "config.h" 45158115Sume#include "debug.h" 46158115Sume#include "query.h" 47158115Sume#include "log.h" 48158115Sume#include "mp_ws_query.h" 49158115Sume#include "mp_rs_query.h" 50158115Sume#include "singletons.h" 51158115Sume 52158115Sumestatic const char negative_data[1] = { 0 }; 53158115Sume 54158115Sumeextern void get_time_func(struct timeval *); 55158115Sume 56158115Sumestatic void clear_config_entry(struct configuration_entry *); 57158115Sumestatic void clear_config_entry_part(struct configuration_entry *, 58158115Sume const char *, size_t); 59158115Sume 60158115Sumestatic int on_query_startup(struct query_state *); 61158115Sumestatic void on_query_destroy(struct query_state *); 62158115Sume 63158115Sumestatic int on_read_request_read1(struct query_state *); 64158115Sumestatic int on_read_request_read2(struct query_state *); 65158115Sumestatic int on_read_request_process(struct query_state *); 66158115Sumestatic int on_read_response_write1(struct query_state *); 67158115Sumestatic int on_read_response_write2(struct query_state *); 68158115Sume 69158115Sumestatic int on_rw_mapper(struct query_state *); 70158115Sume 71158115Sumestatic int on_transform_request_read1(struct query_state *); 72158115Sumestatic int on_transform_request_read2(struct query_state *); 73158115Sumestatic int on_transform_request_process(struct query_state *); 74158115Sumestatic int on_transform_response_write1(struct query_state *); 75158115Sume 76158115Sumestatic int on_write_request_read1(struct query_state *); 77158115Sumestatic int on_write_request_read2(struct query_state *); 78158115Sumestatic int on_negative_write_request_process(struct query_state *); 79158115Sumestatic int on_write_request_process(struct query_state *); 80158115Sumestatic int on_write_response_write1(struct query_state *); 81158115Sume 82158115Sume/* 83158115Sume * Clears the specified configuration entry (clears the cache for positive and 84158115Sume * and negative entries) and also for all multipart entries. 85158115Sume */ 86158115Sumestatic void 87158115Sumeclear_config_entry(struct configuration_entry *config_entry) 88158115Sume{ 89158115Sume size_t i; 90158115Sume 91158115Sume TRACE_IN(clear_config_entry); 92158115Sume configuration_lock_entry(config_entry, CELT_POSITIVE); 93158115Sume if (config_entry->positive_cache_entry != NULL) 94158115Sume transform_cache_entry( 95158115Sume config_entry->positive_cache_entry, 96158115Sume CTT_CLEAR); 97158115Sume configuration_unlock_entry(config_entry, CELT_POSITIVE); 98158115Sume 99158115Sume configuration_lock_entry(config_entry, CELT_NEGATIVE); 100158115Sume if (config_entry->negative_cache_entry != NULL) 101158115Sume transform_cache_entry( 102158115Sume config_entry->negative_cache_entry, 103158115Sume CTT_CLEAR); 104158115Sume configuration_unlock_entry(config_entry, CELT_NEGATIVE); 105158115Sume 106158115Sume configuration_lock_entry(config_entry, CELT_MULTIPART); 107158115Sume for (i = 0; i < config_entry->mp_cache_entries_size; ++i) 108158115Sume transform_cache_entry( 109158115Sume config_entry->mp_cache_entries[i], 110158115Sume CTT_CLEAR); 111158115Sume configuration_unlock_entry(config_entry, CELT_MULTIPART); 112158115Sume 113158115Sume TRACE_OUT(clear_config_entry); 114158115Sume} 115158115Sume 116158115Sume/* 117158115Sume * Clears the specified configuration entry by deleting only the elements, 118158115Sume * that are owned by the user with specified eid_str. 119158115Sume */ 120158115Sumestatic void 121158115Sumeclear_config_entry_part(struct configuration_entry *config_entry, 122158115Sume const char *eid_str, size_t eid_str_length) 123158115Sume{ 124158115Sume cache_entry *start, *finish, *mp_entry; 125158115Sume TRACE_IN(clear_config_entry_part); 126158115Sume configuration_lock_entry(config_entry, CELT_POSITIVE); 127158115Sume if (config_entry->positive_cache_entry != NULL) 128158115Sume transform_cache_entry_part( 129158115Sume config_entry->positive_cache_entry, 130158115Sume CTT_CLEAR, eid_str, eid_str_length, KPPT_LEFT); 131158115Sume configuration_unlock_entry(config_entry, CELT_POSITIVE); 132158115Sume 133158115Sume configuration_lock_entry(config_entry, CELT_NEGATIVE); 134158115Sume if (config_entry->negative_cache_entry != NULL) 135158115Sume transform_cache_entry_part( 136158115Sume config_entry->negative_cache_entry, 137158115Sume CTT_CLEAR, eid_str, eid_str_length, KPPT_LEFT); 138158115Sume configuration_unlock_entry(config_entry, CELT_NEGATIVE); 139158115Sume 140158115Sume configuration_lock_entry(config_entry, CELT_MULTIPART); 141158115Sume if (configuration_entry_find_mp_cache_entries(config_entry, 142158115Sume eid_str, &start, &finish) == 0) { 143158115Sume for (mp_entry = start; mp_entry != finish; ++mp_entry) 144158115Sume transform_cache_entry(*mp_entry, CTT_CLEAR); 145158115Sume } 146158115Sume configuration_unlock_entry(config_entry, CELT_MULTIPART); 147158115Sume 148158115Sume TRACE_OUT(clear_config_entry_part); 149158115Sume} 150158115Sume 151158115Sume/* 152158115Sume * This function is assigned to the query_state structue on its creation. 153158115Sume * It's main purpose is to receive credentials from the client. 154158115Sume */ 155158115Sumestatic int 156158115Sumeon_query_startup(struct query_state *qstate) 157158115Sume{ 158158115Sume struct msghdr cred_hdr; 159158115Sume struct iovec iov; 160158257Sume struct cmsgcred *cred; 161158115Sume int elem_type; 162158115Sume 163158115Sume struct { 164158115Sume struct cmsghdr hdr; 165158257Sume char cred[CMSG_SPACE(sizeof(struct cmsgcred))]; 166158115Sume } cmsg; 167158115Sume 168158115Sume TRACE_IN(on_query_startup); 169158115Sume assert(qstate != NULL); 170158115Sume 171158115Sume memset(&cred_hdr, 0, sizeof(struct msghdr)); 172158115Sume cred_hdr.msg_iov = &iov; 173158115Sume cred_hdr.msg_iovlen = 1; 174158257Sume cred_hdr.msg_control = (caddr_t)&cmsg; 175158257Sume cred_hdr.msg_controllen = CMSG_LEN(sizeof(struct cmsgcred)); 176158115Sume 177158115Sume memset(&iov, 0, sizeof(struct iovec)); 178158115Sume iov.iov_base = &elem_type; 179158115Sume iov.iov_len = sizeof(int); 180158115Sume 181158115Sume if (recvmsg(qstate->sockfd, &cred_hdr, 0) == -1) { 182158115Sume TRACE_OUT(on_query_startup); 183158115Sume return (-1); 184158115Sume } 185158115Sume 186158257Sume if (cmsg.hdr.cmsg_len < CMSG_LEN(sizeof(struct cmsgcred)) 187158115Sume || cmsg.hdr.cmsg_level != SOL_SOCKET 188158115Sume || cmsg.hdr.cmsg_type != SCM_CREDS) { 189158115Sume TRACE_OUT(on_query_startup); 190158115Sume return (-1); 191158115Sume } 192158115Sume 193158257Sume cred = (struct cmsgcred *)CMSG_DATA(&cmsg); 194158257Sume qstate->uid = cred->cmcred_uid; 195158257Sume qstate->gid = cred->cmcred_gid; 196158115Sume 197171795Sbushman#if defined(NS_NSCD_EID_CHECKING) || defined(NS_STRICT_NSCD_EID_CHECKING) 198158115Sume/* 199158115Sume * This check is probably a bit redundant - per-user cache is always separated 200158115Sume * by the euid/egid pair 201158115Sume */ 202158115Sume if (check_query_eids(qstate) != 0) { 203171795Sbushman#ifdef NS_STRICT_NSCD_EID_CHECKING 204158115Sume TRACE_OUT(on_query_startup); 205158115Sume return (-1); 206158115Sume#else 207158115Sume if ((elem_type != CET_READ_REQUEST) && 208158115Sume (elem_type != CET_MP_READ_SESSION_REQUEST) && 209158115Sume (elem_type != CET_WRITE_REQUEST) && 210158115Sume (elem_type != CET_MP_WRITE_SESSION_REQUEST)) { 211158115Sume TRACE_OUT(on_query_startup); 212158115Sume return (-1); 213158115Sume } 214158115Sume#endif 215158115Sume } 216158115Sume#endif 217158115Sume 218158115Sume switch (elem_type) { 219158115Sume case CET_WRITE_REQUEST: 220158115Sume qstate->process_func = on_write_request_read1; 221158115Sume break; 222158115Sume case CET_READ_REQUEST: 223158115Sume qstate->process_func = on_read_request_read1; 224158115Sume break; 225158115Sume case CET_TRANSFORM_REQUEST: 226158115Sume qstate->process_func = on_transform_request_read1; 227158115Sume break; 228158115Sume case CET_MP_WRITE_SESSION_REQUEST: 229158115Sume qstate->process_func = on_mp_write_session_request_read1; 230158115Sume break; 231158115Sume case CET_MP_READ_SESSION_REQUEST: 232158115Sume qstate->process_func = on_mp_read_session_request_read1; 233158115Sume break; 234158115Sume default: 235158115Sume TRACE_OUT(on_query_startup); 236158115Sume return (-1); 237158115Sume } 238158115Sume 239158115Sume qstate->kevent_watermark = 0; 240158115Sume TRACE_OUT(on_query_startup); 241158115Sume return (0); 242158115Sume} 243158115Sume 244158115Sume/* 245158115Sume * on_rw_mapper is used to process multiple read/write requests during 246158115Sume * one connection session. It's never called in the beginning (on query_state 247158115Sume * creation) as it does not process the multipart requests and does not 248158115Sume * receive credentials 249158115Sume */ 250158115Sumestatic int 251158115Sumeon_rw_mapper(struct query_state *qstate) 252158115Sume{ 253158115Sume ssize_t result; 254158115Sume int elem_type; 255158115Sume 256158115Sume TRACE_IN(on_rw_mapper); 257158115Sume if (qstate->kevent_watermark == 0) { 258158115Sume qstate->kevent_watermark = sizeof(int); 259158115Sume } else { 260158115Sume result = qstate->read_func(qstate, &elem_type, sizeof(int)); 261158115Sume if (result != sizeof(int)) { 262158115Sume TRACE_OUT(on_rw_mapper); 263158115Sume return (-1); 264158115Sume } 265158115Sume 266158115Sume switch (elem_type) { 267158115Sume case CET_WRITE_REQUEST: 268158115Sume qstate->kevent_watermark = sizeof(size_t); 269158115Sume qstate->process_func = on_write_request_read1; 270158115Sume break; 271158115Sume case CET_READ_REQUEST: 272158115Sume qstate->kevent_watermark = sizeof(size_t); 273158115Sume qstate->process_func = on_read_request_read1; 274158115Sume break; 275158115Sume default: 276158115Sume TRACE_OUT(on_rw_mapper); 277158115Sume return (-1); 278158115Sume break; 279158115Sume } 280158115Sume } 281158115Sume TRACE_OUT(on_rw_mapper); 282158115Sume return (0); 283158115Sume} 284158115Sume 285158115Sume/* 286158115Sume * The default query_destroy function 287158115Sume */ 288158115Sumestatic void 289158115Sumeon_query_destroy(struct query_state *qstate) 290158115Sume{ 291158115Sume 292158115Sume TRACE_IN(on_query_destroy); 293158115Sume finalize_comm_element(&qstate->response); 294158115Sume finalize_comm_element(&qstate->request); 295158115Sume TRACE_OUT(on_query_destroy); 296158115Sume} 297158115Sume 298158115Sume/* 299158115Sume * The functions below are used to process write requests. 300158115Sume * - on_write_request_read1 and on_write_request_read2 read the request itself 301158115Sume * - on_write_request_process processes it (if the client requests to 302158115Sume * cache the negative result, the on_negative_write_request_process is used) 303158115Sume * - on_write_response_write1 sends the response 304158115Sume */ 305158115Sumestatic int 306158115Sumeon_write_request_read1(struct query_state *qstate) 307158115Sume{ 308158115Sume struct cache_write_request *write_request; 309158115Sume ssize_t result; 310158115Sume 311158115Sume TRACE_IN(on_write_request_read1); 312158115Sume if (qstate->kevent_watermark == 0) 313158115Sume qstate->kevent_watermark = sizeof(size_t) * 3; 314158115Sume else { 315158115Sume init_comm_element(&qstate->request, CET_WRITE_REQUEST); 316158115Sume write_request = get_cache_write_request(&qstate->request); 317158115Sume 318158115Sume result = qstate->read_func(qstate, &write_request->entry_length, 319158115Sume sizeof(size_t)); 320158115Sume result += qstate->read_func(qstate, 321158115Sume &write_request->cache_key_size, sizeof(size_t)); 322158115Sume result += qstate->read_func(qstate, 323158115Sume &write_request->data_size, sizeof(size_t)); 324158115Sume 325158115Sume if (result != sizeof(size_t) * 3) { 326158115Sume TRACE_OUT(on_write_request_read1); 327158115Sume return (-1); 328158115Sume } 329158115Sume 330158115Sume if (BUFSIZE_INVALID(write_request->entry_length) || 331158115Sume BUFSIZE_INVALID(write_request->cache_key_size) || 332158115Sume (BUFSIZE_INVALID(write_request->data_size) && 333158115Sume (write_request->data_size != 0))) { 334158115Sume TRACE_OUT(on_write_request_read1); 335158115Sume return (-1); 336158115Sume } 337158115Sume 338194104Sdes write_request->entry = calloc(1, 339158115Sume write_request->entry_length + 1); 340158115Sume assert(write_request->entry != NULL); 341158115Sume 342194104Sdes write_request->cache_key = calloc(1, 343158115Sume write_request->cache_key_size + 344158115Sume qstate->eid_str_length); 345158115Sume assert(write_request->cache_key != NULL); 346158115Sume memcpy(write_request->cache_key, qstate->eid_str, 347158115Sume qstate->eid_str_length); 348158115Sume 349158115Sume if (write_request->data_size != 0) { 350194104Sdes write_request->data = calloc(1, 351158115Sume write_request->data_size); 352158115Sume assert(write_request->data != NULL); 353158115Sume } 354158115Sume 355158115Sume qstate->kevent_watermark = write_request->entry_length + 356158115Sume write_request->cache_key_size + 357158115Sume write_request->data_size; 358158115Sume qstate->process_func = on_write_request_read2; 359158115Sume } 360158115Sume 361158115Sume TRACE_OUT(on_write_request_read1); 362158115Sume return (0); 363158115Sume} 364158115Sume 365158115Sumestatic int 366158115Sumeon_write_request_read2(struct query_state *qstate) 367158115Sume{ 368158115Sume struct cache_write_request *write_request; 369158115Sume ssize_t result; 370158115Sume 371158115Sume TRACE_IN(on_write_request_read2); 372158115Sume write_request = get_cache_write_request(&qstate->request); 373158115Sume 374158115Sume result = qstate->read_func(qstate, write_request->entry, 375158115Sume write_request->entry_length); 376158115Sume result += qstate->read_func(qstate, write_request->cache_key + 377158115Sume qstate->eid_str_length, write_request->cache_key_size); 378158115Sume if (write_request->data_size != 0) 379158115Sume result += qstate->read_func(qstate, write_request->data, 380158115Sume write_request->data_size); 381158115Sume 382194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 383158115Sume TRACE_OUT(on_write_request_read2); 384158115Sume return (-1); 385158115Sume } 386158115Sume write_request->cache_key_size += qstate->eid_str_length; 387158115Sume 388158115Sume qstate->kevent_watermark = 0; 389158115Sume if (write_request->data_size != 0) 390158115Sume qstate->process_func = on_write_request_process; 391158115Sume else 392158115Sume qstate->process_func = on_negative_write_request_process; 393158115Sume TRACE_OUT(on_write_request_read2); 394158115Sume return (0); 395158115Sume} 396158115Sume 397158115Sumestatic int 398158115Sumeon_write_request_process(struct query_state *qstate) 399158115Sume{ 400158115Sume struct cache_write_request *write_request; 401158115Sume struct cache_write_response *write_response; 402158115Sume cache_entry c_entry; 403158115Sume 404158115Sume TRACE_IN(on_write_request_process); 405158115Sume init_comm_element(&qstate->response, CET_WRITE_RESPONSE); 406158115Sume write_response = get_cache_write_response(&qstate->response); 407158115Sume write_request = get_cache_write_request(&qstate->request); 408158115Sume 409158115Sume qstate->config_entry = configuration_find_entry( 410158115Sume s_configuration, write_request->entry); 411158115Sume 412158115Sume if (qstate->config_entry == NULL) { 413158115Sume write_response->error_code = ENOENT; 414158115Sume 415158115Sume LOG_ERR_2("write_request", "can't find configuration" 416158115Sume " entry '%s'. aborting request", write_request->entry); 417158115Sume goto fin; 418158115Sume } 419158115Sume 420158115Sume if (qstate->config_entry->enabled == 0) { 421158115Sume write_response->error_code = EACCES; 422158115Sume 423158115Sume LOG_ERR_2("write_request", 424158115Sume "configuration entry '%s' is disabled", 425158115Sume write_request->entry); 426158115Sume goto fin; 427158115Sume } 428158115Sume 429158115Sume if (qstate->config_entry->perform_actual_lookups != 0) { 430158115Sume write_response->error_code = EOPNOTSUPP; 431158115Sume 432158115Sume LOG_ERR_2("write_request", 433158115Sume "entry '%s' performs lookups by itself: " 434158115Sume "can't write to it", write_request->entry); 435158115Sume goto fin; 436158115Sume } 437158115Sume 438158115Sume configuration_lock_rdlock(s_configuration); 439158115Sume c_entry = find_cache_entry(s_cache, 440194097Sdes qstate->config_entry->positive_cache_params.cep.entry_name); 441158115Sume configuration_unlock(s_configuration); 442158115Sume if (c_entry != NULL) { 443158115Sume configuration_lock_entry(qstate->config_entry, CELT_POSITIVE); 444158115Sume qstate->config_entry->positive_cache_entry = c_entry; 445158115Sume write_response->error_code = cache_write(c_entry, 446158115Sume write_request->cache_key, 447158115Sume write_request->cache_key_size, 448158115Sume write_request->data, 449158115Sume write_request->data_size); 450158115Sume configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE); 451158115Sume 452158115Sume if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || 453158115Sume (qstate->config_entry->common_query_timeout.tv_usec != 0)) 454158115Sume memcpy(&qstate->timeout, 455158115Sume &qstate->config_entry->common_query_timeout, 456158115Sume sizeof(struct timeval)); 457158115Sume 458158115Sume } else 459158115Sume write_response->error_code = -1; 460158115Sume 461158115Sumefin: 462158115Sume qstate->kevent_filter = EVFILT_WRITE; 463158115Sume qstate->kevent_watermark = sizeof(int); 464158115Sume qstate->process_func = on_write_response_write1; 465158115Sume 466158115Sume TRACE_OUT(on_write_request_process); 467158115Sume return (0); 468158115Sume} 469158115Sume 470158115Sumestatic int 471158115Sumeon_negative_write_request_process(struct query_state *qstate) 472158115Sume{ 473158115Sume struct cache_write_request *write_request; 474158115Sume struct cache_write_response *write_response; 475158115Sume cache_entry c_entry; 476158115Sume 477158115Sume TRACE_IN(on_negative_write_request_process); 478158115Sume init_comm_element(&qstate->response, CET_WRITE_RESPONSE); 479158115Sume write_response = get_cache_write_response(&qstate->response); 480158115Sume write_request = get_cache_write_request(&qstate->request); 481158115Sume 482158115Sume qstate->config_entry = configuration_find_entry ( 483158115Sume s_configuration, write_request->entry); 484158115Sume 485158115Sume if (qstate->config_entry == NULL) { 486158115Sume write_response->error_code = ENOENT; 487158115Sume 488158115Sume LOG_ERR_2("negative_write_request", 489158115Sume "can't find configuration" 490158115Sume " entry '%s'. aborting request", write_request->entry); 491158115Sume goto fin; 492158115Sume } 493158115Sume 494158115Sume if (qstate->config_entry->enabled == 0) { 495158115Sume write_response->error_code = EACCES; 496158115Sume 497158115Sume LOG_ERR_2("negative_write_request", 498158115Sume "configuration entry '%s' is disabled", 499158115Sume write_request->entry); 500158115Sume goto fin; 501158115Sume } 502158115Sume 503158115Sume if (qstate->config_entry->perform_actual_lookups != 0) { 504158115Sume write_response->error_code = EOPNOTSUPP; 505158115Sume 506158115Sume LOG_ERR_2("negative_write_request", 507158115Sume "entry '%s' performs lookups by itself: " 508158115Sume "can't write to it", write_request->entry); 509158115Sume goto fin; 510158115Sume } else { 511171795Sbushman#ifdef NS_NSCD_EID_CHECKING 512158115Sume if (check_query_eids(qstate) != 0) { 513158115Sume write_response->error_code = EPERM; 514158115Sume goto fin; 515158115Sume } 516158115Sume#endif 517158115Sume } 518158115Sume 519158115Sume configuration_lock_rdlock(s_configuration); 520158115Sume c_entry = find_cache_entry(s_cache, 521194097Sdes qstate->config_entry->negative_cache_params.cep.entry_name); 522158115Sume configuration_unlock(s_configuration); 523158115Sume if (c_entry != NULL) { 524158115Sume configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE); 525158115Sume qstate->config_entry->negative_cache_entry = c_entry; 526158115Sume write_response->error_code = cache_write(c_entry, 527158115Sume write_request->cache_key, 528158115Sume write_request->cache_key_size, 529158115Sume negative_data, 530158115Sume sizeof(negative_data)); 531158115Sume configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE); 532158115Sume 533158115Sume if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || 534158115Sume (qstate->config_entry->common_query_timeout.tv_usec != 0)) 535158115Sume memcpy(&qstate->timeout, 536158115Sume &qstate->config_entry->common_query_timeout, 537158115Sume sizeof(struct timeval)); 538158115Sume } else 539158115Sume write_response->error_code = -1; 540158115Sume 541158115Sumefin: 542158115Sume qstate->kevent_filter = EVFILT_WRITE; 543158115Sume qstate->kevent_watermark = sizeof(int); 544158115Sume qstate->process_func = on_write_response_write1; 545158115Sume 546158115Sume TRACE_OUT(on_negative_write_request_process); 547158115Sume return (0); 548158115Sume} 549158115Sume 550158115Sumestatic int 551158115Sumeon_write_response_write1(struct query_state *qstate) 552158115Sume{ 553158115Sume struct cache_write_response *write_response; 554158115Sume ssize_t result; 555158115Sume 556158115Sume TRACE_IN(on_write_response_write1); 557158115Sume write_response = get_cache_write_response(&qstate->response); 558158115Sume result = qstate->write_func(qstate, &write_response->error_code, 559158115Sume sizeof(int)); 560158115Sume if (result != sizeof(int)) { 561158115Sume TRACE_OUT(on_write_response_write1); 562158115Sume return (-1); 563158115Sume } 564158115Sume 565158115Sume finalize_comm_element(&qstate->request); 566158115Sume finalize_comm_element(&qstate->response); 567158115Sume 568158115Sume qstate->kevent_watermark = sizeof(int); 569158115Sume qstate->kevent_filter = EVFILT_READ; 570158115Sume qstate->process_func = on_rw_mapper; 571158115Sume 572158115Sume TRACE_OUT(on_write_response_write1); 573158115Sume return (0); 574158115Sume} 575158115Sume 576158115Sume/* 577158115Sume * The functions below are used to process read requests. 578158115Sume * - on_read_request_read1 and on_read_request_read2 read the request itself 579158115Sume * - on_read_request_process processes it 580158115Sume * - on_read_response_write1 and on_read_response_write2 send the response 581158115Sume */ 582158115Sumestatic int 583158115Sumeon_read_request_read1(struct query_state *qstate) 584158115Sume{ 585158115Sume struct cache_read_request *read_request; 586158115Sume ssize_t result; 587158115Sume 588158115Sume TRACE_IN(on_read_request_read1); 589158115Sume if (qstate->kevent_watermark == 0) 590158115Sume qstate->kevent_watermark = sizeof(size_t) * 2; 591158115Sume else { 592158115Sume init_comm_element(&qstate->request, CET_READ_REQUEST); 593158115Sume read_request = get_cache_read_request(&qstate->request); 594158115Sume 595158115Sume result = qstate->read_func(qstate, 596158115Sume &read_request->entry_length, sizeof(size_t)); 597158115Sume result += qstate->read_func(qstate, 598158115Sume &read_request->cache_key_size, sizeof(size_t)); 599158115Sume 600158115Sume if (result != sizeof(size_t) * 2) { 601158115Sume TRACE_OUT(on_read_request_read1); 602158115Sume return (-1); 603158115Sume } 604158115Sume 605158115Sume if (BUFSIZE_INVALID(read_request->entry_length) || 606158115Sume BUFSIZE_INVALID(read_request->cache_key_size)) { 607158115Sume TRACE_OUT(on_read_request_read1); 608158115Sume return (-1); 609158115Sume } 610158115Sume 611194104Sdes read_request->entry = calloc(1, 612158115Sume read_request->entry_length + 1); 613158115Sume assert(read_request->entry != NULL); 614158115Sume 615194104Sdes read_request->cache_key = calloc(1, 616158115Sume read_request->cache_key_size + 617158115Sume qstate->eid_str_length); 618158115Sume assert(read_request->cache_key != NULL); 619158115Sume memcpy(read_request->cache_key, qstate->eid_str, 620158115Sume qstate->eid_str_length); 621158115Sume 622158115Sume qstate->kevent_watermark = read_request->entry_length + 623158115Sume read_request->cache_key_size; 624158115Sume qstate->process_func = on_read_request_read2; 625158115Sume } 626158115Sume 627158115Sume TRACE_OUT(on_read_request_read1); 628158115Sume return (0); 629158115Sume} 630158115Sume 631158115Sumestatic int 632158115Sumeon_read_request_read2(struct query_state *qstate) 633158115Sume{ 634158115Sume struct cache_read_request *read_request; 635158115Sume ssize_t result; 636158115Sume 637158115Sume TRACE_IN(on_read_request_read2); 638158115Sume read_request = get_cache_read_request(&qstate->request); 639158115Sume 640158115Sume result = qstate->read_func(qstate, read_request->entry, 641158115Sume read_request->entry_length); 642158115Sume result += qstate->read_func(qstate, 643158115Sume read_request->cache_key + qstate->eid_str_length, 644158115Sume read_request->cache_key_size); 645158115Sume 646194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 647158115Sume TRACE_OUT(on_read_request_read2); 648158115Sume return (-1); 649158115Sume } 650158115Sume read_request->cache_key_size += qstate->eid_str_length; 651158115Sume 652158115Sume qstate->kevent_watermark = 0; 653158115Sume qstate->process_func = on_read_request_process; 654158115Sume 655158115Sume TRACE_OUT(on_read_request_read2); 656158115Sume return (0); 657158115Sume} 658158115Sume 659158115Sumestatic int 660158115Sumeon_read_request_process(struct query_state *qstate) 661158115Sume{ 662158115Sume struct cache_read_request *read_request; 663158115Sume struct cache_read_response *read_response; 664158115Sume cache_entry c_entry, neg_c_entry; 665158115Sume 666158115Sume struct agent *lookup_agent; 667158115Sume struct common_agent *c_agent; 668158115Sume int res; 669158115Sume 670158115Sume TRACE_IN(on_read_request_process); 671158115Sume init_comm_element(&qstate->response, CET_READ_RESPONSE); 672158115Sume read_response = get_cache_read_response(&qstate->response); 673158115Sume read_request = get_cache_read_request(&qstate->request); 674158115Sume 675158115Sume qstate->config_entry = configuration_find_entry( 676158115Sume s_configuration, read_request->entry); 677158115Sume if (qstate->config_entry == NULL) { 678158115Sume read_response->error_code = ENOENT; 679158115Sume 680158115Sume LOG_ERR_2("read_request", 681158115Sume "can't find configuration " 682158115Sume "entry '%s'. aborting request", read_request->entry); 683158115Sume goto fin; 684158115Sume } 685158115Sume 686158115Sume if (qstate->config_entry->enabled == 0) { 687158115Sume read_response->error_code = EACCES; 688158115Sume 689158115Sume LOG_ERR_2("read_request", 690158115Sume "configuration entry '%s' is disabled", 691158115Sume read_request->entry); 692158115Sume goto fin; 693158115Sume } 694158115Sume 695158115Sume /* 696158115Sume * if we perform lookups by ourselves, then we don't need to separate 697158115Sume * cache entries by euid and egid 698158115Sume */ 699158115Sume if (qstate->config_entry->perform_actual_lookups != 0) 700158115Sume memset(read_request->cache_key, 0, qstate->eid_str_length); 701158115Sume else { 702171795Sbushman#ifdef NS_NSCD_EID_CHECKING 703158115Sume if (check_query_eids(qstate) != 0) { 704158115Sume /* if the lookup is not self-performing, we check for clients euid/egid */ 705158115Sume read_response->error_code = EPERM; 706158115Sume goto fin; 707158115Sume } 708158115Sume#endif 709158115Sume } 710158115Sume 711158115Sume configuration_lock_rdlock(s_configuration); 712158115Sume c_entry = find_cache_entry(s_cache, 713194097Sdes qstate->config_entry->positive_cache_params.cep.entry_name); 714158115Sume neg_c_entry = find_cache_entry(s_cache, 715194097Sdes qstate->config_entry->negative_cache_params.cep.entry_name); 716158115Sume configuration_unlock(s_configuration); 717158115Sume if ((c_entry != NULL) && (neg_c_entry != NULL)) { 718158115Sume configuration_lock_entry(qstate->config_entry, CELT_POSITIVE); 719158115Sume qstate->config_entry->positive_cache_entry = c_entry; 720158115Sume read_response->error_code = cache_read(c_entry, 721158115Sume read_request->cache_key, 722158115Sume read_request->cache_key_size, NULL, 723158115Sume &read_response->data_size); 724158115Sume 725158115Sume if (read_response->error_code == -2) { 726194104Sdes read_response->data = malloc( 727194104Sdes read_response->data_size); 728158115Sume assert(read_response != NULL); 729158115Sume read_response->error_code = cache_read(c_entry, 730158115Sume read_request->cache_key, 731158115Sume read_request->cache_key_size, 732158115Sume read_response->data, 733158115Sume &read_response->data_size); 734158115Sume } 735158115Sume configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE); 736158115Sume 737158115Sume configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE); 738158115Sume qstate->config_entry->negative_cache_entry = neg_c_entry; 739158115Sume if (read_response->error_code == -1) { 740158115Sume read_response->error_code = cache_read(neg_c_entry, 741158115Sume read_request->cache_key, 742158115Sume read_request->cache_key_size, NULL, 743158115Sume &read_response->data_size); 744158115Sume 745158115Sume if (read_response->error_code == -2) { 746158115Sume read_response->error_code = 0; 747158115Sume read_response->data = NULL; 748158115Sume read_response->data_size = 0; 749158115Sume } 750158115Sume } 751158115Sume configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE); 752158115Sume 753158115Sume if ((read_response->error_code == -1) && 754158115Sume (qstate->config_entry->perform_actual_lookups != 0)) { 755158115Sume free(read_response->data); 756158115Sume read_response->data = NULL; 757158115Sume read_response->data_size = 0; 758158115Sume 759158115Sume lookup_agent = find_agent(s_agent_table, 760158115Sume read_request->entry, COMMON_AGENT); 761158115Sume 762158115Sume if ((lookup_agent != NULL) && 763158115Sume (lookup_agent->type == COMMON_AGENT)) { 764158115Sume c_agent = (struct common_agent *)lookup_agent; 765158115Sume res = c_agent->lookup_func( 766158115Sume read_request->cache_key + 767158115Sume qstate->eid_str_length, 768158115Sume read_request->cache_key_size - 769158115Sume qstate->eid_str_length, 770158115Sume &read_response->data, 771158115Sume &read_response->data_size); 772158115Sume 773158115Sume if (res == NS_SUCCESS) { 774158115Sume read_response->error_code = 0; 775158115Sume configuration_lock_entry( 776158115Sume qstate->config_entry, 777158115Sume CELT_POSITIVE); 778158115Sume cache_write(c_entry, 779158115Sume read_request->cache_key, 780158115Sume read_request->cache_key_size, 781158115Sume read_response->data, 782158115Sume read_response->data_size); 783158115Sume configuration_unlock_entry( 784158115Sume qstate->config_entry, 785158115Sume CELT_POSITIVE); 786158115Sume } else if ((res == NS_NOTFOUND) || 787158115Sume (res == NS_RETURN)) { 788158115Sume configuration_lock_entry( 789158115Sume qstate->config_entry, 790158115Sume CELT_NEGATIVE); 791158115Sume cache_write(neg_c_entry, 792158115Sume read_request->cache_key, 793158115Sume read_request->cache_key_size, 794158115Sume negative_data, 795158115Sume sizeof(negative_data)); 796158115Sume configuration_unlock_entry( 797158115Sume qstate->config_entry, 798158115Sume CELT_NEGATIVE); 799158115Sume 800158115Sume read_response->error_code = 0; 801158115Sume read_response->data = NULL; 802158115Sume read_response->data_size = 0; 803158115Sume } 804158115Sume } 805158115Sume } 806158115Sume 807158115Sume if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || 808158115Sume (qstate->config_entry->common_query_timeout.tv_usec != 0)) 809158115Sume memcpy(&qstate->timeout, 810158115Sume &qstate->config_entry->common_query_timeout, 811158115Sume sizeof(struct timeval)); 812158115Sume } else 813158115Sume read_response->error_code = -1; 814158115Sume 815158115Sumefin: 816158115Sume qstate->kevent_filter = EVFILT_WRITE; 817158115Sume if (read_response->error_code == 0) 818158115Sume qstate->kevent_watermark = sizeof(int) + sizeof(size_t); 819158115Sume else 820158115Sume qstate->kevent_watermark = sizeof(int); 821158115Sume qstate->process_func = on_read_response_write1; 822158115Sume 823158115Sume TRACE_OUT(on_read_request_process); 824158115Sume return (0); 825158115Sume} 826158115Sume 827158115Sumestatic int 828158115Sumeon_read_response_write1(struct query_state *qstate) 829158115Sume{ 830158115Sume struct cache_read_response *read_response; 831158115Sume ssize_t result; 832158115Sume 833158115Sume TRACE_IN(on_read_response_write1); 834158115Sume read_response = get_cache_read_response(&qstate->response); 835158115Sume 836158115Sume result = qstate->write_func(qstate, &read_response->error_code, 837158115Sume sizeof(int)); 838158115Sume 839158115Sume if (read_response->error_code == 0) { 840158115Sume result += qstate->write_func(qstate, &read_response->data_size, 841158115Sume sizeof(size_t)); 842194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 843158115Sume TRACE_OUT(on_read_response_write1); 844158115Sume return (-1); 845158115Sume } 846158115Sume 847158115Sume qstate->kevent_watermark = read_response->data_size; 848158115Sume qstate->process_func = on_read_response_write2; 849158115Sume } else { 850194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 851158115Sume TRACE_OUT(on_read_response_write1); 852158115Sume return (-1); 853158115Sume } 854158115Sume 855158115Sume qstate->kevent_watermark = 0; 856158115Sume qstate->process_func = NULL; 857158115Sume } 858158115Sume 859158115Sume TRACE_OUT(on_read_response_write1); 860158115Sume return (0); 861158115Sume} 862158115Sume 863158115Sumestatic int 864158115Sumeon_read_response_write2(struct query_state *qstate) 865158115Sume{ 866158115Sume struct cache_read_response *read_response; 867158115Sume ssize_t result; 868158115Sume 869158115Sume TRACE_IN(on_read_response_write2); 870158115Sume read_response = get_cache_read_response(&qstate->response); 871158115Sume if (read_response->data_size > 0) { 872158115Sume result = qstate->write_func(qstate, read_response->data, 873158115Sume read_response->data_size); 874194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 875158115Sume TRACE_OUT(on_read_response_write2); 876158115Sume return (-1); 877158115Sume } 878158115Sume } 879158115Sume 880158115Sume finalize_comm_element(&qstate->request); 881158115Sume finalize_comm_element(&qstate->response); 882158115Sume 883158115Sume qstate->kevent_watermark = sizeof(int); 884158115Sume qstate->kevent_filter = EVFILT_READ; 885158115Sume qstate->process_func = on_rw_mapper; 886158115Sume TRACE_OUT(on_read_response_write2); 887158115Sume return (0); 888158115Sume} 889158115Sume 890158115Sume/* 891158115Sume * The functions below are used to process write requests. 892158115Sume * - on_transform_request_read1 and on_transform_request_read2 read the 893158115Sume * request itself 894158115Sume * - on_transform_request_process processes it 895158115Sume * - on_transform_response_write1 sends the response 896158115Sume */ 897158115Sumestatic int 898158115Sumeon_transform_request_read1(struct query_state *qstate) 899158115Sume{ 900158115Sume struct cache_transform_request *transform_request; 901158115Sume ssize_t result; 902158115Sume 903158115Sume TRACE_IN(on_transform_request_read1); 904158115Sume if (qstate->kevent_watermark == 0) 905158115Sume qstate->kevent_watermark = sizeof(size_t) + sizeof(int); 906158115Sume else { 907158115Sume init_comm_element(&qstate->request, CET_TRANSFORM_REQUEST); 908158115Sume transform_request = 909158115Sume get_cache_transform_request(&qstate->request); 910158115Sume 911158115Sume result = qstate->read_func(qstate, 912158115Sume &transform_request->entry_length, sizeof(size_t)); 913158115Sume result += qstate->read_func(qstate, 914158115Sume &transform_request->transformation_type, sizeof(int)); 915158115Sume 916158115Sume if (result != sizeof(size_t) + sizeof(int)) { 917158115Sume TRACE_OUT(on_transform_request_read1); 918158115Sume return (-1); 919158115Sume } 920158115Sume 921158115Sume if ((transform_request->transformation_type != TT_USER) && 922158115Sume (transform_request->transformation_type != TT_ALL)) { 923158115Sume TRACE_OUT(on_transform_request_read1); 924158115Sume return (-1); 925158115Sume } 926158115Sume 927158115Sume if (transform_request->entry_length != 0) { 928158115Sume if (BUFSIZE_INVALID(transform_request->entry_length)) { 929158115Sume TRACE_OUT(on_transform_request_read1); 930158115Sume return (-1); 931158115Sume } 932158115Sume 933194104Sdes transform_request->entry = calloc(1, 934158115Sume transform_request->entry_length + 1); 935158115Sume assert(transform_request->entry != NULL); 936158115Sume 937158115Sume qstate->process_func = on_transform_request_read2; 938158115Sume } else 939158115Sume qstate->process_func = on_transform_request_process; 940158115Sume 941158115Sume qstate->kevent_watermark = transform_request->entry_length; 942158115Sume } 943158115Sume 944158115Sume TRACE_OUT(on_transform_request_read1); 945158115Sume return (0); 946158115Sume} 947158115Sume 948158115Sumestatic int 949158115Sumeon_transform_request_read2(struct query_state *qstate) 950158115Sume{ 951158115Sume struct cache_transform_request *transform_request; 952158115Sume ssize_t result; 953158115Sume 954158115Sume TRACE_IN(on_transform_request_read2); 955158115Sume transform_request = get_cache_transform_request(&qstate->request); 956158115Sume 957158115Sume result = qstate->read_func(qstate, transform_request->entry, 958158115Sume transform_request->entry_length); 959158115Sume 960194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 961158115Sume TRACE_OUT(on_transform_request_read2); 962158115Sume return (-1); 963158115Sume } 964158115Sume 965158115Sume qstate->kevent_watermark = 0; 966158115Sume qstate->process_func = on_transform_request_process; 967158115Sume 968158115Sume TRACE_OUT(on_transform_request_read2); 969158115Sume return (0); 970158115Sume} 971158115Sume 972158115Sumestatic int 973158115Sumeon_transform_request_process(struct query_state *qstate) 974158115Sume{ 975158115Sume struct cache_transform_request *transform_request; 976158115Sume struct cache_transform_response *transform_response; 977158115Sume struct configuration_entry *config_entry; 978158115Sume size_t i, size; 979158115Sume 980158115Sume TRACE_IN(on_transform_request_process); 981158115Sume init_comm_element(&qstate->response, CET_TRANSFORM_RESPONSE); 982158115Sume transform_response = get_cache_transform_response(&qstate->response); 983158115Sume transform_request = get_cache_transform_request(&qstate->request); 984158115Sume 985158115Sume switch (transform_request->transformation_type) { 986158115Sume case TT_USER: 987158115Sume if (transform_request->entry == NULL) { 988158115Sume size = configuration_get_entries_size(s_configuration); 989158115Sume for (i = 0; i < size; ++i) { 990158115Sume config_entry = configuration_get_entry( 991158115Sume s_configuration, i); 992158115Sume 993158115Sume if (config_entry->perform_actual_lookups == 0) 994158115Sume clear_config_entry_part(config_entry, 995158115Sume qstate->eid_str, qstate->eid_str_length); 996158115Sume } 997158115Sume } else { 998158115Sume qstate->config_entry = configuration_find_entry( 999158115Sume s_configuration, transform_request->entry); 1000158115Sume 1001158115Sume if (qstate->config_entry == NULL) { 1002158115Sume LOG_ERR_2("transform_request", 1003158115Sume "can't find configuration" 1004158115Sume " entry '%s'. aborting request", 1005158115Sume transform_request->entry); 1006158115Sume transform_response->error_code = -1; 1007158115Sume goto fin; 1008158115Sume } 1009158115Sume 1010158115Sume if (qstate->config_entry->perform_actual_lookups != 0) { 1011158115Sume LOG_ERR_2("transform_request", 1012158115Sume "can't transform the cache entry %s" 1013158115Sume ", because it ised for actual lookups", 1014158115Sume transform_request->entry); 1015158115Sume transform_response->error_code = -1; 1016158115Sume goto fin; 1017158115Sume } 1018158115Sume 1019158115Sume clear_config_entry_part(qstate->config_entry, 1020158115Sume qstate->eid_str, qstate->eid_str_length); 1021158115Sume } 1022158115Sume break; 1023158115Sume case TT_ALL: 1024158115Sume if (qstate->euid != 0) 1025158115Sume transform_response->error_code = -1; 1026158115Sume else { 1027158115Sume if (transform_request->entry == NULL) { 1028158115Sume size = configuration_get_entries_size( 1029158115Sume s_configuration); 1030158115Sume for (i = 0; i < size; ++i) { 1031158115Sume clear_config_entry( 1032158115Sume configuration_get_entry( 1033158115Sume s_configuration, i)); 1034158115Sume } 1035158115Sume } else { 1036158115Sume qstate->config_entry = configuration_find_entry( 1037158115Sume s_configuration, 1038158115Sume transform_request->entry); 1039158115Sume 1040158115Sume if (qstate->config_entry == NULL) { 1041158115Sume LOG_ERR_2("transform_request", 1042158115Sume "can't find configuration" 1043158115Sume " entry '%s'. aborting request", 1044158115Sume transform_request->entry); 1045158115Sume transform_response->error_code = -1; 1046158115Sume goto fin; 1047158115Sume } 1048158115Sume 1049158115Sume clear_config_entry(qstate->config_entry); 1050158115Sume } 1051158115Sume } 1052158115Sume break; 1053158115Sume default: 1054158115Sume transform_response->error_code = -1; 1055158115Sume } 1056158115Sume 1057158115Sumefin: 1058158115Sume qstate->kevent_watermark = 0; 1059158115Sume qstate->process_func = on_transform_response_write1; 1060158115Sume TRACE_OUT(on_transform_request_process); 1061158115Sume return (0); 1062158115Sume} 1063158115Sume 1064158115Sumestatic int 1065158115Sumeon_transform_response_write1(struct query_state *qstate) 1066158115Sume{ 1067158115Sume struct cache_transform_response *transform_response; 1068158115Sume ssize_t result; 1069158115Sume 1070158115Sume TRACE_IN(on_transform_response_write1); 1071158115Sume transform_response = get_cache_transform_response(&qstate->response); 1072158115Sume result = qstate->write_func(qstate, &transform_response->error_code, 1073158115Sume sizeof(int)); 1074158115Sume if (result != sizeof(int)) { 1075158115Sume TRACE_OUT(on_transform_response_write1); 1076158115Sume return (-1); 1077158115Sume } 1078158115Sume 1079158115Sume finalize_comm_element(&qstate->request); 1080158115Sume finalize_comm_element(&qstate->response); 1081158115Sume 1082158115Sume qstate->kevent_watermark = 0; 1083158115Sume qstate->process_func = NULL; 1084158115Sume TRACE_OUT(on_transform_response_write1); 1085158115Sume return (0); 1086158115Sume} 1087158115Sume 1088158115Sume/* 1089158115Sume * Checks if the client's euid and egid do not differ from its uid and gid. 1090158115Sume * Returns 0 on success. 1091158115Sume */ 1092158115Sumeint 1093158115Sumecheck_query_eids(struct query_state *qstate) 1094158115Sume{ 1095158115Sume 1096158115Sume return ((qstate->uid != qstate->euid) || (qstate->gid != qstate->egid) ? -1 : 0); 1097158115Sume} 1098158115Sume 1099158115Sume/* 1100158115Sume * Uses the qstate fields to process an "alternate" read - when the buffer is 1101158115Sume * too large to be received during one socket read operation 1102158115Sume */ 1103158115Sumessize_t 1104158115Sumequery_io_buffer_read(struct query_state *qstate, void *buf, size_t nbytes) 1105158115Sume{ 1106194096Sdes size_t remaining; 1107158115Sume ssize_t result; 1108158115Sume 1109158115Sume TRACE_IN(query_io_buffer_read); 1110158115Sume if ((qstate->io_buffer_size == 0) || (qstate->io_buffer == NULL)) 1111158115Sume return (-1); 1112158115Sume 1113194096Sdes assert(qstate->io_buffer_p <= 1114194096Sdes qstate->io_buffer + qstate->io_buffer_size); 1115194096Sdes remaining = qstate->io_buffer + qstate->io_buffer_size - 1116194096Sdes qstate->io_buffer_p; 1117194096Sdes if (nbytes < remaining) 1118158115Sume result = nbytes; 1119158115Sume else 1120194096Sdes result = remaining; 1121158115Sume 1122158115Sume memcpy(buf, qstate->io_buffer_p, result); 1123158115Sume qstate->io_buffer_p += result; 1124158115Sume 1125194096Sdes if (remaining == 0) { 1126158115Sume free(qstate->io_buffer); 1127158115Sume qstate->io_buffer = NULL; 1128158115Sume 1129158115Sume qstate->write_func = query_socket_write; 1130158115Sume qstate->read_func = query_socket_read; 1131158115Sume } 1132158115Sume 1133158115Sume TRACE_OUT(query_io_buffer_read); 1134158115Sume return (result); 1135158115Sume} 1136158115Sume 1137158115Sume/* 1138158115Sume * Uses the qstate fields to process an "alternate" write - when the buffer is 1139158115Sume * too large to be sent during one socket write operation 1140158115Sume */ 1141158115Sumessize_t 1142158115Sumequery_io_buffer_write(struct query_state *qstate, const void *buf, 1143158115Sume size_t nbytes) 1144158115Sume{ 1145194096Sdes size_t remaining; 1146158115Sume ssize_t result; 1147158115Sume 1148158115Sume TRACE_IN(query_io_buffer_write); 1149158115Sume if ((qstate->io_buffer_size == 0) || (qstate->io_buffer == NULL)) 1150158115Sume return (-1); 1151158115Sume 1152194096Sdes assert(qstate->io_buffer_p <= 1153194096Sdes qstate->io_buffer + qstate->io_buffer_size); 1154194096Sdes remaining = qstate->io_buffer + qstate->io_buffer_size - 1155194096Sdes qstate->io_buffer_p; 1156194096Sdes if (nbytes < remaining) 1157158115Sume result = nbytes; 1158158115Sume else 1159194096Sdes result = remaining; 1160158115Sume 1161158115Sume memcpy(qstate->io_buffer_p, buf, result); 1162158115Sume qstate->io_buffer_p += result; 1163158115Sume 1164194096Sdes if (remaining == 0) { 1165158115Sume qstate->use_alternate_io = 1; 1166158115Sume qstate->io_buffer_p = qstate->io_buffer; 1167158115Sume 1168158115Sume qstate->write_func = query_socket_write; 1169158115Sume qstate->read_func = query_socket_read; 1170158115Sume } 1171158115Sume 1172158115Sume TRACE_OUT(query_io_buffer_write); 1173158115Sume return (result); 1174158115Sume} 1175158115Sume 1176158115Sume/* 1177158115Sume * The default "read" function, which reads data directly from socket 1178158115Sume */ 1179158115Sumessize_t 1180158115Sumequery_socket_read(struct query_state *qstate, void *buf, size_t nbytes) 1181158115Sume{ 1182158115Sume ssize_t result; 1183158115Sume 1184158115Sume TRACE_IN(query_socket_read); 1185158115Sume if (qstate->socket_failed != 0) { 1186158115Sume TRACE_OUT(query_socket_read); 1187158115Sume return (-1); 1188158115Sume } 1189158115Sume 1190158115Sume result = read(qstate->sockfd, buf, nbytes); 1191194096Sdes if (result < 0 || (size_t)result < nbytes) 1192158115Sume qstate->socket_failed = 1; 1193158115Sume 1194158115Sume TRACE_OUT(query_socket_read); 1195158115Sume return (result); 1196158115Sume} 1197158115Sume 1198158115Sume/* 1199158115Sume * The default "write" function, which writes data directly to socket 1200158115Sume */ 1201158115Sumessize_t 1202158115Sumequery_socket_write(struct query_state *qstate, const void *buf, size_t nbytes) 1203158115Sume{ 1204158115Sume ssize_t result; 1205158115Sume 1206158115Sume TRACE_IN(query_socket_write); 1207158115Sume if (qstate->socket_failed != 0) { 1208158115Sume TRACE_OUT(query_socket_write); 1209158115Sume return (-1); 1210158115Sume } 1211158115Sume 1212158115Sume result = write(qstate->sockfd, buf, nbytes); 1213194096Sdes if (result < 0 || (size_t)result < nbytes) 1214158115Sume qstate->socket_failed = 1; 1215158115Sume 1216158115Sume TRACE_OUT(query_socket_write); 1217158115Sume return (result); 1218158115Sume} 1219158115Sume 1220158115Sume/* 1221158115Sume * Initializes the query_state structure by filling it with the default values. 1222158115Sume */ 1223158115Sumestruct query_state * 1224158115Sumeinit_query_state(int sockfd, size_t kevent_watermark, uid_t euid, gid_t egid) 1225158115Sume{ 1226158115Sume struct query_state *retval; 1227158115Sume 1228158115Sume TRACE_IN(init_query_state); 1229194104Sdes retval = calloc(1, sizeof(*retval)); 1230158115Sume assert(retval != NULL); 1231158115Sume 1232158115Sume retval->sockfd = sockfd; 1233158115Sume retval->kevent_filter = EVFILT_READ; 1234158115Sume retval->kevent_watermark = kevent_watermark; 1235158115Sume 1236158115Sume retval->euid = euid; 1237158115Sume retval->egid = egid; 1238158115Sume retval->uid = retval->gid = -1; 1239158115Sume 1240158115Sume if (asprintf(&retval->eid_str, "%d_%d_", retval->euid, 1241158115Sume retval->egid) == -1) { 1242158115Sume free(retval); 1243158115Sume return (NULL); 1244158115Sume } 1245158115Sume retval->eid_str_length = strlen(retval->eid_str); 1246158115Sume 1247158115Sume init_comm_element(&retval->request, CET_UNDEFINED); 1248158115Sume init_comm_element(&retval->response, CET_UNDEFINED); 1249158115Sume retval->process_func = on_query_startup; 1250158115Sume retval->destroy_func = on_query_destroy; 1251158115Sume 1252158115Sume retval->write_func = query_socket_write; 1253158115Sume retval->read_func = query_socket_read; 1254158115Sume 1255158115Sume get_time_func(&retval->creation_time); 1256272668Sjhb retval->timeout.tv_sec = s_configuration->query_timeout; 1257272668Sjhb retval->timeout.tv_usec = 0; 1258158115Sume 1259158115Sume TRACE_OUT(init_query_state); 1260158115Sume return (retval); 1261158115Sume} 1262158115Sume 1263158115Sumevoid 1264158115Sumedestroy_query_state(struct query_state *qstate) 1265158115Sume{ 1266158115Sume 1267158115Sume TRACE_IN(destroy_query_state); 1268158115Sume if (qstate->eid_str != NULL) 1269158115Sume free(qstate->eid_str); 1270158115Sume 1271158115Sume if (qstate->io_buffer != NULL) 1272158115Sume free(qstate->io_buffer); 1273158115Sume 1274158115Sume qstate->destroy_func(qstate); 1275158115Sume free(qstate); 1276158115Sume TRACE_OUT(destroy_query_state); 1277158115Sume} 1278