X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-ldap%2Fextended.c;h=b0cc19fb48d1dee590bc7a0a82a575c5016df261;hb=473e2c997f6b1f226d35da186db8033c922001f3;hp=12db3fce16f3da297462fa96878e7be25a5c6366;hpb=da6d9eb0463255782f3fa70c61fd958d94c048cf;p=openldap diff --git a/servers/slapd/back-ldap/extended.c b/servers/slapd/back-ldap/extended.c index 12db3fce16..b0cc19fb48 100644 --- a/servers/slapd/back-ldap/extended.c +++ b/servers/slapd/back-ldap/extended.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2007 The OpenLDAP Foundation. + * Copyright 2003-2011 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,24 +28,26 @@ #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; ldapconn_t *lc = NULL; - LDAPControl **oldctrls = NULL; + LDAPControl **ctrls = NULL, **oldctrls = NULL; int rc; /* FIXME: this needs to be called here, so it is @@ -56,9 +58,8 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop ) return -1; } - oldctrls = op->o_ctrls; - if ( ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &op->o_ctrls ) ) + ctrls = op->o_ctrls; + if ( ldap_back_controls_add( op, rs, lc, &ctrls ) ) { op->o_ctrls = oldctrls; send_ldap_extended( op, rs ); @@ -68,17 +69,15 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop ) goto done; } - rc = exop( op, rs ); + op->o_ctrls = ctrls; + rc = exop( op, rs, &lc ); - if ( op->o_ctrls && op->o_ctrls != oldctrls ) { - free( op->o_ctrls[ 0 ] ); - free( op->o_ctrls ); - } op->o_ctrls = oldctrls; + (void)ldap_back_controls_free( op, rs, &ctrls ); done:; if ( lc != NULL ) { - ldap_back_release_conn( op, rs, lc ); + ldap_back_release_conn( li, lc ); } return rc; @@ -91,6 +90,9 @@ ldap_back_extended( { int i; + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ + for ( i = 0; exop_table[i].extended != NULL; i++ ) { if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) ) { @@ -106,36 +108,94 @@ 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 ); + assert( rs->sr_ctrls == NULL ); + + if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) { + /* NOTE: most of this code is mutated + * from slap_passwd_parse(); + * But here 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_get_stringbv( ber, &tmpid, LBER_BV_NOTERM ); + + if ( tag == LBER_ERROR ) { + return LDAP_PROTOCOL_ERROR; + } + } + + if ( !BER_BVISEMPTY( &tmpid ) ) { + char idNull = tmpid.bv_val[tmpid.bv_len]; + tmpid.bv_val[tmpid.bv_len] = '\0'; + rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn, + &ndn, op->o_tmpmemctx ); + tmpid.bv_val[tmpid.bv_len] = idNull; + 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 ); if ( rc == LDAP_SUCCESS ) { - if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) { + /* TODO: set timeout? */ + /* by now, make sure no timeout is used (ITS#6282) */ + struct timeval tv = { -1, 0 }; + if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) { ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc ); rs->sr_err = rc; @@ -151,7 +211,7 @@ retry: rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, (char **)&rs->sr_matched, &text, - NULL, NULL, 0 ); + NULL, &rs->sr_ctrls, 0 ); if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { @@ -204,19 +264,30 @@ 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 ); rs->sr_matched = NULL; } + if ( rs->sr_ctrls ) { + ldap_controls_free( rs->sr_ctrls ); + rs->sr_ctrls = NULL; + } + if ( text ) { free( text ); rs->sr_text = NULL; } - if ( lc != NULL ) { - ldap_back_release_conn( op, rs, lc ); + /* in case, cleanup handler */ + if ( lc == NULL ) { + *lcp = NULL; } return rc; @@ -225,23 +296,22 @@ 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; - - if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { - return -1; - } + char *text = NULL; Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_generic(%s, \"%s\")\n", op->ore_reqoid.bv_val, op->o_req_dn.bv_val, 0 ); + assert( lc != NULL ); + assert( rs->sr_ctrls == NULL ); retry: rc = ldap_extended_operation( lc->lc_ld, @@ -249,7 +319,10 @@ retry: op->o_ctrls, NULL, &msgid ); if ( rc == LDAP_SUCCESS ) { - if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) { + /* TODO: set timeout? */ + /* by now, make sure no timeout is used (ITS#6282) */ + struct timeval tv = { -1, 0 }; + if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) { ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc ); rs->sr_err = rc; @@ -265,7 +338,7 @@ retry: rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, (char **)&rs->sr_matched, &text, - NULL, NULL, 0 ); + NULL, &rs->sr_ctrls, 0 ); if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { rc = ldap_parse_extended_result( lc->lc_ld, res, @@ -310,15 +383,20 @@ retry: rs->sr_matched = NULL; } + if ( rs->sr_ctrls ) { + ldap_controls_free( rs->sr_ctrls ); + rs->sr_ctrls = NULL; + } + if ( text ) { free( text ); rs->sr_text = NULL; } - if ( lc != NULL ) { - ldap_back_release_conn( op, rs, lc ); + /* in case, cleanup handler */ + if ( lc == NULL ) { + *lcp = NULL; } return rc; } -