From 82f3982b8f22efd68e87144b5fff953ea28f4657 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Sun, 22 Jul 2001 04:28:28 +0000 Subject: [PATCH] Bring in LDBM error handling fixes --- CHANGES | 2 + servers/slapd/Makefile.in | 10 +- servers/slapd/back-ldbm/add.c | 41 +++- servers/slapd/back-ldbm/cache.c | 74 ++++-- servers/slapd/back-ldbm/dn2id.c | 63 +++-- servers/slapd/back-ldbm/filterindex.c | 16 +- servers/slapd/back-ldbm/id2entry.c | 4 + servers/slapd/back-ldbm/idl.c | 6 +- servers/slapd/back-ldbm/modrdn.c | 236 +++++++++---------- servers/slapd/back-ldbm/nextid.c | 69 +++--- servers/slapd/back-ldbm/passwd.c | 12 +- servers/slapd/back-ldbm/proto-back-ldbm.h | 13 +- servers/slapd/back-ldbm/tools.c | 12 +- servers/slapd/dn.c | 117 +++++++++- servers/slapd/libslapd.dsp | 6 +- servers/slapd/modify.c | 50 ---- servers/slapd/mods.c | 69 ++++++ servers/slapd/monitor.c | 266 ---------------------- servers/slapd/proto-slap.h | 5 + servers/slapd/tools/mimic.c | 13 ++ 20 files changed, 548 insertions(+), 536 deletions(-) create mode 100644 servers/slapd/mods.c delete mode 100644 servers/slapd/monitor.c diff --git a/CHANGES b/CHANGES index 43b96a7e10..a8a7b89760 100644 --- a/CHANGES +++ b/CHANGES @@ -6,12 +6,14 @@ OpenLDAP 2.0.12 Engineering Fixed slapd empty rootdn bug (ITS#1172) Fixed slapd numericString empty value bug (ITS#1182) Fixed slapd acl default clause bug (ITS#1187) + Fixed slapd passwd modify replication Added slapadd already exists check (ITS#1191) Added slapd modrdn children check (ITS#1053,1192) Added slapd sb_max_incoming_auth support (ITS#1181) Added slapd crypt salt format support (ITS#1202) Updated slapd schema check handling Updated ldbm to use BerkeleyDB's CDB (ITS#1176) + Updated ldbm error handling Updated slapd filter checks Updated ldaptcl API (contrib) Build environment diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index b2468a28a9..2e42c9f1e5 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -17,8 +17,9 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \ repl.c lock.c controls.c extended.c kerberos.c passwd.c \ schema.c schema_check.c schema_init.c schema_prep.c \ schemaparse.c ad.c at.c mr.c syntax.c oc.c \ - monitor.c configinfo.c starttls.c index.c sets.c\ - root_dse.c sasl.c module.c suffixalias.c $(@PLAT@_SRCS) + configinfo.c starttls.c index.c sets.c \ + root_dse.c sasl.c module.c suffixalias.c mods.c \ + $(@PLAT@_SRCS) OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \ attr.o entry.o config.o backend.o result.o operation.o \ @@ -28,8 +29,9 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \ repl.o lock.o controls.o extended.o kerberos.o passwd.o \ schema.o schema_check.o schema_init.o schema_prep.o \ schemaparse.o ad.o at.o mr.o syntax.o oc.o \ - monitor.o configinfo.o starttls.o index.o sets.o\ - root_dse.o sasl.o module.o suffixalias.o $(@PLAT@_OBJS) + configinfo.o starttls.o index.o sets.o \ + root_dse.o sasl.o module.o suffixalias.o mods.o \ + $(@PLAT@_OBJS) LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index a844bf90ce..1d1951913c 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -28,7 +28,8 @@ ldbm_back_add( char *pdn; Entry *p = NULL; int rootlock = 0; - int rc; + int rc; + ID id = NOID; const char *text = NULL; AttributeDescription *children = slap_schema.si_ad_children; char textbuf[SLAP_TEXT_BUFLEN]; @@ -36,12 +37,15 @@ ldbm_back_add( Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0); + /* nobody else can add until we lock our parent */ ldap_pvt_thread_mutex_lock(&li->li_add_mutex); - if ( ( dn2id( be, e->e_ndn ) ) != NOID ) { + if ( ( rc = dn2id( be, e->e_ndn, &id ) ) || id != NOID ) { + /* if (rc) something bad happened to ldbm cache */ ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); - send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, + send_ldap_result( conn, op, + rc ? LDAP_OPERATIONS_ERROR : LDAP_ALREADY_EXISTS, NULL, NULL, NULL, NULL ); return( -1 ); } @@ -54,6 +58,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "entry failed schema check: %s\n", text, 0, 0 ); + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); return( -1 ); @@ -94,8 +99,10 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); + + send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, + refs == NULL ? "parent does not exist" : "parent is referral", + refs, NULL ); if( matched != NULL ) { ber_bvecfree( refs ); @@ -119,6 +126,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "no write access to parent\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, "no write access to parent", NULL, NULL ); @@ -135,6 +143,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, NULL, "parent is an alias", NULL, NULL ); @@ -153,6 +162,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); @@ -175,6 +185,7 @@ ldbm_back_add( pdn == NULL ? "suffix" : "entry at root", 0, 0 ); + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); @@ -190,9 +201,7 @@ ldbm_back_add( ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); } - e->e_id = next_id( be ); - - if( e->e_id == NOID ) { + if ( next_id( be, &e->e_id ) ) { if( p != NULL) { /* free parent and writer lock */ cache_return_entry_w( &li->li_cache, p ); @@ -206,6 +215,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_ANY, "ldbm_add: next_id failed\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_OTHER, NULL, "next_id add failed", NULL, NULL ); @@ -231,6 +241,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0, 0 ); + send_ldap_result( conn, op, rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OTHER, NULL, rc > 0 ? NULL : "cache add failed", NULL, NULL ); @@ -244,6 +255,7 @@ ldbm_back_add( if ( index_entry_add( be, e, e->e_attrs ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "index_entry_add failed\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_OTHER, NULL, "index generation failed", NULL, NULL ); @@ -254,6 +266,8 @@ ldbm_back_add( if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) { Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0, 0, 0 ); + /* FIXME: delete attr indices? */ + send_ldap_result( conn, op, LDAP_OTHER, NULL, "DN index generation failed", NULL, NULL ); @@ -264,7 +278,10 @@ ldbm_back_add( if ( id2entry_add( be, e ) != 0 ) { Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0, 0, 0 ); + + /* FIXME: delete attr indices? */ (void) dn2id_delete( be, e->e_ndn, e->e_id ); + send_ldap_result( conn, op, LDAP_OTHER, NULL, "entry store failed", NULL, NULL ); @@ -273,7 +290,12 @@ ldbm_back_add( send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, NULL ); + + /* marks the entry as committed, so it is added to the cache; + * otherwise it is removed from the cache, but not destroyed; + * it will be destroyed by the caller */ rc = 0; + cache_entry_commit( e ); return_results:; if (p != NULL) { @@ -287,7 +309,8 @@ return_results:; } if ( rc ) { - /* free entry and writer lock */ + /* in case of error, writer lock is freed + * and entry's private data is destroyed */ cache_return_entry_w( &li->li_cache, e ); } diff --git a/servers/slapd/back-ldbm/cache.c b/servers/slapd/back-ldbm/cache.c index c1ad171020..10f2d7061c 100644 --- a/servers/slapd/back-ldbm/cache.c +++ b/servers/slapd/back-ldbm/cache.c @@ -29,9 +29,10 @@ typedef struct ldbm_entry_info { int lei_state; /* for the cache */ #define CACHE_ENTRY_UNDEFINED 0 #define CACHE_ENTRY_CREATING 1 -#define CACHE_ENTRY_READY 2 -#define CACHE_ENTRY_DELETED 3 - +#define CACHE_ENTRY_READY 2 +#define CACHE_ENTRY_DELETED 3 +#define CACHE_ENTRY_COMMITTED 4 + int lei_refcnt; /* # threads ref'ing this entry */ Entry *lei_lrunext; /* for cache lru list */ Entry *lei_lruprev; @@ -113,6 +114,23 @@ cache_entry_private_init( Entry*e ) return 0; } +/* + * marks an entry in CREATING state as committed, so it is really returned + * to the cache. Otherwise an entry in CREATING state is removed. + * Makes e_private be destroyed at the following cache_return_entry_w, + * but lets the entry untouched (owned by someone else) + */ +void +cache_entry_commit( Entry *e ) +{ + assert( e ); + assert( e->e_private ); + assert( LEI(e)->lei_state == CACHE_ENTRY_CREATING ); + /* assert( LEI(e)->lei_refcnt == 1 ); */ + + LEI(e)->lei_state = CACHE_ENTRY_COMMITTED; +} + static int cache_entry_private_destroy( Entry*e ) { @@ -129,7 +147,7 @@ void cache_return_entry_rw( Cache *cache, Entry *e, int rw ) { ID id; - int refcnt; + int refcnt, freeit = 1; /* set cache mutex */ ldap_pvt_thread_mutex_lock( &cache->c_mutex ); @@ -141,7 +159,18 @@ cache_return_entry_rw( Cache *cache, Entry *e, int rw ) id = e->e_id; refcnt = --LEI(e)->lei_refcnt; - if ( LEI(e)->lei_state == CACHE_ENTRY_CREATING ) { + /* + * if the entry is returned when in CREATING state, it is deleted + * but not freed because it may belong to someone else (do_add, + * for instance) + */ + if ( LEI(e)->lei_state == CACHE_ENTRY_CREATING ) { + cache_delete_entry_internal( cache, e ); + freeit = 0; + /* now the entry is in DELETED state */ + } + + if ( LEI(e)->lei_state == CACHE_ENTRY_COMMITTED ) { LEI(e)->lei_state = CACHE_ENTRY_READY; /* free cache mutex */ @@ -162,7 +191,9 @@ cache_return_entry_rw( Cache *cache, Entry *e, int rw ) } else { cache_entry_private_destroy( e ); - entry_free( e ); + if ( freeit ) { + entry_free( e ); + } /* free cache mutex */ ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); @@ -439,14 +470,33 @@ cache_find_entry_dn2id( Cache *cache, const char *dn ) +{ + char *ndn; + ID id; + + ndn = ch_strdup( dn ); + (void) dn_normalize( ndn ); + + id = cache_find_entry_ndn2id( be, cache, ndn ); + + free( ndn ); + + return ( id ); +} + +ID +cache_find_entry_ndn2id( + Backend *be, + Cache *cache, + const char *ndn +) { Entry e, *ep; ID id; int count = 0; - e.e_dn = (char *) dn; - e.e_ndn = ch_strdup( dn ); - (void) dn_normalize( e.e_ndn ); + /* this function is always called with normalized DN */ + e.e_ndn = (char *)ndn; try_again: /* set cache mutex */ @@ -481,7 +531,7 @@ try_again: Debug(LDAP_DEBUG_TRACE, "====> cache_find_entry_dn2id(\"%s\"): %ld (not ready) %d\n", - dn, id, state); + ndn, id, state); ldap_pvt_thread_yield(); goto try_again; @@ -496,7 +546,7 @@ try_again: Debug(LDAP_DEBUG_TRACE, "====> cache_find_entry_dn2id(\"%s\"): %ld (%d tries)\n", - dn, id, count); + ndn, id, count); } else { /* free cache mutex */ @@ -505,8 +555,6 @@ try_again: id = NOID; } - free(e.e_ndn); - return( id ); } diff --git a/servers/slapd/back-ldbm/dn2id.c b/servers/slapd/back-ldbm/dn2id.c index 81f1154a85..0430a3f64b 100644 --- a/servers/slapd/back-ldbm/dn2id.c +++ b/servers/slapd/back-ldbm/dn2id.c @@ -95,31 +95,38 @@ dn2id_add( return( rc ); } -ID +int dn2id( Backend *be, - const char *dn + const char *dn, + ID *idp ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; DBCache *db; - ID id; Datum key, data; Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 ); + assert( idp ); + /* first check the cache */ - if ( (id = cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) { - Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", id, + if ( (*idp = cache_find_entry_ndn2id( be, &li->li_cache, dn )) != NOID ) { + Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", *idp, 0, 0 ); - return( id ); + return( 0 ); } if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT )) == NULL ) { Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n", LDBM_SUFFIX, 0, 0 ); - return( NOID ); + /* + * return code !0 if ldbm cache open failed; + * callers should handle this + */ + *idp = NOID; + return( -1 ); } ldbm_datum_init( key ); @@ -136,37 +143,42 @@ dn2id( if ( data.dptr == NULL ) { Debug( LDAP_DEBUG_TRACE, "<= dn2id NOID\n", 0, 0, 0 ); - return( NOID ); + *idp = NOID; + return( 0 ); } - AC_MEMCPY( (char *) &id, data.dptr, sizeof(ID) ); + AC_MEMCPY( (char *) idp, data.dptr, sizeof(ID) ); - assert( id != NOID ); + assert( *idp != NOID ); ldbm_datum_free( db->dbc_db, data ); - Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", id, 0, 0 ); - return( id ); + Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", *idp, 0, 0 ); + + return( 0 ); } -ID_BLOCK * +int dn2idl( Backend *be, const char *dn, - int prefix + int prefix, + ID_BLOCK **idlp ) { DBCache *db; Datum key; - ID_BLOCK *idl; Debug( LDAP_DEBUG_TRACE, "=> dn2idl( \"%c%s\" )\n", prefix, dn, 0 ); + assert( idlp != NULL ); + *idlp = NULL; + if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT )) == NULL ) { Debug( LDAP_DEBUG_ANY, "<= dn2idl could not open dn2id%s\n", LDBM_SUFFIX, 0, 0 ); - return NULL; + return -1; } ldbm_datum_init( key ); @@ -175,13 +187,13 @@ dn2idl( key.dptr = ch_malloc( key.dsize ); sprintf( key.dptr, "%c%s", prefix, dn ); - idl = idl_fetch( be, db, key ); + *idlp = idl_fetch( be, db, key ); ldbm_cache_close( be, db ); free( key.dptr ); - return( idl ); + return( 0 ); } @@ -287,13 +299,16 @@ dn2entry_rw( *matched = NULL; } - if ( (id = dn2id( be, dn )) != NOID && - (e = id2entry_rw( be, id, rw )) != NULL ) - { - return( e ); - } + if ( dn2id( be, dn, &id ) ) { + /* something bad happened to ldbm cache */ + return( NULL ); + + } else if ( id != NOID ) { + /* try to return the entry */ + if ((e = id2entry_rw( be, id, rw )) != NULL ) { + return( e ); + } - if ( id != NOID ) { Debug(LDAP_DEBUG_ANY, "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n", rw ? "w" : "r", id, dn); diff --git a/servers/slapd/back-ldbm/filterindex.c b/servers/slapd/back-ldbm/filterindex.c index dea9d89f35..04c1890670 100644 --- a/servers/slapd/back-ldbm/filterindex.c +++ b/servers/slapd/back-ldbm/filterindex.c @@ -44,12 +44,24 @@ filter_candidates( switch ( f->f_choice ) { case SLAPD_FILTER_DN_ONE: Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 ); - result = dn2idl( be, f->f_dn, DN_ONE_PREFIX ); + + /* an error is treated as an empty list */ + if ( dn2idl( be, f->f_dn, DN_ONE_PREFIX, &result ) != 0 + && result != NULL ) { + idl_free( result ); + result = NULL; + } break; case SLAPD_FILTER_DN_SUBTREE: Debug( LDAP_DEBUG_FILTER, "\tDN SUBTREE\n", 0, 0, 0 ); - result = dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX ); + + /* an error is treated as an empty list */ + if ( dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX, &result ) != 0 + && result != NULL ) { + idl_free( result ); + result = NULL; + } break; case LDAP_FILTER_PRESENT: diff --git a/servers/slapd/back-ldbm/id2entry.c b/servers/slapd/back-ldbm/id2entry.c index f38802126d..40aaa60cb3 100644 --- a/servers/slapd/back-ldbm/id2entry.c +++ b/servers/slapd/back-ldbm/id2entry.c @@ -176,5 +176,9 @@ id2entry_rw( Backend *be, ID id, int rw ) Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (disk)\n", rw ? "w" : "r", id, (unsigned long) e ); + /* marks the entry as committed, so it will get added to the cache + * when the lock is released */ + cache_entry_commit( e ); + return( e ); } diff --git a/servers/slapd/back-ldbm/idl.c b/servers/slapd/back-ldbm/idl.c index e189a5bd6b..81f1954f57 100644 --- a/servers/slapd/back-ldbm/idl.c +++ b/servers/slapd/back-ldbm/idl.c @@ -65,10 +65,14 @@ ID_BLOCK * idl_allids( Backend *be ) { ID_BLOCK *idl; + ID id; idl = idl_alloc( 0 ); ID_BLOCK_NMAX(idl) = ID_BLOCK_ALLIDS_VALUE; - ID_BLOCK_NIDS(idl) = next_id_get( be ); + if ( next_id_get( be, &id ) ) { + return NULL; + } + ID_BLOCK_NIDS(idl) = id; return( idl ); } diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c index ac78abf6b1..249c7f94aa 100644 --- a/servers/slapd/back-ldbm/modrdn.c +++ b/servers/slapd/back-ldbm/modrdn.c @@ -51,27 +51,25 @@ ldbm_back_modrdn( Entry *e, *p = NULL; Entry *matched; int rootlock = 0; - int rc = -1; + int rc = -1, rc_id = 0; + ID id = NOID; const char *text = NULL; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; /* Added to support LDAP v2 correctly (deleteoldrdn thing) */ - char *new_rdn_val = NULL; /* Val of new rdn */ - char *new_rdn_type = NULL; /* Type of new rdn */ - char *old_rdn = NULL; /* Old rdn's attr type & val */ - char *old_rdn_type = NULL; /* Type of old rdn attr. */ - char *old_rdn_val = NULL; /* Old rdn attribute value */ + char **new_rdn_vals = NULL; /* Vals of new rdn */ + char **new_rdn_types = NULL; /* Types of new rdn */ + int a_cnt, d_cnt; + char *old_rdn = NULL; /* Old rdn's attr type & val */ + char **old_rdn_types = NULL; /* Types of old rdn attrs. */ + char **old_rdn_vals = NULL; /* Old rdn attribute values */ /* Added to support newSuperior */ Entry *np = NULL; /* newSuperior Entry */ - char *np_dn = NULL; /* newSuperior dn */ + char *np_dn = NULL; /* newSuperior dn */ char *np_ndn = NULL; /* newSuperior ndn */ char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */ /* Used to interface with ldbm_modify_internal() */ - struct berval add_bv; /* Stores new rdn att */ - struct berval *add_bvals[2]; /* Stores new rdn att */ - struct berval del_bv; /* Stores old rdn att */ - struct berval *del_bvals[2]; /* Stores old rdn att */ - Modifications mod[2]; /* Used to delete old rdn */ + Modifications *mod = NULL; /* Used to delete old/add new rdn */ int manageDSAit = get_manageDSAit( op ); Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n", @@ -121,7 +119,7 @@ ldbm_back_modrdn( } if ( has_children( be, e ) ) { - Debug( LDAP_DEBUG_TRACE, "entry %s referral\n", 0, + Debug( LDAP_DEBUG_TRACE, "entry %s referral\n", e->e_dn, 0, 0 ); send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, @@ -129,8 +127,7 @@ ldbm_back_modrdn( goto return_results; } - if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) { - + if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL && p_ndn[0] != '\0' ) { /* Make sure parent entry exist and we can write its * children. */ @@ -138,6 +135,7 @@ ldbm_back_modrdn( if( (p = dn2entry_w( be, p_ndn, NULL )) == NULL) { Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0, 0, 0); + send_ldap_result( conn, op, LDAP_OTHER, NULL, "parent entry does not exist", NULL, NULL ); @@ -150,6 +148,7 @@ ldbm_back_modrdn( { Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); goto return_results; @@ -158,18 +157,18 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: wr to children of entry %s OK\n", p_ndn, 0, 0 ); - + p_dn = dn_parent( be, e->e_dn ); - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n", p_dn, 0, 0 ); } else { /* no parent, modrdn entry directly under root */ - if( ! be_isroot( be, op->o_ndn ) ) { + if( ! be_isroot( be, op->o_ndn ) && ! be_issuffix( be, "" ) ) { Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0, 0, 0); + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); goto return_results; @@ -181,7 +180,6 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: no parent, locked root\n", 0, 0, 0 ); - } new_parent_dn = p_dn; /* New Parent unless newSuperior given */ @@ -200,12 +198,12 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new parent \"%s\" seems to be the same as old parent \"%s\"...\n", newSuperior, p_dn, 0 ); + newSuperior = NULL; /* ignore newSuperior */ } } if ( newSuperior != NULL ) { - /* newSuperior == entry being moved?, if so ==> ERROR */ /* Get Entry with dn=newSuperior. Does newSuperior exist? */ @@ -213,6 +211,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: newSup(ndn=%s) not here!\n", np_ndn, 0, 0); + send_ldap_result( conn, op, LDAP_OTHER, NULL, "newSuperior not found", NULL, NULL ); goto return_results; @@ -221,7 +220,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: wr to new parent OK np=%p, id=%ld\n", np, np->e_id, 0 ); - + /* check newSuperior for "children" acl */ if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE ) ) @@ -229,6 +228,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: no wr to newSup children\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); goto return_results; @@ -239,6 +239,7 @@ ldbm_back_modrdn( Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, NULL, "newSuperior is an alias", NULL, NULL ); @@ -265,10 +266,8 @@ ldbm_back_modrdn( } /* Build target dn and make sure target entry doesn't exist already. */ - build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn ); - new_ndn = ch_strdup(new_dn); (void) dn_normalize( new_ndn ); @@ -283,8 +282,10 @@ ldbm_back_modrdn( } ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - if (dn2id ( be, new_ndn ) != NOID) { - send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, + if ( ( rc_id = dn2id ( be, new_ndn, &id ) ) || id != NOID ) { + /* if (rc_id) something bad happened to ldbm cache */ + send_ldap_result( conn, op, + rc_id ? LDAP_OPERATIONS_ERROR : LDAP_ALREADY_EXISTS, NULL, NULL, NULL, NULL ); goto return_results; } @@ -293,144 +294,136 @@ ldbm_back_modrdn( "ldbm_back_modrdn: new ndn=%s does not exist\n", new_ndn, 0, 0 ); - /* Get attribute type and attribute value of our new rdn, we will + + /* Get attribute types and values of our new rdn, we will * need to add that to our new entry */ - - if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) { - + if ( rdn_attrs( newrdn, &new_rdn_types, &new_rdn_vals ) ) { Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out type of newrdn\n", + "ldbm_back_modrdn: can't figure out type(s)/value(s) of newrdn\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "unknown type used in RDN", NULL, NULL ); - goto return_results; - } - - if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out val of newrdn\n", - 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, "could not parse RDN value", NULL, NULL ); + NULL, "unable to parse type(s)/value(s) used in RDN", NULL, NULL ); goto return_results; - } Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n", - new_rdn_val, new_rdn_type, 0 ); + new_rdn_vals[0], new_rdn_types[0], 0 ); /* Retrieve the old rdn from the entry's dn */ - if ( (old_rdn = dn_rdn( be, dn )) == NULL ) { Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: can't figure out old_rdn from dn\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_OTHER, NULL, "could not parse old DN", NULL, NULL ); goto return_results; } - if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) { + if ( rdn_attrs( old_rdn, &old_rdn_types, &old_rdn_vals ) ) { Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out the old_rdn type\n", + "ldbm_back_modrdn: can't figure out the old_rdn type(s)/value(s)\n", 0, 0, 0 ); + send_ldap_result( conn, op, LDAP_OTHER, - NULL, "count parse RDN from old DN", NULL, NULL ); + NULL, "unable to parse type(s)/value(s) used in RDN from old DN", NULL, NULL ); goto return_results; } if ( newSuperior == NULL - && strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) + && charray_strcasecmp( (const char **)old_rdn_types, (const char **)new_rdn_types ) != 0 ) { /* Not a big deal but we may say something */ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n", - old_rdn_type, new_rdn_type, 0 ); + old_rdn_types[0], new_rdn_types[0], 0 ); } - Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n", - 0, 0, 0 ); - - /* Add new attribute value to the entry. - */ + Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n", + 0, 0, 0 ); - add_bvals[0] = &add_bv; /* Array of bervals */ - add_bvals[1] = NULL; + mod = NULL; + for ( a_cnt = 0; new_rdn_types[a_cnt]; a_cnt++ ) { + int rc; + Modifications *mod_tmp; - add_bv.bv_val = new_rdn_val; - add_bv.bv_len = strlen(new_rdn_val); - - { + mod_tmp = (Modifications *)ch_malloc( sizeof( Modifications ) ); + + mod_tmp->sml_desc = NULL; + rc = slap_str2ad( new_rdn_types[a_cnt], + &mod_tmp->sml_desc, &text ); + + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + "ldbm_back_modrdn: %s: %s (new)\n", + text, new_rdn_types[a_cnt], 0 ); + + send_ldap_result( conn, op, rc, + NULL, text, NULL, NULL ); + + goto return_results; + } + + mod_tmp->sml_bvalues = (struct berval **)ch_malloc( 2 * sizeof(struct berval *) ); + mod_tmp->sml_bvalues[0] = ber_bvstrdup( new_rdn_vals[a_cnt] ); + mod_tmp->sml_bvalues[1] = NULL; + mod_tmp->sml_op = SLAP_MOD_SOFTADD; + mod_tmp->sml_next = mod; + mod = mod_tmp; + } + + /* Remove old rdn value if required */ + if ( deleteoldrdn ) { + /* Get value of old rdn */ + if ( old_rdn_vals == NULL ) { + Debug( LDAP_DEBUG_TRACE, + "ldbm_back_modrdn: can't figure out oldRDN value(s) from old RDN\n", + 0, 0, 0 ); + + send_ldap_result( conn, op, LDAP_OTHER, + NULL, "could not parse value(s) from old RDN", NULL, NULL ); + goto return_results; + } + + for ( d_cnt = 0; old_rdn_types[d_cnt]; d_cnt++ ) { int rc; + Modifications *mod_tmp; + + mod_tmp = (Modifications *)ch_malloc( sizeof( Modifications ) ); + - mod[0].sml_desc = NULL; - rc = slap_str2ad( new_rdn_type, &mod[0].sml_desc, &text ); + mod_tmp->sml_desc = NULL; + rc = slap_str2ad( old_rdn_types[d_cnt], + &mod_tmp->sml_desc, &text ); - if( rc != LDAP_SUCCESS ) { + if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: %s: %s (new)\n", - text, new_rdn_type, 0 ); + "ldbm_back_modrdn: %s: %s (old)\n", + text, old_rdn_types[d_cnt], 0 ); + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); - goto return_results; - } - } - mod[0].sml_bvalues = add_bvals; - mod[0].sml_op = SLAP_MOD_SOFTADD; - mod[0].sml_next = NULL; - - /* Remove old rdn value if required */ - if (deleteoldrdn) { - /* Get value of old rdn */ - - if ((old_rdn_val = rdn_attr_value( old_rdn )) - == NULL) { - - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "could not parse value from old RDN", NULL, NULL ); - goto return_results; + goto return_results; } - del_bvals[0] = &del_bv; /* Array of bervals */ - del_bvals[1] = NULL; - /* Remove old value of rdn as an attribute. */ - - del_bv.bv_val = old_rdn_val; - del_bv.bv_len = strlen(old_rdn_val); - - { - int rc; - - mod[1].sml_desc = NULL; - rc = slap_str2ad( old_rdn_type, &mod[1].sml_desc, &text ); - - if( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, - "ldbm_back_modrdn: %s: %s (old)\n", - text, old_rdn_type, 0 ); - send_ldap_result( conn, op, rc, - NULL, text, NULL, NULL ); - goto return_results; - } - } - mod[0].sml_next = &mod[1]; - mod[1].sml_bvalues = del_bvals; - mod[1].sml_op = LDAP_MOD_DELETE; - mod[1].sml_next = NULL; + mod_tmp->sml_bvalues = (struct berval **)ch_malloc( 2 * sizeof(struct berval *) ); + mod_tmp->sml_bvalues[0] = ber_bvstrdup( old_rdn_vals[d_cnt] ); + mod_tmp->sml_bvalues[1] = NULL; + mod_tmp->sml_op = LDAP_MOD_DELETE; + mod_tmp->sml_next = mod; + mod = mod_tmp; Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: removing old_rdn_val=%s\n", - old_rdn_val, 0, 0 ); + old_rdn_vals[0], 0, 0 ); } + } + /* check for abandon */ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex ); @@ -477,6 +470,7 @@ ldbm_back_modrdn( goto return_results; } + rc = -1; (void) cache_update_entry( &li->li_cache, e ); @@ -486,7 +480,6 @@ ldbm_back_modrdn( /* id2entry index */ if ( id2entry_add( be, e ) != 0 ) { - entry_free( e ); send_ldap_result( conn, op, LDAP_OTHER, NULL, "entry update failed", NULL, NULL ); goto return_results; @@ -495,6 +488,7 @@ ldbm_back_modrdn( send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, NULL ); rc = 0; + cache_entry_commit( e ); return_results: if( new_dn != NULL ) free( new_dn ); @@ -504,12 +498,15 @@ return_results: if( p_ndn != NULL ) free( p_ndn ); /* LDAP v2 supporting correct attribute handling. */ - if( new_rdn_type != NULL ) free(new_rdn_type); - if( new_rdn_val != NULL ) free(new_rdn_val); + if( new_rdn_types != NULL ) charray_free( new_rdn_types ); + if( new_rdn_vals != NULL ) charray_free( new_rdn_vals ); if( old_rdn != NULL ) free(old_rdn); - if( old_rdn_type != NULL ) free(old_rdn_type); - if( old_rdn_val != NULL ) free(old_rdn_val); + if( old_rdn_types != NULL ) charray_free( old_rdn_types ); + if( old_rdn_vals != NULL ) charray_free( old_rdn_vals ); + if ( mod != NULL ) { + slap_mods_free( mod ); + } /* LDAP v3 Support */ if ( np_dn != NULL ) free( np_dn ); @@ -532,5 +529,10 @@ return_results: /* free entry and writer lock */ cache_return_entry_w( &li->li_cache, e ); + if ( rc ) { + /* if rc != 0 the entry is uncached and its private data + * is destroyed; the entry must be freed */ + entry_free( e ); + } return( rc ); } diff --git a/servers/slapd/back-ldbm/nextid.c b/servers/slapd/back-ldbm/nextid.c index 2ea984a852..76bd0e0a15 100644 --- a/servers/slapd/back-ldbm/nextid.c +++ b/servers/slapd/back-ldbm/nextid.c @@ -19,52 +19,54 @@ #include "slap.h" #include "back-ldbm.h" -static ID -next_id_read( Backend *be ) +static int +next_id_read( Backend *be, ID *idp ) { - ID id = NOID; Datum key, data; DBCache *db; + *idp = NOID; + if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT )) == NULL ) { Debug( LDAP_DEBUG_ANY, "Could not open/create nextid" LDBM_SUFFIX "\n", 0, 0, 0 ); - return( NOID ); + + return( -1 ); } ldbm_datum_init( key ); - key.dptr = (char *) &id; + key.dptr = (char *) idp; key.dsize = sizeof(ID); data = ldbm_cache_fetch( db, key ); if( data.dptr != NULL ) { - AC_MEMCPY( &id, data.dptr, sizeof( ID ) ); + AC_MEMCPY( idp, data.dptr, sizeof( ID ) ); ldbm_datum_free( db->dbc_db, data ); } else { - id = 1; + *idp = 1; } ldbm_cache_close( be, db ); - return id; + return( 0 ); } -ID +int next_id_write( Backend *be, ID id ) { - struct ldbminfo *li = (struct ldbminfo *) be->be_private; Datum key, data; DBCache *db; ID noid = NOID; - int flags; + int flags, rc = 0; if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT )) == NULL ) { Debug( LDAP_DEBUG_ANY, "Could not open/create nextid" LDBM_SUFFIX "\n", 0, 0, 0 ); - return( NOID ); + + return( -1 ); } ldbm_datum_init( key ); @@ -78,49 +80,58 @@ next_id_write( Backend *be, ID id ) flags = LDBM_REPLACE; if ( ldbm_cache_store( db, key, data, flags ) != 0 ) { - id = NOID; + rc = -1; } ldbm_cache_close( be, db ); - return id; + return( rc ); } -ID -next_id_get( Backend *be ) +int +next_id_get( Backend *be, ID *idp ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id = NOID; + int rc = 0; + + *idp = NOID; ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex ); if ( li->li_nextid == NOID ) { - li->li_nextid = next_id_read( be ); + if ( ( rc = next_id_read( be, idp ) ) ) { + ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); + return( rc ); + } + li->li_nextid = *idp; } - id = li->li_nextid; + *idp = li->li_nextid; ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); - return id; + return( rc ); } -ID -next_id( Backend *be ) +int +next_id( Backend *be, ID *idp ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id = NOID; + int rc = 0; ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex ); if ( li->li_nextid == NOID ) { - li->li_nextid = next_id_read( be ); + if ( ( rc = next_id_read( be, idp ) ) ) { + ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); + return( rc ); + } + li->li_nextid = *idp; } - if ( li->li_nextid != NOID ) { - id = li->li_nextid++; - - (void) next_id_write( be, li->li_nextid ); + *idp = li->li_nextid++; + if ( next_id_write( be, li->li_nextid ) ) { + rc = -1; } ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); - return id; + return( rc ); } diff --git a/servers/slapd/back-ldbm/passwd.c b/servers/slapd/back-ldbm/passwd.c index 563e2c89c2..4f2e906537 100644 --- a/servers/slapd/back-ldbm/passwd.c +++ b/servers/slapd/back-ldbm/passwd.c @@ -135,12 +135,14 @@ ldbm_back_exop_passwd( *text = "entry modify failed"; goto done; } - } - /* change the entry itself */ - if( id2entry_add( be, e ) != 0 ) { - *text = "entry update failed"; - rc = LDAP_OTHER; + /* change the entry itself */ + if( id2entry_add( be, e ) != 0 ) { + *text = "entry update failed"; + rc = LDAP_OTHER; + } + + replog( be, op, e->e_dn, &ml ); } done: diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index 6ac74e95f9..3d3e22b87e 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -51,8 +51,10 @@ int cache_update_entry LDAP_P(( Cache *cache, Entry *e )); void cache_return_entry_rw LDAP_P(( Cache *cache, Entry *e, int rw )); #define cache_return_entry_r(c, e) cache_return_entry_rw((c), (e), 0) #define cache_return_entry_w(c, e) cache_return_entry_rw((c), (e), 1) +void cache_entry_commit LDAP_P(( Entry *e )); ID cache_find_entry_dn2id LDAP_P(( Backend *be, Cache *cache, const char *dn )); +ID cache_find_entry_ndn2id LDAP_P(( Backend *be, Cache *cache, const char *ndn )); Entry * cache_find_entry_id LDAP_P(( Cache *cache, ID id, int rw )); int cache_delete_entry LDAP_P(( Cache *cache, Entry *e )); void cache_release_all LDAP_P(( Cache *cache )); @@ -69,14 +71,15 @@ void ldbm_cache_flush_all LDAP_P(( Backend *be )); Datum ldbm_cache_fetch LDAP_P(( DBCache *db, Datum key )); int ldbm_cache_store LDAP_P(( DBCache *db, Datum key, Datum data, int flags )); int ldbm_cache_delete LDAP_P(( DBCache *db, Datum key )); +void *ldbm_cache_sync_daemon LDAP_P(( void *)); /* * dn2id.c */ int dn2id_add LDAP_P(( Backend *be, const char *dn, ID id )); -ID dn2id LDAP_P(( Backend *be, const char *dn )); -ID_BLOCK *dn2idl LDAP_P(( Backend *be, const char *dn, int prefix )); +int dn2id LDAP_P(( Backend *be, const char *dn, ID *idp )); +int dn2idl LDAP_P(( Backend *be, const char *dn, int prefix, ID_BLOCK **idlp )); int dn2id_delete LDAP_P(( Backend *be, const char *dn, ID id )); Entry * dn2entry_rw LDAP_P(( Backend *be, const char *dn, Entry **matched, int rw )); @@ -208,9 +211,9 @@ int ldbm_modify_internal LDAP_P((Backend *be, * nextid.c */ -ID next_id LDAP_P(( Backend *be )); -ID next_id_get LDAP_P(( Backend *be )); -ID next_id_write LDAP_P(( Backend *be, ID id )); +int next_id LDAP_P(( Backend *be, ID *idp )); +int next_id_get LDAP_P(( Backend *be, ID *idp )); +int next_id_write LDAP_P(( Backend *be, ID id )); LDAP_END_DECL #endif diff --git a/servers/slapd/back-ldbm/tools.c b/servers/slapd/back-ldbm/tools.c index c630e3e580..b5f31005ca 100644 --- a/servers/slapd/back-ldbm/tools.c +++ b/servers/slapd/back-ldbm/tools.c @@ -156,7 +156,7 @@ ID ldbm_tool_entry_put( assert( slapMode & SLAP_TOOL_MODE ); assert( id2entry != NULL ); - if( next_id_get( be ) == NOID ) { + if ( next_id_get( be, &id ) || id == NOID ) { return NOID; } @@ -165,7 +165,11 @@ ID ldbm_tool_entry_put( Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_put( %ld, \"%s\" )\n", e->e_id, e->e_dn, 0 ); - id = dn2id( be, e->e_ndn ); + if ( dn2id( be, e->e_ndn, &id ) ) { + /* something bad happened to ldbm cache */ + return NOID; + } + if( id != NOID ) { Debug( LDAP_DEBUG_TRACE, "<= ldbm_tool_entry_put: \"%s\" already exists (id=%ld)\n", @@ -246,7 +250,9 @@ int ldbm_tool_sync( BackendDB *be ) assert( slapMode & SLAP_TOOL_MODE ); if ( li->li_nextid != NOID ) { - next_id_write( be, li->li_nextid ); + if ( next_id_write( be, li->li_nextid ) ) { + return( -1 ); + } } return 0; diff --git a/servers/slapd/dn.c b/servers/slapd/dn.c index a5ff45d71b..2fe6ca1868 100644 --- a/servers/slapd/dn.c +++ b/servers/slapd/dn.c @@ -460,10 +460,121 @@ rdn_attr_value( const char * rdn ) } -int rdn_validate( const char * rdn ) +/* rdn_attrs: + * + * Given a string (i.e. an rdn) of the form: + * "attribute_type=attribute_value[+attribute_type=attribute_value[...]]" + * this function stores the types of the attributes in ptypes, that is the + * array of strings "attribute_type" which is placed in newly allocated + * memory, and the values of the attributes in pvalues, that is the + * array of strings "attribute_value" which is placed in newly allocated + * memory. Returns 0 on success, -1 on failure. + * + * note: got part of the code from dn_validate + */ + +int +rdn_attrs( const char * rdn_in, char ***ptypes, char ***pvalues) +{ + char **parts, **p; + + *ptypes = NULL; + *pvalues = NULL; + + /* + * explode the rdn in parts + */ + parts = ldap_explode_rdn( rdn_in, 0 ); + + if ( parts == NULL ) { + return( -1 ); + } + + for ( p = parts; p[0]; p++ ) { + char *s, *e, *d; + + /* split each rdn part in type value */ + s = strchr( p[0], '=' ); + if ( s == NULL ) { + charray_free( *ptypes ); + charray_free( *pvalues ); + charray_free( parts ); + return( -1 ); + } + + /* type should be fine */ + charray_add_n( ptypes, p[0], ( s-p[0] ) ); + + /* value needs to be unescaped + * (maybe this should be moved to ldap_explode_rdn?) */ + for ( e = d = s + 1; e[0]; e++ ) { + if ( *e != '\\' ) { + *d++ = *e; + } + } + d[0] = '\0'; + charray_add( pvalues, s + 1 ); + } + + /* free array */ + charray_free( parts ); + + return( 0 ); +} + + +/* rdn_validate: + * + * 1 if rdn is a legal rdn; + * 0 otherwise (including a sequence of rdns) + * + * note: got it from dn_rdn; it should be rewritten + * according to dn_validate + */ +int +rdn_validate( const char * rdn ) { - /* just a simple check for now */ - return strchr( rdn, '=' ) != NULL; + int inquote; + + if ( rdn == NULL ) { + return( 0 ); + } + + if ( strchr( rdn, '=' ) == NULL ) { + return( 0 ); + } + + while ( *rdn && ASCII_SPACE( *rdn ) ) { + rdn++; + } + + if( *rdn == '\0' ) { + return( 0 ); + } + + inquote = 0; + + for ( ; *rdn; rdn++ ) { + if ( *rdn == '\\' ) { + if ( *(rdn + 1) ) { + rdn++; + } + continue; + } + if ( inquote ) { + if ( *rdn == '"' ) { + inquote = 0; + } + } else { + if ( *rdn == '"' ) { + inquote = 1; + } else if ( DN_SEPARATOR( *rdn ) ) { + return( 0 ); + } + } + } + + return( 1 ); } diff --git a/servers/slapd/libslapd.dsp b/servers/slapd/libslapd.dsp index 700b29c4bc..28c189e59b 100644 --- a/servers/slapd/libslapd.dsp +++ b/servers/slapd/libslapd.dsp @@ -184,10 +184,6 @@ SOURCE=.\config.c # End Source File # Begin Source File -SOURCE=.\configinfo.c -# End Source File -# Begin Source File - SOURCE=.\connection.c # End Source File # Begin Source File @@ -248,7 +244,7 @@ SOURCE=.\modrdn.c # End Source File # Begin Source File -SOURCE=.\monitor.c +SOURCE=.\mods.c # End Source File # Begin Source File diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index 6334a7679c..7e3c90890c 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -511,53 +511,3 @@ int slap_mods_opattrs( return LDAP_SUCCESS; } - -void -slap_mod_free( - Modification *mod, - int freeit -) -{ - ad_free( mod->sm_desc, 1 ); - - if ( mod->sm_bvalues != NULL ) - ber_bvecfree( mod->sm_bvalues ); - - if( freeit ) - free( mod ); -} - -void -slap_mods_free( - Modifications *ml -) -{ - Modifications *next; - - for ( ; ml != NULL; ml = next ) { - next = ml->sml_next; - - slap_mod_free( &ml->sml_mod, 0 ); - free( ml ); - } -} - -void -slap_modlist_free( - LDAPModList *ml -) -{ - LDAPModList *next; - - for ( ; ml != NULL; ml = next ) { - next = ml->ml_next; - - if (ml->ml_type) - free( ml->ml_type ); - - if ( ml->ml_bvalues != NULL ) - ber_bvecfree( ml->ml_bvalues ); - - free( ml ); - } -} diff --git a/servers/slapd/mods.c b/servers/slapd/mods.c new file mode 100644 index 0000000000..7b59cc5e1e --- /dev/null +++ b/servers/slapd/mods.c @@ -0,0 +1,69 @@ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ + +#include "portable.h" + +#include "slap.h" + +void +slap_mod_free( + Modification *mod, + int freeit +) +{ + ad_free( mod->sm_desc, 1 ); + + if ( mod->sm_bvalues != NULL ) + ber_bvecfree( mod->sm_bvalues ); + + if( freeit ) + free( mod ); +} + +void +slap_mods_free( + Modifications *ml +) +{ + Modifications *next; + + for ( ; ml != NULL; ml = next ) { + next = ml->sml_next; + + slap_mod_free( &ml->sml_mod, 0 ); + free( ml ); + } +} + +void +slap_modlist_free( + LDAPModList *ml +) +{ + LDAPModList *next; + + for ( ; ml != NULL; ml = next ) { + next = ml->ml_next; + + if (ml->ml_type) + free( ml->ml_type ); + + if ( ml->ml_bvalues != NULL ) + ber_bvecfree( ml->ml_bvalues ); + + free( ml ); + } +} diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c deleted file mode 100644 index 1c337c53b9..0000000000 --- a/servers/slapd/monitor.c +++ /dev/null @@ -1,266 +0,0 @@ -/* $OpenLDAP$ */ -/* - * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ -/* - * Copyright (c) 1995 Regents of the University of Michigan. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and that due credit is given - * to the University of Michigan at Ann Arbor. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. This software - * is provided ``as is'' without express or implied warranty. - */ - -#include "portable.h" - -#include - -#include -#include -#include - -#include "slap.h" - -#if defined( SLAPD_MONITOR_DN ) - -int -monitor_info( - Entry **entry, - const char **text ) -{ - Entry *e; - char buf[BUFSIZ]; - struct berval val; - struct berval *vals[2]; - int nconns, nwritewaiters, nreadwaiters; - struct tm *ltm; - char *p; - char buf2[22]; - char buf3[22]; - Connection *c; - int connindex; - time_t currenttime; - - vals[0] = &val; - vals[1] = NULL; - - e = (Entry *) ch_calloc( 1, sizeof(Entry) ); - e->e_attrs = NULL; - e->e_dn = ch_strdup( SLAPD_MONITOR_DN ); - e->e_ndn = ch_strdup(SLAPD_MONITOR_DN); - (void) dn_normalize( e->e_ndn ); - e->e_private = NULL; - - val.bv_val = "top"; - val.bv_len = sizeof("top")-1; - attr_merge( e, "objectClass", vals ); - - val.bv_val = "LDAPsubentry"; - val.bv_len = sizeof("LDAPsubentry")-1; - attr_merge( e, "objectClass", vals ); - - val.bv_val = "extensibleObject"; - val.bv_len = sizeof("extensibleObject")-1; - attr_merge( e, "objectClass", vals ); - - { - char *rdn = ch_strdup( SLAPD_MONITOR_DN ); - val.bv_val = strchr( rdn, '=' ); - - if( val.bv_val != NULL ) { - *val.bv_val = '\0'; - val.bv_len = strlen( ++val.bv_val ); - - attr_merge( e, rdn, vals ); - } - - free( rdn ); - } - - val.bv_val = (char *) Versionstr; - if (( p = strchr( Versionstr, '\n' )) == NULL ) { - val.bv_len = strlen( Versionstr ); - } else { - val.bv_len = p - Versionstr; - } - attr_merge( e, "version", vals ); - - sprintf( buf, "%d", - ldap_pvt_thread_pool_backload( &connection_pool) ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "threads", vals ); - - nconns = 0; - nwritewaiters = 0; - nreadwaiters = 0; - - /* loop through the connections */ - for ( c = connection_first( &connindex ); - c != NULL; - c = connection_next( c, &connindex )) - { - nconns++; - if ( c->c_writewaiter ) { - nwritewaiters++; - } - if ( c->c_currentber != NULL ) { - nreadwaiters++; - } - - ldap_pvt_thread_mutex_lock( &gmtime_mutex ); - - ltm = gmtime( &c->c_starttime ); - strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm ); - - ltm = gmtime( &c->c_activitytime ); - strftime( buf3, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm ); - - ldap_pvt_thread_mutex_unlock( &gmtime_mutex ); - - sprintf( buf, - "%ld : %ld " - ": %ld/%ld/%ld/%ld " - ": %ld/%ld/%ld " - ": %s%s%s%s%s%s " - ": %s : %s : %s " - ": %s : %s : %s : %s ", - - c->c_connid, - (long) c->c_protocol, - - c->c_n_ops_received, c->c_n_ops_executing, - c->c_n_ops_pending, c->c_n_ops_completed, - - /* add low-level counters here */ - c->c_n_get, c->c_n_read, c->c_n_write, - - c->c_currentber ? "r" : "", - c->c_writewaiter ? "w" : "", - c->c_ops != NULL ? "x" : "", - c->c_pending_ops != NULL ? "p" : "", - connection_state2str( c->c_conn_state ), - c->c_sasl_bind_in_progress ? "S" : "", - - c->c_cdn ? c->c_cdn : SLAPD_ANONYMOUS, - - c->c_listener_url, - c->c_peer_domain, - c->c_peer_name, - c->c_sock_name, - - buf2, - buf3 - ); - - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "connection", vals ); - } - connection_done(c); - - sprintf( buf, "%d", nconns ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "currentConnections", vals ); - - sprintf( buf, "%ld", connections_nextid() ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "totalConnections", vals ); - - sprintf( buf, "%ld", (long) dtblsize ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "dTableSize", vals ); - - sprintf( buf, "%d", nwritewaiters ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "writeWaiters", vals ); - - sprintf( buf, "%d", nreadwaiters ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "readWaiters", vals ); - - ldap_pvt_thread_mutex_lock(&num_ops_mutex); - sprintf( buf, "%ld", num_ops_initiated ); - ldap_pvt_thread_mutex_unlock(&num_ops_mutex); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "opsInitiated", vals ); - - ldap_pvt_thread_mutex_lock(&num_ops_mutex); - sprintf( buf, "%ld", num_ops_completed ); - ldap_pvt_thread_mutex_unlock(&num_ops_mutex); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "opsCompleted", vals ); - - ldap_pvt_thread_mutex_lock(&num_sent_mutex); - sprintf( buf, "%ld", num_entries_sent ); - ldap_pvt_thread_mutex_unlock(&num_sent_mutex); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "entriesSent", vals ); - - ldap_pvt_thread_mutex_lock(&num_sent_mutex); - sprintf( buf, "%ld", num_refs_sent ); - ldap_pvt_thread_mutex_unlock(&num_sent_mutex); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "referencesSent", vals ); - - ldap_pvt_thread_mutex_lock(&num_sent_mutex); - sprintf( buf, "%ld", num_pdu_sent ); - ldap_pvt_thread_mutex_unlock(&num_sent_mutex); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "pduSent", vals ); - - ldap_pvt_thread_mutex_lock(&num_sent_mutex); - sprintf( buf, "%ld", num_bytes_sent ); - ldap_pvt_thread_mutex_unlock(&num_sent_mutex); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "bytesSent", vals ); - - currenttime = slap_get_time(); - - ldap_pvt_thread_mutex_lock( &gmtime_mutex ); - ltm = gmtime( ¤ttime ); - strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "currenttime", vals ); - - ltm = gmtime( &starttime ); - strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm ); - ldap_pvt_thread_mutex_unlock( &gmtime_mutex ); - - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "starttime", vals ); - - sprintf( buf, "%d", nbackends ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "nbackends", vals ); - -#ifdef HAVE_THREAD_CONCURRENCY - sprintf( buf, "%d", ldap_pvt_thread_get_concurrency() ); - val.bv_val = buf; - val.bv_len = strlen( buf ); - attr_merge( e, "concurrency", vals ); -#endif - - *entry = e; - return LDAP_SUCCESS; -} - -#endif /* slapd_monitor_dn */ diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index c0e9a5f6f9..64c8018925 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -231,11 +231,15 @@ LDAP_SLAPD_F (void) ch_free LDAP_P(( void * )); */ LDAP_SLAPD_F (void) charray_add LDAP_P(( char ***a, const char *s )); +LDAP_SLAPD_F (void) charray_add_n LDAP_P(( char ***a, const char *s, int l )); LDAP_SLAPD_F (void) charray_merge LDAP_P(( char ***a, char **s )); LDAP_SLAPD_F (void) charray_free LDAP_P(( char **array )); LDAP_SLAPD_F (int) charray_inlist LDAP_P(( char **a, const char *s )); LDAP_SLAPD_F (char **) charray_dup LDAP_P(( char **a )); LDAP_SLAPD_F (char **) str2charray LDAP_P(( const char *str, const char *brkstr )); +LDAP_SLAPD_F (int) charray_strcmp LDAP_P(( const char **a1, const char **a2 )); +LDAP_SLAPD_F (int) charray_strcasecmp LDAP_P(( const char **a1, const char **a2 )); + /* * controls.c @@ -306,6 +310,7 @@ LDAP_SLAPD_F (int) dn_issuffix LDAP_P(( const char *dn, const char *suffix )); LDAP_SLAPD_F (int) rdn_validate LDAP_P(( const char* str )); LDAP_SLAPD_F (char *) rdn_attr_value LDAP_P(( const char * rdn )); LDAP_SLAPD_F (char *) rdn_attr_type LDAP_P(( const char * rdn )); +LDAP_SLAPD_F (int) rdn_attrs LDAP_P(( const char * rdn, char ***ptypes, char ***pvals )); LDAP_SLAPD_F (void) build_new_dn LDAP_P(( char ** new_dn, const char *e_dn, diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index 0ac35c990d..3f18906061 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -17,6 +17,9 @@ time_t starttime; #endif +/* because Versionstr is used in back-monitor */ +const char Versionstr[] = ""; + /* bogus ../results.c */ int str2result( char* s, @@ -155,3 +158,13 @@ void connection2anonymous( Connection *c ) { assert(0); } + +void replog( Backend *be, Operation *op, char *dn, void *change) +{ + assert(0); +} + +void slap_mods_free( Modifications *ml ) +{ + assert(0); +} -- 2.47.2