]> git.sur5r.net Git - openldap/commitdiff
add SASL bind for acl-authc; use slap_bindconf
authorPierangelo Masarati <ando@openldap.org>
Sun, 10 Apr 2005 23:44:06 +0000 (23:44 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sun, 10 Apr 2005 23:44:06 +0000 (23:44 +0000)
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/chain.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/init.c

index 48b2e949ad14c4f1e718cfd72ec087037dbf5d00..0c0e826bdd4e6984cb5b4b826ed7318b912b81c0 100644 (file)
@@ -37,56 +37,53 @@ struct ldapconn {
        struct berval           lc_bound_ndn;
        struct berval           lc_local_ndn;
        int                     lc_bound;
+       int                     lc_ispriv;
        ldap_pvt_thread_mutex_t lc_mutex;
 };
 
-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;
-       
-#define LDAP_BACK_AUTH_NONE            0x00U
-#define        LDAP_BACK_AUTH_NATIVE_AUTHZ     0x01U
-#define        LDAP_BACK_AUTH_OVERRIDE         0x02U
-       unsigned        la_flags;
+/*
+ * identity assertion modes
+ */
+enum {
+       LDAP_BACK_IDASSERT_LEGACY,
+       LDAP_BACK_IDASSERT_NOASSERT,
+       LDAP_BACK_IDASSERT_ANONYMOUS,
+       LDAP_BACK_IDASSERT_SELF,
+       LDAP_BACK_IDASSERT_OTHERDN,
+       LDAP_BACK_IDASSERT_OTHERID
 };
 
 struct ldapinfo {
        char            *url;
        LDAPURLDesc     *lud;
-       struct ldapauth acl_la;
-#define        acl_authcDN     acl_la.la_authcDN
-#define        acl_passwd      acl_la.la_passwd
+
+       slap_bindconf   acl_la;
+#define        acl_authcID     acl_la.sb_authcId
+#define        acl_authcDN     acl_la.sb_binddn
+#define        acl_passwd      acl_la.sb_cred
+#define        acl_authzID     acl_la.sb_authzId
+#define        acl_authmethod  acl_la.sb_method
+#define        acl_sasl_mech   acl_la.sb_saslmech
+#define        acl_sasl_realm  acl_la.sb_realm
 
        /* ID assert stuff */
        int             idassert_mode;
-#define        LDAP_BACK_IDASSERT_LEGACY       0
-#define        LDAP_BACK_IDASSERT_NOASSERT     1
-#define        LDAP_BACK_IDASSERT_ANONYMOUS    2
-#define        LDAP_BACK_IDASSERT_SELF         3
-#define        LDAP_BACK_IDASSERT_OTHERDN      4
-#define        LDAP_BACK_IDASSERT_OTHERID      5
-
-       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
-#define        idassert_flags          idassert_la.la_flags
+
+       slap_bindconf   idassert_la;
+#define        idassert_authcID        idassert_la.sb_authcId
+#define        idassert_authcDN        idassert_la.sb_binddn
+#define        idassert_passwd         idassert_la.sb_cred
+#define        idassert_authzID        idassert_la.sb_authzId
+#define        idassert_authmethod     idassert_la.sb_method
+#define        idassert_sasl_mech      idassert_la.sb_saslmech
+#define        idassert_sasl_realm     idassert_la.sb_realm
+
+       unsigned        idassert_flags;
+#define LDAP_BACK_AUTH_NONE            0x00U
+#define        LDAP_BACK_AUTH_NATIVE_AUTHZ     0x01U
+#define        LDAP_BACK_AUTH_OVERRIDE         0x02U
+
        BerVarray       idassert_authz;
-       
-       int             idassert_ppolicy;
        /* end of ID assert stuff */
 
        ldap_pvt_thread_mutex_t         conn_mutex;
index 446ce1c458a74c0765857f0782154de1545b1d99..1371f865e7f526cb49d18bf5669f341b748492d3 100644 (file)
@@ -360,8 +360,7 @@ struct ldapconn *
 ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 {
        struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
-       struct ldapconn *lc, lc_curr;
-       int             is_priv = 0;
+       struct ldapconn *lc, lc_curr = { 0 };
 
        /* Searches for a ldapconn in the avl tree */
 
@@ -381,7 +380,7 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
        if ( op->o_do_not_cache || be_isroot( op ) ) {
                lc_curr.lc_local_ndn = op->o_bd->be_rootndn;
                lc_curr.lc_conn = NULL;
-               is_priv = 1;
+               lc_curr.lc_ispriv = 1;
 
        } else {
                lc_curr.lc_local_ndn = op->o_ndn;
@@ -404,9 +403,10 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 
                ldap_pvt_thread_mutex_init( &lc->lc_mutex );
 
-               if ( is_priv ) {
+               if ( lc_curr.lc_ispriv ) {
                        ber_dupbv( &lc->lc_cred, &li->acl_passwd );
                        ber_dupbv( &lc->lc_bound_ndn, &li->acl_authcDN );
+                       lc->lc_ispriv = lc_curr.lc_ispriv;
 
                } else {
                        BER_BVZERO( &lc->lc_cred );
@@ -498,6 +498,8 @@ ldap_back_dobind_int(
                 * It allows to use SASL bind and yet proxyAuthz users
                 */
                if ( op->o_conn != NULL &&
+                               !op->o_do_not_cache &&
+                               !be_isroot( op ) &&
                                ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
                                  ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
                {
@@ -505,6 +507,50 @@ ldap_back_dobind_int(
                        goto done;
                }
 
+#ifdef HAVE_CYRUS_SASL
+               if ( lc->lc_ispriv && li->acl_authmethod == LDAP_AUTH_SASL ) {
+                       void            *defaults = NULL;
+
+#if 0  /* will deal with this later... */
+                       if ( sasl_secprops != NULL ) {
+                               rs->sr_err = ldap_set_option( lc->lc_ld, LDAP_OPT_X_SASL_SECPROPS,
+                                       (void *) sasl_secprops );
+
+                               if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
+                                       send_ldap_result( op, rs );
+                                       lc->lc_bound = 0;
+                                       goto done;
+                               }
+                       }
+#endif
+
+                       defaults = lutil_sasl_defaults( lc->lc_ld,
+                                       li->acl_sasl_mech.bv_val,
+                                       li->acl_sasl_realm.bv_val,
+                                       li->acl_authcID.bv_val,
+                                       li->acl_passwd.bv_val,
+                                       NULL );
+
+                       rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld,
+                                       li->acl_authcDN.bv_val,
+                                       li->acl_sasl_mech.bv_val, NULL, NULL,
+                                       LDAP_SASL_QUIET, lutil_sasl_interact,
+                                       defaults );
+
+                       lutil_sasl_freedefs( defaults );
+
+                       rs->sr_err = slap_map_api2result( rs );
+                       if ( rs->sr_err != LDAP_SUCCESS ) {
+                               lc->lc_bound = 0;
+                               send_ldap_result( op, rs );
+
+                       } else {
+                               lc->lc_bound = 1;
+                       }
+                       goto done;
+               }
+#endif /* HAVE_CYRUS_SASL */
+
 retry:;
                rs->sr_err = ldap_sasl_bind( lc->lc_ld,
                                lc->lc_bound_ndn.bv_val,
@@ -803,7 +849,7 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
 
                rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld, binddn.bv_val,
                                li->idassert_sasl_mech.bv_val, NULL, NULL,
-                               li->idassert_sasl_flags, lutil_sasl_interact,
+                               LDAP_SASL_QUIET, lutil_sasl_interact,
                                defaults );
 
                lutil_sasl_freedefs( defaults );
@@ -898,7 +944,7 @@ ldap_back_proxy_authz_ctrl(
                goto done;
        }
 
-       if ( !op->o_conn ) {
+       if ( !op->o_conn || op->o_do_not_cache || be_isroot( op ) ) {
                goto done;
        }
 
index 543960f2280cd915791c327d9dc41c849d95f530..573ab84ebeb0be6a9caef20376c4acdb4e85d217 100644 (file)
@@ -350,7 +350,7 @@ done:;
 static int
 ldap_chain_response( Operation *op, SlapReply *rs )
 {
-       slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
        void            *private = op->o_bd->be_private;
        slap_callback   *sc = op->o_callback,
                        sc2 = { 0 };
index 436c713c573671045a21fc92d0b10032adbce3bb..6cd07ba40a502df64e5b3463706e8a6282b44774 100644 (file)
@@ -41,6 +41,10 @@ static int
 parse_idassert( BackendDB *be, const char *fname, int lineno,
                int argc, char **argv );
 
+static int
+parse_acl_auth( BackendDB *be, const char *fname, int lineno,
+               int argc, char **argv );
+
 int
 ldap_back_db_config(
                BackendDB       *be,
@@ -258,47 +262,14 @@ ldap_back_db_config(
                        li->flags |= LDAP_BACK_F_PROPAGATE_TLS;
                }
        
-       /* name to use for ldap_back_group */
-       } else if ( strcasecmp( argv[0], "acl-authcdn" ) == 0
-                       || strcasecmp( argv[0], "binddn" ) == 0 )
-       {
-               if ( argc != 2 ) {
-                       fprintf( stderr,
-       "%s: line %d: missing name in \"%s <name>\" line\n",
-                                       fname, lineno, argv[0] );
-                       return( 1 );
-               }
-
-               if ( strcasecmp( argv[0], "binddn" ) == 0 ) {
-                       fprintf( stderr, "%s: line %d: "
-                               "\"binddn\" statement is deprecated; "
-                               "use \"acl-authcDN\" instead\n",
-                               fname, lineno );
-                       /* FIXME: some day we'll need to throw an error */
-               }
-
-               ber_str2bv( argv[1], 0, 1, &li->acl_authcDN );
-
-       /* password to use for ldap_back_group */
-       } else if ( strcasecmp( argv[0], "acl-passwd" ) == 0
-                       || strcasecmp( argv[0], "bindpw" ) == 0 )
+       /* remote ACL stuff... */
+       } else if ( strncasecmp( argv[0], "acl-", STRLENOF( "acl-" ) ) == 0
+                       || strncasecmp( argv[0], "bind", STRLENOF( "bind" ) ) == 0 )
        {
-               if ( argc != 2 ) {
-                       fprintf( stderr,
-       "%s: line %d: missing password in \"%s <password>\" line\n",
-                                       fname, lineno, argv[0] );
-                       return( 1 );
-               }
-
-               if ( strcasecmp( argv[0], "bindpw" ) == 0 ) {
-                       fprintf( stderr, "%s: line %d: "
-                               "\"bindpw\" statement is deprecated; "
-                               "use \"acl-passwd\" instead\n",
-                               fname, lineno );
-                       /* FIXME: some day we'll need to throw an error */
-               }
-
-               ber_str2bv( argv[1], 0, 1, &li->acl_passwd );
+               /* NOTE: "bind{DN,pw}" was initially used; it's now
+                * deprected and undocumented, it can be dropped at some
+                * point, since nobody should be really using it */
+               return parse_acl_auth( be, fname, lineno, argc, argv );
 
        /* identity assertion stuff... */
        } else if ( strncasecmp( argv[0], "idassert-", STRLENOF( "idassert-" ) ) == 0
@@ -783,3 +754,205 @@ parse_idassert(
 
        return 0;
 }
+
+static int
+parse_acl_auth(
+    BackendDB  *be,
+    const char *fname,
+    int                lineno,
+    int                argc,
+    char       **argv
+)
+{
+       struct ldapinfo *li = (struct ldapinfo *) be->be_private;
+
+       /* name to use for remote ACL access */
+       if ( strcasecmp( argv[0], "acl-authcdn" ) == 0
+                       || strcasecmp( argv[0], "binddn" ) == 0 )
+       {
+               struct berval   dn;
+               int             rc;
+
+               /* FIXME: "binddn" is no longer documented, and
+                * temporarily supported for backwards compatibility */
+
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: missing name in \"%s <name>\" line\n",
+                           fname, lineno, argv[0] );
+                       return( 1 );
+               }
+
+               if ( !BER_BVISNULL( &li->acl_authcDN ) ) {
+                       fprintf( stderr, "%s: line %d: "
+                                       "authcDN already defined; replacing...\n",
+                                       fname, lineno );
+                       ch_free( li->acl_authcDN.bv_val );
+               }
+               
+               ber_str2bv( argv[1], 0, 0, &dn );
+               rc = dnNormalize( 0, NULL, NULL, &dn, &li->acl_authcDN, NULL );
+               if ( rc != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s: line %d: acl ID \"%s\" is not a valid DN\n",
+                               fname, lineno, argv[1] );
+                       return 1;
+               }
+
+       /* password to use for remote ACL access */
+       } else if ( strcasecmp( argv[0], "acl-passwd" ) == 0
+                       || strcasecmp( argv[0], "bindpw" ) == 0 )
+       {
+               /* FIXME: "bindpw" is no longer documented, and
+                * temporarily supported for backwards compatibility */
+
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: missing password in \"%s <password>\" line\n",
+                           fname, lineno, argv[0] );
+                       return( 1 );
+               }
+
+               if ( !BER_BVISNULL( &li->acl_passwd ) ) {
+                       fprintf( stderr, "%s: line %d: "
+                                       "passwd already defined; replacing...\n",
+                                       fname, lineno );
+                       ch_free( li->acl_passwd.bv_val );
+               }
+               
+               ber_str2bv( argv[1], 0, 1, &li->acl_passwd );
+
+       } else if ( strcasecmp( argv[0], "acl-method" ) == 0 ) {
+               if ( argc < 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: missing method in \"%s <method>\" line\n",
+                           fname, lineno, argv[0] );
+                       return( 1 );
+               }
+
+               if ( strcasecmp( argv[1], "none" ) == 0 ) {
+                       /* FIXME: is this at all useful? */
+                       li->acl_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->acl_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->acl_sasl_mech ) ) {
+                                               fprintf( stderr, "%s: line %d: "
+                                                               "SASL mech already defined; replacing...\n",
+                                                               fname, lineno );
+                                               ch_free( li->acl_sasl_mech.bv_val );
+                                       }
+                                       ber_str2bv( val, 0, 1, &li->acl_sasl_mech );
+
+                               } else if ( strncasecmp( argv[arg], "realm=", STRLENOF( "realm=" ) ) == 0 ) {
+                                       char    *val = argv[arg] + STRLENOF( "realm=" );
+
+                                       if ( !BER_BVISNULL( &li->acl_sasl_realm ) ) {
+                                               fprintf( stderr, "%s: line %d: "
+                                                               "SASL realm already defined; replacing...\n",
+                                                               fname, lineno );
+                                               ch_free( li->acl_sasl_realm.bv_val );
+                                       }
+                                       ber_str2bv( val, 0, 1, &li->acl_sasl_realm );
+
+                               } else if ( strncasecmp( argv[arg], "authcdn=", STRLENOF( "authcdn=" ) ) == 0 ) {
+                                       char            *val = argv[arg] + STRLENOF( "authcdn=" );
+                                       struct berval   dn;
+                                       int             rc;
+
+                                       if ( !BER_BVISNULL( &li->acl_authcDN ) ) {
+                                               fprintf( stderr, "%s: line %d: "
+                                                               "SASL authcDN already defined; replacing...\n",
+                                                               fname, lineno );
+                                               ch_free( li->acl_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->acl_authcDN, NULL );
+                                       if ( rc != LDAP_SUCCESS ) {
+                                               Debug( LDAP_DEBUG_ANY,
+                                                       "%s: line %d: SASL authcdn \"%s\" is not a valid DN\n",
+                                                       fname, lineno, val );
+                                               return 1;
+                                       }
+
+                               } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) {
+                                       char    *val = argv[arg] + STRLENOF( "authcid=" );
+
+                                       if ( !BER_BVISNULL( &li->acl_authcID ) ) {
+                                               fprintf( stderr, "%s: line %d: "
+                                                               "SASL authcID already defined; replacing...\n",
+                                                               fname, lineno );
+                                               ch_free( li->acl_authcID.bv_val );
+                                       }
+                                       if ( strncasecmp( argv[arg], "u:", STRLENOF( "u:" ) ) == 0 ) {
+                                               val += STRLENOF( "u:" );
+                                       }
+                                       ber_str2bv( val, 0, 1, &li->acl_authcID );
+
+                               } else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) {
+                                       char    *val = argv[arg] + STRLENOF( "cred=" );
+
+                                       if ( !BER_BVISNULL( &li->acl_passwd ) ) {
+                                               fprintf( stderr, "%s: line %d: "
+                                                               "SASL cred already defined; replacing...\n",
+                                                               fname, lineno );
+                                               ch_free( li->acl_passwd.bv_val );
+                                       }
+                                       ber_str2bv( val, 0, 1, &li->acl_passwd );
+
+                               } else {
+                                       fprintf( stderr, "%s: line %d: "
+                                                       "unknown SASL parameter %s\n",
+                                                       fname, lineno, argv[arg] );
+                                       return 1;
+                               }
+                       }
+
+                       li->acl_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 acl-method method %s\n",
+                                       fname, lineno, argv[1] );
+                       return 1;
+               }
+
+       } else {
+               return SLAP_CONF_UNKNOWN;
+       }
+
+       return 0;
+}
+
index 08767a481123c2e4264e0c34ffd67c5a10518f20..328e3ceaa8ecb1506205e4dd0d5df7ff77bcb19f 100644 (file)
@@ -87,9 +87,13 @@ ldap_back_db_init( Backend *be )
                return -1;
        }
 
+       BER_BVZERO( &li->acl_authcID );
        BER_BVZERO( &li->acl_authcDN );
        BER_BVZERO( &li->acl_passwd );
 
+       li->acl_authmethod = LDAP_AUTH_SIMPLE;
+       BER_BVZERO( &li->acl_sasl_mech );
+
        li->idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
 
        BER_BVZERO( &li->idassert_authcID );
@@ -97,18 +101,15 @@ ldap_back_db_init( Backend *be )
        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;
 
        /* by default, use proxyAuthz control on each operation */
        li->idassert_flags = LDAP_BACK_AUTH_NONE;
 
+       li->idassert_authz = NULL;
+
        /* initialize flags */
        li->flags = LDAP_BACK_F_CHASE_REFERRALS;
 
@@ -217,6 +218,10 @@ ldap_back_db_destroy(
                        ldap_free_urldesc( li->lud );
                        li->lud = NULL;
                }
+               if ( !BER_BVISNULL( &li->acl_authcID ) ) {
+                       ch_free( li->acl_authcID.bv_val );
+                       BER_BVZERO( &li->acl_authcID );
+               }
                if ( !BER_BVISNULL( &li->acl_authcDN ) ) {
                        ch_free( li->acl_authcDN.bv_val );
                        BER_BVZERO( &li->acl_authcDN );
@@ -225,6 +230,14 @@ ldap_back_db_destroy(
                        ch_free( li->acl_passwd.bv_val );
                        BER_BVZERO( &li->acl_passwd );
                }
+               if ( !BER_BVISNULL( &li->acl_sasl_mech ) ) {
+                       ch_free( li->acl_sasl_mech.bv_val );
+                       BER_BVZERO( &li->acl_sasl_mech );
+               }
+               if ( !BER_BVISNULL( &li->acl_sasl_realm ) ) {
+                       ch_free( li->acl_sasl_realm.bv_val );
+                       BER_BVZERO( &li->acl_sasl_realm );
+               }
                if ( !BER_BVISNULL( &li->idassert_authcID ) ) {
                        ch_free( li->idassert_authcID.bv_val );
                        BER_BVZERO( &li->idassert_authcID );