]> git.sur5r.net Git - openldap/commitdiff
More bind changes to support SASL/DIGEST.
authorKurt Zeilenga <kurt@openldap.org>
Fri, 2 Jul 1999 19:48:07 +0000 (19:48 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Fri, 2 Jul 1999 19:48:07 +0000 (19:48 +0000)
Added configuration support for "digest-realm <realm>" configure directive.
Added connection state and bind_in_progress fields to cn=monitor connection
attribute.

servers/slapd/backend.c
servers/slapd/bind.c
servers/slapd/config.c
servers/slapd/connection.c
servers/slapd/monitor.c
servers/slapd/proto-slap.h
servers/slapd/slap.h

index 5b5a1f5db822bd99866ab50a86b9ac3777a34059..74cc285665f02cc831d39a6de604d08c924520a0 100644 (file)
@@ -385,6 +385,9 @@ backend_db_init(
        be->be_sizelimit = defsize;
        be->be_timelimit = deftime;
 
+       be->be_realm = global_realm != NULL
+               ? ch_strdup( global_realm ) : NULL;
+
        if(bi->bi_db_init) {
                rc = bi->bi_db_init( be );
        }
index bb9ccd3e1638a431ac888853c60f9ccad3cebadd..8a11db02b0b5a024edd5264a9c9a3b088e1891ea 100644 (file)
@@ -39,7 +39,7 @@ do_bind(
        char            *mech;
        char            *cdn, *ndn;
        ber_tag_t       tag;
-       int                     rc;
+       int                     rc = LDAP_SUCCESS;
        struct berval   cred;
        Backend         *be;
 
@@ -50,6 +50,25 @@ do_bind(
        mech = NULL;
        cred.bv_val = NULL;
 
+       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+       /* Force to connection to "anonymous" until bind succeeds.
+        * This may need to be relocated or done on a case by case basis
+        * to handle certain SASL mechanisms.
+        */
+
+       if ( conn->c_cdn != NULL ) {
+               free( conn->c_cdn );
+               conn->c_cdn = NULL;
+       }
+
+       if ( conn->c_dn != NULL ) {
+               free( conn->c_dn );
+               conn->c_dn = NULL;
+       }
+
+       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
        /*
         * Parse the bind request.  It looks like this:
         *
@@ -59,8 +78,14 @@ do_bind(
         *              authentication  CHOICE {
         *                      simple          [0] OCTET STRING -- passwd
         *                      krbv42ldap      [1] OCTET STRING
-        *                      krbv42dsa       [1] OCTET STRING
+        *                      krbv42dsa       [2] OCTET STRING
+        *                      SASL            [3] SaslCredentials
         *              }
+        *      }
+        *
+        *      SaslCredentials ::= SEQUENCE {
+     *         mechanism           LDAPString,
+     *         credentials         OCTET STRING OPTIONAL
         *      }
         */
 
@@ -152,26 +177,58 @@ do_bind(
                                NULL, "sasl mechanism not supported" );
                        goto cleanup;
                }
-       }
 
-       /* accept null binds */
-       if ( ndn == NULL || *ndn == '\0' ) {
                ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
-               conn->c_protocol = version;
+               if ( conn->c_authmech != NULL ) {
+                       assert( conn->c_bind_in_progress );
+
+                       if((strcmp(conn->c_authmech, mech) != 0)) {
+                               /* mechanism changed, cancel in progress bind */
+                               conn->c_bind_in_progress = 0;
+                               if( conn->c_authstate != NULL ) {
+                                       free(conn->c_authstate);
+                                       conn->c_authstate = NULL;
+                               }
+                               free(conn->c_authmech);
+                               conn->c_authmech = NULL;
+                       }
 
-               if ( conn->c_cdn != NULL ) {
-                       free( conn->c_cdn );
-                       conn->c_cdn = NULL;
+#ifdef LDAP_DEBUG
+               } else {
+                       assert( !conn->c_bind_in_progress );
+                       assert( conn->c_authmech == NULL );
+                       assert( conn->c_authstate == NULL );
+#endif
                }
 
-               if ( conn->c_dn != NULL ) {
-                       free( conn->c_dn );
-                       conn->c_dn = NULL;
+       } else {
+               ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+               if ( conn->c_authmech != NULL ) {
+                       assert( conn->c_bind_in_progress );
+
+                       /* cancel in progress bind */
+                       conn->c_bind_in_progress = 0;
+
+                       if( conn->c_authstate != NULL ) {
+                               free(conn->c_authstate);
+                               conn->c_authstate = NULL;
+                       }
+                       free(conn->c_authmech);
+                       conn->c_authmech = NULL;
                }
+       }
 
-               ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+       conn->c_protocol = version;
+       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
+       /* accept null binds */
+       if ( ndn == NULL || *ndn == '\0' ) {
+               /*
+                * we already forced connection to "anonymous", we just
+                * need to send success
+                */
                send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
                goto cleanup;
        }
@@ -184,27 +241,13 @@ do_bind(
 
        if ( (be = select_backend( ndn )) == NULL ) {
                if ( cred.bv_len == 0 ) {
-                       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
-
-                       conn->c_protocol = version;
-
-                       if ( conn->c_cdn != NULL ) {
-                               free( conn->c_cdn );
-                               conn->c_cdn = NULL;
-                       }
-
-                       if ( conn->c_dn != NULL ) {
-                               free( conn->c_dn );
-                               conn->c_dn = NULL;
-                       }
-
-                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-
                        send_ldap_result( conn, op, LDAP_SUCCESS,
                                NULL, NULL );
+
                } else if ( default_referral && *default_referral ) {
                        send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS,
                                NULL, default_referral );
+
                } else {
                        send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
                                NULL, default_referral );
@@ -222,19 +265,9 @@ do_bind(
                if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) {
                        ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
-                       conn->c_protocol = version;
-
-                       if ( conn->c_cdn != NULL ) {
-                               free( conn->c_cdn );
-                       }
-
                        conn->c_cdn = cdn;
                        cdn = NULL;
 
-                       if ( conn->c_dn != NULL ) {
-                               free( conn->c_dn );
-                       }
-
                        if(edn != NULL) {
                                conn->c_dn = edn;
                        } else {
index 45b25b9d40415ade069d2807dd53be29eff4db42..f2f0cd79a00d90f4d93205d382d263a9fe1fcfab 100644 (file)
@@ -26,6 +26,7 @@ int           global_default_access = ACL_READ;
 char           *replogfile;
 int            global_lastmod;
 int            global_idletimeout = 0;
+char   *global_realm = NULL;
 char           *ldap_srvtab = "";
 
 char   *slapd_pid_file  = NULL;
@@ -144,7 +145,28 @@ read_config( char *fname )
 
                        slapd_args_file = ch_strdup( cargv[1] );
 
-               /* set size limit */
+               /* set DIGEST realm */
+               } else if ( strcasecmp( cargv[0], "digest-realm" ) == 0 ) {
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY,
+           "%s: line %d: missing realm in \"digest-realm <realm>\" line\n",
+                                   fname, lineno, 0 );
+                               return( 1 );
+                       }
+                       if ( be != NULL ) {
+                               be->be_realm = ch_strdup( cargv[1] );
+
+                       } else if ( global_realm != NULL ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "%s: line %d: already set global realm!\n",
+                                       fname, lineno, 0 );
+                               return 1;
+
+                       } else {
+                               global_realm = ch_strdup( cargv[1] );
+                       }
+
+               /* set time limit */
                } else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
                        if ( cargc < 2 ) {
                                Debug( LDAP_DEBUG_ANY,
index 1df8b52800fdbdb7d693266733b6506d08ff7953..a8c6e26fb858ae8ea979b0e762c5c3e5caf3987c 100644 (file)
@@ -30,6 +30,18 @@ static unsigned long conn_nextid = 0;
 #define SLAP_C_BINDING                 0x03    /* binding */
 #define SLAP_C_CLOSING                 0x04    /* closing */
 
+char* connection_state2str( int state ) {
+       switch( state ) {
+       case SLAP_C_INVALID:    return "!";             
+       case SLAP_C_INACTIVE:   return "|";             
+       case SLAP_C_ACTIVE:             return "";                      
+       case SLAP_C_BINDING:    return "B";
+       case SLAP_C_CLOSING:    return "C";                     
+       }
+
+       return "?";
+}
+
 static Connection* connection_get( ber_socket_t s );
 
 static int connection_input( Connection *c );
@@ -326,6 +338,8 @@ long connection_init(
         c->c_client_addr = NULL;
         c->c_ops = NULL;
         c->c_pending_ops = NULL;
+               c->c_authmech = NULL;
+               c->c_authstate = NULL;
 
         c->c_sb = ber_sockbuf_alloc( );
 
@@ -346,6 +360,8 @@ long connection_init(
     assert( c->c_client_addr == NULL );
     assert( c->c_ops == NULL );
     assert( c->c_pending_ops == NULL );
+       assert( c->c_authmech == NULL );
+       assert( c->c_authstate == NULL );
 
     c->c_client_name = ch_strdup( name == NULL ? "" : name );
     c->c_client_addr = ch_strdup( addr );
@@ -416,6 +432,14 @@ connection_destroy( Connection *c )
                free(c->c_client_addr);
                c->c_client_addr = NULL;
        }
+       if(c->c_authmech != NULL ) {
+               free(c->c_authmech);
+               c->c_authmech = NULL;
+       }
+       if(c->c_authstate != NULL ) {
+               free(c->c_authstate);
+               c->c_authstate = NULL;
+       }
 
        if ( ber_pvt_sb_in_use(c->c_sb) ) {
                int sd = ber_pvt_sb_get_desc(c->c_sb);
@@ -916,10 +940,10 @@ static int connection_op_activate( Connection *conn, Operation *op )
 
        arg->co_op->o_protocol = conn->c_protocol;
 
+       arg->co_op->o_authtype = conn->c_authtype;
        arg->co_op->o_authmech = conn->c_authmech != NULL
                ?  ch_strdup( conn->c_authmech ) : NULL;
-       arg->co_op->o_authtype = conn->c_authtype;
-
+       
        slap_op_add( &conn->c_ops, arg->co_op );
 
        if(tag == LDAP_REQ_BIND) {
index a9aef36cf794c7eaeee8fffb82bdc368f39c40ee..a37ab8b2a502b16ba992b8512e9aa49fbdf56918 100644 (file)
@@ -110,7 +110,7 @@ monitor_info( Connection *conn, Operation *op )
                        "%ld : %ld "
                        ": %ld/%ld/%ld/%ld "
                        ": %ld/%ld/%ld "
-                       ": %s%s%s%s "
+                       ": %s%s%s%s%s%s "
                        ": %s : %s : %s "
                        ": %s : %s",
 
@@ -127,6 +127,8 @@ monitor_info( Connection *conn, Operation *op )
                    c->c_writewaiter ? "w" : "",
                    c->c_ops != NULL ? "x" : "",
                    c->c_pending_ops != NULL ? "p" : "",
+                       connection_state2str( c->c_conn_state ),
+                       c->c_bind_in_progress ? "S" : "",
 
                    c->c_cdn ? c->c_cdn : "<anonymous>",
                    c->c_client_addr ? c->c_client_addr : "unknown",
index 0407ea158d3284e5d85ae63240958277d2b7ae46..d8c33673a615e5b6a3b89dfd7fc3ba4fc0ebd634 100644 (file)
@@ -148,6 +148,7 @@ long connection_init LDAP_P((
 
 void connection_closing LDAP_P(( Connection *c ));
 int connection_state_closing LDAP_P(( Connection *c ));
+char *connection_state2str LDAP_P(( int state ));
 
 int connection_write LDAP_P((ber_socket_t s));
 int connection_read LDAP_P((ber_socket_t s));
@@ -331,6 +332,7 @@ extern int          global_default_access;
 extern int             global_lastmod;
 extern int             global_idletimeout;
 extern int             global_schemacheck;
+extern char            *global_realm;
 extern int             lber_debug;
 extern int             ldap_syslog;
 
index 4edb275b8994de449a9289999ef00f34986b6141..d52b63f8bc0286336ca0f9a0123d3e18e7aecc16 100644 (file)
@@ -363,6 +363,8 @@ struct backend_db {
        char    *be_update_ndn; /* allowed to make changes (in replicas)   */
        int     be_lastmod;     /* keep track of lastmodified{by,time}     */
 
+       char    *be_realm;
+
        void    *be_private;    /* anything the backend database needs     */
 };
 
@@ -542,8 +544,9 @@ typedef struct slap_conn {
        char    *c_cdn;         /* DN provided by the client */
        char    *c_dn;          /* DN bound to this conn  */
        ber_int_t       c_protocol;     /* version of the LDAP protocol used by client */
-       ber_tag_t       c_authtype;     /* auth method used to bind c_dn  */
+       ber_tag_t       c_authtype;/* auth method used to bind c_dn  */
        char    *c_authmech;    /* SASL mechanism used to bind c_dn */
+       void    *c_authstate;   /* SASL state data */
 
        Operation       *c_ops;                 /* list of operations being processed */
        Operation       *c_pending_ops; /* list of pending operations */