/** BEGIN COPYRIGHT BLOCK * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. * Copyright (C) 2005 Red Hat, Inc. * All rights reserved. * * License: GPL (version 3 or any later version). * See LICENSE for details. * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H # include #endif #include "cb.h" /* * Perform a modrdn operation * * Returns: * 0 - success * <0 - fail * */ int chaining_back_modrdn ( Slapi_PBlock *pb ) { cb_outgoing_conn *cnx; Slapi_Backend *be; cb_backend_instance *cb; LDAPControl **ctrls, **serverctrls; LDAPMessage *res; LDAP *ld = NULL; Slapi_DN *newsuperior = NULL; Slapi_DN *sdn = NULL; char **referrals = NULL; char *matched_msg, *error_msg; char *ndn = NULL; char *newrdn = NULL; char *cnxerrbuf = NULL; time_t endtime = 0; int deleteoldrdn = 0; int rc, parse_rc, msgid, i; if ( LDAP_SUCCESS != (rc=cb_forward_operation(pb) )) { cb_send_ldap_result( pb, rc, NULL, "Chaining forbidden", 0, NULL ); return -1; } slapi_pblock_get( pb, SLAPI_BACKEND, &be ); cb = cb_get_instance(be); cb_update_monitor_info(pb,cb,SLAPI_OPERATION_MODRDN); /* Check wether the chaining BE is available or not */ if ( cb_check_availability( cb, pb ) == FARMSERVER_UNAVAILABLE ){ return -1; } slapi_pblock_get( pb, SLAPI_MODRDN_TARGET_SDN, &sdn ); if (NULL == sdn) { cb_send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "Null target DN", 0, NULL); return -1; } /* newrdn is passed to ldap_rename, which does not require case-ignored * newrdn. */ slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn ); slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior ); slapi_pblock_get( pb, SLAPI_MODRDN_DELOLDRDN, &deleteoldrdn ); ndn = (char *)slapi_sdn_get_ndn(sdn); if (cb->local_acl && !cb->associated_be_is_disabled) { /* * Check local acls * Keep in mind We don't have the entry for acl evaluation */ char * errbuf=NULL; Slapi_Entry *te = slapi_entry_alloc(); slapi_entry_set_sdn(te, sdn); /* sdn: copied */ rc = cb_access_allowed (pb, te, NULL, NULL, SLAPI_ACL_WRITE,&errbuf); slapi_entry_free(te); if ( rc != LDAP_SUCCESS ) { cb_send_ldap_result( pb, rc, NULL, errbuf, 0, NULL ); slapi_ch_free_string(&errbuf); return -1; } } /* * Grab a connection handle */ rc = cb_get_connection(cb->pool, &ld, &cnx, NULL, &cnxerrbuf); if (LDAP_SUCCESS != rc) { static int warned_get_conn = 0; if (!warned_get_conn) { slapi_log_error(SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, "cb_get_connection failed (%d) %s\n", rc, ldap_err2string(rc)); warned_get_conn = 1; } cb_send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, cnxerrbuf, 0, NULL); slapi_ch_free_string(&cnxerrbuf); /* ping the farm. * If the farm is unreachable, we increment the counter */ cb_ping_farm(cb, NULL, 0); return -1; } /* * Control management */ if ( (rc = cb_update_controls( pb,ld,&ctrls,CB_UPDATE_CONTROLS_ADDAUTH )) != LDAP_SUCCESS ) { cb_send_ldap_result( pb, rc, NULL,NULL, 0, NULL); cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc)); return -1; } if ( slapi_op_abandoned( pb )) { cb_release_op_connection(cb->pool,ld,0); ldap_controls_free(ctrls); return -1; } /* heart-beat management */ if (cb->max_idle_time>0) endtime=current_time() + cb->max_idle_time; /* * Call the backend preoperation plugins */ if((rc = slapi_plugin_call_preop_be_plugins(pb, SLAPI_PLUGIN_MODRDN_OP))){ slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, "modrdn (%s): pre betxn failed, error (%d)\n",ndn,rc); cb_release_op_connection(cb->pool,ld,0); ldap_controls_free(ctrls); return -1; } /* * Send LDAP operation to the remote host */ rc = ldap_rename ( ld, ndn, newrdn, slapi_sdn_get_dn(newsuperior), deleteoldrdn, ctrls, NULL, &msgid ); ldap_controls_free(ctrls); if ( rc != LDAP_SUCCESS ) { cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, ldap_err2string(rc), 0, NULL); cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc)); return -1; } while ( 1 ) { if (cb_check_forward_abandon(cb,pb,ld,msgid)) { return -1; } rc = ldap_result( ld, msgid, 0, &cb->abandon_timeout, &res ); switch ( rc ) { case -1: cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, ldap_err2string(rc), 0, NULL); cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc)); ldap_msgfree(res); return -1; case 0: if ((rc=cb_ping_farm(cb,cnx,endtime)) != LDAP_SUCCESS) { /* does not respond. give up and return a error to the client. */ /*cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL, ldap_err2string(rc), 0, NULL);*/ cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL, "FARM SERVER TEMPORARY UNAVAILABLE", 0, NULL); cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc)); ldap_msgfree(res); return -1; } #ifdef CB_YIELD DS_Sleep(PR_INTERVAL_NO_WAIT); #endif break; default: matched_msg=error_msg=NULL; parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, &error_msg, &referrals, &serverctrls, 1 ); if ( parse_rc != LDAP_SUCCESS ) { static int warned_parse_rc = 0; if (!warned_parse_rc) { slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, "%s%s%s\n", matched_msg?matched_msg:"", (matched_msg&&(*matched_msg!='\0'))?": ":"", ldap_err2string(parse_rc)); warned_parse_rc = 1; } cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, ENDUSERMSG, 0, NULL ); cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(parse_rc)); slapi_ch_free_string(&matched_msg); slapi_ch_free_string(&error_msg); ldap_controls_free(serverctrls); charray_free(referrals); return -1; } if ( rc != LDAP_SUCCESS ) { struct berval ** refs = referrals2berval(referrals); static int warned_rc = 0; if (!warned_rc && error_msg) { slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, "%s%s%s\n", matched_msg?matched_msg:"", (matched_msg&&(*matched_msg!='\0'))?": ":"", error_msg ); warned_rc = 1; } cb_send_ldap_result( pb, rc, matched_msg, ENDUSERMSG, 0, refs); cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc)); slapi_ch_free_string(&matched_msg); slapi_ch_free_string(&error_msg); if (refs) ber_bvecfree(refs); charray_free(referrals); ldap_controls_free(serverctrls); return -1; } cb_release_op_connection(cb->pool,ld,0); /* Call the backend postoperation plugins */ if((rc = slapi_plugin_call_postop_be_plugins(pb, SLAPI_PLUGIN_MODRDN_OP))){ slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, "modrdn (%s): post betxn failed, error (%d)\n",ndn,rc); } /* Add control response sent by the farm server */ for (i=0; serverctrls && serverctrls[i]; i++) slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, serverctrls[i]); ldap_controls_free(serverctrls); slapi_ch_free_string(&matched_msg); slapi_ch_free_string(&error_msg); charray_free(referrals); cb_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL ); return 0; } } /* Never reached */ /* return 0; */ }