1 /* $OpenLDAP: pkg/ldap/servers/slapd/modify.c,v 1.276.2.9 2008/04/14 22:05:06 quanah Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2008 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
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>.
15 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
16 * All rights reserved.
18 * Redistribution and use in source and binary forms are permitted
19 * provided that this notice is preserved and that due credit is given
20 * to the University of Michigan at Ann Arbor. The name of the University
21 * may not be used to endorse or promote products derived from this
22 * software without specific prior written permission. This software
23 * is provided ``as is'' without express or implied warranty.
30 #include <ac/socket.h>
31 #include <ac/string.h>
43 struct berval dn
= BER_BVNULL
;
44 char textbuf
[ SLAP_TEXT_BUFLEN
];
45 size_t textlen
= sizeof( textbuf
);
50 Debug( LDAP_DEBUG_TRACE
, "%s do_modify\n",
51 op
->o_log_prefix
, 0, 0 );
53 * Parse the modify request. It looks like this:
55 * ModifyRequest := [APPLICATION 6] SEQUENCE {
56 * name DistinguishedName,
57 * mods SEQUENCE OF SEQUENCE {
58 * operation ENUMERATED {
63 * modification SEQUENCE {
65 * values SET OF AttributeValue
71 if ( ber_scanf( op
->o_ber
, "{m" /*}*/, &dn
) == LBER_ERROR
) {
72 Debug( LDAP_DEBUG_ANY
, "%s do_modify: ber_scanf failed\n",
73 op
->o_log_prefix
, 0, 0 );
74 send_ldap_discon( op
, rs
, LDAP_PROTOCOL_ERROR
, "decoding error" );
75 return SLAPD_DISCONNECT
;
78 Debug( LDAP_DEBUG_ARGS
, "%s do_modify: dn (%s)\n",
79 op
->o_log_prefix
, dn
.bv_val
, 0 );
81 rs
->sr_err
= slap_parse_modlist( op
, rs
, op
->o_ber
, &op
->oq_modify
);
82 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
83 Debug( LDAP_DEBUG_ANY
, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n",
84 op
->o_log_prefix
, rs
->sr_err
, rs
->sr_text
);
88 if( get_ctrls( op
, rs
, 1 ) != LDAP_SUCCESS
) {
89 Debug( LDAP_DEBUG_ANY
, "%s do_modify: get_ctrls failed\n",
90 op
->o_log_prefix
, 0, 0 );
94 rs
->sr_err
= dnPrettyNormal( NULL
, &dn
, &op
->o_req_dn
, &op
->o_req_ndn
,
96 if( rs
->sr_err
!= LDAP_SUCCESS
) {
97 Debug( LDAP_DEBUG_ANY
, "%s do_modify: invalid dn (%s)\n",
98 op
->o_log_prefix
, dn
.bv_val
, 0 );
99 send_ldap_error( op
, rs
, LDAP_INVALID_DN_SYNTAX
, "invalid DN" );
103 op
->orm_no_opattrs
= 0;
106 Debug( LDAP_DEBUG_ARGS
, "%s modifications:\n",
107 op
->o_log_prefix
, 0, 0 );
109 for ( tmp
= op
->orm_modlist
; tmp
!= NULL
; tmp
= tmp
->sml_next
) {
110 Debug( LDAP_DEBUG_ARGS
, "\t%s: %s\n",
111 tmp
->sml_op
== LDAP_MOD_ADD
? "add" :
112 (tmp
->sml_op
== LDAP_MOD_INCREMENT
? "increment" :
113 (tmp
->sml_op
== LDAP_MOD_DELETE
? "delete" :
114 "replace")), tmp
->sml_type
.bv_val
, 0 );
116 if ( tmp
->sml_values
== NULL
) {
117 Debug( LDAP_DEBUG_ARGS
, "%s\n",
118 "\t\tno values", NULL
, NULL
);
119 } else if ( BER_BVISNULL( &tmp
->sml_values
[ 0 ] ) ) {
120 Debug( LDAP_DEBUG_ARGS
, "%s\n",
121 "\t\tzero values", NULL
, NULL
);
122 } else if ( BER_BVISNULL( &tmp
->sml_values
[ 1 ] ) ) {
123 Debug( LDAP_DEBUG_ARGS
, "%s, length %ld\n",
124 "\t\tone value", (long) tmp
->sml_values
[0].bv_len
, NULL
);
126 Debug( LDAP_DEBUG_ARGS
, "%s\n",
127 "\t\tmultiple values", NULL
, NULL
);
131 if ( StatslogTest( LDAP_DEBUG_STATS
) ) {
132 char abuf
[BUFSIZ
/2], *ptr
= abuf
;
135 Statslog( LDAP_DEBUG_STATS
, "%s MOD dn=\"%s\"\n",
136 op
->o_log_prefix
, op
->o_req_dn
.bv_val
, 0, 0, 0 );
138 for ( tmp
= op
->orm_modlist
; tmp
!= NULL
; tmp
= tmp
->sml_next
) {
139 if (len
+ 1 + tmp
->sml_type
.bv_len
> sizeof(abuf
)) {
140 Statslog( LDAP_DEBUG_STATS
, "%s MOD attr=%s\n",
141 op
->o_log_prefix
, abuf
, 0, 0, 0 );
146 if( 1 + tmp
->sml_type
.bv_len
> sizeof(abuf
)) {
147 Statslog( LDAP_DEBUG_STATS
, "%s MOD attr=%s\n",
148 op
->o_log_prefix
, tmp
->sml_type
.bv_val
, 0, 0, 0 );
156 ptr
= lutil_strcopy(ptr
, tmp
->sml_type
.bv_val
);
157 len
+= tmp
->sml_type
.bv_len
;
160 Statslog( LDAP_DEBUG_STATS
, "%s MOD attr=%s\n",
161 op
->o_log_prefix
, abuf
, 0, 0, 0 );
164 #endif /* LDAP_DEBUG */
166 rs
->sr_err
= slap_mods_check( op
, op
->orm_modlist
,
167 &rs
->sr_text
, textbuf
, textlen
, NULL
);
169 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
170 send_ldap_result( op
, rs
);
174 op
->o_bd
= frontendDB
;
175 rs
->sr_err
= frontendDB
->be_modify( op
, rs
);
178 if( rs
->sr_err
== LDAP_X_TXN_SPECIFY_OKAY
) {
185 op
->o_tmpfree( op
->o_req_dn
.bv_val
, op
->o_tmpmemctx
);
186 op
->o_tmpfree( op
->o_req_ndn
.bv_val
, op
->o_tmpmemctx
);
187 if ( op
->orm_modlist
!= NULL
) slap_mods_free( op
->orm_modlist
, 1 );
193 fe_op_modify( Operation
*op
, SlapReply
*rs
)
195 BackendDB
*op_be
, *bd
= op
->o_bd
;
196 char textbuf
[ SLAP_TEXT_BUFLEN
];
197 size_t textlen
= sizeof( textbuf
);
199 if ( BER_BVISEMPTY( &op
->o_req_ndn
) ) {
200 Debug( LDAP_DEBUG_ANY
, "%s do_modify: root dse!\n",
201 op
->o_log_prefix
, 0, 0 );
202 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
203 "modify upon the root DSE not supported" );
206 } else if ( bvmatch( &op
->o_req_ndn
, &frontendDB
->be_schemandn
) ) {
207 Debug( LDAP_DEBUG_ANY
, "%s do_modify: subschema subentry!\n",
208 op
->o_log_prefix
, 0, 0 );
209 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
210 "modification of subschema subentry not supported" );
215 * We could be serving multiple database backends. Select the
216 * appropriate one, or send a referral to our "referral server"
217 * if we don't hold it.
219 op
->o_bd
= select_backend( &op
->o_req_ndn
, 1 );
220 if ( op
->o_bd
== NULL
) {
222 rs
->sr_ref
= referral_rewrite( default_referral
,
223 NULL
, &op
->o_req_dn
, LDAP_SCOPE_DEFAULT
);
225 rs
->sr_ref
= default_referral
;
228 if ( rs
->sr_ref
!= NULL
) {
229 rs
->sr_err
= LDAP_REFERRAL
;
230 send_ldap_result( op
, rs
);
232 if ( rs
->sr_ref
!= default_referral
) {
233 ber_bvarray_free( rs
->sr_ref
);
237 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
238 "no global superior knowledge" );
243 /* If we've got a glued backend, check the real backend */
245 if ( SLAP_GLUE_INSTANCE( op
->o_bd
)) {
246 op
->o_bd
= select_backend( &op
->o_req_ndn
, 0 );
249 /* check restrictions */
250 if ( backend_check_restrictions( op
, rs
, NULL
) != LDAP_SUCCESS
) {
251 send_ldap_result( op
, rs
);
255 /* check for referrals */
256 if ( backend_check_referrals( op
, rs
) != LDAP_SUCCESS
) {
260 rs
->sr_err
= slap_mods_obsolete_check( op
, op
->orm_modlist
,
261 &rs
->sr_text
, textbuf
, textlen
);
262 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
263 send_ldap_result( op
, rs
);
267 /* check for modify/increment support */
268 if ( op
->orm_increment
&& !SLAP_INCREMENT( op
->o_bd
) ) {
269 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
270 "modify/increment not supported in context" );
274 * do the modify if 1 && (2 || 3)
275 * 1) there is a modify function implemented in this backend;
276 * 2) this backend is master for what it holds;
277 * 3) it's a replica and the dn supplied is the update_ndn.
279 if ( op
->o_bd
->be_modify
) {
280 /* do the update here */
281 int repl_user
= be_isupdate( op
);
284 * Multimaster slapd does not have to check for replicator dn
285 * because it accepts each modify request
287 if ( !SLAP_SINGLE_SHADOW(op
->o_bd
) || repl_user
) {
288 int update
= !BER_BVISEMPTY( &op
->o_bd
->be_update_ndn
);
293 rs
->sr_err
= slap_mods_no_user_mod_check( op
, op
->orm_modlist
,
294 &rs
->sr_text
, textbuf
, textlen
);
295 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
296 send_ldap_result( op
, rs
);
300 op
->o_bd
->be_modify( op
, rs
);
302 } else { /* send a referral */
303 BerVarray defref
= op
->o_bd
->be_update_refs
304 ? op
->o_bd
->be_update_refs
: default_referral
;
305 if ( defref
!= NULL
) {
306 rs
->sr_ref
= referral_rewrite( defref
,
308 LDAP_SCOPE_DEFAULT
);
309 if ( rs
->sr_ref
== NULL
) {
310 /* FIXME: must duplicate, because
311 * overlays may muck with it */
314 rs
->sr_err
= LDAP_REFERRAL
;
315 send_ldap_result( op
, rs
);
316 if ( rs
->sr_ref
!= defref
) {
317 ber_bvarray_free( rs
->sr_ref
);
321 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
322 "shadow context; no update referral" );
327 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
328 "operation not supported within namingContext" );
337 * Obsolete constraint checking.
340 slap_mods_obsolete_check(
347 if( get_relax( op
) ) return LDAP_SUCCESS
;
349 for ( ; ml
!= NULL
; ml
= ml
->sml_next
) {
350 if ( is_at_obsolete( ml
->sml_desc
->ad_type
) &&
351 (( ml
->sml_op
!= LDAP_MOD_REPLACE
&&
352 ml
->sml_op
!= LDAP_MOD_DELETE
) ||
353 ml
->sml_values
!= NULL
))
356 * attribute is obsolete,
357 * only allow replace/delete with no values
359 snprintf( textbuf
, textlen
,
360 "%s: attribute is obsolete",
361 ml
->sml_type
.bv_val
);
363 return LDAP_CONSTRAINT_VIOLATION
;
371 * No-user-modification constraint checking.
374 slap_mods_no_user_mod_check(
381 for ( ; ml
!= NULL
; ml
= ml
->sml_next
) {
382 if ( !is_at_no_user_mod( ml
->sml_desc
->ad_type
) ) {
386 if ( ml
->sml_flags
& SLAP_MOD_INTERNAL
) {
390 if ( get_relax( op
) ) {
391 if ( ml
->sml_desc
->ad_type
->sat_flags
& SLAP_AT_MANAGEABLE
) {
392 ml
->sml_flags
|= SLAP_MOD_MANAGING
;
396 /* attribute not manageable */
397 snprintf( textbuf
, textlen
,
398 "%s: no-user-modification attribute not manageable",
399 ml
->sml_type
.bv_val
);
402 /* user modification disallowed */
403 snprintf( textbuf
, textlen
,
404 "%s: no user modification allowed",
405 ml
->sml_type
.bv_val
);
409 return LDAP_CONSTRAINT_VIOLATION
;
416 slap_mods_no_repl_user_mod_check(
426 for ( mods
= ml
; mods
!= NULL
; mods
= mods
->sml_next
) {
427 assert( mods
->sml_op
== LDAP_MOD_ADD
);
429 /* check doesn't already appear */
430 for ( modp
= ml
; modp
!= NULL
; modp
= modp
->sml_next
) {
431 if ( mods
->sml_desc
== modp
->sml_desc
&& mods
!= modp
) {
432 snprintf( textbuf
, textlen
,
433 "attribute '%s' provided more than once",
434 mods
->sml_desc
->ad_cname
.bv_val
);
436 return LDAP_TYPE_OR_VALUE_EXISTS
;
445 * Do basic attribute type checking and syntax validation.
457 for( ; ml
!= NULL
; ml
= ml
->sml_next
) {
458 AttributeDescription
*ad
= NULL
;
460 /* convert to attribute description */
461 if ( ml
->sml_desc
== NULL
) {
462 rc
= slap_bv2ad( &ml
->sml_type
, &ml
->sml_desc
, text
);
463 if( rc
!= LDAP_SUCCESS
) {
464 if ( get_no_schema_check( op
)) {
465 rc
= slap_bv2undef_ad( &ml
->sml_type
, &ml
->sml_desc
,
469 if( rc
!= LDAP_SUCCESS
) {
470 snprintf( textbuf
, textlen
, "%s: %s",
471 ml
->sml_type
.bv_val
, *text
);
479 if( slap_syntax_is_binary( ad
->ad_type
->sat_syntax
)
480 && !slap_ad_is_binary( ad
))
482 /* attribute requires binary transfer */
483 snprintf( textbuf
, textlen
,
484 "%s: requires ;binary transfer",
485 ml
->sml_type
.bv_val
);
487 return LDAP_UNDEFINED_TYPE
;
490 if( !slap_syntax_is_binary( ad
->ad_type
->sat_syntax
)
491 && slap_ad_is_binary( ad
))
493 /* attribute does not require binary transfer */
494 snprintf( textbuf
, textlen
,
495 "%s: disallows ;binary transfer",
496 ml
->sml_type
.bv_val
);
498 return LDAP_UNDEFINED_TYPE
;
501 if( slap_ad_is_tag_range( ad
)) {
502 /* attribute requires binary transfer */
503 snprintf( textbuf
, textlen
,
504 "%s: inappropriate use of tag range option",
505 ml
->sml_type
.bv_val
);
507 return LDAP_UNDEFINED_TYPE
;
511 if ( is_at_obsolete( ad
->ad_type
) &&
512 (( ml
->sml_op
!= LDAP_MOD_REPLACE
&&
513 ml
->sml_op
!= LDAP_MOD_DELETE
) ||
514 ml
->sml_values
!= NULL
))
517 * attribute is obsolete,
518 * only allow replace/delete with no values
520 snprintf( textbuf
, textlen
,
521 "%s: attribute is obsolete",
522 ml
->sml_type
.bv_val
);
524 return LDAP_CONSTRAINT_VIOLATION
;
528 if ( ml
->sml_op
== LDAP_MOD_INCREMENT
&&
529 #ifdef SLAPD_REAL_SYNTAX
530 !is_at_syntax( ad
->ad_type
, SLAPD_REAL_SYNTAX
) &&
532 !is_at_syntax( ad
->ad_type
, SLAPD_INTEGER_SYNTAX
) )
535 * attribute values must be INTEGER or REAL
537 snprintf( textbuf
, textlen
,
538 "%s: attribute syntax inappropriate for increment",
539 ml
->sml_type
.bv_val
);
541 return LDAP_CONSTRAINT_VIOLATION
;
547 if( ml
->sml_values
!= NULL
) {
549 slap_syntax_validate_func
*validate
=
550 ad
->ad_type
->sat_syntax
->ssyn_validate
;
551 slap_syntax_transform_func
*pretty
=
552 ad
->ad_type
->sat_syntax
->ssyn_pretty
;
554 if( !pretty
&& !validate
) {
555 *text
= "no validator for syntax";
556 snprintf( textbuf
, textlen
,
557 "%s: no validator for syntax %s",
559 ad
->ad_type
->sat_syntax
->ssyn_oid
);
561 return LDAP_INVALID_SYNTAX
;
565 * check that each value is valid per syntax
566 * and pretty if appropriate
568 for ( nvals
= 0; !BER_BVISNULL( &ml
->sml_values
[nvals
] ); nvals
++ ) {
572 rc
= ordered_value_pretty( ad
,
573 &ml
->sml_values
[nvals
], &pval
, ctx
);
575 rc
= ordered_value_validate( ad
,
576 &ml
->sml_values
[nvals
], ml
->sml_op
);
580 snprintf( textbuf
, textlen
,
581 "%s: value #%ld invalid per syntax",
582 ml
->sml_type
.bv_val
, (long) nvals
);
584 return LDAP_INVALID_SYNTAX
;
588 ber_memfree_x( ml
->sml_values
[nvals
].bv_val
, ctx
);
589 ml
->sml_values
[nvals
] = pval
;
592 ml
->sml_values
[nvals
].bv_len
= 0;
593 ml
->sml_numvals
= nvals
;
596 * a rough single value check... an additional check is needed
597 * to catch add of single value to existing single valued attribute
599 if ((ml
->sml_op
== LDAP_MOD_ADD
|| ml
->sml_op
== LDAP_MOD_REPLACE
)
600 && nvals
> 1 && is_at_single_value( ad
->ad_type
))
602 snprintf( textbuf
, textlen
,
603 "%s: multiple values provided",
604 ml
->sml_type
.bv_val
);
606 return LDAP_CONSTRAINT_VIOLATION
;
609 /* if the type has a normalizer, generate the
610 * normalized values. otherwise leave them NULL.
612 * this is different from the rule for attributes
613 * in an entry - in an attribute list, the normalized
614 * value is set equal to the non-normalized value
615 * when there is no normalizer.
617 if( nvals
&& ad
->ad_type
->sat_equality
&&
618 ad
->ad_type
->sat_equality
->smr_normalize
)
620 ml
->sml_nvalues
= ber_memalloc_x(
621 (nvals
+1)*sizeof(struct berval
), ctx
);
623 for ( nvals
= 0; !BER_BVISNULL( &ml
->sml_values
[nvals
] ); nvals
++ ) {
624 rc
= ordered_value_normalize(
625 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
,
627 ad
->ad_type
->sat_equality
,
628 &ml
->sml_values
[nvals
], &ml
->sml_nvalues
[nvals
], ctx
);
630 Debug( LDAP_DEBUG_ANY
,
631 "<= str2entry NULL (ssyn_normalize %d)\n",
633 snprintf( textbuf
, textlen
,
634 "%s: value #%ld normalization failed",
635 ml
->sml_type
.bv_val
, (long) nvals
);
637 BER_BVZERO( &ml
->sml_nvalues
[nvals
] );
642 BER_BVZERO( &ml
->sml_nvalues
[nvals
] );
645 /* check for duplicates, but ignore Deletes.
647 if( nvals
> 1 && ml
->sml_op
!= LDAP_MOD_DELETE
) {
649 rc
= slap_sort_vals( ml
, text
, &i
, ctx
);
650 if ( rc
== LDAP_TYPE_OR_VALUE_EXISTS
) {
651 /* value exists already */
652 snprintf( textbuf
, textlen
,
653 "%s: value #%d provided more than once",
654 ml
->sml_desc
->ad_cname
.bv_val
, i
);
668 /* Sort a set of values. An (Attribute *) may be used interchangeably here
669 * instead of a (Modifications *) structure.
671 * Uses Quicksort + Insertion sort for small arrays
681 AttributeDescription
*ad
;
683 int istack
[sizeof(int)*16];
684 int i
, j
, k
, l
, ir
, jstack
, match
, *ix
, itmp
, nvals
, rc
;
686 struct berval a
, *cv
;
689 #define SWAP(a,b,tmp) tmp=(a);(a)=(b);(b)=tmp
690 #define COMP(a,b) match=0; rc = ordered_value_match( &match, \
691 ad, mr, SLAP_MR_EQUALITY \
692 | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX \
693 | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH \
694 | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, \
698 #define EXCH(x,y) SWAP(ix[x],ix[y],itmp)
699 #define SETA(x) itmp = ix[x]; a = cv[itmp]
700 #define GETA(x) ix[x] = itmp;
701 #define SET(x,y) ix[x] = ix[y]
704 nvals
= ml
->sml_numvals
;
706 /* For Modifications, sml_nvalues is NULL if normalization wasn't needed.
707 * For Attributes, sml_nvalues == sml_values when normalization isn't needed.
709 if ( ml
->sml_nvalues
&& ml
->sml_nvalues
!= ml
->sml_values
) {
710 cv
= ml
->sml_nvalues
;
717 if ( ad
== slap_schema
.si_ad_objectClass
)
718 mr
= NULL
; /* shortcut matching */
720 mr
= ad
->ad_type
->sat_equality
;
722 /* record indices to preserve input ordering */
723 ix
= slap_sl_malloc( nvals
* sizeof(int), ctx
);
724 for (i
=0; i
<nvals
; i
++) ix
[i
] = i
;
731 if (ir
- l
< SMALL
) { /* Insertion sort */
733 for (j
=l
+1;j
<=ir
;j
++) {
735 for (i
=j
-1;i
>=0;i
--) {
742 if ( match
== 0 ) goto done
;
744 if ( jstack
== 0 ) break;
745 if ( match
== 0 ) break;
746 ir
= istack
[jstack
--];
747 l
= istack
[jstack
--];
749 k
= (l
+ ir
) >> 1; /* Choose median of left, center, right */
751 COMP( cv
[IX(l
)], cv
[IX(ir
)] );
754 } else if ( match
== 0 ) {
758 COMP( cv
[IX(l
+1)], cv
[IX(ir
)] );
761 } else if ( match
== 0 ) {
765 COMP( cv
[IX(l
)], cv
[IX(l
+1)] );
768 } else if ( match
== 0 ) {
778 COMP( cv
[IX(i
)], a
);
779 } while( match
< 0 );
782 COMP( cv
[IX(j
)], a
);
800 istack
[jstack
-1] = i
;
804 istack
[jstack
-1] = l
;
813 /* For sorted attributes, put the values in index order */
814 if ( rc
== LDAP_SUCCESS
&& match
&&
815 ( ad
->ad_type
->sat_flags
& SLAP_AT_SORTED_VAL
)) {
816 BerVarray tmpv
= slap_sl_malloc( sizeof( struct berval
) * nvals
, ctx
);
817 for ( i
= 0; i
<nvals
; i
++ )
819 for ( i
= 0; i
<nvals
; i
++ )
821 /* Check if the non-normalized array needs to move too */
824 for ( i
= 0; i
<nvals
; i
++ )
826 for ( i
= 0; i
<nvals
; i
++ )
829 slap_sl_free( tmpv
, ctx
);
832 slap_sl_free( ix
, ctx
);
834 if ( rc
!= LDAP_SUCCESS
) {
836 } else if ( match
== 0 ) {
837 /* value exists already */
840 return LDAP_TYPE_OR_VALUE_EXISTS
;
845 /* Enter with bv->bv_len = sizeof buffer, returns with
846 * actual length of string
848 void slap_timestamp( time_t *tm
, struct berval
*bv
)
854 ltm
= gmtime_r( tm
, <m_buf
);
856 ldap_pvt_thread_mutex_lock( &gmtime_mutex
);
860 bv
->bv_len
= lutil_gentime( bv
->bv_val
, bv
->bv_len
, ltm
);
862 #ifndef HAVE_GMTIME_R
863 ldap_pvt_thread_mutex_unlock( &gmtime_mutex
);
867 /* Called for all modify and modrdn ops. If the current op was replicated
868 * from elsewhere, all of the attrs should already be present.
870 void slap_mods_opattrs(
872 Modifications
**modsp
,
875 struct berval name
, timestamp
, csn
= BER_BVNULL
;
877 char timebuf
[ LDAP_LUTIL_GENTIME_BUFSIZE
];
878 char csnbuf
[ LDAP_LUTIL_CSNSTR_BUFSIZE
];
879 Modifications
*mod
, **modtail
, *modlast
;
880 int gotcsn
= 0, gotmname
= 0, gotmtime
= 0;
882 if ( SLAP_LASTMOD( op
->o_bd
) && !op
->orm_no_opattrs
) {
884 timestamp
.bv_val
= timebuf
;
885 for ( modtail
= modsp
; *modtail
; modtail
= &(*modtail
)->sml_next
) {
886 if ( (*modtail
)->sml_op
!= LDAP_MOD_ADD
&&
887 (*modtail
)->sml_op
!= SLAP_MOD_SOFTADD
&&
888 (*modtail
)->sml_op
!= LDAP_MOD_REPLACE
)
893 if ( (*modtail
)->sml_desc
== slap_schema
.si_ad_entryCSN
)
895 csn
= (*modtail
)->sml_values
[0];
898 } else if ( (*modtail
)->sml_desc
== slap_schema
.si_ad_modifiersName
)
902 } else if ( (*modtail
)->sml_desc
== slap_schema
.si_ad_modifyTimestamp
)
908 if ( BER_BVISEMPTY( &op
->o_csn
)) {
911 csn
.bv_len
= sizeof( csnbuf
);
912 slap_get_csn( op
, &csn
, manage_ctxcsn
);
915 if ( manage_ctxcsn
) {
916 slap_queue_csn( op
, &csn
);
924 ptr
= ber_bvchr( &csn
, '#' );
926 timestamp
.bv_len
= STRLENOF("YYYYMMDDHHMMSSZ");
927 AC_MEMCPY( timebuf
, csn
.bv_val
, timestamp
.bv_len
);
928 timebuf
[timestamp
.bv_len
-1] = 'Z';
929 timebuf
[timestamp
.bv_len
] = '\0';
932 time_t now
= slap_get_time();
934 timestamp
.bv_len
= sizeof(timebuf
);
936 slap_timestamp( &now
, ×tamp
);
939 if ( BER_BVISEMPTY( &op
->o_dn
) ) {
940 BER_BVSTR( &name
, SLAPD_ANONYMOUS
);
949 mod
= (Modifications
*) ch_malloc( sizeof( Modifications
) );
950 mod
->sml_op
= LDAP_MOD_REPLACE
;
951 mod
->sml_flags
= SLAP_MOD_INTERNAL
;
952 mod
->sml_next
= NULL
;
953 BER_BVZERO( &mod
->sml_type
);
954 mod
->sml_desc
= slap_schema
.si_ad_entryCSN
;
955 mod
->sml_numvals
= 1;
956 mod
->sml_values
= (BerVarray
) ch_malloc( 2 * sizeof( struct berval
) );
957 ber_dupbv( &mod
->sml_values
[0], &csn
);
958 BER_BVZERO( &mod
->sml_values
[1] );
959 assert( !BER_BVISNULL( &mod
->sml_values
[0] ) );
960 mod
->sml_nvalues
= NULL
;
963 modtail
= &mod
->sml_next
;
967 mod
= (Modifications
*) ch_malloc( sizeof( Modifications
) );
968 mod
->sml_op
= LDAP_MOD_REPLACE
;
969 mod
->sml_flags
= SLAP_MOD_INTERNAL
;
970 mod
->sml_next
= NULL
;
971 BER_BVZERO( &mod
->sml_type
);
972 mod
->sml_desc
= slap_schema
.si_ad_modifiersName
;
973 mod
->sml_numvals
= 1;
974 mod
->sml_values
= (BerVarray
) ch_malloc( 2 * sizeof( struct berval
) );
975 ber_dupbv( &mod
->sml_values
[0], &name
);
976 BER_BVZERO( &mod
->sml_values
[1] );
977 assert( !BER_BVISNULL( &mod
->sml_values
[0] ) );
979 (BerVarray
) ch_malloc( 2 * sizeof( struct berval
) );
980 ber_dupbv( &mod
->sml_nvalues
[0], &nname
);
981 BER_BVZERO( &mod
->sml_nvalues
[1] );
982 assert( !BER_BVISNULL( &mod
->sml_nvalues
[0] ) );
984 modtail
= &mod
->sml_next
;
988 mod
= (Modifications
*) ch_malloc( sizeof( Modifications
) );
989 mod
->sml_op
= LDAP_MOD_REPLACE
;
990 mod
->sml_flags
= SLAP_MOD_INTERNAL
;
991 mod
->sml_next
= NULL
;
992 BER_BVZERO( &mod
->sml_type
);
993 mod
->sml_desc
= slap_schema
.si_ad_modifyTimestamp
;
994 mod
->sml_numvals
= 1;
995 mod
->sml_values
= (BerVarray
) ch_malloc( 2 * sizeof( struct berval
) );
996 ber_dupbv( &mod
->sml_values
[0], ×tamp
);
997 BER_BVZERO( &mod
->sml_values
[1] );
998 assert( !BER_BVISNULL( &mod
->sml_values
[0] ) );
999 mod
->sml_nvalues
= NULL
;
1001 modtail
= &mod
->sml_next
;
1016 Modifications
**modtail
= &ms
->rs_mods
.rs_modlist
;
1018 ms
->rs_mods
.rs_modlist
= NULL
;
1019 ms
->rs_increment
= 0;
1021 rs
->sr_err
= LDAP_SUCCESS
;
1023 /* collect modifications & save for later */
1024 for ( tag
= ber_first_element( ber
, &len
, &last
);
1025 tag
!= LBER_DEFAULT
;
1026 tag
= ber_next_element( ber
, &len
, last
) )
1029 Modifications tmp
, *mod
;
1031 tmp
.sml_nvalues
= NULL
;
1033 if ( ber_scanf( ber
, "{e{m[W]}}", &mop
,
1034 &tmp
.sml_type
, &tmp
.sml_values
) == LBER_ERROR
)
1036 rs
->sr_text
= "decoding modlist error";
1037 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1041 mod
= (Modifications
*) ch_malloc( sizeof(Modifications
) );
1044 mod
->sml_type
= tmp
.sml_type
;
1045 mod
->sml_values
= tmp
.sml_values
;
1046 mod
->sml_nvalues
= NULL
;
1047 mod
->sml_desc
= NULL
;
1048 mod
->sml_next
= NULL
;
1053 if ( mod
->sml_values
== NULL
) {
1054 rs
->sr_text
= "modify/add operation requires values";
1055 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1061 case LDAP_MOD_DELETE
:
1062 case LDAP_MOD_REPLACE
:
1065 case LDAP_MOD_INCREMENT
:
1066 if( op
->o_protocol
>= LDAP_VERSION3
) {
1068 if ( mod
->sml_values
== NULL
) {
1069 rs
->sr_text
= "modify/increment operation requires value";
1070 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1074 if ( !BER_BVISNULL( &mod
->sml_values
[ 1 ] ) ) {
1075 rs
->sr_text
= "modify/increment operation requires single value";
1076 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1085 rs
->sr_text
= "unrecognized modify operation";
1086 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1090 modtail
= &mod
->sml_next
;
1095 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1096 slap_mods_free( ms
->rs_mods
.rs_modlist
, 1 );
1097 ms
->rs_mods
.rs_modlist
= NULL
;
1098 ms
->rs_increment
= 0;