]> git.sur5r.net Git - openldap/commitdiff
improve timeout support (ITS#4157, ITS#4663); manpage cleanup
authorPierangelo Masarati <ando@openldap.org>
Mon, 4 Sep 2006 08:24:05 +0000 (08:24 +0000)
committerPierangelo Masarati <ando@openldap.org>
Mon, 4 Sep 2006 08:24:05 +0000 (08:24 +0000)
12 files changed:
doc/man/man5/slapd-ldap.5
servers/slapd/back-ldap/add.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/chain.c
servers/slapd/back-ldap/compare.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/distproc.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/search.c

index 79eb9349e38ce14fad15ce16d91ebc0705cc74ec..6ead6fa1c9e4699a173becb56a4f945fedc83633 100644 (file)
@@ -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 
index 1989a5b608627b6317b7101dad6c640f0907b7de..9a8ba0518bdb9f6a9dffb5454361ce1bfdafd65c 100644 (file)
@@ -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;
index a1fb091f311964d3cfc9077515d1c63ad77f50ca..e1ede3506f61f5bd5b7aa061fc3cccf4067ea8cb 100644 (file)
@@ -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 {
index 2d3527e239e89a23ed087a6d214b4c68cd2d0287..1557de1e0a5476be661118911f67421f67442367 100644 (file)
@@ -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:
index c0707c16a273a153e6fe013bac6dd4e1f7ab2f98..6bf0deac50322b2d117d8f26e4ddf3735eb5eba1 100644 (file)
@@ -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;
index 11fd3eb9c30cbdb44bc461772fcb5db733f5471c..f58a4e373151c492539b2e5985316b9c2a832160 100644 (file)
@@ -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;
index 154f4c305a6beef5f72b31baa33979780f80a291..cd93d834c5eb0b1eef43597d0153fe4bab0d5f72 100644 (file)
@@ -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;
                        }
                }
index f95660cace1fe32a9a93f5b2fec1b7140691e524..a46616f02d3632560aa0d136c5165d670ed30b97 100644 (file)
@@ -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;
index b67cb1d7a2c4c6f0b3a3a14563f735187baf3b8f..95c7dfcfbb2e1c5fcbe348384ad2bd975a482ac8 100644 (file)
@@ -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;
index 648dc18a0d293fae536d15a4d8695760cd046b5d..9e53ac2b8e74d7c522f49e0cc2f635a21c1e3d6e 100644 (file)
@@ -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;
index 37e1afe7e86f91c000d0e0e859b4321b384d8feb..e2b3b405e8de51cfe8fb63a5b19ceefc6c2200bb 100644 (file)
@@ -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;
index b5647e5dc9d39e1d3107ae666e7d1cbb7e44a98e..48a4a6179d0ec7846e8e801bd1e478f704790b07 100644 (file)
@@ -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,