Home | History | Annotate | Line # | Download | only in libldap
      1 /*	$NetBSD: msctrl.c,v 1.3 2025/09/05 21:16:21 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 The OpenLDAP Foundation.
      7  * Portions Copyright 2018 Howard Chu.
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted only as authorized by the OpenLDAP
     12  * Public License.
     13  *
     14  * A copy of this license is available in the file LICENSE in the
     15  * top-level directory of the distribution or, alternatively, at
     16  * <http://www.OpenLDAP.org/license.html>.
     17  */
     18 /* ACKNOWLEDGEMENTS:
     19  * This work was developed by Howard Chu for inclusion in
     20  * OpenLDAP Software.
     21  */
     22 
     23 #include <sys/cdefs.h>
     24 __RCSID("$NetBSD: msctrl.c,v 1.3 2025/09/05 21:16:21 christos Exp $");
     25 
     26 #include "portable.h"
     27 
     28 #include <stdio.h>
     29 #include <ac/stdlib.h>
     30 #include <ac/string.h>
     31 #include <ac/time.h>
     32 
     33 #include "ldap-int.h"
     34 
     35 /* MS Active Directory controls - not implemented in slapd(8) */
     36 
     37 #ifdef LDAP_CONTROL_X_DIRSYNC
     38 
     39 int
     40 ldap_create_dirsync_value(
     41 	LDAP		*ld,
     42 	int		flags,
     43 	int		maxAttrCount,
     44 	struct berval	*cookie,
     45 	struct berval	*value )
     46 {
     47 	BerElement	*ber = NULL;
     48 	ber_tag_t	tag;
     49 
     50 	if ( ld == NULL || cookie == NULL ||
     51 		value == NULL )
     52 	{
     53 		if ( ld ) {
     54 			ld->ld_errno = LDAP_PARAM_ERROR;
     55 		}
     56 
     57 		return LDAP_PARAM_ERROR;
     58 	}
     59 
     60 	assert( LDAP_VALID( ld ) );
     61 	ld->ld_errno = LDAP_SUCCESS;
     62 
     63 	/* maxAttrCount less than 0x100000 is treated as 0x100000 by server */
     64 
     65 	/* prepare value */
     66 	value->bv_val = NULL;
     67 	value->bv_len = 0;
     68 
     69 	ber = ldap_alloc_ber_with_options( ld );
     70 	if ( ber == NULL ) {
     71 		ld->ld_errno = LDAP_NO_MEMORY;
     72 		return ld->ld_errno;
     73 	}
     74 
     75 	tag = ber_printf( ber, "{iiO}", flags, maxAttrCount, cookie );
     76 	if ( tag == LBER_ERROR ) {
     77 		ld->ld_errno = LDAP_ENCODING_ERROR;
     78 		goto done;
     79 	}
     80 
     81 	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
     82 		ld->ld_errno = LDAP_NO_MEMORY;
     83 	}
     84 
     85 done:;
     86 	if ( ber != NULL ) {
     87 		ber_free( ber, 1 );
     88 	}
     89 
     90 	return ld->ld_errno;
     91 }
     92 
     93 int
     94 ldap_create_dirsync_control(
     95 	LDAP		*ld,
     96 	int			flags,
     97 	int			maxAttrCount,
     98 	struct berval	*cookie,
     99 	LDAPControl	**ctrlp )
    100 {
    101 	struct berval	value;
    102 
    103 	if ( ctrlp == NULL ) {
    104 		ld->ld_errno = LDAP_PARAM_ERROR;
    105 		return ld->ld_errno;
    106 	}
    107 
    108 	ld->ld_errno = ldap_create_dirsync_value( ld,
    109 		flags, maxAttrCount, cookie, &value );
    110 	if ( ld->ld_errno == LDAP_SUCCESS ) {
    111 		ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_DIRSYNC,
    112 			1, &value, 0, ctrlp );
    113 		if ( ld->ld_errno != LDAP_SUCCESS ) {
    114 			LDAP_FREE( value.bv_val );
    115 		}
    116 	}
    117 
    118 	return ld->ld_errno;
    119 }
    120 
    121 int
    122 ldap_parse_dirsync_control(
    123 	LDAP *ld,
    124 	LDAPControl *ctrl,
    125 	int *continueFlag,
    126 	struct berval *cookie )
    127 {
    128 	BerElement	*ber;
    129 	ber_tag_t	tag;
    130 	ber_len_t	len;
    131 	int unused;
    132 
    133 	if ( ld == NULL ||
    134 		ctrl == NULL ||
    135 		continueFlag == NULL ||
    136 		cookie == NULL )
    137 	{
    138 		if ( ld ) {
    139 			ld->ld_errno = LDAP_PARAM_ERROR;
    140 		}
    141 
    142 		/* NOTE: we want the caller to get all or nothing;
    143 		 * we could allow some of the pointers to be NULL,
    144 		 * if one does not want part of the data */
    145 		return LDAP_PARAM_ERROR;
    146 	}
    147 
    148 	*continueFlag = 0;
    149 	BER_BVZERO( cookie );
    150 
    151 	ber = ber_init( &ctrl->ldctl_value );
    152 
    153 	if ( ber == NULL ) {
    154 		ld->ld_errno = LDAP_NO_MEMORY;
    155 		return ld->ld_errno;
    156 	}
    157 
    158 	tag = ber_scanf( ber, "{iio}", continueFlag, &unused, cookie );
    159 	if ( tag == LBER_DEFAULT )
    160 		tag = LBER_ERROR;
    161 
    162 	(void)ber_free( ber, 1 );
    163 
    164 	if ( tag == LBER_ERROR ) {
    165 		return LDAP_DECODING_ERROR;
    166 	}
    167 
    168 	return ld->ld_errno;
    169 }
    170 
    171 #endif /* LDAP_CONTROL_X_DIRSYNC */
    172 
    173 #ifdef LDAP_CONTROL_X_SHOW_DELETED
    174 
    175 int
    176 ldap_create_show_deleted_control( LDAP *ld,
    177                                     LDAPControl **ctrlp )
    178 {
    179 	assert( ld != NULL );
    180 	assert( LDAP_VALID( ld ) );
    181 	assert( ctrlp != NULL );
    182 
    183 	ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SHOW_DELETED,
    184 		0, NULL, 0, ctrlp );
    185 
    186 	return ld->ld_errno;
    187 }
    188 
    189 #endif /* LDAP_CONTROL_X_SHOW_DELETED */
    190 
    191 #ifdef LDAP_CONTROL_X_EXTENDED_DN
    192 
    193 int
    194 ldap_create_extended_dn_value(
    195 	LDAP		*ld,
    196 	int			flag,
    197 	struct berval	*value )
    198 {
    199 	BerElement	*ber = NULL;
    200 	ber_tag_t	tag;
    201 
    202 	if ( ld == NULL ||
    203 		value == NULL )
    204 	{
    205 		if ( ld ) {
    206 			ld->ld_errno = LDAP_PARAM_ERROR;
    207 		}
    208 
    209 		return LDAP_PARAM_ERROR;
    210 	}
    211 
    212 	assert( LDAP_VALID( ld ) );
    213 	ld->ld_errno = LDAP_SUCCESS;
    214 
    215 	/* prepare value */
    216 	value->bv_val = NULL;
    217 	value->bv_len = 0;
    218 
    219 	ber = ldap_alloc_ber_with_options( ld );
    220 	if ( ber == NULL ) {
    221 		ld->ld_errno = LDAP_NO_MEMORY;
    222 		return ld->ld_errno;
    223 	}
    224 	tag = ber_printf( ber, "{i}", flag );
    225 	if ( tag == LBER_ERROR ) {
    226 		ld->ld_errno = LDAP_ENCODING_ERROR;
    227 		goto done;
    228 	}
    229 
    230 	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
    231 		ld->ld_errno = LDAP_NO_MEMORY;
    232 	}
    233 
    234 done:;
    235 	if ( ber != NULL ) {
    236 		ber_free( ber, 1 );
    237 	}
    238 
    239 	return ld->ld_errno;
    240 }
    241 
    242 int
    243 ldap_create_extended_dn_control(
    244 	LDAP		*ld,
    245 	int			flag,
    246 	LDAPControl	**ctrlp )
    247 {
    248 	struct berval	value;
    249 
    250 	if ( ctrlp == NULL ) {
    251 		ld->ld_errno = LDAP_PARAM_ERROR;
    252 		return ld->ld_errno;
    253 	}
    254 
    255 	ld->ld_errno = ldap_create_extended_dn_value( ld, flag, &value );
    256 	if ( ld->ld_errno == LDAP_SUCCESS ) {
    257 		ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_EXTENDED_DN,
    258 			0, &value, 0, ctrlp );
    259 		if ( ld->ld_errno != LDAP_SUCCESS ) {
    260 			LDAP_FREE( value.bv_val );
    261 		}
    262 	}
    263 
    264 	return ld->ld_errno;
    265 }
    266 
    267 #endif /* LDAP_CONTROL_X_EXTENDED_DN */
    268 
    269 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
    270 
    271 int
    272 ldap_create_server_notification_control( LDAP *ld,
    273                                     LDAPControl **ctrlp )
    274 {
    275 	assert( ld != NULL );
    276 	assert( LDAP_VALID( ld ) );
    277 	assert( ctrlp != NULL );
    278 
    279 	ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SERVER_NOTIFICATION,
    280 		0, NULL, 0, ctrlp );
    281 
    282 	return ld->ld_errno;
    283 }
    284 
    285 #endif /* LDAP_CONTROL_X_SERVER_NOTIFICATION */
    286