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