]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/chain.c
add logs; fix bug in group/dn selection logic
[openldap] / servers / slapd / overlays / chain.c
1 /* chain.c - chain LDAP operations */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2004 The OpenLDAP Foundation.
6  * Portions Copyright 2003 Howard Chu.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by the Howard Chu for inclusion
19  * in OpenLDAP Software.
20  */
21
22 #include "portable.h"
23
24 #if defined(SLAPD_LDAP) 
25
26 #ifdef SLAPD_OVER_CHAIN
27
28 #include <stdio.h>
29
30 #include <ac/string.h>
31 #include <ac/socket.h>
32
33 #include "slap.h"
34 #include "../back-ldap/back-ldap.h"
35
36 static int
37 ldap_chain_chk_referrals( Operation *op, SlapReply *rs )
38 {
39         return LDAP_SUCCESS;
40 }
41
42 static int
43 ldap_chain_response( Operation *op, SlapReply *rs )
44 {
45         slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;
46         void            *private = op->o_bd->be_private;
47         slap_callback   *sc = op->o_callback;
48         LDAPControl     **prev = op->o_ctrls;
49         LDAPControl     **ctrls = NULL, authz;
50         int             i, nctrls, rc = 0;
51         int             cache = op->o_do_not_cache;
52         char            *authzid = NULL;
53         BerVarray       ref;
54         struct berval   ndn = op->o_ndn;
55
56         struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
57
58         if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF )
59                 return SLAP_CB_CONTINUE;
60
61         ref = rs->sr_ref;
62         rs->sr_ref = NULL;
63
64         op->o_callback = NULL;
65
66         if ( lip->url == NULL ) {
67                 li = *lip;
68                 op->o_bd->be_private = &li;
69
70                 if ( rs->sr_type != REP_SEARCHREF ) {
71                         LDAPURLDesc     *srv;
72                         char            *save_dn;
73
74                         /* parse reference and use proto://[host][:port]/ only */
75                         rc = ldap_url_parse_ext( ref[0].bv_val, &srv );
76                         if ( rc != LDAP_SUCCESS) {
77                                 /* error */
78                                 return 1;
79                         }
80
81                         /* remove DN essentially because later on 
82                          * ldap_initialize() will parse the URL 
83                          * as a comma-separated URL list */
84                         save_dn = srv->lud_dn;
85                         srv->lud_dn = "";
86                         li.url = ldap_url_desc2str( srv );
87                         if ( li.url == NULL ) {
88                                 /* error */
89                                 srv->lud_dn = save_dn;
90                                 ldap_free_urldesc( srv );
91                                 return 1;
92                         }
93
94                         srv->lud_dn = save_dn;
95                         ldap_free_urldesc( srv );
96                 }
97
98         } else {
99                 op->o_bd->be_private = on->on_bi.bi_private;
100         }
101
102         /* Chaining is performed by a privileged user on behalf
103          * of a normal user, using the ProxyAuthz control. However,
104          * Binds are done separately, on an anonymous session.
105          */
106         if ( op->o_tag != LDAP_REQ_BIND ) {
107                 for (i=0; prev && prev[i]; i++);
108                 nctrls = i;
109
110                 /* Add an extra NULL slot */
111                 if (!prev) i++;
112
113                 ctrls = op->o_tmpalloc((i+1)*sizeof(LDAPControl *),
114                         op->o_tmpmemctx);
115                 for (i=0; i <nctrls; i++)
116                         ctrls[i] = prev[i];
117                 ctrls[nctrls] = &authz;
118                 ctrls[nctrls+1] = NULL;
119                 authz.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
120                 authz.ldctl_iscritical = 1;
121                 authz.ldctl_value = op->o_dn;
122                 if ( op->o_dn.bv_len ) {
123                         authzid = op->o_tmpalloc( op->o_dn.bv_len + sizeof("dn:") - 1,
124                                 op->o_tmpmemctx );
125                         strcpy(authzid, "dn:");
126                         strcpy(authzid + sizeof("dn:") - 1, op->o_dn.bv_val);
127                         authz.ldctl_value.bv_len = op->o_dn.bv_len + sizeof("dn:") - 1;
128                         authz.ldctl_value.bv_val = authzid;
129                 }
130                 op->o_ctrls = ctrls;
131                 op->o_ndn = op->o_bd->be_rootndn;
132         }
133
134         switch( op->o_tag ) {
135         case LDAP_REQ_BIND: {
136                 struct berval   rndn = op->o_req_ndn;
137                 Connection      *conn = op->o_conn;
138
139                 op->o_req_ndn = slap_empty_bv;
140
141                 op->o_conn = NULL;
142                 rc = ldap_back_bind( op, rs );
143                 op->o_req_ndn = rndn;
144                 op->o_conn = conn;
145                 }
146                 break;
147         case LDAP_REQ_ADD:
148                 rc = ldap_back_add( op, rs );
149                 break;
150         case LDAP_REQ_DELETE:
151                 rc = ldap_back_delete( op, rs );
152                 break;
153         case LDAP_REQ_MODRDN:
154                 rc = ldap_back_modrdn( op, rs );
155                 break;
156         case LDAP_REQ_MODIFY:
157                 rc = ldap_back_modify( op, rs );
158                 break;
159         case LDAP_REQ_COMPARE:
160                 rc = ldap_back_compare( op, rs );
161                 break;
162         case LDAP_REQ_SEARCH:
163                 if ( rs->sr_type == REP_SEARCHREF ) {
164                         struct berval   *curr = ref,
165                                         odn = op->o_req_dn,
166                                         ondn = op->o_req_ndn;
167
168                         rs->sr_type = REP_SEARCH;
169
170                         /* copy the private info because we need to modify it */
171                         for ( ; curr[0].bv_val; curr++ ) {
172                                 LDAPURLDesc     *srv;
173
174                                 /* parse reference and use proto://[host][:port]/ only */
175                                 rc = ldap_url_parse_ext( curr[0].bv_val, &srv );
176                                 if ( rc != LDAP_SUCCESS) {
177                                         /* error */
178                                         rc = 1;
179                                         goto end_of_searchref;
180                                 }
181
182                                 ber_str2bv(srv->lud_dn, 0, 0, &op->o_req_dn);
183                                 op->o_req_ndn = op->o_req_dn;
184
185                                 /* remove DN essentially because later on 
186                                  * ldap_initialize() will parse the URL 
187                                  * as a comma-separated URL list */
188                                 srv->lud_dn = "";
189                                 li.url = ldap_url_desc2str( srv );
190                                 if ( li.url == NULL ) {
191                                         /* error */
192                                         srv->lud_dn = op->o_req_dn.bv_val;
193                                         ldap_free_urldesc( srv );
194                                         rc = 1;
195                                         goto end_of_searchref;
196                                 }
197
198                                 /* FIXME: should we also copy filter and scope?
199                                  * according to RFC3296, no */
200
201                                 rc = ldap_back_search( op, rs );
202
203                                 ldap_memfree( li.url );
204                                 li.url = NULL;
205
206                                 srv->lud_dn = op->o_req_dn.bv_val;
207                                 ldap_free_urldesc( srv );
208
209                                 if ( rc ) {
210                                         /* error */
211                                         rc = 1;
212                                         goto end_of_searchref;
213                                 }
214                         }
215
216 end_of_searchref:;
217                         op->o_req_dn = odn;
218                         op->o_req_ndn = ondn;
219                         rs->sr_type = REP_SEARCHREF;
220                         
221                 } else {
222                         rc = ldap_back_search( op, rs );
223                 }
224                 break;
225         case LDAP_REQ_EXTENDED:
226                 rc = ldap_back_extended( op, rs );
227                 break;
228         default:
229                 rc = SLAP_CB_CONTINUE;
230                 break;
231         }
232         op->o_do_not_cache = cache;
233         op->o_ctrls = prev;
234         op->o_bd->be_private = private;
235         op->o_callback = sc;
236         op->o_ndn = ndn;
237         if ( ctrls ) op->o_tmpfree( ctrls, op->o_tmpmemctx );
238         if ( authzid ) op->o_tmpfree( authzid, op->o_tmpmemctx );
239         rs->sr_ref = ref;
240         if ( lip->url == NULL && li.url ) {
241                 ldap_memfree( li.url );
242         }
243
244         return rc;
245 }
246
247 static int ldap_chain_config(
248     BackendDB   *be,
249     const char  *fname,
250     int         lineno,
251     int         argc,
252     char        **argv
253 )
254 {
255         slap_overinst   *on = (slap_overinst *) be->bd_info;
256         void            *private = be->be_private;
257         char            *argv0 = NULL;
258         int             rc;
259
260         be->be_private = on->on_bi.bi_private;
261         if ( strncasecmp( argv[ 0 ], "chain-", sizeof( "chain-" ) - 1 ) == 0 ) {
262                 argv0 = argv[ 0 ];
263                 argv[ 0 ] = &argv[ 0 ][ sizeof( "chain-" ) - 1 ];
264         }
265         rc = ldap_back_db_config( be, fname, lineno, argc, argv );
266         if ( argv0 ) {
267                 argv[ 0 ] = argv0;
268         }
269         
270         be->be_private = private;
271         return rc;
272 }
273
274 static int ldap_chain_init(
275         BackendDB *be
276 )
277 {
278         slap_overinst *on = (slap_overinst *) be->bd_info;
279         void *private = be->be_private;
280         int rc;
281
282         be->be_private = NULL;
283         rc = ldap_back_db_init( be );
284         on->on_bi.bi_private = be->be_private;
285         be->be_private = private;
286
287         return rc;
288 }
289
290 static int ldap_chain_destroy(
291         BackendDB *be
292 )
293 {
294         slap_overinst *on = (slap_overinst *) be->bd_info;
295         void *private = be->be_private;
296         int rc;
297
298         be->be_private = on->on_bi.bi_private;
299         rc = ldap_back_db_destroy( be );
300         on->on_bi.bi_private = be->be_private;
301         be->be_private = private;
302         return rc;
303 }
304
305 static slap_overinst ldapchain;
306
307 int chain_init()
308 {
309         ldapchain.on_bi.bi_type = "chain";
310         ldapchain.on_bi.bi_db_init = ldap_chain_init;
311         ldapchain.on_bi.bi_db_config = ldap_chain_config;
312         ldapchain.on_bi.bi_db_destroy = ldap_chain_destroy;
313         ldapchain.on_response = ldap_chain_response;
314
315         ldapchain.on_bi.bi_chk_referrals = ldap_chain_chk_referrals;
316
317         return overlay_register( &ldapchain );
318 }
319
320 #if SLAPD_OVER_CHAIN == SLAPD_MOD_DYNAMIC
321 int init_module(int argc, char *argv[]) {
322         return chain_init();
323 }
324 #endif /* SLAPD_OVER_CHAIN == SLAPD_MOD_DYNAMIC */
325
326 #endif /* SLAPD_OVER_CHAIN */
327
328 #endif /* ! defined(SLAPD_LDAP) */