Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to create child URL when trying to list shares #211

Closed
fcatrin opened this issue Mar 19, 2020 · 9 comments
Closed

Failed to create child URL when trying to list shares #211

fcatrin opened this issue Mar 19, 2020 · 9 comments

Comments

@fcatrin
Copy link

fcatrin commented Mar 19, 2020

I'm having the following exception when trying to list shares from an Nvidia Shield TV device

GRAVE: Failed to create child URL
    java.net.MalformedURLException: Name must not be empty
    at jcifs.smb.SmbFile.checkName(SmbFile.java:601)
    at jcifs.smb.SmbFile.<init>(SmbFile.java:466)
    at jcifs.smb.ShareEnumIterator.adapt(ShareEnumIterator.java:94)
    at jcifs.smb.ShareEnumIterator.advance(ShareEnumIterator.java:67)
    at jcifs.smb.ShareEnumIterator.<init>(ShareEnumIterator.java:54)
    at jcifs.smb.SmbEnumerationUtil.doShareEnum(SmbEnumerationUtil.java:173)
    at jcifs.smb.SmbEnumerationUtil.doEnum(SmbEnumerationUtil.java:218)
    at jcifs.smb.SmbEnumerationUtil.list(SmbEnumerationUtil.java:243)
    at jcifs.smb.SmbFile.list(SmbFile.java:1169)
    at smb.test.Test.main(Test.java:51)

Using smbclient and nautilus on Linux I can browse that device without issues.

I've been digging into this problem and I found the cause, but I don't have enough knowledge to know if the problem is in jcifs or it is in the server included with the Nvidia Shield TV which is Alfresco jlan.

What I've found is that within the NetShareEnumAll request (name used by wireshark), just after the server name, jlan expect a 4 byte alignment of the next value, which is the data for Info Level in that request. But in the jcifs code there is no such alignment inserted (class ShareEnumAll, method encode_in). Here is an extract of jcifs:

  _dst.enc_ndr_referent(this.servername, 1);
  if ( this.servername != null ) {
      _dst.enc_ndr_string(this.servername);
  }       // alignment should come here (note by me)
  _dst.enc_ndr_long(this.level);
  int _descr = this.level;
  _dst.enc_ndr_long(_descr);

And here is an extract from the server code in jlan (class DCEBuffer, method getString)

  String str = getString();
  alignRxPosition(align);

where align is a 4 byte alignment.

Without the right alignment, the 32 bit value 01 00 00 00 sent by jcifs is read as 00 00 01 00 by jlan and marked as invalid thus returning error code 02 (WERR_FILE_NOT_FOUND), causing an empty response with jcifs throwing the exception that I put at the beginning.

If I force jcifs to do the alignment, the value is read as 1 by jlan and the share list is returned.

Now, the alignment does not always solve the issue, and this is the part where I got lost. I've seen that jcifs is using the NdrBuffer start address as the base address to calculate the current position to do the alignment (gives around offset 64), while jlan is using the container message as the base address (gives around offset 152), so the alignment fails depending on the info in that message.

The bug totally depends on random factors like the name of the target device, so it may work or it may fail depending on the network name lengths. I tried to look the samba code considering that it always work with that jlan server to see how they do the alignment but without success, it's just too big as a codebase for me right now.

I can prepare an easy test bundle with jlan + jcifs ready to run the test in a unix machine if you need it.

@fcatrin
Copy link
Author

fcatrin commented Mar 20, 2020

As a workaround I changed the servername for "" so the alignment is the same regardless of the server name. According to the spec, this is a valid value.

I've checked again and yes, you are doing the alignment before inserting the long value (this.level), so the calculation may be wrong on the jlan side

@mbechler
Copy link
Contributor

If you have a jlan demo server available, that would be much appreciated.
I haven't found anything obvious yet. Alignment frame of reference sounds interesting, especially concerning the nested objects (however, on first glance this all seems to be 4 byte aligned anyway)

@fcatrin
Copy link
Author

fcatrin commented Mar 23, 2020

Here you can find the jlan server : https://sourceforge.net/projects/alfresco/files/JLAN/Alfresco%20JLAN%205.0/

The code is already built, you only need to set the broadcast address in jlanConfig.xml, then run:
sudo sh runsrv.sh

This is my test client
Test-JCIFS-JLAN.zip

In my original post you can find the relevant client and server classes. As a summary of that post, what I did found is that the base offset for the alignment is different for jcifs and jlan, and in this case there is a two byte difference between both, causing the issue

mbechler added a commit that referenced this issue Apr 13, 2020
The initial pipe transaction response used the byteCount field,
not data length, which includes the optional padding byte.
This results in a zero byte being added to the end of the buffer.
@mbechler
Copy link
Contributor

While I did not get as far as trying the jLAN serer, I think there is a good chance this is caused by the issue described in #210. Could you try master and verify?

@fcatrin
Copy link
Author

fcatrin commented Apr 28, 2020 via email

@mbechler
Copy link
Contributor

mbechler commented May 1, 2020

Thanks for checking, I will have another go at this, hopefully soon.

@mbechler
Copy link
Contributor

Turns out the SMB_COM_TRANSACTION padding algorithm has been wrong all the time (padding two 2 bytes among other things). So this was caused by missing padding before the NetShareEnum structure.

@mbechler
Copy link
Contributor

Please try 593b674

@fcatrin
Copy link
Author

fcatrin commented May 25, 2020

I ran my test and it worked fine. It seems to be fixed now

@fcatrin fcatrin closed this as completed May 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants