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