config.c revision 1.1.1.6
1/* $NetBSD: config.c,v 1.1.1.6 2018/02/06 01:53:17 christos Exp $ */ 2 3/* config.c - sock backend configuration file routine */ 4/* $OpenLDAP$ */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2007-2017 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18/* ACKNOWLEDGEMENTS: 19 * This work was initially developed by Brian Candler for inclusion 20 * in OpenLDAP Software. Dynamic config support by Howard Chu. 21 */ 22 23#include <sys/cdefs.h> 24__RCSID("$NetBSD: config.c,v 1.1.1.6 2018/02/06 01:53:17 christos Exp $"); 25 26#include "portable.h" 27 28#include <stdio.h> 29 30#include <ac/string.h> 31#include <ac/socket.h> 32 33#include "slap.h" 34#include "config.h" 35#include "back-sock.h" 36 37static ConfigDriver bs_cf_gen; 38static int sock_over_setup(); 39static slap_response sock_over_response; 40 41enum { 42 BS_EXT = 1, 43 BS_OPS, 44 BS_RESP 45}; 46 47/* The number of overlay-only config attrs */ 48#define NUM_OV_ATTRS 2 49 50static ConfigTable bscfg[] = { 51 { "sockops", "ops", 2, 0, 0, ARG_MAGIC|BS_OPS, 52 bs_cf_gen, "( OLcfgDbAt:7.3 NAME 'olcOvSocketOps' " 53 "DESC 'Operation types to forward' " 54 "EQUALITY caseIgnoreMatch " 55 "SYNTAX OMsDirectoryString )", NULL, NULL }, 56 { "sockresps", "resps", 2, 0, 0, ARG_MAGIC|BS_RESP, 57 bs_cf_gen, "( OLcfgDbAt:7.4 NAME 'olcOvSocketResps' " 58 "DESC 'Response types to forward' " 59 "EQUALITY caseIgnoreMatch " 60 "SYNTAX OMsDirectoryString )", NULL, NULL }, 61 62 { "socketpath", "pathname", 2, 2, 0, ARG_STRING|ARG_OFFSET, 63 (void *)offsetof(struct sockinfo, si_sockpath), 64 "( OLcfgDbAt:7.1 NAME 'olcDbSocketPath' " 65 "DESC 'Pathname for Unix domain socket' " 66 "EQUALITY caseExactMatch " 67 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 68 { "extensions", "ext", 2, 0, 0, ARG_MAGIC|BS_EXT, 69 bs_cf_gen, "( OLcfgDbAt:7.2 NAME 'olcDbSocketExtensions' " 70 "DESC 'binddn, peername, or ssf' " 71 "EQUALITY caseIgnoreMatch " 72 "SYNTAX OMsDirectoryString )", NULL, NULL }, 73 { NULL, NULL } 74}; 75 76static ConfigOCs bsocs[] = { 77 { "( OLcfgDbOc:7.1 " 78 "NAME 'olcDbSocketConfig' " 79 "DESC 'Socket backend configuration' " 80 "SUP olcDatabaseConfig " 81 "MUST olcDbSocketPath " 82 "MAY olcDbSocketExtensions )", 83 Cft_Database, bscfg+NUM_OV_ATTRS }, 84 { NULL, 0, NULL } 85}; 86 87static ConfigOCs osocs[] = { 88 { "( OLcfgDbOc:7.2 " 89 "NAME 'olcOvSocketConfig' " 90 "DESC 'Socket overlay configuration' " 91 "SUP olcOverlayConfig " 92 "MUST olcDbSocketPath " 93 "MAY ( olcDbSocketExtensions $ " 94 " olcOvSocketOps $ olcOvSocketResps ) )", 95 Cft_Overlay, bscfg }, 96 { NULL, 0, NULL } 97}; 98 99#define SOCK_OP_BIND 0x001 100#define SOCK_OP_UNBIND 0x002 101#define SOCK_OP_SEARCH 0x004 102#define SOCK_OP_COMPARE 0x008 103#define SOCK_OP_MODIFY 0x010 104#define SOCK_OP_MODRDN 0x020 105#define SOCK_OP_ADD 0x040 106#define SOCK_OP_DELETE 0x080 107 108#define SOCK_REP_RESULT 0x001 109#define SOCK_REP_SEARCH 0x002 110 111static slap_verbmasks bs_exts[] = { 112 { BER_BVC("binddn"), SOCK_EXT_BINDDN }, 113 { BER_BVC("peername"), SOCK_EXT_PEERNAME }, 114 { BER_BVC("ssf"), SOCK_EXT_SSF }, 115 { BER_BVC("connid"), SOCK_EXT_CONNID }, 116 { BER_BVNULL, 0 } 117}; 118 119static slap_verbmasks ov_ops[] = { 120 { BER_BVC("bind"), SOCK_OP_BIND }, 121 { BER_BVC("unbind"), SOCK_OP_UNBIND }, 122 { BER_BVC("search"), SOCK_OP_SEARCH }, 123 { BER_BVC("compare"), SOCK_OP_COMPARE }, 124 { BER_BVC("modify"), SOCK_OP_MODIFY }, 125 { BER_BVC("modrdn"), SOCK_OP_MODRDN }, 126 { BER_BVC("add"), SOCK_OP_ADD }, 127 { BER_BVC("delete"), SOCK_OP_DELETE }, 128 { BER_BVNULL, 0 } 129}; 130 131static slap_verbmasks ov_resps[] = { 132 { BER_BVC("result"), SOCK_REP_RESULT }, 133 { BER_BVC("search"), SOCK_REP_SEARCH }, 134 { BER_BVNULL, 0 } 135}; 136 137static int 138bs_cf_gen( ConfigArgs *c ) 139{ 140 struct sockinfo *si; 141 int rc; 142 143 if ( c->be && c->table == Cft_Database ) 144 si = c->be->be_private; 145 else if ( c->bi ) 146 si = c->bi->bi_private; 147 else 148 return ARG_BAD_CONF; 149 150 if ( c->op == SLAP_CONFIG_EMIT ) { 151 switch( c->type ) { 152 case BS_EXT: 153 return mask_to_verbs( bs_exts, si->si_extensions, &c->rvalue_vals ); 154 case BS_OPS: 155 return mask_to_verbs( ov_ops, si->si_ops, &c->rvalue_vals ); 156 case BS_RESP: 157 return mask_to_verbs( ov_resps, si->si_resps, &c->rvalue_vals ); 158 } 159 } else if ( c->op == LDAP_MOD_DELETE ) { 160 switch( c->type ) { 161 case BS_EXT: 162 if ( c->valx < 0 ) { 163 si->si_extensions = 0; 164 rc = 0; 165 } else { 166 slap_mask_t dels = 0; 167 rc = verbs_to_mask( c->argc, c->argv, bs_exts, &dels ); 168 if ( rc == 0 ) 169 si->si_extensions ^= dels; 170 } 171 return rc; 172 case BS_OPS: 173 if ( c->valx < 0 ) { 174 si->si_ops = 0; 175 rc = 0; 176 } else { 177 slap_mask_t dels = 0; 178 rc = verbs_to_mask( c->argc, c->argv, ov_ops, &dels ); 179 if ( rc == 0 ) 180 si->si_ops ^= dels; 181 } 182 return rc; 183 case BS_RESP: 184 if ( c->valx < 0 ) { 185 si->si_resps = 0; 186 rc = 0; 187 } else { 188 slap_mask_t dels = 0; 189 rc = verbs_to_mask( c->argc, c->argv, ov_resps, &dels ); 190 if ( rc == 0 ) 191 si->si_resps ^= dels; 192 } 193 return rc; 194 } 195 196 } else { 197 switch( c->type ) { 198 case BS_EXT: 199 return verbs_to_mask( c->argc, c->argv, bs_exts, &si->si_extensions ); 200 case BS_OPS: 201 return verbs_to_mask( c->argc, c->argv, ov_ops, &si->si_ops ); 202 case BS_RESP: 203 return verbs_to_mask( c->argc, c->argv, ov_resps, &si->si_resps ); 204 } 205 } 206 return 1; 207} 208 209int 210sock_back_init_cf( BackendInfo *bi ) 211{ 212 int rc; 213 bi->bi_cf_ocs = bsocs; 214 215 rc = config_register_schema( bscfg, bsocs ); 216 if ( !rc ) 217 rc = sock_over_setup(); 218 return rc; 219} 220 221/* sock overlay wrapper */ 222static slap_overinst sockover; 223 224static int sock_over_db_init( Backend *be, struct config_reply_s *cr ); 225static int sock_over_db_destroy( Backend *be, struct config_reply_s *cr ); 226 227static BI_op_bind *sockfuncs[] = { 228 sock_back_bind, 229 sock_back_unbind, 230 sock_back_search, 231 sock_back_compare, 232 sock_back_modify, 233 sock_back_modrdn, 234 sock_back_add, 235 sock_back_delete 236}; 237 238static const int sockopflags[] = { 239 SOCK_OP_BIND, 240 SOCK_OP_UNBIND, 241 SOCK_OP_SEARCH, 242 SOCK_OP_COMPARE, 243 SOCK_OP_MODIFY, 244 SOCK_OP_MODRDN, 245 SOCK_OP_ADD, 246 SOCK_OP_DELETE 247}; 248 249static int sock_over_op( 250 Operation *op, 251 SlapReply *rs 252) 253{ 254 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 255 void *private = op->o_bd->be_private; 256 slap_callback *sc; 257 struct sockinfo *si; 258 slap_operation_t which; 259 260 switch (op->o_tag) { 261 case LDAP_REQ_BIND: which = op_bind; break; 262 case LDAP_REQ_UNBIND: which = op_unbind; break; 263 case LDAP_REQ_SEARCH: which = op_search; break; 264 case LDAP_REQ_COMPARE: which = op_compare; break; 265 case LDAP_REQ_MODIFY: which = op_modify; break; 266 case LDAP_REQ_MODRDN: which = op_modrdn; break; 267 case LDAP_REQ_ADD: which = op_add; break; 268 case LDAP_REQ_DELETE: which = op_delete; break; 269 default: 270 return SLAP_CB_CONTINUE; 271 } 272 si = on->on_bi.bi_private; 273 if ( !(si->si_ops & sockopflags[which])) 274 return SLAP_CB_CONTINUE; 275 276 op->o_bd->be_private = si; 277 sc = op->o_callback; 278 op->o_callback = NULL; 279 sockfuncs[which]( op, rs ); 280 op->o_bd->be_private = private; 281 op->o_callback = sc; 282 return rs->sr_err; 283} 284 285static int 286sock_over_response( Operation *op, SlapReply *rs ) 287{ 288 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 289 struct sockinfo *si = (struct sockinfo *)on->on_bi.bi_private; 290 FILE *fp; 291 292 if ( rs->sr_type == REP_RESULT ) { 293 if ( !( si->si_resps & SOCK_REP_RESULT )) 294 return SLAP_CB_CONTINUE; 295 } else if ( rs->sr_type == REP_SEARCH ) { 296 if ( !( si->si_resps & SOCK_REP_SEARCH )) 297 return SLAP_CB_CONTINUE; 298 } else 299 return SLAP_CB_CONTINUE; 300 301 if (( fp = opensock( si->si_sockpath )) == NULL ) 302 return SLAP_CB_CONTINUE; 303 304 if ( rs->sr_type == REP_RESULT ) { 305 /* write out the result */ 306 fprintf( fp, "RESULT\n" ); 307 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); 308 sock_print_conn( fp, op->o_conn, si ); 309 fprintf( fp, "code: %d\n", rs->sr_err ); 310 if ( rs->sr_matched ) 311 fprintf( fp, "matched: %s\n", rs->sr_matched ); 312 if (rs->sr_text ) 313 fprintf( fp, "info: %s\n", rs->sr_text ); 314 } else { 315 /* write out the search entry */ 316 int len; 317 fprintf( fp, "ENTRY\n" ); 318 fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); 319 sock_print_conn( fp, op->o_conn, si ); 320 ldap_pvt_thread_mutex_lock( &entry2str_mutex ); 321 fprintf( fp, "%s", entry2str( rs->sr_entry, &len ) ); 322 ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); 323 } 324 fprintf( fp, "\n" ); 325 fclose( fp ); 326 327 return SLAP_CB_CONTINUE; 328} 329 330static int 331sock_over_setup() 332{ 333 int rc; 334 335 sockover.on_bi.bi_type = "sock"; 336 sockover.on_bi.bi_db_init = sock_over_db_init; 337 sockover.on_bi.bi_db_destroy = sock_over_db_destroy; 338 339 sockover.on_bi.bi_op_bind = sock_over_op; 340 sockover.on_bi.bi_op_unbind = sock_over_op; 341 sockover.on_bi.bi_op_search = sock_over_op; 342 sockover.on_bi.bi_op_compare = sock_over_op; 343 sockover.on_bi.bi_op_modify = sock_over_op; 344 sockover.on_bi.bi_op_modrdn = sock_over_op; 345 sockover.on_bi.bi_op_add = sock_over_op; 346 sockover.on_bi.bi_op_delete = sock_over_op; 347 sockover.on_response = sock_over_response; 348 349 sockover.on_bi.bi_cf_ocs = osocs; 350 351 rc = config_register_schema( bscfg, osocs ); 352 if ( rc ) return rc; 353 354 return overlay_register( &sockover ); 355} 356 357static int 358sock_over_db_init( 359 Backend *be, 360 struct config_reply_s *cr 361) 362{ 363 slap_overinst *on = (slap_overinst *)be->bd_info; 364 void *private = be->be_private; 365 void *cf_ocs = be->be_cf_ocs; 366 int rc; 367 368 be->be_private = NULL; 369 rc = sock_back_db_init( be, cr ); 370 on->on_bi.bi_private = be->be_private; 371 be->be_private = private; 372 be->be_cf_ocs = cf_ocs; 373 return rc; 374} 375 376static int 377sock_over_db_destroy( 378 Backend *be, 379 struct config_reply_s *cr 380) 381{ 382 slap_overinst *on = (slap_overinst *)be->bd_info; 383 void *private = be->be_private; 384 int rc; 385 386 be->be_private = on->on_bi.bi_private; 387 rc = sock_back_db_destroy( be, cr ); 388 on->on_bi.bi_private = be->be_private; 389 be->be_private = private; 390 return rc; 391} 392