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