From e9c2895472d41da41fee1ffb049195b190f6adbc Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 7 Jul 1999 18:51:39 +0000 Subject: [PATCH] Add support for unsolicited notifications. --- servers/slapd/Makefile.in | 4 +- servers/slapd/abandon.c | 4 +- servers/slapd/acl.c | 17 ++-- servers/slapd/add.c | 26 +++--- servers/slapd/ava.c | 4 +- servers/slapd/back-bdb2/modify.c | 4 +- servers/slapd/back-bdb2/search.c | 2 +- servers/slapd/back-ldap/search.c | 2 +- servers/slapd/back-ldbm/modify.c | 4 +- servers/slapd/back-ldbm/search.c | 2 +- servers/slapd/back-passwd/search.c | 4 +- servers/slapd/back-perl/search.c | 3 +- servers/slapd/back-shell/result.c | 2 +- servers/slapd/back-tcl/tcl_util.c | 4 +- servers/slapd/bind.c | 19 +++-- servers/slapd/compare.c | 5 +- servers/slapd/configinfo.c | 2 +- servers/slapd/connection.c | 13 ++- servers/slapd/controls.c | 19 ++++- servers/slapd/delete.c | 5 +- servers/slapd/filter.c | 53 +++++++----- servers/slapd/libslapd.dsp | 4 + servers/slapd/modify.c | 23 +++--- servers/slapd/modrdn.c | 25 +++--- servers/slapd/monitor.c | 6 +- servers/slapd/proto-slap.h | 26 ++++-- servers/slapd/result.c | 124 +++++++++++++++++++++++------ servers/slapd/root_dse.c | 42 ++++------ servers/slapd/schema.c | 81 ++++++++++++++++--- servers/slapd/search.c | 21 +++-- servers/slapd/tools/mimic.c | 3 +- 31 files changed, 372 insertions(+), 181 deletions(-) diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 2c251e85a0..f3c87f6da7 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -9,7 +9,7 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \ dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \ value.c ava.c bind.c unbind.c abandon.c filterentry.c \ phonetic.c acl.c str2filter.c aclparse.c init.c user.c \ - repl.c lock.c controls.c \ + repl.c lock.c controls.c extended.c \ suffixalias.c schema.c schemaparse.c monitor.c configinfo.c \ root_dse.c module.c OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \ @@ -17,7 +17,7 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \ dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \ value.o ava.o bind.o unbind.o abandon.o filterentry.o \ phonetic.o acl.o str2filter.o aclparse.o init.o user.o \ - repl.o lock.o controls.o \ + repl.o lock.o controls.o extended.o \ suffixalias.o schema.o schemaparse.o monitor.o configinfo.o \ root_dse.o module.o diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c index d0eb0244e8..bac282e2b3 100644 --- a/servers/slapd/abandon.c +++ b/servers/slapd/abandon.c @@ -40,7 +40,9 @@ do_abandon( if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "do_abandon: ber_scanf failed\n", 0, 0 ,0 ); - return LDAP_PROTOCOL_ERROR; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } if( (rc = get_ctrls( conn, op, 0 )) != LDAP_SUCCESS ) { diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index cfc8e8923c..6dcdcd5087 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -55,7 +55,7 @@ access_allowed( e->e_dn, attr, 0 ); /* the lastmod attributes are ignored by ACL checking */ - if ( oc_check_operational( attr ) ) { + if ( oc_check_no_usermod_attr( attr ) ) { Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n", attr, 0, 0 ); return(1); @@ -212,7 +212,6 @@ acl_access_allowed( ) { int i; - char *odn; struct access *b; Attribute *at; struct berval bv; @@ -244,11 +243,9 @@ acl_access_allowed( return( default_access >= access ); } - odn = op->o_ndn; - - if ( odn != NULL ) { - bv.bv_val = odn; - bv.bv_len = strlen( odn ); + if ( op->o_ndn != NULL ) { + bv.bv_val = op->o_ndn; + bv.bv_len = strlen( bv.bv_val ); } for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) { @@ -282,7 +279,7 @@ acl_access_allowed( return ACL_GRANT(b->a_access, access ); } } else { - if ( regex_matches( b->a_dnpat, odn, edn, matches ) ) { + if ( regex_matches( b->a_dnpat, op->o_ndn, edn, matches ) ) { Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d access %s\n", i, ACL_GRANT(b->a_access, access) @@ -365,7 +362,7 @@ acl_access_allowed( string_expand(buf, sizeof(buf), b->a_group, edn, matches); (void) dn_normalize_case(buf); - if (backend_group(be, e, buf, odn, + if (backend_group(be, e, buf, op->o_ndn, b->a_group_oc, b->a_group_at) == 0) { Debug( LDAP_DEBUG_ACL, @@ -408,7 +405,7 @@ acl_check_modlist( regmatch_t matches[MAXREMATCHES]; /* the lastmod attributes are ignored by ACL checking */ - if ( oc_check_operational( mlist->ml_type ) ) { + if ( oc_check_no_usermod_attr( mlist->ml_type ) ) { Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n", mlist->ml_type, 0, 0 ); continue; diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 5e85be3aa7..e2438a5d3b 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -57,9 +57,9 @@ do_add( Connection *conn, Operation *op ) /* get the name */ if ( ber_scanf( ber, "{a", /*}*/ &dn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, - "decoding error" ); - return LDAP_PROTOCOL_ERROR; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } e = (Entry *) ch_calloc( 1, sizeof(Entry) ); @@ -80,17 +80,17 @@ do_add( Connection *conn, Operation *op ) struct berval **vals; if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) { - send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, - NULL, "decoding error" ); + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); entry_free( e ); - return LDAP_PROTOCOL_ERROR; + return -1; } if ( vals == NULL ) { Debug( LDAP_DEBUG_ANY, "no values for type %s\n", type, 0, 0 ); - send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, - NULL ); + send_ldap_result( conn, op, + LDAP_PROTOCOL_ERROR, NULL, "no values for type" ); free( type ); entry_free( e ); return LDAP_PROTOCOL_ERROR; @@ -105,9 +105,9 @@ do_add( Connection *conn, Operation *op ) if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) { entry_free( e ); Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, - "decoding error" ); - return LDAP_PROTOCOL_ERROR; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) { @@ -186,7 +186,7 @@ add_created_attrs( Operation *op, Entry *e ) /* remove any attempts by the user to add these attrs */ for ( a = &e->e_attrs; *a != NULL; a = next ) { - if ( oc_check_operational( (*a)->a_type ) ) { + if ( oc_check_no_usermod_attr( (*a)->a_type ) ) { tmp = *a; *a = (*a)->a_next; attr_free( tmp ); @@ -197,7 +197,7 @@ add_created_attrs( Operation *op, Entry *e ) } if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) { - bv.bv_val = "NULLDN"; + bv.bv_val = ""; bv.bv_len = strlen( bv.bv_val ); } else { bv.bv_val = op->o_dn; diff --git a/servers/slapd/ava.c b/servers/slapd/ava.c index 1e10339cb2..33a70723dd 100644 --- a/servers/slapd/ava.c +++ b/servers/slapd/ava.c @@ -18,12 +18,12 @@ get_ava( if ( ber_scanf( ber, "{ao}", &ava->ava_type, &ava->ava_value ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, " get_ava ber_scanf\n", 0, 0, 0 ); - return( LDAP_PROTOCOL_ERROR ); + return( -1 ); } attr_normalize( ava->ava_type ); value_normalize( ava->ava_value.bv_val, attr_syntax( ava->ava_type ) ); - return( 0 ); + return( LDAP_SUCCESS ); } void diff --git a/servers/slapd/back-bdb2/modify.c b/servers/slapd/back-bdb2/modify.c index 8f137608f3..9e891e6a78 100644 --- a/servers/slapd/back-bdb2/modify.c +++ b/servers/slapd/back-bdb2/modify.c @@ -33,9 +33,9 @@ add_lastmods( Operation *op, LDAPModList **modlist ) /* remove any attempts by the user to modify these attrs */ for ( m = modlist; *m != NULL; m = &(*m)->ml_next ) { - if ( oc_check_operational( (*m)->ml_type ) ) { + if ( oc_check_no_usermod_attr( (*m)->ml_type ) ) { Debug( LDAP_DEBUG_TRACE, - "add_lastmods: found operational attr: %s\n", + "add_lastmods: found no user mod attr: %s\n", (*m)->ml_type, 0, 0 ); tmp = *m; *m = (*m)->ml_next; diff --git a/servers/slapd/back-bdb2/search.c b/servers/slapd/back-bdb2/search.c index 3090e89cca..28fed4863a 100644 --- a/servers/slapd/back-bdb2/search.c +++ b/servers/slapd/back-bdb2/search.c @@ -265,7 +265,7 @@ bdb2i_back_search_internal( if (e) { switch ( send_search_entry( be, conn, op, e, - attrs, attrsonly ) ) { + attrs, attrsonly, 0 ) ) { case 0: /* entry sent ok */ nentries++; break; diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index e89cec69ae..6145a0704d 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -158,7 +158,7 @@ ldap_send_entry( if (!attr->a_vals) attr->a_vals = &dummy; } - send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly ); + send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, 0 ); for (;ent.e_attrs;) { attr=ent.e_attrs; ent.e_attrs = attr->a_next; diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index 15c2c72896..9ae8220543 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -33,9 +33,9 @@ add_lastmods( Operation *op, LDAPModList **modlist ) /* remove any attempts by the user to modify these attrs */ for ( m = modlist; *m != NULL; m = &(*m)->ml_next ) { - if ( oc_check_operational( (*m)->ml_type ) ) { + if ( oc_check_no_usermod_attr( (*m)->ml_type ) ) { Debug( LDAP_DEBUG_TRACE, - "add_lastmods: found operational attr: %s\n", + "add_lastmods: found no user mod attr: %s\n", (*m)->ml_type, 0, 0 ); tmp = *m; *m = (*m)->ml_next; diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index 80b184893c..7ab4f5f761 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -264,7 +264,7 @@ ldbm_back_search( } if (e) { switch ( send_search_entry( be, conn, op, e, - attrs, attrsonly ) ) { + attrs, attrsonly, 0 ) ) { case 0: /* entry sent ok */ nentries++; break; diff --git a/servers/slapd/back-passwd/search.c b/servers/slapd/back-passwd/search.c index 859648e9ed..bd61a8070c 100644 --- a/servers/slapd/back-passwd/search.c +++ b/servers/slapd/back-passwd/search.c @@ -139,7 +139,7 @@ passwd_back_search( return( 0 ); } - send_search_entry( be, conn, op, e, attrs, attrsonly ); + send_search_entry( be, conn, op, e, attrs, attrsonly, 0 ); sent++; } @@ -176,7 +176,7 @@ passwd_back_search( e = pw2entry( be, pw, rdn ); if ( test_filter( be, conn, op, e, filter ) == 0 ) { - send_search_entry( be, conn, op, e, attrs, attrsonly ); + send_search_entry( be, conn, op, e, attrs, attrsonly, 0 ); sent++; } diff --git a/servers/slapd/back-perl/search.c b/servers/slapd/back-perl/search.c index 693fcd89fc..7117f4b985 100644 --- a/servers/slapd/back-perl/search.c +++ b/servers/slapd/back-perl/search.c @@ -91,7 +91,8 @@ perl_back_search( op, e, attrs, - attrsonly ); + attrsonly, + 0 ); entry_free( e ); } diff --git a/servers/slapd/back-shell/result.c b/servers/slapd/back-shell/result.c index daa826775d..dfb479e36c 100644 --- a/servers/slapd/back-shell/result.c +++ b/servers/slapd/back-shell/result.c @@ -59,7 +59,7 @@ read_and_send_results( buf, 0, 0 ); } else { send_search_entry( be, conn, op, e, attrs, - attrsonly ); + attrsonly, 0 ); entry_free( e ); } diff --git a/servers/slapd/back-tcl/tcl_util.c b/servers/slapd/back-tcl/tcl_util.c index 3163abcdbc..cdff332fc3 100644 --- a/servers/slapd/back-tcl/tcl_util.c +++ b/servers/slapd/back-tcl/tcl_util.c @@ -1,6 +1,6 @@ /* result.c - tcl backend utility functions * - * $Id: tcl_util.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $ + * $Id: tcl_util.c,v 1.5 1999/02/28 04:55:49 bcollins Exp $ * * Copyright 1999, Ben Collins , All rights reserved. * @@ -80,7 +80,7 @@ interp_send_results ( buf, 0, 0); } else { send_search_entry (be, conn, op, e, attrs, - attrsonly); + attrsonly, 0 ); entry_free (e); } diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index 9586812e3e..4ab5de594a 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -22,7 +22,6 @@ #include "slap.h" char *supportedSASLMechanisms[] = { - "X-CRAM-MD5", "X-DIGEST-MD5", NULL }; @@ -103,8 +102,9 @@ do_bind( if ( tag == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "decoding error" ); + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + rc = -1; goto cleanup; } @@ -131,8 +131,10 @@ do_bind( } if ( tag == LBER_ERROR ) { - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + rc = -1; goto cleanup; } @@ -156,8 +158,8 @@ do_bind( if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) { Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "version not supported" ); + send_ldap_result( conn, op, + rc = LDAP_PROTOCOL_ERROR, NULL, "version not supported" ); goto cleanup; } @@ -165,8 +167,9 @@ do_bind( if ( version < LDAP_VERSION3 ) { Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%d\n", version, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "sasl bind requires LDAPv3" ); + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "sasl bind requires LDAPv3" ); + rc = -1; goto cleanup; } diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index c07c8dabcb..028a4f44d0 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -54,8 +54,9 @@ do_compare( if ( ber_scanf( op->o_ber, "{a{ao}}", &ndn, &ava.ava_type, &ava.ava_value ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" ); - return rc; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } if( ( rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) { diff --git a/servers/slapd/configinfo.c b/servers/slapd/configinfo.c index 332826ceb0..ee6d63fd50 100644 --- a/servers/slapd/configinfo.c +++ b/servers/slapd/configinfo.c @@ -63,7 +63,7 @@ config_info( Connection *conn, Operation *op ) attr_merge( e, "database", vals ); } - send_search_entry( &backends[0], conn, op, e, NULL, 0 ); + send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 ); send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 ); entry_free( e ); diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index dbae86bd30..e8defc9674 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -681,18 +681,22 @@ connection_operation( void *arg_v ) rc = do_abandon( conn, arg->co_op ); break; -#if 0 case LDAP_REQ_EXTENDED: rc = do_extended( conn, arg->co_op ); break; -#endif default: - Debug( LDAP_DEBUG_ANY, "unknown request 0x%lx\n", - arg->co_op->o_tag, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "unknown LDAP request 0x%lx\n", + tag, 0, 0 ); + arg->co_op->o_tag = LBER_ERROR; + send_ldap_disconnect( conn, arg->co_op, + LDAP_PROTOCOL_ERROR, "unknown LDAP request" ); + rc = -1; break; } + if( rc == -1 ) tag = LBER_ERROR; + ldap_pvt_thread_mutex_lock( &num_ops_mutex ); num_ops_completed++; ldap_pvt_thread_mutex_unlock( &num_ops_mutex ); @@ -710,6 +714,7 @@ connection_operation( void *arg_v ) arg = NULL; switch( tag ) { + case LBER_ERROR: case LDAP_REQ_UNBIND: /* c_mutex is locked */ connection_closing( conn ); diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index a1c70d7b3d..1afb52038a 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -32,6 +32,7 @@ int get_ctrls( BerElement *ber = op->o_ber; LDAPControl ***ctrls = &op->o_ctrls; int rc = LDAP_SUCCESS; + char *errmsg = NULL; len = ber_pvt_ber_remaining(ber); @@ -43,14 +44,16 @@ int get_ctrls( if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { if( tag == LBER_ERROR ) { - rc = LDAP_PROTOCOL_ERROR; + rc = -1; + errmsg = "unexpected data in PDU"; } goto return_results; } if( op->o_protocol < LDAP_VERSION3 ) { - rc = LDAP_PROTOCOL_ERROR; + rc = -1; + errmsg = "controls require LDAPv3"; goto return_results; } @@ -61,6 +64,7 @@ int get_ctrls( #if 0 if( *ctrls == NULL ) { rc = LDAP_NO_MEMORY; + errmsg = "no memory"; goto return_results; } #endif @@ -94,6 +98,7 @@ int get_ctrls( *ctrls = NULL; rc = LDAP_NO_MEMORY; + errmsg = "no memory"; goto return_results; } #endif @@ -128,7 +133,8 @@ int get_ctrls( if( tag == LBER_ERROR ) { *ctrls = NULL; ldap_controls_free( tctrls ); - rc = LDAP_DECODING_ERROR; + rc = -1; + errmsg = "decoding controls error"; goto return_results; } @@ -136,6 +142,7 @@ int get_ctrls( !charray_inlist( supportedControls, tctrl->ldctl_oid ) ) { rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + errmsg = "critical extension is unavailable "; goto return_results; } @@ -144,7 +151,11 @@ int get_ctrls( return_results: if( sendres && rc != LDAP_SUCCESS ) { - send_ldap_result( conn, op, rc, NULL, NULL ); + if( rc == -1 ) { + send_ldap_disconnect( conn, op, rc, errmsg ); + } else { + send_ldap_result( conn, op, rc, NULL, errmsg ); + } } return rc; diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c index 87b3207601..4d0d7fb076 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -47,8 +47,9 @@ do_delete( if ( ber_scanf( op->o_ber, "a", &ndn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" ); - return rc; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } if( ( rc = get_ctrls( conn, op, 1 ) ) != LDAP_SUCCESS ) { diff --git a/servers/slapd/filter.c b/servers/slapd/filter.c index 7ea1850916..c1bed43cce 100644 --- a/servers/slapd/filter.c +++ b/servers/slapd/filter.c @@ -34,6 +34,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) * lessOrEqual [6] AttributeValueAssertion, * present [7] AttributeType,, * approxMatch [8] AttributeValueAssertion + * extensibleMatch [9] MatchingRuleAssertion * } * * SubstringFilter ::= SEQUENCE { @@ -44,19 +45,27 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) * final [2] IA5String * } * } + * + * MatchingRuleAssertion ::= SEQUENCE { + * matchingRule [1] MatchingRuleId OPTIONAL, + * type [2] AttributeDescription OPTIONAL, + * matchValue [3] AssertionValue, + * dnAttributes [4] BOOLEAN DEFAULT FALSE + * } + * */ f = (Filter *) ch_malloc( sizeof(Filter) ); f->f_next = NULL; - err = 0; + err = LDAP_SUCCESS; *fstr = NULL; f->f_choice = ber_peek_tag( ber, &len ); switch ( f->f_choice ) { case LDAP_FILTER_EQUALITY: Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 ); - if ( (err = get_ava( ber, &f->f_ava )) == 0 ) { + if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) { *fstr = ch_malloc(4 + strlen( f->f_avtype ) + f->f_avvalue.bv_len); sprintf( *fstr, "(%s=%s)", f->f_avtype, @@ -71,7 +80,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) case LDAP_FILTER_GE: Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 ); - if ( (err = get_ava( ber, &f->f_ava )) == 0 ) { + if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) { *fstr = ch_malloc(5 + strlen( f->f_avtype ) + f->f_avvalue.bv_len); sprintf( *fstr, "(%s>=%s)", f->f_avtype, @@ -81,7 +90,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) case LDAP_FILTER_LE: Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 ); - if ( (err = get_ava( ber, &f->f_ava )) == 0 ) { + if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) { *fstr = ch_malloc(5 + strlen( f->f_avtype ) + f->f_avvalue.bv_len); sprintf( *fstr, "(%s<=%s)", f->f_avtype, @@ -92,7 +101,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) case LDAP_FILTER_PRESENT: Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 ); if ( ber_scanf( ber, "a", &f->f_type ) == LBER_ERROR ) { - err = LDAP_PROTOCOL_ERROR; + err = -1; } else { err = LDAP_SUCCESS; attr_normalize( f->f_type ); @@ -103,7 +112,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) case LDAP_FILTER_APPROX: Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 ); - if ( (err = get_ava( ber, &f->f_ava )) == 0 ) { + if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) { *fstr = ch_malloc(5 + strlen( f->f_avtype ) + f->f_avvalue.bv_len); sprintf( *fstr, "(%s~=%s)", f->f_avtype, @@ -114,7 +123,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) case LDAP_FILTER_AND: Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 ); if ( (err = get_filter_list( conn, ber, &f->f_and, &ftmp )) - == 0 ) { + == LDAP_SUCCESS ) { if (ftmp == NULL) ftmp = ch_strdup(""); *fstr = ch_malloc( 4 + strlen( ftmp ) ); sprintf( *fstr, "(&%s)", ftmp ); @@ -125,7 +134,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) case LDAP_FILTER_OR: Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 ); if ( (err = get_filter_list( conn, ber, &f->f_or, &ftmp )) - == 0 ) { + == LDAP_SUCCESS ) { if (ftmp == NULL) ftmp = ch_strdup(""); *fstr = ch_malloc( 4 + strlen( ftmp ) ); sprintf( *fstr, "(|%s)", ftmp ); @@ -136,7 +145,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) case LDAP_FILTER_NOT: Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 ); (void) ber_skip_tag( ber, &len ); - if ( (err = get_filter( conn, ber, &f->f_not, &ftmp )) == 0 ) { + if ( (err = get_filter( conn, ber, &f->f_not, &ftmp )) == LDAP_SUCCESS ) { if (ftmp == NULL) ftmp = ch_strdup(""); *fstr = ch_malloc( 4 + strlen( ftmp ) ); sprintf( *fstr, "(!%s)", ftmp ); @@ -144,6 +153,12 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) } break; + case LBER_DEFAULT: + Debug( LDAP_DEBUG_ANY, "decoding filter error\n", + 0, 0, 0 ); + err = -1; + break; + default: Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n", f->f_choice, 0, 0 ); @@ -151,7 +166,7 @@ get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr ) break; } - if ( err != 0 ) { + if ( err != LDAP_SUCCESS ) { free( (char *) f ); if ( *fstr != NULL ) { free( *fstr ); @@ -178,8 +193,9 @@ get_filter_list( Connection *conn, BerElement *ber, Filter **f, char **fstr ) *fstr = NULL; new = f; for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; - tag = ber_next_element( ber, &len, last ) ) { - if ( (err = get_filter( conn, ber, new, &ftmp )) != 0 ) + tag = ber_next_element( ber, &len, last ) ) + { + if ( (err = get_filter( conn, ber, new, &ftmp )) != LDAP_SUCCESS ) return( err ); if ( *fstr == NULL ) { *fstr = ftmp; @@ -194,7 +210,7 @@ get_filter_list( Connection *conn, BerElement *ber, Filter **f, char **fstr ) *new = NULL; Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 ); - return( 0 ); + return( LDAP_SUCCESS ); } static int @@ -214,7 +230,7 @@ get_substring_filter( Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 ); if ( ber_scanf( ber, "{a" /*}*/, &f->f_sub_type ) == LBER_ERROR ) { - return( LDAP_PROTOCOL_ERROR ); + return( -1 ); } attr_normalize( f->f_sub_type ); syntax = attr_syntax( f->f_sub_type ); @@ -225,10 +241,11 @@ get_substring_filter( *fstr = ch_malloc( strlen( f->f_sub_type ) + 3 ); sprintf( *fstr, "(%s=", f->f_sub_type ); for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; - tag = ber_next_element( ber, &len, last ) ) { - rc = ber_scanf( ber, "a", &val ); + tag = ber_next_element( ber, &len, last ) ) + { + rc = ber_scanf( ber, "a", &val ); if ( rc == LBER_ERROR ) { - return( LDAP_PROTOCOL_ERROR ); + return( -1 ); } if ( val == NULL || *val == '\0' ) { if ( val != NULL ) { @@ -284,7 +301,7 @@ get_substring_filter( strcat( *fstr, ")" ); Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 ); - return( 0 ); + return( LDAP_SUCCESS ); } void diff --git a/servers/slapd/libslapd.dsp b/servers/slapd/libslapd.dsp index 6800343d72..898d368c6a 100644 --- a/servers/slapd/libslapd.dsp +++ b/servers/slapd/libslapd.dsp @@ -200,6 +200,10 @@ SOURCE=.\entry.c # End Source File # Begin Source File +SOURCE=.\extended.c +# End Source File +# Begin Source File + SOURCE=.\filter.c # End Source File # Begin Source File diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index 6be8038bdf..ccae24d41f 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -71,8 +71,9 @@ do_modify( if ( ber_scanf( op->o_ber, "{a" /*}*/, &ndn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" ); - return rc; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", ndn, 0, 0 ); @@ -95,13 +96,13 @@ do_modify( &(*modtail)->ml_type, &(*modtail)->ml_bvalues ) == LBER_ERROR ) { - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "decoding error" ); + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding modlist error" ); free( ndn ); free( *modtail ); *modtail = NULL; modlist_free( modlist ); - return rc; + return -1; } (*modtail)->ml_op = mop; @@ -110,21 +111,21 @@ do_modify( (*modtail)->ml_op != LDAP_MOD_DELETE && (*modtail)->ml_op != LDAP_MOD_REPLACE ) { - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "unrecognized modify operation" ); + send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, + NULL, "unrecognized modify operation" ); free( ndn ); modlist_free( modlist ); - return rc; + return LDAP_PROTOCOL_ERROR; } if ( (*modtail)->ml_bvalues == NULL && (*modtail)->ml_op != LDAP_MOD_DELETE ) { - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "no values given" ); + send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, + NULL, "unrecognized modify operation" ); free( ndn ); modlist_free( modlist ); - return rc; + return LDAP_PROTOCOL_ERROR; } attr_normalize( (*modtail)->ml_type ); diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index d3f04f8ff5..c80a605fbd 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -72,8 +72,9 @@ do_modrdn( if ( ber_scanf( op->o_ber, "{aab", &ndn, &newrdn, &deloldrdn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" ); - return rc; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } /* Check for newSuperior parameter, if present scan it */ @@ -96,9 +97,9 @@ do_modrdn( Debug( LDAP_DEBUG_ANY, "modrdn(v2): invalid field newSuperior!\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, - NULL, "" ); - return rc; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" ); + return -1; } if ( ber_scanf( op->o_ber, "a", &newSuperior ) @@ -106,9 +107,9 @@ do_modrdn( Debug( LDAP_DEBUG_ANY, "ber_scanf(\"a\"}) failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "" ); - return rc; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } @@ -124,12 +125,11 @@ do_modrdn( free( newrdn ); free( newSuperior ); Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "decoding error" ); - return rc; + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return -1; } -#ifdef GET_CTRLS if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) { free( ndn ); free( newrdn ); @@ -137,7 +137,6 @@ do_modrdn( Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 ); return rc; } -#endif if( newSuperior != NULL ) { /* GET BACKEND FOR NEW SUPERIOR */ diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c index 9dcf13d9e9..a5a5274f12 100644 --- a/servers/slapd/monitor.c +++ b/servers/slapd/monitor.c @@ -21,10 +21,6 @@ #include "ldap_defaults.h" #include "slap.h" -char *supportedExtensions[] = { - NULL -}; - #if defined( SLAPD_MONITOR_DN ) void @@ -232,7 +228,7 @@ monitor_info( Connection *conn, Operation *op ) attr_merge( e, "concurrency", vals ); #endif - send_search_entry( &backends[0], conn, op, e, NULL, 0 ); + send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 ); send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 ); entry_free( e ); diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index d8c33673a6..23cd1297bd 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -257,17 +257,26 @@ void replog LDAP_P(( Backend *be, int optype, char *dn, void *change, int flag ) * result.c */ -void send_ldap_result LDAP_P(( Connection *conn, Operation *op, int err, char *matched, - char *text )); -void send_ldap_search_result LDAP_P(( Connection *conn, Operation *op, int err, - char *matched, char *text, int nentries )); +void send_ldap_result LDAP_P(( + Connection *conn, Operation *op, + int err, char *matched, char *text )); + +void send_ldap_disconnect LDAP_P(( + Connection *conn, Operation *op, + int err, char *text )); + +void send_ldap_search_result LDAP_P(( + Connection *conn, Operation *op, + int err, char *matched, char *text, int nentries )); /* * schema.c */ int oc_schema_check LDAP_P(( Entry *e )); -int oc_check_operational LDAP_P(( char *type )); +int oc_check_operational_attr LDAP_P(( char *type )); +int oc_check_usermod_attr LDAP_P(( char *type )); +int oc_check_no_usermod_attr LDAP_P(( char *type )); ObjectClass *oc_find LDAP_P((const char *ocname)); int oc_add LDAP_P((LDAP_OBJECT_CLASS *oc, const char **err)); Syntax *syn_find LDAP_P((const char *synname)); @@ -401,9 +410,12 @@ extern int do_modify LDAP_P((Connection *conn, Operation *op)); extern int do_modrdn LDAP_P((Connection *conn, Operation *op)); extern int do_search LDAP_P((Connection *conn, Operation *op)); extern int do_unbind LDAP_P((Connection *conn, Operation *op)); -extern int do_exop LDAP_P((Connection *conn, Operation *op)); +extern int do_extended LDAP_P((Connection *conn, Operation *op)); + +extern int send_search_entry LDAP_P(( + Backend *be, Connection *conn, Operation *op, + Entry *e, char **attrs, int attrsonly, int opattrs )); -extern int send_search_entry LDAP_P((Backend *be, Connection *conn, Operation *op, Entry *e, char **attrs, int attrsonly)); extern int str2result LDAP_P(( char *s, int *code, char **matched, char **info )); extern ber_socket_t dtblsize; diff --git a/servers/slapd/result.c b/servers/slapd/result.c index e9c05de439..4fbe02e21c 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -20,6 +20,7 @@ static void send_ldap_result2( Connection *conn, Operation *op, + int disconnect, ber_int_t err, char *matched, char *text, @@ -30,32 +31,50 @@ send_ldap_result2( int rc; ber_tag_t tag; ber_len_t bytes; + int msgid; assert( !LDAP_API_ERROR( err ) ); if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') ) err = LDAP_NO_SUCH_OBJECT; - Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n", err, - matched ? matched : "", - text ? text : "" ); + if( disconnect ) { + msgid = 0; /* unsolicited */ + if ( op->o_protocol > LDAP_VERSION3 ) { + tag = LDAP_RES_EXTENDED; + } + +#define LDAP_UNSOLICITED_ERROR(e) \ + ( (e) == LDAP_PROTOCOL_ERROR \ + || (e) == LDAP_STRONG_AUTH_REQUIRED \ + || (e) == LDAP_UNAVAILABLE ) + + assert( LDAP_UNSOLICITED_ERROR( err ) ); - switch ( op->o_tag ) { - case LBER_DEFAULT: - tag = LBER_SEQUENCE; - break; + } else { + msgid = op->o_msgid; + + switch ( op->o_tag ) { + case LDAP_REQ_ABANDON: + case LDAP_REQ_UNBIND: + case LBER_ERROR: + tag = LBER_SEQUENCE; + msgid = 0; + assert( LDAP_UNSOLICITED_ERROR( err ) ); + break; - case LDAP_REQ_SEARCH: - tag = LDAP_RES_SEARCH_RESULT; - break; + case LDAP_REQ_SEARCH: + tag = LDAP_RES_SEARCH_RESULT; + break; - case LDAP_REQ_DELETE: - tag = LDAP_RES_DELETE; - break; + case LDAP_REQ_DELETE: + tag = LDAP_RES_DELETE; + break; - default: - tag = op->o_tag + 1; - break; + default: + tag = op->o_tag + 1; + break; + } } @@ -68,13 +87,20 @@ send_ldap_result2( #ifdef LDAP_CONNECTIONLESS if ( op->o_cldap ) { - rc = ber_printf( ber, "{is{t{ess}}}", op->o_msgid, "", tag, + rc = ber_printf( ber, "{is{t{ess}}}", msgid, "", tag, err, matched ? matched : "", text ? text : "" ); } else #endif - { - rc = ber_printf( ber, "{it{ess}}", op->o_msgid, tag, err, - matched ? matched : "", text ? text : "" ); + if( tag == LDAP_RES_EXTENDED ) { + rc = ber_printf( ber, "{it{esss}}", + msgid, tag, err, + "", text ? text : "", + LDAP_NOTICE_DISCONNECT ); + + } else { + rc = ber_printf( ber, "{it{ess}}", + msgid, tag, err, + matched ? matched : "", text ? text : "" ); } if ( rc == -1 ) { @@ -158,6 +184,9 @@ send_ldap_result( { assert( !LDAP_API_ERROR( err ) ); + Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n", + err, matched ? matched : "", text ? text : "" ); + #ifdef LDAP_CONNECTIONLESS if ( op->o_cldap ) { ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr ); @@ -168,7 +197,34 @@ send_ldap_result( 0 ); } #endif - send_ldap_result2( conn, op, err, matched, text, 0 ); + send_ldap_result2( conn, op, 0, err, matched, text, 0 ); +} + +void +send_ldap_disconnect( + Connection *conn, + Operation *op, + ber_int_t err, + char *text +) +{ + assert( !LDAP_API_ERROR( err ) ); + + Debug( LDAP_DEBUG_TRACE, + "send_ldap_disconnect %d:%s\n", + err, text ? text : "", NULL ); + +#ifdef LDAP_CONNECTIONLESS + if ( op->o_cldap ) { + ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr ); + Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n", + inet_ntoa(((struct sockaddr_in *) + &op->o_clientaddr)->sin_addr ), + ((struct sockaddr_in *) &op->o_clientaddr)->sin_port, + 0 ); + } +#endif + send_ldap_result2( conn, op, 0, err, NULL, text, 0 ); } void @@ -181,7 +237,10 @@ send_ldap_search_result( int nentries ) { - send_ldap_result2( conn, op, err, matched, text, nentries ); + Debug( LDAP_DEBUG_TRACE, "send_ldap_search_result %d:%s:%s\n", + err, matched ? matched : "", text ? text : "" ); + + send_ldap_result2( conn, op, 0, err, matched, text, nentries ); } int @@ -191,7 +250,8 @@ send_search_entry( Operation *op, Entry *e, char **attrs, - int attrsonly + int attrsonly, + int opattrs ) { BerElement *ber; @@ -202,6 +262,17 @@ send_search_entry( Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 ); +#if defined( SLAPD_SCHEMA_DN ) + { + /* this could be backend specific */ + struct berval val; + val.bv_val = SLAPD_SCHEMA_DN; + val.bv_len = strlen( val.bv_val ); + attr_merge( e, "subschemaSubentry", vals ); + ldap_memfree( val.bv_val ); + } +#endif + if ( ! access_allowed( be, conn, op, e, "entry", NULL, ACL_READ ) ) { @@ -237,12 +308,15 @@ send_search_entry( if ( attrs == NULL ) { /* all addrs request, skip operational attributes */ - if( oc_check_operational( a->a_type )) { + if( !opattrs && oc_check_operational_attr( a->a_type )) { continue; } + } else { /* specific addrs requested */ - if ( !charray_inlist( attrs, a->a_type )) { + if ( !charray_inlist( attrs, a->a_type ) + && !charray_inlist( attrs, LDAP_ALL_USER_ATTRIBUTES ) ) + { continue; } } diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c index f609e71142..540d218d13 100644 --- a/servers/slapd/root_dse.c +++ b/servers/slapd/root_dse.c @@ -19,8 +19,8 @@ void root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) { + char buf[BUFSIZ]; Entry *e; - char buf[BUFSIZ]; struct berval val; struct berval *vals[2]; int i, j; @@ -37,51 +37,44 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) for ( i = 0; i < nbackends; i++ ) { for ( j = 0; backends[i].be_suffix[j] != NULL; j++ ) { - strcpy( buf, backends[i].be_suffix[j] ); - val.bv_val = buf; - val.bv_len = strlen( buf ); + val.bv_val = backends[i].be_suffix[j]; + val.bv_len = strlen( val.bv_val ); attr_merge( e, "namingContexts", vals ); } } #if defined( SLAPD_MONITOR_DN ) - strcpy( buf, SLAPD_MONITOR_DN ); - val.bv_val = buf; - val.bv_len = strlen( buf ); + val.bv_val = SLAPD_MONITOR_DN; + val.bv_len = strlen( val.bv_val ); attr_merge( e, "namingContexts", vals ); + /* subschemasubentry is added by send_search_entry() */ #endif #if defined( SLAPD_CONFIG_DN ) - strcpy( buf, SLAPD_CONFIG_DN ); - val.bv_val = buf; - val.bv_len = strlen( buf ); + val.bv_val = SLAPD_CONFIG_DN; + val.bv_len = strlen( val.bv_val ); attr_merge( e, "namingContexts", vals ); #endif #if defined( SLAPD_SCHEMA_DN ) - strcpy( buf, SLAPD_SCHEMA_DN ); - val.bv_val = buf; + val.bv_val = SLAPD_SCHEMA_DN; val.bv_len = strlen( val.bv_val ); attr_merge( e, "namingContexts", vals ); - attr_merge( e, "subschemaSubentry", vals ); - ldap_memfree( val.bv_val ); #endif /* altServer unsupported */ /* supportedControl */ for ( i=0; supportedControls[i] != NULL; i++ ) { - strcpy( buf, supportedControls[i] ); - val.bv_val = buf; - val.bv_len = strlen( buf ); + val.bv_val = supportedControls[i]; + val.bv_len = strlen( val.bv_val ); attr_merge( e, "supportedControl", vals ); } /* supportedExtension */ for ( i=0; supportedExtensions[i] != NULL; i++ ) { - strcpy( buf, supportedExtensions[i] ); - val.bv_val = buf; - val.bv_len = strlen( buf ); + val.bv_val = supportedExtensions[i]; + val.bv_len = strlen( val.bv_val ); attr_merge( e, "supportedExtension", vals ); } @@ -89,20 +82,19 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) for ( i=LDAP_VERSION_MIN; i<=LDAP_VERSION_MAX; i++ ) { sprintf(buf,"%d",i); val.bv_val = buf; - val.bv_len = strlen( buf ); + val.bv_len = strlen( val.bv_val ); attr_merge( e, "supportedLDAPVersion", vals ); } /* supportedSASLMechanism */ for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) { - strcpy( buf, supportedSASLMechanisms[i] ); - val.bv_val = buf; - val.bv_len = strlen( buf ); + val.bv_val = supportedSASLMechanisms[i]; + val.bv_len = strlen( val.bv_val ); attr_merge( e, "supportedSASLMechanism", vals ); } - send_search_entry( &backends[0], conn, op, e, attrs, attrsonly ); + send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 1 ); send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 ); entry_free( e ); diff --git a/servers/slapd/schema.c b/servers/slapd/schema.c index 746833f796..e71913e0e6 100644 --- a/servers/slapd/schema.c +++ b/servers/slapd/schema.c @@ -123,20 +123,78 @@ oc_check_required( Entry *e, char *ocname ) return( NULL ); } +static char *oc_usermod_attrs[] = { + /* + * OpenLDAP doesn't support any user modification of + * operational attributes. + */ + NULL +}; + +static char *oc_operational_attrs[] = { + /* + * these are operational attributes that *could* be + * modified by users if we supported such. + */ + "objectClasses", + "attributeTypes", + "matchingRules", + "matchingRuleUse", + "dITStructureRules", + "dITContentRules", + "nameForms", + "ldapSyntaxes", + NULL + +}; + +/* this list should be extensible */ +static char *oc_no_usermod_attrs[] = { + /* + * Operational and 'no user modification' attributes + */ + + /* RFC2252, 3.2.1 */ + "creatorsName", + "createTimestamp", + "modifiersName", + "modifyTimestamp", + "subschemaSubentry", + + NULL +}; + + /* * check to see if attribute is 'operational' or not. - * this list should be extensible... */ int -oc_check_operational( char *type ) +oc_check_operational_attr( char *type ) { - return ( strcasecmp( type, "modifiersname" ) == 0 || - strcasecmp( type, "modifytimestamp" ) == 0 || - strcasecmp( type, "creatorsname" ) == 0 || - strcasecmp( type, "createtimestamp" ) == 0 ) - ? 1 : 0; + return charray_inlist( oc_operational_attrs, type ) + || charray_inlist( oc_usermod_attrs, type ) + || charray_inlist( oc_no_usermod_attrs, type ); } +/* + * check to see if attribute can be user modified or not. + */ +int +oc_check_usermod_attr( char *type ) +{ + return charray_inlist( oc_usermod_attrs, type ); +} + +/* + * check to see if attribute is 'no user modification' or not. + */ +int +oc_check_no_usermod_attr( char *type ) +{ + return charray_inlist( oc_no_usermod_attrs, type ); +} + + static int oc_check_allowed( char *type, struct berval **ocl ) { @@ -153,7 +211,12 @@ oc_check_allowed( char *type, struct berval **ocl ) return( 0 ); } - if ( oc_check_operational( type ) ) { + /* + * All operational attributions are allowed by schema rules. + * However, we only check attributions which are stored in the + * the directory regardless if they are user or non-user modified. + */ + if ( oc_check_usermod_attr( type ) || oc_check_no_usermod_attr( type ) ) { return( 0 ); } @@ -1080,7 +1143,7 @@ schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) return; } - send_search_entry( &backends[0], conn, op, e, attrs, attrsonly ); + send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 0 ); send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 ); entry_free( e ); diff --git a/servers/slapd/search.c b/servers/slapd/search.c index fece855dc7..38f44be01c 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -74,14 +74,17 @@ do_search( if ( ber_scanf( op->o_ber, "{aiiiib", &base, &scope, &deref, &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ) { - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" ); + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + rc = -1; goto return_results; } if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL && scope != LDAP_SCOPE_SUBTREE ) { - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, - "Unknown search scope" ); + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + rc = -1; goto return_results; } @@ -93,14 +96,22 @@ do_search( /* filter - returns a "normalized" version */ if ( (err = get_filter( conn, op->o_ber, &filter, &fstr )) != 0 ) { - send_ldap_result( conn, op, err, NULL, "Bad search filter" ); + if( err == -1 ) { + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decode error" ); + } else { + send_ldap_result( conn, op, err, NULL, "Bad search filter" ); + } goto return_results; } + Debug( LDAP_DEBUG_ARGS, " filter: %s\n", fstr, 0, 0 ); /* attributes */ if ( ber_scanf( op->o_ber, /*{*/ "{v}}", &attrs ) == LBER_ERROR ) { - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" ); + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + rc = -1; goto return_results; } diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index d84e8e5bd5..be5a177ab7 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -55,7 +55,8 @@ send_search_entry( Operation *op, Entry *e, char **attrs, - int attrsonly + int attrsonly, + int opattrs ) { assert(0); -- 2.39.5