referral.c revision 1.2
1/* $NetBSD: referral.c,v 1.2 2020/08/11 13:15:40 christos 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-2020 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 <sys/cdefs.h> 20__RCSID("$NetBSD: referral.c,v 1.2 2020/08/11 13:15:40 christos Exp $"); 21 22#include "portable.h" 23#include <stdio.h> 24#include <ac/string.h> 25 26#include "back-mdb.h" 27 28int 29mdb_referrals( Operation *op, SlapReply *rs ) 30{ 31 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; 32 Entry *e = NULL; 33 int rc = LDAP_SUCCESS; 34 35 MDB_txn *rtxn; 36 mdb_op_info opinfo = {0}, *moi = &opinfo; 37 38 if( op->o_tag == LDAP_REQ_SEARCH ) { 39 /* let search take care of itself */ 40 return rc; 41 } 42 43 if( get_manageDSAit( op ) ) { 44 /* let op take care of DSA management */ 45 return rc; 46 } 47 48 rc = mdb_opinfo_get(op, mdb, 1, &moi); 49 switch(rc) { 50 case 0: 51 break; 52 default: 53 return LDAP_OTHER; 54 } 55 56 rtxn = moi->moi_txn; 57 58 /* get entry */ 59 rc = mdb_dn2entry( op, rtxn, &op->o_req_ndn, &e, 1 ); 60 61 switch(rc) { 62 case MDB_NOTFOUND: 63 case 0: 64 break; 65 case LDAP_BUSY: 66 rs->sr_text = "ldap server busy"; 67 goto done; 68 default: 69 Debug( LDAP_DEBUG_TRACE, 70 LDAP_XSTRING(mdb_referrals) 71 ": dn2entry failed: %s (%d)\n", 72 mdb_strerror(rc), rc, 0 ); 73 rs->sr_text = "internal error"; 74 rc = LDAP_OTHER; 75 goto done; 76 } 77 78 if ( rc == MDB_NOTFOUND ) { 79 rc = LDAP_SUCCESS; 80 rs->sr_matched = NULL; 81 if ( e != NULL ) { 82 Debug( LDAP_DEBUG_TRACE, 83 LDAP_XSTRING(mdb_referrals) 84 ": tag=%lu target=\"%s\" matched=\"%s\"\n", 85 (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val ); 86 87 if( is_entry_referral( e ) ) { 88 BerVarray ref = get_entry_referrals( op, e ); 89 rc = LDAP_OTHER; 90 rs->sr_ref = referral_rewrite( ref, &e->e_name, 91 &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 92 ber_bvarray_free( ref ); 93 if ( rs->sr_ref ) { 94 rs->sr_matched = ber_strdup_x( 95 e->e_name.bv_val, op->o_tmpmemctx ); 96 } 97 } 98 99 mdb_entry_return( op, e ); 100 e = NULL; 101 } 102 103 if( rs->sr_ref != NULL ) { 104 /* send referrals */ 105 rc = rs->sr_err = LDAP_REFERRAL; 106 send_ldap_result( op, rs ); 107 ber_bvarray_free( rs->sr_ref ); 108 rs->sr_ref = NULL; 109 } else if ( rc != LDAP_SUCCESS ) { 110 rs->sr_text = rs->sr_matched ? "bad referral object" : NULL; 111 } 112 113 if (rs->sr_matched) { 114 op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx ); 115 rs->sr_matched = NULL; 116 } 117 goto done; 118 } 119 120 if ( is_entry_referral( e ) ) { 121 /* entry is a referral */ 122 BerVarray refs = get_entry_referrals( op, e ); 123 rs->sr_ref = referral_rewrite( 124 refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 125 126 Debug( LDAP_DEBUG_TRACE, 127 LDAP_XSTRING(mdb_referrals) 128 ": tag=%lu target=\"%s\" matched=\"%s\"\n", 129 (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val ); 130 131 rs->sr_matched = e->e_name.bv_val; 132 if( rs->sr_ref != NULL ) { 133 rc = rs->sr_err = LDAP_REFERRAL; 134 send_ldap_result( op, rs ); 135 ber_bvarray_free( rs->sr_ref ); 136 rs->sr_ref = NULL; 137 } else { 138 rc = LDAP_OTHER; 139 rs->sr_text = "bad referral object"; 140 } 141 142 rs->sr_matched = NULL; 143 ber_bvarray_free( refs ); 144 } 145 146done: 147 if ( moi == &opinfo ) { 148 mdb_txn_reset( moi->moi_txn ); 149 LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); 150 } else { 151 moi->moi_ref--; 152 } 153 if ( e ) 154 mdb_entry_return( op, e ); 155 return rc; 156} 157