From: Pierangelo Masarati Date: Sat, 19 May 2007 14:08:49 +0000 (+0000) Subject: re-parse ID from passmod request, if necessary (ultimately fixes ITS#4964, along... X-Git-Tag: OPENLDAP_REL_ENG_2_4_MP~454 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=43367e162e727b8de985d0914759d2f47bfd97e4;p=openldap re-parse ID from passmod request, if necessary (ultimately fixes ITS#4964, along with fix to ITS#4973) --- diff --git a/servers/slapd/back-ldap/extended.c b/servers/slapd/back-ldap/extended.c index 38dbfcd711..febfffacab 100644 --- a/servers/slapd/back-ldap/extended.c +++ b/servers/slapd/back-ldap/extended.c @@ -28,19 +28,21 @@ #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 ); @@ -204,6 +259,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 ); @@ -215,8 +275,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; @@ -225,20 +286,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 ); @@ -315,8 +375,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;