From 9a00bbb35fd40d6181ef0b4bb1440bfd183cd6f5 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Wed, 22 Aug 2007 15:49:35 +0000 Subject: [PATCH] add support for session tracking (draft-wahl-ldap-sessio) to proxy backends requests --- doc/man/man5/slapd-ldap.5 | 7 + doc/man/man5/slapd-meta.5 | 9 ++ servers/slapd/back-ldap/add.c | 7 +- servers/slapd/back-ldap/back-ldap.h | 10 ++ servers/slapd/back-ldap/bind.c | 215 +++++++++++++++++++-------- servers/slapd/back-ldap/compare.c | 7 +- servers/slapd/back-ldap/config.c | 60 ++++++-- servers/slapd/back-ldap/delete.c | 7 +- servers/slapd/back-ldap/extended.c | 13 +- servers/slapd/back-ldap/modify.c | 7 +- servers/slapd/back-ldap/modrdn.c | 7 +- servers/slapd/back-ldap/proto-ldap.h | 21 +++ servers/slapd/back-ldap/search.c | 12 +- servers/slapd/back-meta/add.c | 7 +- servers/slapd/back-meta/back-meta.h | 5 + servers/slapd/back-meta/bind.c | 139 ++++++++++++++++- servers/slapd/back-meta/compare.c | 7 +- servers/slapd/back-meta/config.c | 30 ++++ servers/slapd/back-meta/delete.c | 7 +- servers/slapd/back-meta/modify.c | 7 +- servers/slapd/back-meta/modrdn.c | 7 +- servers/slapd/back-meta/search.c | 7 +- servers/slapd/controls.c | 85 ++++++++++- servers/slapd/daemon.c | 6 +- servers/slapd/proto-slap.h | 14 ++ servers/slapd/slap.h | 7 + 26 files changed, 563 insertions(+), 147 deletions(-) diff --git a/doc/man/man5/slapd-ldap.5 b/doc/man/man5/slapd-ldap.5 index 847ea6d657..ee9fbffdd4 100644 --- a/doc/man/man5/slapd-ldap.5 +++ b/doc/man/man5/slapd-ldap.5 @@ -429,6 +429,13 @@ or when chasing a referral, if is set to .IR yes . +.TP +.B session\-tracking\-request {NO|yes} +Adds session tracking control for all requests. +The client's IP and hostname, and the identity associated to each request, +if known, are sent to the remote server for informational purposes. +This directive is incompatible with setting \fIprotocol\-version\fP to 2. + .TP .B single\-conn {NO|yes} Discards current cached connection when the client rebinds. diff --git a/doc/man/man5/slapd-meta.5 b/doc/man/man5/slapd-meta.5 index 5816c0f753..e2c5bbe0e2 100644 --- a/doc/man/man5/slapd-meta.5 +++ b/doc/man/man5/slapd-meta.5 @@ -172,6 +172,15 @@ or when chasing a referral, if is set to .IR yes . +.TP +.B session\-tracking\-request {NO|yes} +Adds session tracking control for all requests. +The client's IP and hostname, and the identity associated to each request, +if known, are sent to the remote server for informational purposes. +This directive is incompatible with setting \fIprotocol\-version\fP to 2. +If set before any target specification, it affects all targets, unless +overridden by any per-target directive. + .TP .B single\-conn {NO|yes} Discards current cached connection when the client rebinds. diff --git a/servers/slapd/back-ldap/add.c b/servers/slapd/back-ldap/add.c index 9a5c4f5422..8398162ee4 100644 --- a/servers/slapd/back-ldap/add.c +++ b/servers/slapd/back-ldap/add.c @@ -93,8 +93,7 @@ ldap_back_add( retry: ctrls = op->o_ctrls; - rs->sr_err = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &ctrls ); + rs->sr_err = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -109,13 +108,13 @@ retry: retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup: - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( attrs ) { for ( --i; i >= 0; --i ) { diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 442869861d..374a959c74 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -310,6 +310,11 @@ typedef struct ldapinfo_t { #define LDAP_BACK_F_QUARANTINE (0x00010000U) +#ifdef SLAP_CONTROL_X_SESSION_TRACKING +#define LDAP_BACK_F_ST_REQUEST (0x00020000U) +#define LDAP_BACK_F_ST_RESPONSE (0x00040000U) +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + #define LDAP_BACK_ISSET_F(ff,f) ( ( (ff) & (f) ) == (f) ) #define LDAP_BACK_ISMASK_F(ff,m,f) ( ( (ff) & (m) ) == (f) ) @@ -343,6 +348,11 @@ typedef struct ldapinfo_t { #define LDAP_BACK_QUARANTINE(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_QUARANTINE ) +#ifdef SLAP_CONTROL_X_SESSION_TRACKING +#define LDAP_BACK_ST_REQUEST(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_ST_REQUEST) +#define LDAP_BACK_ST_RESPONSE(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_ST_RESPONSE) +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + int li_version; /* cached connections; diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index fd5e39b217..d27d958fd6 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -173,7 +173,10 @@ ldap_back_bind( Operation *op, SlapReply *rs ) ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc; - int rc = 0; + LDAPControl **ctrls = NULL; + struct berval save_o_dn; + int save_o_do_not_cache, + rc = 0; ber_int_t msgid; ldap_back_send_t retrying = LDAP_BACK_RETRYING; @@ -205,11 +208,27 @@ ldap_back_bind( Operation *op, SlapReply *rs ) } LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); + /* don't add proxyAuthz; set the bindDN */ + save_o_dn = op->o_dn; + save_o_do_not_cache = op->o_do_not_cache; + op->o_dn = op->o_req_dn; + op->o_do_not_cache = 1; + + ctrls = op->o_ctrls; + rc = ldap_back_controls_add( op, rs, lc, &ctrls ); + op->o_dn = save_o_dn; + op->o_do_not_cache = save_o_do_not_cache; + if ( rc != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + ldap_back_release_conn( li, lc ); + return( rc ); + } + retry:; /* method is always LDAP_AUTH_SIMPLE if we got here */ rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val, LDAP_SASL_SIMPLE, - &op->orb_cred, op->o_ctrls, NULL, &msgid ); + &op->orb_cred, ctrls, NULL, &msgid ); /* FIXME: should we always retry, or only when piping the bind * in the "override" connection pool? */ rc = ldap_back_op_result( lc, op, rs, msgid, @@ -222,6 +241,8 @@ retry:; } } + ldap_back_controls_free( op, rs, &ctrls ); + if ( rc == LDAP_SUCCESS ) { /* If defined, proxyAuthz will be used also when * back-ldap is the authorizing backend; for this @@ -2210,38 +2231,19 @@ done:; */ int ldap_back_proxy_authz_ctrl( + Operation *op, + SlapReply *rs, struct berval *bound_ndn, int version, slap_idassert_t *si, - Operation *op, - SlapReply *rs, - LDAPControl ***pctrls ) + LDAPControl *ctrl ) { - LDAPControl **ctrls = NULL; - int i = 0; slap_idassert_mode_t mode; struct berval assertedID, ndn; int isroot = 0; - *pctrls = NULL; - - rs->sr_err = LDAP_SUCCESS; - - /* don't proxyAuthz if protocol is not LDAPv3 */ - switch ( version ) { - case LDAP_VERSION3: - break; - - case 0: - if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { - break; - } - /* fall thru */ - - default: - goto done; - } + rs->sr_err = SLAP_CB_CONTINUE; /* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID, * but if it is not set this test fails. We need a different @@ -2391,32 +2393,20 @@ ldap_back_proxy_authz_ctrl( goto done; } - if ( op->o_ctrls ) { - for ( i = 0; op->o_ctrls[ i ]; i++ ) - /* just count ctrls */ ; - } - - ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + 2) + sizeof( LDAPControl ), - op->o_tmpmemctx ); - ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + 2 ]; - - ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; - ctrls[ 0 ]->ldctl_iscritical = 1; - switch ( si->si_mode ) { /* already in u:ID or dn:DN form */ case LDAP_BACK_IDASSERT_OTHERID: case LDAP_BACK_IDASSERT_OTHERDN: - ber_dupbv_x( &ctrls[ 0 ]->ldctl_value, &assertedID, op->o_tmpmemctx ); + ber_dupbv_x( &ctrl->ldctl_value, &assertedID, op->o_tmpmemctx ); break; /* needs the dn: prefix */ default: - ctrls[ 0 ]->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" ); - ctrls[ 0 ]->ldctl_value.bv_val = op->o_tmpalloc( ctrls[ 0 ]->ldctl_value.bv_len + 1, + ctrl->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" ); + ctrl->ldctl_value.bv_val = op->o_tmpalloc( ctrl->ldctl_value.bv_len + 1, op->o_tmpmemctx ); - AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) ); - AC_MEMCPY( &ctrls[ 0 ]->ldctl_value.bv_val[ STRLENOF( "dn:" ) ], + AC_MEMCPY( ctrl->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) ); + AC_MEMCPY( &ctrl->ldctl_value.bv_val[ STRLENOF( "dn:" ) ], assertedID.bv_val, assertedID.bv_len + 1 ); break; } @@ -2426,7 +2416,7 @@ ldap_back_proxy_authz_ctrl( * this hack provides compatibility with those DSAs that * implement it this way */ if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { - struct berval authzID = ctrls[ 0 ]->ldctl_value; + struct berval authzID = ctrl->ldctl_value; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; @@ -2440,7 +2430,7 @@ ldap_back_proxy_authz_ctrl( goto free_ber; } - if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) { + if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) { rs->sr_err = LDAP_OTHER; goto free_ber; } @@ -2450,22 +2440,17 @@ free_ber:; ber_free_buf( ber ); if ( rs->sr_err != LDAP_SUCCESS ) { - op->o_tmpfree( ctrls, op->o_tmpmemctx ); - ctrls = NULL; goto done; } } else if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { - struct berval authzID = ctrls[ 0 ]->ldctl_value, + struct berval authzID = ctrl->ldctl_value, tmp; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; if ( strncasecmp( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ) != 0 ) { - op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx ); - op->o_tmpfree( ctrls, op->o_tmpmemctx ); - ctrls = NULL; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } @@ -2485,7 +2470,7 @@ free_ber:; goto free_ber2; } - if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) { + if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) { rs->sr_err = LDAP_OTHER; goto free_ber2; } @@ -2495,20 +2480,119 @@ free_ber2:; ber_free_buf( ber ); if ( rs->sr_err != LDAP_SUCCESS ) { - op->o_tmpfree( ctrls, op->o_tmpmemctx ); - ctrls = NULL; goto done; } - ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ; + ctrl->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ; + } + +done:; + + return rs->sr_err; +} + +/* + * Add controls; + * + * if any needs to be added, it is prepended to existing ones, + * in a newly allocated array. The companion function + * ldap_back_controls_free() must be used to restore the original + * status of op->o_ctrls. + */ +int +ldap_back_controls_add( + Operation *op, + SlapReply *rs, + ldapconn_t *lc, + LDAPControl ***pctrls ) +{ + ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; + + LDAPControl **ctrls = NULL; + /* set to the maximum number of controls this backend can add */ + LDAPControl c[ 2 ] = { 0 }; + int i = 0, j = 0; + + *pctrls = NULL; + + rs->sr_err = LDAP_SUCCESS; + + /* don't add controls if protocol is not LDAPv3 */ + switch ( li->li_version ) { + case LDAP_VERSION3: + break; + + case 0: + if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { + break; + } + /* fall thru */ + + default: + goto done; + } + + /* proxyAuthz for identity assertion */ + switch ( ldap_back_proxy_authz_ctrl( op, rs, &lc->lc_bound_ndn, + li->li_version, &li->li_idassert, &c[ j ] ) ) + { + case SLAP_CB_CONTINUE: + break; + + case LDAP_SUCCESS: + j++; + break; + + default: + goto done; + } + +#ifdef SLAP_CONTROL_X_SESSION_TRACKING + /* session tracking */ + if ( LDAP_BACK_ST_REQUEST( li ) ) { + switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j ] ) ) { + case SLAP_CB_CONTINUE: + break; + + case LDAP_SUCCESS: + j++; + break; + + default: + goto done; + } + } +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + + if ( rs->sr_err == SLAP_CB_CONTINUE ) { + rs->sr_err = LDAP_SUCCESS; + } + + if ( j == 0 ) { + goto done; } + if ( op->o_ctrls ) { + for ( i = 0; op->o_ctrls[ i ]; i++ ) + /* just count ctrls */ ; + } + + ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + j + 1) + j * sizeof( LDAPControl ), + op->o_tmpmemctx ); + ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + j + 1 ]; + *ctrls[ 0 ] = c[ 0 ]; + for ( i = 1; i < j; i++ ) { + ctrls[ i ] = &ctrls[ 0 ][ i ]; + *ctrls[ i ] = c[ i ]; + } + + i = 0; if ( op->o_ctrls ) { for ( i = 0; op->o_ctrls[ i ]; i++ ) { - ctrls[ i + 1 ] = op->o_ctrls[ i ]; + ctrls[ i + j ] = op->o_ctrls[ i ]; } } - ctrls[ i + 1 ] = NULL; + ctrls[ i + j ] = NULL; done:; if ( ctrls == NULL ) { @@ -2521,18 +2605,25 @@ done:; } int -ldap_back_proxy_authz_ctrl_free( Operation *op, LDAPControl ***pctrls ) +ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls ) { LDAPControl **ctrls = *pctrls; - /* we assume that the first control is the proxyAuthz - * added by back-ldap, so it's the only one we explicitly - * free */ + /* we assume that the controls added by the proxy come first, + * so as soon as we find op->o_ctrls[ 0 ] we can stop */ if ( ctrls && ctrls != op->o_ctrls ) { + int i; + assert( ctrls[ 0 ] != NULL ); - if ( !BER_BVISNULL( &ctrls[ 0 ]->ldctl_value ) ) { - op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx ); + for ( i = 0; ctrls[ i ] != NULL; i++ ) { + if ( op->o_ctrls && ctrls[ i ] == op->o_ctrls[ 0 ] ) { + break; + } + + if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) { + op->o_tmpfree( ctrls[ i ]->ldctl_value.bv_val, op->o_tmpmemctx ); + } } op->o_tmpfree( ctrls, op->o_tmpmemctx ); diff --git a/servers/slapd/back-ldap/compare.c b/servers/slapd/back-ldap/compare.c index a0a1b59807..740be24751 100644 --- a/servers/slapd/back-ldap/compare.c +++ b/servers/slapd/back-ldap/compare.c @@ -51,8 +51,7 @@ ldap_back_compare( retry: ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &ctrls ); + rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -69,13 +68,13 @@ retry: retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup: - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( lc != NULL ) { ldap_back_release_conn( li, lc ); diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index 03acdaab74..389e17d29c 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -69,6 +69,7 @@ enum { LDAP_BACK_CFG_CONNPOOLMAX, LDAP_BACK_CFG_CANCEL, LDAP_BACK_CFG_QUARANTINE, + LDAP_BACK_CFG_ST_REQUEST, LDAP_BACK_CFG_REWRITE, LDAP_BACK_CFG_LAST @@ -183,7 +184,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "X-ORDERED 'VALUES' )", NULL, NULL }, - { "rebind-as-user", "NO|yes", 1, 2, 0, + { "rebind-as-user", "true|FALSE", 1, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND, ldap_back_cf_gen, "( OLcfgDbAt:3.10 " "NAME 'olcDbRebindAsUser' " @@ -191,7 +192,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, - { "chase-referrals", "YES|no", 2, 2, 0, + { "chase-referrals", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE, ldap_back_cf_gen, "( OLcfgDbAt:3.11 " "NAME 'olcDbChaseReferrals' " @@ -199,7 +200,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, - { "t-f-support", "NO|yes|discover", 2, 2, 0, + { "t-f-support", "true|FALSE|discover", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_T_F, ldap_back_cf_gen, "( OLcfgDbAt:3.12 " "NAME 'olcDbTFSupport' " @@ -207,7 +208,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, - { "proxy-whoami", "NO|yes", 1, 2, 0, + { "proxy-whoami", "true|FALSE", 1, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_WHOAMI, ldap_back_cf_gen, "( OLcfgDbAt:3.13 " "NAME 'olcDbProxyWhoAmI' " @@ -223,7 +224,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, - { "idle-timeout", "timeout", 2, 0, 0, + { "idle-timeout", "timeout", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT, ldap_back_cf_gen, "( OLcfgDbAt:3.15 " "NAME 'olcDbIdleTimeout' " @@ -231,7 +232,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, - { "conn-ttl", "ttl", 2, 0, 0, + { "conn-ttl", "ttl", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL, ldap_back_cf_gen, "( OLcfgDbAt:3.16 " "NAME 'olcDbConnTtl' " @@ -239,7 +240,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, - { "network-timeout", "timeout", 2, 0, 0, + { "network-timeout", "timeout", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT, ldap_back_cf_gen, "( OLcfgDbAt:3.17 " "NAME 'olcDbNetworkTimeout' " @@ -247,7 +248,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, - { "protocol-version", "version", 2, 0, 0, + { "protocol-version", "version", 2, 2, 0, ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION, ldap_back_cf_gen, "( OLcfgDbAt:3.18 " "NAME 'olcDbProtocolVersion' " @@ -255,7 +256,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsInteger " "SINGLE-VALUE )", NULL, NULL }, - { "single-conn", "TRUE/FALSE", 2, 0, 0, + { "single-conn", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN, ldap_back_cf_gen, "( OLcfgDbAt:3.19 " "NAME 'olcDbSingleConn' " @@ -263,7 +264,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, - { "cancel", "ABANDON|ignore|exop", 2, 0, 0, + { "cancel", "ABANDON|ignore|exop", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_CANCEL, ldap_back_cf_gen, "( OLcfgDbAt:3.20 " "NAME 'olcDbCancel' " @@ -271,7 +272,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, - { "quarantine", "retrylist", 2, 0, 0, + { "quarantine", "retrylist", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE, ldap_back_cf_gen, "( OLcfgDbAt:3.21 " "NAME 'olcDbQuarantine' " @@ -279,7 +280,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, - { "use-temporary-conn", "TRUE/FALSE", 2, 0, 0, + { "use-temporary-conn", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP, ldap_back_cf_gen, "( OLcfgDbAt:3.22 " "NAME 'olcDbUseTemporaryConn' " @@ -287,7 +288,7 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, - { "conn-pool-max", "", 2, 0, 0, + { "conn-pool-max", "", 2, 2, 0, ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX, ldap_back_cf_gen, "( OLcfgDbAt:3.23 " "NAME 'olcDbConnectionPoolMax' " @@ -295,6 +296,16 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsInteger " "SINGLE-VALUE )", NULL, NULL }, +#ifdef SLAP_CONTROL_X_SESSION_TRACKING + { "session-tracking-request", "true|FALSE", 2, 2, 0, + ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST, + ldap_back_cf_gen, "( OLcfgDbAt:3.24 " + "NAME 'olcDbSessionTrackingRequest' " + "DESC 'Add session tracking control to proxied requests' " + "SYNTAX OMsBoolean " + "SINGLE-VALUE )", + NULL, NULL }, +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ { "suffixmassage", "[virtual]> value_int = LDAP_BACK_ST_REQUEST( li ); + break; +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + default: /* FIXME: we need to handle all... */ assert( 0 ); @@ -1233,6 +1250,12 @@ ldap_back_cf_gen( ConfigArgs *c ) li->li_flags &= ~LDAP_BACK_F_QUARANTINE; break; +#ifdef SLAP_CONTROL_X_SESSION_TRACKING + case LDAP_BACK_CFG_ST_REQUEST: + li->li_flags &= ~LDAP_BACK_F_ST_REQUEST; + break; +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + default: /* FIXME: we need to handle all... */ assert( 0 ); @@ -1866,6 +1889,17 @@ done_url:; } break; +#ifdef SLAP_CONTROL_X_SESSION_TRACKING + case LDAP_BACK_CFG_ST_REQUEST: + if ( c->value_int ) { + li->li_flags |= LDAP_BACK_F_ST_REQUEST; + + } else { + li->li_flags &= ~LDAP_BACK_F_ST_REQUEST; + } + break; +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + case LDAP_BACK_CFG_REWRITE: snprintf( c->cr_msg, sizeof( c->cr_msg ), "rewrite/remap capabilities have been moved " diff --git a/servers/slapd/back-ldap/delete.c b/servers/slapd/back-ldap/delete.c index 4f1e67ddf8..f10c7d0bbb 100644 --- a/servers/slapd/back-ldap/delete.c +++ b/servers/slapd/back-ldap/delete.c @@ -50,8 +50,7 @@ ldap_back_delete( retry: ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &ctrls ); + rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rc = rs->sr_err; @@ -67,13 +66,13 @@ retry: retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup: - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( lc != NULL ) { ldap_back_release_conn( li, lc ); diff --git a/servers/slapd/back-ldap/extended.c b/servers/slapd/back-ldap/extended.c index 06f374ae3c..cf3aacbb71 100644 --- a/servers/slapd/back-ldap/extended.c +++ b/servers/slapd/back-ldap/extended.c @@ -47,7 +47,7 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, ldap_back_exop_f exop ) ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = NULL; - LDAPControl **oldctrls = NULL; + LDAPControl **ctrls = NULL, **oldctrls = NULL; int rc; /* FIXME: this needs to be called here, so it is @@ -58,9 +58,8 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, ldap_back_exop_f exop ) return -1; } - oldctrls = op->o_ctrls; - if ( ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &op->o_ctrls ) ) + ctrls = op->o_ctrls; + if ( ldap_back_controls_add( op, rs, lc, &ctrls ) ) { op->o_ctrls = oldctrls; send_ldap_extended( op, rs ); @@ -70,13 +69,11 @@ ldap_back_extended_one( Operation *op, SlapReply *rs, ldap_back_exop_f exop ) goto done; } + op->o_ctrls = ctrls; rc = exop( op, rs, &lc ); - if ( op->o_ctrls && op->o_ctrls != oldctrls ) { - free( op->o_ctrls[ 0 ] ); - free( op->o_ctrls ); - } op->o_ctrls = oldctrls; + (void)ldap_back_controls_free( op, rs, &ctrls ); done:; if ( lc != NULL ) { diff --git a/servers/slapd/back-ldap/modify.c b/servers/slapd/back-ldap/modify.c index fc247cb571..7b5817f066 100644 --- a/servers/slapd/back-ldap/modify.c +++ b/servers/slapd/back-ldap/modify.c @@ -99,8 +99,7 @@ ldap_back_modify( retry:; ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &ctrls ); + rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rc = -1; @@ -116,13 +115,13 @@ retry:; retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); for ( i = 0; modv[ i ]; i++ ) { ch_free( modv[ i ]->mod_bvalues ); diff --git a/servers/slapd/back-ldap/modrdn.c b/servers/slapd/back-ldap/modrdn.c index 8fa02ef6e2..d6e3b01854 100644 --- a/servers/slapd/back-ldap/modrdn.c +++ b/servers/slapd/back-ldap/modrdn.c @@ -74,8 +74,7 @@ ldap_back_modrdn( retry: ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &ctrls ); + rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rc = -1; @@ -92,13 +91,13 @@ retry: retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup: - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( lc != NULL ) { ldap_back_release_conn( li, lc ); diff --git a/servers/slapd/back-ldap/proto-ldap.h b/servers/slapd/back-ldap/proto-ldap.h index 8eca7f6593..9bc4133387 100644 --- a/servers/slapd/back-ldap/proto-ldap.h +++ b/servers/slapd/back-ldap/proto-ldap.h @@ -63,6 +63,7 @@ extern void ldap_back_conn_free( void *c ); extern ldapconn_t * ldap_back_conn_delete( ldapinfo_t *li, ldapconn_t *lc ); +#if 0 extern int ldap_back_proxy_authz_ctrl( struct berval *bound_ndn, @@ -76,6 +77,26 @@ extern int ldap_back_proxy_authz_ctrl_free( Operation *op, LDAPControl ***pctrls ); +#endif + +extern int +ldap_back_proxy_authz_ctrl( + Operation *op, + SlapReply *rs, + struct berval *bound_ndn, + int version, + slap_idassert_t *si, + LDAPControl *ctrl ); + +extern int +ldap_back_controls_add( + Operation *op, + SlapReply *rs, + ldapconn_t *lc, + LDAPControl ***pctrls ); + +extern int +ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls ); extern void ldap_back_quarantine( diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 732fb203e7..4c4f078fb1 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -205,8 +205,7 @@ ldap_back_search( } ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, rs, &ctrls ); + rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { goto finish; } @@ -529,7 +528,7 @@ finish:; send_ldap_result( op, rs ); } - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); @@ -819,8 +818,7 @@ ldap_back_entry_get( retry: ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn, - li->li_version, &li->li_idassert, op, &rs, &ctrls ); + rc = ldap_back_controls_add( op, &rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { goto cleanup; } @@ -833,7 +831,7 @@ retry: do_retry = 0; if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, &rs, &ctrls ); goto retry; } } @@ -860,7 +858,7 @@ retry: } cleanup: - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, &rs, &ctrls ); if ( result ) { ldap_msgfree( result ); diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c index ddd651f7a9..cfa3e73f5a 100644 --- a/servers/slapd/back-meta/add.c +++ b/servers/slapd/back-meta/add.c @@ -169,8 +169,7 @@ meta_back_add( Operation *op, SlapReply *rs ) retry:; ctrls = op->o_ctrls; - if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn, - mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS ) + if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -184,13 +183,13 @@ retry:; do_retry = 0; if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); for ( --i; i >= 0; --i ) { free( attrs[ i ]->mod_bvalues ); diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index dbceee049e..2f7b080e8b 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -310,6 +310,11 @@ typedef struct metatarget_t { #define META_BACK_TGT_CANCEL_DISCOVER(mt) META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK2, LDAP_BACK_F_CANCEL_EXOP_DISCOVER ) #define META_BACK_TGT_QUARANTINE(mt) META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_QUARANTINE ) +#ifdef SLAP_CONTROL_X_SESSION_TRACKING +#define META_BACK_TGT_ST_REQUEST(mt) META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_REQUEST ) +#define META_BACK_TGT_ST_RESPONSE(mt) META_BACK_TGT_ISSET( (mt), LDAP_BACK_F_ST_RESPONSE ) +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + int mt_version; time_t mt_network_timeout; struct timeval mt_bind_timeout; diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index 03e3ec204e..bae5a47782 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -460,6 +460,9 @@ meta_back_single_bind( metasingleconn_t *msc = &mc->mc_conns[ candidate ]; int msgid; dncookie dc; + struct berval save_o_dn; + int save_o_do_not_cache; + LDAPControl **ctrls = NULL; if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) { ch_free( msc->msc_bound_ndn.bv_val ); @@ -487,6 +490,20 @@ meta_back_single_bind( return rs->sr_err; } + /* don't add proxyAuthz; set the bindDN */ + save_o_dn = op->o_dn; + save_o_do_not_cache = op->o_do_not_cache; + op->o_do_not_cache = 1; + op->o_dn = op->o_req_dn; + + ctrls = op->o_ctrls; + rs->sr_err = meta_back_controls_add( op, rs, mc, candidate, &ctrls ); + op->o_dn = save_o_dn; + op->o_do_not_cache = save_o_do_not_cache; + if ( rs->sr_err != LDAP_SUCCESS ) { + goto return_results; + } + /* FIXME: this fixes the bind problem right now; we need * to use the asynchronous version to get the "matched" * and more in case of failure ... */ @@ -495,12 +512,15 @@ meta_back_single_bind( for (;;) { rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val, LDAP_SASL_SIMPLE, &op->orb_cred, - op->o_ctrls, NULL, &msgid ); + ctrls, NULL, &msgid ); if ( rs->sr_err != LDAP_X_CONNECTING ) { break; } ldap_pvt_thread_yield(); } + + ldap_back_controls_free( op, rs, &ctrls ); + meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND ); if ( rs->sr_err != LDAP_SUCCESS ) { goto return_results; @@ -1537,3 +1557,120 @@ meta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapRe return LDAP_BACK_CONN_ISBOUND( msc ); } + +/* + * Add controls; + * + * if any needs to be added, it is prepended to existing ones, + * in a newly allocated array. The companion function + * ldap_back_controls_free() must be used to restore the original + * status of op->o_ctrls. + */ +int +meta_back_controls_add( + Operation *op, + SlapReply *rs, + metaconn_t *mc, + int candidate, + LDAPControl ***pctrls ) +{ + metainfo_t *mi = (metainfo_t *)op->o_bd->be_private; + metatarget_t *mt = mi->mi_targets[ candidate ]; + metasingleconn_t *msc = &mc->mc_conns[ candidate ]; + + LDAPControl **ctrls = NULL; + /* set to the maximum number of controls this backend can add */ + LDAPControl c[ 2 ] = { 0 }; + int i = 0, j = 0; + + *pctrls = NULL; + + rs->sr_err = LDAP_SUCCESS; + + /* don't add controls if protocol is not LDAPv3 */ + switch ( mt->mt_version ) { + case LDAP_VERSION3: + break; + + case 0: + if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { + break; + } + /* fall thru */ + + default: + goto done; + } + + /* proxyAuthz for identity assertion */ + switch ( ldap_back_proxy_authz_ctrl( op, rs, &msc->msc_bound_ndn, + mt->mt_version, &mt->mt_idassert, &c[ j ] ) ) + { + case SLAP_CB_CONTINUE: + break; + + case LDAP_SUCCESS: + j++; + break; + + default: + goto done; + } + +#ifdef SLAP_CONTROL_X_SESSION_TRACKING + /* session tracking */ + if ( META_BACK_TGT_ST_REQUEST( mt ) ) { + switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j ] ) ) { + case SLAP_CB_CONTINUE: + break; + + case LDAP_SUCCESS: + j++; + break; + + default: + goto done; + } + } +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + + if ( rs->sr_err == SLAP_CB_CONTINUE ) { + rs->sr_err = LDAP_SUCCESS; + } + + if ( j == 0 ) { + goto done; + } + + if ( op->o_ctrls ) { + for ( i = 0; op->o_ctrls[ i ]; i++ ) + /* just count ctrls */ ; + } + + ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + j + 1) + j * sizeof( LDAPControl ), + op->o_tmpmemctx ); + ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + j + 1 ]; + *ctrls[ 0 ] = c[ 0 ]; + for ( i = 1; i < j; i++ ) { + ctrls[ i ] = &ctrls[ 0 ][ i ]; + *ctrls[ i ] = c[ i ]; + } + + i = 0; + if ( op->o_ctrls ) { + for ( i = 0; op->o_ctrls[ i ]; i++ ) { + ctrls[ i + j ] = op->o_ctrls[ i ]; + } + } + ctrls[ i + j ] = NULL; + +done:; + if ( ctrls == NULL ) { + ctrls = op->o_ctrls; + } + + *pctrls = ctrls; + + return rs->sr_err; +} + diff --git a/servers/slapd/back-meta/compare.c b/servers/slapd/back-meta/compare.c index 0a8cf10e6b..b381daf89e 100644 --- a/servers/slapd/back-meta/compare.c +++ b/servers/slapd/back-meta/compare.c @@ -113,8 +113,7 @@ meta_back_compare( Operation *op, SlapReply *rs ) retry:; ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn, - mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ); + rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -130,13 +129,13 @@ retry:; do_retry = 0; if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( mdn.bv_val != op->o_req_dn.bv_val ) { free( mdn.bv_val ); diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index 0725a415d6..6cdfbc60fc 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -1235,6 +1235,36 @@ idassert-authzFrom "dn:" } else { mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags |= LDAP_BACK_F_QUARANTINE; } + + /* session tracking request */ + } else if ( strcasecmp( argv[ 0 ], "session-tracking-request" ) == 0 ) { + unsigned *flagsp = mi->mi_ntargets ? + &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags + : &mi->mi_flags; + + if ( argc != 2 ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: \"session-tracking-request {TRUE|false}\" needs 1 argument.\n", + fname, lineno, 0 ); + return( 1 ); + } + + /* this is the default; we add it because the default might change... */ + switch ( check_true_false( argv[ 1 ] ) ) { + case 1: + *flagsp |= LDAP_BACK_F_ST_REQUEST; + break; + + case 0: + *flagsp &= ~LDAP_BACK_F_ST_REQUEST; + break; + + default: + Debug( LDAP_DEBUG_ANY, + "%s: line %d: \"session-tracking-request {TRUE|false}\": unknown argument \"%s\".\n", + fname, lineno, argv[ 1 ] ); + return( 1 ); + } /* dn massaging */ } else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) { diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c index 8f1eaac21b..da4d7553cd 100644 --- a/servers/slapd/back-meta/delete.c +++ b/servers/slapd/back-meta/delete.c @@ -67,8 +67,7 @@ meta_back_delete( Operation *op, SlapReply *rs ) retry:; ctrls = op->o_ctrls; - if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn, - mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS ) + if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -82,13 +81,13 @@ retry:; do_retry = 0; if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( mdn.bv_val != op->o_req_dn.bv_val ) { free( mdn.bv_val ); diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c index a1088c7932..ef117860e0 100644 --- a/servers/slapd/back-meta/modify.c +++ b/servers/slapd/back-meta/modify.c @@ -178,8 +178,7 @@ meta_back_modify( Operation *op, SlapReply *rs ) retry:; ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn, - mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ); + rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -193,13 +192,13 @@ retry:; do_retry = 0; if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( mdn.bv_val != op->o_req_dn.bv_val ) { free( mdn.bv_val ); diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c index 2a14b27208..66222cfefd 100644 --- a/servers/slapd/back-meta/modrdn.c +++ b/servers/slapd/back-meta/modrdn.c @@ -120,8 +120,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs ) retry:; ctrls = op->o_ctrls; - if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn, - mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS ) + if ( meta_back_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -137,13 +136,13 @@ retry:; do_retry = 0; if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( mdn.bv_val != op->o_req_dn.bv_val ) { free( mdn.bv_val ); diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 713a876761..c9e435b41d 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -598,8 +598,7 @@ meta_back_search_start( retry:; ctrls = op->o_ctrls; - if ( ldap_back_proxy_authz_ctrl( &msc->msc_bound_ndn, - mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) + if ( meta_back_controls_add( op, rs, *mcp, candidate, &ctrls ) != LDAP_SUCCESS ) { candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; @@ -625,7 +624,7 @@ retry:; if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) { nretries = 0; /* if the identity changed, there might be need to re-authz */ - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } @@ -642,7 +641,7 @@ retry:; } done:; - (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); + (void)ldap_back_controls_free( op, rs, &ctrls ); if ( mapped_attrs ) { free( mapped_attrs ); diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index 13dcab4de6..ed887e5f1a 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -21,6 +21,7 @@ #include #include "slap.h" +#include "ldif.h" #include "lutil.h" #include "../../libraries/liblber/lber-int.h" @@ -1755,18 +1756,19 @@ static int parseSessionTracking( } else { /* note: should not be more than 65536... */ tag = ber_scanf( ber, "m", &sessionTrackingIdentifier ); - } - - if ( ldif_is_not_printable( sessionTrackingIdentifier.bv_val, sessionTrackingIdentifier.bv_len ) ) { - /* we want the OID printed, at least */ - BER_BVSTR( &sessionTrackingIdentifier, "" ); + if ( ldif_is_not_printable( sessionTrackingIdentifier.bv_val, sessionTrackingIdentifier.bv_len ) ) { + /* we want the OID printed, at least */ + BER_BVSTR( &sessionTrackingIdentifier, "" ); + } } /* closure */ tag = ber_skip_tag( ber, &len ); - if ( tag == LBER_DEFAULT && len == 0 ) { - tag = 0; + if ( tag != LBER_DEFAULT || len != 0 ) { + tag = LBER_ERROR; + goto error; } + tag = 0; st_len = 0; if ( !BER_BVISNULL( &sessionSourceIp ) ) { @@ -1830,4 +1832,73 @@ error:; return rs->sr_err; } + +int +slap_ctrl_session_tracking_add( + Operation *op, + SlapReply *rs, + struct berval *ip, + struct berval *name, + struct berval *id, + LDAPControl *ctrl ) +{ + BerElementBuffer berbuf; + BerElement *ber = (BerElement *)&berbuf; + + static struct berval oid = BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME ); + + assert( ctrl != NULL ); + + ber_init2( ber, NULL, LBER_USE_DER ); + + ber_printf( ber, "{OOOO}", ip, name, &oid, id ); + + if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) { + rs->sr_err = LDAP_OTHER; + goto done; + } + + ctrl->ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING; + ctrl->ldctl_iscritical = 0; + + rs->sr_err = LDAP_SUCCESS; + +done:; + return rs->sr_err; +} + +int +slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPControl *ctrl ) +{ + static struct berval bv_unknown = BER_BVC( SLAP_STRING_UNKNOWN ); + struct berval ip = BER_BVNULL, + name = BER_BVNULL, + id = BER_BVNULL; + + if ( !BER_BVISNULL( &op->o_conn->c_peer_name ) && + memcmp( op->o_conn->c_peer_name.bv_val, "IP=", STRLENOF( "IP=" ) ) == 0 ) + { + char *ptr; + + ip.bv_val = op->o_conn->c_peer_name.bv_val + STRLENOF( "IP=" ); + ip.bv_len = op->o_conn->c_peer_name.bv_len - STRLENOF( "IP=" ); + + ptr = ber_bvchr( &ip, ':' ); + if ( ptr ) { + ip.bv_len = ptr - ip.bv_val; + } + } + + if ( !BER_BVISNULL( &op->o_conn->c_peer_domain ) && + !bvmatch( &op->o_conn->c_peer_domain, &bv_unknown ) ) + { + name = op->o_conn->c_peer_domain; + } + + if ( !BER_BVISNULL( &op->o_dn ) && !BER_BVISEMPTY( &op->o_dn ) ) { + id = op->o_dn; + } + + return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl ); +} #endif diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 499fc06c89..40d2713952 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -53,11 +53,7 @@ # include int allow_severity = LOG_INFO; int deny_severity = LOG_NOTICE; - -# define SLAP_STRING_UNKNOWN STRING_UNKNOWN -#else /* ! TCP Wrappers */ -# define SLAP_STRING_UNKNOWN "unknown" -#endif /* ! TCP Wrappers */ +#endif /* TCP Wrappers */ #ifdef LDAP_PF_LOCAL # include diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 2e796c08d4..9eb6c9a86d 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -629,6 +629,20 @@ LDAP_SLAPD_F (int) slap_remove_control LDAP_P(( int ctrl, BI_chk_controls fnc )); +#ifdef SLAP_CONTROL_X_SESSION_TRACKING +LDAP_SLAPD_F (int) +slap_ctrl_session_tracking_add LDAP_P(( + Operation *op, + SlapReply *rs, + struct berval *ip, + struct berval *name, + struct berval *id, + LDAPControl *ctrl )); +LDAP_SLAPD_F (int) +slap_ctrl_session_tracking_request_add LDAP_P(( + Operation *op, SlapReply *rs, LDAPControl *ctrl )); +#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ + /* * config.c */ diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 818a36bbac..75aa25d1a9 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -101,6 +101,13 @@ LDAP_BEGIN_DECL #define SERVICE_NAME OPENLDAP_PACKAGE "-slapd" #define SLAPD_ANONYMOUS "" +#ifdef HAVE_TCPD +# include +# define SLAP_STRING_UNKNOWN STRING_UNKNOWN +#else /* ! TCP Wrappers */ +# define SLAP_STRING_UNKNOWN "unknown" +#endif /* ! TCP Wrappers */ + /* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h! * This is a value used internally by the backends. It is needed to allow * adding values that already exist without getting an error as required by -- 2.39.5