int ldap_get_entry_controls( LDAP *ld, LDAPMessage *entry, LDAPControl ***sctrls ) { int rc; BerElement be; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( entry != NULL ); assert( sctrls != NULL ); if ( entry->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) { return LDAP_PARAM_ERROR; } /* make a local copy of the BerElement */ AC_MEMCPY(&be, entry->lm_ber, sizeof(be)); if ( ber_scanf( &be, "{xx" /*}*/ ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto cleanup_and_return; } rc = ldap_pvt_get_controls( &be, sctrls ); cleanup_and_return: if( rc != LDAP_SUCCESS ) { ld->ld_errno = rc; if( ld->ld_matched != NULL ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } if( ld->ld_error != NULL ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } } return rc; }
/* Parse an extended partial */ int ldap_parse_intermediate ( LDAP *ld, LDAPMessage *res, char **retoidp, struct berval **retdatap, LDAPControl ***serverctrls, int freeit ) { BerElement *ber; ber_tag_t tag; ber_len_t len; struct berval *resdata; char *resoid; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( res != NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_parse_intermediate\n", 0, 0, 0 ); if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } if( res->lm_msgtype != LDAP_RES_INTERMEDIATE ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } if( retoidp != NULL ) *retoidp = NULL; if( retdatap != NULL ) *retdatap = NULL; if( serverctrls != NULL ) *serverctrls = NULL; ber = ber_dup( res->lm_ber ); if ( ber == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } tag = ber_scanf( ber, "{" /*}*/ ); if( tag == 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 ); /* * NOTE: accept intermediate and extended response tag values * as older versions of slapd(8) incorrectly used extended * response tags. * Should be removed when 2.2 is moved to Historic. */ if( tag == LDAP_TAG_IM_RES_OID || 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; } assert( resoid[ 0 ] != '\0' ); tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_IM_RES_VALUE || 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; } } if ( serverctrls == NULL ) { ld->ld_errno = LDAP_SUCCESS; goto free_and_return; } if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; goto free_and_return; } ld->ld_errno = ldap_pvt_get_controls( ber, serverctrls ); free_and_return: ber_free( ber, 0 ); if( retoidp != NULL ) { *retoidp = resoid; } else { LDAP_FREE( resoid ); } if( retdatap != NULL ) { *retdatap = resdata; } else { ber_bvfree( resdata ); } if( freeit ) { ldap_msgfree( res ); } return ld->ld_errno; }
/* * Parse LDAPResult Messages: * * LDAPResult ::= SEQUENCE { * resultCode ENUMERATED, * matchedDN LDAPDN, * errorMessage LDAPString, * referral [3] Referral OPTIONAL } * * including Bind results: * * BindResponse ::= [APPLICATION 1] SEQUENCE { * COMPONENTS OF LDAPResult, * serverSaslCreds [7] OCTET STRING OPTIONAL } * * and ExtendedOp results: * * ExtendedResponse ::= [APPLICATION 24] SEQUENCE { * COMPONENTS OF LDAPResult, * responseName [10] LDAPOID OPTIONAL, * response [11] OCTET STRING OPTIONAL } * */ int ldap_parse_result( LDAP *ld, LDAPMessage *r, int *errcodep, char **matcheddnp, char **errmsgp, char ***referralsp, LDAPControl ***serverctrls, int freeit ) { LDAPMessage *lm; ber_int_t errcode = LDAP_SUCCESS; ber_tag_t tag; BerElement *ber; Debug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( r != NULL ); if(errcodep != NULL) *errcodep = LDAP_SUCCESS; if(matcheddnp != NULL) *matcheddnp = NULL; if(errmsgp != NULL) *errmsgp = NULL; if(referralsp != NULL) *referralsp = NULL; if(serverctrls != NULL) *serverctrls = NULL; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); #endif /* Find the result, last msg in chain... */ lm = r->lm_chain_tail; /* FIXME: either this is not possible (assert?) * or it should be handled */ if ( lm != NULL ) { switch ( lm->lm_msgtype ) { case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: lm = NULL; break; default: break; } } if( lm == NULL ) { errcode = ld->ld_errno = LDAP_NO_RESULTS_RETURNED; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); #endif goto done; } 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; } if ( ld->ld_referrals ) { LDAP_VFREE( ld->ld_referrals ); ld->ld_referrals = NULL; } /* parse results */ ber = ber_dup( lm->lm_ber ); if ( ld->ld_version < LDAP_VERSION2 ) { tag = ber_scanf( ber, "{iA}", &ld->ld_errno, &ld->ld_error ); } else { ber_len_t len; tag = ber_scanf( ber, "{iAA" /*}*/, &ld->ld_errno, &ld->ld_matched, &ld->ld_error ); if( tag != LBER_ERROR ) { /* peek for referrals */ if( ber_peek_tag(ber, &len) == LDAP_TAG_REFERRAL ) { tag = ber_scanf( ber, "v", &ld->ld_referrals ); } } /* need to clean out misc items */ if( tag != LBER_ERROR ) { if( lm->lm_msgtype == LDAP_RES_BIND ) { /* look for sasl result creditials */ if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) { /* skip 'em */ tag = ber_scanf( ber, "x" ); } } else if( lm->lm_msgtype == LDAP_RES_EXTENDED ) { /* look for exop result oid or value */ if ( ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_OID ) { /* skip 'em */ tag = ber_scanf( ber, "x" ); } if ( tag != LBER_ERROR && ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) { /* skip 'em */ tag = ber_scanf( ber, "x" ); } } } if( tag != LBER_ERROR ) { int rc = ldap_pvt_get_controls( ber, serverctrls ); if( rc != LDAP_SUCCESS ) { tag = LBER_ERROR; } } if( tag != LBER_ERROR ) { tag = ber_scanf( ber, /*{*/"}" ); } } if ( tag == LBER_ERROR ) { ld->ld_errno = errcode = LDAP_DECODING_ERROR; } if( ber != NULL ) { ber_free( ber, 0 ); } /* return */ if( errcodep != NULL ) { *errcodep = ld->ld_errno; } if ( errcode == LDAP_SUCCESS ) { if( matcheddnp != NULL ) { if ( ld->ld_matched ) { *matcheddnp = LDAP_STRDUP( ld->ld_matched ); } } if( errmsgp != NULL ) { if ( ld->ld_error ) { *errmsgp = LDAP_STRDUP( ld->ld_error ); } } if( referralsp != NULL) { *referralsp = ldap_value_dup( ld->ld_referrals ); } } #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); #endif done: if ( freeit ) { ldap_msgfree( r ); } return errcode; }
int ldap_parse_reference( LDAP *ld, LDAPMessage *ref, char ***referralsp, LDAPControl ***serverctrls, int freeit) { BerElement be; char **refs = NULL; int rc; assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( ref != NULL ); if( ref->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { return LDAP_PARAM_ERROR; } /* make a private copy of BerElement */ AC_MEMCPY(&be, ref->lm_ber, sizeof(be)); if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } if ( serverctrls == NULL ) { rc = LDAP_SUCCESS; goto free_and_return; } if ( ber_scanf( &be, /*{*/ "}" ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } rc = ldap_pvt_get_controls( &be, serverctrls ); free_and_return: if( referralsp != NULL ) { /* provide references regradless of return code */ *referralsp = refs; } else { LDAP_VFREE( refs ); } if( freeit ) { ldap_msgfree( ref ); } if( rc != LDAP_SUCCESS ) { ld->ld_errno = rc; if( ld->ld_matched != NULL ) { LDAP_FREE( ld->ld_matched ); ld->ld_matched = NULL; } if( ld->ld_error != NULL ) { LDAP_FREE( ld->ld_error ); ld->ld_error = NULL; } } return rc; }