jcifs.smb.SmbEnumerationUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcifs-ng Show documentation
Show all versions of jcifs-ng Show documentation
A pure-java CIFS/SMB client library
/*
* © 2017 AgNO3 Gmbh & Co. KG
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jcifs.smb;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jcifs.Address;
import jcifs.CIFSContext;
import jcifs.CIFSException;
import jcifs.CloseableIterator;
import jcifs.ResourceFilter;
import jcifs.ResourceNameFilter;
import jcifs.SmbConstants;
import jcifs.SmbResource;
import jcifs.SmbResourceLocator;
import jcifs.dcerpc.DcerpcException;
import jcifs.dcerpc.DcerpcHandle;
import jcifs.dcerpc.msrpc.MsrpcDfsRootEnum;
import jcifs.dcerpc.msrpc.MsrpcShareEnum;
import jcifs.internal.smb1.net.NetShareEnum;
import jcifs.internal.smb1.net.NetShareEnumResponse;
import jcifs.internal.smb1.trans.SmbComTransaction;
import jcifs.internal.smb1.trans.SmbComTransactionResponse;
/**
* @author mbechler
*
*/
final class SmbEnumerationUtil {
private static final Logger log = LoggerFactory.getLogger(SmbEnumerationUtil.class);
/**
*
*/
private SmbEnumerationUtil () {}
private static DcerpcHandle getHandle ( CIFSContext ctx, SmbResourceLocator loc, Address address, String ep )
throws MalformedURLException, DcerpcException {
return DcerpcHandle.getHandle(String.format("ncacn_np:%s[endpoint=%s,address=%s]", loc.getServer(), ep, address.getHostAddress()), ctx);
}
static FileEntry[] doDfsRootEnum ( CIFSContext ctx, SmbResourceLocator loc, Address address ) throws IOException {
try ( DcerpcHandle handle = getHandle(ctx, loc, address, "\\PIPE\\netdfs") ) {
MsrpcDfsRootEnum rpc = new MsrpcDfsRootEnum(loc.getServer());
handle.sendrecv(rpc);
if ( rpc.retval != 0 ) {
throw new SmbException(rpc.retval, true);
}
return rpc.getEntries();
}
}
static FileEntry[] doMsrpcShareEnum ( CIFSContext ctx, SmbResourceLocator loc, Address address ) throws IOException {
try ( DcerpcHandle handle = getHandle(ctx, loc, address, "\\PIPE\\srvsvc") ) {
MsrpcShareEnum rpc = new MsrpcShareEnum(loc.getServer());
handle.sendrecv(rpc);
if ( rpc.retval != 0 ) {
throw new SmbException(rpc.retval, true);
}
return rpc.getEntries();
}
}
static FileEntry[] doNetShareEnum ( SmbTreeHandleImpl th ) throws CIFSException {
SmbComTransaction req = new NetShareEnum(th.getConfig());
SmbComTransactionResponse resp = new NetShareEnumResponse(th.getConfig());
th.send(req, resp);
if ( resp.getStatus() != WinError.ERROR_SUCCESS )
throw new SmbException(resp.getStatus(), true);
return resp.getResults();
}
static CloseableIterator doShareEnum ( SmbFile parent, String wildcard, int searchAttributes, ResourceNameFilter fnf,
ResourceFilter ff ) throws CIFSException {
// clone the locator so that the address index is not modified
SmbResourceLocatorImpl locator = parent.fileLocator.clone();
CIFSContext tc = parent.getContext();
URL u = locator.getURL();
FileEntry[] entries;
if ( u.getPath().lastIndexOf('/') != ( u.getPath().length() - 1 ) )
throw new SmbException(u.toString() + " directory must end with '/'");
if ( locator.getType() != SmbConstants.TYPE_SERVER )
throw new SmbException("The requested list operations is invalid: " + u.toString());
Set set = new HashSet<>();
if ( tc.getDfs().isTrustedDomain(tc, locator.getServer()) ) {
/*
* The server name is actually the name of a trusted
* domain. Add DFS roots to the list.
*/
try {
entries = doDfsRootEnum(tc, locator, locator.getAddress());
for ( int ei = 0; ei < entries.length; ei++ ) {
FileEntry e = entries[ ei ];
if ( !set.contains(e) && ( fnf == null || fnf.accept(parent, e.getName()) ) ) {
set.add(e);
}
}
}
catch ( IOException ioe ) {
log.debug("DS enumeration failed", ioe);
}
}
SmbTreeConnection treeConn = SmbTreeConnection.create(tc);
try ( SmbTreeHandleImpl th = treeConn.connectHost(locator, locator.getServerWithDfs());
SmbSessionImpl session = th.getSession();
SmbTransportImpl transport = session.getTransport() ) {
try {
entries = doMsrpcShareEnum(tc, locator, transport.getRemoteAddress());
}
catch ( IOException ioe ) {
if ( th.isSMB2() ) {
throw ioe;
}
log.debug("doMsrpcShareEnum failed", ioe);
entries = doNetShareEnum(th);
}
for ( int ei = 0; ei < entries.length; ei++ ) {
FileEntry e = entries[ ei ];
if ( !set.contains(e) && ( fnf == null || fnf.accept(parent, e.getName()) ) ) {
set.add(e);
}
}
}
catch ( SmbException e ) {
throw e;
}
catch ( IOException ioe ) {
log.debug("doNetShareEnum failed", ioe);
throw new SmbException(u.toString(), ioe);
}
return new ShareEnumIterator(parent, set.iterator(), ff);
}
@SuppressWarnings ( "resource" )
static CloseableIterator doEnum ( SmbFile parent, String wildcard, int searchAttributes, ResourceNameFilter fnf, ResourceFilter ff )
throws CIFSException {
DosFileFilter dff = unwrapDOSFilter(ff);
if ( dff != null ) {
if ( dff.wildcard != null )
wildcard = dff.wildcard;
searchAttributes = dff.attributes;
}
SmbResourceLocator locator = parent.getLocator();
if ( locator.getURL().getHost().isEmpty() ) {
// smb:// -> enumerate servers through browsing
Address addr;
try {
addr = locator.getAddress();
}
catch ( CIFSException e ) {
if ( e.getCause() instanceof UnknownHostException ) {
log.debug("Failed to find master browser", e);
throw new SmbUnsupportedOperationException();
}
throw e;
}
try ( SmbFile browser = (SmbFile) parent.resolve(addr.getHostAddress()) ) {
try ( SmbTreeHandleImpl th = browser.ensureTreeConnected() ) {
if ( th.isSMB2() ) {
throw new SmbUnsupportedOperationException();
}
return new NetServerFileEntryAdapterIterator(parent, new NetServerEnumIterator(parent, th, wildcard, searchAttributes, fnf), ff);
}
}
}
else if ( locator.getType() == SmbConstants.TYPE_WORKGROUP ) {
try ( SmbTreeHandleImpl th = parent.ensureTreeConnected() ) {
if ( th.isSMB2() ) {
throw new SmbUnsupportedOperationException();
}
return new NetServerFileEntryAdapterIterator(parent, new NetServerEnumIterator(parent, th, wildcard, searchAttributes, fnf), ff);
}
}
else if ( locator.isRoot() ) {
return doShareEnum(parent, wildcard, searchAttributes, fnf, ff);
}
try ( SmbTreeHandleImpl th = parent.ensureTreeConnected() ) {
if ( th.isSMB2() ) {
return new DirFileEntryAdapterIterator(parent, new DirFileEntryEnumIterator2(th, parent, wildcard, fnf, searchAttributes), ff);
}
return new DirFileEntryAdapterIterator(parent, new DirFileEntryEnumIterator1(th, parent, wildcard, fnf, searchAttributes), ff);
}
}
private static DosFileFilter unwrapDOSFilter ( ResourceFilter ff ) {
if ( ff instanceof ResourceFilterWrapper ) {
SmbFileFilter sff = ( (ResourceFilterWrapper) ff ).getFileFilter();
if ( sff instanceof DosFileFilter ) {
return (DosFileFilter) sff;
}
}
return null;
}
static String[] list ( SmbFile root, String wildcard, int searchAttributes, final SmbFilenameFilter fnf, final SmbFileFilter ff )
throws SmbException {
try ( CloseableIterator it = doEnum(root, wildcard, searchAttributes, fnf == null ? null : new ResourceNameFilter() {
@Override
public boolean accept ( SmbResource parent, String name ) throws CIFSException {
if ( ! ( parent instanceof SmbFile ) ) {
return false;
}
return fnf.accept((SmbFile) parent, name);
}
}, ff == null ? null : new ResourceFilter() {
@Override
public boolean accept ( SmbResource resource ) throws CIFSException {
if ( ! ( resource instanceof SmbFile ) ) {
return false;
}
return ff.accept((SmbFile) resource);
}
}) ) {
List list = new ArrayList<>();
while ( it.hasNext() ) {
try ( SmbResource n = it.next() ) {
list.add(n.getName());
}
}
return list.toArray(new String[list.size()]);
}
catch ( CIFSException e ) {
throw SmbException.wrap(e);
}
}
static SmbFile[] listFiles ( SmbFile root, String wildcard, int searchAttributes, final SmbFilenameFilter fnf, final SmbFileFilter ff )
throws SmbException {
try ( CloseableIterator it = doEnum(
root,
wildcard,
searchAttributes,
fnf == null ? null : new ResourceNameFilterWrapper(fnf),
ff == null ? null : new ResourceFilterWrapper(ff)) ) {
List list = new ArrayList<>();
while ( it.hasNext() ) {
try ( SmbResource n = it.next() ) {
if ( n instanceof SmbFile ) {
list.add((SmbFile) n);
}
}
}
return list.toArray(new SmbFile[list.size()]);
}
catch ( CIFSException e ) {
throw SmbException.wrap(e);
}
}
/**
* @author mbechler
*
*/
private static final class ResourceFilterWrapper implements ResourceFilter {
/**
*
*/
private final SmbFileFilter ff;
/**
* @param ff
*/
ResourceFilterWrapper ( SmbFileFilter ff ) {
this.ff = ff;
}
SmbFileFilter getFileFilter () {
return this.ff;
}
@Override
public boolean accept ( SmbResource resource ) throws CIFSException {
if ( ! ( resource instanceof SmbFile ) ) {
return false;
}
return this.ff.accept((SmbFile) resource);
}
}
/**
* @author mbechler
*
*/
private static final class ResourceNameFilterWrapper implements ResourceNameFilter {
/**
*
*/
private final SmbFilenameFilter fnf;
/**
* @param fnf
*/
ResourceNameFilterWrapper ( SmbFilenameFilter fnf ) {
this.fnf = fnf;
}
@Override
public boolean accept ( SmbResource parent, String name ) throws CIFSException {
if ( ! ( parent instanceof SmbFile ) ) {
return false;
}
return this.fnf.accept((SmbFile) parent, name);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy