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