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  *  modify.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_modify - initiate an ldap modify operation.  Parameters:
40  *
41  *	ld		LDAP descriptor
42  *	dn		DN of the object to modify
43  *	mods		List of modifications to make.  This is null-terminated
44  *			array of struct ldapmod's, specifying the modifications
45  *			to perform.
46  *
47  * Example:
48  *	LDAPMod	*mods[] = {
49  *			{ LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
50  *			{ LDAP_MOD_REPLACE, "sn", { "jensen", 0 } },
51  *			0
52  *		}
53  *	msgid = ldap_modify( ld, dn, mods );
54  */
55 int
56 LDAP_CALL
ldap_modify(LDAP * ld,const char * dn,LDAPMod ** mods)57 ldap_modify( LDAP *ld, const char *dn, LDAPMod **mods )
58 {
59 	int		msgid;
60 
61 	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 );
62 
63 	if ( ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid )
64 	    == LDAP_SUCCESS ) {
65 		return( msgid );
66 	} else {
67 		return( -1 );	/* error is in ld handle */
68 	}
69 }
70 
71 int
72 LDAP_CALL
ldap_modify_ext(LDAP * ld,const char * dn,LDAPMod ** mods,LDAPControl ** serverctrls,LDAPControl ** clientctrls,int * msgidp)73 ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods,
74     LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )
75 {
76 	BerElement	*ber;
77 	int		i, rc, lderr;
78 
79 	/*
80 	 * A modify request looks like this:
81 	 *	ModifyRequet ::= SEQUENCE {
82 	 *		object		DistinguishedName,
83 	 *		modifications	SEQUENCE OF SEQUENCE {
84 	 *			operation	ENUMERATED {
85 	 *				add	(0),
86 	 *				delete	(1),
87 	 *				replace	(2)
88 	 *			},
89 	 *			modification	SEQUENCE {
90 	 *				type	AttributeType,
91 	 *				values	SET OF AttributeValue
92 	 *			}
93 	 *		}
94 	 *	}
95 	 */
96 
97 	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 );
98 
99 	if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
100 		return( LDAP_PARAM_ERROR );
101 	}
102 	if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp ))
103         {
104 		LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
105 		return( LDAP_PARAM_ERROR );
106 	}
107 
108 	if ( !NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods )) {
109 		lderr = LDAP_PARAM_ERROR;
110 		LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
111 		return( lderr );
112 	}
113 	if ( dn == NULL ) {
114 		dn = "";
115 	}
116 
117 	LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
118 	*msgidp = ++ld->ld_msgid;
119 	LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
120 
121 	/* see if we should add to the cache */
122 	if ( ld->ld_cache_on && ld->ld_cache_modify != NULL ) {
123 		LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
124 		if ( (rc = (ld->ld_cache_modify)( ld, *msgidp, LDAP_REQ_MODIFY,
125 		    dn, mods )) != 0 ) {
126 			*msgidp = rc;
127 			LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
128 			return( LDAP_SUCCESS );
129 		}
130 		LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
131 	}
132 
133 	/* create a message to send */
134 	if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber ))
135 	    != LDAP_SUCCESS ) {
136 		return( lderr );
137 	}
138 
139 	if ( ber_printf( ber, "{it{s{", *msgidp, LDAP_REQ_MODIFY, dn )
140 	    == -1 ) {
141 		lderr = LDAP_ENCODING_ERROR;
142 		LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
143 		ber_free( ber, 1 );
144 		return( lderr );
145 	}
146 
147 	/* for each modification to be performed... */
148 	for ( i = 0; mods[i] != NULL; i++ ) {
149 		if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
150 			rc = ber_printf( ber, "{e{s[V]}}",
151 			    mods[i]->mod_op & ~LDAP_MOD_BVALUES,
152 			    mods[i]->mod_type, mods[i]->mod_bvalues );
153 		} else {
154 			rc = ber_printf( ber, "{e{s[v]}}", mods[i]->mod_op,
155 			    mods[i]->mod_type, mods[i]->mod_values );
156 		}
157 
158 		if ( rc == -1 ) {
159 			lderr = LDAP_ENCODING_ERROR;
160 			LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
161 			ber_free( ber, 1 );
162 			return( lderr );
163 		}
164 	}
165 
166 	if ( ber_printf( ber, "}}" ) == -1 ) {
167 		lderr = LDAP_ENCODING_ERROR;
168 		LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
169 		ber_free( ber, 1 );
170 		return( lderr );
171 	}
172 
173 	if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber ))
174 	    != LDAP_SUCCESS ) {
175 		ber_free( ber, 1 );
176 		return( lderr );
177 	}
178 
179 	/* send the message */
180 	rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODIFY,
181 		(char *)dn, ber );
182 	*msgidp = rc;
183 	return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
184 }
185 
186 int
187 LDAP_CALL
ldap_modify_s(LDAP * ld,const char * dn,LDAPMod ** mods)188 ldap_modify_s( LDAP *ld, const char *dn, LDAPMod **mods )
189 {
190 	return( ldap_modify_ext_s( ld, dn, mods, NULL, NULL ));
191 }
192 
193 int
194 LDAP_CALL
ldap_modify_ext_s(LDAP * ld,const char * dn,LDAPMod ** mods,LDAPControl ** serverctrls,LDAPControl ** clientctrls)195 ldap_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
196     LDAPControl **serverctrls, LDAPControl **clientctrls )
197 {
198 	int		msgid, err;
199 	LDAPMessage	*res;
200 
201 	if (( err = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls,
202 	    &msgid )) != LDAP_SUCCESS ) {
203 		return( err );
204 	}
205 
206 	if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) {
207 		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
208 	}
209 
210 	return( ldap_result2error( ld, res, 1 ) );
211 }
212