+ struct berval *bv = NULL;
+
+ if ( op->oq_extended.rs_reqdata != NULL ) {
+ /* no request data should be provided */
+ rs->sr_text = "no request data expected";
+ return rs->sr_err = LDAP_PROTOCOL_ERROR;
+ }
+
+ rs->sr_err = backend_check_restrictions( op, rs,
+ (struct berval *)&slap_EXOP_WHOAMI );
+ if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err;
+
+ /* if auth'd by back-ldap and request is proxied, forward it */
+ if ( op->o_conn->c_authz_backend && !strcmp(op->o_conn->c_authz_backend->be_type, "ldap" ) && !dn_match(&op->o_ndn, &op->o_conn->c_ndn)) {
+ struct ldapconn *lc;
+
+ LDAPControl c, *ctrls[2] = {NULL, NULL};
+ LDAPMessage *res;
+ Operation op2 = *op;
+ ber_int_t msgid;
+
+ ctrls[0] = &c;
+ op2.o_ndn = op->o_conn->c_ndn;
+ lc = ldap_back_getconn(&op2, rs);
+ if (!lc || !ldap_back_dobind( lc, op, rs )) {
+ return -1;
+ }
+ c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
+ c.ldctl_iscritical = 1;
+ c.ldctl_value.bv_val = ch_malloc(op->o_ndn.bv_len+4);
+ c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
+ strcpy(c.ldctl_value.bv_val, "dn:");
+ strcpy(c.ldctl_value.bv_val+3, op->o_ndn.bv_val);
+
+ rs->sr_err = ldap_whoami(lc->ld, ctrls, NULL, &msgid);
+ if (rs->sr_err == LDAP_SUCCESS) {
+ if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
+ ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
+ &rs->sr_err);
+ } else {
+ rs->sr_err = ldap_parse_whoami(lc->ld, res, &bv);
+ ldap_msgfree(res);
+ }
+ }
+ ch_free(c.ldctl_value.bv_val);
+ if (rs->sr_err != LDAP_SUCCESS) {
+ rs->sr_err = ldap_back_map_result(rs);
+ }
+ } else {
+ /* else just do the same as before */
+ bv = (struct berval *) ch_malloc( sizeof(struct berval) );
+ if( op->o_dn.bv_len ) {
+ bv->bv_len = op->o_dn.bv_len + sizeof("dn:")-1;
+ bv->bv_val = ch_malloc( bv->bv_len + 1 );
+ AC_MEMCPY( bv->bv_val, "dn:", sizeof("dn:")-1 );
+ AC_MEMCPY( &bv->bv_val[sizeof("dn:")-1], op->o_dn.bv_val,
+ op->o_dn.bv_len );
+ bv->bv_val[bv->bv_len] = '\0';
+ } else {
+ bv->bv_len = 0;
+ bv->bv_val = NULL;
+ }
+ }