#endif
static int print_syncstate( LDAP *ld, LDAPControl *ctrl );
static int print_syncdone( LDAP *ld, LDAPControl *ctrl );
+#ifdef LDAP_CONTROL_X_DIRSYNC
+static int print_dirsync( LDAP *ld, LDAPControl *ctrl );
+#endif
static struct tool_ctrls_t {
const char *oid;
#endif
{ LDAP_CONTROL_SYNC_STATE, TOOL_SEARCH, print_syncstate },
{ LDAP_CONTROL_SYNC_DONE, TOOL_SEARCH, print_syncdone },
+#ifdef LDAP_CONTROL_X_DIRSYNC
+ { LDAP_CONTROL_X_DIRSYNC, TOOL_SEARCH, print_dirsync },
+#endif
{ NULL, 0, NULL }
};
return 0;
}
+#ifdef LDAP_CONTROL_X_DIRSYNC
+static int
+print_dirsync( LDAP *ld, LDAPControl *ctrl )
+{
+ int rc, continueFlag;
+ struct berval cookie;
+
+ rc = ldap_parse_dirsync_control( ld, ctrl,
+ &continueFlag, &cookie );
+ if ( rc == LDAP_SUCCESS ) {
+ printf(_("# DirSync control continueFlag=%d\n"), continueFlag );
+ if ( !BER_BVISNULL( &cookie )) {
+ if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
+ struct berval bv;
+
+ bv.bv_len = LUTIL_BASE64_ENCODE_LEN( cookie.bv_len ) + 1;
+ bv.bv_val = ber_memalloc( bv.bv_len + 1 );
+
+ bv.bv_len = lutil_b64_ntop(
+ (unsigned char *) cookie.bv_val, cookie.bv_len,
+ bv.bv_val, bv.bv_len );
+
+ printf(_("# cookie:: %s\n"), bv.bv_val );
+ ber_memfree( bv.bv_val );
+ } else {
+ printf(_("# cookie: %s\n"), cookie.bv_val );
+ }
+ }
+ }
+}
+#endif
+
#ifdef LDAP_CONTROL_AUTHZID_RESPONSE
static int
print_authzid( LDAP *ld, LDAPControl *ctrl )
fprintf( stderr, _(" (ldapv3-vlv-09 virtual list views)\n"));
#ifdef LDAP_CONTROL_X_DEREF
fprintf( stderr, _(" [!]deref=derefAttr:attr[,...][;derefAttr:attr[,...][;...]]\n"));
+#endif
+#ifdef LDAP_CONTROL_X_DIRSYNC
+ fprintf( stderr, _(" !dirSync=<flags>/<maxAttrCount>[/<cookie>]\n"));
+ fprintf( stderr, _(" (MS AD DirSync)\n"));
+#endif
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+ fprintf( stderr, _(" [!]extendedDn=<flag> (MS AD Extended DN\n"));
+#endif
+#ifdef LDAP_CONTROL_X_SHOW_DELETED
+ fprintf( stderr, _(" [!]showDeleted (MS AD Show Deleted)\n"));
#endif
fprintf( stderr, _(" [!]<oid>[=:<b64value>] (generic control; no response handling)\n"));
fprintf( stderr, _(" -f file read operations from `file'\n"));
static struct berval derefval;
#endif
+#ifdef LDAP_CONTROL_X_DIRSYNC
+static int dirSync;
+static int dirSyncFlags;
+static int dirSyncMaxAttrCount;
+static struct berval dirSyncCookie;
+#endif
+
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+static int extendedDn;
+static int extendedDnFlag;
+#endif
+
+#ifdef LDAP_CONTROL_X_SHOW_DELETED
+static int showDeleted;
+#endif
+
static int
ctrl_add( void )
{
ldap_memfree( specs );
#endif /* LDAP_CONTROL_X_DEREF */
+#ifdef LDAP_CONTROL_X_DIRSYNC
+ } else if ( strcasecmp( control, "dirSync" ) == 0 ) {
+ char *maxattrp;
+ char *cookiep;
+ int num, tmp;
+ if( dirSync ) {
+ fprintf( stderr,
+ _("dirSync control previously specified\n"));
+ exit( EXIT_FAILURE );
+ }
+ if ( cvalue == NULL ) {
+ fprintf( stderr, _("missing specification of dirSync control\n"));
+ exit( EXIT_FAILURE );
+ }
+ if( !crit ) {
+ fprintf( stderr,
+ _("dirSync: critical flag required\n") );
+ usage();
+ }
+ maxattrp = strchr( cvalue, '/' );
+ if ( maxattrp == NULL ) {
+ fprintf( stderr, _("dirSync control value \"%s\" invalid\n"),
+ cvalue );
+ exit( EXIT_FAILURE );
+ }
+ *maxattrp++ = '\0';
+ cookiep = strchr( maxattrp, '/' );
+ if ( cookiep != NULL ) {
+ *cookiep++ = '\0';
+ if ( *cookiep != '\0' ) {
+ ber_str2bv( cookiep, 0, 0, &dirSyncCookie );
+ }
+ }
+ num = sscanf( cvalue, "%d", &tmp );
+ if ( num != 1 ) {
+ fprintf( stderr,
+ _("Invalid value for dirSync, %s.\n"),
+ cvalue );
+ exit( EXIT_FAILURE );
+ }
+ dirSyncFlags = tmp;
+
+ num = sscanf( maxattrp, "%d", &tmp );
+ if ( num != 1 ) {
+ fprintf( stderr,
+ _("Invalid value for dirSync, %s.\n"),
+ maxattrp );
+ exit( EXIT_FAILURE );
+ }
+ dirSyncMaxAttrCount = tmp;
+
+ dirSync = 1 + crit;
+#endif /* LDAP_CONTROL_X_DIRSYNC */
+
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+ } else if ( strcasecmp( control, "extendedDn" ) == 0 ) {
+ int num, tmp;
+ if( extendedDn ) {
+ fprintf( stderr,
+ _("extendedDn control previously specified\n"));
+ exit( EXIT_FAILURE );
+ }
+ if ( cvalue == NULL ) {
+ fprintf( stderr, _("missing specification of extendedDn control\n"));
+ exit( EXIT_FAILURE );
+ }
+ num = sscanf( cvalue, "%d", &tmp );
+ if ( num != 1 ) {
+ fprintf( stderr,
+ _("Invalid value for extendedDn, %s.\n"),
+ cvalue );
+ exit( EXIT_FAILURE );
+ }
+
+ extendedDnFlag = tmp;
+ extendedDn = 1 + crit;
+#endif /* LDAP_CONTROL_X_EXTENDED_DN */
+
+#ifdef LDAP_CONTROL_X_SHOW_DELETED
+ } else if ( strcasecmp( control, "showDeleted" ) == 0 ) {
+ int num, tmp;
+ if( showDeleted ) {
+ fprintf( stderr,
+ _("showDeleted control previously specified\n"));
+ exit( EXIT_FAILURE );
+ }
+ if ( cvalue != NULL ) {
+ fprintf( stderr,
+ _("showDeleted: no control value expected\n") );
+ usage();
+ }
+
+ showDeleted = 1 + crit;
+#endif /* LDAP_CONTROL_X_SHOW_DELETED */
+
} else if ( tool_is_oid( control ) ) {
if ( c != NULL ) {
int i;
#endif
#ifdef LDAP_CONTROL_X_DEREF
|| derefcrit
+#endif
+#ifdef LDAP_CONTROL_X_DIRSYNC
+ || dirSync
+#endif
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+ || extendedDn
+#endif
+#ifdef LDAP_CONTROL_X_SHOW_DELETED
+ || showDeleted
#endif
|| domainScope
|| pagedResults
}
c[i].ldctl_oid = LDAP_CONTROL_VLVREQUEST;
- c[i].ldctl_iscritical = sss > 1;
+ c[i].ldctl_iscritical = vlv > 1;
i++;
}
#ifdef LDAP_CONTROL_X_DEREF
i++;
}
#endif /* LDAP_CONTROL_X_DEREF */
+#ifdef LDAP_CONTROL_X_DIRSYNC
+ if ( dirSync ) {
+ if ( ctrl_add() ) {
+ tool_exit( ld, EXIT_FAILURE );
+ }
+
+ if ( ldap_create_dirsync_value( ld,
+ dirSyncFlags, dirSyncMaxAttrCount, &dirSyncCookie,
+ &c[i].ldctl_value ) )
+ {
+ tool_exit( ld, EXIT_FAILURE );
+ }
+
+ c[i].ldctl_oid = LDAP_CONTROL_X_DIRSYNC;
+ c[i].ldctl_iscritical = dirSync > 1;
+ i++;
+ }
+#endif
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+ if ( extendedDn ) {
+ if ( ctrl_add() ) {
+ tool_exit( ld, EXIT_FAILURE );
+ }
+
+ if ( ldap_create_extended_dn_value( ld,
+ extendedDnFlag, &c[i].ldctl_value ) )
+ {
+ tool_exit( ld, EXIT_FAILURE );
+ }
+
+ c[i].ldctl_oid = LDAP_CONTROL_X_EXTENDED_DN;
+ c[i].ldctl_iscritical = extendedDn > 1;
+ i++;
+ }
+#endif
+#ifdef LDAP_CONTROL_X_SHOW_DELETED
+ if ( showDeleted ) {
+ if ( ctrl_add() ) {
+ tool_exit( ld, EXIT_FAILURE );
+ }
+
+ c[i].ldctl_oid = LDAP_CONTROL_X_SHOW_DELETED;
+ c[i].ldctl_value.bv_val = NULL;
+ c[i].ldctl_value.bv_len = 0;
+ c[i].ldctl_iscritical = showDeleted > 1;
+ i++;
+ }
+#endif
}
tool_server_controls( ld, c, i );
/* MS Active Directory controls - not implemented in slapd(8) */
#define LDAP_CONTROL_X_EXTENDED_DN "1.2.840.113556.1.4.529"
+#define LDAP_CONTROL_X_SHOW_DELETED "1.2.840.113556.1.4.417"
+#define LDAP_CONTROL_X_DIRSYNC "1.2.840.113556.1.4.841"
+
+#define LDAP_CONTROL_X_DIRSYNC_OBJECT_SECURITY 0x00000001
+#define LDAP_CONTROL_X_DIRSYNC_ANCESTORS_FIRST 0x00000800
+#define LDAP_CONTROL_X_DIRSYNC_PUBLIC_DATA_ONLY 0x00002000
+#define LDAP_CONTROL_X_DIRSYNC_INCREMENTAL_VALUES 0x80000000
+
/* <draft-wahl-ldap-session> */
#define LDAP_CONTROL_X_SESSION_TRACKING "1.3.6.1.4.1.21008.108.63.1"
#endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+/*
+ * in msctrl.c
+ */
+#ifdef LDAP_CONTROL_X_DIRSYNC
+LDAP_F( int )
+ldap_create_dirsync_value LDAP_P((
+ LDAP *ld,
+ int flags,
+ int maxAttrCount,
+ struct berval *cookie,
+ struct berval *value ));
+
+LDAP_F( int )
+ldap_create_dirsync_control LDAP_P((
+ LDAP *ld,
+ int flags,
+ int maxAttrCount,
+ struct berval *cookie,
+ LDAPControl **ctrlp ));
+
+LDAP_F( int )
+ldap_parse_dirsync_control LDAP_P((
+ LDAP *ld,
+ LDAPControl *ctrl,
+ int *continueFlag,
+ struct berval *cookie ));
+#endif /* LDAP_CONTROL_X_DIRSYNC */
+
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+LDAP_F( int )
+ldap_create_extended_dn_value LDAP_P((
+ LDAP *ld,
+ int flag,
+ struct berval *value ));
+
+LDAP_F( int )
+ldap_create_extended_dn_control LDAP_P((
+ LDAP *ld,
+ int flag,
+ LDAPControl **ctrlp ));
+#endif /* LDAP_CONTROL_X_EXTENDED_DN */
+
+#ifdef LDAP_CONTROL_X_SHOW_DELETED
+LDAP_F( int )
+ldap_create_show_deleted_control LDAP_P((
+ LDAP *ld,
+ LDAPControl **ctrlp ));
+#endif /* LDAP_CONTROL_X_SHOW_DELETED */
+
/*
* in assertion.c
*/
charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
tls2.c tls_o.c tls_g.c tls_m.c \
turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
- assertion.c deref.c ldifutil.c ldif.c fetch.c lbase64.c
+ assertion.c deref.c ldifutil.c ldif.c fetch.c lbase64.c \
+ msctrl.c
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
controls.lo messages.lo references.lo extended.lo cyrus.lo \
charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
tls2.lo tls_o.lo tls_g.lo tls_m.lo \
turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
- assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo lbase64.lo
+ assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo lbase64.lo \
+ msctrl.lo
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
--- /dev/null
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2018 The OpenLDAP Foundation.
+ * Portions Copyright 2018 Howard Chu.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was developed by Howard Chu for inclusion in
+ * OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+/* MS Active Directory controls - not implemented in slapd(8) */
+
+#ifdef LDAP_CONTROL_X_DIRSYNC
+
+int
+ldap_create_dirsync_value(
+ LDAP *ld,
+ int flags,
+ int maxAttrCount,
+ struct berval *cookie,
+ struct berval *value )
+{
+ BerElement *ber = NULL;
+ ber_tag_t tag;
+
+ if ( ld == NULL || cookie == NULL ||
+ value == NULL )
+ {
+ if ( ld ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ }
+
+ return LDAP_PARAM_ERROR;
+ }
+
+ assert( LDAP_VALID( ld ) );
+ ld->ld_errno = LDAP_SUCCESS;
+
+ /* maxAttrCount less than 0x100000 is treated as 0x100000 by server */
+
+ /* prepare value */
+ value->bv_val = NULL;
+ value->bv_len = 0;
+
+ ber = ldap_alloc_ber_with_options( ld );
+ if ( ber == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return ld->ld_errno;
+ }
+
+ tag = ber_printf( ber, "{iiO}", flags, maxAttrCount, cookie );
+ if ( tag == LBER_ERROR ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ goto done;
+ }
+
+ if ( ber_flatten2( ber, value, 1 ) == -1 ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ }
+
+done:;
+ if ( ber != NULL ) {
+ ber_free( ber, 1 );
+ }
+
+ return ld->ld_errno;
+}
+
+int
+ldap_create_dirsync_control(
+ LDAP *ld,
+ int flags,
+ int maxAttrCount,
+ struct berval *cookie,
+ LDAPControl **ctrlp )
+{
+ struct berval value;
+
+ if ( ctrlp == NULL ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return ld->ld_errno;
+ }
+
+ ld->ld_errno = ldap_create_dirsync_value( ld,
+ flags, maxAttrCount, cookie, &value );
+ if ( ld->ld_errno == LDAP_SUCCESS ) {
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_DIRSYNC,
+ 0, &value, 0, ctrlp );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
+ LDAP_FREE( value.bv_val );
+ }
+ }
+
+ return ld->ld_errno;
+}
+
+int
+ldap_parse_dirsync_control(
+ LDAP *ld,
+ LDAPControl *ctrl,
+ int *continueFlag,
+ struct berval *cookie )
+{
+ BerElement *ber;
+ ber_tag_t tag;
+ ber_len_t len;
+ int unused;
+
+ if ( ld == NULL ||
+ ctrl == NULL ||
+ continueFlag == NULL ||
+ cookie == NULL )
+ {
+ if ( ld ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ }
+
+ /* NOTE: we want the caller to get all or nothing;
+ * we could allow some of the pointers to be NULL,
+ * if one does not want part of the data */
+ return LDAP_PARAM_ERROR;
+ }
+
+ *continueFlag = 0;
+ BER_BVZERO( cookie );
+
+ ber = ber_init( &ctrl->ldctl_value );
+
+ if ( ber == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return ld->ld_errno;
+ }
+
+ tag = ber_scanf( ber, "{iio}", continueFlag, &unused, cookie );
+ if ( tag == LBER_DEFAULT )
+ tag = LBER_ERROR;
+
+ (void)ber_free( ber, 1 );
+
+ if ( tag == LBER_ERROR ) {
+ return LDAP_DECODING_ERROR;
+ }
+
+ return ld->ld_errno;
+}
+
+#endif /* LDAP_CONTROL_X_DIRSYNC */
+
+#ifdef LDAP_CONTROL_X_SHOW_DELETED
+
+int
+ldap_create_show_deleted_control( LDAP *ld,
+ LDAPControl **ctrlp )
+{
+ assert( ld != NULL );
+ assert( LDAP_VALID( ld ) );
+ assert( ctrlp != NULL );
+
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SHOW_DELETED,
+ 0, NULL, 0, ctrlp );
+
+ return ld->ld_errno;
+}
+
+#endif /* LDAP_CONTROL_X_SHOW_DELETED */
+
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+
+int
+ldap_create_extended_dn_value(
+ LDAP *ld,
+ int flag,
+ struct berval *value )
+{
+ BerElement *ber = NULL;
+ ber_tag_t tag;
+
+ if ( ld == NULL ||
+ value == NULL )
+ {
+ if ( ld ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ }
+
+ return LDAP_PARAM_ERROR;
+ }
+
+ assert( LDAP_VALID( ld ) );
+ ld->ld_errno = LDAP_SUCCESS;
+
+ /* prepare value */
+ value->bv_val = NULL;
+ value->bv_len = 0;
+
+ ber = ldap_alloc_ber_with_options( ld );
+ if ( ber == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return ld->ld_errno;
+ }
+ tag = ber_printf( ber, "{i}", flag );
+ if ( tag == LBER_ERROR ) {
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ goto done;
+ }
+
+ if ( ber_flatten2( ber, value, 1 ) == -1 ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ }
+
+done:;
+ if ( ber != NULL ) {
+ ber_free( ber, 1 );
+ }
+
+ return ld->ld_errno;
+}
+
+int
+ldap_create_extended_dn_control(
+ LDAP *ld,
+ int flag,
+ LDAPControl **ctrlp )
+{
+ struct berval value;
+
+ if ( ctrlp == NULL ) {
+ ld->ld_errno = LDAP_PARAM_ERROR;
+ return ld->ld_errno;
+ }
+
+ ld->ld_errno = ldap_create_extended_dn_value( ld, flag, &value );
+ if ( ld->ld_errno == LDAP_SUCCESS ) {
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_EXTENDED_DN,
+ 0, &value, 0, ctrlp );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
+ LDAP_FREE( value.bv_val );
+ }
+ }
+
+ return ld->ld_errno;
+}
+
+#endif /* LDAP_CONTROL_X_EXTENDED_DN */