From b38ae5c64b7cb0e4c243980930359236b2df887f Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 7 Aug 2014 11:51:33 -0700 Subject: [PATCH 1/3] Use native version of the SecurityHandler class --- .../sun/midp/security/SecurityHandler.java | 434 ++++-------------- midp/midp.js | 14 + native.js | 3 + 3 files changed, 96 insertions(+), 355 deletions(-) diff --git a/java/midp/com/sun/midp/security/SecurityHandler.java b/java/midp/com/sun/midp/security/SecurityHandler.java index 430b7d75..cc9e6e61 100644 --- a/java/midp/com/sun/midp/security/SecurityHandler.java +++ b/java/midp/com/sun/midp/security/SecurityHandler.java @@ -1,5 +1,5 @@ /* - * + * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER @@ -30,17 +30,16 @@ import javax.microedition.io.*; import javax.microedition.lcdui.*; -import com.sun.j2me.security.AccessController; - import com.sun.midp.lcdui.*; +import com.sun.midp.midlet.*; + import com.sun.midp.i18n.Resource; import com.sun.midp.i18n.ResourceConstants; import com.sun.midp.events.EventQueue; import com.sun.midp.io.j2me.storage.*; -import com.sun.midp.configurator.Constants; import com.sun.midp.log.Logging; import com.sun.midp.log.LogChannels; @@ -50,14 +49,6 @@ import com.sun.midp.log.LogChannels; * a MIDlet suite. */ public final class SecurityHandler { - /** Session level interaction has not occured. */ - private final static byte NOT_ASKED = 0; - - /** User granted permission for this session. */ - private final static byte GRANTED = 1; - - /** User denied permission for this session. */ - private final static byte DENIED = -1; /** The security token for this class. */ private static SecurityToken classSecurityToken; @@ -65,34 +56,21 @@ public final class SecurityHandler { /** The standard security exception message. */ public static final String STD_EX_MSG = "Application not authorized " + "to access the restricted API"; - - /** Permission list. */ - private byte permissions[]; - - /** A flag for the session value of each permission. */ - private byte sessionValues[]; - - /** Maximum permission level list. */ - private byte maxPermissionLevels[]; - - /** True, if trusted. */ - private boolean trusted; - /** * Creates a security domain with a list of permitted actions or no list * to indicate all actions. The caller must be have permission for * Permissions.MIDP or be the first caller of * the method for this instance of the VM. * - * @param apiPermissions for the token + * @param ApiPermissions for the token * @param domain name of the security domain * * @exception SecurityException if caller is not permitted to call this * method */ - public SecurityHandler(byte[] apiPermissions, String domain) { - AccessController.checkPermission(Permissions.AMS_PERMISSION_NAME); - init(apiPermissions, domain); + public SecurityHandler(byte[] ApiPermissions, String domain) { + // No-op since we don't cache any permissions in Java + // Query native security manager every time } /** @@ -102,39 +80,16 @@ public final class SecurityHandler { * the method for this instance of the VM. * * @param securityToken security token of the caller - * @param apiPermissions for the token, can be null + * @param ApiPermissions for the token, can be null * @param domain name of the security domain * * @exception SecurityException if caller is not permitted to call this * method */ public SecurityHandler(SecurityToken securityToken, - byte[] apiPermissions, String domain) { - securityToken.checkIfPermissionAllowed(Permissions.AMS); - init(apiPermissions, domain); - } - - /** - * Creates a security domain with a list of permitted actions or no list - * to indicate all actions. The caller must be have permission for - * Permissions.MIDP or be the first caller of - * the method for this instance of the VM. - * - * @param apiPermissions for the token - * @param domain name of the security domain - * - * @exception SecurityException if caller is not permitted to call this - * method - */ - private void init(byte[] apiPermissions, String domain) { - maxPermissionLevels = - (Permissions.forDomain(domain))[Permissions.MAX_LEVELS]; - - permissions = apiPermissions; - - sessionValues = new byte[permissions.length]; - - trusted = Permissions.isTrusted(domain); + byte[] ApiPermissions, String domain) { + // Do not cache anything + // Ask native security manager everytime } /** @@ -149,46 +104,23 @@ public final class SecurityHandler { * -1 if the status is unknown */ public int checkPermission(String permission) { - int i; + int status = 0; + int permId; - synchronized (this) { - try { - i = Permissions.getId(permission); - } catch (SecurityException e) { - return 0; //not found, report denied - } + try { + permId = Permissions.getId(permission); + MIDletSuite current = + MIDletStateHandler.getMidletStateHandler().getMIDletSuite(); - switch (permissions[i]) { - case Permissions.ALLOW: - case Permissions.BLANKET_GRANTED: - // report allowed - return 1; - - case Permissions.SESSION: - if (sessionValues[i] == GRANTED) { - // report allowed - return 1; - } - - if (sessionValues[i] == DENIED) { - // report denied - return 0; - } - - // fall through - case Permissions.BLANKET: - case Permissions.ONESHOT: - // report unknown - return -1; - - default: - // Permissions.NEVER - break; - } - - // report denied - return 0; + if (current != null) { + // query native security mgr for status + status = checkPermissionStatus0(current.getID(), permId); + } + } catch (SecurityException exc) { + // intentionally ignored } + + return status; } /** @@ -207,9 +139,7 @@ public final class SecurityHandler { * the ID must be from * {@link com.sun.midp.security.Permissions} * @param title Resource constant for the title of the dialog - * @param question Resource constant for the question to ask the user - * @param oneshotQuestion Resource constant for the oneshot question to - * ask the user + * @param question Resource constant for the question to ask user * @param app name of the application to insert into a string * can be null if no %1 a string * @param resource string to insert into a string, @@ -217,9 +147,8 @@ public final class SecurityHandler { * @param extraValue string to insert into a string, * can be null if no %3 in a string * - * @return true if the permission interaction has permanently - * changed and the new state should be saved, this will only happen - * if the permission granted + * @return true if the permission was allow and was not allowed + * before * * @exception SecurityException if the permission is not * allowed by this token @@ -232,7 +161,8 @@ public final class SecurityHandler { throws InterruptedException { return checkForPermission(permission, title, question, - oneshotQuestion, app, resource, extraValue, STD_EX_MSG); + oneshotQuestion, app, resource, extraValue, + SecurityToken.STD_EX_MSG); } @@ -263,9 +193,8 @@ public final class SecurityHandler { * can be null if no %3 in a string * @param exceptionMsg message if a security exception is thrown * - * @return true if the permission interaction has permanently - * changed and the new state should be saved, this will only happen - * if the permission granted + * @return true if the permission was allowed and was + * not allowed before; false, if permission is granted.. * * @exception SecurityException if the permission is not * allowed by this token @@ -273,89 +202,22 @@ public final class SecurityHandler { * calling thread while this method is waiting to preempt the * display. */ - public boolean checkForPermission(String permissionStr, String title, String question, + public boolean checkForPermission(String permission, String title, String question, String oneShotQuestion, String app, String resource, String extraValue, String exceptionMsg) throws InterruptedException { - - if (permissions == null) { - /* totally trusted, all permissions allowed */ - return false; + + MIDletSuite current = + MIDletStateHandler.getMidletStateHandler().getMIDletSuite(); + System.out.println("THISCHECKFORPERMISSION"); + if (current != null) { + // can throw SecurityException + System.out.println("HERE"); + int permId = Permissions.getId(permission); + if (checkPermission0(current.getID(), permId)) { + return false; + } } - - synchronized (this) { - int permission; - try { - permission = Permissions.getId(permissionStr); - } catch (SecurityException e) { - throw new SecurityException(exceptionMsg); - } - if (permission >= 0 && permission < permissions.length) { - switch (permissions[permission]) { - case Permissions.ALLOW: - case Permissions.BLANKET_GRANTED: - return false; - - case Permissions.BLANKET: - /* This level means the question has not been asked yet. */ - if (askUserForPermission(classSecurityToken, trusted, - title, question, app, resource, extraValue)) { - - Permissions.setPermissionGroup(permissions, - permission, Permissions.BLANKET_GRANTED); - - return true; - } - - Permissions.setPermissionGroup(permissions, - permission, Permissions.BLANKET_DENIED); - break; - - case Permissions.SESSION: - if (sessionValues[permission] == GRANTED) { - return false; - } - - if (sessionValues[permission] == DENIED) { - break; - } - - if (askUserForPermission(classSecurityToken, trusted, - title, question, app, resource, extraValue)) { - /* - * Save the fact that the question has already - * been asked this session. - */ - Permissions.setPermissionGroup(sessionValues, - permission, GRANTED); - - return false; - } - - /* - * Save the fact that the question has already - * been asked this session. - */ - Permissions.setPermissionGroup(sessionValues, - permission, DENIED); - break; - - case Permissions.ONESHOT: - if (askUserForPermission(classSecurityToken, trusted, - title, oneShotQuestion, app, resource, - extraValue)) { - return false; - } - - break; - - default: - // Permissions.NEVER - break; - } // switch - } // if - - throw new SecurityException(exceptionMsg); - } // synchronized + throw new SecurityException(STD_EX_MSG); } /** @@ -363,10 +225,10 @@ public final class SecurityHandler { * * @param token security token with the permission to preempt the * foreground display - * @param trusted true to display the trusted icon, false to display the - * untrusted icon * @param title Resource constant for the title of the dialog * @param question Resource constant for the question to ask user + * @param oneShotQuestion Resource constant for the oneshot question to + * ask the user * @param app name of the application to insert into a string * can be null if no %1 a string * @param resource string to insert into a string, @@ -383,12 +245,9 @@ public final class SecurityHandler { public static boolean askUserForPermission(SecurityToken token, boolean trusted, String title, String question, String app, String resource, String extraValue) throws InterruptedException { - - PermissionDialog dialog = - new PermissionDialog(token, trusted, title, question, app, - resource, extraValue); - - return dialog.waitForAnswer(); + // Allow Push interrupt since the decision is already made + // at native Push level + return true; } /** @@ -404,168 +263,33 @@ public final class SecurityHandler { classSecurityToken = token; } -} - -/** Implements security permission dialog. */ -class PermissionDialog implements CommandListener { - /** Caches the display manager reference. */ - private DisplayEventHandler displayEventHandler; - - /** Permission Alert. */ - private Alert alert; - - /** Command object for "Yes" command. */ - private Command yesCmd = - new Command(Resource.getString(ResourceConstants.YES), - Command.OK, 1); - /** Command object for "No" command. */ - private Command noCmd = - new Command(Resource.getString(ResourceConstants.NO), - Command.BACK, 1); - /** Holds the preempt token so the form can end. */ - private Object preemptToken; - - /** Holds the answer to the security question. */ - private boolean answer; - - /** - * Construct permission dialog. - *

- * The title, question, and answer strings will be translated, - * if a string resource is available. - * Since the strings can have substitution token in them, if there is a - * "%" it must changed to "%%". If a string has a %1, the app parameter - * will be substituted for it. If a string has a "%2, the resource - * parameter will be substituted for it. If a string has a %3, the - * extraValue parameter will be substituted for it. - * - * @param token security token with the permission to preempt the - * foreground display - * @param trusted true to display the trusted icon, false to display the - * untrusted icon - * @param title Resource constant for the title of the dialog - * @param question Resource constant for the question to ask user - * @param app name of the application to insert into a string - * can be null if no %1 a string - * @param resource string to insert into a string, - * can be null if no %2 in a string - * @param extraValue string to insert into a string, - * can be null if no %3 in a string - * - * @exception InterruptedException if another thread interrupts the - * calling thread while this method is waiting to preempt the - * display. - */ - PermissionDialog(SecurityToken token, boolean trusted, String title, - String question, String app, String resource, String extraValue) - throws InterruptedException { - String[] substitutions = {app, resource, extraValue}; - String iconFilename; - RandomAccessStream stream; - byte[] rawPng; - Image icon; - String configRoot = File.getConfigRoot(Constants.INTERNAL_STORAGE_ID); - - alert = new Alert(Resource.getString(title, substitutions)); - - displayEventHandler = - DisplayEventHandlerFactory.getDisplayEventHandler(token); - - if (trusted) { - iconFilename = configRoot + "trusted_icon.png"; - } else { - iconFilename = configRoot + "untrusted_icon.png"; - } - - stream = new RandomAccessStream(token); - try { - stream.connect(iconFilename, Connector.READ); - rawPng = new byte[stream.getSizeOf()]; - stream.readBytes(rawPng, 0, rawPng.length); - stream.disconnect(); - icon = Image.createImage(rawPng, 0, rawPng.length); - alert.setImage(icon); - } catch (java.io.IOException noImage) { - } - - alert.setString(Resource.getString(question, substitutions)); - alert.addCommand(noCmd); - alert.addCommand(yesCmd); - alert.setCommandListener(this); - preemptToken = displayEventHandler.preemptDisplay(alert, true); - } - - /** - * Waits for the user's answer. - * - * @return user's answer - */ - boolean waitForAnswer() { - synchronized (this) { - if (preemptToken == null) { - return false; - } - - if (EventQueue.isDispatchThread()) { - // Developer programming error - throw new RuntimeException( - "Blocking call performed in the event thread"); - } - - try { - wait(); - } catch (Throwable t) { - return false; - } - - return answer; - } - } - - /** - * Sets the user's answer and notifies waitForAnswer and - * ends the form. - * - * @param theAnswer user's answer - */ - private void setAnswer(boolean theAnswer) { - synchronized (this) { - answer = theAnswer; - - /* - * Since this may be the only display, clear the alert, - * so the user will not be confused by alert text still - * displaying. - * - * The case should happen when running TCK test MIDlets in - * SVM mode. - */ - alert.setTitle(null); - alert.setString(null); - alert.setImage(null); - alert.addCommand(new Command("", 1, 1)); - alert.removeCommand(noCmd); - alert.removeCommand(yesCmd); - - displayEventHandler.donePreempting(preemptToken); - - notify(); - } - - } - - /** - * Respond to a command issued on security question form. - * - * @param c command activated by the user - * @param s the Displayable the command was on. - */ - public void commandAction(Command c, Displayable s) { - if (c == yesCmd) { - setAnswer(true); - return; - } - - setAnswer(false); - } + + /** + * Query native security manager for permission. + * This call may block if user needs to be asked. + * + * @param suiteId the MIDlet suite the permission should be checked against + * @param permission the permission id + * + * @return true if permission is granted. Otherwise, false. + */ + private native boolean checkPermission0(int suiteId, int permission); + + /** + * Get the status of the specified permission. + * This is to implement public API MIDlet.checkPermission() + * and will not block calling thread. + * + * If no API on the device defines the specific permission + * requested then it must be reported as denied. + * If the status of the permission is not known because it might + * require a user interaction then it should be reported as unknown. + * + * @param suiteId the MIDlet suite the permission should be checked against + * @param permission to check if denied, allowed, or unknown. + * @return 0 if the permission is denied; 1 if the permission is allowed; + * -1 if the status is unknown + */ + private native int checkPermissionStatus0(int suiteId, + int permission); } diff --git a/midp/midp.js b/midp/midp.js index 964b2c9a..fa75e0ec 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -616,6 +616,10 @@ Native["com/sun/midp/midletsuite/SuiteSettings.load.()V"] = function(ctx, stack) var _this = stack.pop(); } +Native["com/sun/midp/midletsuite/SuiteSettings.save0.(IBI[B)V"] = function(ctx, stack) { + var permissions = stack.pop(), pushOptions = stack.pop(), pushInterruptSetting = stack.pop(), suiteId = stack.pop(), _this = stack.pop(); +} + Native["com/sun/midp/midletsuite/InstallInfo.load.()V"] = function(ctx, stack) { var _this = stack.pop(); } @@ -1127,3 +1131,13 @@ Native["com/ibm/oti/connection/file/FCOutputStream.writeImpl.([BIII)V"] = functi _this.pos += count; } + +Native["com/sun/midp/security/SecurityHandler.checkPermission0.(II)Z"] = function(ctx, stack) { + var permission = stack.pop(), suiteId = stack.pop(), _this = stack.pop(); + stack.push(1); +} + +Native["com/sun/midp/security/SecurityHandler.checkPermissionStatus0.(II)I"] = function(ctx, stack) { + var permission = stack.pop(), suiteId = stack.pop(), _this = stack.pop(); + stack.push(1); +} diff --git a/native.js b/native.js index 46a6c7c6..7cbe8ed1 100644 --- a/native.js +++ b/native.js @@ -75,6 +75,9 @@ Native["java/lang/System.getProperty0.(Ljava/lang/String;)Ljava/lang/String;"] = case "microedition.platform": value = "NOKIA503/JAVA_RUNTIME_VERSION=NOKIA_ASHA_1_2"; break; + case "microedition.profiles": + value = "MIDP-2.0" + break; case "fileconn.dir.memorycard": value = "fcfile:///tmp/"; break; From 3e3811bea7e93142863b82f56019b2864576270e Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 7 Aug 2014 11:51:33 -0700 Subject: [PATCH 2/3] Use native version of the SecurityHandler class --- .../sun/midp/security/SecurityHandler.java | 434 ++++-------------- midp/midp.js | 14 + native.js | 3 + 3 files changed, 96 insertions(+), 355 deletions(-) diff --git a/java/midp/com/sun/midp/security/SecurityHandler.java b/java/midp/com/sun/midp/security/SecurityHandler.java index 430b7d75..cc9e6e61 100644 --- a/java/midp/com/sun/midp/security/SecurityHandler.java +++ b/java/midp/com/sun/midp/security/SecurityHandler.java @@ -1,5 +1,5 @@ /* - * + * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER @@ -30,17 +30,16 @@ import javax.microedition.io.*; import javax.microedition.lcdui.*; -import com.sun.j2me.security.AccessController; - import com.sun.midp.lcdui.*; +import com.sun.midp.midlet.*; + import com.sun.midp.i18n.Resource; import com.sun.midp.i18n.ResourceConstants; import com.sun.midp.events.EventQueue; import com.sun.midp.io.j2me.storage.*; -import com.sun.midp.configurator.Constants; import com.sun.midp.log.Logging; import com.sun.midp.log.LogChannels; @@ -50,14 +49,6 @@ import com.sun.midp.log.LogChannels; * a MIDlet suite. */ public final class SecurityHandler { - /** Session level interaction has not occured. */ - private final static byte NOT_ASKED = 0; - - /** User granted permission for this session. */ - private final static byte GRANTED = 1; - - /** User denied permission for this session. */ - private final static byte DENIED = -1; /** The security token for this class. */ private static SecurityToken classSecurityToken; @@ -65,34 +56,21 @@ public final class SecurityHandler { /** The standard security exception message. */ public static final String STD_EX_MSG = "Application not authorized " + "to access the restricted API"; - - /** Permission list. */ - private byte permissions[]; - - /** A flag for the session value of each permission. */ - private byte sessionValues[]; - - /** Maximum permission level list. */ - private byte maxPermissionLevels[]; - - /** True, if trusted. */ - private boolean trusted; - /** * Creates a security domain with a list of permitted actions or no list * to indicate all actions. The caller must be have permission for * Permissions.MIDP or be the first caller of * the method for this instance of the VM. * - * @param apiPermissions for the token + * @param ApiPermissions for the token * @param domain name of the security domain * * @exception SecurityException if caller is not permitted to call this * method */ - public SecurityHandler(byte[] apiPermissions, String domain) { - AccessController.checkPermission(Permissions.AMS_PERMISSION_NAME); - init(apiPermissions, domain); + public SecurityHandler(byte[] ApiPermissions, String domain) { + // No-op since we don't cache any permissions in Java + // Query native security manager every time } /** @@ -102,39 +80,16 @@ public final class SecurityHandler { * the method for this instance of the VM. * * @param securityToken security token of the caller - * @param apiPermissions for the token, can be null + * @param ApiPermissions for the token, can be null * @param domain name of the security domain * * @exception SecurityException if caller is not permitted to call this * method */ public SecurityHandler(SecurityToken securityToken, - byte[] apiPermissions, String domain) { - securityToken.checkIfPermissionAllowed(Permissions.AMS); - init(apiPermissions, domain); - } - - /** - * Creates a security domain with a list of permitted actions or no list - * to indicate all actions. The caller must be have permission for - * Permissions.MIDP or be the first caller of - * the method for this instance of the VM. - * - * @param apiPermissions for the token - * @param domain name of the security domain - * - * @exception SecurityException if caller is not permitted to call this - * method - */ - private void init(byte[] apiPermissions, String domain) { - maxPermissionLevels = - (Permissions.forDomain(domain))[Permissions.MAX_LEVELS]; - - permissions = apiPermissions; - - sessionValues = new byte[permissions.length]; - - trusted = Permissions.isTrusted(domain); + byte[] ApiPermissions, String domain) { + // Do not cache anything + // Ask native security manager everytime } /** @@ -149,46 +104,23 @@ public final class SecurityHandler { * -1 if the status is unknown */ public int checkPermission(String permission) { - int i; + int status = 0; + int permId; - synchronized (this) { - try { - i = Permissions.getId(permission); - } catch (SecurityException e) { - return 0; //not found, report denied - } + try { + permId = Permissions.getId(permission); + MIDletSuite current = + MIDletStateHandler.getMidletStateHandler().getMIDletSuite(); - switch (permissions[i]) { - case Permissions.ALLOW: - case Permissions.BLANKET_GRANTED: - // report allowed - return 1; - - case Permissions.SESSION: - if (sessionValues[i] == GRANTED) { - // report allowed - return 1; - } - - if (sessionValues[i] == DENIED) { - // report denied - return 0; - } - - // fall through - case Permissions.BLANKET: - case Permissions.ONESHOT: - // report unknown - return -1; - - default: - // Permissions.NEVER - break; - } - - // report denied - return 0; + if (current != null) { + // query native security mgr for status + status = checkPermissionStatus0(current.getID(), permId); + } + } catch (SecurityException exc) { + // intentionally ignored } + + return status; } /** @@ -207,9 +139,7 @@ public final class SecurityHandler { * the ID must be from * {@link com.sun.midp.security.Permissions} * @param title Resource constant for the title of the dialog - * @param question Resource constant for the question to ask the user - * @param oneshotQuestion Resource constant for the oneshot question to - * ask the user + * @param question Resource constant for the question to ask user * @param app name of the application to insert into a string * can be null if no %1 a string * @param resource string to insert into a string, @@ -217,9 +147,8 @@ public final class SecurityHandler { * @param extraValue string to insert into a string, * can be null if no %3 in a string * - * @return true if the permission interaction has permanently - * changed and the new state should be saved, this will only happen - * if the permission granted + * @return true if the permission was allow and was not allowed + * before * * @exception SecurityException if the permission is not * allowed by this token @@ -232,7 +161,8 @@ public final class SecurityHandler { throws InterruptedException { return checkForPermission(permission, title, question, - oneshotQuestion, app, resource, extraValue, STD_EX_MSG); + oneshotQuestion, app, resource, extraValue, + SecurityToken.STD_EX_MSG); } @@ -263,9 +193,8 @@ public final class SecurityHandler { * can be null if no %3 in a string * @param exceptionMsg message if a security exception is thrown * - * @return true if the permission interaction has permanently - * changed and the new state should be saved, this will only happen - * if the permission granted + * @return true if the permission was allowed and was + * not allowed before; false, if permission is granted.. * * @exception SecurityException if the permission is not * allowed by this token @@ -273,89 +202,22 @@ public final class SecurityHandler { * calling thread while this method is waiting to preempt the * display. */ - public boolean checkForPermission(String permissionStr, String title, String question, + public boolean checkForPermission(String permission, String title, String question, String oneShotQuestion, String app, String resource, String extraValue, String exceptionMsg) throws InterruptedException { - - if (permissions == null) { - /* totally trusted, all permissions allowed */ - return false; + + MIDletSuite current = + MIDletStateHandler.getMidletStateHandler().getMIDletSuite(); + System.out.println("THISCHECKFORPERMISSION"); + if (current != null) { + // can throw SecurityException + System.out.println("HERE"); + int permId = Permissions.getId(permission); + if (checkPermission0(current.getID(), permId)) { + return false; + } } - - synchronized (this) { - int permission; - try { - permission = Permissions.getId(permissionStr); - } catch (SecurityException e) { - throw new SecurityException(exceptionMsg); - } - if (permission >= 0 && permission < permissions.length) { - switch (permissions[permission]) { - case Permissions.ALLOW: - case Permissions.BLANKET_GRANTED: - return false; - - case Permissions.BLANKET: - /* This level means the question has not been asked yet. */ - if (askUserForPermission(classSecurityToken, trusted, - title, question, app, resource, extraValue)) { - - Permissions.setPermissionGroup(permissions, - permission, Permissions.BLANKET_GRANTED); - - return true; - } - - Permissions.setPermissionGroup(permissions, - permission, Permissions.BLANKET_DENIED); - break; - - case Permissions.SESSION: - if (sessionValues[permission] == GRANTED) { - return false; - } - - if (sessionValues[permission] == DENIED) { - break; - } - - if (askUserForPermission(classSecurityToken, trusted, - title, question, app, resource, extraValue)) { - /* - * Save the fact that the question has already - * been asked this session. - */ - Permissions.setPermissionGroup(sessionValues, - permission, GRANTED); - - return false; - } - - /* - * Save the fact that the question has already - * been asked this session. - */ - Permissions.setPermissionGroup(sessionValues, - permission, DENIED); - break; - - case Permissions.ONESHOT: - if (askUserForPermission(classSecurityToken, trusted, - title, oneShotQuestion, app, resource, - extraValue)) { - return false; - } - - break; - - default: - // Permissions.NEVER - break; - } // switch - } // if - - throw new SecurityException(exceptionMsg); - } // synchronized + throw new SecurityException(STD_EX_MSG); } /** @@ -363,10 +225,10 @@ public final class SecurityHandler { * * @param token security token with the permission to preempt the * foreground display - * @param trusted true to display the trusted icon, false to display the - * untrusted icon * @param title Resource constant for the title of the dialog * @param question Resource constant for the question to ask user + * @param oneShotQuestion Resource constant for the oneshot question to + * ask the user * @param app name of the application to insert into a string * can be null if no %1 a string * @param resource string to insert into a string, @@ -383,12 +245,9 @@ public final class SecurityHandler { public static boolean askUserForPermission(SecurityToken token, boolean trusted, String title, String question, String app, String resource, String extraValue) throws InterruptedException { - - PermissionDialog dialog = - new PermissionDialog(token, trusted, title, question, app, - resource, extraValue); - - return dialog.waitForAnswer(); + // Allow Push interrupt since the decision is already made + // at native Push level + return true; } /** @@ -404,168 +263,33 @@ public final class SecurityHandler { classSecurityToken = token; } -} - -/** Implements security permission dialog. */ -class PermissionDialog implements CommandListener { - /** Caches the display manager reference. */ - private DisplayEventHandler displayEventHandler; - - /** Permission Alert. */ - private Alert alert; - - /** Command object for "Yes" command. */ - private Command yesCmd = - new Command(Resource.getString(ResourceConstants.YES), - Command.OK, 1); - /** Command object for "No" command. */ - private Command noCmd = - new Command(Resource.getString(ResourceConstants.NO), - Command.BACK, 1); - /** Holds the preempt token so the form can end. */ - private Object preemptToken; - - /** Holds the answer to the security question. */ - private boolean answer; - - /** - * Construct permission dialog. - *

- * The title, question, and answer strings will be translated, - * if a string resource is available. - * Since the strings can have substitution token in them, if there is a - * "%" it must changed to "%%". If a string has a %1, the app parameter - * will be substituted for it. If a string has a "%2, the resource - * parameter will be substituted for it. If a string has a %3, the - * extraValue parameter will be substituted for it. - * - * @param token security token with the permission to preempt the - * foreground display - * @param trusted true to display the trusted icon, false to display the - * untrusted icon - * @param title Resource constant for the title of the dialog - * @param question Resource constant for the question to ask user - * @param app name of the application to insert into a string - * can be null if no %1 a string - * @param resource string to insert into a string, - * can be null if no %2 in a string - * @param extraValue string to insert into a string, - * can be null if no %3 in a string - * - * @exception InterruptedException if another thread interrupts the - * calling thread while this method is waiting to preempt the - * display. - */ - PermissionDialog(SecurityToken token, boolean trusted, String title, - String question, String app, String resource, String extraValue) - throws InterruptedException { - String[] substitutions = {app, resource, extraValue}; - String iconFilename; - RandomAccessStream stream; - byte[] rawPng; - Image icon; - String configRoot = File.getConfigRoot(Constants.INTERNAL_STORAGE_ID); - - alert = new Alert(Resource.getString(title, substitutions)); - - displayEventHandler = - DisplayEventHandlerFactory.getDisplayEventHandler(token); - - if (trusted) { - iconFilename = configRoot + "trusted_icon.png"; - } else { - iconFilename = configRoot + "untrusted_icon.png"; - } - - stream = new RandomAccessStream(token); - try { - stream.connect(iconFilename, Connector.READ); - rawPng = new byte[stream.getSizeOf()]; - stream.readBytes(rawPng, 0, rawPng.length); - stream.disconnect(); - icon = Image.createImage(rawPng, 0, rawPng.length); - alert.setImage(icon); - } catch (java.io.IOException noImage) { - } - - alert.setString(Resource.getString(question, substitutions)); - alert.addCommand(noCmd); - alert.addCommand(yesCmd); - alert.setCommandListener(this); - preemptToken = displayEventHandler.preemptDisplay(alert, true); - } - - /** - * Waits for the user's answer. - * - * @return user's answer - */ - boolean waitForAnswer() { - synchronized (this) { - if (preemptToken == null) { - return false; - } - - if (EventQueue.isDispatchThread()) { - // Developer programming error - throw new RuntimeException( - "Blocking call performed in the event thread"); - } - - try { - wait(); - } catch (Throwable t) { - return false; - } - - return answer; - } - } - - /** - * Sets the user's answer and notifies waitForAnswer and - * ends the form. - * - * @param theAnswer user's answer - */ - private void setAnswer(boolean theAnswer) { - synchronized (this) { - answer = theAnswer; - - /* - * Since this may be the only display, clear the alert, - * so the user will not be confused by alert text still - * displaying. - * - * The case should happen when running TCK test MIDlets in - * SVM mode. - */ - alert.setTitle(null); - alert.setString(null); - alert.setImage(null); - alert.addCommand(new Command("", 1, 1)); - alert.removeCommand(noCmd); - alert.removeCommand(yesCmd); - - displayEventHandler.donePreempting(preemptToken); - - notify(); - } - - } - - /** - * Respond to a command issued on security question form. - * - * @param c command activated by the user - * @param s the Displayable the command was on. - */ - public void commandAction(Command c, Displayable s) { - if (c == yesCmd) { - setAnswer(true); - return; - } - - setAnswer(false); - } + + /** + * Query native security manager for permission. + * This call may block if user needs to be asked. + * + * @param suiteId the MIDlet suite the permission should be checked against + * @param permission the permission id + * + * @return true if permission is granted. Otherwise, false. + */ + private native boolean checkPermission0(int suiteId, int permission); + + /** + * Get the status of the specified permission. + * This is to implement public API MIDlet.checkPermission() + * and will not block calling thread. + * + * If no API on the device defines the specific permission + * requested then it must be reported as denied. + * If the status of the permission is not known because it might + * require a user interaction then it should be reported as unknown. + * + * @param suiteId the MIDlet suite the permission should be checked against + * @param permission to check if denied, allowed, or unknown. + * @return 0 if the permission is denied; 1 if the permission is allowed; + * -1 if the status is unknown + */ + private native int checkPermissionStatus0(int suiteId, + int permission); } diff --git a/midp/midp.js b/midp/midp.js index 964b2c9a..c9f30e60 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -616,6 +616,10 @@ Native["com/sun/midp/midletsuite/SuiteSettings.load.()V"] = function(ctx, stack) var _this = stack.pop(); } +Native["com/sun/midp/midletsuite/SuiteSettings.save0.(IBI[B)V"] = function(ctx, stack) { + var permissions = stack.pop(), pushOptions = stack.pop(), pushInterruptSetting = stack.pop(), suiteId = stack.pop(), _this = stack.pop(); +} + Native["com/sun/midp/midletsuite/InstallInfo.load.()V"] = function(ctx, stack) { var _this = stack.pop(); } @@ -1127,3 +1131,13 @@ Native["com/ibm/oti/connection/file/FCOutputStream.writeImpl.([BIII)V"] = functi _this.pos += count; } + +Native["com/sun/midp/security/SecurityHandler.checkPermission0.(II)Z"] = function(ctx, stack) { + var permission = stack.pop(), suiteId = stack.pop(), _this = stack.pop(); + stack.push(1); +} + +Native["com/sun/midp/security/SecurityHandler.checkPermissionStatus0.(II)I"] = function(ctx, stack) { + var permission = stack.pop(), suiteId = stack.pop(), _this = stack.pop(); + stack.push(1); +} diff --git a/native.js b/native.js index 46a6c7c6..7cbe8ed1 100644 --- a/native.js +++ b/native.js @@ -75,6 +75,9 @@ Native["java/lang/System.getProperty0.(Ljava/lang/String;)Ljava/lang/String;"] = case "microedition.platform": value = "NOKIA503/JAVA_RUNTIME_VERSION=NOKIA_ASHA_1_2"; break; + case "microedition.profiles": + value = "MIDP-2.0" + break; case "fileconn.dir.memorycard": value = "fcfile:///tmp/"; break; From afda0c2b2aaddf1a477914a73b321048add939bc Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 7 Aug 2014 15:44:47 -0700 Subject: [PATCH 3/3] Remove logging statements --- java/midp/com/sun/midp/security/SecurityHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/midp/com/sun/midp/security/SecurityHandler.java b/java/midp/com/sun/midp/security/SecurityHandler.java index cc9e6e61..b0fcb752 100644 --- a/java/midp/com/sun/midp/security/SecurityHandler.java +++ b/java/midp/com/sun/midp/security/SecurityHandler.java @@ -208,10 +208,9 @@ public final class SecurityHandler { MIDletSuite current = MIDletStateHandler.getMidletStateHandler().getMIDletSuite(); - System.out.println("THISCHECKFORPERMISSION"); + if (current != null) { // can throw SecurityException - System.out.println("HERE"); int permId = Permissions.getId(permission); if (checkPermission0(current.getID(), permId)) { return false;