From: Kurt Zeilenga Date: Fri, 2 Jul 1999 19:48:07 +0000 (+0000) Subject: More bind changes to support SASL/DIGEST. X-Git-Tag: OPENLDAP_REL_ENG_2_BP~199 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=b7bbc7504d14e2d1c18f5e9392f644d94bf91f08;p=openldap More bind changes to support SASL/DIGEST. Added configuration support for "digest-realm " configure directive. Added connection state and bind_in_progress fields to cn=monitor connection attribute. --- diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 5b5a1f5db8..74cc285665 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -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 ); } diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index bb9ccd3e16..8a11db02b0 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -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 { diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 45b25b9d40..f2f0cd79a0 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -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 \" 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, diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 1df8b52800..a8c6e26fb8 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -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) { diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c index a9aef36cf7..a37ab8b2a5 100644 --- a/servers/slapd/monitor.c +++ b/servers/slapd/monitor.c @@ -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 : "", c->c_client_addr ? c->c_client_addr : "unknown", diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 0407ea158d..d8c33673a6 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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; diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 4edb275b89..d52b63f8bc 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -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 */