]> git.sur5r.net Git - openldap/blob - servers/slapd/ldapsync.c
1. Session history support
[openldap] / servers / slapd / ldapsync.c
1 /* $OpenLDAP$ */
2 /*
3  * LDAP Content Sync Routines
4  */
5 /*
6  * Copyright 2003 The OpenLDAP Foundation, All Rights Reserved.
7  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
8  */
9 /* Copyright (c) 2003 by International Business Machines, Inc.
10  *
11  * International Business Machines, Inc. (hereinafter called IBM) grants
12  * permission under its copyrights to use, copy, modify, and distribute this
13  * Software with or without fee, provided that the above copyright notice and
14  * all paragraphs of this notice appear in all copies, and that the name of IBM
15  * not be used in connection with the marketing of any product incorporating
16  * the Software or modifications thereof, without specific, written prior
17  * permission.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
20  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
22  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
23  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
24  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/string.h>
32 #include <ac/socket.h>
33
34 #include "ldap_pvt.h"
35 #include "lutil.h"
36 #include "slap.h"
37 #include "lutil_ldap.h"
38
39 int
40 slap_build_sync_state_ctrl(
41         Operation       *op,
42         SlapReply       *rs,
43         Entry           *e,
44         int                     entry_sync_state,
45         LDAPControl     **ctrls,
46         int                     num_ctrls,
47         int                     send_cookie,
48         struct berval   *csn)
49 {
50         Attribute* a;
51         int ret;
52         int res;
53         const char *text = NULL;
54
55         BerElementBuffer berbuf;
56         BerElement *ber = (BerElement *)&berbuf;
57
58         struct berval entryuuid_bv      = { 0, NULL };
59
60         ber_init2( ber, 0, LBER_USE_DER );
61
62         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
63
64         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
65                 AttributeDescription *desc = a->a_desc;
66                 if ( desc == slap_schema.si_ad_entryUUID ) {
67                         ber_dupbv( &entryuuid_bv, &a->a_vals[0] );
68                 }
69         }
70
71         if ( send_cookie && csn ) {
72                 ber_printf( ber, "{eOON}",
73                         entry_sync_state, &entryuuid_bv, csn );
74         } else {
75                 ber_printf( ber, "{eON}",
76                         entry_sync_state, &entryuuid_bv );
77         }
78
79         ch_free( entryuuid_bv.bv_val );
80         entryuuid_bv.bv_val = NULL;
81
82         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
83         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
84         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
85
86         ber_free_buf( ber );
87
88         if ( ret < 0 ) {
89 #ifdef NEW_LOGGING
90                 LDAP_LOG ( OPERATION, RESULTS, 
91                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
92                         0, 0, 0 );
93 #else
94                 Debug( LDAP_DEBUG_TRACE,
95                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
96                         0, 0, 0 );
97 #endif
98                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
99                 return ret;
100         }
101
102         return LDAP_SUCCESS;
103 }
104
105 int
106 slap_build_sync_done_ctrl(
107         Operation       *op,
108         SlapReply       *rs,
109         LDAPControl     **ctrls,
110         int             num_ctrls,
111         int             send_cookie,
112         struct berval   *csn )
113 {
114         int ret;
115         BerElementBuffer berbuf;
116         BerElement *ber = (BerElement *)&berbuf;
117
118         ber_init2( ber, NULL, LBER_USE_DER );
119
120         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
121
122         if ( send_cookie && csn ) {
123                 ber_printf( ber, "{ON}", csn );
124         } else {
125                 ber_printf( ber, "{N}" );
126         }
127
128         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
129         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
130         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
131
132         ber_free_buf( ber );
133
134         if ( ret < 0 ) {
135 #ifdef NEW_LOGGING
136                 LDAP_LOG ( OPERATION, RESULTS, 
137                         "slap_build_sync_done_ctrl: ber_flatten2 failed\n",
138                         0, 0, 0 );
139 #else
140                 Debug( LDAP_DEBUG_TRACE,
141                         "slap_build_sync_done_ctrl: ber_flatten2 failed\n",
142                         0, 0, 0 );
143 #endif
144                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
145                 return ret;
146         }
147
148         return LDAP_SUCCESS;
149 }
150
151
152 int
153 slap_build_sync_state_ctrl_from_slog(
154         Operation       *op,
155         SlapReply       *rs,
156         struct slog_entry *slog_e,
157         int                     entry_sync_state,
158         LDAPControl     **ctrls,
159         int                     num_ctrls,
160         int                     send_cookie,
161         struct berval   *csn)
162 {
163         Attribute* a;
164         int ret;
165         int res;
166         const char *text = NULL;
167
168         BerElementBuffer berbuf;
169         BerElement *ber = (BerElement *)&berbuf;
170
171         struct berval entryuuid_bv      = { 0, NULL };
172
173         ber_init2( ber, 0, LBER_USE_DER );
174
175         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
176
177         ber_dupbv( &entryuuid_bv, &slog_e->sl_uuid );
178
179         if ( send_cookie && csn ) {
180                 ber_printf( ber, "{eOON}",
181                         entry_sync_state, &entryuuid_bv, csn );
182         } else {
183                 ber_printf( ber, "{eON}",
184                         entry_sync_state, &entryuuid_bv );
185         }
186
187         ch_free( entryuuid_bv.bv_val );
188         entryuuid_bv.bv_val = NULL;
189
190         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
191         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
192         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
193
194         ber_free_buf( ber );
195
196         if ( ret < 0 ) {
197 #ifdef NEW_LOGGING
198                 LDAP_LOG ( OPERATION, RESULTS, 
199                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
200                         0, 0, 0 );
201 #else
202                 Debug( LDAP_DEBUG_TRACE,
203                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
204                         0, 0, 0 );
205 #endif
206                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
207                 return ret;
208         }
209
210         return LDAP_SUCCESS;
211 }
212
213 void
214 slap_compose_sync_cookie(
215         Operation *op,
216         struct berval *cookie,
217         struct berval *csn,
218         int sid )
219 {
220         char cookiestr[ LDAP_LUTIL_CSNSTR_BUFSIZE + 10 ];
221
222         if ( csn->bv_val == NULL ) {
223                 if ( sid == -1 ) {
224                         cookiestr[0] = '\0';
225                 } else {
226                         snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 10,
227                                                 "sid=%03d", sid );
228                 }
229         } else if ( sid == -1 ) {
230                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 10,
231                                                 "csn=%s", csn->bv_val );
232         } else {
233                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 10,
234                                                 "csn=%s,sid=%03d", csn->bv_val, sid );
235         }
236         ber_str2bv( cookiestr, strlen(cookiestr), 1, cookie );
237 }
238
239 void
240 slap_sync_cookie_free(
241         struct sync_cookie *cookie,
242         int free_cookie
243 )
244 {
245         if ( cookie == NULL )
246                 return;
247
248         if ( cookie->ctxcsn ) {
249                 ber_bvarray_free( cookie->ctxcsn );
250                 cookie->ctxcsn = NULL;
251         }
252
253         if ( cookie->octet_str ) {
254                 ber_bvarray_free( cookie->octet_str );
255                 cookie->octet_str = NULL;
256         }
257
258         if ( free_cookie ) {
259                 ch_free( cookie );
260         }
261
262         return;
263 }
264
265 int
266 slap_parse_sync_cookie(
267         struct sync_cookie *cookie
268 )
269 {
270         char *csn_ptr;
271         char *csn_str;
272         char *sid_ptr;
273         char *sid_str;
274         char *cval;
275         struct berval *ctxcsn;
276
277         if ( cookie == NULL )
278                 return -1;
279
280         if (( csn_ptr = strstr( cookie->octet_str[0].bv_val, "csn=" )) != NULL ) {
281                 csn_str = (char *) strndup( csn_ptr, LDAP_LUTIL_CSNSTR_BUFSIZE );
282                 if ( cval = strchr( csn_str, ',' )) {
283                         *cval = '\0';
284                 }
285                 ctxcsn = ber_str2bv( csn_str + 4, strlen(csn_str) - 4, 1, NULL );
286                 ch_free( csn_str );
287                 ber_bvarray_add( &cookie->ctxcsn, ctxcsn );
288                 ch_free( ctxcsn );
289         } else {
290                 cookie->ctxcsn = NULL;
291         }
292
293         if (( sid_ptr = strstr( cookie->octet_str->bv_val, "sid=" )) != NULL ) {
294                 sid_str = (char *) strndup( sid_ptr, 7 );
295                 if ( cval = strchr( sid_str, ',' )) {
296                         *cval = '\0';
297                 }
298                 cookie->sid = atoi( sid_str+4 );
299                 ch_free( sid_str );
300         } else {
301                 cookie->sid = -1;
302         }
303 }
304
305 int
306 slap_init_sync_cookie_ctxcsn(
307         struct sync_cookie *cookie
308 )
309 {
310         char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE + 4 ];
311         struct berval octet_str = { 0, NULL };
312         struct berval ctxcsn = { 0, NULL };
313         struct berval ctxcsn_dup = { 0, NULL };
314         struct berval slap_syncCookie;
315
316         if ( cookie == NULL )
317                 return -1;
318
319         octet_str.bv_len = snprintf( csnbuf, LDAP_LUTIL_CSNSTR_BUFSIZE + 4,
320                                         "csn=%4d%02d%02d%02d:%02d:%02dZ#0x%04x#%d#%04x",
321                                         1900, 1, 1, 0, 0, 0, 0, 0, 0 );
322         octet_str.bv_val = csnbuf;
323         build_new_dn( &slap_syncCookie, &cookie->octet_str[0], &octet_str, NULL );
324         ber_bvarray_free( cookie->octet_str );
325         cookie->octet_str = NULL;
326         ber_bvarray_add( &cookie->octet_str, &slap_syncCookie );
327
328         ber_dupbv( &ctxcsn, &octet_str );
329         ctxcsn.bv_val += 4;
330         ctxcsn.bv_len -= 4;
331         ber_dupbv( &ctxcsn_dup, &ctxcsn );
332         ch_free( ctxcsn.bv_val );
333         ber_bvarray_add( &cookie->ctxcsn, &ctxcsn_dup );
334
335         return 0;
336 }
337
338 struct sync_cookie *
339 slap_dup_sync_cookie(
340         struct sync_cookie *dst,
341         struct sync_cookie *src
342 )
343 {
344         int i;
345         struct sync_cookie *new;
346         struct berval tmp_bv;
347
348         if ( src == NULL )
349                 return NULL;
350
351         if ( dst ) {
352                 ber_bvarray_free( dst->ctxcsn );
353                 ber_bvarray_free( dst->octet_str );
354                 new = dst;
355         } else {
356                 new = ( struct sync_cookie * )
357                                 ch_calloc( 1, sizeof( struct sync_cookie ));
358         }
359
360         new->sid = src->sid;
361
362         if ( src->ctxcsn ) {
363                 for ( i=0; src->ctxcsn[i].bv_val; i++ ) {
364                         ber_dupbv( &tmp_bv, &src->ctxcsn[i] );
365                         ber_bvarray_add( &new->ctxcsn, &tmp_bv );
366                 }
367         }
368
369         if ( src->octet_str ) {
370                 for ( i=0; src->octet_str[i].bv_val; i++ ) {
371                         ber_dupbv( &tmp_bv, &src->octet_str[i] );
372                         ber_bvarray_add( &new->octet_str, &tmp_bv );
373                 }
374         }
375
376         return new;
377 }