1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2011 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 */ 79int 80ldap_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 */ 176int 177ldap_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 191int 192ldap_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 210int 211ldap_modify_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods ) 212{ 213 return ldap_modify_ext_s( ld, dn, mods, NULL, NULL ); 214} 215 216