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