1 /* $OpenLDAP: pkg/ldap/servers/slapd/add.c,v 1.244.2.6 2008/03/21 01:01:07 hyc 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.
29 #include <ac/string.h>
31 #include <ac/socket.h>
37 do_add( Operation
*op
, SlapReply
*rs
)
39 BerElement
*ber
= op
->o_ber
;
41 struct berval dn
= BER_BVNULL
;
44 Modifications
*modlist
= NULL
;
45 Modifications
**modtail
= &modlist
;
47 char textbuf
[ SLAP_TEXT_BUFLEN
];
48 size_t textlen
= sizeof( textbuf
);
53 Debug( LDAP_DEBUG_TRACE
, "%s do_add\n",
54 op
->o_log_prefix
, 0, 0 );
57 * Parse the add request. It looks like this:
59 * AddRequest := [APPLICATION 14] SEQUENCE {
60 * name DistinguishedName,
61 * attrs SEQUENCE OF SEQUENCE {
63 * values SET OF AttributeValue
69 if ( ber_scanf( ber
, "{m", /*}*/ &dn
) == LBER_ERROR
) {
70 Debug( LDAP_DEBUG_ANY
, "%s do_add: ber_scanf failed\n",
71 op
->o_log_prefix
, 0, 0 );
72 send_ldap_discon( op
, rs
, LDAP_PROTOCOL_ERROR
, "decoding error" );
73 return SLAPD_DISCONNECT
;
76 Debug( LDAP_DEBUG_ARGS
, "%s do_add: dn (%s)\n",
77 op
->o_log_prefix
, dn
.bv_val
, 0 );
80 for ( tag
= ber_first_element( ber
, &len
, &last
); tag
!= LBER_DEFAULT
;
81 tag
= ber_next_element( ber
, &len
, last
) )
86 tmp
.sml_nvalues
= NULL
;
88 rtag
= ber_scanf( ber
, "{m{W}}", &tmp
.sml_type
, &tmp
.sml_values
);
90 if ( rtag
== LBER_ERROR
) {
91 Debug( LDAP_DEBUG_ANY
, "%s do_add: decoding error\n",
92 op
->o_log_prefix
, 0, 0 );
93 send_ldap_discon( op
, rs
, LDAP_PROTOCOL_ERROR
, "decoding error" );
94 rs
->sr_err
= SLAPD_DISCONNECT
;
98 if ( tmp
.sml_values
== NULL
) {
99 Debug( LDAP_DEBUG_ANY
, "%s do_add: no values for type %s\n",
100 op
->o_log_prefix
, tmp
.sml_type
.bv_val
, 0 );
101 send_ldap_error( op
, rs
, LDAP_PROTOCOL_ERROR
,
102 "no values for attribute type" );
106 mod
= (Modifications
*) ch_malloc( sizeof(Modifications
) );
107 mod
->sml_op
= LDAP_MOD_ADD
;
109 mod
->sml_next
= NULL
;
110 mod
->sml_desc
= NULL
;
111 mod
->sml_type
= tmp
.sml_type
;
112 mod
->sml_values
= tmp
.sml_values
;
113 mod
->sml_nvalues
= NULL
;
116 modtail
= &mod
->sml_next
;
119 if ( ber_scanf( ber
, /*{*/ "}") == LBER_ERROR
) {
120 Debug( LDAP_DEBUG_ANY
, "%s do_add: ber_scanf failed\n",
121 op
->o_log_prefix
, 0, 0 );
122 send_ldap_discon( op
, rs
, LDAP_PROTOCOL_ERROR
, "decoding error" );
123 rs
->sr_err
= SLAPD_DISCONNECT
;
127 if ( get_ctrls( op
, rs
, 1 ) != LDAP_SUCCESS
) {
128 Debug( LDAP_DEBUG_ANY
, "%s do_add: get_ctrls failed\n",
129 op
->o_log_prefix
, 0, 0 );
133 rs
->sr_err
= dnPrettyNormal( NULL
, &dn
, &op
->o_req_dn
, &op
->o_req_ndn
,
136 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
137 Debug( LDAP_DEBUG_ANY
, "%s do_add: invalid dn (%s)\n",
138 op
->o_log_prefix
, dn
.bv_val
, 0 );
139 send_ldap_error( op
, rs
, LDAP_INVALID_DN_SYNTAX
, "invalid DN" );
143 op
->ora_e
= entry_alloc();
144 ber_dupbv( &op
->ora_e
->e_name
, &op
->o_req_dn
);
145 ber_dupbv( &op
->ora_e
->e_nname
, &op
->o_req_ndn
);
147 Statslog( LDAP_DEBUG_STATS
, "%s ADD dn=\"%s\"\n",
148 op
->o_log_prefix
, op
->o_req_dn
.bv_val
, 0, 0, 0 );
150 if ( modlist
== NULL
) {
151 send_ldap_error( op
, rs
, LDAP_PROTOCOL_ERROR
,
152 "no attributes provided" );
156 if ( dn_match( &op
->ora_e
->e_nname
, &slap_empty_bv
) ) {
157 /* protocolError may be a more appropriate error */
158 send_ldap_error( op
, rs
, LDAP_ALREADY_EXISTS
,
159 "root DSE already exists" );
162 } else if ( dn_match( &op
->ora_e
->e_nname
, &frontendDB
->be_schemandn
) ) {
163 send_ldap_error( op
, rs
, LDAP_ALREADY_EXISTS
,
164 "subschema subentry already exists" );
168 rs
->sr_err
= slap_mods_check( op
, modlist
, &rs
->sr_text
,
169 textbuf
, textlen
, NULL
);
171 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
172 send_ldap_result( op
, rs
);
176 /* temporary; remove if not invoking backend function */
177 op
->ora_modlist
= modlist
;
179 /* call this so global overlays/SLAPI have access to ora_e */
180 rs
->sr_err
= slap_mods2entry( op
->ora_modlist
, &op
->ora_e
,
181 1, 0, &rs
->sr_text
, textbuf
, textlen
);
182 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
183 send_ldap_result( op
, rs
);
189 oex
.oe
.oe_key
= (void *)do_add
;
191 LDAP_SLIST_INSERT_HEAD(&op
->o_extra
, &oex
.oe
, oe_next
);
193 op
->o_bd
= frontendDB
;
194 rc
= frontendDB
->be_add( op
, rs
);
195 LDAP_SLIST_REMOVE(&op
->o_extra
, &oex
.oe
, OpExtra
, oe_next
);
198 if ( rc
== LDAP_X_TXN_SPECIFY_OKAY
) {
204 if ( op
->ora_e
!= NULL
&& oex
.oe_db
!= NULL
) {
205 BackendDB
*bd
= op
->o_bd
;
207 op
->o_bd
= oex
.oe_db
;
209 be_entry_release_w( op
, op
->ora_e
);
217 if ( modlist
!= NULL
) {
218 /* in case of error, free the values as well */
219 slap_mods_free( modlist
, freevals
);
222 if ( op
->ora_e
!= NULL
) {
223 entry_free( op
->ora_e
);
225 op
->o_tmpfree( op
->o_req_dn
.bv_val
, op
->o_tmpmemctx
);
226 op
->o_tmpfree( op
->o_req_ndn
.bv_val
, op
->o_tmpmemctx
);
232 fe_op_add( Operation
*op
, SlapReply
*rs
)
234 Modifications
**modtail
= &op
->ora_modlist
;
236 BackendDB
*op_be
, *bd
= op
->o_bd
;
237 char textbuf
[ SLAP_TEXT_BUFLEN
];
238 size_t textlen
= sizeof( textbuf
);
241 * We could be serving multiple database backends. Select the
242 * appropriate one, or send a referral to our "referral server"
243 * if we don't hold it.
245 op
->o_bd
= select_backend( &op
->ora_e
->e_nname
, 1 );
246 if ( op
->o_bd
== NULL
) {
248 rs
->sr_ref
= referral_rewrite( default_referral
,
249 NULL
, &op
->ora_e
->e_name
, LDAP_SCOPE_DEFAULT
);
250 if ( !rs
->sr_ref
) rs
->sr_ref
= default_referral
;
252 rs
->sr_err
= LDAP_REFERRAL
;
253 send_ldap_result( op
, rs
);
255 if ( rs
->sr_ref
!= default_referral
) {
256 ber_bvarray_free( rs
->sr_ref
);
259 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
260 "no global superior knowledge" );
265 /* If we've got a glued backend, check the real backend */
267 if ( SLAP_GLUE_INSTANCE( op
->o_bd
)) {
268 op
->o_bd
= select_backend( &op
->ora_e
->e_nname
, 0 );
271 /* check restrictions */
272 if( backend_check_restrictions( op
, rs
, NULL
) != LDAP_SUCCESS
) {
273 send_ldap_result( op
, rs
);
277 /* check for referrals */
278 if( backend_check_referrals( op
, rs
) != LDAP_SUCCESS
) {
282 rs
->sr_err
= slap_mods_obsolete_check( op
, op
->ora_modlist
,
283 &rs
->sr_text
, textbuf
, textlen
);
285 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
286 send_ldap_result( op
, rs
);
291 * do the add if 1 && (2 || 3)
292 * 1) there is an add function implemented in this backend;
293 * 2) this backend is master for what it holds;
294 * 3) it's a replica and the dn supplied is the updatedn.
296 if ( op
->o_bd
->be_add
) {
297 /* do the update here */
298 int repl_user
= be_isupdate( op
);
299 if ( !SLAP_SINGLE_SHADOW(op
->o_bd
) || repl_user
) {
300 int update
= !BER_BVISEMPTY( &op
->o_bd
->be_update_ndn
);
305 rs
->sr_err
= slap_mods_no_user_mod_check( op
, op
->ora_modlist
,
306 &rs
->sr_text
, textbuf
, textlen
);
308 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
309 send_ldap_result( op
, rs
);
315 /* go to the last mod */
316 for ( modtail
= &op
->ora_modlist
;
318 modtail
= &(*modtail
)->sml_next
)
320 assert( (*modtail
)->sml_op
== LDAP_MOD_ADD
);
321 assert( (*modtail
)->sml_desc
!= NULL
);
325 /* check for unmodifiable attributes */
326 rs
->sr_err
= slap_mods_no_repl_user_mod_check( op
,
327 op
->ora_modlist
, &rs
->sr_text
, textbuf
, textlen
);
328 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
329 send_ldap_result( op
, rs
);
334 rc
= op
->o_bd
->be_add( op
, rs
);
335 if ( rc
== LDAP_SUCCESS
) {
337 /* NOTE: be_entry_release_w() is
338 * called by do_add(), so that global
339 * overlays on the way back can
340 * at least read the entry */
341 LDAP_SLIST_FOREACH(oex
, &op
->o_extra
, oe_next
) {
342 if ( oex
->oe_key
== (void *)do_add
) {
343 ((OpExtraDB
*)oex
)->oe_db
= op
->o_bd
;
350 BerVarray defref
= NULL
;
352 defref
= op
->o_bd
->be_update_refs
353 ? op
->o_bd
->be_update_refs
: default_referral
;
355 if ( defref
!= NULL
) {
356 rs
->sr_ref
= referral_rewrite( defref
,
357 NULL
, &op
->ora_e
->e_name
, LDAP_SCOPE_DEFAULT
);
358 if ( rs
->sr_ref
== NULL
) rs
->sr_ref
= defref
;
359 rs
->sr_err
= LDAP_REFERRAL
;
360 if (!rs
->sr_ref
) rs
->sr_ref
= default_referral
;
361 send_ldap_result( op
, rs
);
363 if ( rs
->sr_ref
!= default_referral
) {
364 ber_bvarray_free( rs
->sr_ref
);
367 send_ldap_error( op
, rs
,
368 LDAP_UNWILLING_TO_PERFORM
,
369 "shadow context; no update referral" );
373 Debug( LDAP_DEBUG_ARGS
, "do_add: no backend support\n", 0, 0, 0 );
374 send_ldap_error( op
, rs
, LDAP_UNWILLING_TO_PERFORM
,
375 "operation not supported within namingContext" );
390 char *textbuf
, size_t textlen
)
396 assert( (*e
)->e_attrs
== NULL
);
399 for ( tail
= &(*e
)->e_attrs
; *tail
!= NULL
; tail
= &(*tail
)->a_next
)
404 for( ; mods
!= NULL
; mods
= mods
->sml_next
) {
407 assert( mods
->sml_desc
!= NULL
);
409 attr
= attr_find( (*e
)->e_attrs
, mods
->sml_desc
);
412 #define SLURPD_FRIENDLY
413 #ifdef SLURPD_FRIENDLY
418 * This check allows overlays to override operational
419 * attributes by setting them directly in the entry.
420 * We assume slap_mods_no_user_mod_check() was called
421 * with the user modifications.
428 j
= mods
->sml_numvals
;
429 attr
->a_numvals
+= j
;
432 attr
->a_vals
= ch_realloc( attr
->a_vals
,
433 sizeof( struct berval
) * (i
+j
) );
435 /* checked for duplicates in slap_mods_check */
438 for ( j
= 0; mods
->sml_values
[j
].bv_val
; j
++ ) {
439 ber_dupbv( &attr
->a_vals
[i
+j
], &mods
->sml_values
[j
] );
441 BER_BVZERO( &attr
->a_vals
[i
+j
] );
444 AC_MEMCPY( &attr
->a_vals
[i
], mods
->sml_values
,
445 sizeof( struct berval
) * j
);
448 if( mods
->sml_nvalues
) {
449 attr
->a_nvals
= ch_realloc( attr
->a_nvals
,
450 sizeof( struct berval
) * (i
+j
) );
452 for ( j
= 0; mods
->sml_nvalues
[j
].bv_val
; j
++ ) {
453 ber_dupbv( &attr
->a_nvals
[i
+j
], &mods
->sml_nvalues
[j
] );
455 BER_BVZERO( &attr
->a_nvals
[i
+j
] );
457 AC_MEMCPY( &attr
->a_nvals
[i
], mods
->sml_nvalues
,
458 sizeof( struct berval
) * j
);
461 attr
->a_nvals
= attr
->a_vals
;
466 snprintf( textbuf
, textlen
,
467 "attribute '%s' provided more than once",
468 mods
->sml_desc
->ad_cname
.bv_val
);
470 return LDAP_TYPE_OR_VALUE_EXISTS
;
474 attr
= attr_alloc( mods
->sml_desc
);
476 /* move values to attr structure */
477 i
= mods
->sml_numvals
;
478 attr
->a_numvals
= mods
->sml_numvals
;
480 attr
->a_vals
= (BerVarray
) ch_calloc( i
+1, sizeof( BerValue
));
481 for ( i
= 0; mods
->sml_values
[i
].bv_val
; i
++ ) {
482 ber_dupbv( &attr
->a_vals
[i
], &mods
->sml_values
[i
] );
484 BER_BVZERO( &attr
->a_vals
[i
] );
486 attr
->a_vals
= mods
->sml_values
;
489 if ( mods
->sml_nvalues
) {
491 i
= mods
->sml_numvals
;
492 attr
->a_nvals
= (BerVarray
) ch_calloc( i
+1, sizeof( BerValue
));
493 for ( i
= 0; mods
->sml_nvalues
[i
].bv_val
; i
++ ) {
494 ber_dupbv( &attr
->a_nvals
[i
], &mods
->sml_nvalues
[i
] );
496 BER_BVZERO( &attr
->a_nvals
[i
] );
498 attr
->a_nvals
= mods
->sml_nvalues
;
501 attr
->a_nvals
= attr
->a_vals
;
503 /* slap_mods_check() gives us sorted results */
504 if ( attr
->a_desc
->ad_type
->sat_flags
& SLAP_AT_SORTED_VAL
)
505 attr
->a_flags
|= SLAP_ATTR_SORTED_VALS
;
508 tail
= &attr
->a_next
;
519 Modifications
**mods
,
521 char *textbuf
, size_t textlen
)
523 Modifications
*modhead
= NULL
;
525 Modifications
**modtail
= &modhead
;
527 AttributeDescription
*a_new_desc
;
532 while ( a_new
!= NULL
) {
533 a_new_desc
= a_new
->a_desc
;
534 mod
= (Modifications
*) malloc( sizeof( Modifications
));
536 mod
->sml_op
= LDAP_MOD_REPLACE
;
539 mod
->sml_type
= a_new_desc
->ad_cname
;
541 count
= a_new
->a_numvals
;
542 mod
->sml_numvals
= a_new
->a_numvals
;
544 mod
->sml_values
= (struct berval
*) malloc(
545 (count
+1) * sizeof( struct berval
) );
547 /* see slap_mods_check() comments...
548 * if a_vals == a_nvals, there is no normalizer.
549 * in this case, mod->sml_nvalues must be left NULL.
551 if ( a_new
->a_vals
!= a_new
->a_nvals
) {
552 mod
->sml_nvalues
= (struct berval
*) malloc(
553 (count
+1) * sizeof( struct berval
) );
555 mod
->sml_nvalues
= NULL
;
558 for ( i
= 0; i
< count
; i
++ ) {
559 ber_dupbv(mod
->sml_values
+i
, a_new
->a_vals
+i
);
560 if ( mod
->sml_nvalues
) {
561 ber_dupbv( mod
->sml_nvalues
+i
, a_new
->a_nvals
+i
);
565 mod
->sml_values
[count
].bv_val
= NULL
;
566 mod
->sml_values
[count
].bv_len
= 0;
568 if ( mod
->sml_nvalues
) {
569 mod
->sml_nvalues
[count
].bv_val
= NULL
;
570 mod
->sml_nvalues
[count
].bv_len
= 0;
573 mod
->sml_desc
= a_new_desc
;
576 modtail
= &mod
->sml_next
;
577 a_new
= a_new
->a_next
;
585 int slap_add_opattrs(
592 struct berval name
, timestamp
, csn
= BER_BVNULL
;
593 struct berval nname
, tmp
;
594 char timebuf
[ LDAP_LUTIL_GENTIME_BUFSIZE
];
595 char csnbuf
[ LDAP_LUTIL_CSNSTR_BUFSIZE
];
598 if ( SLAP_LASTMOD( op
->o_bd
) ) {
602 timestamp
.bv_val
= timebuf
;
603 a
= attr_find( op
->ora_e
->e_attrs
, slap_schema
.si_ad_entryCSN
);
608 if ( BER_BVISEMPTY( &op
->o_csn
)) {
611 csn
.bv_len
= sizeof(csnbuf
);
612 slap_get_csn( op
, &csn
, manage_ctxcsn
);
615 slap_queue_csn( op
, &csn
);
620 ptr
= ber_bvchr( &csn
, '#' );
622 timestamp
.bv_len
= STRLENOF("YYYYMMDDHHMMSSZ");
623 AC_MEMCPY( timebuf
, csn
.bv_val
, timestamp
.bv_len
);
624 timebuf
[timestamp
.bv_len
-1] = 'Z';
625 timebuf
[timestamp
.bv_len
] = '\0';
627 time_t now
= slap_get_time();
629 timestamp
.bv_len
= sizeof(timebuf
);
631 slap_timestamp( &now
, ×tamp
);
634 if ( BER_BVISEMPTY( &op
->o_dn
) ) {
635 BER_BVSTR( &name
, SLAPD_ANONYMOUS
);
642 a
= attr_find( op
->ora_e
->e_attrs
,
643 slap_schema
.si_ad_entryUUID
);
645 char uuidbuf
[ LDAP_LUTIL_UUIDSTR_BUFSIZE
];
647 tmp
.bv_len
= lutil_uuidstr( uuidbuf
, sizeof( uuidbuf
) );
648 tmp
.bv_val
= uuidbuf
;
650 attr_merge_normalize_one( op
->ora_e
,
651 slap_schema
.si_ad_entryUUID
, &tmp
, op
->o_tmpmemctx
);
654 a
= attr_find( op
->ora_e
->e_attrs
,
655 slap_schema
.si_ad_creatorsName
);
657 attr_merge_one( op
->ora_e
,
658 slap_schema
.si_ad_creatorsName
, &name
, &nname
);
661 a
= attr_find( op
->ora_e
->e_attrs
,
662 slap_schema
.si_ad_createTimestamp
);
664 attr_merge_one( op
->ora_e
,
665 slap_schema
.si_ad_createTimestamp
, ×tamp
, NULL
);
669 attr_merge_one( op
->ora_e
,
670 slap_schema
.si_ad_entryCSN
, &csn
, NULL
);
673 a
= attr_find( op
->ora_e
->e_attrs
,
674 slap_schema
.si_ad_modifiersName
);
676 attr_merge_one( op
->ora_e
,
677 slap_schema
.si_ad_modifiersName
, &name
, &nname
);
680 a
= attr_find( op
->ora_e
->e_attrs
,
681 slap_schema
.si_ad_modifyTimestamp
);
683 attr_merge_one( op
->ora_e
,
684 slap_schema
.si_ad_modifyTimestamp
, ×tamp
, NULL
);