I use the AclFileAttributeView from Java7 to read the folder permissions of a Windows directory. The problem is that I'm not able to get a complete overview because the AclFileAttributeView doesn't return generic permissions like GENERIC_ALL, GENERIC_WRITE, GENERIC_READ and GENERIC_EXECUTE (the four high-order bits in the access mask). In fact, when it comes to generic permissions it gives me wrong information about other AclEntries for the same member. Let me give an example:
When I use a tool like AccessChk to list the AclEntries of c:\windows for the System account I get the following:
[2] ACCESS_ALLOWED_ACE_TYPE: NT AUTHORITY\SYSTEM
FILE_ADD_FILE
FILE_ADD_SUBDIRECTORY
FILE_LIST_DIRECTORY
FILE_READ_ATTRIBUTES
FILE_READ_EA
FILE_TRAVERSE
FILE_WRITE_ATTRIBUTES
FILE_WRITE_EA
DELETE
SYNCHRONIZE
READ_CONTROL
[3] ACCESS_ALLOWED_ACE_TYPE: NT AUTHORITY\SYSTEM
[OBJECT_INHERIT_ACE]
[CONTAINER_INHERIT_ACE]
[INHERIT_ONLY_ACE]
GENERIC_ALL
As you can see the first AclEntry only applies to the folder itself and has not the special permissions WRITE_ACL and WRITE_OWNER.
The second AclEntry applies only to subfolders and files and contains the generic permission GENERIC_ALL. This is exactly how I see it in the Security tab of Windows Explorer. Two records for the System account, one applies only to the folder (with a subset of permissions) and one applies to subfolders/files with Full control.
Now I run my java program using the following code:
AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class);
System.out.println(view.getAcl());
This gives my the following results for the System account:
NT AUTHORITY\SYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
NT
AUTHORITY\SYSTEM:FILE_INHERIT/DIRECTORY_INHERIT/INHERIT_ONLY:ALLOW
The first AclEntry applies only to the folder itself and contains all the special permissions, including WRITE_ACL and WRITE_OWNER, which is not correct! The second AclEntry doesn't show any permissions, because it has GENERIC_ALL on it!
I'm not sure where this goes wrong, it seems the JRE just decodes the ACE bitmask given by the OS (sun.nio.fs.WindowsSecurityDescriptor.decode).
Has anyone experienced these same issues? I will try some other JRE's, perhaps that makes a difference.
I too ran into this same issue. As it turns out the spec for AclFileAttributeView states it is designed to be compatible with RFC 3530: Network File System (NFS) version 4 Protocol. In RFC 3530, there is no support for GENERIC_* values. I also looked at the JDK code source (From OpenJDK project downloaded from here) which runs the JVM. While it seems to me that there would be a way to make the JVM compatible by mapping from the appropriate RFC 3530 flags to and from GENERIC_*, the maintainers clearly have not. This is the reason for your empty entry NT AUTHORITY\SYSTEM:FILE_INHERIT/DIRECTORY_INHERIT/INHERIT_ONLY:ALLOW
Worse yet, the JVM does NOT support the SE_DACL_PROTECTED and SE_SACL_PROTECTED flags from Windows Security descriptors (which are set via the meta flags (UN)PROTECTED_(S/D)ACL_SECURITY_INFORMATION as indicated in comments here. If you use the tool AccessChk, it actually shows you the effective ACE list not the actual ACE list, which AclFileAttributeView and other Windows tools do (look at FileTest.) This is the reason why the number of ACEs are different. In my case, I had 9 ACEs but AccessChk showed 5. 4 out of those 9 where really duplicates on the SID (the user or group) value where the 1st ACE for a given SID had permissions and the 2nd ACE for a given SID had NO permissions, but just the SE_DACL_PROTECTED set or not set.
I'm not entirely sure what it is you wanted to DO with these ACLs, but I may have a solution for you depending upon your intent. I went ahead and made changes to the JNA project to start allowing one to modify Windows Security Descriptors in a more direct way. You can see my merged pull request here. I don't know how often they publish versions to the Maven public repo, so you may have to download and compile the source directly to get those changes. See the GetNamedSecurityInfo for how to get the SD of an object. Then, you can use the help APIs in AdvApi32Util to maninuplate the SECURITY_DESCRIPTOR objects. See public static SECURITY_DESCRIPTOR_RELATIVE getFileSecurityDescriptor(File file, boolean getSACL) for a way to get the SD into self relative format and then that object allows you to walk the ACEs in the ACL.
I ended up using reflection to get the ACE's access mask (using
sun.nio.fs.WindowsNativeDispatcher.GetAce). With the access mask I check the four high order bits to determine the generic permissions.
It also allows me to get the INHERITED_ACE bit, which is not available in the JRE spec. I get the 'raw' ACL information, which is a lot more then the Windows Security tab. For example, my c:\ drive gives me two ACE's for the BUILT-IN\Administrators, one with GENERIC_ALL permissions and propagation to subfolders and files (not the container itself), and one with the applied special permissions having no flags at all (only applied on the current container). That's how Windows uses these Generic permissions. The same applies for the subfolders, like the Program Files directory, Generic permissions are propagated and every sub container has a separate ACE for the actual special permissions that apply only to the container itself.
About the tool AccessChck, are you sure you use the -l parameter? This gives a lot more information and the 'raw' ACL information.
I already use the JNA Project to retrieve local groups from a server. Thanks for the tip about the AdvApi32Util! I will look into it. How was your experience with the setACL method in the JRE?
I use all this to release a tool that combines group membership from a LDAP with the ACL information found in the directories and files. All this information is saved in a local database (or external) and can be used to create overviews. This overview offers a lot of filter options and displays permission info for a specific user or a group of users (including nested group membership). Because everything is saved in a database, it gives you overviews in seconds instead of scanning the whole network every time. You can also trace permissions, it displays where permissions come from, from what group membership or from what folder, etc. It will contain a feature to modify a single ACE, but the focus is on viewing permissions.
The tool is ready for testing ;) Let me know if you're interested... The tool won't be for free because it took me a hell of a lot time to write, but let me know if you're interested. I can get you a license. See the following links for a quick impression. Don't mind the website, it still mentions an old version of the tool.
Scan screenshot
Overview screenshot
Permission Analyzer 64bit
Permission Analyzer 32bit
Permission Analyzer 64bit with embedded JRE
Permission Analyzer 32bit with embedded JRE
Related
We would like to brand a piece of software based on which customer's website it is downloaded from. E.g. by showing the customer's logo etc. All we need is an ID, the software can handle the rest of the customization at runtime based on that.
The number of customizations is potentially large, and we would like to avoid prebuilding and storing these installers.
I'm open to consider all options, especially some out-of-the-box ideas.
I think it is impossible to change a signed installer (exe/dmg) without breaking the signature.
Some ideas I'm toying with (and their trade-offs):
Store the ID in the installer download filename (Con: Brittle, browsers might change the name or append a suffix to avoid duplicate names)
Ask the user to enter a code shown on the download page (Con: some inconvenience for the user)
Provide a zip with installer and config-file next to it (Con: some users will not manage to unzip, or only unzip the installer without the config file)
On Linux the installer shell script can be modified at download time, as the script cannot be signed.
Set up a server that builds and signs installers on the fly at the time of the download request. To speed this up, it could be yet another installer wrapping the main installer, and it's only task would be to extract and run the main installer with the ID parameter. (Con: complex infrastructure, code signing certificates on the public facing server, very slow for MacOS notarization)
Chromium-based browsers like Google Chrome, Chromium, Opera, Microsoft Edge, etc. save the URL of origin and the referrer URL for all downloaded files on Windows 10 (only on NTFS file systems) and Linux (only on Ext4).
For details see for example here. On Windows the metadata is also accessible from command line or direcly from Java.
There seems to be a similar feature on Mac. See for example this question on superuser.
Accessing this metadata from within your installer could help to customize the behavior of your installer. While the data will not be available in all setups (e.g. Internet Explorer stores only a zone ID and no URL) and may get lost (e.g. a user deletes the data or copies the file to a file system that does not support metadata) it could propably cover the majority of your users. Asking users to enter a code when the metadata is not found could still be used as a fallback.
Main concern I would have with this approach is that the Chromium developers may decide to remove this feature in near future or make it optional, like the developers of wget (see for example here)
On latest Windows 10 I still get the following metadata for a downloaded file with both, latest Google Chrome and Microsoft Edge Browser:
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://httpd.apache.org/
HostUrl=https://mirror.klaus-uwe.me/apache//httpd/httpd-2.4.46.tar.bz2
i am working on a method to import files which are stored on an usb device to my database.
I already done it for Mac and Windows, but I don't know how to get the path to the usb device when the application is used under Linux/Ubuntu with java.
Is there a way to find the path?
I don't think there is any way that is guaranteed to work on all Linux systems. There are a few approaches I have used, with varying degrees of success.
A method that requires no external utilities is to enumerate and parse the pseudo-files in /dev/disk, /proc/mounts, and /sys/bus/usb, and build a representation of the USB devices that hold storage. There might be more than one, so you might still have to make some guesses, or offer users a choice. This is a pretty tedious method, but I think it is the most general. You can just look at /media, /run/media, as somebody else suggested, but this only works on some Linux installations, and only if that form of auto-mounting is enabled.
A less tedious approach is to invoke the utility udisksctl from your program. I think this utility exists for almost all Linux variants, but it isn't always installed by default. The output of the utility has to be parsed, but it's less hassle that working directly with the kernel psedofiles.
To get a list of disk devices, execute udisksctl status. This will tell you the model name, which will often include the text "USB", and the block device (e.g., /dev/sdb). Then you can execute udisksctl info -b /dev/sdb and look for the line that begins "MountPoints". If the device is not mount you could, if you wished, force it by executing udisksctl mount.... There's a heap of other useful stuff that udisksctl can do -- see its man page.
In Java you can use Runtime.exec() to run udisksctl, but it's probably friendlier to users to check that it is installed first, by check for the existence of /usr/bin/udisksctl.
The easiest way I found is using the Volumes directory.
/Volumes/NAME_OF_USB_DRIVE/file.whatever
Some relevant background:
My application is a Java app compiled into a .exe via JSmooth. The anticipated user base would likely be a few hundred users, but could grow well beyond that, as it's a community specific application.
How it works:
2 .jar files, one that preforms initial checks, another with the meat of the application.
Ideally, the init jar displays the splash, checks the version in desktop.txt against server.txt, if they differ, it prompts the user to update.
What I need to figure out:
1) What is a cheap, scalable hosting service that I could use as the file host for updates?
2) How can I create an "updater" to actually preform the jar replacement? My current solution is simply writing an updater in Java, but I was hoping for something like the installers people are more familiar with.
All of the research I've done has resulted in lackluster results, as 99% of hosting searches result in site hosting results. I just need an update repository with reasonable security. i.e., decent DDoS resistance and not left wide open to the Internet.
Edit: formatting
Easy to do and very foolish cheap with Amazon S3 or Joyent Manta as both support time-limited signed URLs and headers (which can contain a SHA-1 of the file) to check to see if the update is needed before downloading
On startup your app would check the update URL to see if it has changed. If it has changed, download the JARs. Do this before the app loads classes from those JARs. Updating the updater itself will be trickier so consider that an update might need a new update URL to prevent expiry.
I would like to associate a specific file type with my application, so when I double-click one of the files of this specific type, my application opens. This works just fine, but the file I double-clicked does not get passed as an argument to my program.
If I for instance associate my application with txt files and I double-click todo.txt, my application opens, but I have no idea which txt file I double-clicked.
From what I can read, this is how it's supposed to work on OS X, and instead of relying on the default behaviour (how it works on e.g. Windows), I should use ApplicationListener.handleOpenFile(); from com.apple.eawt. When I attempt this, however, I'm being told that I'm not allowed to do so:
Access restriction: The type ApplicationListener is not accessible due
to restriction on required library
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/ui.jar
In another question here, one guy says he found the solution on some Chinese website, and the other says it isn't legal according to Java's license agreement terms.
I can find no mention of it in the Mac OS X Developer Library, and whatever links might seem useful on this site about JAR Bundler just sends me to a dead page on Apple's Developer site.
What am I missing? Is it supposed to be nearly impossible to do this, even though it's trivial on other operating systems?
It's probably worth mentioning... since JARfiles can't be associated with programs on OS X, I've created an OS X Application Bundle using JAR Bundler; an Apple tool made specifically for the purpose of being able to treat Java applications as native OS X applications. Using this is what allowed me to associate the file type with my application in the first place.
I've used OSXAdapter for preferences, about, and quit functionality. You might be able to leverage it's introspective approach to avoid the restriction. As com.apple.eawt.ApplicationListener is deprecated, you might try com.apple.eawt.OpenFilesHandler instead.
My Java application is saving stuff in 'user.home' but on windows this does not seem to be the correct path to save application information (as a friend told me). An other option is using the preferences api but it's not possible to set up the hsqldb location using the preferences api. Also, I want all files to be available in the same folder (local database, config, cache, ...).
I'm looking for some example code or a framework that takes care of os-specific stuff.
On my WinXP Pro SP3 system, user.home points to C:\Documents and settings\<username>
Lot of applications just store their data there (instead of this path + Application data, but some others go down to there), creating a directory in Unix style, ie. dot + application name (examples: .antexplorer, .sqlworkbench, .squirrel-sql, .SunDownloadManager, .p4qt, .gimp-2.4, etc.).
Looks like a decent, common practice...
It's unusual for a window app to save data in user.home but not "wrong". Windows applications love to spread their data all over the place (a bit in the registry, a bit in the application's install directory, a bit in the Windows directory, a bit in System32, a bit here and a bit there). In the end, this makes it impossible to cleanly backup or remove something which results in the famous "Windows rot" (i.e. you have to reinstall every few months).
Anyway. If you really don't want to use user.home (and I see no reason not to), use code like this from Apache commons-lang to figure out if you're running on Windows. If this yields true, pop up a directory selection dialog where the user can specify where they want to save their data.
Save this information in Preferences and use this path the next time when your app is started. This way, users can specify where they want their data and you only have to leave one bit of information in the prefs.
For an application "foo" I'd create a directory named ".foo" inside user.home. For Windows it will look slightly strange, but almost noone ever looks in that directory (and it's filled with obscure directories anyway) and on Linux/Solaris/... it will result in a hidden directory that doesn't clutter the users home directory visually.
dynamically read (from your code) the value of APPDATA environment variable, and store your config files in %APPDATA%\\.myapp\config
==> value is platform dependent, do not use any hard-coded paths, always read the env. var.
The problem is not Wiindows but the standard java setup.
Long Discussion
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4787931>Here
I would advise picking this up on a '-D MYLOC=%USERPROFILE%' property on the command line.
Note that you will only get a "USERPROFILE" if the user did a desktop login, this does not get set if the user logged in remotly with citrix or similar or via ssh, also, coprporate desktops mess around with this setting and may set it to something unusable.