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

Sync with HEAD

Ready for release?
parent 21698f6e
OpenLDAP 2.3 Change Log
OpenLDAP 2.3.10 Engineering
Fixed libldap ndelay without timeout
Fixed libldap chasing of chased referrals (ITS#2942)
Added libldap LDAP_NO_SUPPORT for TLS (ITS#4072)
Added libldap LDAP_MSG_RECEIVED support
Dropped libldap LDAP_MORE_RESULTS_TO_RETURN use
Fixed slapd cn=config undated rootdn issue (ITS#4035)
Fixed slapd-meta bus error (ITS#4073)
Fixed slapd-meta/ldap/rwm empty naming context issue (ITS#4071)
OpenLDAP 2.3.9 Release
Fixed slapd req_pwdexop bug
Fixed slapo-syncprov queued UUIDs bug (ITS#4068)
......
......@@ -15,7 +15,7 @@
ol_package=OpenLDAP
ol_major=2
ol_minor=3
ol_patch=9
ol_patch=X
ol_api_inc=20309
ol_api_current=1
ol_api_revision=4
......
......@@ -610,7 +610,7 @@ typedef struct ldapcontrol {
#define LDAP_NOT_SUPPORTED (-12)
#define LDAP_CONTROL_NOT_FOUND (-13)
#define LDAP_NO_RESULTS_RETURNED (-14)
#define LDAP_MORE_RESULTS_TO_RETURN (-15)
#define LDAP_MORE_RESULTS_TO_RETURN (-15) /* Obsolete */
#define LDAP_CLIENT_LOOP (-16)
#define LDAP_REFERRAL_LIMIT_EXCEEDED (-17)
......
......@@ -273,26 +273,12 @@ ldap_parse_result(
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif
/* Find the next result... */
if ( r->lm_chain == NULL ) {
if ((r->lm_msgtype == LDAP_RES_SEARCH_ENTRY) ||
(r->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) ||
(r->lm_msgtype == LDAP_RES_INTERMEDIATE)) {
lm = NULL;
} else {
lm = r;
}
} else {
if ((r->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_SEARCH_ENTRY) ||
(r->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_SEARCH_REFERENCE) ||
(r->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_INTERMEDIATE)) {
lm = NULL;
} else {
lm = r->lm_chain_tail->lm_chain;
}
/* Find the result, last msg in chain... */
lm = r->lm_chain_tail;
if ((lm->lm_msgtype == LDAP_RES_SEARCH_ENTRY) ||
(lm->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) ||
(lm->lm_msgtype == LDAP_RES_INTERMEDIATE)) {
lm = NULL;
}
if( lm == NULL ) {
......@@ -396,28 +382,6 @@ ldap_parse_result(
if( referralsp != NULL) {
*referralsp = ldap_value_dup( ld->ld_referrals );
}
/* Find the next result... */
lm = lm->lm_chain;
if ( lm ) {
if ( lm->lm_chain == NULL ) {
if ((lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) &&
(lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) &&
(lm->lm_msgtype != LDAP_RES_INTERMEDIATE)) {
/* more results to return */
errcode = LDAP_MORE_RESULTS_TO_RETURN;
}
} else {
if ((lm->lm_chain_tail->lm_chain->lm_msgtype
!= LDAP_RES_SEARCH_ENTRY) &&
(lm->lm_chain_tail->lm_chain->lm_msgtype
!= LDAP_RES_SEARCH_REFERENCE) &&
(lm->lm_chain_tail->lm_chain->lm_msgtype
!= LDAP_RES_INTERMEDIATE)) {
errcode = LDAP_MORE_RESULTS_TO_RETURN;
}
}
}
}
if ( freeit ) {
......
......@@ -256,6 +256,7 @@ typedef struct ldapreq {
char *lr_res_matched;/* result matched DN string */
BerElement *lr_ber; /* ber encoded request contents */
LDAPConn *lr_conn; /* connection used to send request */
struct berval lr_dn; /* DN of request, in lr_ber */
struct ldapreq *lr_parent; /* request that spawned this referral */
struct ldapreq *lr_child; /* first child request */
struct ldapreq *lr_refnext; /* next referral spawned */
......
......@@ -271,6 +271,31 @@ ldap_send_server_request(
lr->lr_origid = lr->lr_msgid;
}
/* Extract requestDN for future reference */
{
BerElement tmpber = *ber;
ber_int_t bint;
ber_tag_t tag, rtag;
ber_reset( &tmpber, 1 );
rtag = ber_scanf( &tmpber, "{it", /*}*/ &bint, &tag );
switch ( tag ) {
case LDAP_REQ_BIND:
rtag = ber_scanf( &tmpber, "{i" /*}*/, &bint );
break;
case LDAP_REQ_DELETE:
break;
default:
rtag = ber_scanf( &tmpber, "{" /*}*/ );
case LDAP_REQ_ABANDON:
break;
}
if ( tag != LDAP_REQ_ABANDON ) {
ber_skip_tag( &tmpber, &lr->lr_dn.bv_len );
lr->lr_dn.bv_val = tmpber.ber_ptr;
}
}
lr->lr_prev = NULL;
if (( lr->lr_next = ld->ld_requests ) != NULL ) {
lr->lr_next->lr_prev = lr;
......@@ -820,6 +845,33 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
/* check connection for re-bind in progress */
if (( lc = find_connection( ld, srv, 1 )) != NULL ) {
/* See if we've already requested this DN with this conn */
LDAPRequest *lp;
int looped = 0;
int len = srv->lud_dn ? strlen( srv->lud_dn ) : 0;
for (lp = origreq; lp; ) {
if ( lp->lr_conn == lc ) {
if ( len == lp->lr_dn.bv_len ) {
if ( len && strncmp( srv->lud_dn, lp->lr_dn.bv_val,
len ))
continue;
looped = 1;
break;
}
}
if ( lp == origreq )
lp = lp->lr_child;
else
lp = lr->lr_refnext;
}
if ( looped ) {
ldap_free_urllist( srv );
srv = NULL;
ld->ld_errno = LDAP_CLIENT_LOOP;
rc = -1;
continue;
}
if( lc->lconn_rebind_inprogress) {
/* We are already chasing a referral or search reference and a
* bind on that connection is in progress. We must queue
......@@ -904,7 +956,7 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
rc = ldap_send_server_request( ld, ber, id,
origreq, srv, NULL, &rinfo );
origreq, srv, NULL, &rinfo );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
......@@ -915,6 +967,7 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
unfollowedcnt += ldap_append_referral( ld, &unfollowed, refarray[i] );
ldap_free_urllist( srv );
srv = NULL;
ld->ld_errno = LDAP_REFERRAL;
} else {
/* Success, no need to try this referral list further */
rc = 0;
......@@ -965,7 +1018,6 @@ done:
LDAP_FREE( unfollowed );
return count;
} else {
ld->ld_errno = LDAP_REFERRAL;
*errstrp = unfollowed;
return rc;
}
......@@ -988,6 +1040,7 @@ ldap_chase_referrals( LDAP *ld,
LDAPURLDesc *srv;
BerElement *ber;
LDAPreqinfo rinfo;
LDAPConn *lc;
Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 );
......@@ -1055,6 +1108,30 @@ ldap_chase_referrals( LDAP *ld,
*hadrefp = 1;
/* See if we've already been here */
if (( lc = find_connection( ld, srv, 1 )) != NULL ) {
LDAPRequest *lp;
int looped = 0;
int len = srv->lud_dn ? strlen( srv->lud_dn ) : 0;
for (lp = lr; lp; lp = lp->lr_parent ) {
if ( lp->lr_conn == lc ) {
if ( len == lp->lr_dn.bv_len ) {
if ( len && strncmp( srv->lud_dn, lp->lr_dn.bv_val,
len ))
continue;
looped = 1;
break;
}
}
}
if ( looped ) {
ldap_free_urllist(srv);
ld->ld_errno = LDAP_CLIENT_LOOP;
rc = -1;
continue;
}
}
LDAP_NEXT_MSGID( ld, id );
ber = re_encode_request( ld, origreq->lr_ber,
id, sref, srv, &rinfo.ri_request );
......@@ -1148,7 +1225,7 @@ re_encode_request( LDAP *ld,
ber_int_t scope;
int rc;
BerElement tmpber, *ber;
char *orig_dn;
struct berval orig_dn;
char *dn;
Debug( LDAP_DEBUG_TRACE,
......@@ -1174,15 +1251,15 @@ re_encode_request( LDAP *ld,
assert( tag != 0);
if ( tag == LDAP_REQ_BIND ) {
/* bind requests have a version number before the DN & other stuff */
rtag = ber_scanf( &tmpber, "{ia" /*}*/, &ver, &orig_dn );
rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &orig_dn );
} else if ( tag == LDAP_REQ_DELETE ) {
/* delete requests don't have a DN wrapping sequence */
rtag = ber_scanf( &tmpber, "a", &orig_dn );
rtag = ber_scanf( &tmpber, "m", &orig_dn );
} else if ( tag == LDAP_REQ_SEARCH ) {
/* search requests need to be re-scope-ed */
rtag = ber_scanf( &tmpber, "{ae" /*"}"*/, &orig_dn, &scope );
rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &orig_dn, &scope );
if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
/* use the scope provided in reference */
......@@ -1211,7 +1288,7 @@ re_encode_request( LDAP *ld,
}
} else {
rtag = ber_scanf( &tmpber, "{a" /*}*/, &orig_dn );
rtag = ber_scanf( &tmpber, "{m" /*}*/, &orig_dn );
}
if( rtag == LBER_ERROR ) {
......@@ -1224,7 +1301,7 @@ re_encode_request( LDAP *ld,
}
if ( srv->lud_dn == NULL ) {
dn = orig_dn;
dn = orig_dn.bv_val;
} else {
dn = srv->lud_dn;
}
......@@ -1239,8 +1316,6 @@ re_encode_request( LDAP *ld,
rc = ber_printf( ber, "{it{s" /*}}*/, msgid, tag, dn );
}
LDAP_FREE( orig_dn );
if ( rc == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
ber_free( ber, 1 );
......
......@@ -137,7 +137,7 @@ chkResponseList(
int msgid,
int all)
{
LDAPMessage *lm, *lastlm, *nextlm;
LDAPMessage *lm, **lastlm, *nextlm;
/*
* Look through the list of responses we have received on
* this association and see if the response we're interested in
......@@ -148,7 +148,7 @@ chkResponseList(
Debug( LDAP_DEBUG_TRACE,
"ldap_chkResponseList for msgid=%d, all=%d\n",
msgid, all, 0 );
lastlm = NULL;
lastlm = &ld->ld_responses;
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
nextlm = lm->lm_next;
......@@ -158,12 +158,8 @@ chkResponseList(
msgid, 0, 0 );
ldap_mark_abandoned( ld, lm->lm_msgid );
if ( lastlm == NULL ) {
/* Remove first entry in list */
ld->ld_responses = lm->lm_next;
} else {
lastlm->lm_next = nextlm;
}
/* Remove this entry from list */
*lastlm = nextlm;
ldap_msgfree( lm );
......@@ -173,32 +169,16 @@ chkResponseList(
if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) {
LDAPMessage *tmp;
if ( all == LDAP_MSG_ONE || msgid == LDAP_RES_UNSOLICITED ) {
if ( all == LDAP_MSG_ONE || all == LDAP_MSG_RECEIVED ||
msgid == LDAP_RES_UNSOLICITED ) {
break;
}
if ( lm->lm_chain == NULL ) {
assert(lm->lm_chain_tail == lm);
if ((lm->lm_msgtype == LDAP_RES_SEARCH_ENTRY) ||
(lm->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) ||
(lm->lm_msgtype == LDAP_RES_INTERMEDIATE)) {
tmp = NULL;
} else {
tmp = lm;
}
} else {
assert(lm->lm_chain_tail != NULL);
assert(lm->lm_chain_tail->lm_chain != NULL);
if ((lm->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_SEARCH_ENTRY) ||
(lm->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_SEARCH_REFERENCE) ||
(lm->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_INTERMEDIATE)) {
tmp = NULL;
} else {
tmp = lm->lm_chain_tail->lm_chain;
}
tmp = lm->lm_chain_tail;
if ((tmp->lm_msgtype == LDAP_RES_SEARCH_ENTRY) ||
(tmp->lm_msgtype == LDAP_RES_SEARCH_REFERENCE) ||
(tmp->lm_msgtype == LDAP_RES_INTERMEDIATE)) {
tmp = NULL;
}
if ( tmp == NULL ) {
......@@ -207,25 +187,20 @@ chkResponseList(
break;
}
lastlm = lm;
lastlm = &lm->lm_next;
}
if ( lm != NULL ) {
/* Found an entry, remove it from the list */
if ( lastlm == NULL ) {
ld->ld_responses = (all == LDAP_MSG_ONE && lm->lm_chain != NULL
? lm->lm_chain : lm->lm_next);
} else {
lastlm->lm_next = (all == LDAP_MSG_ONE && lm->lm_chain != NULL
? lm->lm_chain : lm->lm_next);
}
if ( all == LDAP_MSG_ONE && lm->lm_chain != NULL ) {
*lastlm = lm->lm_chain;
lm->lm_chain->lm_next = lm->lm_next;
lm->lm_chain->lm_chain_tail = ( lm->lm_chain_tail != lm ) ? lm->lm_chain_tail : lm->lm_chain;
assert(lm->lm_chain->lm_chain_tail != NULL);
lm->lm_chain = NULL;
lm->lm_chain_tail = NULL;
}
} else {
*lastlm = lm->lm_next;
}
lm->lm_next = NULL;
}
......@@ -403,7 +378,7 @@ try_read1msg(
#ifdef LDAP_CONNECTIONLESS
LDAPMessage *tmp = NULL, *chain_head = NULL;
int firstmsg = 1, moremsgs = 0, isv2 = 0;
int moremsgs = 0, isv2 = 0;
#endif
/*
......@@ -806,6 +781,7 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
newmsg->lm_msgid = (int)id;
newmsg->lm_msgtype = tag;
newmsg->lm_ber = ber;
newmsg->lm_chain_tail = newmsg;
#ifdef LDAP_CONNECTIONLESS
/* CLDAP replies all fit in a single datagram. In LDAPv2 RFC1798
......@@ -852,17 +828,14 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
if (ber_sockbuf_ctrl(sb, LBER_SB_OPT_DATA_READY, NULL)) ok=1;
}
/* set up response chain */
if ( firstmsg ) {
firstmsg = 0;
if ( tmp == NULL ) {
newmsg->lm_next = ld->ld_responses;
ld->ld_responses = newmsg;
newmsg->lm_chain_tail = newmsg;
chain_head = newmsg;
} else {
assert( tmp != NULL );
tmp->lm_chain = newmsg;
chain_head->lm_chain_tail = tmp;
}
chain_head->lm_chain_tail = newmsg;
tmp = newmsg;
/* "ok" means there's more to parse */
if (ok) {
......@@ -883,7 +856,7 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
* first response off the head of the chain.
*/
tmp->lm_chain = newmsg;
chain_head->lm_chain_tail = tmp;
chain_head->lm_chain_tail = newmsg;
*result = chkResponseList( ld, msgid, all );
ld->ld_errno = LDAP_SUCCESS;
return( (*result)->lm_msgtype );
......@@ -927,7 +900,6 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
newmsg->lm_next = ld->ld_responses;
ld->ld_responses = newmsg;
newmsg->lm_chain_tail = newmsg;
goto exit;
}
......@@ -935,25 +907,8 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
(long) newmsg->lm_msgid, (long) newmsg->lm_msgtype, 0 );
/* part of a search response - add to end of list of entries */
if (l->lm_chain == NULL) {
assert(l->lm_chain_tail == l);
l->lm_chain = newmsg;
} else {
assert(l->lm_chain_tail != NULL);
assert(l->lm_chain_tail->lm_chain != NULL);
if ((l->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_SEARCH_ENTRY) ||
(l->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_SEARCH_REFERENCE) ||
(l->lm_chain_tail->lm_chain->lm_msgtype
== LDAP_RES_INTERMEDIATE)) {
l->lm_chain_tail->lm_chain->lm_chain = newmsg;
l->lm_chain_tail = l->lm_chain_tail->lm_chain;
} else {
/*FIXME: ldap_msgfree( l->lm_chain_tail->lm_chain );*/
l->lm_chain_tail->lm_chain = newmsg;
}
}
l->lm_chain_tail->lm_chain = newmsg;
l->lm_chain_tail = newmsg;
/* return the whole chain if that's what we were looking for */
if ( foundit ) {
......
......@@ -199,6 +199,12 @@ ldap_pvt_tls_init_def_ctx( void )
char *certfile = tls_opt_certfile;
char *keyfile = tls_opt_keyfile;
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
#endif
if (( !cacertfile && !cacertdir ) || !certfile || !keyfile )
return LDAP_NOT_SUPPORTED;
#ifdef HAVE_EBCDIC
/* This ASCII/EBCDIC handling is a real pain! */
if ( ciphersuite ) {
......@@ -222,10 +228,6 @@ ldap_pvt_tls_init_def_ctx( void )
__atoe( keyfile );
}
#endif
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
#endif
if ( tls_def_ctx == NULL ) {
int i;
tls_def_ctx = SSL_CTX_new( SSLv23_method() );
......
......@@ -120,6 +120,13 @@ meta_back_db_config(
fname, lineno );
return 1;
}
if ( be->be_nsuffix == NULL ) {
fprintf( stderr,
"%s: line %d: the suffix must be defined before any target.\n",
fname, lineno );
return 1;
}
++mi->mi_ntargets;
......@@ -163,12 +170,29 @@ meta_back_db_config(
/*
* uri MUST have the <dn> part!
*/
if ( ludp->lud_dn == NULL || ludp->lud_dn[ 0 ] == '\0' ) {
if ( ludp->lud_dn == NULL ) {
fprintf( stderr,
"%s: line %d: missing <naming context> "
" in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
fname, lineno );
return 1;
} else if ( ludp->lud_dn[ 0 ] == '\0' ) {
int j = -1;
for ( j = 0; !BER_BVISNULL( &be->be_nsuffix[ j ] ); j++ ) {
if ( BER_BVISEMPTY( &be->be_nsuffix[ j ] ) ) {
break;
}
}
if ( BER_BVISNULL( &be->be_nsuffix[ j ] ) ) {
fprintf( stderr,
"%s: line %d: missing <naming context> "
" in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
fname, lineno );
return 1;
}
}
/*
......@@ -1029,6 +1053,10 @@ suffix_massage_regexize( const char *s )
const char *p, *r;
int i;
if ( s[ 0 ] == '\0' ) {
return ch_strdup( "^(.+)$" );
}
for ( i = 0, p = s;
( r = strchr( p, ',' ) ) != NULL;
p = r + 1, i++ )
......@@ -1036,10 +1064,11 @@ suffix_massage_regexize( const char *s )
res = ch_calloc( sizeof( char ),
strlen( s )
+ STRLENOF( "(.+,)?" )
+ STRLENOF( "[ ]?" ) * i + 1 );
+ STRLENOF( "((.+),)?" )
+ STRLENOF( "[ ]?" ) * i
+ STRLENOF( "$" ) + 1 );
ptr = lutil_strcopy( res, "(.+,)?" );
ptr = lutil_strcopy( res, "((.+),)?" );
for ( i = 0, p = s;
( r = strchr( p, ',' ) ) != NULL;
p = r + 1 , i++ ) {
......@@ -1050,26 +1079,37 @@ suffix_massage_regexize( const char *s )
r++;
}
}
lutil_strcopy( ptr, p );
ptr = lutil_strcopy( ptr, p );
ptr[ 0 ] = '$';
ptr++;
ptr[ 0 ] = '\0';
return res;
}
static char *
suffix_massage_patternize( const char *s )
suffix_massage_patternize( const char *s, const char *p )
{
ber_len_t len;
char *res;
char *res, *ptr;
len = strlen( p );
len = strlen( s );
if ( s[ 0 ] == '\0' ) {
len++;
}
res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 );
if ( res == NULL ) {
return NULL;
}
strcpy( res, "%1" );
strcpy( &res[ STRLENOF( "%1" ) ], s );
ptr = lutil_strcopy( res, ( p[ 0 ] == '\0' ? "%2" : "%1" ) );
if ( s[ 0 ] == '\0' ) {
ptr[ 0 ] = ',';
ptr++;
}
lutil_strcopy( ptr, p );
return res;
}
......@@ -1098,12 +1138,21 @@ suffix_massage_config(
rargv[ 0 ] = "rewriteRule";
rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val );
rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val, prnc->bv_val );
rargv[ 3 ] = ":";
rargv[ 4 ] = NULL;
rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );