1 /*        $NetBSD: operational.c,v 1.3 2021/08/14 16:15:01 christos Exp $       */
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2021 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.3 2021/08/14 16:15:01 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 *
backsql_operational_entryUUID(backsql_info * bi,backsql_entryID * id)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 *
backsql_operational_entryCSN(Operation * op)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
backsql_operational(Operation * op,SlapReply * rs)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 );
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                     return 1;
176           }
177 
178           if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
179                               && !got[ BACKSQL_OP_HASSUBORDINATES ]
180                               && attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL )
181           {
182                     rc = backsql_has_children( op, dbh, &rs->sr_entry->e_nname );
183 
184                     switch( rc ) {
185                     case LDAP_COMPARE_TRUE:
186                     case LDAP_COMPARE_FALSE:
187                               *ap = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE );
188                               assert( *ap != NULL );
189                               ap = &(*ap)->a_next;
190                               rc = 0;
191                               break;
192 
193                     default:
194                               Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
195                                         "has_children failed( %d)\n", rc );
196                               return 1;
197                     }
198           }
199 
200           if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryUUID, rs->sr_attrs ) )
201                               && !got[ BACKSQL_OP_ENTRYUUID ]
202                               && attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID ) == NULL )
203           {
204                     backsql_srch_info   bsi = { 0 };
205 
206                     rc = backsql_init_search( &bsi, &rs->sr_entry->e_nname,
207                                         LDAP_SCOPE_BASE,
208                                         (time_t)(-1), NULL, dbh, op, rs, NULL,
209                                         BACKSQL_ISF_GET_ID );
210                     if ( rc != LDAP_SUCCESS ) {
211                               Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
212                                         "could not retrieve entry ID - no such entry\n" );
213                               return 1;
214                     }
215 
216                     *ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id );
217 
218                     (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
219 
220                     if ( bsi.bsi_attrs != NULL ) {
221                               op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
222                     }
223 
224                     if ( *ap == NULL ) {
225                               Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
226                                         "could not retrieve entryUUID\n" );
227                               return 1;
228                     }
229 
230                     ap = &(*ap)->a_next;
231           }
232 
233           if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryCSN, rs->sr_attrs ) )
234                               && !got[ BACKSQL_OP_ENTRYCSN ]
235                               && attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryCSN ) == NULL )
236           {
237                     *ap = backsql_operational_entryCSN( op );
238                     if ( *ap == NULL ) {
239                               Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
240                                         "could not retrieve entryCSN\n" );
241                               return 1;
242                     }
243 
244                     ap = &(*ap)->a_next;
245           }
246 
247           Debug( LDAP_DEBUG_TRACE, "<==backsql_operational(%d)\n", rc );
248 
249           return rc;
250 }
251 
252