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 
39 int
ldap_create_dirsync_value(LDAP * ld,int flags,int maxAttrCount,struct berval * cookie,struct berval * value)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
ldap_create_dirsync_control(LDAP * ld,int flags,int maxAttrCount,struct berval * cookie,LDAPControl ** ctrlp)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
ldap_parse_dirsync_control(LDAP * ld,LDAPControl * ctrl,int * continueFlag,struct berval * cookie)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
ldap_create_show_deleted_control(LDAP * ld,LDAPControl ** ctrlp)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
ldap_create_extended_dn_value(LDAP * ld,int flag,struct berval * value)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
ldap_create_extended_dn_control(LDAP * ld,int flag,LDAPControl ** ctrlp)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
ldap_create_server_notification_control(LDAP * ld,LDAPControl ** ctrlp)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