Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15360840
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-05-31 17:45:45

浅析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;
    }
}

阅读(10344) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~