From: Pierangelo Masarati Date: Sat, 22 May 2004 17:26:02 +0000 (+0000) Subject: more on identity assertion X-Git-Tag: OPENDLAP_REL_ENG_2_2_MP~343 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a18e199e0df68075d4803c797bb653360bfbb33a;p=openldap more on identity assertion --- diff --git a/doc/man/man5/slapd-ldap.5 b/doc/man/man5/slapd-ldap.5 index afff3fe073..8449b9997a 100644 --- a/doc/man/man5/slapd-ldap.5 +++ b/doc/man/man5/slapd-ldap.5 @@ -77,14 +77,17 @@ The URI list is space- or comma-separated. .B server Obsolete option; same as `uri ldap:///'. .TP -.B binddn "" +.B acl-authcDN "" DN which is used to query the target server for acl checking; it should have read access on the target server to attributes used on the proxy for acl checking. There is no risk of giving away such values; they are only used to check permissions. +.B The acl-authcDN identity is by no means implicitly used by the proxy +.B when the client connects anonymously, so it cannot be used to +.B anonymously query Active Directory. .TP -.B bindpw +.B acl-passwd Password used with the bind DN above. .TP .B idassert-authcdn "" @@ -94,7 +97,7 @@ belong to the DIT fragment that is being proxyied by back-ldap. This is useful when operations performed by users bound to another backend are propagated through back-ldap. This requires the entry with -.B proxyauthzdn +.B idassert-authcdn identity on the remote server to have .B proxyAuthz privileges on a wide set of DNs, e.g. @@ -130,11 +133,11 @@ The supported modes are: The default is .BR legacy , which implies that the proxy will bind as -.I proxyauthzdn +.I idassert-authcdn and assert the client's identity when it is not anonymous. Direct binds are always proxied. The other modes imply that the proxy will always bind as -.IR proxyauthzdn , +.IR idassert-authcdn , unless restricted by .BR idassert-authz rules (see below), in which case the operation will fail; @@ -152,7 +155,7 @@ identity will be asserted; .BR none , which means that no proxyAuthz control will be used, so the -.I proxyauthzdn +.I idassert-authcdn identity will be asserted. Moreover, if a string prefixed with .B u: diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 2697340a1e..a16d050434 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -82,12 +82,27 @@ struct ldaprwmap { struct ldapmap rwm_at; }; +struct ldapauth { + struct berval la_authcID; + struct berval la_authcDN; + struct berval la_passwd; + + struct berval la_authzID; + + int la_authmethod; + int la_sasl_flags; + struct berval la_sasl_mech; + struct berval la_sasl_realm; +}; + struct ldapinfo { struct slap_backend_db *be; char *url; LDAPURLDesc *lud; - struct berval binddn; - struct berval bindpw; + struct ldapauth acl_la; +#define acl_authcDN acl_la.la_authcDN +#define acl_passwd acl_la.la_passwd + #ifdef LDAP_BACK_PROXY_AUTHZ /* ID assert stuff */ int idassert_mode; @@ -98,18 +113,17 @@ struct ldapinfo { #define LDAP_BACK_IDASSERT_OTHERDN 4 #define LDAP_BACK_IDASSERT_OTHERID 5 - struct berval idassert_authcID; - struct berval idassert_authcDN; - struct berval idassert_passwd; - - struct berval idassert_authzID; + struct ldapauth idassert_la; +#define idassert_authcID idassert_la.la_authcID +#define idassert_authcDN idassert_la.la_authcDN +#define idassert_passwd idassert_la.la_passwd +#define idassert_authzID idassert_la.la_authzID +#define idassert_authmethod idassert_la.la_authmethod +#define idassert_sasl_flags idassert_la.la_sasl_flags +#define idassert_sasl_mech idassert_la.la_sasl_mech +#define idassert_sasl_realm idassert_la.la_sasl_realm BerVarray idassert_authz; - int idassert_authmethod; - int idassert_sasl_flags; - struct berval idassert_sasl_mech; - struct berval idassert_sasl_realm; - int idassert_ppolicy; /* end of ID assert stuff */ #endif /* LDAP_BACK_PROXY_AUTHZ */ diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 4d91afe8b6..f5f23e1c79 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -224,6 +224,7 @@ ldap_back_getconn(Operation *op, SlapReply *rs) || (op->o_conn && (op->o_bd == op->o_conn->c_authz_backend ))) { lc_curr.conn = op->o_conn; + } else { lc_curr.conn = NULL; } @@ -233,6 +234,7 @@ ldap_back_getconn(Operation *op, SlapReply *rs) lc_curr.local_dn = li->be->be_rootndn; lc_curr.conn = NULL; is_priv = 1; + } else { lc_curr.local_dn = op->o_ndn; } @@ -283,8 +285,9 @@ ldap_back_getconn(Operation *op, SlapReply *rs) ldap_pvt_thread_mutex_init( &lc->lc_mutex ); if ( is_priv ) { - ber_dupbv( &lc->cred, &li->bindpw ); - ber_dupbv( &lc->bound_dn, &li->binddn ); + ber_dupbv( &lc->cred, &li->acl_passwd ); + ber_dupbv( &lc->bound_dn, &li->acl_authcDN ); + } else { BER_BVZERO( &lc->cred ); BER_BVZERO( &lc->bound_dn ); @@ -404,17 +407,18 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) && ( BER_BVISNULL( &lc->bound_dn ) || BER_BVISEMPTY( &lc->bound_dn ) ) ) { struct berval binddn = slap_empty_bv; struct berval bindcred = slap_empty_bv; + int dobind = 0; /* bind as proxyauthzdn only if no idassert mode is requested, * or if the client's identity is authorized */ switch ( li->idassert_mode ) { case LDAP_BACK_IDASSERT_LEGACY: if ( !BER_BVISNULL( &op->o_conn->c_dn ) && !BER_BVISEMPTY( &op->o_conn->c_dn ) ) { - if ( li->idassert_authmethod != LDAP_AUTH_SASL - && !BER_BVISNULL( &li->idassert_authcDN ) && !BER_BVISEMPTY( &li->idassert_authcDN ) ) + if ( !BER_BVISNULL( &li->idassert_authcDN ) && !BER_BVISEMPTY( &li->idassert_authcDN ) ) { binddn = li->idassert_authcDN; bindcred = li->idassert_passwd; + dobind = 1; } } break; @@ -432,20 +436,40 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) } } - if ( li->idassert_authmethod != LDAP_AUTH_SASL ) { - binddn = li->idassert_authcDN; - } + binddn = li->idassert_authcDN; bindcred = li->idassert_passwd; + dobind = 1; break; } - /* NOTE: essentially copied from clients/tools/common.c :) */ - switch ( li->idassert_authmethod ) { + if ( dobind && li->idassert_authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL - case LDAP_AUTH_SASL: - { void *defaults = NULL; struct berval authzID = BER_BVNULL; + int freeauthz = 0; + + switch ( li->idassert_mode ) { + case LDAP_BACK_IDASSERT_OTHERID: + case LDAP_BACK_IDASSERT_OTHERDN: + authzID = li->idassert_authzID; + break; + + case LDAP_BACK_IDASSERT_ANONYMOUS: + BER_BVSTR( &authzID, "dn:" ); + break; + + case LDAP_BACK_IDASSERT_SELF: + authzID.bv_len = STRLENOF( "dn:" ) + op->o_conn->c_dn.bv_len; + authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx ); + AC_MEMCPY( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ); + AC_MEMCPY( authzID.bv_val + STRLENOF( "dn:" ), + op->o_conn->c_dn.bv_val, op->o_conn->c_dn.bv_len + 1 ); + freeauthz = 1; + break; + + default: + break; + } #if 0 /* will deal with this later... */ if ( sasl_secprops != NULL ) { @@ -461,12 +485,6 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) } #endif - switch ( li->idassert_mode ) { - case LDAP_BACK_IDASSERT_OTHERID: - case LDAP_BACK_IDASSERT_OTHERDN: - authzID = li->idassert_authzID; - } - defaults = lutil_sasl_defaults( lc->ld, li->idassert_sasl_mech.bv_val, li->idassert_sasl_realm.bv_val, @@ -474,12 +492,15 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) li->idassert_passwd.bv_val, authzID.bv_val ); - rs->sr_err = ldap_sasl_interactive_bind_s( lc->ld, NULL, + rs->sr_err = ldap_sasl_interactive_bind_s( lc->ld, binddn.bv_val, li->idassert_sasl_mech.bv_val, NULL, NULL, li->idassert_sasl_flags, lutil_sasl_interact, defaults ); lutil_sasl_freedefs( defaults ); + if ( freeauthz ) { + slap_sl_free( authzID.bv_val, op->o_tmpmemctx ); + } rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err != LDAP_SUCCESS ) { @@ -490,9 +511,10 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) lc->bound = 1; } goto done; - } + } #endif /* HAVE_CYRUS_SASL */ + switch ( li->idassert_authmethod ) { case LDAP_AUTH_SIMPLE: rs->sr_err = ldap_sasl_bind(lc->ld, binddn.bv_val, LDAP_SASL_SIMPLE, @@ -714,7 +736,8 @@ ldap_back_proxy_authz_ctrl( *pctrls = NULL; - if ( BER_BVISNULL( &li->idassert_authcID ) ) { + if ( ( BER_BVISNULL( &li->idassert_authcID ) || BER_BVISEMPTY( &li->idassert_authcID ) ) + && ( BER_BVISNULL( &li->idassert_authcDN ) || BER_BVISEMPTY( &li->idassert_authcDN ) ) ) { goto done; } @@ -749,11 +772,11 @@ ldap_back_proxy_authz_ctrl( goto done; } - if ( BER_BVISEMPTY( &li->idassert_authcID ) ) { + if ( BER_BVISNULL( &li->idassert_authcDN ) || BER_BVISEMPTY( &li->idassert_authcDN ) ) { goto done; } - } else if ( li->idassert_mode == LDAP_BACK_IDASSERT_OTHERID && li->idassert_authmethod == LDAP_AUTH_SASL ) { + } else if ( li->idassert_authmethod == LDAP_AUTH_SASL ) { /* already asserted in SASL */ goto done; diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index a98431fe79..1b2da1c400 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -133,24 +133,26 @@ ldap_back_db_config( #endif /* name to use for ldap_back_group */ - } else if ( strcasecmp( argv[0], "binddn" ) == 0 ) { + } else if ( strcasecmp( argv[0], "acl-authcdn" ) == 0 + || strcasecmp( argv[0], "binddn" ) == 0 ) { if (argc != 2) { fprintf( stderr, - "%s: line %d: missing name in \"binddn \" line\n", - fname, lineno ); + "%s: line %d: missing name in \"%s \" line\n", + fname, lineno, argv[0] ); return( 1 ); } - ber_str2bv( argv[1], 0, 1, &li->binddn ); + ber_str2bv( argv[1], 0, 1, &li->acl_authcDN ); /* password to use for ldap_back_group */ - } else if ( strcasecmp( argv[0], "bindpw" ) == 0 ) { + } else if ( strcasecmp( argv[0], "acl-passwd" ) == 0 + || strcasecmp( argv[0], "bindpw" ) == 0 ) { if (argc != 2) { fprintf( stderr, - "%s: line %d: missing password in \"bindpw \" line\n", - fname, lineno ); + "%s: line %d: missing password in \"%s \" line\n", + fname, lineno, argv[0] ); return( 1 ); } - ber_str2bv( argv[1], 0, 1, &li->bindpw ); + ber_str2bv( argv[1], 0, 1, &li->acl_passwd ); #ifdef LDAP_BACK_PROXY_AUTHZ /* identity assertion stuff... */ @@ -721,7 +723,8 @@ parse_idassert( return 1; } - li->idassert_authzID.bv_val = ch_malloc( STRLENOF( "dn:" ) + dn.bv_len + 1 ); + li->idassert_authzID.bv_len = STRLENOF( "dn:" ) + dn.bv_len; + li->idassert_authzID.bv_val = ch_malloc( li->idassert_authzID.bv_len + 1 ); AC_MEMCPY( li->idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) ); AC_MEMCPY( &li->idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], dn.bv_val, dn.bv_len + 1 ); ch_free( dn.bv_val ); @@ -733,6 +736,9 @@ parse_idassert( /* name to use for proxyAuthz propagation */ } else if ( strcasecmp( argv[0], "idassert-authcdn" ) == 0 || strcasecmp( argv[0], "proxyauthzdn" ) == 0 ) { + struct berval dn; + int rc; + if ( argc != 2 ) { fprintf( stderr, "%s: line %d: missing name in \"%s \" line\n", @@ -740,13 +746,6 @@ parse_idassert( return( 1 ); } - if ( !BER_BVISNULL( &li->idassert_authcID ) ) { - fprintf( stderr, - "%s: line %d: authcDN incompatible with previously defined authcID\n", - fname, lineno ); - return( 1 ); - } - if ( !BER_BVISNULL( &li->idassert_authcDN ) ) { fprintf( stderr, "%s: line %d: " "authcDN already defined; replacing...\n", @@ -754,7 +753,20 @@ parse_idassert( ch_free( li->idassert_authcDN.bv_val ); } - ber_str2bv( argv[1], 0, 1, &li->idassert_authcDN ); + ber_str2bv( argv[1], 0, 0, &dn ); + rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL ); + if ( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, CRIT, + "%s: line %d: idassert ID \"%s\" is not a valid DN.\n", + fname, lineno, argv[1] ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: idassert ID \"%s\" is not a valid DN\n", + fname, lineno, argv[1] ); +#endif + return 1; + } /* password to use for proxyAuthz propagation */ } else if ( strcasecmp( argv[0], "idassert-passwd" ) == 0 @@ -837,16 +849,39 @@ parse_idassert( } ber_str2bv( val, 0, 1, &li->idassert_sasl_realm ); - } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) { - char *val = argv[arg] + STRLENOF( "authcid=" ); + } else if ( strncasecmp( argv[arg], "authcdn=", STRLENOF( "authcdn=" ) ) == 0 ) { + char *val = argv[arg] + STRLENOF( "authcdn=" ); + struct berval dn; + int rc; if ( !BER_BVISNULL( &li->idassert_authcDN ) ) { - fprintf( stderr, - "%s: line %d: SASL authcID incompatible with previously defined authcDN\n", - fname, lineno ); - return( 1 ); + fprintf( stderr, "%s: line %d: " + "SASL authcDN already defined; replacing...\n", + fname, lineno ); + ch_free( li->idassert_authcDN.bv_val ); + } + if ( strncasecmp( argv[arg], "dn:", STRLENOF( "dn:" ) ) == 0 ) { + val += STRLENOF( "dn:" ); } + ber_str2bv( val, 0, 0, &dn ); + rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL ); + if ( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG( CONFIG, CRIT, + "%s: line %d: SASL authcdn \"%s\" is not a valid DN.\n", + fname, lineno, val ); +#else + Debug( LDAP_DEBUG_ANY, + "%s: line %d: SASL authcdn \"%s\" is not a valid DN\n", + fname, lineno, val ); +#endif + return 1; + } + + } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) { + char *val = argv[arg] + STRLENOF( "authcid=" ); + if ( !BER_BVISNULL( &li->idassert_authcID ) ) { fprintf( stderr, "%s: line %d: " "SASL authcID already defined; replacing...\n", diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index 2a7ec51491..75870fac0b 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -98,8 +98,8 @@ ldap_back_db_init( return -1; } - BER_BVZERO( &li->binddn ); - BER_BVZERO( &li->bindpw ); + BER_BVZERO( &li->acl_authcDN ); + BER_BVZERO( &li->acl_passwd ); #ifdef LDAP_BACK_PROXY_AUTHZ li->idassert_mode = LDAP_BACK_IDASSERT_LEGACY; @@ -210,13 +210,13 @@ ldap_back_db_destroy( ldap_free_urldesc( li->lud ); li->lud = NULL; } - if ( !BER_BVISNULL( &li->binddn ) ) { - ch_free( li->binddn.bv_val ); - BER_BVZERO( &li->binddn ); + if ( !BER_BVISNULL( &li->acl_authcDN ) ) { + ch_free( li->acl_authcDN.bv_val ); + BER_BVZERO( &li->acl_authcDN ); } - if ( !BER_BVISNULL( &li->bindpw ) ) { - ch_free( li->bindpw.bv_val ); - BER_BVZERO( &li->bindpw ); + if ( !BER_BVISNULL( &li->acl_passwd ) ) { + ch_free( li->acl_passwd.bv_val ); + BER_BVZERO( &li->acl_passwd ); } #ifdef LDAP_BACK_PROXY_AUTHZ if ( !BER_BVISNULL( &li->idassert_authcID ) ) { diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 469d1cea87..9b12268b7a 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -368,12 +368,15 @@ ldap_build_entry( * * FIXME: should we log anything, or delegate to dnNormalize? */ + /* Note: if the distinguished values or the naming attributes + * change, should we massage them as well? + */ if ( dnNormalize( 0, NULL, NULL, &ent->e_name, &ent->e_nname, op->o_tmpmemctx ) != LDAP_SUCCESS ) { return LDAP_INVALID_DN_SYNTAX; } - + attrp = &ent->e_attrs; #ifdef ENABLE_REWRITE