Репозитории ALT
S: | 2.6.4-alt1 |
5.1: | 2.3.43-alt2.3 |
4.1: | 2.3.41-alt3.M41.3 |
4.0: | 2.3.35-alt1.M40.1 |
3.0: | 2.2.27-alt1.1 |
Группа :: Система/Серверы
Пакет: openldap
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: openldap-2.3.34-alt-meta-backend.patch
Скачать
Скачать
diff -ruN openldap-2.3.34.orig/servers/slapd/back-meta/bind.c openldap-2.3.34/servers/slapd/back-meta/bind.c
--- openldap-2.3.34.orig/servers/slapd/back-meta/bind.c 2007-01-28 09:56:43 +1000
+++ openldap-2.3.34/servers/slapd/back-meta/bind.c 2007-03-18 04:28:07 +1000
@@ -1437,3 +1437,365 @@
return LDAP_BACK_CONN_ISBOUND( msc );
}
+
+#define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ "2.16.840.1.113730.3.4.12"
+/*
+ * ldap_back_proxy_authz_ctrl() prepends a proxyAuthz control
+ * to existing server-side controls if required; if not,
+ * the existing server-side controls are placed in *pctrls.
+ * The caller, after using the controls in client API
+ * operations, if ( *pctrls != op->o_ctrls ), should
+ * free( (*pctrls)[ 0 ] ) and free( *pctrls ).
+ * The function returns success if the control could
+ * be added if required, or if it did nothing; in the future,
+ * it might return some error if it failed.
+ *
+ * if no bind took place yet, but the connection is bound
+ * and the "proxyauthzdn" is set, then bind as "proxyauthzdn"
+ * and explicitly add proxyAuthz the control to every operation
+ * with the dn bound to the connection as control value.
+ *
+ * If no server-side controls are defined for the operation,
+ * simply add the proxyAuthz control; otherwise, if the
+ * proxyAuthz control is not already set, add it as
+ * the first one
+ *
+ * FIXME: is controls order significant for security?
+ * ANSWER: controls ordering and interoperability
+ * must be indicated by the specs of each control; if none
+ * is specified, the order is irrelevant.
+ */
+int
+ldap_back_proxy_authz_ctrl(
+ struct berval *bound_ndn,
+ int version,
+ slap_idassert_t *si,
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl ***pctrls )
+{
+ 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;
+ }
+
+ /* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID,
+ * but if it is not set this test fails. We need a different
+ * means to detect if idassert is enabled */
+ if ( ( BER_BVISNULL( &si->si_bc.sb_authcId ) || BER_BVISEMPTY( &si->si_bc.sb_authcId ) )
+ && ( BER_BVISNULL( &si->si_bc.sb_binddn ) || BER_BVISEMPTY( &si->si_bc.sb_binddn ) ) )
+ {
+ goto done;
+ }
+
+ if ( !op->o_conn || op->o_do_not_cache || ( isroot = be_isroot( op ) ) ) {
+ goto done;
+ }
+
+ if ( op->o_tag == LDAP_REQ_BIND ) {
+ ndn = op->o_req_ndn;
+
+ } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
+ ndn = op->o_conn->c_ndn;
+
+ } else {
+ ndn = op->o_ndn;
+ }
+
+ if ( si->si_mode == LDAP_BACK_IDASSERT_LEGACY ) {
+ if ( op->o_proxy_authz ) {
+ /*
+ * FIXME: we do not want to perform proxyAuthz
+ * on behalf of the client, because this would
+ * be performed with "proxyauthzdn" privileges.
+ *
+ * This might actually be too strict, since
+ * the "proxyauthzdn" authzTo, and each entry's
+ * authzFrom attributes may be crafted
+ * to avoid unwanted proxyAuthz to take place.
+ */
+#if 0
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "proxyAuthz not allowed within namingContext";
+#endif
+ goto done;
+ }
+
+ if ( !BER_BVISNULL( bound_ndn ) ) {
+ goto done;
+ }
+
+ if ( BER_BVISNULL( &ndn ) ) {
+ goto done;
+ }
+
+ if ( BER_BVISNULL( &si->si_bc.sb_binddn ) ) {
+ goto done;
+ }
+
+ } else if ( si->si_bc.sb_method == LDAP_AUTH_SASL ) {
+ if ( ( si->si_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
+ {
+ /* already asserted in SASL via native authz */
+ goto done;
+ }
+
+ } else if ( si->si_authz && !isroot ) {
+ int rc;
+ struct berval authcDN;
+
+ if ( BER_BVISNULL( &ndn ) ) {
+ authcDN = slap_empty_bv;
+ } else {
+ authcDN = ndn;
+ }
+ rc = slap_sasl_matches( op, si->si_authz,
+ &authcDN, & authcDN );
+ if ( rc != LDAP_SUCCESS ) {
+ if ( si->si_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+ /* ndn is not authorized
+ * to use idassert */
+ rs->sr_err = rc;
+ }
+ goto done;
+ }
+ }
+
+ if ( op->o_proxy_authz ) {
+ /*
+ * FIXME: we can:
+ * 1) ignore the already set proxyAuthz control
+ * 2) leave it in place, and don't set ours
+ * 3) add both
+ * 4) reject the operation
+ *
+ * option (4) is very drastic
+ * option (3) will make the remote server reject
+ * the operation, thus being equivalent to (4)
+ * option (2) will likely break the idassert
+ * assumptions, so we cannot accept it;
+ * option (1) means that we are contradicting
+ * the client's reques.
+ *
+ * I think (4) is the only correct choice.
+ */
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "proxyAuthz not allowed within namingContext";
+ }
+
+ if ( op->o_is_auth_check ) {
+ mode = LDAP_BACK_IDASSERT_NOASSERT;
+
+ } else {
+ mode = si->si_mode;
+ }
+
+ switch ( mode ) {
+ case LDAP_BACK_IDASSERT_LEGACY:
+ /* original behavior:
+ * assert the client's identity */
+ case LDAP_BACK_IDASSERT_SELF:
+ assertedID = ndn;
+ break;
+
+ case LDAP_BACK_IDASSERT_ANONYMOUS:
+ /* assert "anonymous" */
+ assertedID = slap_empty_bv;
+ break;
+
+ case LDAP_BACK_IDASSERT_NOASSERT:
+ /* don't assert; bind as proxyauthzdn */
+ goto done;
+
+ case LDAP_BACK_IDASSERT_OTHERID:
+ case LDAP_BACK_IDASSERT_OTHERDN:
+ /* assert idassert DN */
+ assertedID = si->si_bc.sb_authzId;
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ /* if we got here, "" is allowed to proxyAuthz */
+ if ( BER_BVISNULL( &assertedID ) ) {
+ assertedID = slap_empty_bv;
+ }
+
+ /* don't idassert the bound DN (ITS#4497) */
+ if ( dn_match( &assertedID, bound_ndn ) ) {
+ 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 );
+ 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,
+ op->o_tmpmemctx );
+ AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );
+ AC_MEMCPY( &ctrls[ 0 ]->ldctl_value.bv_val[ STRLENOF( "dn:" ) ],
+ assertedID.bv_val, assertedID.bv_len + 1 );
+ break;
+ }
+
+ /* Older versions of <draft-weltman-ldapv3-proxy> required
+ * to encode the value of the authzID (and called it proxyDN);
+ * 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;
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+
+ ber_init2( ber, 0, LBER_USE_DER );
+ ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
+
+ tag = ber_printf( ber, "O", &authzID );
+ if ( tag == LBER_ERROR ) {
+ rs->sr_err = LDAP_OTHER;
+ goto free_ber;
+ }
+
+ if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+ rs->sr_err = LDAP_OTHER;
+ goto free_ber;
+ }
+
+free_ber:;
+ op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx );
+ 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,
+ 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;
+ }
+
+ tmp = authzID;
+ tmp.bv_val += STRLENOF( "dn:" );
+ tmp.bv_len -= STRLENOF( "dn:" );
+
+ ber_init2( ber, 0, LBER_USE_DER );
+ ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
+
+ /* apparently, Mozilla API encodes this
+ * as "SEQUENCE { LDAPDN }" */
+ tag = ber_printf( ber, "{O}", &tmp );
+ if ( tag == LBER_ERROR ) {
+ rs->sr_err = LDAP_OTHER;
+ goto free_ber2;
+ }
+
+ if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {
+ rs->sr_err = LDAP_OTHER;
+ goto free_ber2;
+ }
+
+free_ber2:;
+ op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx );
+ 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;
+ }
+
+ if ( op->o_ctrls ) {
+ for ( i = 0; op->o_ctrls[ i ]; i++ ) {
+ ctrls[ i + 1 ] = op->o_ctrls[ i ];
+ }
+ }
+ ctrls[ i + 1 ] = NULL;
+
+done:;
+ if ( ctrls == NULL ) {
+ ctrls = op->o_ctrls;
+ }
+
+ *pctrls = ctrls;
+
+ return rs->sr_err;
+}
+
+int
+ldap_back_proxy_authz_ctrl_free( Operation *op, 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 */
+ if ( ctrls && ctrls != op->o_ctrls ) {
+ assert( ctrls[ 0 ] != NULL );
+
+ if ( !BER_BVISNULL( &ctrls[ 0 ]->ldctl_value ) ) {
+ op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );
+ }
+
+ op->o_tmpfree( ctrls, op->o_tmpmemctx );
+ }
+
+ *pctrls = NULL;
+
+ return 0;
+}
diff -ruN openldap-2.3.34.orig/servers/slapd/back-meta/config.c openldap-2.3.34/servers/slapd/back-meta/config.c
--- openldap-2.3.34.orig/servers/slapd/back-meta/config.c 2007-01-28 09:56:43 +1000
+++ openldap-2.3.34/servers/slapd/back-meta/config.c 2007-03-18 04:27:08 +1000
@@ -28,12 +28,232 @@
#include <ac/socket.h>
#include "slap.h"
+#include "config.h"
#include "lutil.h"
#include "../back-ldap/back-ldap.h"
#undef ldap_debug /* silence a warning in ldap-int.h */
#include "../../../libraries/libldap/ldap-int.h"
#include "back-meta.h"
+static slap_verbmasks idassert_mode[] = {
+ { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF },
+ { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS },
+ { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT },
+ { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY },
+ { BER_BVNULL, 0 }
+};
+
+
+
+static int
+slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si )
+{
+ struct berval bv;
+
+ if ( strcmp( c->argv[ 1 ], "*" ) == 0
+ || strcmp( c->argv[ 1 ], "dn:*" ) == 0
+ || strcasecmp( c->argv[ 1 ], "dn.regex:.*" ) == 0 )
+ {
+ if ( si->si_authz != NULL ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-authzFrom <authz>\": "
+ "\"%s\" conflicts with existing authz rules",
+ c->argv[ 1 ] );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ return 1;
+ }
+
+ si->si_flags |= LDAP_BACK_AUTH_AUTHZ_ALL;
+
+ return 0;
+
+ } else if ( ( si->si_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-authzFrom <authz>\": "
+ "\"<authz>\" conflicts with \"*\"" );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ return 1;
+ }
+
+#ifdef SLAP_AUTHZ_SYNTAX
+ {
+ struct berval in;
+ int rc;
+
+ ber_str2bv( c->argv[ 1 ], 0, 0, &in );
+ rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-authzFrom <authz>\": "
+ "invalid syntax" );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ return 1;
+ }
+ }
+#else /* !SLAP_AUTHZ_SYNTAX */
+ ber_str2bv( c->argv[ 1 ], 0, 1, &bv );
+#endif /* !SLAP_AUTHZ_SYNTAX */
+
+ ber_bvarray_add( &si->si_authz, &bv );
+
+ return 0;
+}
+
+
+static int
+slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
+{
+ int i;
+
+ for ( i = 1; i < c->argc; i++ ) {
+ if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
+ char *argvi = c->argv[ i ] + STRLENOF( "mode=" );
+ int j;
+
+ j = verb_to_mask( argvi, idassert_mode );
+ if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-bind <args>\": "
+ "unknown mode \"%s\"",
+ argvi );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ return 1;
+ }
+
+ si->si_mode = idassert_mode[ j ].mask;
+
+ } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
+ char *argvi = c->argv[ i ] + STRLENOF( "authz=" );
+
+ if ( strcasecmp( argvi, "native" ) == 0 ) {
+ if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-bind <args>\": "
+ "authz=\"native\" incompatible "
+ "with auth method" );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ return 1;
+ }
+ si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
+
+ } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
+ si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
+
+ } else {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-bind <args>\": "
+ "unknown authz \"%s\"",
+ argvi );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ return 1;
+ }
+
+ } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
+ char *argvi = c->argv[ i ] + STRLENOF( "flags=" );
+ char **flags = ldap_str2charray( argvi, "," );
+ int j, err = 0;
+
+ if ( flags == NULL ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-bind <args>\": "
+ "unable to parse flags \"%s\"",
+ argvi );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ return 1;
+ }
+
+ for ( j = 0; flags[ j ] != NULL; j++ ) {
+
+ if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
+ si->si_flags |= LDAP_BACK_AUTH_OVERRIDE;
+
+ } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
+ si->si_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
+
+ } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
+ si->si_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
+
+ } else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) {
+ if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: \"obsolete-proxy-authz\" flag "
+ "in \"idassert-mode <args>\" "
+ "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
+ c->log, 0, 0 );
+ err = 1;
+ break;
+
+ } else {
+ si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
+ }
+
+ } else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) {
+ if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: \"obsolete-encoding-workaround\" flag "
+ "in \"idassert-mode <args>\" "
+ "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
+ c->log, 0, 0 );
+ err = 1;
+ break;
+
+ } else {
+ si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
+ }
+
+ } else {
+ snprintf( c->msg, sizeof( c->msg ),
+ "\"idassert-bind <args>\": "
+ "unknown flag \"%s\"",
+ flags[ j ] );
+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+ err = 1;
+ break;
+ }
+ }
+
+ ldap_charray_free( flags );
+ if ( err ) {
+ return 1;
+ }
+
+ } else if ( bindconf_parse( c->argv[ i ], &si->si_bc ) ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* NOTE: temporary, until back-meta is ported to back-config */
+int
+slap_idassert_authzfrom_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si )
+{
+ ConfigArgs c = { 0 };
+ char *argv[ 3 ];
+
+ snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
+ c.argc = 2;
+ c.argv = argv;
+ argv[ 0 ] = "idassert-authzFrom";
+ argv[ 1 ] = (char *)arg;
+ argv[ 2 ] = NULL;
+
+ return slap_idassert_authzfrom_parse( &c, si );
+}
+int
+slap_idassert_parse_cf( const char *fname, int lineno, int argc, char *argv[], slap_idassert_t *si )
+{
+ ConfigArgs c = { 0 };
+
+ snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
+ c.argc = argc;
+ c.argv = argv;
+
+ return slap_idassert_parse( &c, si );
+}
+
+
static int
meta_back_new_target(
metatarget_t **mtp )