]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Add some MS AD controls
authorHoward Chu <hyc@openldap.org>
Sun, 18 Nov 2018 02:33:41 +0000 (18:33 -0800)
committerHoward Chu <hyc@openldap.org>
Sun, 18 Nov 2018 02:33:41 +0000 (18:33 -0800)
clients/tools/common.c
clients/tools/ldapsearch.c
include/ldap.h
libraries/libldap/Makefile.in
libraries/libldap/msctrl.c [new file with mode: 0644]

index 23829eada072ada88fc4e696f968d9f561a1ec26..14704b235037e3140c4a701b5c353676dba7c88a 100644 (file)
@@ -155,6 +155,9 @@ static int print_whatfailed( LDAP *ld, LDAPControl *ctrl );
 #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;
@@ -181,6 +184,9 @@ static struct tool_ctrls_t {
 #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 }
 };
 
@@ -2468,6 +2474,38 @@ print_syncdone( LDAP *ld, LDAPControl *ctrl )
        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 )
index 543c6cefbad16b3a0d55660f8718812ee44192cc..f0c062292a6a3cdb9d0e06359be188a2b5a6178e 100644 (file)
@@ -138,6 +138,16 @@ usage( void )
        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"));
@@ -245,6 +255,22 @@ static LDAPDerefSpec *ds;
 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 )
 {
@@ -625,6 +651,101 @@ handle_private_option( int i )
                        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;
@@ -923,6 +1044,15 @@ getNextPage:
 #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
@@ -1090,7 +1220,7 @@ getNextPage:
                        }
 
                        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
@@ -1122,6 +1252,54 @@ getNextPage:
                        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 );
index 1d42f0d05561995f87da9a1d479d51e6826a424d..c58c576d3ae0a3bf6ce46c2d672b6f13eff36296 100644 (file)
@@ -347,6 +347,14 @@ typedef struct ldapcontrol {
 
 /* 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"
@@ -2547,6 +2555,55 @@ ldap_parse_session_tracking_control LDAP_P((
 
 #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
  */
index cd902c99dc9aa038db76a5317a16d0484c42afec..afab839b5873e5577f154154fa25d0c1f5b095d0 100644 (file)
@@ -28,7 +28,8 @@ SRCS  = bind.c open.c result.c error.c compare.c search.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 \
@@ -41,7 +42,8 @@ OBJS  = bind.lo open.lo result.lo error.lo compare.lo search.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
diff --git a/libraries/libldap/msctrl.c b/libraries/libldap/msctrl.c
new file mode 100644 (file)
index 0000000..bbfc2f5
--- /dev/null
@@ -0,0 +1,262 @@
+/* $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 */