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 41Attribute * 42backsql_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 75Attribute * 76backsql_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 108int 109backsql_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