]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/chain.c
Should not have deleted chain.c
[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-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 #include <stdio.h>
25
26 #include <ac/string.h>
27 #include <ac/socket.h>
28
29 #include "slap.h"
30 #include "back-ldap.h"
31
32 static int
33 ldap_chain_response( Operation *op, SlapReply *rs )
34 {
35         slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
36         void *private = op->o_bd->be_private;
37         slap_callback *sc = op->o_callback;
38         LDAPControl **prev = op->o_ctrls;
39         LDAPControl **ctrls = NULL, authz;
40         int i, nctrls, rc;
41         int cache = op->o_do_not_cache;
42         char *authzid = NULL;
43         BerVarray ref;
44         struct berval ndn = op->o_ndn;
45
46         if ( rs->sr_err != LDAP_REFERRAL )
47                 return SLAP_CB_CONTINUE;
48
49         /* currently we assume only one referral destination.
50          * we'll have to parse this in the future.
51          */
52         ref = rs->sr_ref;
53         rs->sr_ref = NULL;
54
55         op->o_bd->be_private = on->on_bi.bi_private;
56         op->o_callback = NULL;
57
58         /* Chaining is performed by a privileged user on behalf
59          * of a normal user, using the ProxyAuthz control. However,
60          * Binds are done separately, on an anonymous session.
61          */
62         if ( op->o_tag != LDAP_REQ_BIND ) {
63                 for (i=0; prev && prev[i]; i++);
64                 nctrls = i;
65
66                 /* Add an extra NULL slot */
67                 if (!prev) i++;
68
69                 ctrls = op->o_tmpalloc((i+1)*sizeof(LDAPControl *),
70                         op->o_tmpmemctx);
71                 for (i=0; i <nctrls; i++)
72                         ctrls[i] = prev[i];
73                 ctrls[nctrls] = &authz;
74                 ctrls[nctrls+1] = NULL;
75                 authz.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
76                 authz.ldctl_iscritical = 1;
77                 authz.ldctl_value = op->o_dn;
78                 if ( op->o_dn.bv_len ) {
79                         authzid = op->o_tmpalloc( op->o_dn.bv_len+4,
80                                 op->o_tmpmemctx );
81                         strcpy(authzid, "dn: ");
82                         strcpy(authzid+4, op->o_dn.bv_val);
83                         authz.ldctl_value.bv_len = op->o_dn.bv_len + 4;
84                         authz.ldctl_value.bv_val = authzid;
85                 }
86                 op->o_ctrls = ctrls;
87                 op->o_ndn = op->o_bd->be_rootndn;
88         }
89
90         switch( op->o_tag ) {
91         case LDAP_REQ_BIND: {
92                 struct berval rndn = op->o_req_ndn;
93                 Connection *conn = op->o_conn;
94                 op->o_req_ndn = slap_empty_bv;
95                 op->o_conn = NULL;
96                 rc = ldap_back_bind( op, rs );
97                 op->o_req_ndn = rndn;
98                 op->o_conn = conn;
99                 }
100                 break;
101         case LDAP_REQ_ADD:
102                 rc = ldap_back_add( op, rs );
103                 break;
104         case LDAP_REQ_DELETE:
105                 rc = ldap_back_delete( op, rs );
106                 break;
107         case LDAP_REQ_MODRDN:
108                 rc = ldap_back_modrdn( op, rs );
109                 break;
110         case LDAP_REQ_MODIFY:
111                 rc = ldap_back_modify( op, rs );
112                 break;
113         case LDAP_REQ_COMPARE:
114                 rc = ldap_back_compare( op, rs );
115                 break;
116         case LDAP_REQ_SEARCH:
117                 rc = ldap_back_search( op, rs );
118                 break;
119         case LDAP_REQ_EXTENDED:
120                 rc = ldap_back_extended( op, rs );
121                 break;
122         default:
123                 rc = SLAP_CB_CONTINUE;
124                 break;
125         }
126         op->o_do_not_cache = cache;
127         op->o_ctrls = prev;
128         op->o_bd->be_private = private;
129         op->o_callback = sc;
130         op->o_ndn = ndn;
131         if ( ctrls ) op->o_tmpfree( ctrls, op->o_tmpmemctx );
132         if ( authzid ) op->o_tmpfree( authzid, op->o_tmpmemctx );
133         rs->sr_ref = ref;
134
135         return rc;
136 }
137
138 static int ldap_chain_config(
139     BackendDB   *be,
140     const char  *fname,
141     int         lineno,
142     int         argc,
143     char        **argv
144 )
145 {
146         slap_overinst *on = (slap_overinst *) be->bd_info;
147         void *private = be->be_private;
148         int rc;
149
150         be->be_private = on->on_bi.bi_private;
151         rc = ldap_back_db_config( be, fname, lineno, argc, argv );
152         be->be_private = private;
153         return rc;
154 }
155
156 static int ldap_chain_init(
157         BackendDB *be
158 )
159 {
160         slap_overinst *on = (slap_overinst *) be->bd_info;
161         void *private = be->be_private;
162         int rc;
163
164         be->be_private = NULL;
165         rc = ldap_back_db_init( be );
166         on->on_bi.bi_private = be->be_private;
167         be->be_private = private;
168         return rc;
169 }
170
171 static int ldap_chain_destroy(
172         BackendDB *be
173 )
174 {
175         slap_overinst *on = (slap_overinst *) be->bd_info;
176         void *private = be->be_private;
177         int rc;
178
179         be->be_private = on->on_bi.bi_private;
180         rc = ldap_back_db_destroy( be );
181         on->on_bi.bi_private = be->be_private;
182         be->be_private = private;
183         return rc;
184 }
185
186 static slap_overinst ldapchain;
187
188 int ldap_chain_setup()
189 {
190         ldapchain.on_bi.bi_type = "chain";
191         ldapchain.on_bi.bi_db_init = ldap_chain_init;
192         ldapchain.on_bi.bi_db_config = ldap_chain_config;
193         ldapchain.on_bi.bi_db_destroy = ldap_chain_destroy;
194         ldapchain.on_response = ldap_chain_response;
195
196         return overlay_register( &ldapchain );
197 }