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