Because some sensors may reveal sensitive information, access to
sensors needs to be protected by the security framework. The sensor
access is defined as any attempt by a MIDlet in a MIDlet suite to
open the connection to the sensor and retrieve data using the
SensorConnection
interface. Discovery of the
sensors is not protected and all the sensors are visible to be
found by any MIDlet.
SensorManager.findSensors()
methods return all the
matching sensors, but they cannot necessary be opened. The
Connector.open()
and
PushRegistry.registerConnection()
methods throw a
SecurityException
if the application
does not have the required permission to use the sensor.
Originally the MIDP security model was defined in the MIDP 2.0 Specification and the Recommended Security Policy. The JTWI JSR 185 Specification defines the policy for the third-party domain ("untrusted domain"). The MSA JSR 248 Specification defines the four domains that the MIDlet suites are categorized to and a recommended policy for them. A MIDlet suite can belong to one of the four domains:
Manufacturer domain
Operator domain
Identified third-party domain
Third-party domain
This API specifies three permissions to restrict the usage of some sensors. Some sensors might handle confidential data that the user doesn't want to be exposed. Examples include sensors related to health, or wealth like a heart rate sensor, or scales. Such sensors are considered to be private.
Another category of sensors with restricted access are system sensors. System sensors might handle hidden, or protected system resources. Data from these sensors is provided only for trusted applications. These sensors are called protected sensors.
Sensors that are not private or protected are understood
as public sensors. All these sensor groups, private, protected, and public,
require the javax.microedition.io.Connector.sensor
permission
to open the connection.
The table below defines the names of the three sensor related permissions and the methods that are protected by each permission.
Table B.1. Sensor security permissions
Permission name |
Methods protected by this permission |
---|---|
javax.microedition.sensor.PrivateSensor |
|
javax.microedition.sensor.ProtectedSensor |
|
javax.microedition.io.Connector.sensor |
|
The permissions must be placed into some function group. This specification does not mandate any particular function group. This is left to the MSA EG to decide.
Each function group lists modes for domains, whether:
Not allowed
Always allowed
Ask first time
Ask every time
The function group lists also the mode options, which a user can set for trusted/untrusted applications.
The permissions of the application are cut from permissions of the application domain and permissions asked in a jad descriptor in:
- MIDlet-Permissions, or/and
- MIDlet-Permissions-Opt
In different devices the protection of specific sensors may vary. This is problematic for the developers, because they do not know in advance which permissions are required. If, for example, MIDlet-Permissions: javax.microedition.sensor.PrivateSensor is requested, but the application domain does not have rights, the application is not even installed. The solution to this problem could be to use MIDlet-Permissions-Opt instead of MIDlet-Permissions. In this case the application is installed even if the domain didn't have defined rights.
Let's take the sensor measuring the quantity "fingerprint" as an example. In some devices it might require "javax.microedition.sensor.PrivateSensor" permission, in some devices it might not. By requesting in a JAD:
MIDlet-Permissions-Opt: javax.microedition.sensor.PrivateSensor
the application is installed in every case - even its domain has not got the required permissions to use the sensor. The installed application might even work, if the private sensor is not essential for that functionality. The application also works fine in the case the sensor is not private, i.e., requesting permissions in vain does not cause harm.
JSR 256 implementation in CDC and MIDP 3 based environments requires a permission class to be defined in addition to the traditional permission names that worked with MIDP 2. The permission class should be based on the existing permission names already defined in the JSR.
Permissions for CDC and CLDC 1.1.1 implementations use the fine-grained
security permissions based on java.security.Permission
.
In this API the only control point is opening the sensor with the
call Connector.open()
or push registering the sensor for an automatic launch.
Hence only one permission class, javax.microedition.sensor.SensorProtocolPermission
,
was defined. If the sensor can be opened, all the actions are allowed thereafter,
therefore no actions are listed in the SensorProtocolPermission
.
This permission accepts as a name either a valid sensor URI or
constants "javax.microedition.sensor.PrivateSensor" / "javax.microedition.sensor.ProtectedSensor".
The constants are for granting access to private or protected sensors.
Permission class with different name options | Corresponding named permission | Methods protected by this permission |
---|---|---|
SensorProtocolPermission(PRIVATE) | javax.microedition.sensor.PrivateSensor, javax.microedition.io.Connector.sensor |
Connector.open() ,
PushRegistry.registerConnection()
|
SensorProtocolPermission(PROTECTED) | javax.microedition.sensor.ProtectedSensor, javax.microedition.io.Connector.sensor |
Connector.open() ,
PushRegistry.registerConnection()
|
SensorProtocolPermission(sensor_url) | javax.microedition.io.Connector.sensor and when needed: javax.microedition.sensor.PrivateSensor and/or javax.microedition.sensor.ProtectedSensor |
Connector.open() ,
PushRegistry.registerConnection()
|
package javax.microedition.sensor; import java.security.Permission; import javax.microedition.io.GCFPermission; /** <p>This class represents an access right to a connection/connections via the "sensor" protocol. The <code>SensorProtocolPermission</code> grants the permission to either sensors measuring a certain quantity or to private/protected sensors. If the name given is a sensor URI then the access for sensors pointed by this URI is granted. Because a valid sensor URI always contains a quantity, <code>SensorProtocolPermissions</code> constructed with a URI will always address sensors of one quantity. The sensor URI is defined in {@link SensorConnection}.</p> <p>{@link #PRIVATE} and {@link #PROTECTED} constants are for private and protected sensors; the access is granted for the whole group of such sensors. The sensors of the group are most probably measuring different quantities.</p> <p>In the Mobile Sensor API the only security control points are opening a connection and registering for push, no other methods are protected. That is why no actions are listed here.</p> <p>Note: the sensor URI as a name may refer to one or more sensors, including private and protected sensors. If the policy prevents opening any of these sensors, the permission must not be granted.</p> */ public final class SensorProtocolPermission extends GCFPermission { /** *<p> The name for the permission targeted to private sensors. </p> */ public final static String PRIVATE = "javax.microedition.sensor.PrivateSensor"; /** *<p> The name for the permission targeted to protected sensor. </p> */ public final static String PROTECTED = "javax.microedition.sensor.ProtectedSensor"; /** <p>The method creates a new <code>SensorProtocolPermission</code>, the name of which may be:</p> <ul> <li>the sensor URI</li> <li>{@link #PRIVATE}</li> <li>{@link #PROTECTED}</li> </ul> @param name the permission name @throws IllegalArgumentException if the <code>uri</code> is zero length or not a valid name @throws NullPointerException if <code>uri</code> is <code>null</code> */ public SensorProtocolPermission(java.lang.String name){ if (name==null) throw new NullPointerException( "SensorProtocolPermission called with a null value"); if (name.length() == 0) throw new IllegalArgumentException( "SensorProtocolPermission called with a zero-length name"); try{ SensorManager.findSensors(name); }catch (IllegalArgumentException e) { throw new IllegalArgumentException( "SensorProtocolPermission called with an invalid name "+name); } } /**<p> The method checks two <code>SensorProtocolPermission</code> objects for equality. Checks that given <i>object</i> is a <code>SensorProtocolPermission</code> and has the same name as this object.</p> @param object the object we are testing for equality with this object. @return <code>true</code> if object is a <code>SensorProtocolPermission</code>, and has the same name as this <code>SensorProtocolPermission</code> object. */ public boolean equals(Object object) { if (object == this) return true; if (! (object instanceof SensorProtocolPermission)) return false; return getName().equals(((SensorProtocolPermission)object).getName()); } /**<p> The method returns actions, for this permission the method returns always <code>null</code> since no actions are defined.</p> @return <code>null</code> */ public String getActions() { return null; } /**<p> The method returns the hash code value for this object. The value returned complies with the requirements of the the hashCode method of the superclass.</p> @return a hash code value for this object. */ public int hashCode() { return this.getName().hashCode(); } /**<p> The method checks if this <code>SensorProtocolPermission</code> object "implies" the specified permission. More specifically, this method returns <code>true</code> if:</p> <ul> <li><i>p</i> is an instanceof <code>SensorProtocolPermission</code>, and</li> <li><i>p</i>'s actions return <code>null</code>, and</li> <li><i>p</i>'s name equals this object's name, or if</li> <li><i>p</i>'s sensor URI defines a subset of the category (private/protected), or if</li> <li><i>p</i>'s sensor URI defines a subset of sensors of this object's URI</li> </ul> @param p the permission to check against. * @return <code>true</code> if the specified permission is implied by this object, <code>false</code> if not. */ public boolean implies(Permission p) { if (!(p instanceof SensorProtocolPermission)) return false; // Check of this SensorProtocolPermission's name implies the other's name String name = getName(); String name2 = p.getName(); if (name.equals(name2)) return true; // URI defines a subset of sensors of this object's category (private/protected) String[] categories = {PRIVATE, PROTECTED}; SensorInfo[] infos2 = SensorManager.findSensors(name2); for (int i=0; i<categories.length; i++){ if (!name.equals(categories[i])) continue; if (name2.equals(categories[i])) return false; for (int j=0; j<infos2.length; j++){ String category = null; if (infos2[j].getProperty(SensorInfo.PROP_PERMISSION)!=null){ category = (String)infos2[j].getProperty(SensorInfo.PROP_PERMISSION); } if (category == null) return false; if (category.indexOf(categories[i])==-1) return false; } // true only if sensors were found return (infos2.length>0); } // URI defines a subset of sensors of this object's URI SensorInfo[] infos = SensorManager.findSensors(name); //infos2 must be a subset of infos for (int i=0; i<infos2.length; i++){ String tmpUrl2 = infos2[i].getUrl(); int j=0; for (; j<infos.length && !(infos[i].getUrl().equals(tmpUrl2)); j++); if (j==infos.length) return false; } // true only if sensors were found return (infos2.length>0); } }