Permissions and privileges together determine the level of access to API objects (e.g., windows and sessions).
Permissions and privileges are two different things. Permissions define the ability to perform certain operations, such as setting a property. Privileges are the set of permissions that are granted based on the type of role.
Note that permissions are not applied when it comes to the creation (e.g., screen_create_*()) or destruction (e.g., screen_destroy_*()) of objects.
Privileges are permissions that are controlled by roles. Just as how POSIX uses the roles of user, group, and other to determine permissions, Screen uses the roles of owner, user, manager, and consumer.
Role | Description |
---|---|
Owner | An owner is defined as whoever creates the object. The owner, by default, has privileges to get and set certain properties, to perform certain functions, and to grant user permissions. |
User | A user has privileges based on user permissions. These user permissions are granted by the owner of the object. By default, an owner has owner and user privileges. User permissions (SCREEN_PROPERTY_PERMISSIONS) are set through the Screen API. |
Manager |
A manager, by default, has privileges to get and set certain properties, and to perform certain functions. Managers must be created within a privileged context type. The following context types provide managers with privileged access: SCREEN_WINDOW_MANAGER_CONTEXT SCREEN_POWER_MANAGER_CONTEXT SCREEN_DISPLAY_MANAGER_CONTEXT SCREEN_INPUT_MANAGER_CONTEXT A parent assumes a manager role for read and write access to certain properties because it can be considered a manager of its child windows (but not all parents necessarily manage their children). Manager privileges can't be set. The role of manager can only be gained or lost by joining or leaving groups, respectively. |
Consumer |
A consumer, by default, has privileges to get and set certain properties, and to perform certain functions. Generally a consumer takes its source from another object. Consumer privileges can't be set. The role of consumer can only be gained or lost by joining or leaving groups, respectively. |
Don't confuse the user role with the permissions class of user.
The user role corresponds to the privileges (user-permissions) that are granted by the owner to others through setting SCREEN_PROPERTY_PERMISSIONS.
The permissions class of user refers a category of permissions. An owner can use this user permissions class to grant permissions to others based on user ID and/or user name. For example:
char permissions[] = "user:1000:r--"; screen_set_window_property_cv(screen_win, SCREEN_PROPERTY_PERMISSIONS, \ strlen(permissions), permissions);
This example illustrates how to set user permissions to allow read access to any context with the user ID of 1000.
Permissions from the user role are what's granted to others. The owner grants these user permissions so that others can access the object. A SCREEN_EVENT_CREATE and a SCREEN_EVENT_CLOSE event are used to notify whoever gains or loses access to the object respectively. In the case of multiple grants of access, a SCREEN_EVENT_CREATE event is received only by those actually gaining the access. For example, someone granted access to its top-level window to everyone. A window manager, who already has access to all top-level windows doesn't receive a SCREEN_EVENT_CREATE event for this action. Instead, it receives a SCREEN_EVENT_PROPERTY event to indicate that the SCREEN_PROPERTY_PERMISSIONS property of that window has changed.
The user permissions apply only to those properties that can be changed by the owner of the object. Properties that can be changed only by a specific role remain unaffected regardless of the setting of SCREEN_PROPERTY_PERMISSIONS. For example, there are window properties that can be changed only by a window's parent. This rule still holds true despite the value that SCREEN_PROPERTY_PERMISSIONS is set to. The exeception is that if the window has no parent, or if there is no window manager, then the permissions apply to all window properties.
Permissions can be set dynamically; this means you can set the SCREEN_PROPERTY_PERMISSIONS property at any time. However, note that permissions are not cached. If you change permissions, you'll need to ensure that it doesn't interfere with any ongoing processing that your application is doing. For example, a screen_blit() could be successful, but then if permissions are changed, it could cause a subsequent call to screen_blit() to fail.
Similar to setting file permissions with chmod (change file modes in POSIX) or setfacl, if you want someone to have special access to an object, you need to set the appropriate permissions on that object. The permissions control the read, write, and execute accessibilities to your object following file permissions conventions.
The read, write, and execute permissions can be specified for each class of user for an object. Note that the following mapping applies:
Execute permission means that you're able to access the object to inject events to it. This means that screen_inject_event() function can be used to inject the event.
The function screen_inject_event() doesn't require an object handle. Therefore, if you grant only execute permissions to others, Screen doesn't send SCREEN_EVENT_CREATE or SCREEN_EVENT_CLOSE events.
Permissions are set using the SCREEN_PROPERTY_PERMISSIONS property. You can set this property as:
When you set the SCREEN_PROPERTY_PERMISSIONS as a string, Screen updates the integer value where applicable.
The SCREEN_PROPERTY_PERMISSIONS can't be retrieved as a string. When you retrieve it using a screen_get_*_property_iv() function, you won't see any permission changes you've made by setting SCREEN_PROPERTY_PERMISSIONS as a string, unless your string permissions corresponds to an integer setting.
Setting SCREEN_PROPERTY_PERMISSIONS as an integer
Valid permissions that can be used and combined are are defined by Screen permission masks. You can retrieve and set this property by using the Screen API functions screen_get_*_property_iv() and screen_set_*_property_iv(), respectively. For example, if the object in question is a window, then you'd use screen_get_window_property_iv() to retrieve SCREEN_PROPERTY_PERMISSIONS and screen_set_window_property_iv() to set it.
Class | Mask group | Description | Permission masks |
---|---|---|---|
Owner | WIN | If you are the owner of this object, you will have the specified permissions to this object. |
SCREEN_PERMISSION_IRWIN SCREEN_PERMISSION_IWWIN SCREEN_PERMISSION_IXWIN |
Parent | TOP | If you are the parent of this object, you will have the specified permissions to this object. |
SCREEN_PERMISSION_IRTOP SCREEN_PERMISSION_IWTOP SCREEN_PERMISSION_IXTOP |
User ID | USR | If you have the same user ID as the owner of this object, you will have the specified permissions to this object. |
SCREEN_PERMISSION_IRUSR SCREEN_PERMISSION_IWUSR SCREEN_PERMISSION_IXUSR |
Group ID | GRP | If you have the same group ID as the owner of this object, you will have the specified permissions to this object. |
SCREEN_PERMISSION_IRGRP SCREEN_PERMISSION_IWGRP SCREEN_PERMISSION_IXGRP |
Process ID | PID | If you have the same process ID as the owner of this object, you will have the specified permissions to this object. |
SCREEN_PERMISSION_IRPID SCREEN_PERMISSION_IWPID SCREEN_PERMISSION_IXPID |
Process group ID | PGP | If you have the same process group ID as the owner of this object, you will have the specified permissions to this object. |
SCREEN_PERMISSION_IRPGP SCREEN_PERMISSION_IWPGP SCREEN_PERMISSION_IXPGP |
Application group | AGP | If you are in the same application group as the owner of this object, you will have the specified permissions to this object. |
SCREEN_PERMISSION_IRAGP SCREEN_PERMISSION_IWAGP SCREEN_PERMISSION_IXAGP |
Other | OTH | Anyone will have the specified permissions to this object. |
SCREEN_PERMISSION_IROTH SCREEN_PERMISSION_IWOTH SCREEN_PERMISSION_IXOTH |
For example, let's say you have this code:
... screen_window_t screen_win; int permissions = SCREEN_PERMISSION_IRWIN | SCREEN_PERMISSION_IWWIN | SCREEN_PERMISSION_IXWIN \ SCREEN_PERMISSION_IRPID | SCREEN_PERMISSION_IWPID | SCREEN_PERMISSION_IXPID; /* Note that the above permissions include the owner privileges. These need to be included * because when setting permissions using masks, the setting replaces all previous values. That's * why we include the owner privileges so that we don't lose them. */ ... screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_PERMISSIONS, permissions); ...
When you use SCREEN_PROPERTY_PERMISSIONS as an integer, you're able to grant access to different classes, but all within the context created by the same process. If you want to grant access to an outside process, the only way to do so is to set the permissions for Others. However, by granting the Others permission, it includes all others. So, there's really no way to grant access to a particular outside process without giving access to everyone else. Use SCREEN_PROPERTY_PERMISSIONS as a string if you need to have more control on filtering permissions.
Setting SCREEN_PROPERTY_PERMISSIONS as a string
You can further restrict permissions to particular clients or classes of clients if you use the SCREEN_PROPERTY_PERMISSIONS property as a string. Unlike the integer permissions, the string permissions allow you to specify a specific context, process, process group, group, or user that's not the same as the owner of the object.
You can set this property by using the Screen API set functions (screen_set_*_property_cv()). For example, if the object in question is a window, then you'd use screen_set_window_property_cv() to set it. When using permissions as a string, the permissions masks (integer) are set, but only the bits that have an integer association with the string form.
The following table shows permissions strings and their corresponding permissions masks:
Class | Permissions string | Applicable permissions masks |
---|---|---|
Owner | context::rwx |
SCREEN_PERMISSION_IRWIN SCREEN_PERMISSION_IWWIN SCREEN_PERMISSION_IXWIN |
Parent | parent::rwx |
SCREEN_PERMISSION_IRTOP SCREEN_PERMISSION_IWTOP SCREEN_PERMISSION_IXTOP |
Application | application::rwx |
SCREEN_PERMISSION_IRAGP SCREEN_PERMISSION_IWAGP SCREEN_PERMISSION_IXAGP |
Process | process::rwx |
SCREEN_PERMISSION_IRPID SCREEN_PERMISSION_IWPID SCREEN_PERMISSION_IXPID |
Process group | processgroup::rwx |
SCREEN_PERMISSION_IRPGP SCREEN_PERMISSION_IWPGP SCREEN_PERMISSION_IXPGP |
User | user::rwx |
SCREEN_PERMISSION_IRUSR SCREEN_PERMISSION_IWUSR SCREEN_PERMISSION_IXUSR |
Group | group::rwx |
SCREEN_PERMISSION_IRGRP SCREEN_PERMISSION_IWGRP SCREEN_PERMISSION_IXGRP |
Other | other::rwx |
SCREEN_PERMISSION_IROTH SCREEN_PERMISSION_IWOTH SCREEN_PERMISSION_IXOTH |
The following table shows the format for all permissions strings:
Class | Format | Example |
---|---|---|
Parent | parent::permissions | parent::rwx |
Application | application::permissions | application::rwx |
Owner | context::permissions | context::rwx |
Specified context | context:id:permissions | context:screen-ctx-0-00000000-657eb725d72a0c965a743c0672534abf:rwx |
Process | process::permissions | process::rwx |
Specified process | process:pid:permissions | process:1234:rwx |
Process group | process group::permissions | process group::rwx |
Specified process group | process group:pgid:permissions | process group:5678:rwx |
User | user::permissions | user::rwx |
Specified user | user:uid:permissions | user:1000:rwx |
Named user | user:uname:permissions | user:root:rwx |
Group | group::permissions | group::rwx |
Specified group | group:gid:permissions | group:2000:rwx |
Named group | group:gname:permissions | group:root:rwx |
Other | other::permissions | other::rwx |
The id for specified contexts is the identifier of the context object. You can retrieve this identifier from the context by calling screen_get_context_property_cv() for SCREEN_PROPERTY_ID. The ID of the context is returned. This string is used to set the permissions.
The permissions string is a combination of r (read), w (write), x (execute), and - (no permission). The permissions must be specified in this order.
Here are some examples (presuming a default set of permissions mask that includes owner privileges):
Example 1: Setting SCREEN_PROPERTY_PERMISSIONS as a string, then retrieving the property
... char c_permissions[] = "parent::rwx"; int i_permissions; screen_set_window_property_cv(screen_win, SCREEN_PROPERTY_PERMISSIONS, strlen(c_permissions),c_permissions); screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_PERMISSIONS, i_permissions);
Example 2: Setting SCREEN_PROPERTY_PERMISSIONS as a string and as an integer, then retrieving the property
... char c_permissions[] = "context:screen-ctx-0-00000000-657eb725d72a0c965a743c0672534abf:rwx"; int i_permissions = SCREEN_PERMISSION_IRWIN | SCREEN_PERMISSION_IWWIN | SCREEN_PERMISSION_IXWIN | \ SCREEN_PERMISSION_IRGRP | SCREEN_PERMISSION_IWGRP | SCREEN_PERMISSION_IXGRP; screen_set_window_property_cv(screen_win, SCREEN_PROPERTY_PERMISSIONS, strlen(c_permissions), c_permissions); screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_PERMISSIONS, i_permissions); screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_PERMISSIONS, i_permissions);
In this example, the permissions set in string form don't have corresponding permissions masks. Therefore, the resulting property value is: SCREEN_PERMISSION_IRGRP | SCREEN_PERMISSION_IWGRP | SCREEN_PERMISSION_IXGRP | SCREEN_PERMISSION_IRWIN | SCREEN_PERMISSION_IWWIN | SCREEN_PERMISSION_IXWIN . Despite not being accounted for in the integer value, the permissions that were set in string form are still applied.
Example 3: Setting SCREEN_PROPERTY_PERMISSIONS as strings, then retrieving the property
... char permissions1000[] = "user:1000:rw-"; char permissions1001[] = "user:1001:rw-"; int permissions; screen_set_window_property_cv(screen_win, SCREEN_PROPERTY_PERMISSIONS, \ strlen(permissions1000), permissions1000); screen_set_window_property_cv(screen_win, SCREEN_PROPERTY_PERMISSIONS, \ strlen(permissions1001), permissions1001); screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_PERMISSIONS, permissions);
In this example, the permissions set in string form don't have corresponding permissions masks. Therefore, the default permissions mask is returned from the query of SCREEN_PROPERTY_PERMISSIONS. Despite not being accounted for in the integer value, the permissions that are set in string form are still applied. Unlike setting permissions as an integer, setting permissions as a string is additive. Subsequent settings of permissions won't undo previous settings. Therefore, users 1000 and 1001 both result in having rw- permissions.
To remove permissions from user 1000, you can call set again with the string permissions as: user:1000:---
Setting specified classes won't affect the permission masks