1 /* $NetBSD: modify.c,v 1.2 2020/08/11 13:15:37 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2020 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.2 2020/08/11 13:15:37 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 * 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 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 Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); 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 200 ldap_modify( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods ) 201 { 202 int rc, msgid; 203 204 Debug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 ); 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 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 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