From b99b6998e795ec259a13fb5a7d89f1cef8b8f905 Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Wed, 17 Aug 2022 13:04:22 -0500 Subject: [PATCH] Try next DFS referral if fail to find link referral While getReferralTransport() deals with the use case of a failed connection to the referred server, it does not address a successful connection that subsequently fails while calling getReferral. There are probably a number of ways this could occur, but in our case one set of servers where failing with SmbUnsupportedOperationExceptions during getReferral, due to misconfig. In the prior logic, this would cause an immediate failure to find the link, rather than trying the other referrals received from the getRootReferral. The new logic follows the pattern used in getReferralTransport to loop until we either succeed and break out or follow the referrals all the way back to the first option. --- src/main/java/jcifs/smb/DfsImpl.java | 47 +++++++++++++++------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/main/java/jcifs/smb/DfsImpl.java b/src/main/java/jcifs/smb/DfsImpl.java index 307cee2..92fa669 100644 --- a/src/main/java/jcifs/smb/DfsImpl.java +++ b/src/main/java/jcifs/smb/DfsImpl.java @@ -676,34 +676,39 @@ else if ( path.charAt(path.length() - 1) == '\\' ) { } if ( dr == null ) { - try ( SmbTransportInternal trans = getReferralTransport(tf, rootDr) ) { - if ( trans == null ) - return null; + DfsReferralDataInternal currentRootDr = rootDr; + do { + try ( SmbTransportInternal trans = getReferralTransport(tf, currentRootDr) ) { + if ( trans == null ) + return null; - dr = getReferral(tf, trans, domain, domain, trans.getRemoteHostName(), root, path); - if ( dr != null ) { + dr = getReferral(tf, trans, domain, domain, trans.getRemoteHostName(), root, path); + if ( dr != null ) { - if ( tf.getConfig().isDfsConvertToFQDN() && dr instanceof DfsReferralDataImpl ) { - ( (DfsReferralDataImpl) dr ).fixupDomain(domain); - } + if ( tf.getConfig().isDfsConvertToFQDN() && dr instanceof DfsReferralDataImpl ) { + ( (DfsReferralDataImpl) dr ).fixupDomain(domain); + } - dr.stripPathConsumed(1 + domain.length() + 1 + root.length()); + dr.stripPathConsumed(1 + domain.length() + 1 + root.length()); - if ( dr.getPathConsumed() > ( path != null ? path.length() : 0 ) ) { - log.error("Consumed more than we provided"); - } + if ( dr.getPathConsumed() > ( path != null ? path.length() : 0 ) ) { + log.error("Consumed more than we provided"); + } - link = path != null && dr.getPathConsumed() > 0 ? path.substring(0, dr.getPathConsumed()) : "\\"; - dr.setLink(link); - if ( log.isTraceEnabled() ) { - log.trace("Have referral " + dr); + link = path != null && dr.getPathConsumed() > 0 ? path.substring(0, dr.getPathConsumed()) : "\\"; + dr.setLink(link); + if ( log.isTraceEnabled() ) { + log.trace("Have referral " + dr); + } + links.map.put(link, dr); + break; + } + else { + log.debug("No referral found for " + link + ", trying next root referral"); + currentRootDr = currentRootDr.next(); } - links.map.put(link, dr); - } - else { - log.debug("No referral found for " + link); } - } + } while (currentRootDr != rootDr); } else if ( log.isTraceEnabled() ) { log.trace("Have cached referral for " + dr.getLink() + " " + dr);