]> git.sur5r.net Git - openldap/blob - libraries/libldap/modify.c
Merge remote-tracking branch 'origin/mdb.RE/0.9'
[openldap] / libraries / libldap / modify.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2014 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
19 #include "portable.h"
20
21 #include <stdio.h>
22
23 #include <ac/socket.h>
24 #include <ac/string.h>
25 #include <ac/time.h>
26
27 #include "ldap-int.h"
28
29 /* A modify request/response looks like this:
30  *        ModifyRequest ::= [APPLICATION 6] SEQUENCE {              
31  *             object          LDAPDN,
32  *             changes         SEQUENCE OF change SEQUENCE {
33  *                  operation       ENUMERATED {      
34  *                       add     (0),                
35  *                       delete  (1),                 
36  *                       replace (2),
37  *                       ...  },
38  *                  modification    PartialAttribute } }                  
39  *
40  *        PartialAttribute ::= SEQUENCE {
41  *             type       AttributeDescription,
42  *             vals       SET OF value AttributeValue }
43  *
44  *        AttributeDescription ::= LDAPString           
45  *              -- Constrained to <attributedescription> [RFC4512]
46  *                                      
47  *        AttributeValue ::= OCTET STRING
48  *              
49  *        ModifyResponse ::= [APPLICATION 7] LDAPResult
50  *
51  * (Source: RFC 4511)
52  */
53
54
55 /*
56  * ldap_modify_ext - initiate an ldap extended modify operation.
57  *
58  * Parameters:
59  *
60  *      ld              LDAP descriptor
61  *      dn              DN of the object to modify
62  *      mods            List of modifications to make.  This is null-terminated
63  *                      array of struct ldapmod's, specifying the modifications
64  *                      to perform.
65  *      sctrls  Server Controls
66  *      cctrls  Client Controls
67  *      msgidp  Message ID pointer
68  *
69  * Example:
70  *      LDAPMod *mods[] = { 
71  *                      { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
72  *                      { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } },
73  *                      { LDAP_MOD_DELETE, "ou", 0 },
74  *                      { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } }
75  *                      0
76  *              }
77  *      rc=  ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid );
78  */
79 int
80 ldap_modify_ext( LDAP *ld,
81         LDAP_CONST char *dn,
82         LDAPMod **mods,
83         LDAPControl **sctrls,
84         LDAPControl **cctrls,
85         int *msgidp )
86 {
87         BerElement      *ber;
88         int             i, rc;
89         ber_int_t       id;
90
91         Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 );
92
93         /* check client controls */
94         rc = ldap_int_client_controls( ld, cctrls );
95         if( rc != LDAP_SUCCESS ) return rc;
96
97         /* create a message to send */
98         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
99                 return( LDAP_NO_MEMORY );
100         }
101
102         LDAP_NEXT_MSGID( ld, id );
103         rc = ber_printf( ber, "{it{s{" /*}}}*/, id, LDAP_REQ_MODIFY, dn );
104         if ( rc == -1 ) {
105                 ld->ld_errno = LDAP_ENCODING_ERROR;
106                 ber_free( ber, 1 );
107                 return( ld->ld_errno );
108         }
109
110         /* allow mods to be NULL ("touch") */
111         if ( mods ) {
112                 /* for each modification to be performed... */
113                 for ( i = 0; mods[i] != NULL; i++ ) {
114                         if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
115                                 rc = ber_printf( ber, "{e{s[V]N}N}",
116                                     (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ),
117                                     mods[i]->mod_type, mods[i]->mod_bvalues );
118                         } else {
119                                 rc = ber_printf( ber, "{e{s[v]N}N}",
120                                         (ber_int_t) mods[i]->mod_op,
121                                     mods[i]->mod_type, mods[i]->mod_values );
122                         }
123
124                         if ( rc == -1 ) {
125                                 ld->ld_errno = LDAP_ENCODING_ERROR;
126                                 ber_free( ber, 1 );
127                                 return( ld->ld_errno );
128                         }
129                 }
130         }
131
132         if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
133                 ld->ld_errno = LDAP_ENCODING_ERROR;
134                 ber_free( ber, 1 );
135                 return( ld->ld_errno );
136         }
137
138         /* Put Server Controls */
139         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
140                 ber_free( ber, 1 );
141                 return ld->ld_errno;
142         }
143
144         if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
145                 ld->ld_errno = LDAP_ENCODING_ERROR;
146                 ber_free( ber, 1 );
147                 return( ld->ld_errno );
148         }
149
150         /* send the message */
151         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id );
152         return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
153 }
154
155 /*
156  * ldap_modify - initiate an ldap modify operation.
157  *
158  * Parameters:
159  *
160  *      ld              LDAP descriptor
161  *      dn              DN of the object to modify
162  *      mods            List of modifications to make.  This is null-terminated
163  *                      array of struct ldapmod's, specifying the modifications
164  *                      to perform.
165  *
166  * Example:
167  *      LDAPMod *mods[] = { 
168  *                      { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
169  *                      { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } },
170  *                      { LDAP_MOD_DELETE, "ou", 0 },
171  *                      { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } }
172  *                      0
173  *              }
174  *      msgid = ldap_modify( ld, dn, mods );
175  */
176 int
177 ldap_modify( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )
178 {
179         int rc, msgid;
180
181         Debug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 );
182
183         rc = ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid );
184
185         if ( rc != LDAP_SUCCESS )
186                 return -1;
187
188         return msgid;
189 }
190
191 int
192 ldap_modify_ext_s( LDAP *ld, LDAP_CONST char *dn,
193         LDAPMod **mods, LDAPControl **sctrl, LDAPControl **cctrl )
194 {
195         int             rc;
196         int             msgid;
197         LDAPMessage     *res;
198
199         rc = ldap_modify_ext( ld, dn, mods, sctrl, cctrl, &msgid );
200
201         if ( rc != LDAP_SUCCESS )
202                 return( rc );
203
204         if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res )
205                 return( ld->ld_errno );
206
207         return( ldap_result2error( ld, res, 1 ) );
208 }
209
210 int
211 ldap_modify_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )
212 {
213         return ldap_modify_ext_s( ld, dn, mods, NULL, NULL );
214 }
215