Commit b78d2220 authored by John Palmieri's avatar John Palmieri

Console user security policy

* bus/config-parser.c:
(struct PolicyType): Add POLICY_CONSOLE
(struct Element.d.policy): s/gid_or_uid/gid_uid_or_at_console
(start_busconfig_child): Sets up console element when
<policy at_console=""> is encountered in a policy file
(append_rule_from_element): Convert console elements to console
rules.

* bus/policy.c:
(bus_policy_create_client_policy): Add console rules to the client
policy based on if the client is at the console
(bus_policy_append_console_rule): New function for adding a
console rule to a policy
(bus_policy_merge): Handle console rule merging

* dbus/dbus-sysdeps.h: Added the DBUS_CONSOLE_DIR constant
where we check for console user files

* dbus/dbus-sysdeps.c:
(_dbus_file_exists): New function which checks if the given
file exists
(_dbus_user_at_console): New function which does the system
specific process of checking if the user is at the console

* dbus/dbus-userdb.c:
(_dbus_is_console_user): New function converts a UID to user name
and then calls the system specific _dbus_user_at_console to
see if the user is at the console and therefor a console user
parent 8a2c91b8
2004-08-25 John Palmieri <johnp@redhat.com>
* bus/config-parser.c:
(struct PolicyType): Add POLICY_CONSOLE
(struct Element.d.policy): s/gid_or_uid/gid_uid_or_at_console
(start_busconfig_child): Sets up console element when
<policy at_console=""> is encountered in a policy file
(append_rule_from_element): Convert console elements to console
rules.
* bus/policy.c:
(bus_policy_create_client_policy): Add console rules to the client
policy based on if the client is at the console
(bus_policy_append_console_rule): New function for adding a
console rule to a policy
(bus_policy_merge): Handle console rule merging
* dbus/dbus-sysdeps.h: Added the DBUS_CONSOLE_DIR constant
where we check for console user files
* dbus/dbus-sysdeps.c:
(_dbus_file_exists): New function which checks if the given
file exists
(_dbus_user_at_console): New function which does the system
specific process of checking if the user is at the console
* dbus/dbus-userdb.c:
(_dbus_is_console_user): New function converts a UID to user name
and then calls the system specific _dbus_user_at_console to
see if the user is at the console and therefor a console user
2004-08-25 Olivier Andrieu <oliv__a@users.sourceforge.net>
* bus/config-parser.c (set_limit):
......
......@@ -59,7 +59,8 @@ typedef enum
POLICY_DEFAULT,
POLICY_MANDATORY,
POLICY_USER,
POLICY_GROUP
POLICY_GROUP,
POLICY_CONSOLE
} PolicyType;
typedef struct
......@@ -79,7 +80,7 @@ typedef struct
struct
{
PolicyType type;
unsigned long gid_or_uid;
unsigned long gid_uid_or_at_console;
} policy;
struct
......@@ -775,6 +776,7 @@ start_busconfig_child (BusConfigParser *parser,
const char *context;
const char *user;
const char *group;
const char *at_console;
if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
{
......@@ -791,16 +793,20 @@ start_busconfig_child (BusConfigParser *parser,
"context", &context,
"user", &user,
"group", &group,
"at_console", &at_console,
NULL))
return FALSE;
if (((context && user) ||
(context && group)) ||
(user && group) ||
!(context || user || group))
(context && group) ||
(context && at_console)) ||
((user && group) ||
(user && at_console)) ||
(group && at_console) ||
!(context || user || group || at_console))
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"<policy> element must have exactly one of (context|user|group) attributes");
"<policy> element must have exactly one of (context|user|group|at_console) attributes");
return FALSE;
}
......@@ -828,7 +834,7 @@ start_busconfig_child (BusConfigParser *parser,
_dbus_string_init_const (&username, user);
if (_dbus_get_user_id (&username,
&e->d.policy.gid_or_uid))
&e->d.policy.gid_uid_or_at_console))
e->d.policy.type = POLICY_USER;
else
_dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
......@@ -840,12 +846,30 @@ start_busconfig_child (BusConfigParser *parser,
_dbus_string_init_const (&group_name, group);
if (_dbus_get_group_id (&group_name,
&e->d.policy.gid_or_uid))
&e->d.policy.gid_uid_or_at_console))
e->d.policy.type = POLICY_GROUP;
else
_dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
group);
}
else if (at_console != NULL)
{
dbus_bool_t t;
t = (strcmp (at_console, "true") == 0);
if (t || strcmp (at_console, "false") == 0)
{
e->d.policy.gid_uid_or_at_console = t;
e->d.policy.type = POLICY_CONSOLE;
}
else
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Unknown value \"%s\" for at_console in message bus configuration file",
at_console);
return FALSE;
}
}
else
{
_dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
......@@ -936,6 +960,7 @@ append_rule_from_element (BusConfigParser *parser,
const char *own;
const char *user;
const char *group;
BusPolicyRule *rule;
if (!locate_attributes (parser, element_name,
......@@ -1369,7 +1394,7 @@ append_rule_from_element (BusConfigParser *parser,
goto failed;
}
if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_or_uid,
if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
rule))
goto nomem;
break;
......@@ -1382,12 +1407,19 @@ append_rule_from_element (BusConfigParser *parser,
goto failed;
}
if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_or_uid,
if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
rule))
goto nomem;
break;
case POLICY_CONSOLE:
if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
rule))
goto nomem;
break;
}
bus_policy_rule_unref (rule);
rule = NULL;
}
......@@ -2545,7 +2577,7 @@ elements_equal (const Element *a,
case ELEMENT_POLICY:
if (a->d.policy.type != b->d.policy.type)
return FALSE;
if (a->d.policy.gid_or_uid != b->d.policy.gid_or_uid)
if (a->d.policy.gid_uid_or_at_console != b->d.policy.gid_uid_or_at_console)
return FALSE;
break;
......
......@@ -125,10 +125,12 @@ struct BusPolicy
{
int refcount;
DBusList *default_rules; /**< Default policy rules */
DBusList *mandatory_rules; /**< Mandatory policy rules */
DBusHashTable *rules_by_uid; /**< per-UID policy rules */
DBusHashTable *rules_by_gid; /**< per-GID policy rules */
DBusList *default_rules; /**< Default policy rules */
DBusList *mandatory_rules; /**< Mandatory policy rules */
DBusHashTable *rules_by_uid; /**< per-UID policy rules */
DBusHashTable *rules_by_gid; /**< per-GID policy rules */
DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
};
static void
......@@ -209,7 +211,13 @@ bus_policy_unref (BusPolicy *policy)
_dbus_list_foreach (&policy->mandatory_rules, free_rule_func, NULL);
_dbus_list_clear (&policy->mandatory_rules);
_dbus_list_foreach (&policy->at_console_true_rules, free_rule_func, NULL);
_dbus_list_clear (&policy->at_console_true_rules);
_dbus_list_foreach (&policy->at_console_false_rules, free_rule_func, NULL);
_dbus_list_clear (&policy->at_console_false_rules);
if (policy->rules_by_uid)
{
_dbus_hash_table_unref (policy->rules_by_uid);
......@@ -264,7 +272,8 @@ bus_policy_create_client_policy (BusPolicy *policy,
DBusError *error)
{
BusClientPolicy *client;
unsigned long uid;
dbus_uid_t uid;
dbus_bool_t at_console;
_dbus_assert (dbus_connection_get_is_authenticated (connection));
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
......@@ -333,6 +342,23 @@ bus_policy_create_client_policy (BusPolicy *policy,
}
}
/* Add console rules */
at_console = _dbus_is_console_user (uid, error);
if (at_console)
{
if (!add_list_to_client (&policy->at_console_true_rules, client))
goto nomem;
}
else if (dbus_error_is_set (error) == TRUE)
{
goto failed;
}
else if (!add_list_to_client (&policy->at_console_false_rules, client))
{
goto nomem;
}
if (!add_list_to_client (&policy->mandatory_rules,
client))
goto nomem;
......@@ -367,7 +393,7 @@ list_allows_user (dbus_bool_t def,
{
BusPolicyRule *rule = link->data;
link = _dbus_list_get_next_link (list, link);
if (rule->type == BUS_POLICY_RULE_USER)
{
_dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n",
......@@ -471,6 +497,8 @@ bus_policy_append_mandatory_rule (BusPolicy *policy,
return TRUE;
}
static DBusList**
get_list (DBusHashTable *hash,
unsigned long key)
......@@ -535,6 +563,28 @@ bus_policy_append_group_rule (BusPolicy *policy,
return TRUE;
}
dbus_bool_t
bus_policy_append_console_rule (BusPolicy *policy,
dbus_bool_t at_console,
BusPolicyRule *rule)
{
if (at_console)
{
if (!_dbus_list_append (&policy->at_console_true_rules, rule))
return FALSE;
}
else
{
if (!_dbus_list_append (&policy->at_console_false_rules, rule))
return FALSE;
}
bus_policy_rule_ref (rule);
return TRUE;
}
static dbus_bool_t
append_copy_of_policy_list (DBusList **list,
DBusList **to_append)
......@@ -606,6 +656,14 @@ bus_policy_merge (BusPolicy *policy,
&to_absorb->mandatory_rules))
return FALSE;
if (!append_copy_of_policy_list (&policy->at_console_true_rules,
&to_absorb->at_console_true_rules))
return FALSE;
if (!append_copy_of_policy_list (&policy->at_console_false_rules,
&to_absorb->at_console_false_rules))
return FALSE;
if (!merge_id_hash (policy->rules_by_uid,
to_absorb->rules_by_uid))
return FALSE;
......
......@@ -26,6 +26,7 @@
#include <dbus/dbus.h>
#include <dbus/dbus-string.h>
#include <dbus/dbus-list.h>
#include <dbus/dbus-sysdeps.h>
#include "bus.h"
......@@ -96,7 +97,7 @@ struct BusPolicyRule
/* can be DBUS_GID_UNSET meaning "any" */
dbus_gid_t gid;
} group;
} d;
};
......@@ -124,6 +125,10 @@ dbus_bool_t bus_policy_append_user_rule (BusPolicy *policy,
dbus_bool_t bus_policy_append_group_rule (BusPolicy *policy,
dbus_gid_t gid,
BusPolicyRule *rule);
dbus_bool_t bus_policy_append_console_rule (BusPolicy *policy,
dbus_bool_t at_console,
BusPolicyRule *rule);
dbus_bool_t bus_policy_merge (BusPolicy *policy,
BusPolicy *to_absorb);
......
......@@ -3332,6 +3332,55 @@ _dbus_set_signal_handler (int sig,
sigaction (sig, &act, 0);
}
/** Checks if a file exists
*
* @param file full path to the file
* @returns #TRUE if file exists
*/
dbus_bool_t
_dbus_file_exists (const char *file)
{
return (access (file, F_OK) == 0);
}
/** Checks if user is at the console
*
* @param username user to check
* @param error return location for errors
* @returns #TRUE is the user is at the consolei and there are no errors
*/
dbus_bool_t
_dbus_user_at_console (const char *username,
DBusError *error)
{
DBusString f;
dbus_bool_t result;
if (!_dbus_string_init (&f))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return FALSE;
}
if (!_dbus_string_append (&f, DBUS_CONSOLE_DIR))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return FALSE;
}
if (!_dbus_string_append (&f, username))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return FALSE;
}
result = _dbus_file_exists (_dbus_string_get_const_data (&f));
_dbus_string_free (&f);
return result;
}
#ifdef DBUS_BUILD_TESTS
#include <stdlib.h>
......
......@@ -99,6 +99,8 @@ typedef unsigned long dbus_gid_t;
#define DBUS_UID_FORMAT "%lu"
#define DBUS_GID_FORMAT "%lu"
#define DBUS_CONSOLE_DIR "/var/run/console/"
/**
* Struct representing socket credentials
*/
......@@ -309,6 +311,9 @@ typedef void (* DBusSignalHandler) (int sig);
void _dbus_set_signal_handler (int sig,
DBusSignalHandler handler);
dbus_bool_t _dbus_file_exists (const char *file);
dbus_bool_t _dbus_user_at_console (const char *username,
DBusError *error);
/* Define DBUS_VA_COPY() to do the right thing for copying va_list variables.
* config.h may have already defined DBUS_VA_COPY as va_copy or __va_copy.
......
......@@ -38,6 +38,7 @@ struct DBusUserDatabase
DBusHashTable *groups; /**< Groups in the database by GID */
DBusHashTable *users_by_name; /**< Users in the database by name */
DBusHashTable *groups_by_name; /**< Groups in the database by name */
};
static void
......@@ -398,6 +399,48 @@ _dbus_get_user_id (const DBusString *username,
return TRUE;
}
/**
* Checks to see if the UID sent in is the console user
*
* @param uid UID of person to check
* @param error return location for errors
* @returns #TRUE if the UID is the same as the console user and there are no errors
*/
dbus_bool_t
_dbus_is_console_user (dbus_uid_t uid,
DBusError *error)
{
DBusUserDatabase *db;
const DBusUserInfo *info;
DBusString *console_file;
dbus_bool_t result = FALSE;
_dbus_user_database_lock_system ();
db = _dbus_user_database_get_system ();
if (db == NULL)
{
dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get system database.");
_dbus_user_database_unlock_system ();
return FALSE;
}
info = _dbus_user_database_lookup (db, uid, NULL, error);
if (info == NULL)
{
_dbus_user_database_unlock_system ();
return FALSE;
}
result = _dbus_user_at_console (info->username, error);
_dbus_user_database_unlock_system ();
return result;
}
/**
* Gets group ID given groupname
*
......
......@@ -56,7 +56,6 @@ dbus_bool_t _dbus_user_database_get_groupname (DBusUserDatabase *db,
DBusError *error);
DBusUserDatabase* _dbus_user_database_get_system (void);
void _dbus_user_database_lock_system (void);
void _dbus_user_database_unlock_system (void);
......@@ -75,6 +74,8 @@ dbus_bool_t _dbus_credentials_from_username (const DBusString *username,
DBusCredentials *credentials);
dbus_bool_t _dbus_credentials_from_uid (dbus_uid_t user_id,
DBusCredentials *credentials);
dbus_bool_t _dbus_is_console_user (dbus_uid_t uid,
DBusError *error);
DBUS_END_DECLS;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment