1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 1998-2011 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
52/*
53 * ldap_rename - initiate an ldap extended modifyDN operation.
54 *
55 * Parameters:
56 *	ld				LDAP descriptor
57 *	dn				DN of the object to modify
58 *	newrdn			RDN to give the object
59 *	deleteoldrdn	nonzero means to delete old rdn values from the entry
60 *	newSuperior		DN of the new parent if applicable
61 *
62 * Returns the LDAP error code.
63 */
64
65int
66ldap_rename(
67	LDAP *ld,
68	LDAP_CONST char *dn,
69	LDAP_CONST char *newrdn,
70	LDAP_CONST char *newSuperior,
71	int deleteoldrdn,
72	LDAPControl **sctrls,
73	LDAPControl **cctrls,
74	int *msgidp )
75{
76	BerElement	*ber;
77	int rc;
78	ber_int_t id;
79
80	Debug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 );
81
82	/* check client controls */
83	rc = ldap_int_client_controls( ld, cctrls );
84	if( rc != LDAP_SUCCESS ) return rc;
85
86	/* create a message to send */
87	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
88		return( LDAP_NO_MEMORY );
89	}
90
91	LDAP_NEXT_MSGID( ld, id );
92	if( newSuperior != NULL ) {
93		/* must be version 3 (or greater) */
94		if ( ld->ld_version < LDAP_VERSION3 ) {
95			ld->ld_errno = LDAP_NOT_SUPPORTED;
96			ber_free( ber, 1 );
97			return( ld->ld_errno );
98		}
99		rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */
100			id, LDAP_REQ_MODDN,
101			dn, newrdn, (ber_int_t) deleteoldrdn,
102			LDAP_TAG_NEWSUPERIOR, newSuperior );
103
104	} else {
105		rc = ber_printf( ber, "{it{ssbN}", /* '}' */
106			id, LDAP_REQ_MODDN,
107			dn, newrdn, (ber_int_t) deleteoldrdn );
108	}
109
110	if ( rc < 0 ) {
111		ld->ld_errno = LDAP_ENCODING_ERROR;
112		ber_free( ber, 1 );
113		return( ld->ld_errno );
114	}
115
116	/* Put Server Controls */
117	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
118		ber_free( ber, 1 );
119		return ld->ld_errno;
120	}
121
122	rc = ber_printf( ber, /*{*/ "N}" );
123	if ( rc < 0 ) {
124		ld->ld_errno = LDAP_ENCODING_ERROR;
125		ber_free( ber, 1 );
126		return( ld->ld_errno );
127	}
128
129	/* send the message */
130	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id );
131
132	if( *msgidp < 0 ) {
133		return( ld->ld_errno );
134	}
135
136	return LDAP_SUCCESS;
137}
138
139
140/*
141 * ldap_rename2 - initiate an ldap (and X.500) modifyDN operation. Parameters:
142 *	(LDAP V3 MODIFYDN REQUEST)
143 *	ld		LDAP descriptor
144 *	dn		DN of the object to modify
145 *	newrdn		RDN to give the object
146 *	deleteoldrdn	nonzero means to delete old rdn values from the entry
147 *	newSuperior	DN of the new parent if applicable
148 *
149 * ldap_rename2 uses a U-Mich Style API.  It returns the msgid.
150 */
151
152int
153ldap_rename2(
154	LDAP *ld,
155	LDAP_CONST char *dn,
156	LDAP_CONST char *newrdn,
157	LDAP_CONST char *newSuperior,
158	int deleteoldrdn )
159{
160	int msgid;
161	int rc;
162
163	Debug( LDAP_DEBUG_TRACE, "ldap_rename2\n", 0, 0, 0 );
164
165	rc = ldap_rename( ld, dn, newrdn, newSuperior,
166		deleteoldrdn, NULL, NULL, &msgid );
167
168	return rc == LDAP_SUCCESS ? msgid : -1;
169}
170
171
172/*
173 * ldap_modrdn2 - initiate an ldap modifyRDN operation. Parameters:
174 *
175 *	ld		LDAP descriptor
176 *	dn		DN of the object to modify
177 *	newrdn		RDN to give the object
178 *	deleteoldrdn	nonzero means to delete old rdn values from the entry
179 *
180 * Example:
181 *	msgid = ldap_modrdn( ld, dn, newrdn );
182 */
183int
184ldap_modrdn2( LDAP *ld,
185	LDAP_CONST char *dn,
186	LDAP_CONST char *newrdn,
187	int deleteoldrdn )
188{
189	return ldap_rename2( ld, dn, newrdn, NULL, deleteoldrdn );
190}
191
192int
193ldap_modrdn( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )
194{
195	return( ldap_rename2( ld, dn, newrdn, NULL, 1 ) );
196}
197
198
199int
200ldap_rename_s(
201	LDAP *ld,
202	LDAP_CONST char *dn,
203	LDAP_CONST char *newrdn,
204	LDAP_CONST char *newSuperior,
205	int deleteoldrdn,
206	LDAPControl **sctrls,
207	LDAPControl **cctrls )
208{
209	int rc;
210	int msgid;
211	LDAPMessage *res;
212
213	rc = ldap_rename( ld, dn, newrdn, newSuperior,
214		deleteoldrdn, sctrls, cctrls, &msgid );
215
216	if( rc != LDAP_SUCCESS ) {
217		return rc;
218	}
219
220	rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &res );
221
222	if( rc == -1 || !res ) {
223		return ld->ld_errno;
224	}
225
226	return ldap_result2error( ld, res, 1 );
227}
228
229int
230ldap_rename2_s(
231	LDAP *ld,
232	LDAP_CONST char *dn,
233	LDAP_CONST char *newrdn,
234	LDAP_CONST char *newSuperior,
235	int deleteoldrdn )
236{
237	return ldap_rename_s( ld, dn, newrdn, newSuperior,
238		deleteoldrdn, NULL, NULL );
239}
240
241int
242ldap_modrdn2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, int deleteoldrdn )
243{
244	return ldap_rename_s( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL );
245}
246
247int
248ldap_modrdn_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn )
249{
250	return ldap_rename_s( ld, dn, newrdn, NULL, 1, NULL, NULL );
251}
252
253