noopsrch.c revision 1.1 1 1.1 tron /* $NetBSD: noopsrch.c,v 1.1 2014/05/28 09:58:27 tron Exp $ */
2 1.1 tron
3 1.1 tron /* noopsrch.c - LDAP Control that counts entries a search would return */
4 1.1 tron /* $OpenLDAP$ */
5 1.1 tron /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 tron *
7 1.1 tron * Copyright 2010-2014 The OpenLDAP Foundation.
8 1.1 tron * All rights reserved.
9 1.1 tron *
10 1.1 tron * Redistribution and use in source and binary forms, with or without
11 1.1 tron * modification, are permitted only as authorized by the OpenLDAP
12 1.1 tron * Public License.
13 1.1 tron *
14 1.1 tron * A copy of this license is available in the file LICENSE in the
15 1.1 tron * top-level directory of the distribution or, alternatively, at
16 1.1 tron * <http://www.OpenLDAP.org/license.html>.
17 1.1 tron */
18 1.1 tron /* ACKNOWLEDGEMENTS:
19 1.1 tron * This work was initially developed by Pierangelo Masarati for inclusion
20 1.1 tron * in OpenLDAP Software.
21 1.1 tron */
22 1.1 tron
23 1.1 tron #include "portable.h"
24 1.1 tron
25 1.1 tron /* define SLAPD_OVER_NOOPSRCH=2 to build as run-time loadable module */
26 1.1 tron #ifdef SLAPD_OVER_NOOPSRCH
27 1.1 tron
28 1.1 tron /*
29 1.1 tron * Control OID
30 1.1 tron */
31 1.1 tron #define LDAP_CONTROL_X_NOOPSRCH "1.3.6.1.4.1.4203.666.5.18"
32 1.1 tron
33 1.1 tron #include "slap.h"
34 1.1 tron #include "ac/string.h"
35 1.1 tron
36 1.1 tron #define o_noopsrch o_ctrlflag[noopsrch_cid]
37 1.1 tron #define o_ctrlnoopsrch o_controls[noopsrch_cid]
38 1.1 tron
39 1.1 tron static int noopsrch_cid;
40 1.1 tron static slap_overinst noopsrch;
41 1.1 tron
42 1.1 tron static int
43 1.1 tron noopsrch_parseCtrl (
44 1.1 tron Operation *op,
45 1.1 tron SlapReply *rs,
46 1.1 tron LDAPControl *ctrl )
47 1.1 tron {
48 1.1 tron if ( op->o_noopsrch != SLAP_CONTROL_NONE ) {
49 1.1 tron rs->sr_text = "No-op Search control specified multiple times";
50 1.1 tron return LDAP_PROTOCOL_ERROR;
51 1.1 tron }
52 1.1 tron
53 1.1 tron if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
54 1.1 tron rs->sr_text = "No-op Search control value is present";
55 1.1 tron return LDAP_PROTOCOL_ERROR;
56 1.1 tron }
57 1.1 tron
58 1.1 tron op->o_ctrlnoopsrch = (void *)NULL;
59 1.1 tron
60 1.1 tron op->o_noopsrch = ctrl->ldctl_iscritical
61 1.1 tron ? SLAP_CONTROL_CRITICAL
62 1.1 tron : SLAP_CONTROL_NONCRITICAL;
63 1.1 tron
64 1.1 tron rs->sr_err = LDAP_SUCCESS;
65 1.1 tron
66 1.1 tron return rs->sr_err;
67 1.1 tron }
68 1.1 tron
69 1.1 tron int dummy;
70 1.1 tron
71 1.1 tron typedef struct noopsrch_cb_t {
72 1.1 tron slap_overinst *nc_on;
73 1.1 tron ber_int_t nc_nentries;
74 1.1 tron ber_int_t nc_nsearchref;
75 1.1 tron AttributeName *nc_save_attrs;
76 1.1 tron int *nc_pdummy;
77 1.1 tron int nc_save_slimit;
78 1.1 tron } noopsrch_cb_t;
79 1.1 tron
80 1.1 tron static int
81 1.1 tron noopsrch_response( Operation *op, SlapReply *rs )
82 1.1 tron {
83 1.1 tron noopsrch_cb_t *nc = (noopsrch_cb_t *)op->o_callback->sc_private;
84 1.1 tron
85 1.1 tron /* if the control is global, limits are not computed yet */
86 1.1 tron if ( nc->nc_pdummy == &dummy ) {
87 1.1 tron nc->nc_save_slimit = op->ors_slimit;
88 1.1 tron op->ors_slimit = SLAP_NO_LIMIT;
89 1.1 tron nc->nc_pdummy = NULL;
90 1.1 tron }
91 1.1 tron
92 1.1 tron if ( rs->sr_type == REP_SEARCH ) {
93 1.1 tron nc->nc_nentries++;
94 1.1 tron #ifdef NOOPSRCH_DEBUG
95 1.1 tron Debug( LDAP_DEBUG_TRACE, "noopsrch_response(REP_SEARCH): nentries=%d\n", nc->nc_nentries, 0, 0 );
96 1.1 tron #endif
97 1.1 tron return 0;
98 1.1 tron
99 1.1 tron } else if ( rs->sr_type == REP_SEARCHREF ) {
100 1.1 tron nc->nc_nsearchref++;
101 1.1 tron return 0;
102 1.1 tron
103 1.1 tron } else if ( rs->sr_type == REP_RESULT ) {
104 1.1 tron BerElementBuffer berbuf;
105 1.1 tron BerElement *ber = (BerElement *) &berbuf;
106 1.1 tron struct berval ctrlval;
107 1.1 tron LDAPControl *ctrl, *ctrlsp[2];
108 1.1 tron int rc = rs->sr_err;
109 1.1 tron
110 1.1 tron if ( nc->nc_save_slimit >= 0 && nc->nc_nentries >= nc->nc_save_slimit ) {
111 1.1 tron rc = LDAP_SIZELIMIT_EXCEEDED;
112 1.1 tron }
113 1.1 tron
114 1.1 tron #ifdef NOOPSRCH_DEBUG
115 1.1 tron Debug( LDAP_DEBUG_TRACE, "noopsrch_response(REP_RESULT): err=%d nentries=%d nref=%d\n", rc, nc->nc_nentries, nc->nc_nsearchref );
116 1.1 tron #endif
117 1.1 tron
118 1.1 tron ber_init2( ber, NULL, LBER_USE_DER );
119 1.1 tron
120 1.1 tron ber_printf( ber, "{iii}", rc, nc->nc_nentries, nc->nc_nsearchref );
121 1.1 tron if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
122 1.1 tron ber_free_buf( ber );
123 1.1 tron if ( op->o_noopsrch == SLAP_CONTROL_CRITICAL ) {
124 1.1 tron return LDAP_CONSTRAINT_VIOLATION;
125 1.1 tron }
126 1.1 tron return SLAP_CB_CONTINUE;
127 1.1 tron }
128 1.1 tron
129 1.1 tron ctrl = op->o_tmpcalloc( 1,
130 1.1 tron sizeof( LDAPControl ) + ctrlval.bv_len + 1,
131 1.1 tron op->o_tmpmemctx );
132 1.1 tron ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
133 1.1 tron ctrl->ldctl_oid = LDAP_CONTROL_X_NOOPSRCH;
134 1.1 tron ctrl->ldctl_iscritical = 0;
135 1.1 tron ctrl->ldctl_value.bv_len = ctrlval.bv_len;
136 1.1 tron AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
137 1.1 tron ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';
138 1.1 tron
139 1.1 tron ber_free_buf( ber );
140 1.1 tron
141 1.1 tron ctrlsp[0] = ctrl;
142 1.1 tron ctrlsp[1] = NULL;
143 1.1 tron slap_add_ctrls( op, rs, ctrlsp );
144 1.1 tron
145 1.1 tron return SLAP_CB_CONTINUE;
146 1.1 tron }
147 1.1 tron }
148 1.1 tron
149 1.1 tron static int
150 1.1 tron noopsrch_cleanup( Operation *op, SlapReply *rs )
151 1.1 tron {
152 1.1 tron if ( rs->sr_type == REP_RESULT || rs->sr_err == SLAPD_ABANDON ) {
153 1.1 tron noopsrch_cb_t *nc = (noopsrch_cb_t *)op->o_callback->sc_private;
154 1.1 tron op->ors_attrs = nc->nc_save_attrs;
155 1.1 tron if ( nc->nc_pdummy == NULL ) {
156 1.1 tron op->ors_slimit = nc->nc_save_slimit;
157 1.1 tron }
158 1.1 tron
159 1.1 tron op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
160 1.1 tron op->o_callback = NULL;
161 1.1 tron }
162 1.1 tron
163 1.1 tron return SLAP_CB_CONTINUE;
164 1.1 tron }
165 1.1 tron
166 1.1 tron static int
167 1.1 tron noopsrch_op_search( Operation *op, SlapReply *rs )
168 1.1 tron {
169 1.1 tron if ( op->o_noopsrch != SLAP_CONTROL_NONE ) {
170 1.1 tron slap_callback *sc;
171 1.1 tron noopsrch_cb_t *nc;
172 1.1 tron
173 1.1 tron sc = op->o_tmpcalloc( 1, sizeof( slap_callback ) + sizeof( noopsrch_cb_t ), op->o_tmpmemctx );
174 1.1 tron
175 1.1 tron nc = (noopsrch_cb_t *)&sc[ 1 ];
176 1.1 tron nc->nc_on = (slap_overinst *)op->o_bd->bd_info;
177 1.1 tron nc->nc_nentries = 0;
178 1.1 tron nc->nc_nsearchref = 0;
179 1.1 tron nc->nc_save_attrs = op->ors_attrs;
180 1.1 tron nc->nc_pdummy = &dummy;
181 1.1 tron
182 1.1 tron sc->sc_response = noopsrch_response;
183 1.1 tron sc->sc_cleanup = noopsrch_cleanup;
184 1.1 tron sc->sc_private = (void *)nc;
185 1.1 tron
186 1.1 tron op->ors_attrs = slap_anlist_no_attrs;
187 1.1 tron
188 1.1 tron sc->sc_next = op->o_callback->sc_next;
189 1.1 tron op->o_callback->sc_next = sc;
190 1.1 tron }
191 1.1 tron
192 1.1 tron return SLAP_CB_CONTINUE;
193 1.1 tron }
194 1.1 tron
195 1.1 tron static int noopsrch_cnt;
196 1.1 tron
197 1.1 tron static int
198 1.1 tron noopsrch_db_init( BackendDB *be, ConfigReply *cr)
199 1.1 tron {
200 1.1 tron if ( noopsrch_cnt++ == 0 ) {
201 1.1 tron int rc;
202 1.1 tron
203 1.1 tron rc = register_supported_control( LDAP_CONTROL_X_NOOPSRCH,
204 1.1 tron SLAP_CTRL_SEARCH | SLAP_CTRL_GLOBAL_SEARCH, NULL,
205 1.1 tron noopsrch_parseCtrl, &noopsrch_cid );
206 1.1 tron if ( rc != LDAP_SUCCESS ) {
207 1.1 tron Debug( LDAP_DEBUG_ANY,
208 1.1 tron "noopsrch_initialize: Failed to register control '%s' (%d)\n",
209 1.1 tron LDAP_CONTROL_X_NOOPSRCH, rc, 0 );
210 1.1 tron return rc;
211 1.1 tron }
212 1.1 tron }
213 1.1 tron
214 1.1 tron return LDAP_SUCCESS;
215 1.1 tron }
216 1.1 tron
217 1.1 tron static int
218 1.1 tron noopsrch_db_destroy( BackendDB *be, ConfigReply *cr )
219 1.1 tron {
220 1.1 tron assert( noopsrch_cnt > 0 );
221 1.1 tron
222 1.1 tron #ifdef SLAP_CONFIG_DELETE
223 1.1 tron overlay_unregister_control( be, LDAP_CONTROL_X_NOOPSRCH );
224 1.1 tron if ( --noopsrch_cnt == 0 ) {
225 1.1 tron unregister_supported_control( LDAP_CONTROL_X_NOOPSRCH );
226 1.1 tron }
227 1.1 tron
228 1.1 tron #endif /* SLAP_CONFIG_DELETE */
229 1.1 tron
230 1.1 tron return 0;
231 1.1 tron }
232 1.1 tron
233 1.1 tron #if SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC
234 1.1 tron static
235 1.1 tron #endif /* SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC */
236 1.1 tron int
237 1.1 tron noopsrch_initialize( void )
238 1.1 tron {
239 1.1 tron
240 1.1 tron noopsrch.on_bi.bi_type = "noopsrch";
241 1.1 tron
242 1.1 tron noopsrch.on_bi.bi_db_init = noopsrch_db_init;
243 1.1 tron noopsrch.on_bi.bi_db_destroy = noopsrch_db_destroy;
244 1.1 tron noopsrch.on_bi.bi_op_search = noopsrch_op_search;
245 1.1 tron
246 1.1 tron return overlay_register( &noopsrch );
247 1.1 tron }
248 1.1 tron
249 1.1 tron #if SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC
250 1.1 tron int
251 1.1 tron init_module( int argc, char *argv[] )
252 1.1 tron {
253 1.1 tron return noopsrch_initialize();
254 1.1 tron }
255 1.1 tron #endif /* SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC */
256 1.1 tron
257 1.1 tron #endif /* SLAPD_OVER_NOOPSRCH */
258