Commit 150a4f10 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

improve timeout support (ITS#4157, ITS#4663); manpage cleanup

parent 35f8b9c9
......@@ -64,21 +64,20 @@ lastmod off
.fi
.RE
.LP
for every
for
.B ldap
and
.B meta
database.
This is because operational attributes related to entry creation and
modification should not be proxied, as they could be mistakenly written
databases.
This was required because operational attributes related to entry creation
and modification should not be proxied, as they could be mistakenly written
to the target server(s), generating an error.
The current implementation automatically sets lastmod to off, so its use
is redundant and should be omitted, because the lastmod directive will
be deprecated in the future.
The current implementation automatically sets lastmod to \fBoff\fP,
so its use is redundant and should be omitted.
.TP
.B uri <ldapurl>
LDAP server to use. Multiple URIs can be set in in a single
LDAP server to use. Multiple URIs can be set in a single
.B ldapurl
argument, resulting in the underlying library automatically
call the first server of the list that responds, e.g.
......@@ -86,10 +85,10 @@ call the first server of the list that responds, e.g.
\fBuri "ldap://host/ ldap://backup-host/"\fP
The URI list is space- or comma-separated.
.\"This statement is mandatory.
.\".TP
.\".B server <hostport>
.\"Obsolete option; same as `uri ldap://<hostport>/'.
Whenever the server that responds is not the first one in the list,
the list is rearranged and the responsive server is moved to the head,
so that it will be first contacted the next time a connection
needs be created.
.HP
.hy 0
.B acl-bind
......@@ -226,7 +225,8 @@ or
parameters).
Otherwise, the default
.B proxyauthz
is used, i.e. the proxyAuthz control is added to all operations.
is used, i.e. the proxyAuthz control (Proxied Authorization, RFC 4370)
is added to all operations.
The supported modes are:
......@@ -297,7 +297,7 @@ useful when the asserted identities do not exist on the remote server.
Flags can be
\fBoverride,{prescriptive|non-prescriptive}\fP
\fBoverride,[non-]prescriptive\fP
When the
.B override
......@@ -389,19 +389,37 @@ If set to
support is detected by reading the remote server's root DSE.
.TP
.B timeout [{add|delete|modify|modrdn}=]<val> [...]
.B timeout [<op>=]<val> [...]
This directive allows to set per-operation timeouts.
If no operation is specified, it affects all.
Currently, only write operations are addressed, because searches
can already be limited by means of the
.B limits
directive (see
Operations can be
\fB<op> ::= bind, add, delete, modrdn, modify, compare\fP
The \fBsearch\fP operation is already controlled either
by the \fBtimelimit\fP parameter or by server-side enforced
time limits (see \fBtimelimit\fP and \fBlimits\fP in
.BR slapd.conf (5)
for details), and other operations are not supposed to incur into the
need for timeouts.
Note: if the timelimit is exceeded, the operation is abandoned;
the protocol does not provide any means to rollback the operation,
so the client will not know if the operation eventually succeeded or not.
for details).
Timeout is meaningless for the remaining operations,
\fBunbind\fP and \fBabandon\fP, which do not imply any response,
while it is not yet implemented in currently supported \fBextended\fP
operations.
If no operation is specified, the timeout \fBval\fP affects all
supported operations.
Note: if the timelimit is exceeded, the operation is cancelled
(according to the \fBcancel\fP directive);
the protocol does not provide any means to rollback operations,
so the client will not be notified about the result of the operation,
which may eventually succeeded or not.
In case the timeout is exceeded during a bind operation, the connection
is destroyed, according to RFC4511.
Note: in some cases, this backend may issue binds prior
to other operations (e.g. to bind anonymously or with some prescribed
identity according to the \fBidassert-bind\fP directive).
In this case, the timeout of the operation that resulted in the bind
is used.
.TP
.B tls {[try-]start|[try-]propagate}
......@@ -410,26 +428,31 @@ only works if the URI directive protocol scheme is not \fBldaps://\fP.
\fBpropagate\fP issues the StartTLS operation only if the original
connection did.
The \fBtry-\fP prefix instructs the proxy to continue operations
if the StartTLS operation failed; its use is highly deprecated.
if the StartTLS operation failed; its use is \fBnot\fP recommended.
.SH BACKWARD COMPATIBILITY
The LDAP backend has been heavily reworked between releases 2.2 and 2.3;
as a side-effect, some of the traditional directives have been
The LDAP backend has been heavily reworked between releases 2.2 and 2.3,
and subsequently between 2.3 and 2.4.
As a side-effect, some of the traditional directives have been
deprecated and should be no longer used, as they might disappear
in future releases.
.TP
.B acl-authcDN "<administrative DN for access control purposes>"
DN which is used to query the target server for acl checking; it
is supposed to have read access on the target server to attributes used
Formerly known as the
.BR binddn ,
it is the DN that is used to query the target server for acl checking;
it is supposed to have read access on the target server to attributes used
on the proxy for acl checking.
There is no risk of giving away such values; they are only used to
check permissions.
.B The acl-authcDN identity is by no means implicitly used by the proxy
.B when the client connects anonymously.
See the
The
.B idassert-*
feature instead.
feature can be used (at own risk) for that purpose instead.
This directive is obsoleted by the
.B binddn
arg of
......@@ -438,11 +461,13 @@ when \fIbindmethod\fP=\fBsimple\fP, and will be dismissed in the future.
.TP
.B acl-passwd <password>
Password used with the above
Formerly known as the
.BR bindpw ,
it is the password used with the above
.B acl-authcDN
directive.
This directive is obsoleted by the
.B binddn
.B credentials
arg of
.B acl-bind
when \fIbindmethod\fP=\fBsimple\fP, and will be dismissed in the future.
......@@ -465,7 +490,7 @@ Password used with the
above.
This directive is obsoleted by the
.B crendentials
of
arg of
.B idassert-bind
when \fIbindmethod\fP=\fBsimple\fP, and will be dismissed in the future.
......@@ -488,6 +513,12 @@ arg of
.BR idassert-bind ,
and will be dismissed in the future.
.TP
.B port <port>
this directive is no longer supported. Use the
.B uri
directive as described above.
.TP
.B server <hostname[:port]>
this directive is no longer supported. Use the
......
......@@ -104,7 +104,7 @@ retry:
rs->sr_err = ldap_add_ext( lc->lc_ld, op->o_req_dn.bv_val, attrs,
ctrls, NULL, &msgid );
rs->sr_err = ldap_back_op_result( lc, op, rs, msgid,
li->li_timeout[ LDAP_BACK_OP_ADD ],
li->li_timeout[ SLAP_OP_ADD ],
( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
......
......@@ -101,17 +101,6 @@ typedef struct ldapconn_t {
time_t lc_time;
} ldapconn_t;
/*
* operation enumeration for timeouts
*/
enum {
LDAP_BACK_OP_ADD = 0,
LDAP_BACK_OP_DELETE,
LDAP_BACK_OP_MODIFY,
LDAP_BACK_OP_MODRDN,
LDAP_BACK_OP_LAST
};
typedef struct ldap_avl_info_t {
ldap_pvt_thread_mutex_t lai_mutex;
Avlnode *lai_tree;
......@@ -279,7 +268,7 @@ typedef struct ldapinfo_t {
time_t li_network_timeout;
time_t li_conn_ttl;
time_t li_idle_timeout;
time_t li_timeout[ LDAP_BACK_OP_LAST ];
time_t li_timeout[ SLAP_OP_LAST ];
} ldapinfo_t;
typedef enum ldap_back_send_t {
......
......@@ -117,8 +117,9 @@ ldap_back_bind( Operation *op, SlapReply *rs )
rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val,
LDAP_SASL_SIMPLE,
&op->orb_cred, op->o_ctrls, NULL, &msgid );
rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_SENDERR );
rc = ldap_back_op_result( lc, op, rs, msgid,
li->li_timeout[ SLAP_OP_BIND ],
LDAP_BACK_BIND_SERR );
if ( rc == LDAP_SUCCESS ) {
/* If defined, proxyAuthz will be used also when
* back-ldap is the authorizing backend; for this
......@@ -1116,7 +1117,8 @@ retry:;
return 0;
}
rc = ldap_back_op_result( lc, op, rs, msgid, 0, sendok );
rc = ldap_back_op_result( lc, op, rs, msgid,
-1, (sendok|LDAP_BACK_BINDING) );
if ( rc == LDAP_SUCCESS ) {
LDAP_BACK_CONN_ISBOUND_SET( lc );
}
......@@ -1270,28 +1272,67 @@ ldap_back_op_result(
int rc;
struct timeval tv;
LDAPMessage *res = NULL;
time_t stoptime = (time_t)(-1);
int timeout_err = op->o_protocol >= LDAP_VERSION3 ?
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
const char *timeout_text = "Operation timed out";
if ( timeout ) {
tv.tv_sec = timeout;
tv.tv_usec = 0;
/* if timeout is not specified, compute and use
* the one specific to the ongoing operation */
if ( timeout == (time_t)(-1) ) {
slap_op_t opidx = slap_req2op( op->o_tag );
} else {
LDAP_BACK_TV_SET( &tv );
if ( opidx == SLAP_OP_SEARCH ) {
if ( op->ors_tlimit <= 0 ) {
timeout = 0;
} else {
timeout = op->ors_tlimit;
timeout_err = LDAP_TIMELIMIT_EXCEEDED;
timeout_text = NULL;
}
} else {
timeout = li->li_timeout[ opidx ];
}
}
/* better than nothing :) */
if ( timeout == 0 ) {
if ( li->li_idle_timeout ) {
timeout = li->li_idle_timeout;
} else if ( li->li_conn_ttl ) {
timeout = li->li_conn_ttl;
}
}
if ( timeout ) {
stoptime = op->o_time + timeout;
}
LDAP_BACK_TV_SET( &tv );
retry:;
/* if result parsing fails, note the failure reason */
rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
switch ( rc ) {
case 0:
if ( timeout ) {
(void)ldap_back_cancel( lc, op, rs, msgid, sendok );
rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
rs->sr_text = "Operation timed out";
if ( timeout && slap_get_time() > stoptime ) {
if ( sendok & LDAP_BACK_BINDING ) {
ldap_unbind_ext( lc->lc_ld, NULL, NULL );
lc->lc_ld = NULL;
LDAP_BACK_CONN_TAINTED_SET( lc );
} else {
(void)ldap_back_cancel( lc, op, rs, msgid, sendok );
}
rs->sr_err = timeout_err;
rs->sr_text = timeout_text;
break;
}
/* timeout == 0 */
LDAP_BACK_TV_SET( &tv );
ldap_pvt_thread_yield();
goto retry;
......@@ -1690,7 +1731,8 @@ ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_b
rs->sr_err = ldap_sasl_bind( lc->lc_ld,
binddn.bv_val, LDAP_SASL_SIMPLE,
&bindcred, NULL, NULL, &msgid );
rc = ldap_back_op_result( lc, op, rs, msgid, 0, sendok );
rc = ldap_back_op_result( lc, op, rs, msgid,
-1, (sendok|LDAP_BACK_BINDING) );
break;
default:
......
......@@ -1741,7 +1741,7 @@ ldap_chain_db_init_one(
BackendInfo *bi = be->bd_info;
ldapinfo_t *li;
int t;
slap_op_t t;
be->bd_info = lback;
be->be_private = NULL;
......@@ -1757,7 +1757,7 @@ ldap_chain_db_init_one(
li->li_nretries = lc->lc_common_li->li_nretries;
li->li_flags = lc->lc_common_li->li_flags;
li->li_version = lc->lc_common_li->li_version;
for ( t = 0; t < LDAP_BACK_OP_LAST; t++ ) {
for ( t = 0; t < SLAP_OP_LAST; t++ ) {
li->li_timeout[ t ] = lc->lc_common_li->li_timeout[ t ];
}
be->bd_info = bi;
......
......@@ -63,7 +63,8 @@ retry:
op->orc_ava->aa_desc->ad_cname.bv_val,
&op->orc_ava->aa_value,
ctrls, NULL, &msgid );
rc = ldap_back_op_result( lc, op, rs, msgid, 0,
rc = ldap_back_op_result( lc, op, rs, msgid,
li->li_timeout[ SLAP_OP_COMPARE ],
( LDAP_BACK_SENDRESULT | retrying ) );
if ( rc == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
......
......@@ -351,11 +351,22 @@ static slap_verbmasks cancel_mode[] = {
{ BER_BVNULL, 0 }
};
/* see enum in slap.h */
static slap_cf_aux_table timeout_table[] = {
{ BER_BVC("add="), 0 * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("delete="), 1 * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("modify="), 2 * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("modrdn="), 3 * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL },
/* unbind makes no sense */
{ BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL },
{ BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL },
#if 0 /* uses timelimit instead */
{ BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL },
#endif
/* abandon makes little sense */
#if 0 /* not implemented yet */
{ BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL },
#endif
{ BER_BVNULL, 0, 0, 0, NULL }
};
......@@ -921,13 +932,13 @@ ldap_back_cf_gen( ConfigArgs *c )
case LDAP_BACK_CFG_TIMEOUT:
BER_BVZERO( &bv );
for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) {
for ( i = 0; i < SLAP_OP_LAST; i++ ) {
if ( li->li_timeout[ i ] != 0 ) {
break;
}
}
if ( i == LDAP_BACK_OP_LAST ) {
if ( i == SLAP_OP_LAST ) {
return 1;
}
......@@ -1099,7 +1110,7 @@ ldap_back_cf_gen( ConfigArgs *c )
break;
case LDAP_BACK_CFG_TIMEOUT:
for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) {
for ( i = 0; i < SLAP_OP_LAST; i++ ) {
li->li_timeout[ i ] = 0;
}
break;
......@@ -1578,10 +1589,14 @@ done_url:;
unsigned u;
if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
snprintf( c->msg, sizeof( c->msg),
"unable to parse timeout \"%s\"",
c->argv[ i ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
return 1;
}
for ( j = 0; j < LDAP_BACK_OP_LAST; j++ ) {
for ( j = 0; j < SLAP_OP_LAST; j++ ) {
li->li_timeout[ j ] = u;
}
......@@ -1589,6 +1604,10 @@ done_url:;
}
if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) {
snprintf( c->msg, sizeof( c->msg),
"unable to parse timeout \"%s\"",
c->argv[ i ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
return 1;
}
}
......
......@@ -63,7 +63,7 @@ retry:
rs->sr_err = ldap_delete_ext( lc->lc_ld, op->o_req_dn.bv_val,
ctrls, NULL, &msgid );
rc = ldap_back_op_result( lc, op, rs, msgid,
li->li_timeout[ LDAP_BACK_OP_DELETE],
li->li_timeout[ SLAP_OP_DELETE ],
( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_SERVER_DOWN && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
......
......@@ -831,7 +831,7 @@ ldap_distproc_db_init_one(
BackendInfo *bi = be->bd_info;
ldapinfo_t *li;
int t;
slap_op_t t;
be->bd_info = lback;
be->be_private = NULL;
......@@ -845,7 +845,7 @@ ldap_distproc_db_init_one(
li->li_nretries = lc->lc_common_li->li_nretries;
li->li_flags = lc->lc_common_li->li_flags;
li->li_version = lc->lc_common_li->li_version;
for ( t = 0; t < LDAP_BACK_OP_LAST; t++ ) {
for ( t = 0; t < SLAP_OP_LAST; t++ ) {
li->li_timeout[ t ] = lc->lc_common_li->li_timeout[ t ];
}
be->bd_info = bi;
......
......@@ -111,7 +111,7 @@ retry:
rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_dn.bv_val, modv,
ctrls, NULL, &msgid );
rc = ldap_back_op_result( lc, op, rs, msgid,
li->li_timeout[ LDAP_BACK_OP_MODIFY],
li->li_timeout[ SLAP_OP_MODIFY ],
( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
......
......@@ -87,7 +87,7 @@ retry:
op->orr_newrdn.bv_val, newSup,
op->orr_deleteoldrdn, ctrls, NULL, &msgid );
rc = ldap_back_op_result( lc, op, rs, msgid,
li->li_timeout[ LDAP_BACK_OP_MODRDN ],
li->li_timeout[ SLAP_OP_MODRDN ],
( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_SERVER_DOWN && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
......
......@@ -145,7 +145,7 @@ ldap_back_search(
ldapconn_t *lc;
struct timeval tv;
time_t stoptime = (time_t)-1;
time_t stoptime = (time_t)(-1);
LDAPMessage *res,
*e;
int rc = 0,
......
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