xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-meta/add.c (revision 09afef20633f5fe63d92dfe43ee3a9380dc06883)
1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/add.c,v 1.51.2.7 2008/02/12 00:25:47 quanah Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2008 The OpenLDAP Foundation.
5  * Portions Copyright 2001-2003 Pierangelo Masarati.
6  * Portions Copyright 1999-2003 Howard Chu.
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 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by the Howard Chu for inclusion
19  * in OpenLDAP Software and subsequently enhanced by Pierangelo
20  * Masarati.
21  */
22 
23 
24 #include "portable.h"
25 
26 #include <stdio.h>
27 
28 #include <ac/string.h>
29 #include <ac/socket.h>
30 
31 #include "slap.h"
32 #include "../back-ldap/back-ldap.h"
33 #include "back-meta.h"
34 
35 int
36 meta_back_add( Operation *op, SlapReply *rs )
37 {
38 	metainfo_t	*mi = ( metainfo_t * )op->o_bd->be_private;
39 	metatarget_t	*mt;
40 	metaconn_t	*mc;
41 	int		i, candidate = -1;
42 	int		isupdate;
43 	Attribute	*a;
44 	LDAPMod		**attrs;
45 	struct berval	mdn = BER_BVNULL, mapped;
46 	dncookie	dc;
47 	int		msgid;
48 	int		do_retry = 1;
49 	LDAPControl	**ctrls = NULL;
50 
51 	Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
52 			op->o_req_dn.bv_val, 0, 0 );
53 
54 	/*
55 	 * get the current connection
56 	 */
57 	mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
58 	if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
59 		return rs->sr_err;
60 	}
61 
62 	assert( mc->mc_conns[ candidate ].msc_ld != NULL );
63 
64 	/*
65 	 * Rewrite the add dn, if needed
66 	 */
67 	mt = mi->mi_targets[ candidate ];
68 	dc.target = mt;
69 	dc.conn = op->o_conn;
70 	dc.rs = rs;
71 	dc.ctx = "addDN";
72 
73 	if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
74 		send_ldap_result( op, rs );
75 		goto done;
76 	}
77 
78 	/* Count number of attributes in entry ( +1 ) */
79 	for ( i = 1, a = op->ora_e->e_attrs; a; i++, a = a->a_next );
80 
81 	/* Create array of LDAPMods for ldap_add() */
82 	attrs = ch_malloc( sizeof( LDAPMod * )*i );
83 
84 	dc.ctx = "addAttrDN";
85 	isupdate = be_shadow_update( op );
86 	for ( i = 0, a = op->ora_e->e_attrs; a; a = a->a_next ) {
87 		int			j, is_oc = 0;
88 
89 		if ( !isupdate && !get_relax( op ) && a->a_desc->ad_type->sat_no_user_mod  )
90 		{
91 			continue;
92 		}
93 
94 		if ( a->a_desc == slap_schema.si_ad_objectClass
95 				|| a->a_desc == slap_schema.si_ad_structuralObjectClass )
96 		{
97 			is_oc = 1;
98 			mapped = a->a_desc->ad_cname;
99 
100 		} else {
101 			ldap_back_map( &mt->mt_rwmap.rwm_at,
102 					&a->a_desc->ad_cname, &mapped, BACKLDAP_MAP );
103 			if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
104 				continue;
105 			}
106 		}
107 
108 		attrs[ i ] = ch_malloc( sizeof( LDAPMod ) );
109 		if ( attrs[ i ] == NULL ) {
110 			continue;
111 		}
112 		attrs[ i ]->mod_op = LDAP_MOD_BVALUES;
113 		attrs[ i ]->mod_type = mapped.bv_val;
114 
115 		if ( is_oc ) {
116 			for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ )
117 				;
118 
119 			attrs[ i ]->mod_bvalues =
120 				(struct berval **)ch_malloc( ( j + 1 ) *
121 				sizeof( struct berval * ) );
122 
123 			for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) {
124 				struct ldapmapping	*mapping;
125 
126 				ldap_back_mapping( &mt->mt_rwmap.rwm_oc,
127 						&a->a_vals[ j ], &mapping, BACKLDAP_MAP );
128 
129 				if ( mapping == NULL ) {
130 					if ( mt->mt_rwmap.rwm_oc.drop_missing ) {
131 						continue;
132 					}
133 					attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
134 
135 				} else {
136 					attrs[ i ]->mod_bvalues[ j ] = &mapping->dst;
137 				}
138 				j++;
139 			}
140 			attrs[ i ]->mod_bvalues[ j ] = NULL;
141 
142 		} else {
143 			/*
144 			 * FIXME: dn-valued attrs should be rewritten
145 			 * to allow their use in ACLs at the back-ldap
146 			 * level.
147 			 */
148 			if ( a->a_desc->ad_type->sat_syntax ==
149 				slap_schema.si_syn_distinguishedName )
150 			{
151 				(void)ldap_dnattr_rewrite( &dc, a->a_vals );
152 				if ( a->a_vals == NULL ) {
153 					continue;
154 				}
155 			}
156 
157 			for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ )
158 				;
159 
160 			attrs[ i ]->mod_bvalues = ch_malloc( ( j + 1 ) * sizeof( struct berval * ) );
161 			for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) {
162 				attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ];
163 			}
164 			attrs[ i ]->mod_bvalues[ j ] = NULL;
165 		}
166 		i++;
167 	}
168 	attrs[ i ] = NULL;
169 
170 retry:;
171 	ctrls = op->o_ctrls;
172 	if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
173 	{
174 		send_ldap_result( op, rs );
175 		goto cleanup;
176 	}
177 
178 	rs->sr_err = ldap_add_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
179 			      attrs, ctrls, NULL, &msgid );
180 	rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
181 		mt->mt_timeout[ SLAP_OP_ADD ], LDAP_BACK_SENDRESULT );
182 	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
183 		do_retry = 0;
184 		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
185 			/* if the identity changed, there might be need to re-authz */
186 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
187 			goto retry;
188 		}
189 	}
190 
191 cleanup:;
192 	(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
193 
194 	for ( --i; i >= 0; --i ) {
195 		free( attrs[ i ]->mod_bvalues );
196 		free( attrs[ i ] );
197 	}
198 	free( attrs );
199 	if ( mdn.bv_val != op->ora_e->e_dn ) {
200 		free( mdn.bv_val );
201 		BER_BVZERO( &mdn );
202 	}
203 
204 done:;
205 	if ( mc ) {
206 		meta_back_release_conn( mi, mc );
207 	}
208 
209 	return rs->sr_err;
210 }
211 
212