]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldap/extended.c
import fix to ITS#4964
[openldap] / servers / slapd / back-ldap / extended.c
index c17cb5b7a25177be136ce3f640c26495215ecf8e..68acea97890ae55a0f442d1327a5e4718cd81233 100644 (file)
 #include "back-ldap.h"
 #include "lber_pvt.h"
 
-static BI_op_extended ldap_back_exop_passwd;
-static BI_op_extended ldap_back_exop_generic;
+typedef int (ldap_back_exop_f)( Operation *op, SlapReply *rs, ldapconn_t **lc );
+
+static ldap_back_exop_f ldap_back_exop_passwd;
+static ldap_back_exop_f ldap_back_exop_generic;
 
 static struct exop {
-       struct berval   oid;
-       BI_op_extended  *extended;
+       struct berval           oid;
+       ldap_back_exop_f        *extended;
 } exop_table[] = {
        { BER_BVC(LDAP_EXOP_MODIFY_PASSWD),     ldap_back_exop_passwd },
        { BER_BVNULL, NULL }
 };
 
 static int
-ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
+ldap_back_extended_one( Operation *op, SlapReply *rs, ldap_back_exop_f exop )
 {
        ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
 
@@ -68,7 +70,7 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop )
                goto done;
        }
 
-       rc = exop( op, rs );
+       rc = exop( op, rs, &lc );
 
        if ( op->o_ctrls && op->o_ctrls != oldctrls ) {
                free( op->o_ctrls[ 0 ] );
@@ -106,30 +108,83 @@ ldap_back_extended(
 
 static int
 ldap_back_exop_passwd(
-               Operation       *op,
-               SlapReply       *rs )
+       Operation       *op,
+       SlapReply       *rs,
+       ldapconn_t      **lcp )
 {
        ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
 
-       ldapconn_t      *lc = NULL;
+       ldapconn_t      *lc = *lcp;
        req_pwdexop_s   *qpw = &op->oq_pwdexop;
        LDAPMessage     *res;
        ber_int_t       msgid;
-       int             rc, isproxy;
+       int             rc, isproxy, freedn = 0;
        int             do_retry = 1;
-       char *text = NULL;
+       char            *text = NULL;
+       struct berval   dn = op->o_req_dn,
+                       ndn = op->o_req_ndn;
 
-       if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return -1;
+       assert( lc != NULL );
+
+       if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) {
+               /* NOTE: most of this code is mutuated
+                * from slap_passwd_parse(); we can't call
+                * that function since now the request data
+                * has been destroyed by NULL-terminating
+                * the bervals.  Luckily enough, we only need
+                * the first berval... */
+
+               ber_tag_t tag;
+               ber_len_t len = -1;
+               BerElementBuffer berbuf;
+               BerElement *ber = (BerElement *)&berbuf;
+
+               struct berval   tmpid = BER_BVNULL;
+
+               if ( op->ore_reqdata->bv_len == 0 ) {
+                       return LDAP_PROTOCOL_ERROR;
+               }
+
+               /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
+               ber_init2( ber, op->ore_reqdata, 0 );
+
+               tag = ber_scanf( ber, "{" /*}*/ );
+
+               if ( tag == LBER_ERROR ) {
+                       return LDAP_PROTOCOL_ERROR;
+               }
+
+               tag = ber_peek_tag( ber, &len );
+               if ( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) {
+                       tag = ber_scanf( ber, "m", &tmpid );
+
+                       if ( tag == LBER_ERROR ) {
+                               return LDAP_PROTOCOL_ERROR;
+                       }
+               }
+
+               if ( !BER_BVISEMPTY( &tmpid ) ) {
+                       rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn,
+                               &ndn, op->o_tmpmemctx );
+                       if ( rs->sr_err != LDAP_SUCCESS ) {
+                               /* should have been successfully parsed earlier! */
+                               return rs->sr_err;
+                       }
+                       freedn = 1;
+
+               } else {
+                       dn = op->o_dn;
+                       ndn = op->o_ndn;
+               }
        }
 
-       isproxy = ber_bvcmp( &op->o_req_ndn, &op->o_ndn );
+       isproxy = ber_bvcmp( &ndn, &op->o_ndn );
 
        Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_passwd(\"%s\")%s\n",
-               op->o_req_dn.bv_val, isproxy ? " (proxy)" : "", 0 );
+               dn.bv_val, isproxy ? " (proxy)" : "", 0 );
 
 retry:
-       rc = ldap_passwd( lc->lc_ld, isproxy ? &op->o_req_dn : NULL,
+       rc = ldap_passwd( lc->lc_ld, isproxy ? &dn : NULL,
                qpw->rs_old.bv_val ? &qpw->rs_old : NULL,
                qpw->rs_new.bv_val ? &qpw->rs_new : NULL,
                op->o_ctrls, NULL, &msgid );
@@ -214,6 +269,11 @@ retry:
                ldap_back_quarantine( op, rs );
        }
 
+       if ( freedn ) {
+               op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
+               op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
+       }
+
        /* these have to be freed anyway... */
        if ( rs->sr_matched ) {
                free( (char *)rs->sr_matched );
@@ -225,8 +285,9 @@ retry:
                rs->sr_text = NULL;
        }
 
-       if ( lc != NULL ) {
-               ldap_back_release_conn( li, lc );
+       /* in case, cleanup handler */
+       if ( lc == NULL ) {
+               *lcp = NULL;
        }
 
        return rc;
@@ -235,20 +296,19 @@ retry:
 static int
 ldap_back_exop_generic(
        Operation       *op,
-       SlapReply       *rs )
+       SlapReply       *rs,
+       ldapconn_t      **lcp )
 {
        ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
 
-       ldapconn_t      *lc = NULL;
+       ldapconn_t      *lc = *lcp;
        LDAPMessage     *res;
        ber_int_t       msgid;
        int             rc;
        int             do_retry = 1;
-       char *text = NULL;
+       char            *text = NULL;
 
-       if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return -1;
-       }
+       assert( lc != NULL );
 
        Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_generic(%s, \"%s\")\n",
                op->ore_reqoid.bv_val, op->o_req_dn.bv_val, 0 );
@@ -335,8 +395,9 @@ retry:
                rs->sr_text = NULL;
        }
 
-       if ( lc != NULL ) {
-               ldap_back_release_conn( li, lc );
+       /* in case, cleanup handler */
+       if ( lc == NULL ) {
+               *lcp = NULL;
        }
 
        return rc;