mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-23 23:33:07 -05:00
LDAP Client Update Protocol - non-persistent update (TODO: response control ...)
This commit is contained in:
parent
5d062ef54c
commit
4b48c05a8e
6 changed files with 238 additions and 0 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@
|
|||
#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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue