xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-sql/operational.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /*	$NetBSD: operational.c,v 1.2 2020/08/11 13:15:42 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2020 The OpenLDAP Foundation.
7  * Portions Copyright 1999 Dmitry Kovalev.
8  * Portions Copyright 2002 Pierangelo Masarati.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was initially developed by Dmitry Kovalev for inclusion
21  * by OpenLDAP Software.  Additional significant contributors include
22  * Pierangelo Masarati.
23  */
24 
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: operational.c,v 1.2 2020/08/11 13:15:42 christos Exp $");
27 
28 #include "portable.h"
29 
30 #include <stdio.h>
31 #include <sys/types.h>
32 
33 #include "slap.h"
34 #include "proto-sql.h"
35 #include "lutil.h"
36 
37 /*
38  * sets the supported operational attributes (if required)
39  */
40 
41 Attribute *
42 backsql_operational_entryUUID( backsql_info *bi, backsql_entryID *id )
43 {
44 	int			rc;
45 	struct berval		val, nval;
46 	AttributeDescription	*desc = slap_schema.si_ad_entryUUID;
47 	Attribute		*a;
48 
49 	backsql_entryUUID( bi, id, &val, NULL );
50 
51 	rc = (*desc->ad_type->sat_equality->smr_normalize)(
52 			SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
53 			desc->ad_type->sat_syntax,
54 			desc->ad_type->sat_equality,
55 			&val, &nval, NULL );
56 	if ( rc != LDAP_SUCCESS ) {
57 		ber_memfree( val.bv_val );
58 		return NULL;
59 	}
60 
61 	a = attr_alloc( desc );
62 
63 	a->a_numvals = 1;
64 	a->a_vals = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
65 	a->a_vals[ 0 ] = val;
66 	BER_BVZERO( &a->a_vals[ 1 ] );
67 
68 	a->a_nvals = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
69 	a->a_nvals[ 0 ] = nval;
70 	BER_BVZERO( &a->a_nvals[ 1 ] );
71 
72 	return a;
73 }
74 
75 Attribute *
76 backsql_operational_entryCSN( Operation *op )
77 {
78 	char		csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ];
79 	struct berval	entryCSN;
80 	Attribute	*a;
81 
82 	a = attr_alloc( slap_schema.si_ad_entryCSN );
83 	a->a_numvals = 1;
84 	a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
85 	BER_BVZERO( &a->a_vals[ 1 ] );
86 
87 #ifdef BACKSQL_SYNCPROV
88 	if ( op->o_sync && op->o_tag == LDAP_REQ_SEARCH && op->o_private != NULL ) {
89 		assert( op->o_private != NULL );
90 
91 		entryCSN = *((struct berval *)op->o_private);
92 
93 	} else
94 #endif /* BACKSQL_SYNCPROV */
95 	{
96 		entryCSN.bv_val = csnbuf;
97 		entryCSN.bv_len = sizeof( csnbuf );
98 		slap_get_csn( op, &entryCSN, 0 );
99 	}
100 
101 	ber_dupbv( &a->a_vals[ 0 ], &entryCSN );
102 
103 	a->a_nvals = a->a_vals;
104 
105 	return a;
106 }
107 
108 int
109 backsql_operational(
110 	Operation	*op,
111 	SlapReply	*rs )
112 {
113 
114 	backsql_info 	*bi = (backsql_info*)op->o_bd->be_private;
115 	SQLHDBC 	dbh = SQL_NULL_HDBC;
116 	int		rc = 0;
117 	Attribute	**ap;
118 	enum {
119 		BACKSQL_OP_HASSUBORDINATES = 0,
120 		BACKSQL_OP_ENTRYUUID,
121 		BACKSQL_OP_ENTRYCSN,
122 
123 		BACKSQL_OP_LAST
124 	};
125 	int		get_conn = BACKSQL_OP_LAST,
126 			got[ BACKSQL_OP_LAST ] = { 0 };
127 
128 	Debug( LDAP_DEBUG_TRACE, "==>backsql_operational(): entry \"%s\"\n",
129 			rs->sr_entry->e_nname.bv_val, 0, 0 );
130 
131 	for ( ap = &rs->sr_entry->e_attrs; *ap; ap = &(*ap)->a_next ) {
132 		if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
133 			get_conn--;
134 			got[ BACKSQL_OP_HASSUBORDINATES ] = 1;
135 
136 		} else if ( (*ap)->a_desc == slap_schema.si_ad_entryUUID ) {
137 			get_conn--;
138 			got[ BACKSQL_OP_ENTRYUUID ] = 1;
139 
140 		} else if ( (*ap)->a_desc == slap_schema.si_ad_entryCSN ) {
141 			get_conn--;
142 			got[ BACKSQL_OP_ENTRYCSN ] = 1;
143 		}
144 	}
145 
146 	for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
147 		if ( !got[ BACKSQL_OP_HASSUBORDINATES ] &&
148 			(*ap)->a_desc == slap_schema.si_ad_hasSubordinates )
149 		{
150 			get_conn--;
151 			got[ BACKSQL_OP_HASSUBORDINATES ] = 1;
152 
153 		} else if ( !got[ BACKSQL_OP_ENTRYUUID ] &&
154 			(*ap)->a_desc == slap_schema.si_ad_entryUUID )
155 		{
156 			get_conn--;
157 			got[ BACKSQL_OP_ENTRYUUID ] = 1;
158 
159 		} else if ( !got[ BACKSQL_OP_ENTRYCSN ] &&
160 			(*ap)->a_desc == slap_schema.si_ad_entryCSN )
161 		{
162 			get_conn--;
163 			got[ BACKSQL_OP_ENTRYCSN ] = 1;
164 		}
165 	}
166 
167 	if ( !get_conn ) {
168 		return 0;
169 	}
170 
171 	rc = backsql_get_db_conn( op, &dbh );
172 	if ( rc != LDAP_SUCCESS ) {
173 		Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
174 			"could not get connection handle - exiting\n",
175 			0, 0, 0 );
176 		return 1;
177 	}
178 
179 	if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
180 			&& !got[ BACKSQL_OP_HASSUBORDINATES ]
181 			&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL )
182 	{
183 		rc = backsql_has_children( op, dbh, &rs->sr_entry->e_nname );
184 
185 		switch( rc ) {
186 		case LDAP_COMPARE_TRUE:
187 		case LDAP_COMPARE_FALSE:
188 			*ap = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE );
189 			assert( *ap != NULL );
190 			ap = &(*ap)->a_next;
191 			rc = 0;
192 			break;
193 
194 		default:
195 			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
196 				"has_children failed( %d)\n", rc, 0, 0 );
197 			return 1;
198 		}
199 	}
200 
201 	if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryUUID, rs->sr_attrs ) )
202 			&& !got[ BACKSQL_OP_ENTRYUUID ]
203 			&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID ) == NULL )
204 	{
205 		backsql_srch_info	bsi = { 0 };
206 
207 		rc = backsql_init_search( &bsi, &rs->sr_entry->e_nname,
208 				LDAP_SCOPE_BASE,
209 				(time_t)(-1), NULL, dbh, op, rs, NULL,
210 				BACKSQL_ISF_GET_ID );
211 		if ( rc != LDAP_SUCCESS ) {
212 			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
213 				"could not retrieve entry ID - no such entry\n",
214 				0, 0, 0 );
215 			return 1;
216 		}
217 
218 		*ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id );
219 
220 		(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
221 
222 		if ( bsi.bsi_attrs != NULL ) {
223 			op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
224 		}
225 
226 		if ( *ap == NULL ) {
227 			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
228 				"could not retrieve entryUUID\n",
229 				0, 0, 0 );
230 			return 1;
231 		}
232 
233 		ap = &(*ap)->a_next;
234 	}
235 
236 	if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryCSN, rs->sr_attrs ) )
237 			&& !got[ BACKSQL_OP_ENTRYCSN ]
238 			&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryCSN ) == NULL )
239 	{
240 		*ap = backsql_operational_entryCSN( op );
241 		if ( *ap == NULL ) {
242 			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
243 				"could not retrieve entryCSN\n",
244 				0, 0, 0 );
245 			return 1;
246 		}
247 
248 		ap = &(*ap)->a_next;
249 	}
250 
251 	Debug( LDAP_DEBUG_TRACE, "<==backsql_operational(%d)\n", rc, 0, 0);
252 
253 	return rc;
254 }
255 
256