Commit b7bbc750 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

More bind changes to support SASL/DIGEST.

Added configuration support for "digest-realm <realm>" configure directive.
Added connection state and bind_in_progress fields to cn=monitor connection
attribute.
parent c8e37af0
......@@ -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 );
}
......
......@@ -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 {
......
......@@ -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,
......
......@@ -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) {
......
......@@ -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",
......
......@@ -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;
......
......@@ -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 */
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment