return rs->sr_err;
}
+static int
+pc_setpw( Operation *op, struct berval *pwd, cache_manager *cm )
+{
+ struct berval vals[2];
+
+ {
+ const char *text = NULL;
+ BER_BVZERO( &vals[0] );
+ slap_passwd_hash( pwd, &vals[0], &text );
+ if ( BER_BVISEMPTY( &vals[0] )) {
+ Debug( pcache_debug, "pc_setpw: hash failed %s\n",
+ text, 0, 0 );
+ return LDAP_OTHER;
+ }
+ }
+
+ BER_BVZERO( &vals[1] );
+
+ {
+ Modifications mod;
+ SlapReply sr = { REP_RESULT };
+ slap_callback cb = { 0, slap_null_cb, 0, 0 };
+ int rc;
+
+ mod.sml_op = LDAP_MOD_REPLACE;
+ mod.sml_flags = 0;
+ mod.sml_desc = slap_schema.si_ad_userPassword;
+ mod.sml_type = mod.sml_desc->ad_cname;
+ mod.sml_values = vals;
+ mod.sml_nvalues = NULL;
+ mod.sml_numvals = 1;
+ mod.sml_next = NULL;
+
+ op->o_tag = LDAP_REQ_MODIFY;
+ op->orm_modlist = &mod;
+ op->o_bd = &cm->db;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ op->o_callback = &cb;
+ Debug( pcache_debug, "pc_setpw: caching bind for %s\n",
+ op->o_req_dn.bv_val, 0, 0 );
+ rc = op->o_bd->be_modify( op, &sr );
+ ch_free( vals[0].bv_val );
+ return rc;
+ }
+}
+
typedef struct bindcacheinfo {
slap_overinst *on;
CachedQuery *qc;
} bindcacheinfo;
-
+
static int
pc_bind_save( Operation *op, SlapReply *rs )
{
bindcacheinfo *bci = op->o_callback->sc_private;
slap_overinst *on = bci->on;
cache_manager *cm = on->on_bi.bi_private;
- struct berval vals[2];
- const char *text = NULL;
- BER_BVZERO( &vals[0] );
- BER_BVZERO( &vals[1] );
- slap_passwd_hash( &op->orb_cred, &vals[0], &text );
- if ( BER_BVISEMPTY( &vals[0] )) {
- Debug( pcache_debug, "pcache_bind_save: hash failed %s\n",
- text, 0, 0 );
- } else {
- Operation op2 = *op;
- Modifications mod;
- SlapReply sr = { REP_RESULT };
- slap_callback cb = { 0, slap_null_cb, 0, 0 };
-
- mod.sml_op = LDAP_MOD_REPLACE;
- mod.sml_flags = 0;
- mod.sml_desc = slap_schema.si_ad_userPassword;
- mod.sml_type = mod.sml_desc->ad_cname;
- mod.sml_values = vals;
- mod.sml_nvalues = NULL;
- mod.sml_numvals = 1;
- mod.sml_next = NULL;
-
- op2.o_tag = LDAP_REQ_MODIFY;
- op2.orm_modlist = &mod;
- op2.o_bd = &cm->db;
- op2.o_dn = op2.o_bd->be_rootdn;
- op2.o_ndn = op2.o_bd->be_rootndn;
- op2.o_callback = &cb;
- Debug( pcache_debug, "pcache_bind_save: caching bind for %s\n",
- op->o_req_dn.bv_val, 0, 0 );
- if ( op2.o_bd->be_modify( &op2, &sr ) == LDAP_SUCCESS )
- bci->qc->bindref_time = op->o_time + bci->qc->qtemp->bindttr;
- ch_free( vals[0].bv_val );
- }
+ Operation op2 = *op;
+ if ( pc_setpw( &op2, &op->orb_cred, cm ) == LDAP_SUCCESS )
+ bci->qc->bindref_time = op->o_time + bci->qc->qtemp->bindttr;
}
return SLAP_CB_CONTINUE;
}
return SLAP_CB_CONTINUE;
}
+#ifdef PCACHE_CONTROL_PRIVDB
static int
-pcache_op_bind(
+pcache_op_privdb(
Operation *op,
SlapReply *rs )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
cache_manager *cm = on->on_bi.bi_private;
- QueryTemplate *temp;
- Entry *e;
- slap_callback cb = { 0 }, *sc;
- bindinfo bi;
- bindcacheinfo *bci;
- Operation op2;
- int is_priv = 0, rc;
-
-#ifdef PCACHE_CONTROL_PRIVDB
- if ( op->o_ctrlflag[ privDB_cid ] == SLAP_CONTROL_CRITICAL )
- is_priv = 1;
-#endif
+ slap_callback *save_cb;
+ slap_op_t type;
- /* Skip if we're not configured for Binds, and no priv control */
- if ( !cm->cache_binds && !is_priv )
+ /* skip if control is unset */
+ if ( op->o_ctrlflag[ privDB_cid ] != SLAP_CONTROL_CRITICAL ) {
return SLAP_CB_CONTINUE;
+ }
/* The cache DB isn't open yet */
if ( cm->defer_db_open ) {
- if ( !is_priv ) {
- /* Just passthru for now */
- return SLAP_CB_CONTINUE;
- } else {
- send_ldap_error( op, rs, LDAP_UNAVAILABLE,
- "pcachePrivDB: cacheDB not available" );
- return rs->sr_err;
- }
+ send_ldap_error( op, rs, LDAP_UNAVAILABLE,
+ "pcachePrivDB: cacheDB not available" );
+ return rs->sr_err;
}
- if ( is_priv ) {
- int rc;
- slap_callback *save_cb;
+ /* FIXME: might be a little bit exaggerated... */
+ if ( !be_isroot( op ) ) {
+ save_cb = op->o_callback;
+ op->o_callback = NULL;
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "pcachePrivDB: operation not allowed" );
+ op->o_callback = save_cb;
- /* FIXME: might be a little bit exaggerated... */
- if ( !be_isroot( op ) ) {
- save_cb = op->o_callback;
- op->o_callback = NULL;
- send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
- "pcachePrivDB: operation not allowed" );
- op->o_callback = save_cb;
+ return rs->sr_err;
+ }
- return rs->sr_err;
- }
+ /* map tag to operation */
+ type = slap_req2op( op->o_tag );
+ if ( type != SLAP_OP_LAST ) {
+ BI_op_func **func;
+ int rc;
/* execute, if possible */
- if ( cm->db.be_bind != NULL ) {
- op2 = *op;
+ func = &cm->db.be_bind;
+ if ( func[ type ] != NULL ) {
+ Operation op2 = *op;
+
op2.o_bd = &cm->db;
- rc = op2.o_bd->be_bind( &op2, rs );
- if ( rc == LDAP_SUCCESS ) {
+ rc = func[ type ]( &op2, rs );
+ if ( type == SLAP_OP_BIND && rc == LDAP_SUCCESS ) {
op->o_conn->c_authz_cookie = cm->db.be_private;
}
- } else {
- /* otherwise fall back to error */
- save_cb = op->o_callback;
- op->o_callback = NULL;
- send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
- "operation not supported with pcachePrivDB control" );
- op->o_callback = save_cb;
- }
- return rs->sr_err;
+ return rs->sr_err;
+ }
}
+ /* otherwise fall back to error */
+ save_cb = op->o_callback;
+ op->o_callback = NULL;
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "operation not supported with pcachePrivDB control" );
+ op->o_callback = save_cb;
+
+ return rs->sr_err;
+}
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+static int
+pcache_op_bind(
+ Operation *op,
+ SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ cache_manager *cm = on->on_bi.bi_private;
+ QueryTemplate *temp;
+ Entry *e;
+ slap_callback cb = { 0 }, *sc;
+ bindinfo bi;
+ bindcacheinfo *bci;
+ Operation op2;
+ int rc;
+
+#ifdef PCACHE_CONTROL_PRIVDB
+ if ( op->o_ctrlflag[ privDB_cid ] == SLAP_CONTROL_CRITICAL )
+ return pcache_op_privdb( op, rs );
+#endif /* PCACHE_CONTROL_PRIVDB */
+
+ /* Skip if we're not configured for Binds, or cache DB isn't open yet */
+ if ( !cm->cache_binds || cm->defer_db_open )
+ return SLAP_CB_CONTINUE;
+
/* First find a matching template with Bind info */
for ( temp=cm->qm->templates; temp; temp=temp->qmnext ) {
if ( temp->bindttr && dnIsSuffix( &op->o_req_ndn, &temp->bindbase ))
e = NULL;
rc = be_entry_get_rw( &op2, &op->o_req_ndn, NULL, NULL, 0, &e );
if ( rc == LDAP_SUCCESS && e ) {
- int i;
- Attribute *a;
-
bi.bi_flags |= BI_LOOKUP;
op2.ors_filter = pc_bind_attrs( op, e, temp, &op2.ors_filterstr );
be_entry_release_r( &op2, e );
return SLAP_CB_CONTINUE;
}
-#ifdef PCACHE_CONTROL_PRIVDB
-static int
-pcache_op_privdb(
- Operation *op,
- SlapReply *rs )
-{
- slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
- cache_manager *cm = on->on_bi.bi_private;
- slap_callback *save_cb;
- slap_op_t type;
-
- /* skip if control is unset */
- if ( op->o_ctrlflag[ privDB_cid ] != SLAP_CONTROL_CRITICAL ) {
- return SLAP_CB_CONTINUE;
- }
-
- /* The cache DB isn't open yet */
- if ( cm->defer_db_open ) {
- send_ldap_error( op, rs, LDAP_UNAVAILABLE,
- "pcachePrivDB: cacheDB not available" );
- return rs->sr_err;
- }
-
- /* FIXME: might be a little bit exaggerated... */
- if ( !be_isroot( op ) ) {
- save_cb = op->o_callback;
- op->o_callback = NULL;
- send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
- "pcachePrivDB: operation not allowed" );
- op->o_callback = save_cb;
-
- return rs->sr_err;
- }
-
- /* map tag to operation */
- type = slap_req2op( op->o_tag );
- if ( type != SLAP_OP_LAST ) {
- BI_op_func **func;
- int rc;
-
- /* execute, if possible */
- func = &cm->db.be_bind;
- if ( func[ type ] != NULL ) {
- Operation op2 = *op;
-
- op2.o_bd = &cm->db;
-
- rc = func[ type ]( &op2, rs );
- if ( type == SLAP_OP_BIND && rc == LDAP_SUCCESS ) {
- op->o_conn->c_authz_cookie = cm->db.be_private;
- }
-
- return rs->sr_err;
- }
- }
-
- /* otherwise fall back to error */
- save_cb = op->o_callback;
- op->o_callback = NULL;
- send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
- "operation not supported with pcachePrivDB control" );
- op->o_callback = save_cb;
-
- return rs->sr_err;
-}
-#endif /* PCACHE_CONTROL_PRIVDB */
-
static int
pcache_op_search(
Operation *op,
};
#endif /* PCACHE_CONTROL_PRIVDB */
+static struct berval pcache_exop_MODIFY_PASSWD = BER_BVC( LDAP_EXOP_MODIFY_PASSWD );
#ifdef PCACHE_EXOP_QUERY_DELETE
static struct berval pcache_exop_QUERY_DELETE = BER_BVC( PCACHE_EXOP_QUERY_DELETE );
return rs->sr_err;
}
+#endif /* PCACHE_EXOP_QUERY_DELETE */
static int
pcache_op_extended( Operation *op, SlapReply *rs )
}
#endif /* PCACHE_CONTROL_PRIVDB */
+#ifdef PCACHE_EXOP_QUERY_DELETE
if ( bvmatch( &op->ore_reqoid, &pcache_exop_QUERY_DELETE ) ) {
struct berval uuid = BER_BVNULL;
ber_tag_t tag = LBER_DEFAULT;
}
op->o_tmpfree( uuid.bv_val, op->o_tmpmemctx );
+ return rs->sr_err;
}
+#endif /* PCACHE_EXOP_QUERY_DELETE */
- return rs->sr_err;
+ /* We only care if we're configured for Bind caching */
+ if ( bvmatch( &op->ore_reqoid, &pcache_exop_MODIFY_PASSWD ) &&
+ cm->cache_binds ) {
+ /* See if the local entry exists and has a password.
+ * It's too much work to find the matching query, so
+ * we just see if there's a hashed password to update.
+ */
+ Operation op2 = *op;
+ Entry *e = NULL;
+ int rc;
+ int doit = 0;
+
+ op2.o_bd = &cm->db;
+ op2.o_dn = op->o_bd->be_rootdn;
+ op2.o_ndn = op->o_bd->be_rootndn;
+ rc = be_entry_get_rw( &op2, &op->o_req_ndn, NULL,
+ slap_schema.si_ad_userPassword, 0, &e );
+ if ( rc == LDAP_SUCCESS && e ) {
+ /* See if a recognized password is hashed here */
+ Attribute *a = attr_find( e->e_attrs,
+ slap_schema.si_ad_userPassword );
+ if ( a && a->a_vals[0].bv_val[0] == '{' &&
+ lutil_passwd_scheme( a->a_vals[0].bv_val )) {
+ doit = 1;
+ }
+ be_entry_release_r( &op2, e );
+ }
+
+ if ( doit ) {
+ rc = overlay_op_walk( op, rs, op_extended, on->on_info,
+ on->on_next );
+ if ( rc == LDAP_SUCCESS ) {
+ req_pwdexop_s *qpw = &op->oq_pwdexop;
+
+ /* We don't care if it succeeds or not */
+ pc_setpw( &op2, &qpw->rs_new, cm );
+ }
+ return rc;
+ }
+ }
+ return SLAP_CB_CONTINUE;
}
-#endif /* PCACHE_EXOP_QUERY_DELETE */
#ifdef PCACHE_MONITOR
pcache.on_bi.bi_op_add = pcache_op_privdb;
pcache.on_bi.bi_op_delete = pcache_op_privdb;
#endif /* PCACHE_CONTROL_PRIVDB */
-#ifdef PCACHE_EXOP_QUERY_DELETE
pcache.on_bi.bi_extended = pcache_op_extended;
-#elif defined( PCACHE_CONTROL_PRIVDB )
- pcache.on_bi.bi_extended = pcache_op_privdb;
-#endif
pcache.on_bi.bi_chk_controls = pcache_chk_controls;