]> git.sur5r.net Git - openldap/blob - servers/slapd/ldapsync.c
cleanup
[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 *csn_str_val;
360         char *sid_ptr;
361         char *sid_str;
362         char *sid_str_val;
363         char *cval;
364         struct berval *ctxcsn;
365
366         if ( cookie == NULL )
367                 return -1;
368
369         if (( csn_ptr = strstr( cookie->octet_str[0].bv_val, "csn=" )) != NULL ) {
370                 csn_str = (char *) SLAP_STRNDUP( csn_ptr, LDAP_LUTIL_CSNSTR_BUFSIZE );
371                 csn_str_val = csn_str + sizeof("csn=") - 1;
372                 if ( cval = strchr( csn_str, ',' )) {
373                         *cval = '\0';
374                 }
375                 ctxcsn = ber_str2bv( csn_str_val, strlen(csn_str_val), 1, NULL );
376                 ch_free( csn_str );
377                 ber_bvarray_add( &cookie->ctxcsn, ctxcsn );
378                 ch_free( ctxcsn );
379         } else {
380                 cookie->ctxcsn = NULL;
381         }
382
383         if (( sid_ptr = strstr( cookie->octet_str->bv_val, "sid=" )) != NULL ) {
384                 sid_str = (char *) SLAP_STRNDUP( sid_ptr,
385                                                         SLAP_SYNC_SID_SIZE + sizeof("sid=") - 1 );
386                 sid_str_val = sid_str + sizeof("sid=") - 1;
387                 if ( cval = strchr( sid_str, ',' )) {
388                         *cval = '\0';
389                 }
390                 cookie->sid = atoi( sid_str_val );
391                 ch_free( sid_str );
392         } else {
393                 cookie->sid = -1;
394         }
395 }
396
397 int
398 slap_init_sync_cookie_ctxcsn(
399         struct sync_cookie *cookie
400 )
401 {
402         char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE + 4 ];
403         struct berval octet_str = { 0, NULL };
404         struct berval ctxcsn = { 0, NULL };
405         struct berval ctxcsn_dup = { 0, NULL };
406         struct berval slap_syncCookie;
407
408         if ( cookie == NULL )
409                 return -1;
410
411         octet_str.bv_len = snprintf( csnbuf, LDAP_LUTIL_CSNSTR_BUFSIZE + 4,
412                                         "csn=%4d%02d%02d%02d:%02d:%02dZ#0x%04x#%d#%04x",
413                                         1900, 1, 1, 0, 0, 0, 0, 0, 0 );
414         octet_str.bv_val = csnbuf;
415         build_new_dn( &slap_syncCookie, &cookie->octet_str[0], &octet_str, NULL );
416         ber_bvarray_free( cookie->octet_str );
417         cookie->octet_str = NULL;
418         ber_bvarray_add( &cookie->octet_str, &slap_syncCookie );
419
420         ber_dupbv( &ctxcsn, &octet_str );
421         ctxcsn.bv_val += 4;
422         ctxcsn.bv_len -= 4;
423         ber_dupbv( &ctxcsn_dup, &ctxcsn );
424         ch_free( ctxcsn.bv_val );
425         ber_bvarray_add( &cookie->ctxcsn, &ctxcsn_dup );
426
427         return 0;
428 }
429
430 struct sync_cookie *
431 slap_dup_sync_cookie(
432         struct sync_cookie *dst,
433         struct sync_cookie *src
434 )
435 {
436         int i;
437         struct sync_cookie *new;
438         struct berval tmp_bv;
439
440         if ( src == NULL )
441                 return NULL;
442
443         if ( dst ) {
444                 ber_bvarray_free( dst->ctxcsn );
445                 ber_bvarray_free( dst->octet_str );
446                 new = dst;
447         } else {
448                 new = ( struct sync_cookie * )
449                                 ch_calloc( 1, sizeof( struct sync_cookie ));
450         }
451
452         new->sid = src->sid;
453
454         if ( src->ctxcsn ) {
455                 for ( i=0; src->ctxcsn[i].bv_val; i++ ) {
456                         ber_dupbv( &tmp_bv, &src->ctxcsn[i] );
457                         ber_bvarray_add( &new->ctxcsn, &tmp_bv );
458                 }
459         }
460
461         if ( src->octet_str ) {
462                 for ( i=0; src->octet_str[i].bv_val; i++ ) {
463                         ber_dupbv( &tmp_bv, &src->octet_str[i] );
464                         ber_bvarray_add( &new->octet_str, &tmp_bv );
465                 }
466         }
467
468         return new;
469 }