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: stable/11/usr.sbin/nscd/query.c 319178 2017-05-30 03:30:53Z cy $"); 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); 728319178Scy assert(read_response->data != 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) { 746319177Scy read_response->data = malloc( 747319177Scy read_response->data_size); 748319178Scy assert(read_response->data != NULL); 749319177Scy read_response->error_code = cache_read(neg_c_entry, 750319177Scy read_request->cache_key, 751319177Scy read_request->cache_key_size, 752319177Scy read_response->data, 753319177Scy &read_response->data_size); 754158115Sume } 755158115Sume } 756158115Sume configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE); 757158115Sume 758158115Sume if ((read_response->error_code == -1) && 759158115Sume (qstate->config_entry->perform_actual_lookups != 0)) { 760158115Sume free(read_response->data); 761158115Sume read_response->data = NULL; 762158115Sume read_response->data_size = 0; 763158115Sume 764158115Sume lookup_agent = find_agent(s_agent_table, 765158115Sume read_request->entry, COMMON_AGENT); 766158115Sume 767158115Sume if ((lookup_agent != NULL) && 768158115Sume (lookup_agent->type == COMMON_AGENT)) { 769158115Sume c_agent = (struct common_agent *)lookup_agent; 770158115Sume res = c_agent->lookup_func( 771158115Sume read_request->cache_key + 772158115Sume qstate->eid_str_length, 773158115Sume read_request->cache_key_size - 774158115Sume qstate->eid_str_length, 775158115Sume &read_response->data, 776158115Sume &read_response->data_size); 777158115Sume 778158115Sume if (res == NS_SUCCESS) { 779158115Sume read_response->error_code = 0; 780158115Sume configuration_lock_entry( 781158115Sume qstate->config_entry, 782158115Sume CELT_POSITIVE); 783158115Sume cache_write(c_entry, 784158115Sume read_request->cache_key, 785158115Sume read_request->cache_key_size, 786158115Sume read_response->data, 787158115Sume read_response->data_size); 788158115Sume configuration_unlock_entry( 789158115Sume qstate->config_entry, 790158115Sume CELT_POSITIVE); 791158115Sume } else if ((res == NS_NOTFOUND) || 792158115Sume (res == NS_RETURN)) { 793158115Sume configuration_lock_entry( 794158115Sume qstate->config_entry, 795158115Sume CELT_NEGATIVE); 796158115Sume cache_write(neg_c_entry, 797158115Sume read_request->cache_key, 798158115Sume read_request->cache_key_size, 799158115Sume negative_data, 800158115Sume sizeof(negative_data)); 801158115Sume configuration_unlock_entry( 802158115Sume qstate->config_entry, 803158115Sume CELT_NEGATIVE); 804158115Sume 805158115Sume read_response->error_code = 0; 806158115Sume read_response->data = NULL; 807158115Sume read_response->data_size = 0; 808158115Sume } 809158115Sume } 810158115Sume } 811158115Sume 812158115Sume if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || 813158115Sume (qstate->config_entry->common_query_timeout.tv_usec != 0)) 814158115Sume memcpy(&qstate->timeout, 815158115Sume &qstate->config_entry->common_query_timeout, 816158115Sume sizeof(struct timeval)); 817158115Sume } else 818158115Sume read_response->error_code = -1; 819158115Sume 820158115Sumefin: 821158115Sume qstate->kevent_filter = EVFILT_WRITE; 822158115Sume if (read_response->error_code == 0) 823158115Sume qstate->kevent_watermark = sizeof(int) + sizeof(size_t); 824158115Sume else 825158115Sume qstate->kevent_watermark = sizeof(int); 826158115Sume qstate->process_func = on_read_response_write1; 827158115Sume 828158115Sume TRACE_OUT(on_read_request_process); 829158115Sume return (0); 830158115Sume} 831158115Sume 832158115Sumestatic int 833158115Sumeon_read_response_write1(struct query_state *qstate) 834158115Sume{ 835158115Sume struct cache_read_response *read_response; 836158115Sume ssize_t result; 837158115Sume 838158115Sume TRACE_IN(on_read_response_write1); 839158115Sume read_response = get_cache_read_response(&qstate->response); 840158115Sume 841158115Sume result = qstate->write_func(qstate, &read_response->error_code, 842158115Sume sizeof(int)); 843158115Sume 844158115Sume if (read_response->error_code == 0) { 845158115Sume result += qstate->write_func(qstate, &read_response->data_size, 846158115Sume sizeof(size_t)); 847194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 848158115Sume TRACE_OUT(on_read_response_write1); 849158115Sume return (-1); 850158115Sume } 851158115Sume 852158115Sume qstate->kevent_watermark = read_response->data_size; 853158115Sume qstate->process_func = on_read_response_write2; 854158115Sume } else { 855194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 856158115Sume TRACE_OUT(on_read_response_write1); 857158115Sume return (-1); 858158115Sume } 859158115Sume 860158115Sume qstate->kevent_watermark = 0; 861158115Sume qstate->process_func = NULL; 862158115Sume } 863158115Sume 864158115Sume TRACE_OUT(on_read_response_write1); 865158115Sume return (0); 866158115Sume} 867158115Sume 868158115Sumestatic int 869158115Sumeon_read_response_write2(struct query_state *qstate) 870158115Sume{ 871158115Sume struct cache_read_response *read_response; 872158115Sume ssize_t result; 873158115Sume 874158115Sume TRACE_IN(on_read_response_write2); 875158115Sume read_response = get_cache_read_response(&qstate->response); 876158115Sume if (read_response->data_size > 0) { 877158115Sume result = qstate->write_func(qstate, read_response->data, 878158115Sume read_response->data_size); 879194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 880158115Sume TRACE_OUT(on_read_response_write2); 881158115Sume return (-1); 882158115Sume } 883158115Sume } 884158115Sume 885158115Sume finalize_comm_element(&qstate->request); 886158115Sume finalize_comm_element(&qstate->response); 887158115Sume 888158115Sume qstate->kevent_watermark = sizeof(int); 889158115Sume qstate->kevent_filter = EVFILT_READ; 890158115Sume qstate->process_func = on_rw_mapper; 891158115Sume TRACE_OUT(on_read_response_write2); 892158115Sume return (0); 893158115Sume} 894158115Sume 895158115Sume/* 896158115Sume * The functions below are used to process write requests. 897158115Sume * - on_transform_request_read1 and on_transform_request_read2 read the 898158115Sume * request itself 899158115Sume * - on_transform_request_process processes it 900158115Sume * - on_transform_response_write1 sends the response 901158115Sume */ 902158115Sumestatic int 903158115Sumeon_transform_request_read1(struct query_state *qstate) 904158115Sume{ 905158115Sume struct cache_transform_request *transform_request; 906158115Sume ssize_t result; 907158115Sume 908158115Sume TRACE_IN(on_transform_request_read1); 909158115Sume if (qstate->kevent_watermark == 0) 910158115Sume qstate->kevent_watermark = sizeof(size_t) + sizeof(int); 911158115Sume else { 912158115Sume init_comm_element(&qstate->request, CET_TRANSFORM_REQUEST); 913158115Sume transform_request = 914158115Sume get_cache_transform_request(&qstate->request); 915158115Sume 916158115Sume result = qstate->read_func(qstate, 917158115Sume &transform_request->entry_length, sizeof(size_t)); 918158115Sume result += qstate->read_func(qstate, 919158115Sume &transform_request->transformation_type, sizeof(int)); 920158115Sume 921158115Sume if (result != sizeof(size_t) + sizeof(int)) { 922158115Sume TRACE_OUT(on_transform_request_read1); 923158115Sume return (-1); 924158115Sume } 925158115Sume 926158115Sume if ((transform_request->transformation_type != TT_USER) && 927158115Sume (transform_request->transformation_type != TT_ALL)) { 928158115Sume TRACE_OUT(on_transform_request_read1); 929158115Sume return (-1); 930158115Sume } 931158115Sume 932158115Sume if (transform_request->entry_length != 0) { 933158115Sume if (BUFSIZE_INVALID(transform_request->entry_length)) { 934158115Sume TRACE_OUT(on_transform_request_read1); 935158115Sume return (-1); 936158115Sume } 937158115Sume 938194104Sdes transform_request->entry = calloc(1, 939158115Sume transform_request->entry_length + 1); 940158115Sume assert(transform_request->entry != NULL); 941158115Sume 942158115Sume qstate->process_func = on_transform_request_read2; 943158115Sume } else 944158115Sume qstate->process_func = on_transform_request_process; 945158115Sume 946158115Sume qstate->kevent_watermark = transform_request->entry_length; 947158115Sume } 948158115Sume 949158115Sume TRACE_OUT(on_transform_request_read1); 950158115Sume return (0); 951158115Sume} 952158115Sume 953158115Sumestatic int 954158115Sumeon_transform_request_read2(struct query_state *qstate) 955158115Sume{ 956158115Sume struct cache_transform_request *transform_request; 957158115Sume ssize_t result; 958158115Sume 959158115Sume TRACE_IN(on_transform_request_read2); 960158115Sume transform_request = get_cache_transform_request(&qstate->request); 961158115Sume 962158115Sume result = qstate->read_func(qstate, transform_request->entry, 963158115Sume transform_request->entry_length); 964158115Sume 965194096Sdes if (result != (ssize_t)qstate->kevent_watermark) { 966158115Sume TRACE_OUT(on_transform_request_read2); 967158115Sume return (-1); 968158115Sume } 969158115Sume 970158115Sume qstate->kevent_watermark = 0; 971158115Sume qstate->process_func = on_transform_request_process; 972158115Sume 973158115Sume TRACE_OUT(on_transform_request_read2); 974158115Sume return (0); 975158115Sume} 976158115Sume 977158115Sumestatic int 978158115Sumeon_transform_request_process(struct query_state *qstate) 979158115Sume{ 980158115Sume struct cache_transform_request *transform_request; 981158115Sume struct cache_transform_response *transform_response; 982158115Sume struct configuration_entry *config_entry; 983158115Sume size_t i, size; 984158115Sume 985158115Sume TRACE_IN(on_transform_request_process); 986158115Sume init_comm_element(&qstate->response, CET_TRANSFORM_RESPONSE); 987158115Sume transform_response = get_cache_transform_response(&qstate->response); 988158115Sume transform_request = get_cache_transform_request(&qstate->request); 989158115Sume 990158115Sume switch (transform_request->transformation_type) { 991158115Sume case TT_USER: 992158115Sume if (transform_request->entry == NULL) { 993158115Sume size = configuration_get_entries_size(s_configuration); 994158115Sume for (i = 0; i < size; ++i) { 995158115Sume config_entry = configuration_get_entry( 996158115Sume s_configuration, i); 997158115Sume 998158115Sume if (config_entry->perform_actual_lookups == 0) 999158115Sume clear_config_entry_part(config_entry, 1000158115Sume qstate->eid_str, qstate->eid_str_length); 1001158115Sume } 1002158115Sume } else { 1003158115Sume qstate->config_entry = configuration_find_entry( 1004158115Sume s_configuration, transform_request->entry); 1005158115Sume 1006158115Sume if (qstate->config_entry == NULL) { 1007158115Sume LOG_ERR_2("transform_request", 1008158115Sume "can't find configuration" 1009158115Sume " entry '%s'. aborting request", 1010158115Sume transform_request->entry); 1011158115Sume transform_response->error_code = -1; 1012158115Sume goto fin; 1013158115Sume } 1014158115Sume 1015158115Sume if (qstate->config_entry->perform_actual_lookups != 0) { 1016158115Sume LOG_ERR_2("transform_request", 1017158115Sume "can't transform the cache entry %s" 1018158115Sume ", because it ised for actual lookups", 1019158115Sume transform_request->entry); 1020158115Sume transform_response->error_code = -1; 1021158115Sume goto fin; 1022158115Sume } 1023158115Sume 1024158115Sume clear_config_entry_part(qstate->config_entry, 1025158115Sume qstate->eid_str, qstate->eid_str_length); 1026158115Sume } 1027158115Sume break; 1028158115Sume case TT_ALL: 1029158115Sume if (qstate->euid != 0) 1030158115Sume transform_response->error_code = -1; 1031158115Sume else { 1032158115Sume if (transform_request->entry == NULL) { 1033158115Sume size = configuration_get_entries_size( 1034158115Sume s_configuration); 1035158115Sume for (i = 0; i < size; ++i) { 1036158115Sume clear_config_entry( 1037158115Sume configuration_get_entry( 1038158115Sume s_configuration, i)); 1039158115Sume } 1040158115Sume } else { 1041158115Sume qstate->config_entry = configuration_find_entry( 1042158115Sume s_configuration, 1043158115Sume transform_request->entry); 1044158115Sume 1045158115Sume if (qstate->config_entry == NULL) { 1046158115Sume LOG_ERR_2("transform_request", 1047158115Sume "can't find configuration" 1048158115Sume " entry '%s'. aborting request", 1049158115Sume transform_request->entry); 1050158115Sume transform_response->error_code = -1; 1051158115Sume goto fin; 1052158115Sume } 1053158115Sume 1054158115Sume clear_config_entry(qstate->config_entry); 1055158115Sume } 1056158115Sume } 1057158115Sume break; 1058158115Sume default: 1059158115Sume transform_response->error_code = -1; 1060158115Sume } 1061158115Sume 1062158115Sumefin: 1063158115Sume qstate->kevent_watermark = 0; 1064158115Sume qstate->process_func = on_transform_response_write1; 1065158115Sume TRACE_OUT(on_transform_request_process); 1066158115Sume return (0); 1067158115Sume} 1068158115Sume 1069158115Sumestatic int 1070158115Sumeon_transform_response_write1(struct query_state *qstate) 1071158115Sume{ 1072158115Sume struct cache_transform_response *transform_response; 1073158115Sume ssize_t result; 1074158115Sume 1075158115Sume TRACE_IN(on_transform_response_write1); 1076158115Sume transform_response = get_cache_transform_response(&qstate->response); 1077158115Sume result = qstate->write_func(qstate, &transform_response->error_code, 1078158115Sume sizeof(int)); 1079158115Sume if (result != sizeof(int)) { 1080158115Sume TRACE_OUT(on_transform_response_write1); 1081158115Sume return (-1); 1082158115Sume } 1083158115Sume 1084158115Sume finalize_comm_element(&qstate->request); 1085158115Sume finalize_comm_element(&qstate->response); 1086158115Sume 1087158115Sume qstate->kevent_watermark = 0; 1088158115Sume qstate->process_func = NULL; 1089158115Sume TRACE_OUT(on_transform_response_write1); 1090158115Sume return (0); 1091158115Sume} 1092158115Sume 1093158115Sume/* 1094158115Sume * Checks if the client's euid and egid do not differ from its uid and gid. 1095158115Sume * Returns 0 on success. 1096158115Sume */ 1097158115Sumeint 1098158115Sumecheck_query_eids(struct query_state *qstate) 1099158115Sume{ 1100158115Sume 1101158115Sume return ((qstate->uid != qstate->euid) || (qstate->gid != qstate->egid) ? -1 : 0); 1102158115Sume} 1103158115Sume 1104158115Sume/* 1105158115Sume * Uses the qstate fields to process an "alternate" read - when the buffer is 1106158115Sume * too large to be received during one socket read operation 1107158115Sume */ 1108158115Sumessize_t 1109158115Sumequery_io_buffer_read(struct query_state *qstate, void *buf, size_t nbytes) 1110158115Sume{ 1111194096Sdes size_t remaining; 1112158115Sume ssize_t result; 1113158115Sume 1114158115Sume TRACE_IN(query_io_buffer_read); 1115158115Sume if ((qstate->io_buffer_size == 0) || (qstate->io_buffer == NULL)) 1116158115Sume return (-1); 1117158115Sume 1118194096Sdes assert(qstate->io_buffer_p <= 1119194096Sdes qstate->io_buffer + qstate->io_buffer_size); 1120194096Sdes remaining = qstate->io_buffer + qstate->io_buffer_size - 1121194096Sdes qstate->io_buffer_p; 1122194096Sdes if (nbytes < remaining) 1123158115Sume result = nbytes; 1124158115Sume else 1125194096Sdes result = remaining; 1126158115Sume 1127158115Sume memcpy(buf, qstate->io_buffer_p, result); 1128158115Sume qstate->io_buffer_p += result; 1129158115Sume 1130194096Sdes if (remaining == 0) { 1131158115Sume free(qstate->io_buffer); 1132158115Sume qstate->io_buffer = NULL; 1133158115Sume 1134158115Sume qstate->write_func = query_socket_write; 1135158115Sume qstate->read_func = query_socket_read; 1136158115Sume } 1137158115Sume 1138158115Sume TRACE_OUT(query_io_buffer_read); 1139158115Sume return (result); 1140158115Sume} 1141158115Sume 1142158115Sume/* 1143158115Sume * Uses the qstate fields to process an "alternate" write - when the buffer is 1144158115Sume * too large to be sent during one socket write operation 1145158115Sume */ 1146158115Sumessize_t 1147158115Sumequery_io_buffer_write(struct query_state *qstate, const void *buf, 1148158115Sume size_t nbytes) 1149158115Sume{ 1150194096Sdes size_t remaining; 1151158115Sume ssize_t result; 1152158115Sume 1153158115Sume TRACE_IN(query_io_buffer_write); 1154158115Sume if ((qstate->io_buffer_size == 0) || (qstate->io_buffer == NULL)) 1155158115Sume return (-1); 1156158115Sume 1157194096Sdes assert(qstate->io_buffer_p <= 1158194096Sdes qstate->io_buffer + qstate->io_buffer_size); 1159194096Sdes remaining = qstate->io_buffer + qstate->io_buffer_size - 1160194096Sdes qstate->io_buffer_p; 1161194096Sdes if (nbytes < remaining) 1162158115Sume result = nbytes; 1163158115Sume else 1164194096Sdes result = remaining; 1165158115Sume 1166158115Sume memcpy(qstate->io_buffer_p, buf, result); 1167158115Sume qstate->io_buffer_p += result; 1168158115Sume 1169194096Sdes if (remaining == 0) { 1170158115Sume qstate->use_alternate_io = 1; 1171158115Sume qstate->io_buffer_p = qstate->io_buffer; 1172158115Sume 1173158115Sume qstate->write_func = query_socket_write; 1174158115Sume qstate->read_func = query_socket_read; 1175158115Sume } 1176158115Sume 1177158115Sume TRACE_OUT(query_io_buffer_write); 1178158115Sume return (result); 1179158115Sume} 1180158115Sume 1181158115Sume/* 1182158115Sume * The default "read" function, which reads data directly from socket 1183158115Sume */ 1184158115Sumessize_t 1185158115Sumequery_socket_read(struct query_state *qstate, void *buf, size_t nbytes) 1186158115Sume{ 1187158115Sume ssize_t result; 1188158115Sume 1189158115Sume TRACE_IN(query_socket_read); 1190158115Sume if (qstate->socket_failed != 0) { 1191158115Sume TRACE_OUT(query_socket_read); 1192158115Sume return (-1); 1193158115Sume } 1194158115Sume 1195158115Sume result = read(qstate->sockfd, buf, nbytes); 1196194096Sdes if (result < 0 || (size_t)result < nbytes) 1197158115Sume qstate->socket_failed = 1; 1198158115Sume 1199158115Sume TRACE_OUT(query_socket_read); 1200158115Sume return (result); 1201158115Sume} 1202158115Sume 1203158115Sume/* 1204158115Sume * The default "write" function, which writes data directly to socket 1205158115Sume */ 1206158115Sumessize_t 1207158115Sumequery_socket_write(struct query_state *qstate, const void *buf, size_t nbytes) 1208158115Sume{ 1209158115Sume ssize_t result; 1210158115Sume 1211158115Sume TRACE_IN(query_socket_write); 1212158115Sume if (qstate->socket_failed != 0) { 1213158115Sume TRACE_OUT(query_socket_write); 1214158115Sume return (-1); 1215158115Sume } 1216158115Sume 1217158115Sume result = write(qstate->sockfd, buf, nbytes); 1218194096Sdes if (result < 0 || (size_t)result < nbytes) 1219158115Sume qstate->socket_failed = 1; 1220158115Sume 1221158115Sume TRACE_OUT(query_socket_write); 1222158115Sume return (result); 1223158115Sume} 1224158115Sume 1225158115Sume/* 1226158115Sume * Initializes the query_state structure by filling it with the default values. 1227158115Sume */ 1228158115Sumestruct query_state * 1229158115Sumeinit_query_state(int sockfd, size_t kevent_watermark, uid_t euid, gid_t egid) 1230158115Sume{ 1231158115Sume struct query_state *retval; 1232158115Sume 1233158115Sume TRACE_IN(init_query_state); 1234194104Sdes retval = calloc(1, sizeof(*retval)); 1235158115Sume assert(retval != NULL); 1236158115Sume 1237158115Sume retval->sockfd = sockfd; 1238158115Sume retval->kevent_filter = EVFILT_READ; 1239158115Sume retval->kevent_watermark = kevent_watermark; 1240158115Sume 1241158115Sume retval->euid = euid; 1242158115Sume retval->egid = egid; 1243158115Sume retval->uid = retval->gid = -1; 1244158115Sume 1245158115Sume if (asprintf(&retval->eid_str, "%d_%d_", retval->euid, 1246158115Sume retval->egid) == -1) { 1247158115Sume free(retval); 1248158115Sume return (NULL); 1249158115Sume } 1250158115Sume retval->eid_str_length = strlen(retval->eid_str); 1251158115Sume 1252158115Sume init_comm_element(&retval->request, CET_UNDEFINED); 1253158115Sume init_comm_element(&retval->response, CET_UNDEFINED); 1254158115Sume retval->process_func = on_query_startup; 1255158115Sume retval->destroy_func = on_query_destroy; 1256158115Sume 1257158115Sume retval->write_func = query_socket_write; 1258158115Sume retval->read_func = query_socket_read; 1259158115Sume 1260158115Sume get_time_func(&retval->creation_time); 1261272668Sjhb retval->timeout.tv_sec = s_configuration->query_timeout; 1262272668Sjhb retval->timeout.tv_usec = 0; 1263158115Sume 1264158115Sume TRACE_OUT(init_query_state); 1265158115Sume return (retval); 1266158115Sume} 1267158115Sume 1268158115Sumevoid 1269158115Sumedestroy_query_state(struct query_state *qstate) 1270158115Sume{ 1271158115Sume 1272158115Sume TRACE_IN(destroy_query_state); 1273158115Sume if (qstate->eid_str != NULL) 1274158115Sume free(qstate->eid_str); 1275158115Sume 1276158115Sume if (qstate->io_buffer != NULL) 1277158115Sume free(qstate->io_buffer); 1278158115Sume 1279158115Sume qstate->destroy_func(qstate); 1280158115Sume free(qstate); 1281158115Sume TRACE_OUT(destroy_query_state); 1282158115Sume} 1283