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