1 /* $NetBSD: modify.c,v 1.1.1.3 2010/12/12 15:23:25 adam Exp $ */ 2 3 /* OpenLDAP: pkg/ldap/servers/slapd/back-sql/modify.c,v 1.53.2.8 2010/04/13 20:23:43 kurt Exp */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2010 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 "portable.h" 26 27 #include <stdio.h> 28 #include <sys/types.h> 29 #include "ac/string.h" 30 31 #include "slap.h" 32 #include "proto-sql.h" 33 34 int 35 backsql_modify( Operation *op, SlapReply *rs ) 36 { 37 backsql_info *bi = (backsql_info*)op->o_bd->be_private; 38 SQLHDBC dbh = SQL_NULL_HDBC; 39 backsql_oc_map_rec *oc = NULL; 40 backsql_srch_info bsi = { 0 }; 41 Entry m = { 0 }, *e = NULL; 42 int manageDSAit = get_manageDSAit( op ); 43 SQLUSMALLINT CompletionType = SQL_ROLLBACK; 44 45 /* 46 * FIXME: in case part of the operation cannot be performed 47 * (missing mapping, SQL write fails or so) the entire operation 48 * should be rolled-back 49 */ 50 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): modifying entry \"%s\"\n", 51 op->o_req_ndn.bv_val, 0, 0 ); 52 53 rs->sr_err = backsql_get_db_conn( op, &dbh ); 54 if ( rs->sr_err != LDAP_SUCCESS ) { 55 Debug( LDAP_DEBUG_TRACE, " backsql_modify(): " 56 "could not get connection handle - exiting\n", 57 0, 0, 0 ); 58 /* 59 * FIXME: we don't want to send back 60 * excessively detailed messages 61 */ 62 rs->sr_text = ( rs->sr_err == LDAP_OTHER ) 63 ? "SQL-backend error" : NULL; 64 goto done; 65 } 66 67 bsi.bsi_e = &m; 68 rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, 69 LDAP_SCOPE_BASE, 70 (time_t)(-1), NULL, dbh, op, rs, 71 slap_anlist_all_attributes, 72 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) ); 73 switch ( rs->sr_err ) { 74 case LDAP_SUCCESS: 75 break; 76 77 case LDAP_REFERRAL: 78 if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && 79 dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) ) 80 { 81 rs->sr_err = LDAP_SUCCESS; 82 rs->sr_text = NULL; 83 rs->sr_matched = NULL; 84 if ( rs->sr_ref ) { 85 ber_bvarray_free( rs->sr_ref ); 86 rs->sr_ref = NULL; 87 } 88 break; 89 } 90 e = &m; 91 /* fallthru */ 92 93 default: 94 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): " 95 "could not retrieve modifyDN ID - no such entry\n", 96 0, 0, 0 ); 97 if ( !BER_BVISNULL( &m.e_nname ) ) { 98 /* FIXME: should always be true! */ 99 e = &m; 100 101 } else { 102 e = NULL; 103 } 104 goto done; 105 } 106 107 #ifdef BACKSQL_ARBITRARY_KEY 108 Debug( LDAP_DEBUG_TRACE, " backsql_modify(): " 109 "modifying entry \"%s\" (id=%s)\n", 110 bsi.bsi_base_id.eid_dn.bv_val, 111 bsi.bsi_base_id.eid_id.bv_val, 0 ); 112 #else /* ! BACKSQL_ARBITRARY_KEY */ 113 Debug( LDAP_DEBUG_TRACE, " backsql_modify(): " 114 "modifying entry \"%s\" (id=%ld)\n", 115 bsi.bsi_base_id.eid_dn.bv_val, bsi.bsi_base_id.eid_id, 0 ); 116 #endif /* ! BACKSQL_ARBITRARY_KEY */ 117 118 if ( get_assert( op ) && 119 ( test_filter( op, &m, get_assertion( op ) ) 120 != LDAP_COMPARE_TRUE )) 121 { 122 rs->sr_err = LDAP_ASSERTION_FAILED; 123 e = &m; 124 goto done; 125 } 126 127 slap_mods_opattrs( op, &op->orm_modlist, 1 ); 128 129 assert( bsi.bsi_base_id.eid_oc != NULL ); 130 oc = bsi.bsi_base_id.eid_oc; 131 132 if ( !acl_check_modlist( op, &m, op->orm_modlist ) ) { 133 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 134 e = &m; 135 goto done; 136 } 137 138 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, 139 &bsi.bsi_base_id, op->orm_modlist ); 140 if ( rs->sr_err != LDAP_SUCCESS ) { 141 e = &m; 142 goto do_transact; 143 } 144 145 if ( BACKSQL_CHECK_SCHEMA( bi ) ) { 146 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' }; 147 148 backsql_entry_clean( op, &m ); 149 150 bsi.bsi_e = &m; 151 rs->sr_err = backsql_id2entry( &bsi, &bsi.bsi_base_id ); 152 if ( rs->sr_err != LDAP_SUCCESS ) { 153 e = &m; 154 goto do_transact; 155 } 156 157 rs->sr_err = entry_schema_check( op, &m, NULL, 0, 0, NULL, 158 &rs->sr_text, textbuf, sizeof( textbuf ) ); 159 if ( rs->sr_err != LDAP_SUCCESS ) { 160 Debug( LDAP_DEBUG_TRACE, " backsql_modify(\"%s\"): " 161 "entry failed schema check -- aborting\n", 162 m.e_name.bv_val, 0, 0 ); 163 e = NULL; 164 goto do_transact; 165 } 166 } 167 168 do_transact:; 169 /* 170 * Commit only if all operations succeed 171 */ 172 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { 173 assert( e == NULL ); 174 CompletionType = SQL_COMMIT; 175 } 176 177 SQLTransact( SQL_NULL_HENV, dbh, CompletionType ); 178 179 done:; 180 if ( e != NULL ) { 181 if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, 182 ACL_DISCLOSE, NULL ) ) 183 { 184 rs->sr_err = LDAP_NO_SUCH_OBJECT; 185 rs->sr_text = NULL; 186 rs->sr_matched = NULL; 187 if ( rs->sr_ref ) { 188 ber_bvarray_free( rs->sr_ref ); 189 rs->sr_ref = NULL; 190 } 191 } 192 } 193 194 if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) { 195 rs->sr_err = LDAP_X_NO_OPERATION; 196 } 197 198 send_ldap_result( op, rs ); 199 slap_graduate_commit_csn( op ); 200 201 if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { 202 (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); 203 } 204 205 if ( !BER_BVISNULL( &m.e_nname ) ) { 206 backsql_entry_clean( op, &m ); 207 } 208 209 if ( bsi.bsi_attrs != NULL ) { 210 op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); 211 } 212 213 if ( rs->sr_ref ) { 214 ber_bvarray_free( rs->sr_ref ); 215 rs->sr_ref = NULL; 216 } 217 218 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 ); 219 220 return rs->sr_err; 221 } 222 223