I have read everywhere that unsigned Java applets are not allowed to make network connections to any server but the one which originated the applet. This is OK for my application since my applet only needs to talk to the server. However, when I wrote a test applet to try opening a socket to communicate with a process on my development machine, it throws the following exception:
Error establishing socket connection:
java.security.AccessControlException:
access denied (java.net.SocketPermission 127.0.0.1:11000 connect,resolve)
The code which caused the exception:
private void sendMsg(String msg) {
Socket s = null;
try {
s = new Socket("localhost", 11000);
}
catch (Exception e) {
System.err.println("Error establishing socket connection:");
e.printStackTrace();
return;
}
try {
OutputStream out = s.getOutputStream();
out.write(msg.getBytes());
out.flush();
s.shutdownOutput();
s.close();
}
catch (Exception e) {
System.err.println("Error in writing to the socket:");
e.printStackTrace();
}
At first I thought it was a problem in my code that my inexperience had caused me to miss. However, I get the same exception when trying to run the Talk Server example from the official Java Tutorials. This leads me to believe that I actually have a setup problem, or a misunderstanding of the default security restrictions. Does the default security manager prevent you from opening sockets to the machine running the applet even if it is also the machine serving the applet? If so, that is a problem for me because the deployed system will need to allow a user logged in on the actual server to use the same applet that a remote user would use. Is there a way around the exception I'm getting that doesn't involve signing the applet? I don't want to go to the trouble if not necessary.
NOTE: I know it would be better not to have users access the applet from the server. That wasn't the original design, but practical considerations unfortunately forced this implementation compromise on me.
UPDATE: Viewing the applet's page from a webserver solves the problem. Even if the server is localhost. The security update in Java 1.6.0_11 only applies to applets loaded directly from the local file system.
This is due to a change in the PlugIn introduced in a recent security update. Sorry! Applets loaded from the local file system are no longer granted socket permissions to localhost.
Solution 246387 : A Security Vulnerability in the Java Runtime Environment may Allow Code Loaded From the Local Filesystem to Access LocalHost
The Java Runtime Environment (JRE)
allows code loaded from the local
filesystem to access localhost. This
may allow code that is maliciously
placed on the local filesystem and
then subsequently run, to have network
access to localhost that would not
otherwise be allowed if the code were
loaded from a remote host. This may be
leveraged to steal cookies and hijack
sessions (for domains that map a name
to the localhost).
I suspect you're running the applet from a local HTML file (eg applet.html), which brings up the error Tom Hawtin mentions.
Instead run a webserver (eg Tomcat) on your machine and access the file through http://localhost/applet.html
It would be probably be better to open the socket port from a servlet in your webserver too. This way your webserver manages your whole system, and it can be simpler to transfer between machines.
I use the same setup regularly with socket connection between applet and servlet on both localhost and live.
Oracle knows of this Java problem that severely restricts use of Applets: A Security Vulnerability in the Java Runtime Environment may Allow Code Loaded From the Local Filesystem to Access LocalHost is what they're saying. This was Bug Id 6704154
And their solution is: There is no workaround for this issue; this 'workaround' was issued 03-Dec-2008. So, if you wish to use Applets with Tomcat or any like server, you'll have to go back to Java 1.4.2
It took me over a week to fully document these facts and since I'm in the same boat.
Related
I have a java application that I programmed, and I also created a Wampserver database to store the app's data. When I install the application in another computer, it basically can't do anything because wampserver isn't installed on that computer, and even if it was, the database wouldn't be imported on that same computer.
Can I install the database with the program itself, without making a database server in my computer? (For security reasons)
Sorry if this is a dumb question, im new to programming.
Assuming you are doing this in a Home/office environment. Where your IP Addresses do not change so often. Or you have the power to assign them statically.
You could try using a multi-threaded client server model. Where your wampserver computer(server) will accept a connection from another computer(client), and from there any queries to the database will be handled by that thread. This way, you could get away without installing wampserver on every client.
It would require some networking codes to be added to your java program. There are many examples on multi-threaded client server model -> Multithreading with client server program
You can open your MySQL server to the outside world or to certain IP (comment or edit bind value in your MySQL configuration file).
This can be a security issue. What is your objective? Usually, you'd do an API allowing access to your data from your application.
You are talking about "hosting" your database. You need to either:
Create, develop, and run a hosting service (not trivial), or
Pay to one the myriad of hosting services available, and install your database there (cheap these days). Just a couple of well known examples: Digital Ocean or Amazon Web Services.
In any case, it's a huge security risk to open your database to any client online.
Normally you write a program/application that accesses the database in the same [local] network, and that application serves web pages (or other web service) to the world.
It seems that with the latest Java update, 1.7.0u45, my JNLP application that is supposed to connect to a server is instead forced to try and connect to localhost for some reason that I cannot quite seem to figure out.
I know that some other changes have been made, such as requiring the Permissions attribute in the manifest and some such things, which I'm currently trying to figure out a reasonable way to comply to, but I cannot find anything that ought to cause this behavior.
My code just does an ordinary Socket.connect call to a specific server, but what happens is that the connection is instead made to localhost. This only happens when the code is running in the JNLP client; not when I run it "manually" by starting the VM on it.
Does anyone know why this is?
At last, I managed to figure out what was happening. It was not, in fact, that connections as such were being redirected, but rather that the JNLP client has started blocking JNLP files that are not signed from setting system properties with certain names. Particularly, only properties whose names begin with jnlp are, it seems, guaranteed to be configurable by unsigned JNLP files.
The problem, therefore, was that I specified what server to connect to via a system property whose name did not begin with jnlp, and it then being blocked (since my JNLP file isn't signed) led to my program using its default server specification instead, being localhost.
I am trying to achieve a TCP connection between a JavaScript client and a java server. (implementation must be this way I cannot swap to node for the server for example ).
Web sockets implmentation in java looked very complicated. I had a look at Jetty and JWebSocket and was quickly scared off. I have no idea what is going on in the source for them. – So I didn’t have much luck implementing a server using them.
So then I looked for websocket alternatives.
I noticed SocketBridge, It seems very straight forwards and offers exactly what I need for my project so I downloaded that.
I created a simple java server that just prints what I receives and sends a string as bytes back. I used the prebuilt JavaSocketBridge and modified the index.html to point to my server. My server recived the message but nothing showed up on the client.
function run(){
socket_connect('localhost', 31113);
socket_send("Hello from JavaSocketBridge applet");
}
I then decided to build the JavaSocketBridge to see if I could debug the read methods. However my build of JavaSocketBridge refuses to connect with the error.
Java Socket Bridge ERROR: Could not connect to localhost on port 31113
Access denied (“java.net.SocketPermission” “127.0.0.1:31113” “connect,resolve” )
(This was in chrome but it happens in firefox too)
So my questions:
Why does my build get a socket permission error?
Why does the client not receive anything even though the example does from google.com:80?
Notes.
My server appears to be working fine. (I have used a simple java client to test it.
I have used java 1.6 and 1.7 to build the JavaSocketBridge)
I have included C:\Program Files\Java\jre7\lib\plugin.jar
My System is Win7 64 and java SDK / JRE is up to date
Edit. Ive gone back to jetty and got a client/server working, however I will monitor this question.
I have an applet that throws this exception when trying to communicate with the server (running on localhost). This problem is limited to Applets only - a POJO client is able to communicate with the exact same server without any problem.
Exception in thread "AWT-EventQueue-1" java.security.AccessControlException: access denied (java.net
.SocketPermission 127.0.0.1:9999 connect,resolve)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
My applet.policy file's contents is:
grant {
permission java.security.AllPermission;
};
My question is what are the other places where I need to modify my security settings to grant an Applet more security settings?
Thank you.
EDIT: Further investigation has lead me to find that this problem only occurs on some machines - but not others. So it could be a machine level (global) setting that is causing this, rather than a application-specific setting such as the one in the applet.policy file.
EDIT: Another SO question: Socket connection to originating server of an unsigned Java applet
This seems to describe the exact same problem, and Tom Hawtin - tackline 's answer provides the reason why (a security patch released that disallows applets from connecting to localhost). Bearing this in mind, how do I grant the applet the security settings such that in can indeed run on my machine. Also why does it run as-is on other machines but not mine?
Seeing this: http://sunsolve.sun.com/search/document.do?assetkey=1-66-246387-1, it's clear that Applets run from localhost (without being deployed to a web server) cannot access localhost.
There is no workaround for this issue as indicated
4. Workaround
There is no workaround for this issue.
Please see the Resolution section
below.
My suggestion is as follows:
Signing a Jar file to get more security privileges (http://java.sun.com/docs/books/tutorial/deployment/jar/signindex.html)
It stipulates:
Users who verify your signature can
grant your JAR-bundled software
security privileges that it wouldn't
ordinarily have.
Running your applet from a web server (such as Tomcat) and accessing it locally through your browser.
I've recently gotten my hobby java project embedded into a page thanks to this very site, but now I'm having some security issues.
I have the include:
import java.sql.*;
and the line:
Class.forName("com.mysql.jdbc.Driver").newInstance();
as well as a mysql .jar file in my src directory, it works from the console, and in the applet works fine from the applet - up until that forName() line in my code, where it throws the exception:
Exception: com.mysql.jdbc.Driverjava.lang.ClassNotFoundException: com.mysql.jdbc.Driver
java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.-1)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkExit(Unknown Source)
at java.lang.Runtime.exit(Unknown Source)
at java.lang.System.exit(Unknown Source)
at applet.Database.connectDB(Database.java:80)
etc...
I think I may be able to fix it with a client.policy file, otherwise I might need to write an abstraction layer which uses a server-client network connection to query from the server-side...
I'm sure the Java gurus here probably know the best way about it.
I think the security exception is actually from a System.exit() call in your applet, after the Class.forName(). Generally you are not allowed to call System.exit() in unsigned applets as it shuts the whole JVM down. Have you checked if line 80 is actually the Class.forName() line, or does line 80 have some kind of exception handler which tries to call System.exit() if the driver does not load?
Anyway, in order to load the mysql jar file in your applet, you need to include it in an ARCHIVE attribute like this:
<APPLET ARCHIVE="mysql.jar" CODEBASE="./src/" ...
Once you get past this stage, you will still need to host the mysql server at the same IP number/hostname as the webserver, and open it to all the same people who can access your applet. As Tony said, this isn't how people normally do it, for security reasons. Better to write something on the server side, if you have control of the app server, and use XML or some other data exchange method to get the data out to the applet. Of course if you are just experimenting to learn about applets, then it's probably fine - but do take care to keep mysql behind your firewall if possible.
If you're trying to use the a JDBC driver from the applet, then the applet needs to be signed with a certificate, and your server needs to deliver this certificate when the applet is loaded on the client side.
The accepted way to do this is to make HTTP requests for data from the server from which the applet was loaded, and run the queries from the server. JSON or XML are good ways to exchange data between the applet and the server (similar to the way you do an AJAX application, sending XML or JSON between the browser and the server).
As mentioned in one of the other answers (#Leigh Caldwell), I would strongly recommend not doing things this way. If your applet has access to MySQL then so does everyone else in the world. Decompilation is so trivial these days that it would only be a moment's work for an industrious hacker to get the applet credentials to the database. Also, MySQL's user/pass authentication is fairly weak, most of its security is IP-based. By opening it up to the world, you're throwing away your first line of deference.
A better approach would be to build some sort of frontend protocol on the server side (XMLRPC would be a good foundation and easy to use). If the applet absolutely needs access to a database, your best bet would be HSQLDB in memory. This doesn't require any file permissions and can be run completely in-sandbox. The local in memory database could be synchronized with the server as necessary using the aforementioned XMLRPC facade.
Try getting rid of the newInstance() part. I think just having the Class.forName() does it for loading the driver.
The exception tells you that the applet has been unable to load the driver class. Your applet needs to download the jar containing the class at runtime, via HTTP, so you must have the jar (mysql.jar or whatever it is called) available on the webserver.
Once you solve this problem the user will have to allow the applet permissions so that it can make a TCP socket connection to the mysql db server. They will prompted with a dialog box...