浅析dbus程序对启动脚本--system.conf配置文件解析
main
==>bus_context_new
==>bus_config_load
XML_SetUserData (expat, &context);
XML_SetElementHandler (expat,
expat_StartElementHandler,
expat_EndElementHandler);
XML_SetCharacterDataHandler (expat,
expat_CharacterDataHandler);
_dbus_file_get_contents (&data, file, error);
XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE);
expat_StartElementHandler
==>process_content
++>bus_config_parser_content // 第1次进入因为待处理的内容空,所以直接退出[luther.gliethttp]
dbus_bool_t
bus_config_parser_content (BusConfigParser *parser,
const DBusString *content,
DBusError *error)
{
......
case ELEMENT_LISTEN:
{
char *s;
// unix:path=/dev/socket/dbus
e->had_content = TRUE;
if (!_dbus_string_copy_data (content, &s))
goto nomem;
if (!_dbus_list_append (&parser->listen_on,
s))
{
dbus_free (s);
goto nomem;
}
}
/*
main
==>bus_context_new
==>process_config_first_time_only
==>addresses = bus_config_parser_get_addresses (parser);
==>link = _dbus_list_get_first_link (addresses);
DBusList**
bus_config_parser_get_addresses (BusConfigParser *parser)
{
return &parser->listen_on;
}
==>dbus_server_listen(link->data, error);
==>dbus_parse_address (address, &entries, &len, error)
address = "unix:path=/dev/socket/dbus"
method = "unix"
key = "path"
value = "/dev/socket/dbus"
==>listen_funcs
++>_dbus_server_listen_platform_specific
++>method = dbus_address_entry_get_method (entry);
++>if (strcmp (method, "unix") == 0)
++>const char *path = dbus_address_entry_get_value (entry, "path");
*/
break;
......
}
==>bus_config_parser_start_element(context->parser, name, (const char **) names, (const char **) values, context->error)
==>start_busconfig_child 和 bus_config_parser_content
==>element_type = bus_config_parser_element_name_to_type (element_name);
==>push_element
/*
expat_CharacterDataHandler
==> context->content // context->content="send_requested_reply="true""
static void
expat_CharacterDataHandler (void *userData,
const XML_Char *s,
int len)
{
ExpatParseContext *context = userData;
if (context->failed)
return;
if (!_dbus_string_append_len (&context->content,
s, len))
{
dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL);
context->failed = TRUE;
return;
}
}
当遇到<之后就开始执行expat_StartElementHandler
当遇到/>之后就开始执行expat_EndElementHandler
expat_EndElementHandler
==>process_content
==>bus_config_parser_end_element
==>pop_element
*/
static dbus_bool_t
start_busconfig_child (BusConfigParser *parser,
const char *element_name,
const char **attribute_names,
const char **attribute_values,
DBusError *error)
{
ElementType element_type;
element_type = bus_config_parser_element_name_to_type (element_name); // 字符串名转为enum type值
if (element_type == ELEMENT_TYPE)
{
if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
return FALSE;
if (push_element (parser, ELEMENT_TYPE) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
return TRUE;
}
else if (element_type == ELEMENT_FORK)
{
if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
return FALSE;
if (push_element (parser, ELEMENT_FORK) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
parser->fork = TRUE;
return TRUE;
}
else if (element_type == ELEMENT_LISTEN)
{
if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
return FALSE;
if (push_element (parser, ELEMENT_LISTEN) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
return TRUE;
}
else if (element_type == ELEMENT_AUTH)
{
if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
return FALSE;
if (push_element (parser, ELEMENT_AUTH) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
return TRUE;
}
else if (element_type == ELEMENT_POLICY) // 处理dbus.conf的policy字段
{
Element *e;
const char *context;
const char *user;
const char *group;
const char *at_console;
if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
e->d.policy.type = POLICY_IGNORED;
// dbus.conf
// 这里的context就是这个元素的第一个属性
if (!locate_attributes (parser, "policy", // 读取属性值
attribute_names,
attribute_values,
error,
"context", &context, // 所以context = "default"
"user", &user,
"group", &group,
"at_console", &at_console,
NULL))
return FALSE;
if (((context && user) ||
(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,
" element must have exactly one of (context|user|group|at_console) attributes");
return FALSE;
}
if (context != NULL)
{
if (strcmp (context, "default") == 0)
{
e->d.policy.type = POLICY_DEFAULT; // 我们的dbus.conf文件设置的就是"default"
/*
==>bus_config_parser_start_element(context->parser, name, (const char **) names, (const char **) values, context->error)
==>start_policy_child
static dbus_bool_t
start_policy_child (BusConfigParser *parser,
const char *element_name,
const char **attribute_names,
const char **attribute_values,
DBusError *error)
{
if (strcmp (element_name, "allow") == 0) // 该元素的标记名为allow,它有自己的属性跟在allow之后了
// 比如:
//
// allow标记下有一个属性名own,该属性名的value为"*"
//
// allow标记下有一个属性名send_destination,该属性名value为"org.bluez.PasskeyAgent"
{
if (!append_rule_from_element (parser, element_name,
attribute_names, attribute_values,
TRUE, error))
return FALSE;
if (push_element (parser, ELEMENT_ALLOW) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
return TRUE;
}
else if (strcmp (element_name, "deny") == 0)
{
if (!append_rule_from_element (parser, element_name,
attribute_names, attribute_values,
FALSE, error))
return FALSE;
if (push_element (parser, ELEMENT_DENY) == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
return TRUE;
}
else
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Element <%s> not allowed inside <%s> in configuration file",
element_name, "policy");
return FALSE;
}
}
==>append_rule_from_element
==>locate_attributes (parser, element_name,
// 查看该标记allow下的属性value值务必为如下字符串,同时执行相应关键字下对应操作[luther.gliethttp]
// 比如:
//
// allow标记下有一个属性名send_destination,该属性名value为"org.bluez.PasskeyAgent"
// 这就是此次locate_attributes需要处理的内容,即:
// element_name等于"allow"
// attribute_names[0] = "send_destination"
// attribute_values[0] = "org.bluez.PasskeyAgent"
attribute_names,
attribute_values,
error,
"send_interface", &send_interface,
"send_member", &send_member,
"send_error", &send_error,
"send_destination", &send_destination,
"send_path", &send_path,
"send_type", &send_type,
"receive_interface", &receive_interface,
"receive_member", &receive_member,
"receive_error", &receive_error,
"receive_sender", &receive_sender,
"receive_path", &receive_path,
"receive_type", &receive_type,
"eavesdrop", &eavesdrop,
"send_requested_reply", &send_requested_reply,
"receive_requested_reply", &receive_requested_reply,
"own", &own,
"user", &user,
"group", &group,
"log", &log,
NULL)
==>pe = peek_element (parser); // 取出被push到链表上的最新元素,即:
// 这个就是pe的开始
// 如下都是该pe对应的rule们,它都将添加到parser->policy->default_rules中
// 这个就是pe的结束,将会push下一个pe
==>bus_policy_append_default_rule (parser->policy, rule)
dbus_bool_t
bus_policy_append_default_rule (BusPolicy *policy,
BusPolicyRule *rule)
{
if (!_dbus_list_append (&policy->default_rules, rule))
return FALSE;
bus_policy_rule_ref (rule);
return TRUE;
}
// 看看policy->default_rules的引用
main
==>bus_context_new
==>process_config_first_time_only
==>setup_server
==>dbus_server_set_new_connection_function (server, // 设置回调函数
new_connection_callback,
context, NULL);
最后server->new_connection_function = new_connection_callback;
==>new_connection_callback
==>bus_connections_setup_connection(context->connections, new_connection)
==>dbus_connection_set_unix_user_function (connection, // 设置回调函数allow_unix_user_function
allow_unix_user_function,
NULL, NULL);
最后connection->transport->unix_user_function = allow_unix_user_function;
==>allow_unix_user_function
==>bus_context_allow_unix_user
==>bus_policy_allow_unix_use
dbus_bool_t
bus_policy_allow_unix_user (BusPolicy *policy,
unsigned long uid)
{
dbus_bool_t allowed;
unsigned long *group_ids;
int n_group_ids;
// On OOM or error we always reject the user
if (!_dbus_unix_groups_from_uid (uid, &group_ids, &n_group_ids))
{
_dbus_verbose ("Did not get any groups for UID %lu\n",
uid);
return FALSE;
}
// Default to "user owning bus" can connect
allowed = _dbus_unix_user_is_process_owner (uid);
allowed = list_allows_user (allowed,
&policy->default_rules, //是否符合rules
uid,
group_ids, n_group_ids);
allowed = list_allows_user (allowed,
&policy->mandatory_rules,
uid,
group_ids, n_group_ids);
dbus_free (group_ids);
_dbus_verbose ("UID %lu allowed = %d\n", uid, allowed);
return allowed;
}
main
==>_dbus_loop_run
==>_dbus_loop_iterate
==>_dbus_loop_dispatch
==>dbus_connection_dispatch
==>(* filter->function) (connection, message, filter->user_data);
++>bus_dispatch_add_connection
dbus_bool_t
bus_dispatch_add_connection (DBusConnection *connection)
{
if (!dbus_connection_add_filter (connection,
bus_dispatch_message_filter,
NULL, NULL))
return FALSE;
return TRUE;
}
==>bus_dispatch_message_filter
==>bus_dispatch 或者 bus_driver_handle_activate_servic
==>send_one_message 或者 bus_transaction_send_from_driver
==>bus_context_check_security_policy
==>bus_client_policy_check_can_send
==>link = _dbus_list_get_first_link (&policy->rules); // 遍历policy它的所有rules,一一比对是否符合rules
*/
}
else if (strcmp (context, "mandatory") == 0)
{
e->d.policy.type = POLICY_MANDATORY;
}
else
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"context attribute on must have the value \"default\" or \"mandatory\", not \"%s\"",
context);
return FALSE;
}
}
else if (user != NULL)
{
DBusString username;
_dbus_string_init_const (&username, user);
if (_dbus_parse_unix_user_from_config (&username,
&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",
user);
}
else if (group != NULL)
{
DBusString group_name;
_dbus_string_init_const (&group_name, group);
if (_dbus_parse_unix_group_from_config (&group_name,
&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 attributes null and we didn't set error");
}
return TRUE;
}
......
}
static void
expat_EndElementHandler (void *userData,
const XML_Char *name)
{
ExpatParseContext *context = userData;
if (!process_content (context))
return;
if (!bus_config_parser_end_element (context->parser,
name,
context->error))
{
context->failed = TRUE;
return;
}
}
|