xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/modify.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: modify.c,v 1.3 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  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* Portions Copyright (c) 1990 Regents of the University of Michigan.
18  * All rights reserved.
19  */
20 
21 #include <sys/cdefs.h>
22 __RCSID("$NetBSD: modify.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
23 
24 #include "portable.h"
25 
26 #include <stdio.h>
27 
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31 
32 #include "ldap-int.h"
33 
34 /* A modify request/response looks like this:
35  *        ModifyRequest ::= [APPLICATION 6] SEQUENCE {
36  *             object          LDAPDN,
37  *             changes         SEQUENCE OF change SEQUENCE {
38  *                  operation       ENUMERATED {
39  *                       add     (0),
40  *                       delete  (1),
41  *                       replace (2),
42  *                       ...  },
43  *                  modification    PartialAttribute } }
44  *
45  *        PartialAttribute ::= SEQUENCE {
46  *             type       AttributeDescription,
47  *             vals       SET OF value AttributeValue }
48  *
49  *        AttributeDescription ::= LDAPString
50  *              -- Constrained to <attributedescription> [RFC4512]
51  *
52  *        AttributeValue ::= OCTET STRING
53  *
54  *        ModifyResponse ::= [APPLICATION 7] LDAPResult
55  *
56  * (Source: RFC 4511)
57  */
58 
59 BerElement *
ldap_build_modify_req(LDAP * ld,LDAP_CONST char * dn,LDAPMod ** mods,LDAPControl ** sctrls,LDAPControl ** cctrls,ber_int_t * msgidp)60 ldap_build_modify_req(
61 	LDAP *ld,
62 	LDAP_CONST char *dn,
63 	LDAPMod **mods,
64 	LDAPControl **sctrls,
65 	LDAPControl **cctrls,
66 	ber_int_t *msgidp )
67 {
68 	BerElement	*ber;
69 	int		i, rc;
70 
71 	/* create a message to send */
72 	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
73 		return( NULL );
74 	}
75 
76 	LDAP_NEXT_MSGID( ld, *msgidp );
77 	rc = ber_printf( ber, "{it{s{" /*}}}*/, *msgidp, LDAP_REQ_MODIFY, dn );
78 	if ( rc == -1 ) {
79 		ld->ld_errno = LDAP_ENCODING_ERROR;
80 		ber_free( ber, 1 );
81 		return( NULL );
82 	}
83 
84 	/* allow mods to be NULL ("touch") */
85 	if ( mods ) {
86 		/* for each modification to be performed... */
87 		for ( i = 0; mods[i] != NULL; i++ ) {
88 			if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
89 				rc = ber_printf( ber, "{e{s[V]N}N}",
90 				    (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ),
91 				    mods[i]->mod_type, mods[i]->mod_bvalues );
92 			} else {
93 				rc = ber_printf( ber, "{e{s[v]N}N}",
94 					(ber_int_t) mods[i]->mod_op,
95 				    mods[i]->mod_type, mods[i]->mod_values );
96 			}
97 
98 			if ( rc == -1 ) {
99 				ld->ld_errno = LDAP_ENCODING_ERROR;
100 				ber_free( ber, 1 );
101 				return( NULL );
102 			}
103 		}
104 	}
105 
106 	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
107 		ld->ld_errno = LDAP_ENCODING_ERROR;
108 		ber_free( ber, 1 );
109 		return( NULL );
110 	}
111 
112 	/* Put Server Controls */
113 	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
114 		ber_free( ber, 1 );
115 		return( NULL );
116 	}
117 
118 	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
119 		ld->ld_errno = LDAP_ENCODING_ERROR;
120 		ber_free( ber, 1 );
121 		return( NULL );
122 	}
123 
124 	return( ber );
125 }
126 
127 /*
128  * ldap_modify_ext - initiate an ldap extended modify operation.
129  *
130  * Parameters:
131  *
132  *	ld		LDAP descriptor
133  *	dn		DN of the object to modify
134  *	mods		List of modifications to make.  This is null-terminated
135  *			array of struct ldapmod's, specifying the modifications
136  *			to perform.
137  *	sctrls	Server Controls
138  *	cctrls	Client Controls
139  *	msgidp	Message ID pointer
140  *
141  * Example:
142  *	LDAPMod	*mods[] = {
143  *			{ LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
144  *			{ LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } },
145  *			{ LDAP_MOD_DELETE, "ou", 0 },
146  *			{ LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } }
147  *			0
148  *		}
149  *	rc=  ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid );
150  */
151 int
ldap_modify_ext(LDAP * ld,LDAP_CONST char * dn,LDAPMod ** mods,LDAPControl ** sctrls,LDAPControl ** cctrls,int * msgidp)152 ldap_modify_ext( LDAP *ld,
153 	LDAP_CONST char *dn,
154 	LDAPMod **mods,
155 	LDAPControl **sctrls,
156 	LDAPControl **cctrls,
157 	int *msgidp )
158 {
159 	BerElement	*ber;
160 	int		rc;
161 	ber_int_t	id;
162 
163 	Debug0( LDAP_DEBUG_TRACE, "ldap_modify_ext\n" );
164 
165 	/* check client controls */
166 	rc = ldap_int_client_controls( ld, cctrls );
167 	if( rc != LDAP_SUCCESS ) return rc;
168 
169 	ber = ldap_build_modify_req( ld, dn, mods, sctrls, cctrls, &id );
170 	if( !ber )
171 		return ld->ld_errno;
172 
173 	/* send the message */
174 	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id );
175 	return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
176 }
177 
178 /*
179  * ldap_modify - initiate an ldap modify operation.
180  *
181  * Parameters:
182  *
183  *	ld		LDAP descriptor
184  *	dn		DN of the object to modify
185  *	mods		List of modifications to make.  This is null-terminated
186  *			array of struct ldapmod's, specifying the modifications
187  *			to perform.
188  *
189  * Example:
190  *	LDAPMod	*mods[] = {
191  *			{ LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
192  *			{ LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } },
193  *			{ LDAP_MOD_DELETE, "ou", 0 },
194  *			{ LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } }
195  *			0
196  *		}
197  *	msgid = ldap_modify( ld, dn, mods );
198  */
199 int
ldap_modify(LDAP * ld,LDAP_CONST char * dn,LDAPMod ** mods)200 ldap_modify( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )
201 {
202 	int rc, msgid;
203 
204 	Debug0( LDAP_DEBUG_TRACE, "ldap_modify\n" );
205 
206 	rc = ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid );
207 
208 	if ( rc != LDAP_SUCCESS )
209 		return -1;
210 
211 	return msgid;
212 }
213 
214 int
ldap_modify_ext_s(LDAP * ld,LDAP_CONST char * dn,LDAPMod ** mods,LDAPControl ** sctrl,LDAPControl ** cctrl)215 ldap_modify_ext_s( LDAP *ld, LDAP_CONST char *dn,
216 	LDAPMod **mods, LDAPControl **sctrl, LDAPControl **cctrl )
217 {
218 	int		rc;
219 	int		msgid;
220 	LDAPMessage	*res;
221 
222 	rc = ldap_modify_ext( ld, dn, mods, sctrl, cctrl, &msgid );
223 
224 	if ( rc != LDAP_SUCCESS )
225 		return( rc );
226 
227 	if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res )
228 		return( ld->ld_errno );
229 
230 	return( ldap_result2error( ld, res, 1 ) );
231 }
232 
233 int
ldap_modify_s(LDAP * ld,LDAP_CONST char * dn,LDAPMod ** mods)234 ldap_modify_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )
235 {
236 	return ldap_modify_ext_s( ld, dn, mods, NULL, NULL );
237 }
238 
239