Patch, begin of signed applet support
Koos Vriezen
koos.vriezen at xs4all.nl
Mon Feb 9 19:17:13 GMT 2004
On Sun, Feb 08, 2004 at 06:48:38PM -0500, George Staikos wrote:
> On Saturday 07 February 2004 20:07, Koos Vriezen wrote:
> > Signed applets is one major missing feature. Attached a patch that could
> > be a start of this. It asks the user in case a permission is not granted
> > by the security manager.
> > What needs to be done is a way to store granted permissions, eg. with
> > this patch for each applet the user must answer if it allows access to
> > the clipboard.
>
> Do you need any PKCS support from KSSL for this?
Don't know yet, maybe you can tell me :). The certificates are described here
http://java.sun.com/j2se/1.4.2/docs/api/java/security/cert/X509Certificate.html
Certificate is created with
$JAVA_HOME/bin/keytool -genkey -keystore mystore -alias myalias
and signing of jar file is done with
$JAVA_HOME/bin/jarsigner -keystore mystore myjar.jar myalias
Its the combination of a valid certificate and permission that should be stored
somewhere. Java itself has support for it, like
$JAVA_HOME/bin/keytool -import -keystore mystore -alias myalias -file mycert
and policy file like
keystore "file:mystore", "JKS"
grant signedBy "myalias"
{
permission java.io.FilePermission "file:/home/koos/dir", "read"
}
Anyway, lets make these applets work first. I've updated the patch, it saves
quite some 'Yes' clicking :-) by remembering which permission were granted
for which certificate.
It makes use of Object.getSigners() and SecurityManager.getClassContext() (which is an array of all classes in the calling stack).
Duplicates from http://bugs.kde.org/show_bug.cgi?id=65602 actually seem to
work (although some questions are really scary, one applet managed to make
a c:\temp\jts directory in my home dir)
Koos
-------------- next part --------------
Index: kjavaappletserver.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/java/kjavaappletserver.cpp,v
retrieving revision 1.68
diff -u -3 -p -r1.68 kjavaappletserver.cpp
--- kjavaappletserver.cpp 29 Nov 2003 13:05:21 -0000 1.68
+++ kjavaappletserver.cpp 9 Feb 2004 18:29:21 -0000
@@ -40,6 +40,7 @@
#include <qvaluelist.h>
#include <qdir.h>
#include <qeventloop.h>
+#include <qapplication.h>
#include <stdlib.h>
#include <assert.h>
@@ -71,6 +72,7 @@
#define KJAS_DATA_COMMAND (char)25
#define KJAS_PUT_URLDATA (char)26
#define KJAS_PUT_DATA (char)27
+#define KJAS_SECURITY_CONFIRM (char)28
class JSStackFrame;
@@ -589,6 +591,14 @@ void KJavaAppletServer::slotJavaRequest(
kdDebug(6100) << "Applet " << args[0] << " Failed: " << args[1] << endl;
cmd = QString::fromLatin1( "AppletFailed" );
break;
+ case KJAS_SECURITY_CONFIRM: {
+ kdDebug(6100) << "Security confirm " << args[0] << endl;
+ QStringList sl;
+ sl.push_front( KMessageBox::warningYesNo(qApp->activeWindow(), args[0], i18n("Security alert")) == KMessageBox::Yes ? "1" : "0");
+ sl.push_front(QString::number(ID_num));
+ process->send( KJAS_SECURITY_CONFIRM, sl );
+ return;
+ }
default:
return;
break;
Index: org/kde/kjas/server/KJASProtocolHandler.java
===================================================================
RCS file: /home/kde/kdelibs/khtml/java/org/kde/kjas/server/KJASProtocolHandler.java,v
retrieving revision 1.51
diff -u -3 -p -r1.51 KJASProtocolHandler.java
--- org/kde/kjas/server/KJASProtocolHandler.java 23 Jan 2004 12:18:53 -0000 1.51
+++ org/kde/kjas/server/KJASProtocolHandler.java 9 Feb 2004 18:29:21 -0000
@@ -42,6 +42,7 @@ public class KJASProtocolHandler
private static final int DataCommand = 25;
private static final int PutURLDataCode = 26;
private static final int PutDataCode = 27;
+ private static final int SecurityConfirmCode = 28;
//Holds contexts in contextID-context pairs
private Hashtable contexts;
@@ -332,6 +333,19 @@ public class KJASProtocolHandler
if ( context != null )
context.derefObject(Integer.parseInt(objid));
Main.debug( "DerefObject " + objid);
+ } else
+ if (cmd_code_value == SecurityConfirmCode)
+ {
+ String id = getArg( command );
+ String confirm = getArg( command );
+ Thread t = (Thread) KJASSecurityManager.confirmRequests.get(id);
+ Main.debug( "SecurityConfirmCode " + id + " confirm:" + confirm );
+ if (t != null) {
+ KJASSecurityManager.confirmRequests.put(id, confirm);
+ try {
+ t.interrupt();
+ } catch (SecurityException se) {}
+ }
}
else
{
@@ -830,6 +844,32 @@ public class KJASProtocolHandler
signals.write( bytes, 0, bytes.length );
}
+ public void sendSecurityConfirm( String text, String id )
+ {
+ Main.debug("sendSecurityConfirm, ID = " + id + " text = " + text);
+
+ byte [] id_bytes = id.getBytes();
+ byte [] text_bytes = text.getBytes();
+ int length = text_bytes.length + id_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) SecurityConfirmCode;
+ bytes[index++] = sep;
+
+ System.arraycopy( id_bytes, 0, bytes, index, id_bytes.length );
+ index += id_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( text_bytes, 0, bytes, index, text_bytes.length );
+ index += text_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
/**************************************************************
***** Utility functions for parsing commands ****************
**************************************************************/
Index: org/kde/kjas/server/KJASSecurityManager.java
===================================================================
RCS file: /home/kde/kdelibs/khtml/java/org/kde/kjas/server/KJASSecurityManager.java,v
retrieving revision 1.4
diff -u -3 -p -r1.4 KJASSecurityManager.java
--- org/kde/kjas/server/KJASSecurityManager.java 16 May 2002 23:55:32 -0000 1.4
+++ org/kde/kjas/server/KJASSecurityManager.java 9 Feb 2004 18:29:21 -0000
@@ -1,11 +1,17 @@
package org.kde.kjas.server;
import java.security.*;
+import java.security.cert.*;
import java.net.*;
+import java.util.*;
public class KJASSecurityManager extends SecurityManager
{
+ static Hashtable confirmRequests = new Hashtable();
+ static int confirmId = 0;
+ Hashtable grantedPermissions = new Hashtable();
+
public KJASSecurityManager()
{
}
@@ -15,6 +21,66 @@ public class KJASSecurityManager extends
* applet cannot connect to any other but the host, where it comes from.
* Anything else seems to be handled automagically
*/
+ public void checkPermission(Permission perm) throws SecurityException, NullPointerException {
+ try {
+ super.checkPermission(perm);
+ } catch (SecurityException se) {
+ HashSet set = new HashSet();
+ Class [] cls = getClassContext();
+ for (int i = 1; i < cls.length; i++) {
+ Object[] objs = cls[i].getSigners();
+ if (objs != null && objs.length > 0)
+ for (int j = 0; j < objs.length; j++)
+ set.add(objs[j]);
+ }
+ Main.debug("Certificates " + set.size() + " for " + perm);
+ if (set.size() == 0)
+ throw se;
+ String text = new String();
+ for (Iterator i = set.iterator(); i.hasNext(); ) {
+ Object cert = i.next();
+ HashSet permset = (HashSet) grantedPermissions.get(cert);
+ if (permset != null) {
+ for (Iterator j = permset.iterator(); j.hasNext(); ) {
+ Permission p = (Permission) j.next();
+ if (p.equals(perm) || p.implies(perm))
+ return;
+ }
+ }
+ if (cert instanceof X509Certificate)
+ text += ((X509Certificate) cert).getIssuerDN().getName();
+ else
+ text += cert.toString();
+ text += "\n";
+ }
+ String id = "" + confirmId++;
+ confirmRequests.put(id, Thread.currentThread());
+ Main.protocol.sendSecurityConfirm(text + perm, id);
+ boolean ok = false;
+ try {
+ Thread.currentThread().sleep(300000);
+ } catch (InterruptedException ie) {
+ if (((String) confirmRequests.get(id)).equals("1")) {
+ for (Iterator it = set.iterator(); it.hasNext(); ) {
+ Object cert = it.next();
+ HashSet permset = (HashSet) grantedPermissions.get(cert);
+ if (permset == null) {
+ permset = new HashSet();
+ grantedPermissions.put(cert, permset);
+ }
+ permset.add(perm);
+ }
+ ok = true;
+ }
+ } finally {
+ confirmRequests.remove(id);
+ }
+ if (!ok) {
+ Main.debug("Permission denied" + perm);
+ throw se;
+ }
+ }
+ }
public void disabled___checkPermission(Permission perm) throws SecurityException, NullPointerException
{
// does not seem to work as expected, Problems with proxy - and it seems that the default
More information about the kfm-devel
mailing list