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