Permissions and Privileges

Updated: April 19, 2023

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

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.

Note:

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 to 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

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:

read
Read permission means that you're able to access the object to retrieve properties and buffers. Examples of functions that can be performed if you have read access are:
write
Write permission means that you're able to access the object to set properties and write to buffers. Examples of functions that can be performed if you have write access are:
execute

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 correspond to an integer setting.

Setting SCREEN_PROPERTY_PERMISSIONS as an integer

Valid permissions that can be used and combined 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.

Note: Setting SCREEN_PROPERTY_PERMISSIONS as an integer is absolute. It completely replaces any previous value of SCREEN_PROPERTY_PERMISSIONS.
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);
...
            
In this case, if you have the same process ID as that window, then you're permitted to call the following on that window:
CAUTION:
We don't recommend removing all owner permissions. When you set SCREEN_PROPERTY_PERMISSIONS as an integer, make sure that the following bits are included in the permissions that you're setting:
  • SCREEN_PERMISSION_IRWIN
  • SCREEN_PERMISSION_IWWIN
  • SCREEN_PERMISSION_IXWIN

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 each permission string and its 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

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);
            
In this example, the permissions in string form have corresponding masks. Therefore, in addition to the default permissions mask, the following bits are now set:
  • SCREEN_PERMISSION_IRTOP
  • SCREEN_PERMISSION_IWTOP
  • SCREEN_PERMISSION_IXTOP

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

Note: Whether you're setting SCREEN_PROPERTY_PERMISSIONS as an integer or as a string, you still change it by calling the object's set property function. This function is delayed in its execution. That is, the command is queued for batch processing at a later time. Remember to perform a flush using screen_flush_context() to ensure that your permissions are changed and take effect when you expect them to.