I know this is a long shot but is there any way of getting the serial number or a uniquely identifying piece of information on Linux?
If so, how can this be programmed into a Java program?
In context, I need to build a license validator that locks down to one machine. If you have any other suggestions they are welcome.
Here is an excerpt of a blog post by Lennart Poettering about IDs in general. It is about unique IDs, not necessarily about unique IDs in relation with security:
/sys/class/dmi/id/product_uuid: The main board product UUID, as set by the
board manufacturer and encoded in the
BIOS DMI information. It may be used
to identify a mainboard and only the
mainboard. It changes when the user
replaces the main board. Also, often
enough BIOS manufacturers write bogus
serials into it. In addition, it is
x86-specific. Access for unprivileged
users is forbidden. Hence it is of
little general use.
CPUID/EAX=3 CPU serial number: A CPU UUID, as set by the CPU manufacturer
and encoded on the CPU chip. It may be
used to identify a CPU and only a CPU.
It changes when the user replaces the
CPU. Also, most modern CPUs don't
implement this feature anymore, and
older computers tend to disable this
option by default, controllable via a
BIOS Setup option. In addition, it is
x86-specific. Hence this too is of
little general use.
So /sys/class/dmi/id/product_uuid seems like a good candidate for your validation daemon but means that your validation code needs to be run as a privileged user. The full blog post is really a valuable read!
Unless you can actually get a hardware dongle to the users machine, you cannot devise a copy protection setting that cannot be circumvented.
If you just want to tell the user that "hey, you are already running this license on another machine on your network, get another license", then a good way is to do network broadcasts so they can find one another. The simplest way to do reliably is probably using Zeroconf with the jmdns library.
If you want to be certain that the program is only being run at one place with a given serial number, the only way to do so with generic PC's is to have the program call a central mothership over the internet while being run and register where it is being used. The mothership then returns a snippet containing important code needing it to be run. You could most likely implement this using Java WebStart.
I use the MAC-Adress as an unique id.
InetAddress address = InetAddress.getByName("192.168.1.1");
NetworkInterface ni = NetworkInterface.getByInetAddress(address);
byte[] mac = ni.getHardwareAddress();
Mac address can be changed. Check this. Also, Mac-Address is tied to an interface (Ethernet/Wireless/HPNA etc). So a smart user can easily tweak this up. There is a similar problem discussed on stackoverflow. Check this.
The MAC address is not a good choice, as it can be changed on some systems. If you want to stay in native Java then logical system parameters such as the machine ID and user log-in account are your only options. For some cases machine name is adequately secure as there can't be two machines on the one network with the same name.
Related
I have a Java application, and I need it to be high available.
I was thinking of FastMPJ, like running multiple instances on different PCs. Every minute the app will check if master instance is running, and if not, the other will run instead of it.
I'd like to ask if it is a good solution, or if there is any better.
A more general solution is to use a load-balancing system, that is: you have N instances of the application running with the same privileges (if possible on different hardware), then a redundant load-balancer in front selects one of those based on the actual load for each request/task.
The benefit of this solution is obviously, that hardware is actually used and doesn't sit somewhere idle, waiting on the 0.01% case to jump in. Then the instance is actually tested all the time, and errors will be reported when they happen (like faulty hardware), and you prevent a: "Oh... the backup isn't even working". And on top of that you balance the load between machines adaptively.
In one of my project while implementing a exchange we used Apache Qpid for high availability and my experiense was quite satisfaotory. It scales very well too. I have been running application up to 32 node clusters. Please find further details here and let me know in case u need any further infromation:
http://qpid.apache.org/releases/qpid-0.18/books/AMQP-Messaging-Broker-Java-Book/html/High-Availability.html
Hope it helps:)
One often forgets that there must also be high availability from the application to database as well. It is my experience that the data access layer is where most of the application bottlenecks occur. So make sure you have a good application aware DB load balancer. Oracle has a solid solution but is for Oracle databases only. PostGres has an open source version. Heimdall Data is a commercial solution.
Having an issue with the product I code for where our licensing service is unable to find a host MAC address. We don't have much idea why this is happening and it is only happening to very small percentage of users.
The method to get this MAC address is using the Java NetworkInterface methods. If this fails and returns NULL (or users JRE is <1.6) we then fall back to using Sigar to get our address. However it seems this is also failing. The problem is either that it can't obtain the IP address (and then further to this can't get the MAC address) or just can't get the MAC. This issue is happening across all OS' we support (AIX, Solaris, Win7/8, Win Server, Linux & MAC).
As such, my first thought was that these users were enabling the Java security manager (as this is a common factor), but this is looking less likely as I try to reproduce it as this requires a lot of extra configuration steps with permissions to even get our product to run. As such we would have expected to see users asking us for what they need to enable to get our software to run, but this does not happen.
As such I am wondering what is causing this to fail. My only lead now is that it is something lower level (within the OS) that is being enabled to block Java's attempts to natively get this information. I am searching for this now, but it is slow going and an odd thing to search for.
My question is, is this kind of behavior possible (i.e. disabling calling of native methods to discover network info to anything other than trusted code within the OS?), on any/some of the platforms listed above?
Has anyone had this problem before with Java NetworkInterface methods?
We have a master program and agents (both) on the customer side on different computers. The network configuration can be any type (we don't know). The agents connect to the master program and currently we only can get the IP and computer name as information. How do I distinguish if two IPs belong to the same computer?
Computers may have more than one ethernet cards.
Thanks.
There is no way to tell just by looking at the IP addresses.
Some computers have unique identifiers, but you would need JNI to access them and your code would be very platform-specific. It might be a better idea to generate a GUID and write it to a file in a temp folder on the machine. Then, all instances of the software that run on that machine would read the same GUID and can provide this data to the server when a connection is made.
You can modify the agents to send the MAC(s) of the machines in question. Beyond that, you can't really determine if they are the same.
You say you're getting the computer name - can't you de-duplicate based on that value?
From across a network, and given only an IP address, you can't tell. The way NAT works, and the fact that today's laptops and wireless devices often hop from network to network throughout the day, all you see is the public-facing IP address of that machine, which is very likely shared across a group, or entire organization of machines.
Unless you modify the agent application to also include a unique identifier (such as MAC address - which even then only tells you it's a unique NIC, not necessarily a unique machine if machines have multiple NICs), you're out of luck. You can't determine uniqueness from the IP address alone.
Not sure what your use case is, but if it's for banning/tracing actions within the application, then it's better to require some kind of unique identifier for the machine to access the system (such as a username) so you know that you can ban/trace a single instance of the app, or a single user logged into any instance of the app, rather than trying to solve that kind of a problem through IP addresses.
You could create a service in its machine that will expose a unique identifier. You could then call this service using different IPs as the host name and compare the values.
Is there a reliable, cross-platform way to do IPC (between two JVMs running on the same host) in Java (J2SE) that doesn't rely on the network stack?
To be more specific, I have a server application that I'd like to provide a small "monitoring" GUI app for. The monitor app would simply talk to the server process and display simple status information. The server app has a web interface for most of its interaction, but sometimes things go wrong (port conflict, user forgot password) that require a local control app.
In the past I've done this by having the server listen on 127.0.01 on a specific port and the client communicates that way. However, this isn't as reliable as I'd like. Certain things can make this not work (Windows's network stack can be bizarre with VPN adapters, MediaSense, laptops lid closing/power saving modes). You can imagine the user's confusion when the tool they use to diagnose the server doesn't even think the server is running.
Named Pipes seem plausible, but Java doesn't seem to have an API for them unless I'm mistaken. Ideas? Third party libraries that support this? My performance requirements are obviously extremely lax in case that helps.
One of my specialties is really low-tech solutions. Especially if your performance requirements aren't critical:
The low-low tech alternative to named pipes is named FILES. Think yourself up a protocol where one app writes a file and another reads it. If need be, you can do semaphoring between them.
Remember that a rename is pretty much an atomic operation, so you could calmly write a file in some process and then make it magically appear in its entirety by renaming/moving it from somewhere that wasn't previously visible.
You can poll for data by checking for appearance of a file (in a loop with a SLEEP in it), and you can signal completion by deleting the file.
An added benefit is that you can debug your app using the DIR command :)
Depending on how much data you need to pass between the server and the diagnostic tool you could:
go low-tech and have a background thread check a file in the file system; fetch commands from it; write ouput into a second to be picked up by the diagnostic tool.
build a component that manages an input/output queue in shared memory connecting to it via JNI.
Consider JMX. I do not know if any of the Windows JVM's allow JMX over shared memory.
Does Windows even have named pipes? I was going to suggest it. You'd just have to use an exec() to create it.
Map a read_write byte buffer into memory from a FileChannel. Write status information into the byte buffer, then call force() to get it written out. On the monitor side, open up the same file and map it into memory too. Poll it periodically to find out the status.
We have a Java program run as root on Unix, that therefore can read for example the content of the folders /home/user1 and /home/user2. However, if the Unix user "user1" is logged in in our application, he should not be able to access "/home/user2" data.
We would like to use directly the Unix rights and not recreate all the permissions in our application !
So, could we...
try to change the UID of our
program depending on the user logged
in ? Sounds difficult, and each file
access is in different threads so
the UID would be different on each
thread of our program...
use JNI to read permissions of
"/home/user2"...And then determine
if user1 has sufficient permissions
on "/home/user2" ? (how ?).
Use SecurityManager!
Put current unix user id into ThreadLocal
Create your own SecurityManager that checks unix user permissions on checkRead() and checkWrite()
System.setSecurityManager(new MySecurityManager())
Enjoy
Update
There is no, of course, standard library to read unix file permissions. It's not WORA.
But I have tried briefly to find a ready to use library, and found this one:
http://jan.newmarch.name/java/posix/ It uses JNI, but you don't need to write your own JNI code, which is a big relief. :) I'm sure there must also be others.
Class Stat from there gives you all required access information:
http://jan.newmarch.name/java/posix/posix.Stat.html
Update 2
As folks mentioned, this approach fails to check for "non-standard" unix security features, such as ACL or Posix Capabilities (may be; not sure if they apply to files). But if the goal of being totally in sync with host OS security is set, then we even more need to use SecurityManager, because it's a JVM-wide protection mechanism! Yes, we can start a child SUID-process to verify the permissions (and keep it running, talking to it via pipe running while the user is logged in), but we need to do so from SecurityManager!
The simplest and most portable way would be to spawn a child process, have it exec a wrapper written in C which changes the UID, drops all the privileges (be careful, writting a wrapper to do that is tricky - it is as hard as writing a setuid wrapper), and execs another java instance to which you talk via RMI. That java instance would do all the filesystem manipulation on behalf of the user.
For single-threaded Linux programs, you could instead use setfsuid()/setfsgid(), but that is not an option for portable or multithreaded programs.
if you only want the app to be allowed to read files by user1 i strongly suggest the app runs as user1.
If everything else fails, you can run a shellscript from java and parse the result.
Described for example here
For those who were wondering, it's apparently not possible to do this by calling setuid with JNI for each independent thread. setuid affects the whole process, not just the thread that invoked it.
Should you want to call setuid within a single-threaded Java program there's a good example at http://www2.sys-con.com/itsg/virtualcd/Java/archives/0510/Silverman/index.html.
Another option would be to invert the approach: instead of the code running as root most of the time and either changing the user ID or somehow checking the permissions whenever it has to use some restricted resource, run as the user most of the time and talk to a smaller daemon running as root when it needs to do something only root can do. This also has the added benefit of reducing the attack surface.
Of course, you then have to authenticate the connection from the process running as the user to the process running as root.
I am also having the exact problem as Mikael, and got to this page looking for answers.
None of the answers are 100% satisfactionary for me. So I am thinking of 4 alternatives:
Use a Linux group that has access to all the users. Run a single Java app under that group. This Java app can communicate to the 'root' app using whatever means.
Potentially, it can be "hotel"-ed. e.g. 1 "hotel" (app with group permissions) per 100 users (or as appropriate). So if you have 10,000 users you need 100 hotels, which is quite manageable.
Spawn a JVM for each child app under its own user ID. This is like calling a script, but rather than using stdin/stdio/stderr, use any communication protocol. In my case, I'm using XMPP and IO Data (which, since it's already in use by other components, it doesn't matter "where" aka which JVM it runs).
Create a Super-Server 'root' app. This can be part of the original 'root' app or a separate service dedicated to service management.
The Super-Server is responsible for handling incoming requests (i.e. it practically becomes a reverse proxy) for the user-specific sub-apps, and launching the real child apps (if they're not running already), and passing messages back and forth between the client and the child app(s).
Additionally, the child apps can be pooled (or even "passivated", if there's such thing), much in the way Java EE EJB Container does it. So even if there are 10,000 users and (potentially) 10,000 child apps servicing, the maximum number of child apps running are capped. Idle apps are shut down to make room for others.
Same as #3 but rather than creating a proprietary service management mechanism, integrate with Upstart (or the service management framework in the underlying OS). i.e. there is a 'root' service that can control Upstart. Upstart can start, stop, restart, can query the status of the child services, just like it can control mysqld, Apache, etc.
For me, now, the quickest and simplest to implement would be #1. However, my ideal solution would be #4, but it will take time and testing whether it works well. (the concept itself borrows from inetd/xinetd and EJB, so I think it's pretty sound fundamentally)