From: Pierangelo Masarati Date: Sat, 15 May 2004 10:11:10 +0000 (+0000) Subject: more on idassert: SASL bind/authz X-Git-Tag: OPENDLAP_REL_ENG_2_2_MP~366 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=cdebc4d376453007c8c80942a40faee054552fad;p=openldap more on idassert: SASL bind/authz --- diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 96e8ef5af4..2697340a1e 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -89,9 +89,6 @@ struct ldapinfo { struct berval binddn; struct berval bindpw; #ifdef LDAP_BACK_PROXY_AUTHZ - struct berval proxyauthzdn; - struct berval proxyauthzpw; - /* ID assert stuff */ int idassert_mode; #define LDAP_BACK_IDASSERT_LEGACY 0 @@ -100,8 +97,20 @@ struct ldapinfo { #define LDAP_BACK_IDASSERT_SELF 3 #define LDAP_BACK_IDASSERT_OTHERDN 4 #define LDAP_BACK_IDASSERT_OTHERID 5 - struct berval idassert_id; + + struct berval idassert_authcID; + struct berval idassert_authcDN; + struct berval idassert_passwd; + + struct berval idassert_authzID; 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 26e94c62c0..4d91afe8b6 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -28,11 +28,12 @@ #include #include - #define AVL_INTERNAL #include "slap.h" #include "back-ldap.h" +#include + #define PRINT_CONNTREE 0 static LDAP_REBIND_PROC ldap_back_rebind; @@ -408,11 +409,13 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) * 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 ) - && !BER_BVISNULL( &li->proxyauthzdn ) && !BER_BVISEMPTY( &li->proxyauthzdn ) ) - { - binddn = li->proxyauthzdn; - bindcred = li->proxyauthzpw; + 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 ) ) + { + binddn = li->idassert_authcDN; + bindcred = li->idassert_passwd; + } } break; @@ -428,13 +431,85 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) goto done; } } - binddn = li->proxyauthzdn; - bindcred = li->proxyauthzpw; + + if ( li->idassert_authmethod != LDAP_AUTH_SASL ) { + binddn = li->idassert_authcDN; + } + bindcred = li->idassert_passwd; break; } - rs->sr_err = ldap_sasl_bind(lc->ld, binddn.bv_val, - LDAP_SASL_SIMPLE, &bindcred, NULL, NULL, &msgid); + /* NOTE: essentially copied from clients/tools/common.c :) */ + switch ( li->idassert_authmethod ) { +#ifdef HAVE_CYRUS_SASL + case LDAP_AUTH_SASL: + { + void *defaults = NULL; + struct berval authzID = BER_BVNULL; + +#if 0 /* will deal with this later... */ + if ( sasl_secprops != NULL ) { + rs->sr_err = ldap_set_option( lc->ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if ( rs->sr_err != LDAP_OPT_SUCCESS ) { + send_ldap_result( op, rs ); + lc->bound = 0; + goto done; + + } + } +#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, + li->idassert_authcID.bv_val, + li->idassert_passwd.bv_val, + authzID.bv_val ); + + rs->sr_err = ldap_sasl_interactive_bind_s( lc->ld, NULL, + li->idassert_sasl_mech.bv_val, NULL, NULL, + li->idassert_sasl_flags, lutil_sasl_interact, + defaults ); + + lutil_sasl_freedefs( defaults ); + + rs->sr_err = slap_map_api2result( rs ); + if ( rs->sr_err != LDAP_SUCCESS ) { + lc->bound = 0; + send_ldap_result( op, rs ); + + } else { + lc->bound = 1; + } + goto done; + } +#endif /* HAVE_CYRUS_SASL */ + + case LDAP_AUTH_SIMPLE: + rs->sr_err = ldap_sasl_bind(lc->ld, + binddn.bv_val, LDAP_SASL_SIMPLE, + &bindcred, NULL, NULL, &msgid); + break; + + case LDAP_AUTH_NONE: + lc->bound = 1; + goto done; + + default: + /* unsupported! */ + lc->bound = 0; + rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED; + send_ldap_result( op, rs ); + goto done; + } } else #endif /* LDAP_BACK_PROXY_AUTHZ */ @@ -639,7 +714,7 @@ ldap_back_proxy_authz_ctrl( *pctrls = NULL; - if ( BER_BVISNULL( &li->proxyauthzdn ) ) { + if ( BER_BVISNULL( &li->idassert_authcID ) ) { goto done; } @@ -674,10 +749,14 @@ ldap_back_proxy_authz_ctrl( goto done; } - if ( BER_BVISEMPTY( &li->proxyauthzdn ) ) { + if ( BER_BVISEMPTY( &li->idassert_authcID ) ) { goto done; } + } else if ( li->idassert_mode == LDAP_BACK_IDASSERT_OTHERID && li->idassert_authmethod == LDAP_AUTH_SASL ) { + /* already asserted in SASL */ + goto done; + } else if ( li->idassert_authz ) { int rc; struct berval authcDN = BER_BVISNULL( &op->o_conn->c_dn ) ? slap_empty_bv : op->o_conn->c_dn; @@ -712,7 +791,7 @@ ldap_back_proxy_authz_ctrl( case LDAP_BACK_IDASSERT_OTHERID: case LDAP_BACK_IDASSERT_OTHERDN: /* assert idassert DN */ - assertedID = li->idassert_id; + assertedID = li->idassert_authzID; break; default: @@ -729,17 +808,21 @@ ldap_back_proxy_authz_ctrl( ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; ctrls[ 0 ]->ldctl_iscritical = 1; - /* already in u:ID form */ - if ( li->idassert_mode == LDAP_BACK_IDASSERT_OTHERID ) { + switch ( li->idassert_mode ) { + /* already in u:ID or dn:DN form */ + case LDAP_BACK_IDASSERT_OTHERID: + case LDAP_BACK_IDASSERT_OTHERDN: ber_dupbv( &ctrls[ 0 ]->ldctl_value, &assertedID ); + break; /* needs the dn: prefix */ - } else { + default: ctrls[ 0 ]->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" ); ctrls[ 0 ]->ldctl_value.bv_val = ch_malloc( ctrls[ 0 ]->ldctl_value.bv_len + 1 ); 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; } if ( op->o_ctrls ) { diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index b83405e244..a98431fe79 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -153,28 +153,9 @@ ldap_back_db_config( ber_str2bv( argv[1], 0, 1, &li->bindpw ); #ifdef LDAP_BACK_PROXY_AUTHZ - /* name to use for proxyAuthz propagation */ - } else if ( strcasecmp( argv[0], "proxyauthzdn" ) == 0 ) { - if (argc != 2) { - fprintf( stderr, - "%s: line %d: missing name in \"proxyauthzdn \" line\n", - fname, lineno ); - return( 1 ); - } - ber_str2bv( argv[1], 0, 1, &li->proxyauthzdn ); - - /* password to use for proxyAuthz propagation */ - } else if ( strcasecmp( argv[0], "proxyauthzpw" ) == 0 ) { - if (argc != 2) { - fprintf( stderr, - "%s: line %d: missing password in \"proxyauthzpw \" line\n", - fname, lineno ); - return( 1 ); - } - ber_str2bv( argv[1], 0, 1, &li->proxyauthzpw ); - /* identity assertion stuff... */ - } else if ( strncasecmp( argv[0], "idassert-", STRLENOF( "idassert-" ) ) == 0 ) { + } else if ( strncasecmp( argv[0], "idassert-", STRLENOF( "idassert-" ) ) == 0 + || strncasecmp( argv[0], "proxyauthz", STRLENOF( "proxyauthz" ) ) == 0 ) { return parse_idassert( be, fname, lineno, argc, argv ); #endif /* LDAP_BACK_PROXY_AUTHZ */ @@ -673,6 +654,7 @@ parse_idassert( { struct ldapinfo *li = (struct ldapinfo *) be->be_private; + /* identity assertion mode */ if ( strcasecmp( argv[0], "idassert-mode" ) == 0 ) { if ( argc != 2 ) { #ifdef NEW_LOGGING @@ -714,16 +696,18 @@ parse_idassert( /* force lowercase... */ id.bv_val[0] = 'u'; li->idassert_mode = LDAP_BACK_IDASSERT_OTHERID; - ber_dupbv( &li->idassert_id, &id ); + ber_dupbv( &li->idassert_authzID, &id ); } else { + struct berval dn; + /* default is DN? */ if ( strncasecmp( id.bv_val, "dn:", STRLENOF( "dn:" ) ) == 0 ) { id.bv_val += STRLENOF( "dn:" ); id.bv_len -= STRLENOF( "dn:" ); } - rc = dnNormalize( 0, NULL, NULL, &id, &li->idassert_id, NULL ); + rc = dnNormalize( 0, NULL, NULL, &id, &dn, NULL ); if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( CONFIG, CRIT, @@ -737,10 +721,61 @@ parse_idassert( return 1; } + li->idassert_authzID.bv_val = ch_malloc( STRLENOF( "dn:" ) + dn.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 ); + li->idassert_mode = LDAP_BACK_IDASSERT_OTHERDN; } } + /* name to use for proxyAuthz propagation */ + } else if ( strcasecmp( argv[0], "idassert-authcdn" ) == 0 + || strcasecmp( argv[0], "proxyauthzdn" ) == 0 ) { + if ( argc != 2 ) { + fprintf( stderr, + "%s: line %d: missing name in \"%s \" line\n", + fname, lineno, argv[0] ); + 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", + fname, lineno ); + ch_free( li->idassert_authcDN.bv_val ); + } + + ber_str2bv( argv[1], 0, 1, &li->idassert_authcDN ); + + /* password to use for proxyAuthz propagation */ + } else if ( strcasecmp( argv[0], "idassert-passwd" ) == 0 + || strcasecmp( argv[0], "proxyauthzpw" ) == 0 ) { + if ( argc != 2 ) { + fprintf( stderr, + "%s: line %d: missing password in \"%s \" line\n", + fname, lineno, argv[0] ); + return( 1 ); + } + + if ( !BER_BVISNULL( &li->idassert_passwd ) ) { + fprintf( stderr, "%s: line %d: " + "passwd already defined; replacing...\n", + fname, lineno ); + ch_free( li->idassert_passwd.bv_val ); + } + + ber_str2bv( argv[1], 0, 1, &li->idassert_passwd ); + + /* rules to accept identity assertion... */ } else if ( strcasecmp( argv[0], "idassert-authz" ) == 0 ) { struct berval rule; @@ -748,6 +783,116 @@ parse_idassert( ber_bvarray_add( &li->idassert_authz, &rule ); + } else if ( strcasecmp( argv[0], "idassert-method" ) == 0 ) { + if ( argc < 2 ) { + fprintf( stderr, + "%s: line %d: missing method in \"%s \" line\n", + fname, lineno, argv[0] ); + return( 1 ); + } + + if ( strcasecmp( argv[1], "none" ) == 0 ) { + /* FIXME: is this useful? */ + li->idassert_authmethod = LDAP_AUTH_NONE; + + if ( argc != 2 ) { + fprintf( stderr, + "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n", + fname, lineno, argv[0], argv[1] ); + } + + } else if ( strcasecmp( argv[1], "simple" ) == 0 ) { + li->idassert_authmethod = LDAP_AUTH_SIMPLE; + + if ( argc != 2 ) { + fprintf( stderr, + "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n", + fname, lineno, argv[0], argv[1] ); + } + + } else if ( strcasecmp( argv[1], "sasl" ) == 0 ) { +#ifdef HAVE_CYRUS_SASL + int arg; + + for ( arg = 2; arg < argc; arg++ ) { + if ( strncasecmp( argv[arg], "mech=", STRLENOF( "mech=" ) ) == 0 ) { + char *val = argv[arg] + STRLENOF( "mech=" ); + + if ( !BER_BVISNULL( &li->idassert_sasl_mech ) ) { + fprintf( stderr, "%s: line %d: " + "SASL mech already defined; replacing...\n", + fname, lineno ); + ch_free( li->idassert_sasl_mech.bv_val ); + } + ber_str2bv( val, 0, 1, &li->idassert_sasl_mech ); + + } else if ( strncasecmp( argv[arg], "realm=", STRLENOF( "realm=" ) ) == 0 ) { + char *val = argv[arg] + STRLENOF( "realm=" ); + + if ( !BER_BVISNULL( &li->idassert_sasl_realm ) ) { + fprintf( stderr, "%s: line %d: " + "SASL realm already defined; replacing...\n", + fname, lineno ); + ch_free( li->idassert_sasl_realm.bv_val ); + } + ber_str2bv( val, 0, 1, &li->idassert_sasl_realm ); + + } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) { + char *val = argv[arg] + STRLENOF( "authcid=" ); + + if ( !BER_BVISNULL( &li->idassert_authcDN ) ) { + fprintf( stderr, + "%s: line %d: SASL authcID incompatible with previously defined authcDN\n", + fname, lineno ); + return( 1 ); + } + + if ( !BER_BVISNULL( &li->idassert_authcID ) ) { + fprintf( stderr, "%s: line %d: " + "SASL authcID already defined; replacing...\n", + fname, lineno ); + ch_free( li->idassert_authcID.bv_val ); + } + if ( strncasecmp( argv[arg], "u:", STRLENOF( "u:" ) ) == 0 ) { + val += STRLENOF( "u:" ); + } + ber_str2bv( val, 0, 1, &li->idassert_authcID ); + + } else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) { + char *val = argv[arg] + STRLENOF( "cred=" ); + + if ( !BER_BVISNULL( &li->idassert_passwd ) ) { + fprintf( stderr, "%s: line %d: " + "SASL cred already defined; replacing...\n", + fname, lineno ); + ch_free( li->idassert_passwd.bv_val ); + } + ber_str2bv( val, 0, 1, &li->idassert_passwd ); + + } else { + fprintf( stderr, "%s: line %d: " + "unknown SASL parameter %s\n", + fname, lineno, argv[arg] ); + return 1; + } + } + + li->idassert_authmethod = LDAP_AUTH_SASL; + +#else /* !HAVE_CYRUS_SASL */ + fprintf( stderr, "%s: line %d: " + "compile --with-cyrus-sasl to enable SASL auth\n", + fname, lineno ); + return 1; +#endif /* !HAVE_CYRUS_SASL */ + + } else { + fprintf( stderr, "%s: line %d: " + "unhandled auth method %s\n", + fname, lineno ); + return 1; + } + } else { return SLAP_CONF_UNKNOWN; } diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index 4645b5195e..2a7ec51491 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -102,11 +102,21 @@ ldap_back_db_init( BER_BVZERO( &li->bindpw ); #ifdef LDAP_BACK_PROXY_AUTHZ - BER_BVZERO( &li->proxyauthzdn ); - BER_BVZERO( &li->proxyauthzpw ); - li->idassert_mode = LDAP_BACK_IDASSERT_LEGACY; - BER_BVZERO( &li->idassert_id ); + + BER_BVZERO( &li->idassert_authcID ); + BER_BVZERO( &li->idassert_authcDN ); + BER_BVZERO( &li->idassert_passwd ); + + BER_BVZERO( &li->idassert_authzID ); + li->idassert_authz = NULL; + + li->idassert_authmethod = LDAP_AUTH_SIMPLE; + li->idassert_sasl_flags = LDAP_SASL_QUIET; + BER_BVZERO( &li->idassert_sasl_mech ); + BER_BVZERO( &li->idassert_sasl_realm ); + + li->idassert_ppolicy = 0; #endif /* LDAP_BACK_PROXY_AUTHZ */ #ifdef ENABLE_REWRITE @@ -209,17 +219,29 @@ ldap_back_db_destroy( BER_BVZERO( &li->bindpw ); } #ifdef LDAP_BACK_PROXY_AUTHZ - if ( !BER_BVISNULL( &li->proxyauthzdn ) ) { - ch_free( li->proxyauthzdn.bv_val ); - BER_BVZERO( &li->proxyauthzdn ); + if ( !BER_BVISNULL( &li->idassert_authcID ) ) { + ch_free( li->idassert_authcID.bv_val ); + BER_BVZERO( &li->idassert_authcID ); + } + if ( !BER_BVISNULL( &li->idassert_authcDN ) ) { + ch_free( li->idassert_authcDN.bv_val ); + BER_BVZERO( &li->idassert_authcDN ); + } + if ( !BER_BVISNULL( &li->idassert_passwd ) ) { + ch_free( li->idassert_passwd.bv_val ); + BER_BVZERO( &li->idassert_passwd ); + } + if ( !BER_BVISNULL( &li->idassert_authzID ) ) { + ch_free( li->idassert_authzID.bv_val ); + BER_BVZERO( &li->idassert_authzID ); } - if ( !BER_BVISNULL( &li->proxyauthzpw ) ) { - ch_free( li->proxyauthzpw.bv_val ); - BER_BVZERO( &li->proxyauthzpw ); + if ( !BER_BVISNULL( &li->idassert_sasl_mech ) ) { + ch_free( li->idassert_sasl_mech.bv_val ); + BER_BVZERO( &li->idassert_sasl_mech ); } - if ( !BER_BVISNULL( &li->idassert_id ) ) { - ch_free( li->idassert_id.bv_val ); - BER_BVZERO( &li->idassert_id ); + if ( !BER_BVISNULL( &li->idassert_sasl_realm ) ) { + ch_free( li->idassert_sasl_realm.bv_val ); + BER_BVZERO( &li->idassert_sasl_realm ); } #endif /* LDAP_BACK_PROXY_AUTHZ */ if (li->conntree) {