1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2021 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* Portions Copyright (c) 1990 Regents of the University of Michigan.
16  * All rights reserved.
17  */
18 /* Copyright 1999, Juan C. Gomez, All rights reserved.
19  * This software is not subject to any license of Silicon Graphics
20  * Inc. or Purdue University.
21  *
22  * Redistribution and use in source and binary forms are permitted
23  * without restriction or fee of any kind as long as this notice
24  * is preserved.
25  */
26 
27 /* ACKNOWLEDGEMENTS:
28  * 	Juan C. Gomez
29  */
30 
31 #include "portable.h"
32 
33 #include <stdio.h>
34 
35 #include <ac/socket.h>
36 #include <ac/string.h>
37 #include <ac/time.h>
38 
39 #include "ldap-int.h"
40 
41 /*
42  * A modify rdn request looks like this:
43  *	ModifyRDNRequest ::= SEQUENCE {
44  *		entry		DistinguishedName,
45  *		newrdn		RelativeDistinguishedName,
46  *		deleteoldrdn	BOOLEAN
47  *		newSuperior	[0] DistinguishedName	[v3 only]
48  *	}
49  */
50 
51 BerElement *
ldap_build_moddn_req(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn,LDAP_CONST char * newSuperior,int deleteoldrdn,LDAPControl ** sctrls,LDAPControl ** cctrls,ber_int_t * msgidp)52 ldap_build_moddn_req(
53 	LDAP *ld,
54 	LDAP_CONST char *dn,
55 	LDAP_CONST char *newrdn,
56 	LDAP_CONST char *newSuperior,
57 	int deleteoldrdn,
58 	LDAPControl **sctrls,
59 	LDAPControl **cctrls,
60 	ber_int_t *msgidp )
61 {
62 	BerElement	*ber;
63 	int rc;
64 
65 	/* create a message to send */
66 	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
67 		return( NULL );
68 	}
69 
70 	LDAP_NEXT_MSGID( ld, *msgidp );
71 	if( newSuperior != NULL ) {
72 		/* must be version 3 (or greater) */
73 		if ( ld->ld_version < LDAP_VERSION3 ) {
74 			ld->ld_errno = LDAP_NOT_SUPPORTED;
75 			ber_free( ber, 1 );
76 			return( NULL );
77 		}
78 		rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */
79 			*msgidp, LDAP_REQ_MODDN,
80 			dn, newrdn, (ber_int_t) deleteoldrdn,
81 			LDAP_TAG_NEWSUPERIOR, newSuperior );
82 
83 	} else {
84 		rc = ber_printf( ber, "{it{ssbN}", /* '}' */
85 			*msgidp, LDAP_REQ_MODDN,
86 			dn, newrdn, (ber_int_t) deleteoldrdn );
87 	}
88 
89 	if ( rc < 0 ) {
90 		ld->ld_errno = LDAP_ENCODING_ERROR;
91 		ber_free( ber, 1 );
92 		return( NULL );
93 	}
94 
95 	/* Put Server Controls */
96 	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
97 		ber_free( ber, 1 );
98 		return( NULL );
99 	}
100 
101 	rc = ber_printf( ber, /*{*/ "N}" );
102 	if ( rc < 0 ) {
103 		ld->ld_errno = LDAP_ENCODING_ERROR;
104 		ber_free( ber, 1 );
105 		return( NULL );
106 	}
107 
108 	return( ber );
109 }
110 
111 /*
112  * ldap_rename - initiate an ldap extended modifyDN operation.
113  *
114  * Parameters:
115  *	ld				LDAP descriptor
116  *	dn				DN of the object to modify
117  *	newrdn			RDN to give the object
118  *	deleteoldrdn	nonzero means to delete old rdn values from the entry
119  *	newSuperior		DN of the new parent if applicable
120  *
121  * Returns the LDAP error code.
122  */
123 
124 int
ldap_rename(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn,LDAP_CONST char * newSuperior,int deleteoldrdn,LDAPControl ** sctrls,LDAPControl ** cctrls,int * msgidp)125 ldap_rename(
126 	LDAP *ld,
127 	LDAP_CONST char *dn,
128 	LDAP_CONST char *newrdn,
129 	LDAP_CONST char *newSuperior,
130 	int deleteoldrdn,
131 	LDAPControl **sctrls,
132 	LDAPControl **cctrls,
133 	int *msgidp )
134 {
135 	BerElement	*ber;
136 	int rc;
137 	ber_int_t id;
138 
139 	Debug0( LDAP_DEBUG_TRACE, "ldap_rename\n" );
140 
141 	/* check client controls */
142 	rc = ldap_int_client_controls( ld, cctrls );
143 	if( rc != LDAP_SUCCESS ) return rc;
144 
145 	ber = ldap_build_moddn_req( ld, dn, newrdn, newSuperior,
146 		deleteoldrdn, sctrls, cctrls, &id );
147 	if( !ber )
148 		return ld->ld_errno;
149 
150 	/* send the message */
151 	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id );
152 
153 	if( *msgidp < 0 ) {
154 		return( ld->ld_errno );
155 	}
156 
157 	return LDAP_SUCCESS;
158 }
159 
160 
161 /*
162  * ldap_rename2 - initiate an ldap (and X.500) modifyDN operation. Parameters:
163  *	(LDAP V3 MODIFYDN REQUEST)
164  *	ld		LDAP descriptor
165  *	dn		DN of the object to modify
166  *	newrdn		RDN to give the object
167  *	deleteoldrdn	nonzero means to delete old rdn values from the entry
168  *	newSuperior	DN of the new parent if applicable
169  *
170  * ldap_rename2 uses a U-Mich Style API.  It returns the msgid.
171  */
172 
173 int
ldap_rename2(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn,LDAP_CONST char * newSuperior,int deleteoldrdn)174 ldap_rename2(
175 	LDAP *ld,
176 	LDAP_CONST char *dn,
177 	LDAP_CONST char *newrdn,
178 	LDAP_CONST char *newSuperior,
179 	int deleteoldrdn )
180 {
181 	int msgid;
182 	int rc;
183 
184 	Debug0( LDAP_DEBUG_TRACE, "ldap_rename2\n" );
185 
186 	rc = ldap_rename( ld, dn, newrdn, newSuperior,
187 		deleteoldrdn, NULL, NULL, &msgid );
188 
189 	return rc == LDAP_SUCCESS ? msgid : -1;
190 }
191 
192 
193 /*
194  * ldap_modrdn2 - initiate an ldap modifyRDN operation. Parameters:
195  *
196  *	ld		LDAP descriptor
197  *	dn		DN of the object to modify
198  *	newrdn		RDN to give the object
199  *	deleteoldrdn	nonzero means to delete old rdn values from the entry
200  *
201  * Example:
202  *	msgid = ldap_modrdn( ld, dn, newrdn );
203  */
204 int
ldap_modrdn2(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn,int deleteoldrdn)205 ldap_modrdn2( LDAP *ld,
206 	LDAP_CONST char *dn,
207 	LDAP_CONST char *newrdn,
208 	int deleteoldrdn )
209 {
210 	return ldap_rename2( ld, dn, newrdn, NULL, deleteoldrdn );
211 }
212 
213 int
ldap_modrdn(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn)214 ldap_modrdn( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )
215 {
216 	return( ldap_rename2( ld, dn, newrdn, NULL, 1 ) );
217 }
218 
219 
220 int
ldap_rename_s(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn,LDAP_CONST char * newSuperior,int deleteoldrdn,LDAPControl ** sctrls,LDAPControl ** cctrls)221 ldap_rename_s(
222 	LDAP *ld,
223 	LDAP_CONST char *dn,
224 	LDAP_CONST char *newrdn,
225 	LDAP_CONST char *newSuperior,
226 	int deleteoldrdn,
227 	LDAPControl **sctrls,
228 	LDAPControl **cctrls )
229 {
230 	int rc;
231 	int msgid;
232 	LDAPMessage *res;
233 
234 	rc = ldap_rename( ld, dn, newrdn, newSuperior,
235 		deleteoldrdn, sctrls, cctrls, &msgid );
236 
237 	if( rc != LDAP_SUCCESS ) {
238 		return rc;
239 	}
240 
241 	rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &res );
242 
243 	if( rc == -1 || !res ) {
244 		return ld->ld_errno;
245 	}
246 
247 	return ldap_result2error( ld, res, 1 );
248 }
249 
250 int
ldap_rename2_s(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn,LDAP_CONST char * newSuperior,int deleteoldrdn)251 ldap_rename2_s(
252 	LDAP *ld,
253 	LDAP_CONST char *dn,
254 	LDAP_CONST char *newrdn,
255 	LDAP_CONST char *newSuperior,
256 	int deleteoldrdn )
257 {
258 	return ldap_rename_s( ld, dn, newrdn, newSuperior,
259 		deleteoldrdn, NULL, NULL );
260 }
261 
262 int
ldap_modrdn2_s(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn,int deleteoldrdn)263 ldap_modrdn2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn )
264 {
265 	return ldap_rename_s( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL );
266 }
267 
268 int
ldap_modrdn_s(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * newrdn)269 ldap_modrdn_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )
270 {
271 	return ldap_rename_s( ld, dn, newrdn, NULL, 1, NULL, NULL );
272 }
273 
274