From 2df20cb03abca6a4b69535aa8371507b9d5cea35 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Tue, 29 Oct 2002 02:26:19 +0000 Subject: [PATCH] numSubordinates and lcup (behind #ifdefs) update_anon --- servers/slapd/abandon.c | 17 +++- servers/slapd/backend.c | 31 +++++- servers/slapd/config.c | 16 ++-- servers/slapd/connection.c | 51 +++------- servers/slapd/controls.c | 3 + servers/slapd/daemon.c | 176 ++++++++++++++++++++++------------- servers/slapd/filterentry.c | 59 +++++++++++- servers/slapd/phonetic.c | 4 + servers/slapd/proto-slap.h | 8 +- servers/slapd/result.c | 4 +- servers/slapd/schema_check.c | 2 +- servers/slapd/schema_prep.c | 13 ++- servers/slapd/search.c | 15 ++- servers/slapd/slap.h | 75 +++++++++++++-- 14 files changed, 334 insertions(+), 140 deletions(-) diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c index 80ea94be0c..5f2ac08275 100644 --- a/servers/slapd/abandon.c +++ b/servers/slapd/abandon.c @@ -30,9 +30,12 @@ do_abandon( Operation *op ) { - ber_int_t id; + ber_int_t id; Operation *o; - int rc; + int rc; +#ifdef LDAP_CLIENT_UPDATE + int i; +#endif #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "conn: %d do_abandon\n", conn->c_connid, 0, 0); @@ -105,6 +108,16 @@ do_abandon( } done: + +#if LDAP_CLIENT_UPDATE + for ( i = 0; i < nbackends; i++ ) { + if ( strncmp( backends[i].be_type, "bdb", 3 ) ) continue; + if ( bdb_abandon( &backends[i], conn, id ) == LDAP_SUCCESS ) { + break; + } + } +#endif + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); #ifdef NEW_LOGGING diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 04fac3ccec..124ec7c422 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -910,10 +910,20 @@ backend_check_restrictions( return LDAP_CONFIDENTIALITY_REQUIRED; } - if( op->o_ndn.bv_len == 0 ) { + if( !( global_allows & SLAP_ALLOW_UPDATE_ANON ) && + op->o_ndn.bv_len == 0 ) + { *text = "modifications require authentication"; return LDAP_STRONG_AUTH_REQUIRED; } + +#ifdef SLAP_X_LISTENER_MOD + if ( ! ( conn->c_listener->sl_perms & S_IWUSR ) ) { + /* no "w" mode means readonly */ + *text = "modifications not allowed on this listener"; + return LDAP_UNWILLING_TO_PERFORM; + } +#endif /* SLAP_X_LISTENER_MOD */ } } @@ -964,6 +974,25 @@ backend_check_restrictions( return LDAP_OPERATIONS_ERROR; } } + +#ifdef SLAP_X_LISTENER_MOD + if ( !starttls && op->o_dn.bv_len == 0 ) { + if ( ! ( conn->c_listener->sl_perms & S_IXUSR ) ) { + /* no "x" mode means bind required */ + *text = "bind required on this listener"; + return LDAP_STRONG_AUTH_REQUIRED; + } + } + + if ( !starttls && !updateop ) { + if ( ! ( conn->c_listener->sl_perms & S_IRUSR ) ) { + /* no "r" mode means no read */ + *text = "read not allowed on this listener"; + return LDAP_UNWILLING_TO_PERFORM; + } + } +#endif /* SLAP_X_LISTENER_MOD */ + } if( restrictops & opflag ) { diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 72a9964021..80ea143703 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -1271,16 +1271,18 @@ read_config( const char *fname, int depth ) } else if( strcasecmp( cargv[i], "bind_anon_dn" ) == 0 ) { allows |= SLAP_ALLOW_BIND_ANON_DN; + } else if( strcasecmp( cargv[i], "update_anon" ) == 0 ) { + allows |= SLAP_ALLOW_UPDATE_ANON; + } else if( strcasecmp( cargv[i], "none" ) != 0 ) { #ifdef NEW_LOGGING - LDAP_LOG( CONFIG, CRIT, - "%s: line %d: unknown feature %s in " - "\"allow \" line.\n", - fname, lineno, cargv[1] ); + LDAP_LOG( CONFIG, CRIT, "%s: line %d: " + "unknown feature %s in \"allow \" line.\n", + fname, lineno, cargv[1] ); #else - Debug( LDAP_DEBUG_ANY, - "%s: line %d: unknown feature %s in \"allow \" line\n", - fname, lineno, cargv[i] ); + Debug( LDAP_DEBUG_ANY, "%s: line %d: " + "unknown feature %s in \"allow \" line\n", + fname, lineno, cargv[i] ); #endif return( 1 ); diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 241c600391..aeed4237b8 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -320,10 +320,9 @@ static void connection_return( Connection *c ) long connection_init( ber_socket_t s, - const char* url, + Listener *listener, const char* dnsname, const char* peername, - const char* sockname, int tls_udp_option, slap_ssf_t ssf, const char *authid ) @@ -333,9 +332,9 @@ long connection_init( assert( connections != NULL ); + assert( listener != NULL ); assert( dnsname != NULL ); assert( peername != NULL ); - assert( sockname != NULL ); #ifndef HAVE_TLS assert( tls_udp_option != 1 ); @@ -420,14 +419,11 @@ long connection_init( c->c_ndn.bv_len = 0; c->c_groups = NULL; - c->c_listener_url.bv_val = NULL; - c->c_listener_url.bv_len = 0; + c->c_listener = NULL; c->c_peer_domain.bv_val = NULL; c->c_peer_domain.bv_len = 0; c->c_peer_name.bv_val = NULL; c->c_peer_name.bv_len = 0; - c->c_sock_name.bv_val = NULL; - c->c_sock_name.bv_len = 0; LDAP_STAILQ_INIT(&c->c_ops); LDAP_STAILQ_INIT(&c->c_pending_ops); @@ -462,10 +458,9 @@ long connection_init( assert( c->c_dn.bv_val == NULL ); assert( c->c_ndn.bv_val == NULL ); assert( c->c_groups == NULL ); - assert( c->c_listener_url.bv_val == NULL ); + assert( c->c_listener == NULL ); assert( c->c_peer_domain.bv_val == NULL ); assert( c->c_peer_name.bv_val == NULL ); - assert( c->c_sock_name.bv_val == NULL ); assert( LDAP_STAILQ_EMPTY(&c->c_ops) ); assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) ); assert( c->c_sasl_bind_mech.bv_val == NULL ); @@ -474,10 +469,9 @@ long connection_init( assert( c->c_sasl_bindop == NULL ); assert( c->c_currentber == NULL ); - ber_str2bv( url, 0, 1, &c->c_listener_url ); + c->c_listener = listener; ber_str2bv( dnsname, 0, 1, &c->c_peer_domain ); ber_str2bv( peername, 0, 1, &c->c_peer_name ); - ber_str2bv( sockname, 0, 1, &c->c_sock_name ); c->c_n_ops_received = 0; c->c_n_ops_executing = 0; @@ -633,12 +627,7 @@ connection_destroy( Connection *c ) c->c_activitytime = c->c_starttime = 0; connection2anonymous( c ); - - if(c->c_listener_url.bv_val != NULL) { - free(c->c_listener_url.bv_val); - c->c_listener_url.bv_val = NULL; - } - c->c_listener_url.bv_len = 0; + c->c_listener = NULL; if(c->c_peer_domain.bv_val != NULL) { free(c->c_peer_domain.bv_val); @@ -646,31 +635,10 @@ connection_destroy( Connection *c ) } c->c_peer_domain.bv_len = 0; if(c->c_peer_name.bv_val != NULL) { -#ifdef LDAP_PF_LOCAL - /* - * If peer was a domain socket, unlink. Mind you, - * they may be un-named. Should we leave this to - * the client? - */ - if (strncmp(c->c_peer_name.bv_val, "PATH=", - sizeof("PATH=") - 1) == 0) { - char *path = c->c_peer_name.bv_val - + sizeof("PATH=") - 1; - if (path[0] != '\0') { - (void)unlink(path); - } - } -#endif /* LDAP_PF_LOCAL */ - free(c->c_peer_name.bv_val); c->c_peer_name.bv_val = NULL; } c->c_peer_name.bv_len = 0; - if(c->c_sock_name.bv_val != NULL) { - free(c->c_sock_name.bv_val); - c->c_sock_name.bv_val = NULL; - } - c->c_sock_name.bv_len = 0; c->c_sasl_bind_in_progress = 0; if(c->c_sasl_bind_mech.bv_val != NULL) { @@ -1057,7 +1025,12 @@ operations_error: LDAP_STAILQ_REMOVE( &conn->c_ops, arg->co_op, slap_op, o_next); LDAP_STAILQ_NEXT(arg->co_op, o_next) = NULL; - slap_op_free( arg->co_op ); +#ifdef LDAP_CLIENT_UPDATE + if ( !( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) ) +#endif /* LDAP_CLIENT_UPDATE */ + { + slap_op_free( arg->co_op ); + } arg->co_op = NULL; arg->co_conn = NULL; free( (char *) arg ); diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index 7c26ff1c38..acd9f6949f 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -318,6 +318,9 @@ int get_ctrls( case LDAP_REQ_UNBIND: tagmask = SLAP_CTRL_UNBIND; break; + case LDAP_REQ_ABANDON: + tagmask = SLAP_CTRL_ABANDON; + break; case LDAP_REQ_EXTENDED: /* FIXME: check list of extended operations */ tagmask = ~0U; diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index f8fc27aef4..37cd0d7a07 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -22,10 +22,13 @@ #ifdef HAVE_TCPD #include +#define SLAP_STRING_UNKNOWN STRING_UNKNOWN int allow_severity = LOG_INFO; int deny_severity = LOG_NOTICE; -#endif /* TCP Wrappers */ +#else /* ! TCP Wrappers */ +#define SLAP_STRING_UNKNOWN "unknown" +#endif /* ! TCP Wrappers */ #ifdef LDAP_PF_LOCAL #include @@ -311,7 +314,7 @@ static void slap_free_listener_addresses(struct sockaddr **sal) ch_free(sal); } -#ifdef LDAP_PF_LOCAL +#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) static int get_url_perms( char **exts, mode_t *perms, @@ -334,27 +337,53 @@ static int get_url_perms( } if ( strncasecmp( type, LDAPI_MOD_URLEXT "=", sizeof(LDAPI_MOD_URLEXT "=") - 1 ) == 0 ) { - char *value = type + sizeof(LDAPI_MOD_URLEXT "=") - 1; + char *value = type + + ( sizeof(LDAPI_MOD_URLEXT "=") - 1 ); mode_t p = 0; int j; - if ( strlen(value) != 3 ) { - return LDAP_OTHER; - } + switch (strlen(value)) { + case 4: + /* skip leading '0' */ + if ( value[ 0 ] != '0' ) { + return LDAP_OTHER; + } + value++; - for ( j = 0; j < 3; j++ ) { - static mode_t m[ 3 ] - = { S_IRWXU, S_IRWXG, S_IRWXO }; + case 3: + for ( j = 0; j < 3; j++) { + int v; - switch ( value[ j ] ) { - case 'w': - p |= m[ j ]; - break; - case '-': - break; - default: - return LDAP_OTHER; + v = value[ j ] - '0'; + + if ( v < 0 || v > 7 ) { + return LDAP_OTHER; + } + + p |= v << 3*(2-j); + } + break; + + case 10: + for ( j = 1; j < 10; j++ ) { + static mode_t m[] = { 0, + S_IRUSR, S_IWUSR, S_IXUSR, + S_IRGRP, S_IWGRP, S_IXGRP, + S_IROTH, S_IWOTH, S_IXOTH + }; + static char c[] = "-rwxrwxrwx"; + + if ( value[ j ] == c[ j ] ) { + p |= m[ j ]; + + } else if ( value[ j ] != '-' ) { + return LDAP_OTHER; + } } + break; + + default: + return LDAP_OTHER; } *crit = c; @@ -366,7 +395,7 @@ static int get_url_perms( return LDAP_OTHER; } -#endif /* LDAP_PF_LOCAL */ +#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ /* port = 0 indicates AF_LOCAL */ static int slap_get_listener_addresses( @@ -561,10 +590,12 @@ static int slap_open_listener( struct sockaddr **sal, **psal; int socktype = SOCK_STREAM; /* default to COTS */ -#ifdef LDAP_PF_LOCAL - mode_t perms = S_IRWXU; +#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) + /* + * use safe defaults + */ int crit = 1; -#endif +#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ rc = ldap_url_parse( url, &lud ); @@ -581,7 +612,7 @@ static int slap_open_listener( return rc; } - l.sl_url = NULL; + l.sl_url.bv_val = NULL; #ifndef HAVE_TLS if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) { @@ -619,10 +650,6 @@ static int slap_open_listener( } else { err = slap_get_listener_addresses(lud->lud_host, 0, &sal); } - - if ( lud->lud_exts ) { - err = get_url_perms( lud->lud_exts, &perms, &crit ); - } #else #ifdef NEW_LOGGING @@ -648,6 +675,14 @@ static int slap_open_listener( } } +#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) + if ( lud->lud_exts ) { + err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit ); + } else { + l.sl_perms = S_IRWXU; + } +#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ + ldap_free_urldesc( lud ); if ( err ) { return -1; @@ -791,7 +826,7 @@ static int slap_open_listener( #ifdef LDAP_PF_LOCAL case AF_LOCAL: { char *addr = ((struct sockaddr_un *)*sal)->sun_path; - if ( chmod( addr, perms ) < 0 && crit ) { + if ( chmod( addr, l.sl_perms ) < 0 && crit ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, @@ -805,8 +840,10 @@ static int slap_open_listener( slap_free_listener_addresses(psal); return -1; } - l.sl_name = ch_malloc( strlen(addr) + sizeof("PATH=") ); - sprintf( l.sl_name, "PATH=%s", addr ); + l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1; + l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 ); + snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, + "PATH=%s", addr ); } break; #endif /* LDAP_PF_LOCAL */ @@ -821,9 +858,11 @@ static int slap_open_listener( s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr ); #endif port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port ); - l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65535") ); - sprintf( l.sl_name, "IP=%s:%d", - s != NULL ? s : "unknown" , port ); + l.sl_name.bv_val = ber_memalloc( sizeof("IP=255.255.255.255:65535") ); + snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"), + "IP=%s:%d", + s != NULL ? s : SLAP_STRING_UNKNOWN, port ); + l.sl_name.bv_len = strlen( l.sl_name.bv_val ); } break; #ifdef LDAP_PF_INET6 @@ -832,8 +871,11 @@ static int slap_open_listener( inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr, addr, sizeof addr); port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port ); - l.sl_name = ch_malloc( strlen(addr) + sizeof("IP= 65535") ); - sprintf( l.sl_name, "IP=%s %d", addr, port ); + l.sl_name.bv_len = strlen(addr) + sizeof("IP= 65535"); + l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len ); + snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=%s %d", + addr, port ); + l.sl_name.bv_len = strlen( l.sl_name.bv_val ); } break; #endif /* LDAP_PF_INET6 */ @@ -850,7 +892,7 @@ static int slap_open_listener( } AC_MEMCPY(&l.sl_sa, *sal, addrlen); - l.sl_url = ch_strdup( url ); + ber_str2bv( url, 0, 1, &l.sl_url); li = ch_malloc( sizeof( Listener ) ); *li = l; slap_listeners[*cur] = li; @@ -861,7 +903,7 @@ static int slap_open_listener( slap_free_listener_addresses(psal); - if ( l.sl_url == NULL ) + if ( l.sl_url.bv_val == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, RESULTS, @@ -875,10 +917,11 @@ static int slap_open_listener( #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, RESULTS, - "slap_open_listener: daemon initialized %s\n", l.sl_url, 0, 0 ); + "slap_open_listener: daemon initialized %s\n", + l.sl_url.bv_val, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n", - l.sl_url, 0, 0 ); + l.sl_url.bv_val, 0, 0 ); #endif return 0; } @@ -1045,10 +1088,10 @@ close_listeners( #endif /* LDAP_PF_LOCAL */ slapd_close( slap_listeners[l]->sl_sd ); } - if ( slap_listeners[l]->sl_url ) - free ( slap_listeners[l]->sl_url ); - if ( slap_listeners[l]->sl_name ) - free ( slap_listeners[l]->sl_name ); + if ( slap_listeners[l]->sl_url.bv_val ) + ber_memfree( slap_listeners[l]->sl_url.bv_val ); + if ( slap_listeners[l]->sl_name.bv_val ) + ber_memfree( slap_listeners[l]->sl_name.bv_val ); free ( slap_listeners[l] ); slap_listeners[l] = NULL; } @@ -1123,11 +1166,11 @@ slapd_daemon_task( #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: listen( %s, 5 ) failed errno=%d (%s)\n", - slap_listeners[l]->sl_url, err, sock_errstr(err) ); + slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "daemon: listen(%s, 5) failed errno=%d (%s)\n", - slap_listeners[l]->sl_url, err, + slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); #endif return( (void*)-1 ); @@ -1342,7 +1385,7 @@ slapd_daemon_task( char *authid = NULL; char *dnsname = NULL; - char *peeraddr; + char *peeraddr = NULL; #ifdef LDAP_PF_LOCAL char peername[MAXPATHLEN + sizeof("PATH=")]; #elif defined(LDAP_PF_INET6) @@ -1367,9 +1410,8 @@ slapd_daemon_task( */ if ( slap_listeners[l]->sl_is_udp < 2 ) { id = connection_init( - slap_listeners[l]->sl_sd, - slap_listeners[l]->sl_url, "", "", - slap_listeners[l]->sl_name, + slap_listeners[l]->sl_sd, + slap_listeners[l], "", "", 2, ssf, authid ); slap_listeners[l]->sl_is_udp++; } @@ -1523,7 +1565,7 @@ slapd_daemon_task( peeraddr = inet_ntoa( *((struct in_addr *) &from.sa_in6_addr.sin6_addr.s6_addr[12]) ); sprintf( peername, "IP=%s:%d", - peeraddr != NULL ? peeraddr : "unknown", + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); } else { char addr[INET6_ADDRSTRLEN]; @@ -1532,7 +1574,7 @@ slapd_daemon_task( &from.sa_in6_addr.sin6_addr, addr, sizeof addr ); sprintf( peername, "IP=%s %d", - peeraddr != NULL ? peeraddr : "unknown", + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); } break; @@ -1541,7 +1583,7 @@ slapd_daemon_task( case AF_INET: peeraddr = inet_ntoa( from.sa_in_addr.sin_addr ); sprintf( peername, "IP=%s:%d", - peeraddr != NULL ? peeraddr : "unknown", + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in_addr.sin_port ) ); break; @@ -1577,16 +1619,16 @@ slapd_daemon_task( #ifdef HAVE_TCPD if ( !hosts_ctl("slapd", - dnsname != NULL ? dnsname : STRING_UNKNOWN, - peeraddr != NULL ? peeraddr : STRING_UNKNOWN, - STRING_UNKNOWN )) + dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, + SLAP_STRING_UNKNOWN )) { /* DENY ACCESS */ Statslog( LDAP_DEBUG_ANY, "fd=%ld host access from %s (%s) denied.\n", (long) s, - dnsname != NULL ? dnsname : "unknown", - peeraddr != NULL ? peeraddr : "unknown", + dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, 0, 0 ); slapd_close(s); continue; @@ -1595,10 +1637,9 @@ slapd_daemon_task( } id = connection_init(s, - slap_listeners[l]->sl_url, - dnsname != NULL ? dnsname : "unknown", + slap_listeners[l], + dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peername, - slap_listeners[l]->sl_name, #ifdef HAVE_TLS slap_listeners[l]->sl_is_tls, #else @@ -1612,24 +1653,29 @@ slapd_daemon_task( if( id < 0 ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, - "slapd_daemon_task: connection_init(%ld, %s, %s) failed.\n", - (long)s, peername, slap_listeners[l]->sl_name ); + "slapd_daemon_task: " + "connection_init(%ld, %s, %s) " + "failed.\n", + (long)s, peername, + slap_listeners[l]->sl_name.bv_val ); #else Debug( LDAP_DEBUG_ANY, - "daemon: connection_init(%ld, %s, %s) failed.\n", + "daemon: connection_init(%ld, %s, %s) " + "failed.\n", (long) s, peername, - slap_listeners[l]->sl_name ); + slap_listeners[l]->sl_name.bv_val ); #endif slapd_close(s); continue; } Statslog( LDAP_DEBUG_STATS, - "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n", + "daemon: conn=%ld fd=%ld connection from %s " + "(%s) accepted.\n", id, (long) s, peername, - slap_listeners[l]->sl_name, + slap_listeners[l]->sl_name.bv_val, 0 ); slapd_add( s ); diff --git a/servers/slapd/filterentry.c b/servers/slapd/filterentry.c index 82cd8cd327..eee672a9b9 100644 --- a/servers/slapd/filterentry.c +++ b/servers/slapd/filterentry.c @@ -460,6 +460,41 @@ test_ava_filter( } } +#ifdef SLAP_X_FILTER_HASSUBORDINATES + if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates + && be && be->be_has_subordinates ) { + int hasSubordinates; + struct berval hs; + + /* + * No other match should be allowed ... + */ + assert( type == LDAP_FILTER_EQUALITY ); + + if ( (*be->be_has_subordinates)( be, conn, op, e, &hasSubordinates ) ) { + return LDAP_OTHER; + } + + if ( hasSubordinates == LDAP_COMPARE_TRUE ) { + hs.bv_val = "TRUE"; + hs.bv_len = sizeof( "TRUE" ) - 1; + + } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) { + hs.bv_val = "FALSE"; + hs.bv_len = sizeof( "FALSE" ) - 1; + + } else { + return LDAP_OTHER; + } + + if ( bvmatch( &ava->aa_value, &hs ) ) { + return LDAP_COMPARE_TRUE; + } + + return LDAP_COMPARE_FALSE; + } +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + return( LDAP_COMPARE_FALSE ); } @@ -473,13 +508,33 @@ test_presence_filter( AttributeDescription *desc ) { + Attribute *a; + if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH, NULL ) ) { return LDAP_INSUFFICIENT_ACCESS; } - return attrs_find( e->e_attrs, desc ) != NULL - ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; + a = attrs_find( e->e_attrs, desc ); + +#ifdef SLAP_X_FILTER_HASSUBORDINATES + if ( a == NULL && desc == slap_schema.si_ad_hasSubordinates ) { + + /* + * XXX: fairly optimistic: if the function is defined, + * then PRESENCE must succeed, because hasSubordinate + * is boolean-valued; I think we may live with this + * simplification by now + */ + if ( be && be->be_has_subordinates ) { + return LDAP_COMPARE_TRUE; + } + + return LDAP_COMPARE_FALSE; + } +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + + return a != NULL ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; } diff --git a/servers/slapd/phonetic.c b/servers/slapd/phonetic.c index 80522af3e7..bfd2011be1 100644 --- a/servers/slapd/phonetic.c +++ b/servers/slapd/phonetic.c @@ -163,6 +163,10 @@ phonetic( char *s ) #elif defined(SLAPD_METAPHONE) +/* + * Metaphone was originally developed by Lawrence Philips and + * published in the "Computer Language" magazine in 1990. + */ /* * Metaphone copied from C Gazette, June/July 1991, pp 56-57, * author Gary A. Parker, with changes by Bernard Tiffany of the diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index d7a963ed1b..441007c0bb 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -287,10 +287,9 @@ LDAP_SLAPD_F (int) connections_timeout_idle LDAP_P((time_t)); LDAP_SLAPD_F (long) connection_init LDAP_P(( ber_socket_t s, - const char* url, + Listener* url, const char* dnsname, const char* peername, - const char* sockname, int use_tls, slap_ssf_t ssf, const char *id )); @@ -484,11 +483,6 @@ LDAP_SLAPD_F (int) get_vrFilter LDAP_P(( Connection *conn, BerElement *ber, LDAP_SLAPD_F (void) vrFilter_free LDAP_P(( ValuesReturnFilter *f )); LDAP_SLAPD_F (void) vrFilter2bv LDAP_P(( ValuesReturnFilter *f, struct berval *fstr )); -/* - * define to honor hasSubordinates operational attribute in search filters - */ -#undef SLAP_X_FILTER_HASSUBORDINATES - #ifdef SLAP_X_FILTER_HASSUBORDINATES LDAP_SLAPD_F (int) filter_has_subordinates LDAP_P(( Filter *filter )); #endif /* SLAP_X_FILTER_HASSUBORDINATES */ diff --git a/servers/slapd/result.c b/servers/slapd/result.c index e23f9b4368..a7607d646b 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -715,10 +715,10 @@ send_search_entry( if (rc != sizeof(struct sockaddr)) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "send_search_entry: conn %lu ber_printf failed\n", + "send_search_entry: conn %lu ber_write failed\n", conn ? conn->c_connid : 0, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 ); #endif ber_free_buf( ber ); return( 1 ); diff --git a/servers/slapd/schema_check.c b/servers/slapd/schema_check.c index 737a0eb4a1..313668a4cb 100644 --- a/servers/slapd/schema_check.c +++ b/servers/slapd/schema_check.c @@ -739,7 +739,7 @@ int structural_class( } if( sc == NULL ) { - *text = "no structural object classes provided"; + *text = "no structural object class provided"; return LDAP_OBJECT_CLASS_VIOLATION; } diff --git a/servers/slapd/schema_prep.c b/servers/slapd/schema_prep.c index d50649f85e..2cea01e1d9 100644 --- a/servers/slapd/schema_prep.c +++ b/servers/slapd/schema_prep.c @@ -413,7 +413,7 @@ static struct slap_schema_ad_map { offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) }, { "entryUUID", "( 1.3.6.1.4.1.4203.666.1.6 NAME 'entryUUID' " - "DESC 'LCUP/LDUP: universally unique identifier' " + "DESC 'LCUP/LDUP: UUID of the entry' " "EQUALITY octetStringMatch " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} " "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", @@ -421,7 +421,7 @@ static struct slap_schema_ad_map { NULL, NULL, NULL, NULL, NULL, offsetof(struct slap_internal_schema, si_ad_entryUUID) }, { "entryCSN", "( 1.3.6.1.4.1.4203.666.1.7 NAME 'entryCSN' " - "DESC 'LCUP/LDUP: change sequence number' " + "DESC 'LCUP/LDUP: change sequence number of the entry' " "EQUALITY octetStringMatch " "ORDERING octetStringOrderingMatch " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} " @@ -430,6 +430,15 @@ static struct slap_schema_ad_map { NULL, NULL, NULL, NULL, NULL, offsetof(struct slap_internal_schema, si_ad_entryCSN) }, + { "superiorUUID", "( 1.3.6.1.4.1.4203.666.1.11 NAME 'superiorUUID' " + "DESC 'LCUP/LDUP: UUID of the superior entry' " + "EQUALITY octetStringMatch " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} " + "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", + NULL, SLAP_AT_HIDE, + NULL, NULL, NULL, NULL, NULL, + offsetof(struct slap_internal_schema, si_ad_superiorUUID) }, + /* root DSE attributes */ { "altServer", "( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' " "DESC 'RFC2252: alternative servers' " diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 9b4492ea11..4699633403 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -322,12 +322,17 @@ do_search( } return_results:; - if( pbase.bv_val != NULL) free( pbase.bv_val ); - if( nbase.bv_val != NULL) free( nbase.bv_val ); +#ifdef LDAP_CLIENT_UPDATE + if ( !( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) ) +#endif /* LDAP_CLIENT_UPDATE */ + { + if( pbase.bv_val != NULL) free( pbase.bv_val ); + if( nbase.bv_val != NULL) free( nbase.bv_val ); - if( fstr.bv_val != NULL) free( fstr.bv_val ); - if( filter != NULL) filter_free( filter ); - if( an != NULL ) free( an ); + if( fstr.bv_val != NULL) free( fstr.bv_val ); + if( filter != NULL) filter_free( filter ); + if( an != NULL ) free( an ); + } return rc; } diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 055ffa6323..013ec0f593 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -674,6 +674,7 @@ struct slap_internal_schema { AttributeDescription *si_ad_subschemaSubentry; AttributeDescription *si_ad_entryUUID; AttributeDescription *si_ad_entryCSN; + AttributeDescription *si_ad_superiorUUID; /* root DSE attribute descriptions */ AttributeDescription *si_ad_altServer; @@ -1199,6 +1200,15 @@ struct slap_backend_db { #define be_attribute bd_info->bi_acl_attribute #define be_operational bd_info->bi_operational +/* + * define to honor hasSubordinates operational attribute in search filters + * (in previous use there was a flaw with back-bdb and back-ldbm; now it + * is fixed). + */ +#ifdef SLAP_X_FILTER_HASSUBORDINATES +#define be_has_subordinates bd_info->bi_has_subordinates +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + #define be_controls bd_info->bi_controls #define be_connection_init bd_info->bi_connection_init @@ -1253,7 +1263,9 @@ struct slap_backend_db { #define SLAP_ALLOW_BIND_V2 0x0001U /* LDAPv2 bind */ #define SLAP_ALLOW_BIND_ANON_CRED 0x0002U /* cred should be empty */ -#define SLAP_ALLOW_BIND_ANON_DN 0x0003U /* dn should be empty */ +#define SLAP_ALLOW_BIND_ANON_DN 0x0004U /* dn should be empty */ + +#define SLAP_ALLOW_UPDATE_ANON 0x0008U /* allow anonymous updates */ #define SLAP_DISALLOW_BIND_ANON 0x0001U /* no anonymous */ #define SLAP_DISALLOW_BIND_SIMPLE 0x0002U /* simple authentication */ @@ -1396,6 +1408,12 @@ typedef int (BI_operational) LDAP_P((Backend *bd, struct slap_conn *c, struct slap_op *o, Entry *e, AttributeName *attrs, int opattrs, Attribute **a )); +#ifdef SLAP_X_FILTER_HASSUBORDINATES +typedef int (BI_has_subordinates) LDAP_P((Backend *bd, + struct slap_conn *c, struct slap_op *o, + Entry *e, int *has_subordinates )); +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + typedef int (BI_connection_init) LDAP_P((BackendDB *bd, struct slap_conn *c)); typedef int (BI_connection_destroy) LDAP_P((BackendDB *bd, @@ -1489,6 +1507,9 @@ struct slap_backend_info { BI_acl_attribute *bi_acl_attribute; BI_operational *bi_operational; +#ifdef SLAP_X_FILTER_HASSUBORDINATES + BI_has_subordinates *bi_has_subordinates; +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ BI_connection_init *bi_connection_init; BI_connection_destroy *bi_connection_destroy; @@ -1559,6 +1580,39 @@ typedef struct slap_paged_state { ID ps_id; } PagedResultsState; + +#ifdef LDAP_CLIENT_UPDATE +#define LCUP_PSEARCH_BY_ADD 0x01 +#define LCUP_PSEARCH_BY_DELETE 0x02 +#define LCUP_PSEARCH_BY_PREMODIFY 0x03 +#define LCUP_PSEARCH_BY_MODIFY 0x04 +#define LCUP_PSEARCH_BY_SCOPEOUT 0x05 + +struct lcup_search_spec { + struct slap_op *op; + struct berval *base; + struct berval *nbase; + int scope; + int deref; + int slimit; + int tlimit; + Filter *filter; + struct berval *filterstr; + AttributeName *attrs; + int attrsonly; + struct lcup_entry *elist; + ldap_pvt_thread_mutex_t elist_mutex; + int entry_count; + LDAP_LIST_ENTRY(lcup_search_spec) link; +}; + +struct psid_entry { + struct lcup_search_spec* ps; + LDAP_LIST_ENTRY(psid_entry) link; +}; +#endif /* LDAP_CLIENT_UPDATE */ + + /* * represents an operation pending from an ldap client */ @@ -1600,6 +1654,9 @@ typedef struct slap_op { #define SLAP_LCUP_SYNC_AND_PERSIST (0x3) ber_int_t o_clientupdate_interval; struct berval o_clientupdate_state; + LDAP_LIST_HEAD(lss, lcup_search_spec) psearch_spec; + LDAP_LIST_HEAD(pe, psid_entry) premodify_list; + LDAP_LIST_ENTRY(slap_op) link; #endif /* LDAP_CLIENT_UPDATE */ #ifdef LDAP_CONNECTIONLESS @@ -1635,6 +1692,8 @@ typedef struct slap_gacl { char ga_ndn[1]; } GroupAssertion; +typedef struct slap_listener Listener; + /* * represents a connection from an ldap client */ @@ -1650,10 +1709,11 @@ typedef struct slap_conn { time_t c_activitytime; /* when the connection was last used */ unsigned long c_connid; /* id of this connection for stats*/ - struct berval c_listener_url; /* listener URL */ struct berval c_peer_domain; /* DNS name of client */ struct berval c_peer_name; /* peer name (trans=addr:port) */ - struct berval c_sock_name; /* sock name (trans=addr:port) */ + Listener *c_listener; +#define c_listener_url c_listener->sl_url /* listener URL */ +#define c_sock_name c_listener->sl_name /* sock name (trans=addr:port) */ /* only can be changed by binding thread */ int c_sasl_bind_in_progress; /* multi-op bind in progress */ @@ -1717,9 +1777,10 @@ typedef struct slap_conn { /* * listener; need to access it from monitor backend */ -typedef struct slap_listener { - char* sl_url; - char* sl_name; +struct slap_listener { + struct berval sl_url; + struct berval sl_name; + mode_t sl_perms; #ifdef HAVE_TLS int sl_is_tls; #endif @@ -1729,7 +1790,7 @@ typedef struct slap_listener { ber_socket_t sl_sd; Sockaddr sl_sa; #define sl_addr sl_sa.sa_in_addr -} Listener; +}; #ifdef SLAPD_MONITOR /* -- 2.39.2