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