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