Commit a9bfce12 authored by Howard Chu's avatar Howard Chu
Browse files

Add some MS AD controls

parent 2f276058
......@@ -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 )
......
......@@ -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 );
......
......@@ -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
*/
......
......@@ -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
......
/* $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 );