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