1 /* $NetBSD: referral.c,v 1.1.1.1 2014/05/28 09:58:50 tron Exp $ */ 2 3 /* referral.c - MDB backend referral handler */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2000-2014 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19 #include "portable.h" 20 #include <stdio.h> 21 #include <ac/string.h> 22 23 #include "back-mdb.h" 24 25 int 26 mdb_referrals( Operation *op, SlapReply *rs ) 27 { 28 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; 29 Entry *e = NULL; 30 int rc = LDAP_SUCCESS; 31 32 MDB_txn *rtxn; 33 mdb_op_info opinfo = {0}, *moi = &opinfo; 34 35 if( op->o_tag == LDAP_REQ_SEARCH ) { 36 /* let search take care of itself */ 37 return rc; 38 } 39 40 if( get_manageDSAit( op ) ) { 41 /* let op take care of DSA management */ 42 return rc; 43 } 44 45 rc = mdb_opinfo_get(op, mdb, 1, &moi); 46 switch(rc) { 47 case 0: 48 break; 49 default: 50 return LDAP_OTHER; 51 } 52 53 rtxn = moi->moi_txn; 54 55 /* get entry */ 56 rc = mdb_dn2entry( op, rtxn, &op->o_req_ndn, &e, 1 ); 57 58 switch(rc) { 59 case MDB_NOTFOUND: 60 case 0: 61 break; 62 case LDAP_BUSY: 63 rs->sr_text = "ldap server busy"; 64 goto done; 65 default: 66 Debug( LDAP_DEBUG_TRACE, 67 LDAP_XSTRING(mdb_referrals) 68 ": dn2entry failed: %s (%d)\n", 69 mdb_strerror(rc), rc, 0 ); 70 rs->sr_text = "internal error"; 71 rc = LDAP_OTHER; 72 goto done; 73 } 74 75 if ( rc == MDB_NOTFOUND ) { 76 rc = LDAP_SUCCESS; 77 rs->sr_matched = NULL; 78 if ( e != NULL ) { 79 Debug( LDAP_DEBUG_TRACE, 80 LDAP_XSTRING(mdb_referrals) 81 ": tag=%lu target=\"%s\" matched=\"%s\"\n", 82 (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val ); 83 84 if( is_entry_referral( e ) ) { 85 BerVarray ref = get_entry_referrals( op, e ); 86 rc = LDAP_OTHER; 87 rs->sr_ref = referral_rewrite( ref, &e->e_name, 88 &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 89 ber_bvarray_free( ref ); 90 if ( rs->sr_ref ) { 91 rs->sr_matched = ber_strdup_x( 92 e->e_name.bv_val, op->o_tmpmemctx ); 93 } 94 } 95 96 mdb_entry_return( op, e ); 97 e = NULL; 98 } 99 100 if( rs->sr_ref != NULL ) { 101 /* send referrals */ 102 rc = rs->sr_err = LDAP_REFERRAL; 103 send_ldap_result( op, rs ); 104 ber_bvarray_free( rs->sr_ref ); 105 rs->sr_ref = NULL; 106 } else if ( rc != LDAP_SUCCESS ) { 107 rs->sr_text = rs->sr_matched ? "bad referral object" : NULL; 108 } 109 110 if (rs->sr_matched) { 111 op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx ); 112 rs->sr_matched = NULL; 113 } 114 goto done; 115 } 116 117 if ( is_entry_referral( e ) ) { 118 /* entry is a referral */ 119 BerVarray refs = get_entry_referrals( op, e ); 120 rs->sr_ref = referral_rewrite( 121 refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 122 123 Debug( LDAP_DEBUG_TRACE, 124 LDAP_XSTRING(mdb_referrals) 125 ": tag=%lu target=\"%s\" matched=\"%s\"\n", 126 (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val ); 127 128 rs->sr_matched = e->e_name.bv_val; 129 if( rs->sr_ref != NULL ) { 130 rc = rs->sr_err = LDAP_REFERRAL; 131 send_ldap_result( op, rs ); 132 ber_bvarray_free( rs->sr_ref ); 133 rs->sr_ref = NULL; 134 } else { 135 rc = LDAP_OTHER; 136 rs->sr_text = "bad referral object"; 137 } 138 139 rs->sr_matched = NULL; 140 ber_bvarray_free( refs ); 141 } 142 143 done: 144 if ( moi == &opinfo ) { 145 mdb_txn_reset( moi->moi_txn ); 146 LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); 147 } else { 148 moi->moi_ref--; 149 } 150 if ( e ) 151 mdb_entry_return( op, e ); 152 return rc; 153 } 154