]> git.sur5r.net Git - openldap/commitdiff
LDAP Client Update Protocol - non-persistent update (TODO: response control ...)
authorJong Hyuk Choi <jongchoi@openldap.org>
Wed, 4 Sep 2002 02:00:42 +0000 (02:00 +0000)
committerJong Hyuk Choi <jongchoi@openldap.org>
Wed, 4 Sep 2002 02:00:42 +0000 (02:00 +0000)
include/ldap.h
servers/slapd/back-bdb/search.c
servers/slapd/controls.c
servers/slapd/schema_init.c
servers/slapd/schema_prep.c
servers/slapd/slap.h

index 0540f1ffc4b9edd21f2c2377835a3bb2d81c4a31..b976dc49f798e5a0af90869b52857958e3c32239 100644 (file)
@@ -32,6 +32,9 @@
 
 LDAP_BEGIN_DECL
 
+#define LDAP_CLIENT_UPDATE     1
+#undef LDAP_CLIENT_UPDATE
+
 #define LDAP_VERSION1  1
 #define LDAP_VERSION2  2
 #define LDAP_VERSION3  3
@@ -201,6 +204,12 @@ typedef struct ldapcontrol {
 #define LDAP_CONTROL_PAGEDRESULTS      "1.2.840.113556.1.4.319"
 #endif
 
+#if LDAP_CLIENT_UPDATE
+#define LDAP_CONTROL_CLIENT_UPDATE     "1.3.6.1.4.1.4203.666.7.1"
+#define LDAP_CONTROL_ENTRY_UPDATE      "1.3.6.1.4.1.4203.666.7.2"
+#define LDAP_CONTROL_CLIENT_UPDATE_DONE        "1.3.6.1.4.1.4203.666.7.3"
+#endif
+
 #define LDAP_CONTROL_SORTREQUEST    "1.2.840.113556.1.4.473"
 #define LDAP_CONTROL_SORTRESPONSE      "1.2.840.113556.1.4.474"
 #define LDAP_CONTROL_VLVREQUEST        "2.16.840.1.113730.3.4.9"
@@ -254,8 +263,18 @@ typedef struct ldapcontrol {
 /* general stuff */
 #define LDAP_TAG_MESSAGE       ((ber_tag_t) 0x30U)     /* constructed + 16 */
 #define LDAP_TAG_MSGID         ((ber_tag_t) 0x02U)     /* integer */
+
+#ifdef LDAP_CLIENT_UPDATE
+#define LDAP_TAG_INTERVAL      ((ber_tag_t) 0x02U)     /* integer */
+#endif /* LDAP_CLIENT_UPDATE */
+
 #define LDAP_TAG_LDAPDN                ((ber_tag_t) 0x04U)     /* octet string */
 #define LDAP_TAG_LDAPCRED      ((ber_tag_t) 0x04U)     /* octet string */
+
+#ifdef LDAP_CLIENT_UPDATE
+#define LDAP_TAG_COOKIE                ((ber_tag_t) 0x30U)     /* sequence */
+#endif /* LDAP_CLIENT_UPDATE */
+
 #define LDAP_TAG_CONTROLS      ((ber_tag_t) 0xa0U)     /* context specific + constructed + 0 */
 #define LDAP_TAG_REFERRAL      ((ber_tag_t) 0xa3U)     /* context specific + constructed + 3 */
 
@@ -442,6 +461,26 @@ typedef struct ldapcontrol {
 #define LDAP_CLIENT_LOOP                               0x60    /* draft-ietf-ldap-c-api-xx */
 #define LDAP_REFERRAL_LIMIT_EXCEEDED   0x61    /* draft-ietf-ldap-c-api-xx */
 
+#ifdef LDAP_CLIENT_UPDATE
+/* resultCode for LCUP */
+#define LCUP_RESOURCES_EXHAUSTED       0x62
+#define LCUP_SECURITY_VIOLATION                0x63
+#define LCUP_INVALID_COOKIE            0x64
+#define LCUP_UNSUPPORTED_SCHEME                0x65
+#define LCUP_CLIENT_DISCONNECT         0x66
+#define LCUP_RELOAD_REQUIRED           0x67
+#endif /* LDAP_CLIENT_UPDATE */
+
+#ifdef LDAP_CLIENT_UPDATE
+#define SYNCHRONIZE_ONLY       0x00
+#define SYNCHRONIZE_AND_PERSIST        0x01
+#define PERSIST_ONLY           0x02
+#endif /* LDAP_CLIENT_UPDATE */
+
+#ifdef LDAP_CLIENT_UPDATE
+#define LDAP_LCUP_DEFAULT_SEND_COOKIE_INTERVAL 0x01
+#endif /* LDAP_CLIENT_UPDATE */
+
 /*
  * This structure represents both ldap messages and ldap responses.
  * These are really the same, except in the case of search responses,
index 30abec8b259f04faa3b171eb9271b65427b42879..6cdf1cd41bba037cd6387fea1876c253f2a3b91b 100644 (file)
@@ -56,6 +56,13 @@ bdb_search(
        int             nentries = 0;
        int             manageDSAit;
 
+#ifdef LDAP_CLIENT_UPDATE
+       Filter          lcupf, csnfnot, csnfeq, csnfand, csnfge;
+       AttributeAssertion aa_ge, aa_eq;
+       LDAPControl     ctrl;
+       int             entry_count = 0;
+#endif /* LDAP_CLIENT_UPDATE */
+
        struct slap_limits_set *limit = NULL;
        int isroot = 0;
 
@@ -334,6 +341,34 @@ dn2entry_retry:
        filter_hasSubordinates = filter_has_subordinates( filter );
 #endif /* SLAP_X_FILTER_HASSUBORDINATES */
 
+#ifdef LDAP_CLIENT_UPDATE
+       if ( op->o_clientupdatetype == SYNCHRONIZE_ONLY ||
+            op->o_clientupdatetype == SYNCHRONIZE_AND_PERSIST ) {
+               lcupf.f_choice = LDAP_FILTER_AND;
+               lcupf.f_and = &csnfnot;
+               lcupf.f_next = NULL;
+
+               csnfnot.f_choice = LDAP_FILTER_NOT;
+               csnfnot.f_not = &csnfeq;
+               csnfnot.f_next = &csnfand;
+
+               csnfeq.f_choice = LDAP_FILTER_EQUALITY;
+               csnfeq.f_ava = &aa_eq;
+               csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv(&csnfeq.f_av_value, op->o_clientupdatestate);
+
+               csnfand.f_choice = LDAP_FILTER_AND;
+               csnfand.f_and = &csnfge;
+               csnfand.f_next = NULL;
+
+               csnfge.f_choice = LDAP_FILTER_GE;
+               csnfge.f_ava = &aa_ge;
+               csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv(&csnfge.f_av_value, op->o_clientupdatestate);
+               csnfge.f_next = filter;
+       }
+#endif /* LDAP_CLIENT_UPDATE */
+
        for ( id = bdb_idl_first( candidates, &cursor );
                id != NOID;
                id = bdb_idl_next( candidates, &cursor ) )
@@ -529,7 +564,17 @@ id2entry_retry:
 #endif /* SLAP_X_FILTER_HASSUBORDINATES */
 
                /* if it matches the filter and scope, send it */
+#ifdef LDAP_CLIENT_UPDATE
+               if ( op->o_clientupdatetype == SYNCHRONIZE_ONLY ||
+                    op->o_clientupdatetype == SYNCHRONIZE_AND_PERSIST ) {
+                       rc = test_filter( be, conn, op, e, &lcupf );
+               }
+               else {
+                       rc = test_filter( be, conn, op, e, filter );
+               }
+#else /* LDAP_CLIENT_UPDATE */
                rc = test_filter( be, conn, op, e, filter );
+#endif /* LDAP_CLIENT_UPDATE */
 
 #ifdef SLAP_X_FILTER_HASSUBORDINATES
                if ( hasSubordinates ) {
@@ -586,6 +631,7 @@ id2entry_retry:
 #endif
                                                result = send_search_entry( be, conn, op,
                                                        e, attrs, attrsonly, NULL);
+
 #if 0
                                        }
 #endif
@@ -633,6 +679,7 @@ loop_continue:
 
                ldap_pvt_thread_yield();
        }
+
        send_search_result( conn, op,
                v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
                NULL, NULL, v2refs, NULL, nentries );
index 3450172de731121279228db648140f0235a03fcc..d0da95c2bb04a8ff1914038c7af0ddd048c91186 100644 (file)
@@ -50,6 +50,10 @@ static SLAP_CTRL_PARSE_FN parseNoOp;
 static SLAP_CTRL_PARSE_FN parsePagedResults;
 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
 
+#ifdef LDAP_CLIENT_UPDATE
+static SLAP_CTRL_PARSE_FN parseClientUpdate;
+#endif /* LDAP_CLIENT_UPDATE */
+
 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
 
 static struct slap_control {
@@ -81,6 +85,11 @@ static struct slap_control {
        { LDAP_CONTROL_VALUESRETURNFILTER,
                SLAP_CTRL_SEARCH, NULL,
                parseValuesReturnFilter },
+#endif
+#ifdef LDAP_CLIENT_UPDATE
+       { LDAP_CONTROL_CLIENT_UPDATE,
+               SLAP_CTRL_SEARCH, NULL,
+               parseClientUpdate },
 #endif
        { NULL }
 };
@@ -117,6 +126,10 @@ int get_ctrls(
        int rc = LDAP_SUCCESS;
        const char *errmsg = NULL;
 
+#ifdef LDAP_CLIENT_UPDATE
+       op->o_clientupdatetype = -1;
+#endif
+
        len = ber_pvt_ber_remaining(ber);
 
        if( len == 0) {
@@ -595,3 +608,119 @@ int parseValuesReturnFilter (
        return LDAP_SUCCESS;
 }
 #endif
+
+#ifdef LDAP_CLIENT_UPDATE
+static int parseClientUpdate (
+       Connection *conn,
+       Operation *op,
+       LDAPControl *ctrl,
+       const char **text )
+{
+       ber_tag_t tag;
+       BerElement *ber;
+       ber_int_t type;
+       ber_int_t interval;
+       ber_len_t len;
+       struct berval scheme = { 0, NULL };
+       struct berval cookie = { 0, NULL };
+
+       if ( op->o_noop != SLAP_NO_CONTROL ) {
+               *text = "LCUP client update control specified multiple times";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( ctrl->ldctl_value.bv_len == 0 ) {
+               *text = "LCUP client update control value is empty";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       /* Parse the control value
+        *      ClientUpdateControlValue ::= SEQUENCE {
+        *              updateType      ENUMERATED {
+        *                                      synchronizeOnly {0},
+        *                                      synchronizeAndPersist {1},
+        *                                      persistOnly {2} },
+        *              sendCookieInterval INTEGER OPTIONAL,
+        *              cookie          LCUPCookie OPTIONAL
+        *      }
+        */
+
+       ber = ber_init( &ctrl->ldctl_value );
+       if( ber == NULL ) {
+               *text = "internal error";
+               return LDAP_OTHER;
+       }
+
+       if ( (tag = ber_scanf( ber, "{i" /*}*/, &type )) == LBER_ERROR ) {
+               *text = "LCUP client update control : decoding error";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( type != SYNCHRONIZE_ONLY &&
+            type != SYNCHRONIZE_AND_PERSIST &&
+            type != PERSIST_ONLY ) {
+               *text = "LCUP client update control : unknown update type";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( (tag = ber_peek_tag( ber, &len )) == LBER_DEFAULT ) {
+               *text = "LCUP client update control : decoding error";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( tag == LDAP_TAG_INTERVAL ) {
+               if ( (tag = ber_scanf( ber, "i", &interval )) == LBER_ERROR ) {
+                       *text = "LCUP client update control : decoding error";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+               
+               if ( interval <= 0 ) {
+                       /* server chooses interval */
+                       interval = LDAP_LCUP_DEFAULT_SEND_COOKIE_INTERVAL;
+               }
+       }
+       else {
+               /* server chooses interval */
+               interval = LDAP_LCUP_DEFAULT_SEND_COOKIE_INTERVAL;
+       }
+
+       if ( (tag = ber_peek_tag( ber, &len )) == LBER_DEFAULT ) {
+               *text = "LCUP client update control : decoding error";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( tag == LDAP_TAG_COOKIE ) {
+               if ( (tag = ber_scanf( ber, /*{*/ "{mm}}",
+                                       &scheme, &cookie )) == LBER_ERROR ) {
+                       *text = "LCUP client update control : decoding error";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+       }
+
+       /* TODO : Cookie Scheme Validation */
+#if 0
+       if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) {
+               *text = "Invalid LCUP cookie";
+               return LCUP_INVALID_COOKIE;
+       }
+
+       if ( lcup_cookie_scheme_validate(scheme) != LDAP_SUCCESS ) {
+               *text = "Unsupported LCUP cookie scheme";
+               return LCUP_UNSUPPORTED_SCHEME;
+       }
+#endif
+
+       op->o_clientupdatestate = ber_dupbv(NULL, &cookie);
+
+       (void) ber_free( ber, 1 );
+
+       op->o_clientupdatetype = type;
+       op->o_clientupdateinterval = interval;
+
+       op->o_clientupdate = ctrl->ldctl_iscritical
+               ? SLAP_CRITICAL_CONTROL
+               : SLAP_NONCRITICAL_CONTROL;
+
+       return LDAP_SUCCESS;
+}
+#endif
index 173fabc1bacf871cc081b0bfc39b5a213607e43f..af322982a376b6580790b7d67600706937d1b6db 100644 (file)
 #define caseExactOrderingMatch                 caseExactMatch
 #define integerOrderingMatch                   integerMatch
 
+#ifdef LDAP_CLIENT_UPDATE
+#define        octetStringOrderingMatch                octetStringMatch
+#endif /* LDAP_CLIENT_UPDATE */
+
 /* unimplemented matching routines */
 #define caseIgnoreListMatch                            NULL
 #define caseIgnoreListSubstringsMatch  NULL
@@ -4631,6 +4635,15 @@ static slap_mrule_defs_rec mrule_defs[] = {
                octetStringMatch, octetStringIndexer, octetStringFilter,
                NULL},
 
+#ifdef LDAP_CLIENT_UPDATE
+       {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
+               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
+               SLAP_MR_ORDERING, NULL,
+               NULL, NULL,
+               octetStringOrderingMatch, NULL, NULL,
+               NULL},
+#endif /* LDAP_CLIENT_UPDATE */
+
        {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
index 4ed8cc30543b32b2856cb14ed220f5683282d143..b9bf64226eb6ad594e3cd3f703dd6487fe42839e 100644 (file)
@@ -450,6 +450,9 @@ static struct slap_schema_ad_map {
        { "entryCSN", "( 1.3.6.1.4.1.4203.666.1.7 NAME 'entryCSN' "
                        "DESC 'LCUP/LDUP: change sequence number' "
                        "EQUALITY octetStringMatch "
+#ifdef LDAP_CLIENT_UPDATE
+                       "ORDERING octetStringOrderingMatch "
+#endif /* LDAP_CLIENT_UPDATE */
                        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
                        "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
                NULL, SLAP_AT_HIDE,
index a672e1ea86301fd7e7b062bcec3d4173fb1c074f..059cc66f5ca78ed75f99e0588d8340530dd6949b 100644 (file)
@@ -1585,6 +1585,13 @@ typedef struct slap_op {
        ber_int_t o_pagedresults_size;
        PagedResultsState o_pagedresults_state;
 
+#ifdef LDAP_CLIENT_UPDATE
+       char o_clientupdate;
+       ber_int_t o_clientupdatetype;
+       ber_int_t o_clientupdateinterval;
+       struct berval* o_clientupdatestate;
+#endif
+
 #ifdef LDAP_CONNECTIONLESS
        Sockaddr        o_peeraddr;     /* UDP peer address               */
 #endif