SmbSessionpublic final class SmbSession extends Object
Fields Summary |
---|
private static final String | LOGON_SHARE | private static final int | LOOKUP_RESP_LIMIT | private static final String | DOMAIN | private static final String | USERNAME | private static final int | CACHE_POLICY | static jcifs.netbios.NbtAddress[] | dc_list | static long | dc_list_expiration | static int | dc_list_counter | int | connectionState | int | uid | Vector | trees | private jcifs.UniAddress | address | private int | port | private int | localPort | private InetAddress | localAddr | SmbTransport | transport | NtlmPasswordAuthentication | auth | long | expiration | String | netbiosName |
Constructors Summary |
---|
SmbSession(jcifs.UniAddress address, int port, InetAddress localAddr, int localPort, NtlmPasswordAuthentication auth)
this.address = address;
this.port = port;
this.localAddr = localAddr;
this.localPort = localPort;
this.auth = auth;
trees = new Vector();
connectionState = 0;
|
Methods Summary |
---|
public static byte[] | getChallenge(jcifs.UniAddress dc)
return getChallenge(dc, 0);
| public static byte[] | getChallenge(jcifs.UniAddress dc, int port)
SmbTransport trans = SmbTransport.getSmbTransport( dc, port );
trans.connect();
return trans.server.encryptionKey;
| public static NtlmChallenge | getChallengeForDomain()
if( DOMAIN == null ) {
throw new SmbException( "A domain was not specified" );
}
synchronized (DOMAIN) {
long now = System.currentTimeMillis();
int retry = 1;
do {
if (dc_list_expiration < now) {
NbtAddress[] list = NbtAddress.getAllByName( DOMAIN, 0x1C, null, null );
dc_list_expiration = now + CACHE_POLICY * 1000L;
if (list != null && list.length > 0) {
dc_list = list;
} else { /* keep using the old list */
dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
if (SmbTransport.log.level >= 2) {
SmbTransport.log.println( "Failed to retrieve DC list from WINS" );
}
}
}
int max = Math.min( dc_list.length, LOOKUP_RESP_LIMIT );
for (int j = 0; j < max; j++) {
int i = dc_list_counter++ % max;
if (dc_list[i] != null) {
try {
return interrogate( dc_list[i] );
} catch (SmbException se) {
if (SmbTransport.log.level >= 2) {
SmbTransport.log.println( "Failed validate DC: " + dc_list[i] );
if (SmbTransport.log.level > 2)
se.printStackTrace( SmbTransport.log );
}
}
dc_list[i] = null;
}
}
/* No DCs found, for retieval of list by expiring it and retry.
*/
dc_list_expiration = 0;
} while (retry-- > 0);
dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
}
throw new UnknownHostException(
"Failed to negotiate with a suitable domain controller for " + DOMAIN );
| synchronized SmbTree | getSmbTree(java.lang.String share, java.lang.String service)
SmbTree t;
if( share == null ) {
share = "IPC$";
}
for( Enumeration e = trees.elements(); e.hasMoreElements(); ) {
t = (SmbTree)e.nextElement();
if( t.matches( share, service )) {
return t;
}
}
t = new SmbTree( this, share, service );
trees.addElement( t );
return t;
| private static NtlmChallenge | interrogate(jcifs.netbios.NbtAddress addr)
UniAddress dc = new UniAddress( addr );
SmbTransport trans = SmbTransport.getSmbTransport( dc, 0 );
if (USERNAME == null) {
trans.connect();
if (SmbTransport.log.level >= 3)
SmbTransport.log.println(
"Default credentials (jcifs.smb.client.username/password)" +
" not specified. SMB signing may not work propertly." +
" Skipping DC interrogation." );
} else {
SmbSession ssn = trans.getSmbSession( NtlmPasswordAuthentication.DEFAULT );
ssn.getSmbTree( LOGON_SHARE, null ).treeConnect( null, null );
}
return new NtlmChallenge( trans.server.encryptionKey, dc );
| void | logoff(boolean inError)
synchronized (transport()) {
if (connectionState != 2) // not-connected
return;
connectionState = 3; // disconnecting
netbiosName = null;
for( Enumeration e = trees.elements(); e.hasMoreElements(); ) {
SmbTree t = (SmbTree)e.nextElement();
t.treeDisconnect( inError );
}
if( !inError && transport.server.security != ServerMessageBlock.SECURITY_SHARE ) {
/*
* Logoff And X Request / Response
*/
SmbComLogoffAndX request = new SmbComLogoffAndX( null );
request.uid = uid;
try {
transport.send( request, null );
} catch( SmbException se ) {
}
uid = 0;
}
connectionState = 0;
transport.notifyAll();
}
| public static void | logon(jcifs.UniAddress dc, NtlmPasswordAuthentication auth)Authenticate arbitrary credentials represented by the
NtlmPasswordAuthentication object against the domain controller
specified by the UniAddress parameter. If the credentials are
not accepted, an SmbAuthException will be thrown. If an error
occurs an SmbException will be thrown. If the credentials are
valid, the method will return without throwing an exception. See the
last FAQ question.
See also the jcifs.smb.client.logonShare property.
logon(dc, 0, auth);
| public static void | logon(jcifs.UniAddress dc, int port, NtlmPasswordAuthentication auth)
SmbTree tree = SmbTransport.getSmbTransport( dc, port ).getSmbSession( auth ).getSmbTree( LOGON_SHARE, null );
if( LOGON_SHARE == null ) {
tree.treeConnect( null, null );
} else {
Trans2FindFirst2 req = new Trans2FindFirst2( "\\", "*", SmbFile.ATTR_DIRECTORY );
Trans2FindFirst2Response resp = new Trans2FindFirst2Response();
tree.send( req, resp );
}
| boolean | matches(NtlmPasswordAuthentication auth)
return this.auth == auth || this.auth.equals( auth );
| void | send(ServerMessageBlock request, ServerMessageBlock response)
synchronized (transport()) {
if( response != null ) {
response.received = false;
}
expiration = System.currentTimeMillis() + SmbTransport.SO_TIMEOUT;
sessionSetup( request, response );
if( response != null && response.received ) {
return;
}
if (request instanceof SmbComTreeConnectAndX) {
SmbComTreeConnectAndX tcax = (SmbComTreeConnectAndX)request;
if (netbiosName != null && tcax.path.endsWith("\\IPC$")) {
/* Some pipes may require that the hostname in the tree connect
* be the netbios name. So if we have the netbios server name
* from the NTLMSSP type 2 message, and the share is IPC$, we
* assert that the tree connect path uses the netbios hostname.
*/
tcax.path = "\\\\" + netbiosName + "\\IPC$";
}
}
request.uid = uid;
request.auth = auth;
try {
transport.send( request, response );
} catch (SmbException se) {
if (request instanceof SmbComTreeConnectAndX) {
logoff(true);
}
request.digest = null;
throw se;
}
}
| void | sessionSetup(ServerMessageBlock andx, ServerMessageBlock andxResponse)
synchronized (transport()) {
NtlmContext nctx = null;
SmbException ex = null;
SmbComSessionSetupAndX request;
SmbComSessionSetupAndXResponse response;
byte[] token = new byte[0];
int state = 10;
while (connectionState != 0) {
if (connectionState == 2 || connectionState == 3) // connected or disconnecting
return;
try {
transport.wait();
} catch (InterruptedException ie) {
throw new SmbException(ie.getMessage(), ie);
}
}
connectionState = 1; // trying ...
try {
transport.connect();
/*
* Session Setup And X Request / Response
*/
if( transport.log.level >= 4 )
transport.log.println( "sessionSetup: accountName=" + auth.username + ",primaryDomain=" + auth.domain );
/* We explicitly set uid to 0 here to prevent a new
* SMB_COM_SESSION_SETUP_ANDX from having it's uid set to an
* old value when the session is re-established. Otherwise a
* "The parameter is incorrect" error can occur.
*/
uid = 0;
do {
switch (state) {
case 10: /* NTLM */
if (auth != NtlmPasswordAuthentication.ANONYMOUS &&
transport.hasCapability(SmbConstants.CAP_EXTENDED_SECURITY)) {
state = 20; /* NTLMSSP */
break;
}
request = new SmbComSessionSetupAndX( this, andx, auth );
response = new SmbComSessionSetupAndXResponse( andxResponse );
/* Create SMB signature digest if necessary
* Only the first SMB_COM_SESSION_SETUP_ANX with non-null or
* blank password initializes signing.
*/
if (transport.isSignatureSetupRequired( auth )) {
if( auth.hashesExternal && NtlmPasswordAuthentication.DEFAULT_PASSWORD != NtlmPasswordAuthentication.BLANK ) {
/* preauthentication
*/
transport.getSmbSession( NtlmPasswordAuthentication.DEFAULT ).getSmbTree( LOGON_SHARE, null ).treeConnect( null, null );
} else {
byte[] signingKey = auth.getSigningKey(transport.server.encryptionKey);
request.digest = new SigningDigest(signingKey, false);
}
}
request.auth = auth;
try {
transport.send( request, response );
} catch (SmbAuthException sae) {
throw sae;
} catch (SmbException se) {
ex = se;
}
if( response.isLoggedInAsGuest &&
"GUEST".equalsIgnoreCase( auth.username ) == false &&
transport.server.security != SmbConstants.SECURITY_SHARE &&
auth != NtlmPasswordAuthentication.ANONYMOUS) {
throw new SmbAuthException( NtStatus.NT_STATUS_LOGON_FAILURE );
}
if (ex != null)
throw ex;
uid = response.uid;
if( request.digest != null ) {
/* success - install the signing digest */
transport.digest = request.digest;
}
connectionState = 2;
state = 0;
break;
case 20:
if (nctx == null) {
boolean doSigning = (transport.flags2 & ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES) != 0;
nctx = new NtlmContext(auth, doSigning);
}
if (SmbTransport.log.level >= 4)
SmbTransport.log.println(nctx);
if (nctx.isEstablished()) {
netbiosName = nctx.getNetbiosName();
connectionState = 2;
state = 0;
break;
}
try {
token = nctx.initSecContext(token, 0, token.length);
} catch (SmbException se) {
/* We must close the transport or the server will be expecting a
* Type3Message. Otherwise, when we send a Type1Message it will return
* "Invalid parameter".
*/
try { transport.disconnect(true); } catch (IOException ioe) {}
uid = 0;
throw se;
}
if (token != null) {
request = new SmbComSessionSetupAndX(this, null, token);
response = new SmbComSessionSetupAndXResponse(null);
if (transport.isSignatureSetupRequired( auth )) {
byte[] signingKey = nctx.getSigningKey();
if (signingKey != null)
request.digest = new SigningDigest(signingKey, true);
}
request.uid = uid;
uid = 0;
try {
transport.send( request, response );
} catch (SmbAuthException sae) {
throw sae;
} catch (SmbException se) {
ex = se;
/* Apparently once a successfull NTLMSSP login occurs, the
* server will return "Access denied" even if a logoff is
* sent. Unfortunately calling disconnect() doesn't always
* actually shutdown the connection before other threads
* have committed themselves (e.g. InterruptTest example).
*/
try { transport.disconnect(true); } catch (Exception e) {}
}
if( response.isLoggedInAsGuest &&
"GUEST".equalsIgnoreCase( auth.username ) == false) {
throw new SmbAuthException( NtStatus.NT_STATUS_LOGON_FAILURE );
}
if (ex != null)
throw ex;
uid = response.uid;
if (request.digest != null) {
/* success - install the signing digest */
transport.digest = request.digest;
}
token = response.blob;
}
break;
default:
throw new SmbException("Unexpected session setup state: " + state);
}
} while (state != 0);
} catch (SmbException se) {
logoff(true);
connectionState = 0;
throw se;
} finally {
transport.notifyAll();
}
}
| public java.lang.String | toString()
return "SmbSession[accountName=" + auth.username +
",primaryDomain=" + auth.domain +
",uid=" + uid +
",connectionState=" + connectionState + "]";
| synchronized SmbTransport | transport()
if( transport == null ) {
transport = SmbTransport.getSmbTransport( address, port, localAddr, localPort, null );
}
return transport;
|
|