1 /* $NetBSD: referral.c,v 1.3 2021/08/14 16:15:00 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-2021 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.3 2021/08/14 16:15:00 christos Exp $");
21
22 #include "portable.h"
23 #include <stdio.h>
24 #include <ac/string.h>
25
26 #include "back-mdb.h"
27
28 int
mdb_referrals(Operation * op,SlapReply * rs)29 mdb_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 );
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
146 done:
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