]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/chain.c
984e5723d1fe6da68e459d01e738531d0fe9746b
[openldap] / servers / slapd / back-ldap / 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 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 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by the Howard Chu for inclusion
18  * in OpenLDAP Software.
19  */
20 /* This is an altered version */
21 /*
22  * Copyright 2003, Howard Chu, All rights reserved. <hyc@highlandsun.com>
23  * 
24  * Permission is granted to anyone to use this software for any purpose
25  * on any computer system, and to alter it and redistribute it, subject
26  * to the following restrictions:
27  * 
28  * 1. The author is not responsible for the consequences of use of this
29  *    software, no matter how awful, even if they arise from flaws in it.
30  * 
31  * 2. The origin of this software must not be misrepresented, either by
32  *    explicit claim or by omission.  Since few users ever read sources,
33  *    credits should appear in the documentation.
34  * 
35  * 3. Altered versions must be plainly marked as such, and must not be
36  *    misrepresented as being the original software.  Since few users
37  *    ever read sources, credits should appear in the documentation.
38  * 
39  * 4. This notice may not be removed or altered.
40  */
41
42 #include "portable.h"
43
44 #include <stdio.h>
45
46 #include <ac/string.h>
47 #include <ac/socket.h>
48
49 #include "slap.h"
50 #include "back-ldap.h"
51
52 static int
53 ldap_chain_response( Operation *op, SlapReply *rs )
54 {
55         slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
56         void *private = op->o_bd->be_private;
57         slap_callback *sc = op->o_callback;
58         LDAPControl **prev = op->o_ctrls;
59         LDAPControl **ctrls = NULL, authz;
60         int i, nctrls, rc;
61         int cache = op->o_do_not_cache;
62         char *authzid = NULL;
63         BerVarray ref;
64         struct berval ndn = op->o_ndn;
65
66         if ( rs->sr_err != LDAP_REFERRAL )
67                 return SLAP_CB_CONTINUE;
68
69         /* currently we assume only one referral destination.
70          * we'll have to parse this in the future.
71          */
72         ref = rs->sr_ref;
73         rs->sr_ref = NULL;
74
75         op->o_bd->be_private = on->on_bi.bi_private;
76         op->o_callback = NULL;
77
78         /* Chaining is performed by a privileged user on behalf
79          * of a normal user, using the ProxyAuthz control. However,
80          * Binds are done separately, on an anonymous session.
81          */
82         if ( op->o_tag != LDAP_REQ_BIND ) {
83                 for (i=0; prev && prev[i]; i++);
84                 nctrls = i;
85
86                 /* Add an extra NULL slot */
87                 if (!prev) i++;
88
89                 ctrls = op->o_tmpalloc((i+1)*sizeof(LDAPControl *),
90                         op->o_tmpmemctx);
91                 for (i=0; i <nctrls; i++)
92                         ctrls[i] = prev[i];
93                 ctrls[nctrls] = &authz;
94                 ctrls[nctrls+1] = NULL;
95                 authz.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
96                 authz.ldctl_iscritical = 1;
97                 authz.ldctl_value = op->o_dn;
98                 if ( op->o_dn.bv_len ) {
99                         authzid = op->o_tmpalloc( op->o_dn.bv_len+4,
100                                 op->o_tmpmemctx );
101                         strcpy(authzid, "dn: ");
102                         strcpy(authzid+4, op->o_dn.bv_val);
103                         authz.ldctl_value.bv_len = op->o_dn.bv_len + 4;
104                         authz.ldctl_value.bv_val = authzid;
105                 }
106                 op->o_ctrls = ctrls;
107                 op->o_ndn = op->o_bd->be_rootndn;
108         }
109
110         switch( op->o_tag ) {
111         case LDAP_REQ_BIND: {
112                 struct berval rndn = op->o_req_ndn;
113                 Connection *conn = op->o_conn;
114                 op->o_req_ndn = slap_empty_bv;
115                 op->o_conn = NULL;
116                 rc = ldap_back_bind( op, rs );
117                 op->o_req_ndn = rndn;
118                 op->o_conn = conn;
119                 }
120                 break;
121         case LDAP_REQ_ADD:
122                 rc = ldap_back_add( op, rs );
123                 break;
124         case LDAP_REQ_DELETE:
125                 rc = ldap_back_delete( op, rs );
126                 break;
127         case LDAP_REQ_MODRDN:
128                 rc = ldap_back_modrdn( op, rs );
129                 break;
130         case LDAP_REQ_MODIFY:
131                 rc = ldap_back_modify( op, rs );
132                 break;
133         case LDAP_REQ_COMPARE:
134                 rc = ldap_back_compare( op, rs );
135                 break;
136         case LDAP_REQ_SEARCH:
137                 rc = ldap_back_search( op, rs );
138                 break;
139         case LDAP_REQ_EXTENDED:
140                 rc = ldap_back_extended( op, rs );
141                 break;
142         default:
143                 rc = SLAP_CB_CONTINUE;
144                 break;
145         }
146         op->o_do_not_cache = cache;
147         op->o_ctrls = prev;
148         op->o_bd->be_private = private;
149         op->o_callback = sc;
150         op->o_ndn = ndn;
151         if ( ctrls ) op->o_tmpfree( ctrls, op->o_tmpmemctx );
152         if ( authzid ) op->o_tmpfree( authzid, op->o_tmpmemctx );
153         rs->sr_ref = ref;
154
155         return rc;
156 }
157
158 static int ldap_chain_config(
159     BackendDB   *be,
160     const char  *fname,
161     int         lineno,
162     int         argc,
163     char        **argv
164 )
165 {
166         slap_overinst *on = (slap_overinst *) be->bd_info;
167         void *private = be->be_private;
168         int rc;
169
170         be->be_private = on->on_bi.bi_private;
171         rc = ldap_back_db_config( be, fname, lineno, argc, argv );
172         be->be_private = private;
173         return rc;
174 }
175
176 static int ldap_chain_init(
177         BackendDB *be
178 )
179 {
180         slap_overinst *on = (slap_overinst *) be->bd_info;
181         void *private = be->be_private;
182         int rc;
183
184         be->be_private = NULL;
185         rc = ldap_back_db_init( be );
186         on->on_bi.bi_private = be->be_private;
187         be->be_private = private;
188         return rc;
189 }
190
191 static int ldap_chain_destroy(
192         BackendDB *be
193 )
194 {
195         slap_overinst *on = (slap_overinst *) be->bd_info;
196         void *private = be->be_private;
197         int rc;
198
199         be->be_private = on->on_bi.bi_private;
200         rc = ldap_back_db_destroy( be );
201         on->on_bi.bi_private = be->be_private;
202         be->be_private = private;
203         return rc;
204 }
205
206 static slap_overinst ldapchain;
207
208 int ldap_chain_setup()
209 {
210         ldapchain.on_bi.bi_type = "chain";
211         ldapchain.on_bi.bi_db_init = ldap_chain_init;
212         ldapchain.on_bi.bi_db_config = ldap_chain_config;
213         ldapchain.on_bi.bi_db_destroy = ldap_chain_destroy;
214         ldapchain.on_response = ldap_chain_response;
215
216         return overlay_register( &ldapchain );
217 }