]> git.sur5r.net Git - openldap/commitdiff
add support for local RFC 3062 password modification extended operation (ITS#5656)
authorPierangelo Masarati <ando@openldap.org>
Sat, 20 Sep 2008 15:01:12 +0000 (15:01 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 20 Sep 2008 15:01:12 +0000 (15:01 +0000)
doc/man/man5/slapo-translucent.5
servers/slapd/overlays/translucent.c

index 99d36b1c07f8d8758aa5b2c32bc2372c1e0aa8c5..6a9801c67da420f741a6e18043c92b25836412d8 100644 (file)
@@ -90,7 +90,13 @@ before being returned to the client.
 .TP
 .B translucent_bind_local 
 Enable looking for locally stored credentials for simple bind when binding
-to the remote database fails.
+to the remote database fails.  Disabled by default.
+
+.TP
+.B translucent_pwmod_local
+Enable RFC 3062 Password Modification extended operation on locally stored
+credentials.  The operation only applies to entries that exist in the remote
+database.  Disabled by default.
 
 .SH ACCESS CONTROL
 Access control is delegated to either the remote DSA(s) or to the local database
index c8fc02e7377e1e12684fe59f58ab59db25dc9c1e..a5b4e6a80b5a12391619b4dbfa9993a74a2bb60e 100644 (file)
@@ -42,6 +42,7 @@ typedef struct translucent_info {
        int no_glue;
        int defer_db_open;
        int bind_local;
+       int pwmod_local;
 } translucent_info;
 
 static ConfigLDAPadd translucent_ldadd;
@@ -85,6 +86,12 @@ static ConfigTable translucentcfg[] = {
          "( OLcfgOvAt:14.5 NAME 'olcTranslucentBindLocal' "
          "DESC 'Enable local bind' "
          "SYNTAX OMsBoolean SINGLE-VALUE)", NULL, NULL },
+       { "translucent_pwmod_local", "on|off", 1, 2, 0,
+         ARG_ON_OFF|ARG_OFFSET,
+         (void *)offsetof(translucent_info, pwmod_local),
+         "( OLcfgOvAt:14.6 NAME 'olcTranslucentPwModLocal' "
+         "DESC 'Enable local RFC 3062 Password Modify extended operation' "
+         "SYNTAX OMsBoolean SINGLE-VALUE)", NULL, NULL },
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
 
@@ -103,7 +110,7 @@ static ConfigOCs translucentocs[] = {
          "SUP olcOverlayConfig "
          "MAY ( olcTranslucentStrict $ olcTranslucentNoGlue $"
          " olcTranslucentLocal $ olcTranslucentRemote $"
-         " olcTranslucentBindLocal ) )",
+         " olcTranslucentBindLocal $ olcTranslucentPwModLocal ) )",
          Cft_Overlay, translucentcfg, NULL, translucent_cfadd },
        { "( OLcfgOvOc:14.2 "
          "NAME 'olcTranslucentDatabase' "
@@ -636,6 +643,128 @@ static int translucent_compare(Operation *op, SlapReply *rs) {
        return(rc);
 }
 
+static int translucent_pwmod(Operation *op, SlapReply *rs) {
+       SlapReply nrs = { REP_RESULT };
+       Operation nop;
+
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       translucent_info *ov = on->on_bi.bi_private;
+       const struct berval bv_exop_pwmod = BER_BVC(LDAP_EXOP_MODIFY_PASSWD);
+       Entry *e = NULL, *re = NULL;
+       BackendDB *db;
+       int rc = 0;
+       slap_callback cb = { 0 };
+
+       if (!ov->pwmod_local) {
+               rs->sr_err = LDAP_CONSTRAINT_VIOLATION,
+               rs->sr_text = "attempt to modify password in local database";
+               return rs->sr_err;
+       }
+
+/*
+** fetch entry from the captive backend;
+** if it did not exist, fail;
+** release it, if captive backend supports this;
+**
+*/
+       db = op->o_bd;
+       op->o_bd = &ov->db;
+       rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re);
+       if(rc != LDAP_SUCCESS || re == NULL ) {
+               send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT,
+                       "attempt to modify nonexistent local record");
+               return(rs->sr_err);
+       }
+       op->o_bd = db;
+/*
+** fetch entry from local backend;
+** if it exists:
+**     return CONTINUE;
+*/
+
+       op->o_bd->bd_info = (BackendInfo *) on->on_info;
+       rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e);
+       op->o_bd->bd_info = (BackendInfo *) on;
+
+       if(e && rc == LDAP_SUCCESS) {
+               if(re) {
+                       if(ov->db.bd_info->bi_entry_release_rw) {
+                               op->o_bd = &ov->db;
+                               ov->db.bd_info->bi_entry_release_rw(op, re, 0);
+                               op->o_bd = db;
+                       } else {
+                               entry_free(re);
+                       }
+               }
+               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+               be_entry_release_r(op, e);
+               op->o_bd->bd_info = (BackendInfo *) on;
+               return SLAP_CB_CONTINUE;
+       }
+
+       /* don't leak remote entry copy */
+       if(re) {
+               if(ov->db.bd_info->bi_entry_release_rw) {
+                       op->o_bd = &ov->db;
+                       ov->db.bd_info->bi_entry_release_rw(op, re, 0);
+                       op->o_bd = db;
+               } else {
+                       entry_free(re);
+               }
+       }
+/*
+** glue_parent() for this Entry;
+** call bi_op_add() in local backend;
+**
+*/
+       e = entry_alloc();
+       ber_dupbv( &e->e_name, &op->o_req_dn );
+       ber_dupbv( &e->e_nname, &op->o_req_ndn );
+       e->e_attrs = NULL;
+
+       nop = *op;
+       nop.o_tag = LDAP_REQ_ADD;
+       cb.sc_response = slap_null_cb;
+       nop.oq_add.rs_e = e;
+
+       glue_parent(&nop);
+
+       nop.o_callback = &cb;
+       rc = on->on_info->oi_orig->bi_op_add(&nop, &nrs);
+       if ( nop.ora_e == e ) {
+               entry_free( e );
+       }
+
+       if ( rc == LDAP_SUCCESS ) {
+               return SLAP_CB_CONTINUE;
+       }
+
+       return rc;
+}
+
+static int translucent_exop(Operation *op, SlapReply *rs) {
+       SlapReply nrs = { REP_RESULT };
+
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       translucent_info *ov = on->on_bi.bi_private;
+       const struct berval bv_exop_pwmod = BER_BVC(LDAP_EXOP_MODIFY_PASSWD);
+
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_exop: %s\n",
+               op->o_req_dn.bv_val, 0, 0);
+
+       if(ov->defer_db_open) {
+               send_ldap_error(op, rs, LDAP_UNAVAILABLE,
+                       "remote DB not available");
+               return(rs->sr_err);
+       }
+
+       if ( bvmatch( &bv_exop_pwmod, &op->ore_reqoid ) ) {
+               return translucent_pwmod( op, rs );
+       }
+
+       return SLAP_CB_CONTINUE;
+}
+
 /*
 ** translucent_search_cb()
 **     merge local data with remote data
@@ -1270,6 +1399,7 @@ int translucent_initialize() {
        translucent.on_bi.bi_op_search  = translucent_search;
        translucent.on_bi.bi_op_compare = translucent_compare;
        translucent.on_bi.bi_connection_destroy = translucent_connection_destroy;
+       translucent.on_bi.bi_extended   = translucent_exop;
 
        translucent.on_bi.bi_cf_ocs = translucentocs;
        rc = config_register_schema ( translucentcfg, translucentocs );