1 /* $NetBSD: compare.c,v 1.3 2021/08/14 16:15:00 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1999-2021 The OpenLDAP Foundation.
7 * Portions Copyright 2001-2003 Pierangelo Masarati.
8 * Portions Copyright 1999-2003 Howard Chu.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in the file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19 /* ACKNOWLEDGEMENTS:
20 * This work was initially developed by the Howard Chu for inclusion
21 * in OpenLDAP Software and subsequently enhanced by Pierangelo
22 * Masarati.
23 */
24
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: compare.c,v 1.3 2021/08/14 16:15:00 christos Exp $");
27
28 #include "portable.h"
29
30 #include <stdio.h>
31
32 #include <ac/string.h>
33 #include <ac/socket.h>
34
35 #include "slap.h"
36 #include "../back-ldap/back-ldap.h"
37 #include "back-meta.h"
38
39 int
meta_back_compare(Operation * op,SlapReply * rs)40 meta_back_compare( Operation *op, SlapReply *rs )
41 {
42 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
43 metatarget_t *mt;
44 metaconn_t *mc;
45 int rc = 0;
46 int candidate = -1;
47 struct berval mdn = BER_BVNULL;
48 dncookie dc;
49 struct berval mapped_attr = op->orc_ava->aa_desc->ad_cname;
50 struct berval mapped_value = op->orc_ava->aa_value;
51 int msgid;
52 ldap_back_send_t retrying = LDAP_BACK_RETRYING;
53 LDAPControl **ctrls = NULL;
54
55 mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
56 if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
57 return rs->sr_err;
58 }
59
60 assert( mc->mc_conns[ candidate ].msc_ld != NULL );
61
62 /*
63 * Rewrite the modify dn, if needed
64 */
65 mt = mi->mi_targets[ candidate ];
66 dc.target = mt;
67 dc.conn = op->o_conn;
68 dc.rs = rs;
69 dc.ctx = "compareDN";
70
71 switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
72 case LDAP_UNWILLING_TO_PERFORM:
73 rc = 1;
74 goto cleanup;
75
76 default:
77 break;
78 }
79
80 /*
81 * if attr is objectClass, try to remap the value
82 */
83 if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
84 ldap_back_map( &mt->mt_rwmap.rwm_oc,
85 &op->orc_ava->aa_value,
86 &mapped_value, BACKLDAP_MAP );
87
88 if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
89 goto cleanup;
90 }
91
92 /*
93 * else try to remap the attribute
94 */
95 } else {
96 ldap_back_map( &mt->mt_rwmap.rwm_at,
97 &op->orc_ava->aa_desc->ad_cname,
98 &mapped_attr, BACKLDAP_MAP );
99 if ( BER_BVISNULL( &mapped_attr ) || BER_BVISEMPTY( &mapped_attr ) ) {
100 goto cleanup;
101 }
102
103 if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
104 {
105 dc.ctx = "compareAttrDN";
106
107 switch ( ldap_back_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
108 {
109 case LDAP_UNWILLING_TO_PERFORM:
110 rc = 1;
111 goto cleanup;
112
113 default:
114 break;
115 }
116 }
117 }
118
119 retry:;
120 ctrls = op->o_ctrls;
121 rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
122 if ( rc != LDAP_SUCCESS ) {
123 send_ldap_result( op, rs );
124 goto cleanup;
125 }
126
127 rs->sr_err = ldap_compare_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
128 mapped_attr.bv_val, &mapped_value,
129 ctrls, NULL, &msgid );
130
131 rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
132 mt->mt_timeout[ SLAP_OP_COMPARE ], ( LDAP_BACK_SENDRESULT | retrying ) );
133 if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
134 retrying &= ~LDAP_BACK_RETRYING;
135 if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
136 /* if the identity changed, there might be need to re-authz */
137 (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
138 goto retry;
139 }
140 }
141
142 cleanup:;
143 (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
144
145 if ( mdn.bv_val != op->o_req_dn.bv_val ) {
146 free( mdn.bv_val );
147 }
148
149 if ( op->orc_ava->aa_value.bv_val != mapped_value.bv_val ) {
150 free( mapped_value.bv_val );
151 }
152
153 if ( mc ) {
154 meta_back_release_conn( mi, mc );
155 }
156
157 return rs->sr_err;
158 }
159
160