1 /*
2  * The contents of this file are subject to the Netscape Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/NPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is Mozilla Communicator client code, released
13  * March 31, 1998.
14  *
15  * The Initial Developer of the Original Code is Netscape
16  * Communications Corporation. Portions created by Netscape are
17  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
18  * Rights Reserved.
19  *
20  * Contributor(s):
21  */
22 /*
23  *  Copyright (c) 1990 Regents of the University of Michigan.
24  *  All rights reserved.
25  */
26 /*
27  *  rename.c
28  */
29 
30 #if 0
31 #ifndef lint
32 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
33 #endif
34 #endif
35 
36 #include "ldap-int.h"
37 
38 /*
39  * ldap_rename - initiate an ldap modifyDN operation. Parameters:
40  *
41  *	ld		LDAP descriptor
42  *	dn		DN of the object to modify
43  *	newrdn		RDN that will form leftmost component of entry's new name
44  *      newparent       if present, this is the Distinguished Name of the entry
45  *                      which becomes the immediate parent of the existing entry
46  *	deleteoldrdn	nonzero means to delete old rdn values from the entry
47  *                      while zero means to retain them as attributes of the entry
48  *      serverctrls     list of LDAP server controls
49  *      clientctrls     list of client controls
50  *      msgidp          this result parameter will be set to the message id of the
51  *                      request if the ldap_rename() call succeeds
52  *
53  * Example:
54  *      int rc;
55  *	rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls, &msgid );
56  */
57 int
58 LDAP_CALL
ldap_rename(LDAP * ld,const char * dn,const char * newrdn,const char * newparent,int deleteoldrdn,LDAPControl ** serverctrls,LDAPControl ** clientctrls,int * msgidp)59 ldap_rename(
60 	   LDAP *ld,
61 	   const char *dn,
62 	   const char *newrdn,
63 	   const char *newparent,
64 	   int deleteoldrdn,
65 	   LDAPControl	**serverctrls,
66 	   LDAPControl	**clientctrls,  /* not used for anything yet */
67 	   int *msgidp
68 )
69 {
70 	BerElement	*ber;
71 	int		rc, err;
72 
73 	/*
74 	 * A modify dn request looks like this:
75 	 *	ModifyDNRequest ::= SEQUENCE {
76 	 *		entry		LDAPDN,
77 	 *		newrdn		RelativeLDAPDN,
78 	 *              newparent       [0] LDAPDN OPTIONAL,
79 	 *		deleteoldrdn	BOOLEAN
80 	 *	}
81 	 */
82 
83 	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 );
84 
85 	if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
86 		return( LDAP_PARAM_ERROR );
87 	}
88 	if ( NULL == newrdn) {
89 		LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
90 		return( LDAP_PARAM_ERROR );
91 	}
92 
93 	/* only ldapv3 or higher can do a proper rename
94 	 * (i.e. with non-NULL newparent and/or controls)
95 	 */
96 
97 	if (( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 )
98 	    && ((newparent != NULL) || (serverctrls != NULL)
99 	    || (clientctrls != NULL))) {
100 		LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
101 		return( LDAP_NOT_SUPPORTED );
102 	}
103 
104 	if ( msgidp == NULL ) {
105 		LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
106                 return( LDAP_PARAM_ERROR );
107         }
108 
109 	LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
110 	*msgidp = ++ld->ld_msgid;
111         LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
112 
113 	/* see if modRDN or modDN is handled by the cache */
114  	if ( ld->ld_cache_on ) {
115 		if ( newparent == NULL && ld->ld_cache_modrdn != NULL ) {
116 			LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
117 			if ( (rc = (ld->ld_cache_modrdn)( ld, *msgidp,
118 			    LDAP_REQ_MODRDN, dn, newrdn, deleteoldrdn ))
119 			    != 0 ) {
120 				*msgidp = rc;
121 				LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
122 				return( LDAP_SUCCESS );
123 			}
124 			LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
125 #if 0
126 		} else if ( ld->ld_cache_rename != NULL ) {
127 			LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
128 			if ( (rc = (ld->ld_cache_rename)( ld, *msgidp,
129 			    LDAP_REQ_MODDN, dn, newrdn, newparent,
130 			    deleteoldrdn )) != 0 ) {
131 				*msgidp = rc;
132 				return( LDAP_SUCCESS );
133 			}
134 			LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
135 #endif
136 		}
137 	}
138 
139 	/* create a message to send */
140 	if (( err = nsldapi_alloc_ber_with_options( ld, &ber ))
141 	    != LDAP_SUCCESS ) {
142 		return( err );
143 	}
144 
145 	/* fill it in */
146 	if ( ber_printf( ber, "{it{ssb", *msgidp, LDAP_REQ_MODDN, dn,
147 	    newrdn, deleteoldrdn ) == -1 ) {
148 		LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
149 		ber_free( ber, 1 );
150 		return( LDAP_ENCODING_ERROR );
151 	}
152 
153 	if ( newparent == NULL ) {
154 		if ( ber_printf( ber, "}" ) == -1 ) {
155 			LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
156 			ber_free( ber, 1 );
157 			return( LDAP_ENCODING_ERROR );
158 		}
159 	} else {
160 		if ( ber_printf( ber, "ts}", LDAP_TAG_NEWSUPERIOR, newparent )
161 		    == -1 ) {
162 			LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
163 			ber_free( ber, 1 );
164 			return( LDAP_ENCODING_ERROR );
165 		}
166 	}
167 
168 	if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber ))
169 	    != LDAP_SUCCESS ) {
170 		ber_free( ber, 1 );
171 		return( rc );
172 	}
173 
174 	/* send the message */
175 	rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODDN,
176 		(char *) dn, ber );
177 	*msgidp = rc;
178 	return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
179 }
180 
181 int
182 LDAP_CALL
ldap_modrdn2(LDAP * ld,const char * dn,const char * newrdn,int deleteoldrdn)183 ldap_modrdn2( LDAP *ld, const char *dn, const char *newrdn, int deleteoldrdn )
184 {
185 	int             msgid;
186 
187 	if ( ldap_rename( ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL, &msgid ) == LDAP_SUCCESS ) {
188 		return( msgid );
189 	} else {
190 		return( -1 );	/* error is in ld handle */
191 	}
192 }
193 
194 int
195 LDAP_CALL
ldap_modrdn(LDAP * ld,const char * dn,const char * newrdn)196 ldap_modrdn( LDAP *ld, const char *dn, const char *newrdn )
197 {
198 	return( ldap_modrdn2( ld, dn, newrdn, 1 ) );
199 }
200 
201 int
202 LDAP_CALL
ldap_rename_s(LDAP * ld,const char * dn,const char * newrdn,const char * newparent,int deleteoldrdn,LDAPControl ** serverctrls,LDAPControl ** clientctrls)203 ldap_rename_s(
204 	   LDAP *ld,
205 	   const char *dn,
206 	   const char *newrdn,
207 	   const char *newparent,
208 	   int deleteoldrdn,
209 	   LDAPControl	**serverctrls,
210 	   LDAPControl	**clientctrls  /* not used for anything yet */
211 )
212 {
213 	int		msgid;
214 	LDAPMessage	*res;
215 
216 	if ( ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls, &msgid ) != LDAP_SUCCESS ) {
217 		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
218 	}
219 
220  	if ( msgid == -1 )
221 		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
222 
223 	if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
224 		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
225 
226 	return( ldap_result2error( ld, res, 1 ) );
227 }
228 
229 int
230 LDAP_CALL
ldap_modrdn2_s(LDAP * ld,const char * dn,const char * newrdn,int deleteoldrdn)231 ldap_modrdn2_s( LDAP *ld, const char *dn, const char *newrdn, int deleteoldrdn )
232 {
233         int             msgid;
234         LDAPMessage     *res;
235 
236         if ( (msgid = ldap_modrdn2( ld, dn, newrdn, deleteoldrdn )) == -1 )
237                 return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
238 
239         if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
240                 return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
241 
242         return( ldap_result2error( ld, res, 1 ) );
243 }
244 
245 int
246 LDAP_CALL
ldap_modrdn_s(LDAP * ld,const char * dn,const char * newrdn)247 ldap_modrdn_s( LDAP *ld, const char *dn, const char *newrdn )
248 {
249 	return( ldap_modrdn2_s( ld, dn, newrdn, 1 ) );
250 }
251