/// <summary> /// Returns the next result as an LdapEntry. /// If automatic referral following is disabled or if a referral /// was not followed, next() will throw an LdapReferralException /// when the referral is received. /// </summary> /// <returns> /// The next search result as an LdapEntry. /// </returns> /// <exception> /// LdapException A general exception which includes an error /// message and an Ldap error code. /// </exception> /// <exception> /// LdapReferralException A referral was received and not /// followed. /// </exception> public virtual LdapEntry next() { if (completed && entryIndex >= entryCount && referenceIndex >= referenceCount) { throw new ArgumentOutOfRangeException("LdapSearchResults.next() no more results"); } // Check if the enumeration is empty and must be reloaded resetVectors(); object element = null; // Check for Search References & deliver to app as they come in // We only get here if not following referrals/references if (referenceIndex < referenceCount) { var refs = (string[])references[referenceIndex++]; var rex = new LdapReferralException(ExceptionMessages.REFERENCE_NOFOLLOW); rex.setReferrals(refs); throw rex; } if (entryIndex < entryCount) { // Check for Search Entries and the Search Result element = entries[entryIndex++]; if (element is LdapResponse) { // Search done w/bad status if (((LdapResponse)element).hasException()) { var lr = (LdapResponse)element; var ri = lr.ActiveReferral; if (ri != null) { // Error attempting to follow a search continuation reference var rex = new LdapReferralException(ExceptionMessages.REFERENCE_ERROR, lr.Exception); rex.setReferrals(ri.ReferralList); rex.FailedReferral = ri.ReferralUrl.ToString(); throw rex; } } // Throw an exception if not success ((LdapResponse)element).chkResultCode(); } else if (element is LdapException) { throw (LdapException)element; } } else { // If not a Search Entry, Search Result, or search continuation // we are very confused. // LdapSearchResults.next(): No entry found & request is not complete throw new LdapException(ExceptionMessages.REFERRAL_LOCAL, new object[] { "next" }, LdapException.LOCAL_ERROR, null); } return((LdapEntry)element); }
/// <summary> Returns the next result as an LdapEntry. /// /// If automatic referral following is disabled or if a referral /// was not followed, next() will throw an LdapReferralException /// when the referral is received. /// /// </summary> /// <returns> The next search result as an LdapEntry. /// /// </returns> /// <exception> LdapException A general exception which includes an error /// message and an Ldap error code. /// </exception> /// <exception> LdapReferralException A referral was received and not /// followed. /// </exception> public virtual LdapEntry next() { if (completed && (entryIndex >= entryCount) && (referenceIndex >= referenceCount)) { throw new System.ArgumentOutOfRangeException("LdapSearchResults.next() no more results"); } // Check if the enumeration is empty and must be reloaded resetVectors(); System.Object element = null; // Check for Search References & deliver to app as they come in // We only get here if not following referrals/references if (referenceIndex < referenceCount) { System.String[] refs = (System.String[]) (references[referenceIndex++]); LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERENCE_NOFOLLOW); rex.setReferrals(refs); throw rex; } else if (entryIndex < entryCount) { // Check for Search Entries and the Search Result element = entries[entryIndex++]; if (element is LdapResponse) { // Search done w/bad status if (((LdapResponse) element).hasException()) { LdapResponse lr = (LdapResponse) element; ReferralInfo ri = lr.ActiveReferral; if (ri != null) { // Error attempting to follow a search continuation reference LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERENCE_ERROR, lr.Exception); rex.setReferrals(ri.ReferralList); rex.FailedReferral = ri.ReferralUrl.ToString(); throw rex; } } // Throw an exception if not success ((LdapResponse) element).chkResultCode(); } else if (element is LdapException) { throw (LdapException) element; } } else { // If not a Search Entry, Search Result, or search continuation // we are very confused. // LdapSearchResults.next(): No entry found & request is not complete throw new LdapException(ExceptionMessages.REFERRAL_LOCAL, new System.Object[]{"next"}, LdapException.LOCAL_ERROR, (System.String) null); } return (LdapEntry) element; }
/// <summary> Follow referrals if necessary referral following enabled. /// This function is called only by synchronous requests. /// Search responses come here only if referral following is /// enabled and if we are processing a SearchResultReference /// or a Response with a status of REFERRAL, i.e. we are /// going to follow a referral. /// /// This functions recursively follows a referral until a result /// is returned or until the hop limit is reached. /// /// </summary> /// <param name="queue">The LdapResponseQueue for this request /// /// </param> /// <param name="cons">The constraints that apply to the request /// /// </param> /// <param name="msg">The referral or search reference response message /// /// </param> /// <param name="initialReferrals">The referral array returned from the /// initial request. /// /// </param> /// <param name="hopCount">the number of hops already used while /// following this referral /// /// </param> /// <param name="searchReference">true if the message is a search reference /// /// </param> /// <param name="connectionList">An optional array list used to store /// the LdapConnection objects used in following the referral. /// /// </param> /// <returns> The array list used to store the all LdapConnection objects /// used in following the referral. The list will be empty /// if there were none. /// /// </returns> /// <exception> LdapException A general exception which includes an error /// message and an Ldap error code. /// </exception> /* package */ internal virtual System.Collections.ArrayList chaseReferral(LdapMessageQueue queue, LdapConstraints cons, LdapMessage msg, System.String[] initialReferrals, int hopCount, bool searchReference, System.Collections.ArrayList connectionList) { System.Collections.ArrayList connList = connectionList; LdapConnection rconn = null; // new conn for following referral ReferralInfo rinfo = null; // referral info LdapMessage origMsg; // Get a place to store new connections if (connList == null) { connList = new System.Collections.ArrayList(cons.HopLimit); } // Following referrals or search reference System.String[] refs; // referral list if (initialReferrals != null) { // Search continuation reference from a search request refs = initialReferrals; origMsg = msg.RequestingMessage; } else { // Not a search request LdapResponse resp = (LdapResponse) queue.getResponse(); if (resp.ResultCode != LdapException.REFERRAL) { // Not referral result,throw Exception if nonzero result resp.chkResultCode(); return connList; } // We have a referral response refs = resp.Referrals; origMsg = resp.RequestingMessage; } LdapUrl refUrl; // referral represented as URL try { // increment hop count, check max hops if (hopCount++ > cons.HopLimit) { throw new LdapLocalException("Max hops exceeded", LdapException.REFERRAL_LIMIT_EXCEEDED); } // Get a connection to follow the referral rinfo = getReferralConnection(refs); rconn = rinfo.ReferralConnection; refUrl = rinfo.ReferralUrl; connList.Add(rconn); // rebuild msg into new msg changing msgID,dn,scope,filter LdapMessage newMsg = rebuildRequest(origMsg, refUrl, searchReference); // Send new message on new connection try { MessageAgent agent; if (queue is LdapResponseQueue) { agent = queue.MessageAgent; } else { agent = queue.MessageAgent; } agent.sendMessage(rconn.Connection, newMsg, defSearchCons.TimeLimit, queue, null); } catch (InterThreadException ex) { // Error ending request to referred server LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_SEND, LdapException.CONNECT_ERROR, null, ex); rex.setReferrals(initialReferrals); ReferralInfo ref_Renamed = rconn.Connection.ActiveReferral; rex.FailedReferral = ref_Renamed.ReferralUrl.ToString(); throw rex; } if (initialReferrals == null) { // For operation results, when all responses are complete, // the stack unwinds back to the original and returns // to the application. // An exception is thrown for an error connList = chaseReferral(queue, cons, null, null, hopCount, false, connList); } else { // For search, just return to LdapSearchResults object return connList; } } catch (System.Exception ex) { if (ex is LdapReferralException) { throw (LdapReferralException) ex; } else { // Set referral list and failed referral LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_ERROR, ex); rex.setReferrals(refs); if (rinfo != null) { rex.FailedReferral = rinfo.ReferralUrl.ToString(); } else { rex.FailedReferral = refs[refs.Length - 1]; } throw rex; } } return connList; }
/// <summary> get an LdapConnection object so that we can follow a referral. /// This function is never called if cons.getReferralFollowing() returns /// false. /// /// </summary> /// <param name="referrals">the array of referral strings /// /// /// </param> /// <returns> The referralInfo object /// /// </returns> /// <exception> LdapReferralException A general exception which includes /// an error message and an Ldap error code. /// </exception> private ReferralInfo getReferralConnection(System.String[] referrals) { ReferralInfo refInfo = null; System.Exception ex = null; LdapConnection rconn = null; LdapReferralHandler rh = defSearchCons.getReferralHandler(); int i = 0; // Check if we use LdapRebind to get authentication credentials if ((rh == null) || (rh is LdapAuthHandler)) { for (i = 0; i < referrals.Length; i++) { // dn, pw are null in the default case (anonymous bind) System.String dn = null; sbyte[] pw = null; try { rconn = new LdapConnection(); rconn.Constraints = defSearchCons; LdapUrl url = new LdapUrl(referrals[i]); rconn.Connect(url.Host, url.Port); if (rh != null) { if (rh is LdapAuthHandler) { // Get application supplied dn and pw LdapAuthProvider ap = ((LdapAuthHandler) rh).getAuthProvider(url.Host, url.Port); dn = ap.DN; pw = ap.Password; } } rconn.Bind(Ldap_V3, dn, pw); ex = null; refInfo = new ReferralInfo(rconn, referrals, url); // Indicate this connection created to follow referral rconn.Connection.ActiveReferral = refInfo; break; } catch (System.Exception lex) { if (rconn != null) { try { rconn.Disconnect(); rconn = null; ex = lex; } catch (LdapException e) { ; // ignore } } } } } // Check if application gets connection and does bind else { // rh instanceof LdapBind try { rconn = ((LdapBindHandler) rh).Bind(referrals, this); if (rconn == null) { LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_ERROR); rex.setReferrals(referrals); throw rex; } // Figure out which Url belongs to the connection for (int idx = 0; idx < referrals.Length; idx++) { try { LdapUrl url = new LdapUrl(referrals[idx]); if (url.Host.ToUpper().Equals(rconn.Host.ToUpper()) && (url.Port == rconn.Port)) { refInfo = new ReferralInfo(rconn, referrals, url); break; } } catch (System.Exception e) { ; // ignore } } if (refInfo == null) { // Could not match LdapBind.bind() connecction with URL list ex = new LdapLocalException(ExceptionMessages.REFERRAL_BIND_MATCH, LdapException.CONNECT_ERROR); } } catch (System.Exception lex) { rconn = null; ex = lex; } } if (ex != null) { // Could not connect to any server, throw an exception LdapException ldapex; if (ex is LdapReferralException) { throw (LdapReferralException) ex; } else if (ex is LdapException) { ldapex = (LdapException) ex; } else { ldapex = new LdapLocalException(ExceptionMessages.SERVER_CONNECT_ERROR, new System.Object[]{conn.Host}, LdapException.CONNECT_ERROR, ex); } // Error attempting to follow a referral LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_ERROR, ldapex); rex.setReferrals(referrals); // Use last URL string for the failed referral rex.FailedReferral = referrals[referrals.Length - 1]; throw rex; } // We now have an authenticated connection // to be used to follow the referral. return refInfo; }
/// <summary> /// Returns the next result as an LdapEntry. /// If automatic referral following is disabled or if a referral /// was not followed, next() will throw an LdapReferralException /// when the referral is received. /// </summary> /// <param name="cancellationToken"></param> /// <returns> /// The next search result as an LdapEntry. /// </returns> /// <exception> /// LdapException A general exception which includes an error /// message and an Ldap error code. /// </exception> /// <exception> /// LdapReferralException A referral was received and not /// followed. /// </exception> private async Task <LdapEntry> NextAsync(CancellationToken cancellationToken) { if (_completed && _entryIndex >= _entryCount && _referenceIndex >= _referenceCount) { throw new ArgumentOutOfRangeException("LdapSearchResults.Next() no more results"); } // Check if the enumeration is empty and must be reloaded await ResetVectorsAsync(cancellationToken).ConfigureAwait(false); // Check for Search References & deliver to app as they come in // We only get here if not following referrals/references if (_referenceIndex < _referenceCount) { var refs = _references[_referenceIndex++]; var rex = new LdapReferralException(ExceptionMessages.ReferenceNofollow); rex.SetReferrals(refs); throw rex; } object element; if (_entryIndex < _entryCount) { // Check for Search Entries and the Search Result element = _entries[_entryIndex++]; if (element is LdapResponse) { // Search done w/bad status if (((LdapResponse)element).HasException()) { var lr = (LdapResponse)element; var ri = lr.ActiveReferral; if (ri != null) { // Error attempting to follow a search continuation reference var rex = new LdapReferralException(ExceptionMessages.ReferenceError, lr.Exception); rex.SetReferrals(ri.ReferralList); rex.FailedReferral = ri.ReferralUrl.ToString(); throw rex; } } // Throw an exception if not success ((LdapResponse)element).ChkResultCode(); } else if (element is LdapException) { throw (LdapException)element; } } else { // If not a Search Entry, Search Result, or search continuation // we are very confused. // LdapSearchResults.next(): No entry found & request is not complete throw new LdapException(ExceptionMessages.ReferralLocal, new object[] { "next" }, LdapException.LocalError, null); } return((LdapEntry)element); }