The LDAP modify operation can be used to make one or more changes to the set of attribute values in an entry. All of the changes in a modify request are processed atomically, so either all of the changes are applied to the entry, or none of them are, and clients will never see the entry in an intermediate state with only a portion of the changes applied. However, changes (whether to the same entry or different entries) spread across multiple modify requests are not atomic unless they’re part of an LDAP transaction.
The modify request protocol operation is defined as follows in RFC 4511 section 4.6:
ModifyRequest ::= [APPLICATION 6] SEQUENCE { object LDAPDN, changes SEQUENCE OF change SEQUENCE { operation ENUMERATED { add (0), delete (1), replace (2), ... }, modification PartialAttribute } }
And its dependencies from elsewhere in RFC 4511 are:
LDAPDN ::= LDAPString -- Constrained to <distinguishedName> -- [RFC4514] PartialAttribute ::= SEQUENCE { type AttributeDescription, vals SET OF value AttributeValue } LDAPString ::= OCTET STRING -- UTF-8 encoded, -- [ISO10646] characters AttributeDescription ::= LDAPString -- Constrained to <attributedescription> -- [RFC4512] AttributeValue ::= OCTET STRING
So a modify request protocol op is encoded as a sequence that contains a DN and a sequence of changes. And each of those changes contains a change type, an attribute description (an attribute name or OID and zero or more attribute options), and an optional set of values.
The change types defined in RFC 4511 (in the operation enumerated element of a change sequence) are:
For example, let’s say that we want to apply the following set of modifications to the uid=jdoe,ou=People,dc=example,dc=com entry:
dn: uid=jdoe,ou=People,dc=example,dc=com changetype: modify delete: givenName givenName: John - add: givenName givenName: Jonathan - replace: cn cn: Jonathan Doe
If the modify request has a message ID of two and no request controls, then it would be encoded as:
30 81 80 -- Begin the LDAPMessage sequence 02 01 02 -- The message ID (integer value 2) 66 7b -- Begin the modify request protocol op 04 24 75 69 64 3d 6a 64 6f 65 -- The DN of the entry to modify (octet string 2c 6f 75 3d 50 65 6f 70 -- "uid=jdoe,ou=People,dc=example,dc=com") 6c 65 2c 64 63 3d 65 78 61 6d 70 6c 65 2c 64 63 3d 63 6f 6d 30 53 -- Begin the sequence of modifications 30 18 -- Begin the sequence for the first modification 0a 01 01 -- The delete modification type (enumerated value 1) 30 13 -- Begin the attribute sequence 04 09 67 69 76 65 6e 4e 61 6d -- The attribute description 65 -- (octet string "givenName") 31 06 -- Begin the attribute value set 04 04 4a 6f 68 6e -- The attribute value (octet string "John") 30 1c -- Begin the sequence for the second modification 0a 01 00 -- The add modification type (enumerated value 0) 30 17 -- Begin the attribute sequence 04 09 67 69 76 65 6e 4e 61 6d -- The attribute description 65 -- (octet string "givenName") 31 0a -- Begin the attribute value set 04 08 4a 6f 6e 61 74 68 61 6e -- The attribute value -- (octet string "Jonathan") 30 19 -- Begin the sequence for the third modification 0a 01 02 -- The replace modification type (enumerated value 2) 30 14 -- Begin the attribute sequence 04 02 63 6e -- The attribute description (octet string "cn") 31 0e -- Begin the attribute value set 04 0c 4a 6f 6e 61 74 68 61 6e -- The attribute value 20 44 6f 65 -- (octet string "Jonathan Doe")
The modify response protocol operation is also defined in RFC 4511 section 4.6. That definition is:
ModifyResponse ::= [APPLICATION 7] LDAPResult
As with most response protocol ops, this is just an LDAPResult (which we’ve already covered in an earlier section), this time with BER type 0x67 (application class, constructed, tag number seven). So a successful response to the above modify request would look like:
30 0c -- Begin the LDAPMessage sequence 02 01 02 -- The message ID (integer value 2) 67 07 -- Begin the modify response protocol op 0a 01 00 -- success result code (enumerated value 0) 04 00 -- No matched DN (0-byte octet string) 04 00 -- No diagnostic message (0-byte octet string)
The core LDAPv3 specification in RFC 4511 defines three modification types. But if you look closely at the ASN.1 definition for the operation enumerated element listed above in the modify request protocol operation, you’ll see that it uses “...” to indicate that additional modification types may be added in the future. And, in fact, RFC 4525 does introduce a new modification type. That is the increment modification type, which has an enumerated value of 3.
The increment modification type may be used to request that the server atomically increase the integer value of a single-valued attribute by a specified amount (or atomically decrease the value of that attribute if the increment amount is negative). This modification type can only be used under the following circumstances:
The primary benefit of the increment modification type is that you can use it to increase or decrease an attribute value by a specified amount without needing to know the current value in advance, and without needing to worry about any other changes that might affect the same entry around the same time. It’s often used in conjunction with the LDAP pre-read or post-read control (RFC 4527) to have the server send the value of the specified attribute as it appeared either immediately before or immediately after the operation was processed, and potentially in conjunction with the LDAP assertion control (RFC 4528) to indicate that the operation should only be processed if the entry matches a provided filter.
For example, let’s say that you want to decrement the value of the accountBalance attribute by a value of 123 in user entry uid=jdoe,ou=People,dc=example,dc=com. We only want to do that if the accountBalance attribute currently has a value that is greater than or equal to 123 (because we don’t want the balance to become negative), so we’ll use an assertion request control to accomplish that. And we want to get the updated accountBalance value after the modification is processed, so we’ll use the post-read request control for that. The modify request we’d send to do that would be encoded as below. Note that for the sake of brevity, I won’t get into the specific encodings of the assertion and post-read controls here, but you can find them in the RFCs referenced above. For now, just assume that these controls are encoded correctly:
30 81 a3 -- Begin the LDAPMessage sequence 02 01 02 -- The message ID (integer value 2) 66 47 -- Begin the modify request protocol op 04 24 75 69 64 3d 6a 64 6f 65 -- The DN of the entry to modify (octet string 2c 6f 75 3d 50 65 6f 70 -- "uid=jdoe,ou=People,dc=example,dc=com") 6c 65 2c 64 63 3d 65 78 61 6d 70 6c 65 2c 64 63 3d 63 6f 6d 30 1f -- Begin the sequence of modifications 30 1d -- Begin the sequence for the first modification 0a 01 03 -- The increment modification type (enumerated value 3) 30 18 -- Begin the attribute sequence 04 0e 61 63 63 6f 75 6e 74 42 -- The attribute description 61 6c 61 6e 63 65 -- (octet string "accountBalance") 31 06 -- Begin the attribute value set 04 04 2d 31 32 33 -- The attribute value (octet string "-123") a0 55 -- Begin the sequence of request controls 30 2a -- Begin the sequence for the first control (assertion request) 04 0c 31 2e 33 2e 36 2e 31 2e -- The control OID (octet string 31 2e 31 32 -- "1.3.6.1.1.12") 01 01 ff -- The control criticality (boolean value true) 04 17 -- Begin the control value a5 15 -- Begin a greater-or-equal filter sequence 04 0e 61 63 63 6f 75 6e 74 42 -- The attribute description 61 6c 61 6e 63 65 -- (octet string "accountBalance") 04 03 31 32 33 -- The assertion value (octet string "123") 30 27 -- Begin the sequence for the second control (post-read request) 04 0e 31 2e 33 2e 36 2e 31 2e -- The control OID (octet string 31 2e 31 33 2e 32 -- "1.3.6.1.1.13.2") 01 01 ff -- The control criticality (boolean value true) 04 12 -- Begin the control value 30 10 -- Begin the requested attributes sequence 04 0e 61 63 63 6f 75 6e 74 42 -- A requested attribute 61 6c 61 6e 63 65 -- (octet string "accountBalance")
Assuming that the above modify request is processed successfully, and that the accountBalance attribute had an initial value of 456 (meaning that the resulting value would be 456 − 123 = 333), the corresponding modify response (including a post-read response control) would be encoded as:
30 65 -- Begin the LDAPMessage sequence 02 01 02 -- The message ID (integer value 2) 67 07 -- Begin the modify response protocol op 0a 01 00 -- success result code (enumerated value 0) 04 00 -- No matched DN (0-byte octet string) 04 00 -- No diagnostic message (0-byte octet string) a0 57 -- Begin the sequence of response controls 30 55 -- Begin the sequence for the first control (post-read response) 04 0e 31 2e 33 2e 36 2e 31 2e -- The control OID (octet string 31 2e 31 33 2e 32 -- "1.3.6.1.1.13.2") 04 43 -- Begin the control value 64 41 -- Begin the search result entry protocol op 04 24 75 69 64 3d 6a 64 6f 65 -- The entry DN (octet string 2c 6f 75 3d 50 65 6f 70 -- "uid=jdoe,ou=People,dc=example, 6c 65 2c 64 63 3d 65 78 -- dc=com") 61 6d 70 6c 65 2c 64 63 3d 63 6f 6d 30 19 -- Begin the sequence of attributes 30 17 -- Begin the sequence for the first attribute 04 0e 61 63 63 6f 75 6e 74 42 -- The attribute description 61 6c 61 6e 63 65 -- (octet string "accountBalance") 31 05 -- Begin the attribute value set 04 03 33 33 33 -- The attribute value (octet string "333")
Previous: The LDAP Extended Operation | Next: The LDAP Modify DN Operation |