1/*	$NetBSD: msctrl.c,v 1.2 2021/08/14 16:14:56 christos Exp $	*/
2
3/* $OpenLDAP$ */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2021 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.2 2021/08/14 16:14:56 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
39int
40ldap_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
85done:;
86	if ( ber != NULL ) {
87		ber_free( ber, 1 );
88	}
89
90	return ld->ld_errno;
91}
92
93int
94ldap_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
121int
122ldap_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
175int
176ldap_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
193int
194ldap_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
234done:;
235	if ( ber != NULL ) {
236		ber_free( ber, 1 );
237	}
238
239	return ld->ld_errno;
240}
241
242int
243ldap_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
271int
272ldap_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