From: Jong Hyuk Choi Date: Mon, 3 Feb 2003 17:28:19 +0000 (+0000) Subject: Intermediate Response X-Git-Tag: NO_SLAP_OP_BLOCKS~447 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=e1bf8cc437cd21381006ea176f82dc92a1728eec;p=openldap Intermediate Response --- diff --git a/include/ldap.h b/include/ldap.h index b746ad773f..361a824439 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -322,6 +322,7 @@ typedef struct ldapcontrol { #define LDAP_RES_COMPARE ((ber_tag_t) 0x6fU) /* application + constructed */ #define LDAP_RES_EXTENDED ((ber_tag_t) 0x78U) /* V3: application + constructed */ #define LDAP_RES_EXTENDED_PARTIAL ((ber_tag_t) 0x79U) /* V3+: application + constructed */ +#define LDAP_RES_INTERMEDIATE_RESP ((ber_tag_t) 0x7aU) #define LDAP_RES_ANY (-1) #define LDAP_RES_UNSOLICITED (0) @@ -683,6 +684,14 @@ ldap_parse_extended_partial LDAP_P(( LDAPControl ***serverctrls, int freeit )); +LDAP_F( int ) +ldap_parse_intermediate_resp_result LDAP_P(( + LDAP *ld, + LDAPMessage *res, + char **retoidp, + struct berval **retdatap, + int freeit )); + /* * in abandon.c: */ diff --git a/libraries/libldap/extended.c b/libraries/libldap/extended.c index 18281bb23e..5a6508f9b8 100644 --- a/libraries/libldap/extended.c +++ b/libraries/libldap/extended.c @@ -393,3 +393,118 @@ free_and_return: return LDAP_SUCCESS; } + +/* Parse an intermediate response result */ +int +ldap_parse_intermediate_resp_result ( + LDAP *ld, + LDAPMessage *res, + char **retoidp, + struct berval **retdatap, + int freeit ) +{ + BerElement *ber; + ber_tag_t rc; + ber_tag_t tag; + ber_len_t len; + struct berval *resdata; + ber_int_t errcode; + char *resoid; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( res != NULL ); + +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ENTRY, "ldap_parse_intermediate_resp_result\n", 0,0,0 ); +#else + Debug( LDAP_DEBUG_TRACE, "ldap_parse_intermediate_resp_result\n", 0, 0, 0 ); +#endif + + if( ld->ld_version < LDAP_VERSION3 ) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + + if( res->lm_msgtype != LDAP_RES_INTERMEDIATE_RESP ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + if( retoidp != NULL ) *retoidp = NULL; + if( retdatap != NULL ) *retdatap = NULL; + + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + + if ( ld->ld_matched ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + + ber = ber_dup( res->lm_ber ); + + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + rc = ber_scanf( ber, "{iaa" /*}*/, &errcode, + &ld->ld_matched, &ld->ld_error ); + + if( rc == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + resoid = NULL; + resdata = NULL; + + tag = ber_peek_tag( ber, &len ); + + if( tag == LDAP_TAG_EXOP_RES_OID ) { + /* we have a resoid */ + if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + return ld->ld_errno; + } + + tag = ber_peek_tag( ber, &len ); + } + + if( tag == LDAP_TAG_EXOP_RES_VALUE ) { + /* we have a resdata */ + if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) { + ld->ld_errno = LDAP_DECODING_ERROR; + ber_free( ber, 0 ); + if( resoid != NULL ) LDAP_FREE( resoid ); + return ld->ld_errno; + } + } + + ber_free( ber, 0 ); + + if( retoidp != NULL ) { + *retoidp = resoid; + } else { + LDAP_FREE( resoid ); + } + + if( retdatap != NULL ) { + *retdatap = resdata; + } else { + ber_bvfree( resdata ); + } + + ld->ld_errno = errcode; + + if( freeit ) { + ldap_msgfree( res ); + } + + return LDAP_SUCCESS; +} diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index ab9a075b47..f6d62b64ef 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -645,7 +645,8 @@ retry_ber: * go through the following code. This code also chases V2 referrals * and checks if all referrals have been chased. */ - if ( (tag != LDAP_RES_SEARCH_ENTRY) && (v3ref > -1) ) { + if ( (tag != LDAP_RES_SEARCH_ENTRY) && (v3ref > -1) && + (tag != LDAP_RES_INTERMEDIATE_RESP ) ) { /* For a v3 search referral/reference, only come here if already chased it */ if ( ld->ld_version >= LDAP_VERSION2 && ( lr->lr_parent != NULL || diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 13bdbe36fc..0f54d412eb 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -416,6 +416,7 @@ long connection_init( c->c_send_search_result = slap_send_search_result; c->c_send_search_reference = slap_send_search_reference; c->c_send_ldap_extended = slap_send_ldap_extended; + c->c_send_ldap_intermediate_resp = slap_send_ldap_intermediate_resp; c->c_authmech.bv_val = NULL; c->c_authmech.bv_len = 0; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index de11528d19..4b26475dfc 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -821,6 +821,13 @@ LDAP_SLAPD_F (void) slap_send_ldap_extended LDAP_P(( const char *rspoid, struct berval *rspdata, LDAPControl **ctrls )); +LDAP_SLAPD_F (void) slap_send_ldap_intermediate_resp LDAP_P(( + Connection *conn, Operation *op, + ber_int_t err, const char *matched, + const char *text, BerVarray refs, + const char *rspoid, struct berval *rspdata, + LDAPControl **ctrls )); + LDAP_SLAPD_F (void) send_ldap_partial LDAP_P(( Connection *conn, Operation *op, const char *rspoid, struct berval *rspdata, diff --git a/servers/slapd/result.c b/servers/slapd/result.c index fcae73adf0..23c4099df7 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -582,6 +582,38 @@ slap_send_ldap_extended( rspoid, rspdata, NULL, ctrls ); } +void +slap_send_ldap_intermediate_resp( + Connection *conn, + Operation *op, + ber_int_t err, + const char *matched, + const char *text, + BerVarray refs, + const char *rspoid, + struct berval *rspdata, + LDAPControl **ctrls ) +{ + ber_tag_t tag; + ber_int_t msgid; +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ENTRY, + "send_ldap_intermediate: err=%d oid=%s len=%ld\n", + err, rspoid ? rspoid : "", + rspdata != NULL ? rspdata->bv_len : 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "send_ldap_intermediate: err=%d oid=%s len=%ld\n", + err, + rspoid ? rspoid : "", + rspdata != NULL ? rspdata->bv_len : 0 ); +#endif + tag = LDAP_RES_INTERMEDIATE_RESP; + msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0; + send_ldap_response( conn, op, tag, msgid, + err, matched, text, refs, + rspoid, rspdata, NULL, ctrls ); +} void slap_send_search_result( diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index a0a1b920d6..152f971462 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1800,6 +1800,22 @@ typedef void (*SEND_LDAP_EXTENDED)( #define send_ldap_extended( conn, op, err, matched, text, refs, rspoid, rspdata, ctrls) \ (*conn->c_send_ldap_extended)( conn, op, err, matched, text, refs, rspoid, rspdata, ctrls ) +typedef void (*SEND_LDAP_INTERMEDIATE_RESP)( + struct slap_conn *conn, + struct slap_op *op, + ber_int_t err, + const char *matched, + const char *text, + BerVarray refs, + const char *rspoid, + struct berval *rspdata, + LDAPControl **ctrls + ); + +#define send_ldap_intermediate_resp( conn, op, err, matched, text, refs, \ + rspoid, rspdata, ctrls) \ + (*conn->c_send_ldap_intermediate_resp)( conn, op, err, matched, text, \ + refs, rspoid, rspdata, ctrls ) /* * Caches the result of a backend_group check for ACL evaluation @@ -1894,6 +1910,7 @@ typedef struct slap_conn { SEND_SEARCH_RESULT c_send_search_result; SEND_SEARCH_REFERENCE c_send_search_reference; SEND_LDAP_EXTENDED c_send_ldap_extended; + SEND_LDAP_INTERMEDIATE_RESP c_send_ldap_intermediate_resp; } Connection; diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index 53131be6d6..dd5dc46eaf 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -57,6 +57,22 @@ slap_send_ldap_extended( assert(0); } +void +slap_send_ldap_intermediate_resp( + Connection *conn, + Operation *op, + ber_int_t err, + const char *matched, + const char *text, + BerVarray refs, + const char *rspoid, + struct berval *rspdata, + LDAPControl **ctrls +) +{ + assert(0); +} + void send_ldap_sasl( Connection *conn,