From 3ca2a91ae1c57e3b992cd50fc283ee850ea0d4e3 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Tue, 10 Jun 2003 02:19:30 +0000 Subject: [PATCH] Assertion control with no backend support (yet) --- clients/tools/common.c | 48 ++++++++++++++++++- include/ldap.h | 1 + servers/slapd/controls.c | 101 +++++++++++++++++++++++++++++++-------- servers/slapd/slap.h | 8 +++- 4 files changed, 134 insertions(+), 24 deletions(-) diff --git a/clients/tools/common.c b/clients/tools/common.c index b558b2942b..f6cac8bd1c 100644 --- a/clients/tools/common.c +++ b/clients/tools/common.c @@ -41,6 +41,7 @@ char *sasl_secprops = NULL; #endif int use_tls = 0; +char *assertion = NULL; char *authzid = NULL; int manageDSAit = 0; int noop = 0; @@ -74,6 +75,7 @@ N_(" -C chase referrals\n"), N_(" -d level set LDAP debugging level to `level'\n"), N_(" -D binddn bind DN\n"), N_(" -e [!][=] general controls (! indicates criticality)\n") +N_(" [!]assert= (an RFC 2254 Filter)\n") N_(" [!]authzid= (\"dn:\" or \"u:\")\n") N_(" [!]manageDSAit (alternate form, see -M)\n") N_(" [!]noop\n"), @@ -155,7 +157,20 @@ tool_args( int argc, char **argv ) *cvalue++ = '\0'; } - if ( strcasecmp( control, "authzid" ) == 0 ) { + if ( strcasecmp( control, "assert" ) == 0 ) { + if( assertion != NULL ) { + fprintf( stderr, "assert control previously specified\n"); + exit( EXIT_FAILURE ); + } + if( cvalue == NULL ) { + fprintf( stderr, "assert: control value expected\n" ); + usage(); + } + + assert( assertion == NULL ); + assertion = cvalue; + + } else if ( strcasecmp( control, "authzid" ) == 0 ) { if( authzid != NULL ) { fprintf( stderr, "authzid control previously specified\n"); exit( EXIT_FAILURE ); @@ -710,7 +725,7 @@ void tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) { int i = 0, j, crit = 0, err; - LDAPControl c[3], **ctrls; + LDAPControl c[4], **ctrls; ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*)); if ( ctrls == NULL ) { @@ -718,6 +733,35 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) exit( EXIT_FAILURE ); } + if ( assertion ) { + char berbuf[LBER_ELEMENT_SIZEOF]; + BerElement *ber = (BerElement *)berbuf; + + if( *assertion == '\0' ) { + fprintf( stderr, "Assertion=\n" ); + exit( EXIT_FAILURE ); + } + + ber_init2( ber, NULL, LBER_USE_DER ); + + err = ldap_pvt_put_filter( ber, assertion ); + if( err < 0 ) { + fprintf( stderr, "assertion encode failed (%d)\n", err ); + exit( EXIT_FAILURE ); + } + + err = ber_flatten2( ber, &c[i].ldctl_value, 0 ); + if( err < 0 ) { + fprintf( stderr, "assertion flatten failed (%d)\n", err ); + exit( EXIT_FAILURE ); + } + + c[i].ldctl_oid = LDAP_CONTROL_ASSERT; + c[i].ldctl_iscritical = 1; + ctrls[i] = &c[i]; + i++; + } + if ( authzid ) { c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; c[i].ldctl_value.bv_val = authzid; diff --git a/include/ldap.h b/include/ldap.h index e28755214c..a6acd33c81 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -180,6 +180,7 @@ typedef struct ldapcontrol { } LDAPControl; /* LDAP Controls */ +#define LDAP_CONTROL_ASSERT "1.3.6.1.4.1.4203.666.5.9" #define LDAP_CONTROL_VALUESRETURNFILTER "1.2.826.0.1.334810.2.3" #define LDAP_CONTROL_SUBENTRIES "1.3.6.1.4.1.4203.1.10.1" #define LDAP_CONTROL_NOOP "1.3.6.1.4.1.4203.1.10.2" diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index c5eacd2029..fcb2640a0f 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -19,6 +19,7 @@ #include "../../libraries/liblber/lber-int.h" +static SLAP_CTRL_PARSE_FN parseAssert; static SLAP_CTRL_PARSE_FN parseProxyAuthz; static SLAP_CTRL_PARSE_FN parseManageDSAit; static SLAP_CTRL_PARSE_FN parseNoOp; @@ -39,31 +40,17 @@ static SLAP_CTRL_PARSE_FN parseLdupSync; #undef sc_mask /* avoid conflict with Irix 6.5 */ -static char *proxy_authz_extops[] = { - LDAP_EXOP_MODIFY_PASSWD, - LDAP_EXOP_X_WHO_AM_I, - NULL -}; - struct slap_control { - /* - * Control OID - */ + /* Control OID */ char *sc_oid; - /* - * Operations supported by control - */ + /* Operations supported by control */ slap_mask_t sc_mask; - /* - * Extended operations supported by control - */ + /* Extended operations supported by control */ char **sc_extendedops; - /* - * Control parsing callback - */ + /* Control parsing callback */ SLAP_CTRL_PARSE_FN *sc_parse; LDAP_SLIST_ENTRY(slap_control) sc_next; @@ -77,7 +64,16 @@ static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list */ char **slap_known_controls = NULL; +static char *proxy_authz_extops[] = { + LDAP_EXOP_MODIFY_PASSWD, + LDAP_EXOP_X_WHO_AM_I, + NULL +}; + static struct slap_control control_defs[] = { + { LDAP_CONTROL_ASSERT, + SLAP_CTRL_ACCESS, NULL, + parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) }, { LDAP_CONTROL_VALUESRETURNFILTER, SLAP_CTRL_SEARCH, NULL, parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) }, @@ -872,6 +868,69 @@ static int parsePagedResults ( } #endif +static int parseAssert ( + Operation *op, + SlapReply *rs, + LDAPControl *ctrl ) +{ + BerElement *ber; + struct berval fstr = { 0, NULL }; + const char *err_msg = ""; + + if ( op->o_assert != SLAP_NO_CONTROL ) { + rs->sr_text = "assert control specified multiple times"; + return LDAP_PROTOCOL_ERROR; + } + + if ( ctrl->ldctl_value.bv_len == 0 ) { + rs->sr_text = "assert control value is empty (or absent)"; + return LDAP_PROTOCOL_ERROR; + } + + ber = ber_init( &(ctrl->ldctl_value) ); + if (ber == NULL) { + rs->sr_text = "internal error"; + return LDAP_OTHER; + } + + rs->sr_err = get_filter( op, ber, &(op->o_assertion), &rs->sr_text); + + if( rs->sr_err != LDAP_SUCCESS ) { + if( rs->sr_err == SLAPD_DISCONNECT ) { + rs->sr_err = LDAP_PROTOCOL_ERROR; + send_ldap_disconnect( op, rs ); + rs->sr_err = SLAPD_DISCONNECT; + } else { + send_ldap_result( op, rs ); + } + if( op->o_assertion != NULL) { + filter_free_x( op, op->o_assertion ); + } + } +#ifdef LDAP_DEBUG + else { + filter2bv_x( op, op->o_assertion, &fstr ); + } + +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ARGS, + "parseAssert: conn %d assert: %s\n", + op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 ); +#else + Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %d assert: %s\n", + op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 ); +#endif + op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx ); +#endif + + op->o_assert = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; + + rs->sr_err = LDAP_SUCCESS; + return LDAP_SUCCESS; +} + int parseValuesReturnFilter ( Operation *op, SlapReply *rs, @@ -897,7 +956,7 @@ int parseValuesReturnFilter ( return LDAP_OTHER; } - rs->sr_err = get_vrFilter( op, ber, &(op->vrFilter), &rs->sr_text); + rs->sr_err = get_vrFilter( op, ber, &(op->o_vrFilter), &rs->sr_text); if( rs->sr_err != LDAP_SUCCESS ) { if( rs->sr_err == SLAPD_DISCONNECT ) { @@ -907,12 +966,12 @@ int parseValuesReturnFilter ( } else { send_ldap_result( op, rs ); } - if( op->vrFilter != NULL) vrFilter_free( op, op->vrFilter ); + if( op->o_vrFilter != NULL) vrFilter_free( op, op->o_vrFilter ); } #ifdef LDAP_DEBUG else { - vrFilter2bv( op, op->vrFilter, &fstr ); + vrFilter2bv( op, op->o_vrFilter, &fstr ); } #ifdef NEW_LOGGING diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 1de6599454..e931a7d800 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1915,6 +1915,9 @@ typedef struct slap_op { char o_subentries_visibility; #define get_subentries_visibility(op) ((int)(op)->o_subentries_visibility) + char o_assert; +#define get_assert(op) ((int)(op)->o_assert) + char o_valuesreturnfilter; #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY @@ -1987,7 +1990,10 @@ typedef struct slap_op { void *o_private; /* anything the backend needs */ LDAP_STAILQ_ENTRY(slap_op) o_next; /* next operation in list */ - ValuesReturnFilter *vrFilter; /* Structure represents ValuesReturnFilter */ + + Filter *o_assertion; /* Assert control filter */ +#define get_assertion(op) ((op)->o_assertion) + ValuesReturnFilter *o_vrFilter; /* ValuesReturnFilter */ #ifdef LDAP_CACHING char o_caching_on; -- 2.39.5