Back to index

openldap  2.4.31
config.c
Go to the documentation of this file.
00001 /* config.c - sock backend configuration file routine */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2007-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* ACKNOWLEDGEMENTS:
00017  * This work was initially developed by Brian Candler for inclusion
00018  * in OpenLDAP Software. Dynamic config support by Howard Chu.
00019  */
00020 
00021 #include "portable.h"
00022 
00023 #include <stdio.h>
00024 
00025 #include <ac/string.h>
00026 #include <ac/socket.h>
00027 
00028 #include "slap.h"
00029 #include "config.h"
00030 #include "back-sock.h"
00031 
00032 static ConfigDriver bs_cf_gen;
00033 static int sock_over_setup();
00034 static slap_response sock_over_response;
00035 
00036 enum {
00037        BS_EXT = 1,
00038        BS_OPS,
00039        BS_RESP
00040 };
00041 
00042 /* The number of overlay-only config attrs */
00043 #define NUM_OV_ATTRS 2
00044 
00045 static ConfigTable bscfg[] = {
00046        { "sockops", "ops", 2, 0, 0, ARG_MAGIC|BS_OPS,
00047               bs_cf_gen, "( OLcfgDbAt:7.3 NAME 'olcOvSocketOps' "
00048                      "DESC 'Operation types to forward' "
00049                      "EQUALITY caseIgnoreMatch "
00050                      "SYNTAX OMsDirectoryString )", NULL, NULL },
00051        { "sockresps", "resps", 2, 0, 0, ARG_MAGIC|BS_RESP,
00052               bs_cf_gen, "( OLcfgDbAt:7.4 NAME 'olcOvSocketResps' "
00053                      "DESC 'Response types to forward' "
00054                      "EQUALITY caseIgnoreMatch "
00055                      "SYNTAX OMsDirectoryString )", NULL, NULL },
00056 
00057        { "socketpath", "pathname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
00058               (void *)offsetof(struct sockinfo, si_sockpath),
00059               "( OLcfgDbAt:7.1 NAME 'olcDbSocketPath' "
00060                      "DESC 'Pathname for Unix domain socket' "
00061                      "EQUALITY caseExactMatch "
00062                      "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
00063        { "extensions", "ext", 2, 0, 0, ARG_MAGIC|BS_EXT,
00064               bs_cf_gen, "( OLcfgDbAt:7.2 NAME 'olcDbSocketExtensions' "
00065                      "DESC 'binddn, peername, or ssf' "
00066                      "EQUALITY caseIgnoreMatch "
00067                      "SYNTAX OMsDirectoryString )", NULL, NULL },
00068        { NULL, NULL }
00069 };
00070 
00071 static ConfigOCs bsocs[] = {
00072        { "( OLcfgDbOc:7.1 "
00073               "NAME 'olcDbSocketConfig' "
00074               "DESC 'Socket backend configuration' "
00075               "SUP olcDatabaseConfig "
00076               "MUST olcDbSocketPath "
00077               "MAY olcDbSocketExtensions )",
00078                      Cft_Database, bscfg+NUM_OV_ATTRS },
00079        { NULL, 0, NULL }
00080 };
00081 
00082 static ConfigOCs osocs[] = {
00083        { "( OLcfgDbOc:7.2 "
00084               "NAME 'olcOvSocketConfig' "
00085               "DESC 'Socket overlay configuration' "
00086               "SUP olcOverlayConfig "
00087               "MUST olcDbSocketPath "
00088               "MAY ( olcDbSocketExtensions $ "
00089                      " olcOvSocketOps $ olcOvSocketResps ) )",
00090                      Cft_Overlay, bscfg },
00091        { NULL, 0, NULL }
00092 };
00093 
00094 #define SOCK_OP_BIND 0x001
00095 #define SOCK_OP_UNBIND      0x002
00096 #define SOCK_OP_SEARCH      0x004
00097 #define SOCK_OP_COMPARE     0x008
00098 #define SOCK_OP_MODIFY      0x010
00099 #define SOCK_OP_MODRDN      0x020
00100 #define SOCK_OP_ADD         0x040
00101 #define SOCK_OP_DELETE      0x080
00102 
00103 #define SOCK_REP_RESULT     0x001
00104 #define SOCK_REP_SEARCH     0x002
00105 
00106 static slap_verbmasks bs_exts[] = {
00107        { BER_BVC("binddn"), SOCK_EXT_BINDDN },
00108        { BER_BVC("peername"), SOCK_EXT_PEERNAME },
00109        { BER_BVC("ssf"), SOCK_EXT_SSF },
00110        { BER_BVC("connid"), SOCK_EXT_CONNID },
00111        { BER_BVNULL, 0 }
00112 };
00113 
00114 static slap_verbmasks ov_ops[] = {
00115        { BER_BVC("bind"), SOCK_OP_BIND },
00116        { BER_BVC("unbind"), SOCK_OP_UNBIND },
00117        { BER_BVC("search"), SOCK_OP_SEARCH },
00118        { BER_BVC("compare"), SOCK_OP_COMPARE },
00119        { BER_BVC("modify"), SOCK_OP_MODIFY },
00120        { BER_BVC("modrdn"), SOCK_OP_MODRDN },
00121        { BER_BVC("add"), SOCK_OP_ADD },
00122        { BER_BVC("delete"), SOCK_OP_DELETE },
00123        { BER_BVNULL, 0 }
00124 };
00125 
00126 static slap_verbmasks ov_resps[] = {
00127        { BER_BVC("result"), SOCK_REP_RESULT },
00128        { BER_BVC("search"), SOCK_REP_SEARCH },
00129        { BER_BVNULL, 0 }
00130 };
00131 
00132 static int
00133 bs_cf_gen( ConfigArgs *c )
00134 {
00135        struct sockinfo      *si;
00136        int rc;
00137 
00138        if ( c->be && c->table == Cft_Database )
00139               si = c->be->be_private;
00140        else if ( c->bi )
00141               si = c->bi->bi_private;
00142        else
00143               return ARG_BAD_CONF;
00144 
00145        if ( c->op == SLAP_CONFIG_EMIT ) {
00146               switch( c->type ) {
00147               case BS_EXT:
00148                      return mask_to_verbs( bs_exts, si->si_extensions, &c->rvalue_vals );
00149               case BS_OPS:
00150                      return mask_to_verbs( ov_ops, si->si_ops, &c->rvalue_vals );
00151               case BS_RESP:
00152                      return mask_to_verbs( ov_resps, si->si_resps, &c->rvalue_vals );
00153               }
00154        } else if ( c->op == LDAP_MOD_DELETE ) {
00155               switch( c->type ) {
00156               case BS_EXT:
00157                      if ( c->valx < 0 ) {
00158                             si->si_extensions = 0;
00159                             rc = 0;
00160                      } else {
00161                             slap_mask_t dels = 0;
00162                             rc = verbs_to_mask( c->argc, c->argv, bs_exts, &dels );
00163                             if ( rc == 0 )
00164                                    si->si_extensions ^= dels;
00165                      }
00166                      return rc;
00167               case BS_OPS:
00168                      if ( c->valx < 0 ) {
00169                             si->si_ops = 0;
00170                             rc = 0;
00171                      } else {
00172                             slap_mask_t dels = 0;
00173                             rc = verbs_to_mask( c->argc, c->argv, ov_ops, &dels );
00174                             if ( rc == 0 )
00175                                    si->si_ops ^= dels;
00176                      }
00177                      return rc;
00178               case BS_RESP:
00179                      if ( c->valx < 0 ) {
00180                             si->si_resps = 0;
00181                             rc = 0;
00182                      } else {
00183                             slap_mask_t dels = 0;
00184                             rc = verbs_to_mask( c->argc, c->argv, ov_resps, &dels );
00185                             if ( rc == 0 )
00186                                    si->si_resps ^= dels;
00187                      }
00188                      return rc;
00189               }
00190 
00191        } else {
00192               switch( c->type ) {
00193               case BS_EXT:
00194                      return verbs_to_mask( c->argc, c->argv, bs_exts, &si->si_extensions );
00195               case BS_OPS:
00196                      return verbs_to_mask( c->argc, c->argv, ov_ops, &si->si_ops );
00197               case BS_RESP:
00198                      return verbs_to_mask( c->argc, c->argv, ov_resps, &si->si_resps );
00199               }
00200        }
00201        return 1;
00202 }
00203 
00204 int
00205 sock_back_init_cf( BackendInfo *bi )
00206 {
00207        int rc;
00208        bi->bi_cf_ocs = bsocs;
00209 
00210        rc = config_register_schema( bscfg, bsocs );
00211        if ( !rc )
00212               rc = sock_over_setup();
00213        return rc;
00214 }
00215 
00216 /* sock overlay wrapper */
00217 static slap_overinst sockover;
00218 
00219 static int sock_over_db_init( Backend *be, struct config_reply_s *cr );
00220 static int sock_over_db_destroy( Backend *be, struct config_reply_s *cr );
00221 
00222 static BI_op_bind *sockfuncs[] = {
00223        sock_back_bind,
00224        sock_back_unbind,
00225        sock_back_search,
00226        sock_back_compare,
00227        sock_back_modify,
00228        sock_back_modrdn,
00229        sock_back_add,
00230        sock_back_delete
00231 };
00232 
00233 static const int sockopflags[] = {
00234        SOCK_OP_BIND,
00235        SOCK_OP_UNBIND,
00236        SOCK_OP_SEARCH,
00237        SOCK_OP_COMPARE,
00238        SOCK_OP_MODIFY,
00239        SOCK_OP_MODRDN,
00240        SOCK_OP_ADD,
00241        SOCK_OP_DELETE
00242 };
00243 
00244 static int sock_over_op(
00245        Operation *op,
00246        SlapReply *rs
00247 )
00248 {
00249        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
00250        void *private = op->o_bd->be_private;
00251        slap_callback *sc;
00252        struct sockinfo      *si;
00253        slap_operation_t which;
00254 
00255        switch (op->o_tag) {
00256        case LDAP_REQ_BIND:  which = op_bind; break;
00257        case LDAP_REQ_UNBIND:       which = op_unbind; break;
00258        case LDAP_REQ_SEARCH:       which = op_search; break;
00259        case LDAP_REQ_COMPARE:      which = op_compare; break;
00260        case LDAP_REQ_MODIFY:       which = op_modify; break;
00261        case LDAP_REQ_MODRDN:       which = op_modrdn; break;
00262        case LDAP_REQ_ADD:   which = op_add; break;
00263        case LDAP_REQ_DELETE:       which = op_delete; break;
00264        default:
00265               return SLAP_CB_CONTINUE;
00266        }
00267        si = on->on_bi.bi_private;
00268        if ( !(si->si_ops & sockopflags[which]))
00269               return SLAP_CB_CONTINUE;
00270 
00271        op->o_bd->be_private = si;
00272        sc = op->o_callback;
00273        op->o_callback = NULL;
00274        sockfuncs[which]( op, rs );
00275        op->o_bd->be_private = private;
00276        op->o_callback = sc;
00277        return rs->sr_err;
00278 }
00279 
00280 static int
00281 sock_over_response( Operation *op, SlapReply *rs )
00282 {
00283        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
00284        struct sockinfo *si = (struct sockinfo *)on->on_bi.bi_private;
00285        FILE *fp;
00286 
00287        if ( rs->sr_type == REP_RESULT ) {
00288               if ( !( si->si_resps & SOCK_REP_RESULT ))
00289                      return SLAP_CB_CONTINUE;
00290        } else if ( rs->sr_type == REP_SEARCH ) {
00291               if ( !( si->si_resps & SOCK_REP_SEARCH ))
00292                      return SLAP_CB_CONTINUE;
00293        } else
00294               return SLAP_CB_CONTINUE;
00295 
00296        if (( fp = opensock( si->si_sockpath )) == NULL )
00297               return SLAP_CB_CONTINUE;
00298 
00299        if ( rs->sr_type == REP_RESULT ) {
00300               /* write out the result */
00301               fprintf( fp, "RESULT\n" );
00302               fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
00303               sock_print_conn( fp, op->o_conn, si );
00304               fprintf( fp, "code: %d\n", rs->sr_err );
00305               if ( rs->sr_matched )
00306                      fprintf( fp, "matched: %s\n", rs->sr_matched );
00307               if (rs->sr_text )
00308                      fprintf( fp, "info: %s\n", rs->sr_text );
00309        } else {
00310               /* write out the search entry */
00311               int len;
00312               fprintf( fp, "ENTRY\n" );
00313               fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
00314               sock_print_conn( fp, op->o_conn, si );
00315               ldap_pvt_thread_mutex_lock( &entry2str_mutex );
00316               fprintf( fp, "%s", entry2str( rs->sr_entry, &len ) );
00317               ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
00318        }
00319        fprintf( fp, "\n" );
00320        fclose( fp );
00321 
00322        return SLAP_CB_CONTINUE;
00323 }
00324 
00325 static int
00326 sock_over_setup()
00327 {
00328        int rc;
00329 
00330        sockover.on_bi.bi_type = "sock";
00331        sockover.on_bi.bi_db_init = sock_over_db_init;
00332        sockover.on_bi.bi_db_destroy = sock_over_db_destroy;
00333 
00334        sockover.on_bi.bi_op_bind = sock_over_op;
00335        sockover.on_bi.bi_op_unbind = sock_over_op;
00336        sockover.on_bi.bi_op_search = sock_over_op;
00337        sockover.on_bi.bi_op_compare = sock_over_op;
00338        sockover.on_bi.bi_op_modify = sock_over_op;
00339        sockover.on_bi.bi_op_modrdn = sock_over_op;
00340        sockover.on_bi.bi_op_add = sock_over_op;
00341        sockover.on_bi.bi_op_delete = sock_over_op;
00342        sockover.on_response = sock_over_response;
00343 
00344        sockover.on_bi.bi_cf_ocs = osocs;
00345 
00346        rc = config_register_schema( bscfg, osocs );
00347        if ( rc ) return rc;
00348 
00349        return overlay_register( &sockover );
00350 }
00351 
00352 static int
00353 sock_over_db_init(
00354     Backend   *be,
00355        struct config_reply_s *cr
00356 )
00357 {
00358        slap_overinst *on = (slap_overinst *)be->bd_info;
00359        void *private = be->be_private;
00360        int rc;
00361 
00362        be->be_private = NULL;
00363        rc = sock_back_db_init( be, cr );
00364        on->on_bi.bi_private = be->be_private;
00365        be->be_private = private;
00366        return rc;
00367 }
00368 
00369 static int
00370 sock_over_db_destroy(
00371     Backend   *be,
00372        struct config_reply_s *cr
00373 )
00374 {
00375        slap_overinst *on = (slap_overinst *)be->bd_info;
00376        void *private = be->be_private;
00377        int rc;
00378 
00379        be->be_private = on->on_bi.bi_private;
00380        rc = sock_back_db_destroy( be, cr );
00381        on->on_bi.bi_private = be->be_private;
00382        be->be_private = private;
00383        return rc;
00384 }