]> git.sur5r.net Git - openldap/blob - servers/slapd/ldapsync.c
adjust cookie precedence : command line cookie has higer precedence over stored cookie
[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   *cookie)
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 && cookie ) {
72                 ber_printf( ber, "{eOON}",
73                         entry_sync_state, &entryuuid_bv, cookie );
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 *cookie,
113         int                     refreshDeletes )
114 {
115         int ret;
116         BerElementBuffer berbuf;
117         BerElement *ber = (BerElement *)&berbuf;
118
119         ber_init2( ber, NULL, LBER_USE_DER );
120
121         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
122
123         ber_printf( ber, "{" );
124         if ( send_cookie && cookie ) {
125                 ber_printf( ber, "O", cookie );
126         }
127         if ( refreshDeletes == LDAP_SYNC_REFRESH_DELETES ) {
128                 ber_printf( ber, "b", refreshDeletes );
129         }
130         ber_printf( ber, "N}" );        
131
132         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
133         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
134         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
135
136         ber_free_buf( ber );
137
138         if ( ret < 0 ) {
139 #ifdef NEW_LOGGING
140                 LDAP_LOG ( OPERATION, RESULTS, 
141                         "slap_build_sync_done_ctrl: ber_flatten2 failed\n",
142                         0, 0, 0 );
143 #else
144                 Debug( LDAP_DEBUG_TRACE,
145                         "slap_build_sync_done_ctrl: ber_flatten2 failed\n",
146                         0, 0, 0 );
147 #endif
148                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
149                 return ret;
150         }
151
152         return LDAP_SUCCESS;
153 }
154
155
156 int
157 slap_build_sync_state_ctrl_from_slog(
158         Operation       *op,
159         SlapReply       *rs,
160         struct slog_entry *slog_e,
161         int                     entry_sync_state,
162         LDAPControl     **ctrls,
163         int                     num_ctrls,
164         int                     send_cookie,
165         struct berval   *cookie)
166 {
167         Attribute* a;
168         int ret;
169         int res;
170         const char *text = NULL;
171
172         BerElementBuffer berbuf;
173         BerElement *ber = (BerElement *)&berbuf;
174
175         struct berval entryuuid_bv      = { 0, NULL };
176
177         ber_init2( ber, 0, LBER_USE_DER );
178
179         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
180
181         ber_dupbv( &entryuuid_bv, &slog_e->sl_uuid );
182
183         if ( send_cookie && cookie ) {
184                 ber_printf( ber, "{eOON}",
185                         entry_sync_state, &entryuuid_bv, cookie );
186         } else {
187                 ber_printf( ber, "{eON}",
188                         entry_sync_state, &entryuuid_bv );
189         }
190
191         ch_free( entryuuid_bv.bv_val );
192         entryuuid_bv.bv_val = NULL;
193
194         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
195         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
196         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
197
198         ber_free_buf( ber );
199
200         if ( ret < 0 ) {
201 #ifdef NEW_LOGGING
202                 LDAP_LOG ( OPERATION, RESULTS, 
203                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
204                         0, 0, 0 );
205 #else
206                 Debug( LDAP_DEBUG_TRACE,
207                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
208                         0, 0, 0 );
209 #endif
210                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
211                 return ret;
212         }
213
214         return LDAP_SUCCESS;
215 }
216
217 int
218 slap_send_syncinfo(
219         Operation       *op,
220         SlapReply       *rs,
221         int                     type,
222         struct berval *cookie,
223         int                     refreshDone,
224         BerVarray       syncUUIDs,
225         int                     refreshDeletes )
226 {
227         BerElementBuffer berbuf;
228         BerElement *ber = (BerElement *)&berbuf;
229         struct berval rspdata;
230
231         int ret;
232
233         ber_init2( ber, NULL, LBER_USE_DER );
234
235         if ( type ) {
236                 switch ( type ) {
237                 case LDAP_TAG_SYNC_NEW_COOKIE:
238                         ber_printf( ber, "tO", type, cookie );
239                         break;
240                 case LDAP_TAG_SYNC_REFRESH_DELETE:
241                 case LDAP_TAG_SYNC_REFRESH_PRESENT:
242                         ber_printf( ber, "t{", type );
243                         if ( cookie ) {
244                                 ber_printf( ber, "O", cookie );
245                         }
246                         if ( refreshDone == 0 ) {
247                                 ber_printf( ber, "b", refreshDone );
248                         }
249                         ber_printf( ber, "N}" );
250                         break;
251                 case LDAP_TAG_SYNC_ID_SET:
252                         ber_printf( ber, "t{", type );
253                         if ( cookie ) {
254                                 ber_printf( ber, "O", cookie );
255                         }
256                         if ( refreshDeletes == 1 ) {
257                                 ber_printf( ber, "b", refreshDeletes );
258                         }
259                         ber_printf( ber, "[W]", syncUUIDs );
260                         ber_printf( ber, "N}" );
261                         break;
262                 default:
263 #ifdef NEW_LOGGING
264                         LDAP_LOG ( OPERATION, RESULTS,
265                                 "slap_send_syncinfo: invalid syncinfo type (%d)\n",
266                                 type, 0, 0 );
267 #else
268                         Debug( LDAP_DEBUG_TRACE,
269                                 "slap_send_syncinfo: invalid syncinfo type (%d)\n",
270                                 type, 0, 0 );
271 #endif
272                         return LDAP_OTHER;
273                 }
274         }
275
276         ret = ber_flatten2( ber, &rspdata, 0 );
277
278         if ( ret < 0 ) {
279 #ifdef NEW_LOGGING
280                 LDAP_LOG ( OPERATION, RESULTS,
281                         "slap_send_syncinfo: ber_flatten2 failed\n",
282                         0, 0, 0 );
283 #else
284                 Debug( LDAP_DEBUG_TRACE,
285                         "slap_send_syncinfo: ber_flatten2 failed\n",
286                         0, 0, 0 );
287 #endif
288                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
289                 return ret;
290         }
291
292         rs->sr_rspdata = &rspdata;
293         send_ldap_intermediate( op, rs );
294         rs->sr_rspdata = NULL;
295         ber_free_buf( ber );
296
297         return LDAP_SUCCESS;
298 }
299
300 void
301 slap_compose_sync_cookie(
302         Operation *op,
303         struct berval *cookie,
304         struct berval *csn,
305         int sid )
306 {
307         char cookiestr[ LDAP_LUTIL_CSNSTR_BUFSIZE + 10 ];
308
309         if ( csn->bv_val == NULL ) {
310                 if ( sid == -1 ) {
311                         cookiestr[0] = '\0';
312                 } else {
313                         snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 10,
314                                                 "sid=%03d", sid );
315                 }
316         } else if ( sid == -1 ) {
317                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 10,
318                                                 "csn=%s", csn->bv_val );
319         } else {
320                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 10,
321                                                 "csn=%s,sid=%03d", csn->bv_val, sid );
322         }
323         ber_str2bv( cookiestr, strlen(cookiestr), 1, cookie );
324 }
325
326 void
327 slap_sync_cookie_free(
328         struct sync_cookie *cookie,
329         int free_cookie
330 )
331 {
332         if ( cookie == NULL )
333                 return;
334
335         if ( cookie->ctxcsn ) {
336                 ber_bvarray_free( cookie->ctxcsn );
337                 cookie->ctxcsn = NULL;
338         }
339
340         if ( cookie->octet_str ) {
341                 ber_bvarray_free( cookie->octet_str );
342                 cookie->octet_str = NULL;
343         }
344
345         if ( free_cookie ) {
346                 ch_free( cookie );
347         }
348
349         return;
350 }
351
352 int
353 slap_parse_sync_cookie(
354         struct sync_cookie *cookie
355 )
356 {
357         char *csn_ptr;
358         char *csn_str;
359         char *sid_ptr;
360         char *sid_str;
361         char *cval;
362         struct berval *ctxcsn;
363
364         if ( cookie == NULL )
365                 return -1;
366
367         if (( csn_ptr = strstr( cookie->octet_str[0].bv_val, "csn=" )) != NULL ) {
368                 csn_str = (char *) strndup( csn_ptr, LDAP_LUTIL_CSNSTR_BUFSIZE );
369                 if ( cval = strchr( csn_str, ',' )) {
370                         *cval = '\0';
371                 }
372                 ctxcsn = ber_str2bv( csn_str + 4, strlen(csn_str) - 4, 1, NULL );
373                 ch_free( csn_str );
374                 ber_bvarray_add( &cookie->ctxcsn, ctxcsn );
375                 ch_free( ctxcsn );
376         } else {
377                 cookie->ctxcsn = NULL;
378         }
379
380         if (( sid_ptr = strstr( cookie->octet_str->bv_val, "sid=" )) != NULL ) {
381                 sid_str = (char *) strndup( sid_ptr, 7 );
382                 if ( cval = strchr( sid_str, ',' )) {
383                         *cval = '\0';
384                 }
385                 cookie->sid = atoi( sid_str+4 );
386                 ch_free( sid_str );
387         } else {
388                 cookie->sid = -1;
389         }
390 }
391
392 int
393 slap_init_sync_cookie_ctxcsn(
394         struct sync_cookie *cookie
395 )
396 {
397         char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE + 4 ];
398         struct berval octet_str = { 0, NULL };
399         struct berval ctxcsn = { 0, NULL };
400         struct berval ctxcsn_dup = { 0, NULL };
401         struct berval slap_syncCookie;
402
403         if ( cookie == NULL )
404                 return -1;
405
406         octet_str.bv_len = snprintf( csnbuf, LDAP_LUTIL_CSNSTR_BUFSIZE + 4,
407                                         "csn=%4d%02d%02d%02d:%02d:%02dZ#0x%04x#%d#%04x",
408                                         1900, 1, 1, 0, 0, 0, 0, 0, 0 );
409         octet_str.bv_val = csnbuf;
410         build_new_dn( &slap_syncCookie, &cookie->octet_str[0], &octet_str, NULL );
411         ber_bvarray_free( cookie->octet_str );
412         cookie->octet_str = NULL;
413         ber_bvarray_add( &cookie->octet_str, &slap_syncCookie );
414
415         ber_dupbv( &ctxcsn, &octet_str );
416         ctxcsn.bv_val += 4;
417         ctxcsn.bv_len -= 4;
418         ber_dupbv( &ctxcsn_dup, &ctxcsn );
419         ch_free( ctxcsn.bv_val );
420         ber_bvarray_add( &cookie->ctxcsn, &ctxcsn_dup );
421
422         return 0;
423 }
424
425 struct sync_cookie *
426 slap_dup_sync_cookie(
427         struct sync_cookie *dst,
428         struct sync_cookie *src
429 )
430 {
431         int i;
432         struct sync_cookie *new;
433         struct berval tmp_bv;
434
435         if ( src == NULL )
436                 return NULL;
437
438         if ( dst ) {
439                 ber_bvarray_free( dst->ctxcsn );
440                 ber_bvarray_free( dst->octet_str );
441                 new = dst;
442         } else {
443                 new = ( struct sync_cookie * )
444                                 ch_calloc( 1, sizeof( struct sync_cookie ));
445         }
446
447         new->sid = src->sid;
448
449         if ( src->ctxcsn ) {
450                 for ( i=0; src->ctxcsn[i].bv_val; i++ ) {
451                         ber_dupbv( &tmp_bv, &src->ctxcsn[i] );
452                         ber_bvarray_add( &new->ctxcsn, &tmp_bv );
453                 }
454         }
455
456         if ( src->octet_str ) {
457                 for ( i=0; src->octet_str[i].bv_val; i++ ) {
458                         ber_dupbv( &tmp_bv, &src->octet_str[i] );
459                         ber_bvarray_add( &new->octet_str, &tmp_bv );
460                 }
461         }
462
463         return new;
464 }