📄 smbtransport.java
字号:
if (log.level >= 4) {
log.println( "New data read: " + this );
jcifs.util.Hexdump.hexdump( log, sbuf, 4, 32 );
}
for ( ;; ) {
/* 01234567
* 00SSFSMB
* 0 - 0's
* S - size of payload
* FSMB - 0xFF SMB magic #
*/
if (sbuf[0] == (byte)0x00 &&
sbuf[1] == (byte)0x00 &&
sbuf[4] == (byte)0xFF &&
sbuf[5] == (byte)'S' &&
sbuf[6] == (byte)'M' &&
sbuf[7] == (byte)'B') {
break; /* all good */
}
/* out of phase maybe? */
/* inch forward 1 byte and try again */
for (int i = 0; i < 35; i++) {
sbuf[i] = sbuf[i + 1];
}
int b;
if ((b = in.read()) == -1) return null;
sbuf[35] = (byte)b;
}
key.mid = Encdec.dec_uint16le( sbuf, 34 ) & 0xFFFF;
/* Unless key returned is null or invalid Transport.loop() always
* calls doRecv() after and no one else but the transport thread
* should call doRecv(). Therefore it is ok to expect that the data
* in sbuf will be preserved for copying into BUF in doRecv().
*/
return key;
}
protected void doSend( Request request ) throws IOException {
synchronized (BUF) {
ServerMessageBlock smb = (ServerMessageBlock)request;
int n = smb.encode( BUF, 4 );
Encdec.enc_uint32be( n & 0xFFFF, BUF, 0 ); /* 4 byte session message header */
if (log.level >= 4) {
do {
log.println( smb );
} while (smb instanceof AndXServerMessageBlock &&
(smb = ((AndXServerMessageBlock)smb).andx) != null);
if (log.level >= 6) {
Hexdump.hexdump( log, BUF, 4, n );
}
}
out.write( BUF, 0, 4 + n );
}
}
protected void doSend0( Request request ) throws IOException {
try {
doSend( request );
} catch( IOException ioe ) {
if (log.level > 2)
ioe.printStackTrace( log );
try {
disconnect( true );
} catch( IOException ioe2 ) {
ioe2.printStackTrace( log );
}
throw ioe;
}
}
protected void doRecv( Response response ) throws IOException {
ServerMessageBlock resp = (ServerMessageBlock)response;
resp.useUnicode = useUnicode;
resp.extendedSecurity = (capabilities & CAP_EXTENDED_SECURITY) == CAP_EXTENDED_SECURITY;
synchronized (BUF) {
System.arraycopy( sbuf, 0, BUF, 0, 4 + HEADER_LENGTH );
int size = Encdec.dec_uint16be( BUF, 2 ) & 0xFFFF;
if (size < (HEADER_LENGTH + 1) || (4 + size) > rcv_buf_size ) {
throw new IOException( "Invalid payload size: " + size );
}
int errorCode = Encdec.dec_uint32le( BUF, 9 ) & 0xFFFFFFFF;
if (resp.command == ServerMessageBlock.SMB_COM_READ_ANDX &&
(errorCode == 0 ||
errorCode == 0x80000005)) { // overflow indicator normal for pipe
SmbComReadAndXResponse r = (SmbComReadAndXResponse)resp;
int off = HEADER_LENGTH;
/* WordCount thru dataOffset always 27 */
readn( in, BUF, 4 + off, 27 ); off += 27;
resp.decode( BUF, 4 );
if (r.dataLength > 0) {
readn( in, BUF, 4 + off, r.dataOffset - off); /* pad */
readn( in, r.b, r.off, r.dataLength ); /* read direct */
}
} else {
readn( in, BUF, 4 + 32, size - 32 );
resp.decode( BUF, 4 );
if (resp instanceof SmbComTransactionResponse) {
((SmbComTransactionResponse)resp).nextElement();
}
}
/* Verification fails (w/ W2K3 server at least) if status is not 0. This
* suggests MS doesn't compute the signature (correctly) for error responses
* (perhaps for DOS reasons).
*/
if (digest != null && resp.errorCode == 0) {
digest.verify( BUF, 4, resp );
}
if (log.level >= 4) {
log.println( response );
if (log.level >= 6) {
Hexdump.hexdump( log, BUF, 4, size );
}
}
}
}
protected void doSkip() throws IOException {
int size = Encdec.dec_uint16be( sbuf, 2 ) & 0xFFFF;
if (size < 33 || (4 + size) > rcv_buf_size ) {
/* log message? */
in.skip( in.available() );
} else {
in.skip( size - 32 );
}
}
void checkStatus( ServerMessageBlock req, ServerMessageBlock resp ) throws SmbException {
resp.errorCode = SmbException.getStatusByCode( resp.errorCode );
switch( resp.errorCode ) {
case NtStatus.NT_STATUS_OK:
break;
case NtStatus.NT_STATUS_ACCESS_DENIED:
case NtStatus.NT_STATUS_WRONG_PASSWORD:
case NtStatus.NT_STATUS_LOGON_FAILURE:
case NtStatus.NT_STATUS_ACCOUNT_RESTRICTION:
case NtStatus.NT_STATUS_INVALID_LOGON_HOURS:
case NtStatus.NT_STATUS_INVALID_WORKSTATION:
case NtStatus.NT_STATUS_PASSWORD_EXPIRED:
case NtStatus.NT_STATUS_ACCOUNT_DISABLED:
case NtStatus.NT_STATUS_ACCOUNT_LOCKED_OUT:
case NtStatus.NT_STATUS_TRUSTED_DOMAIN_FAILURE:
throw new SmbAuthException( resp.errorCode );
case NtStatus.NT_STATUS_PATH_NOT_COVERED:
if( req.auth == null ) {
throw new SmbException( resp.errorCode, null );
}
DfsReferral[] drs = getDfsReferrals(req.auth, req.path, 1);
if (0 == drs.length) {
/* Nov 12, 2008: liuqiang from rst.ricoh.com claims this
* stops AIOBE in certain cases.
*/
throw new SmbException(resp.errorCode, null);
}
SmbFile.dfs.insert(req.path, drs[0]);
throw drs[0];
case 0x80000005: /* STATUS_BUFFER_OVERFLOW */
break; /* normal for DCERPC named pipes */
case NtStatus.NT_STATUS_MORE_PROCESSING_REQUIRED:
break; /* normal for NTLMSSP */
default:
throw new SmbException( resp.errorCode, null );
}
if (resp.verifyFailed) {
throw new SmbException( "Signature verification failed." );
}
}
void send( ServerMessageBlock request, ServerMessageBlock response ) throws SmbException {
connect(); /* must negotiate before we can test flags2, useUnicode, etc */
request.flags2 |= flags2;
request.useUnicode = useUnicode;
request.response = response; /* needed by sign */
if (request.digest == null)
request.digest = digest; /* for sign called in encode */
try {
if (response == null) {
doSend0( request );
return;
} else if (request instanceof SmbComTransaction) {
response.command = request.command;
SmbComTransaction req = (SmbComTransaction)request;
SmbComTransactionResponse resp = (SmbComTransactionResponse)response;
req.maxBufferSize = snd_buf_size;
resp.reset();
try {
BufferCache.getBuffers( req, resp );
/*
* First request w/ interim response
*/
req.nextElement();
if (req.hasMoreElements()) {
SmbComBlankResponse interim = new SmbComBlankResponse();
super.sendrecv( req, interim, RESPONSE_TIMEOUT );
if (interim.errorCode != 0) {
checkStatus( req, interim );
}
req.nextElement();
} else {
makeKey( req );
}
synchronized (response_map) {
response.received = false;
resp.isReceived = false;
try {
response_map.put( req, resp );
/*
* Send multiple fragments
*/
do {
doSend0( req );
} while( req.hasMoreElements() && req.nextElement() != null );
/*
* Receive multiple fragments
*/
long timeout = RESPONSE_TIMEOUT;
resp.expiration = System.currentTimeMillis() + timeout;
while( resp.hasMoreElements() ) {
response_map.wait( timeout );
timeout = resp.expiration - System.currentTimeMillis();
if (timeout <= 0) {
throw new TransportException( this +
" timedout waiting for response to " +
req );
}
}
if (response.errorCode != 0) {
checkStatus( req, resp );
}
} catch( InterruptedException ie ) {
throw new TransportException( ie );
} finally {
response_map.remove( req );
}
}
} finally {
BufferCache.releaseBuffer( req.txn_buf );
BufferCache.releaseBuffer( resp.txn_buf );
}
} else {
response.command = request.command;
super.sendrecv( request, response, RESPONSE_TIMEOUT );
}
} catch( SmbException se ) {
throw se;
} catch( InterruptedException ie ) {
throw new SmbException( ie.getMessage(), ie );
} catch( IOException ioe ) {
throw new SmbException( ioe.getMessage(), ioe );
}
checkStatus( request, response );
}
public String toString() {
return super.toString() + "[" + address + ":" + port + "]";
}
/* DFS */
/* Split DFS path like \fs1.example.com\root5\link2\foo\bar.txt into at
* most 3 components (not including the first index which is always empty):
* result[0] = ""
* result[1] = "fs1.example.com"
* result[2] = "root5"
* result[3] = "link2\foo\bar.txt"
*/
void dfsPathSplit(String path, String[] result)
{
int ri = 0, rlast = result.length - 1;
int i = 0, b = 0, len = path.length();
do {
if (ri == rlast) {
result[rlast] = path.substring(b);
return;
}
if (i == len || path.charAt(i) == '\\') {
result[ri++] = path.substring(b, i);
b = i + 1;
}
} while (i++ < len);
while (ri < result.length) {
result[ri++] = "";
}
}
DfsReferral[] getDfsReferrals(NtlmPasswordAuthentication auth,
String path,
int rn) throws SmbException {
SmbTree ipc = getSmbSession( auth ).getSmbTree( "IPC$", null );
Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
ipc.send( new Trans2GetDfsReferral( path ), resp );
if (rn == 0 || resp.numReferrals < rn) {
rn = resp.numReferrals;
}
DfsReferral[] drs = new DfsReferral[rn];
String[] arr = new String[4];
long expiration = System.currentTimeMillis() + Dfs.TTL * 1000;
for (int di = 0; di < drs.length; di++) {
DfsReferral dr = new DfsReferral();
/* NTLM HTTP Authentication must be re-negotiated
* with challenge from 'server' to access DFS vol. */
dr.resolveHashes = auth.hashesExternal;
dr.ttl = resp.referrals[di].ttl;
dr.expiration = expiration;
if (path.equals("")) {
dr.server = resp.referrals[di].path.substring(1).toLowerCase();
} else {
dfsPathSplit(resp.referrals[di].node, arr);
dr.server = arr[1];
dr.share = arr[2];
dr.path = arr[3];
}
dr.pathConsumed = resp.pathConsumed;
drs[di] = dr;
}
return drs;
}
FileEntry[] getDfsRoots(String domainName, NtlmPasswordAuthentication auth) throws IOException {
MsrpcDfsRootEnum rpc;
DcerpcHandle handle = null;
/* Procedure:
* Lookup a DC in the target domain
* Ask the DC for a referral for the domain (e.g. "\example.com")
* Do NetrDfsEnumEx on the server returned in the referral to
* get roots in target domain
*/
UniAddress dc = UniAddress.getByName(domainName);
SmbTransport trans = SmbTransport.getSmbTransport(dc, 0);
DfsReferral[] dr = trans.getDfsReferrals(auth, "\\" + domainName, 1);
handle = DcerpcHandle.getHandle("ncacn_np:" +
UniAddress.getByName(dr[0].server).getHostAddress() +
"[\\PIPE\\netdfs]", auth);
try {
rpc = new MsrpcDfsRootEnum(domainName);
handle.sendrecv(rpc);
if (rpc.retval != 0)
throw new SmbException(rpc.retval, true);
return rpc.getEntries();
} finally {
try {
handle.close();
} catch(IOException ioe) {
if (log.level >= 4)
ioe.printStackTrace(log);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -