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.
I'm having the following exception when trying to list shares from an Nvidia Shield TV device
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:
And here is an extract from the server code in jlan (class DCEBuffer, method getString)
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.