/**
 * Loads the message in the given message file.
 *
 * @param filename filename to load
 * @param data string to load message into
 * @returns #TRUE if the message was loaded
 */
dbus_bool_t
dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
                                            DBusString          *data)
{
  dbus_bool_t retval;
  DBusError error = DBUS_ERROR_INIT;

  retval = FALSE;

  _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
  if (!_dbus_file_get_contents (data, filename, &error))
    {
      _dbus_warn ("Could not load message file %s: %s\n",
                  _dbus_string_get_const_data (filename),
                  error.message);
      dbus_error_free (&error);
      goto failed;
    }

  retval = TRUE;

 failed:

  return retval;
}
예제 #2
0
파일: bus.c 프로젝트: kobolabs/dbus
/* This code only gets executed the first time the
 * config files are parsed.  It is not executed
 * when config files are reloaded.
 */
static dbus_bool_t
process_config_first_time_only (BusContext       *context,
				BusConfigParser  *parser,
                                const DBusString *address,
                                BusContextFlags   flags,
				DBusError        *error)
{
  DBusString log_prefix;
  DBusList *link;
  DBusList **addresses;
  const char *user, *pidfile;
  char **auth_mechanisms;
  DBusList **auth_mechanisms_list;
  int len;
  dbus_bool_t retval;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  retval = FALSE;
  auth_mechanisms = NULL;
  pidfile = NULL;

  _dbus_init_system_log (TRUE);

  if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION)
    context->systemd_activation = TRUE;
  else
    context->systemd_activation = FALSE;

  /* Check for an existing pid file. Of course this is a race;
   * we'd have to use fcntl() locks on the pid file to
   * avoid that. But we want to check for the pid file
   * before overwriting any existing sockets, etc.
   */

  if (flags & BUS_CONTEXT_FLAG_WRITE_PID_FILE)
    pidfile = bus_config_parser_get_pidfile (parser);

  if (pidfile != NULL)
    {
      DBusString u;
      DBusStat stbuf;

      _dbus_string_init_const (&u, pidfile);

      if (_dbus_stat (&u, &stbuf, NULL))
        {
#ifdef DBUS_CYGWIN
          DBusString p;
          long /* int */ pid;

          _dbus_string_init (&p);
          _dbus_file_get_contents(&p, &u, NULL);
          _dbus_string_parse_int(&p, 0, &pid, NULL);
          _dbus_string_free(&p);

          if ((kill((int)pid, 0))) {
            dbus_set_error(NULL, DBUS_ERROR_FILE_EXISTS,
                           "pid %ld not running, removing stale pid file\n",
                           pid);
            _dbus_delete_file(&u, NULL);
          } else {
#endif
          dbus_set_error (error, DBUS_ERROR_FAILED,
		                  "The pid file \"%s\" exists, if the message bus is not running, remove this file",
                          pidfile);
	      goto failed;
#ifdef DBUS_CYGWIN
          }
#endif
        }
    }

  /* keep around the pid filename so we can delete it later */
  context->pidfile = _dbus_strdup (pidfile);

  /* note that type may be NULL */
  context->type = _dbus_strdup (bus_config_parser_get_type (parser));
  if (bus_config_parser_get_type (parser) != NULL && context->type == NULL)
    goto oom;

  user = bus_config_parser_get_user (parser);
  if (user != NULL)
    {
      context->user = _dbus_strdup (user);
      if (context->user == NULL)
        goto oom;
    }

  /* Set up the prefix for syslog messages */
  if (!_dbus_string_init (&log_prefix))
    goto oom;
  if (context->type && !strcmp (context->type, "system"))
    {
      if (!_dbus_string_append (&log_prefix, "[system] "))
        goto oom;
    }
  else if (context->type && !strcmp (context->type, "session"))
    {
      DBusCredentials *credentials;

      credentials = _dbus_credentials_new_from_current_process ();
      if (!credentials)
        goto oom;
      if (!_dbus_string_append (&log_prefix, "[session "))
        {
          _dbus_credentials_unref (credentials);
          goto oom;
        }
      if (!_dbus_credentials_to_string_append (credentials, &log_prefix))
        {
          _dbus_credentials_unref (credentials);
          goto oom;
        }
      if (!_dbus_string_append (&log_prefix, "] "))
        {
          _dbus_credentials_unref (credentials);
          goto oom;
        }
      _dbus_credentials_unref (credentials);
    }
  if (!_dbus_string_steal_data (&log_prefix, &context->log_prefix))
    goto oom;
  _dbus_string_free (&log_prefix);

  /* Build an array of auth mechanisms */

  auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
  len = _dbus_list_get_length (auth_mechanisms_list);

  if (len > 0)
    {
      int i;

      auth_mechanisms = dbus_new0 (char*, len + 1);
      if (auth_mechanisms == NULL)
        goto oom;

      i = 0;
      link = _dbus_list_get_first_link (auth_mechanisms_list);
      while (link != NULL)
        {
          auth_mechanisms[i] = _dbus_strdup (link->data);
          if (auth_mechanisms[i] == NULL)
            goto oom;
          link = _dbus_list_get_next_link (auth_mechanisms_list, link);
          i += 1;
        }
    }
BusDesktopFile*
bus_desktop_file_load (DBusString *filename,
		       DBusError  *error)
{
  DBusString str;
  BusDesktopFileParser parser;
  DBusStat sb;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  /* Clearly there's a race here, but it's just to make it unlikely
   * that we do something silly, we still handle doing it below.
   */
  if (!_dbus_stat (filename, &sb, error))
    return NULL;

  if (sb.size > _DBUS_ONE_KILOBYTE * 128)
    {
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "Desktop file size (%ld bytes) is too large", (long) sb.size);
      return NULL;
    }
  
  if (!_dbus_string_init (&str))
    return NULL;
  
  if (!_dbus_file_get_contents (&str, filename, error))
    {
      _dbus_string_free (&str);
      return NULL;
    }

  if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str)))
    {
      _dbus_string_free (&str);
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "invalid UTF-8");   
      return NULL;
    }
  
  parser.desktop_file = dbus_new0 (BusDesktopFile, 1);
  if (parser.desktop_file == NULL)
    {
      _dbus_string_free (&str);
      BUS_SET_OOM (error);
      return NULL;
    }
  
  parser.data = str;
  parser.line_num = 1;
  parser.pos = 0;
  parser.len = _dbus_string_get_length (&parser.data);
  parser.current_section = -1;

  while (parser.pos < parser.len)
    {
      if (_dbus_string_get_byte (&parser.data, parser.pos) == '[')
	{
	  if (!parse_section_start (&parser, error))
            {
              return NULL;
            }
	}
      else if (is_blank_line (&parser) ||
	       _dbus_string_get_byte (&parser.data, parser.pos) == '#')
	parse_comment_or_blank (&parser);
      else
	{
	  if (!parse_key_value (&parser, error))
            {
              return NULL;
            }
	}
    }

  _dbus_string_free (&parser.data);

  return parser.desktop_file;
}
예제 #4
0
static dbus_bool_t
_dbus_read_uuid_file_without_creating (const DBusString *filename,
                                       DBusGUID         *uuid,
                                       DBusError        *error)
{
  DBusString contents;
  DBusString decoded;
  int end;
  
  if (!_dbus_string_init (&contents))
    {
      _DBUS_SET_OOM (error);
      return FALSE;
    }

  if (!_dbus_string_init (&decoded))
    {
      _dbus_string_free (&contents);
      _DBUS_SET_OOM (error);
      return FALSE;
    }
  
  if (!_dbus_file_get_contents (&contents, filename, error))
    goto error;

  _dbus_string_chop_white (&contents);

  if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
    {
      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
                      "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
                      _dbus_string_get_const_data (filename),
                      DBUS_UUID_LENGTH_HEX,
                      _dbus_string_get_length (&contents));
      goto error;
    }

  if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
    {
      _DBUS_SET_OOM (error);
      goto error;
    }

  if (end == 0)
    {
      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
                      "UUID file '%s' contains invalid hex data",
                      _dbus_string_get_const_data (filename));
      goto error;
    }

  if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
    {
      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
                      "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
                      _dbus_string_get_const_data (filename),
                      _dbus_string_get_length (&decoded),
                      DBUS_UUID_LENGTH_BYTES);
      goto error;
    }

  _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);

  _dbus_string_free (&decoded);
  _dbus_string_free (&contents);

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  return TRUE;
  
 error:
  _DBUS_ASSERT_ERROR_IS_SET (error);
  _dbus_string_free (&contents);
  _dbus_string_free (&decoded);
  return FALSE;
}
BusConfigParser*
bus_config_load (const DBusString      *file,
                 dbus_bool_t            is_toplevel,
                 const BusConfigParser *parent,
                 DBusError             *error)

{
  xmlTextReader *reader;
  BusConfigParser *parser;
  DBusString dirname, data;
  DBusError tmp_error;
  int ret;
  
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  
  parser = NULL;
  reader = NULL;

  if (!_dbus_string_init (&dirname))
    {
      _DBUS_SET_OOM (error);
      return NULL;
    }

  if (!_dbus_string_init (&data))
    {
      _DBUS_SET_OOM (error);
      _dbus_string_free (&dirname);
      return NULL;
    }

  if (is_toplevel)
    {
      /* xmlMemSetup only fails if one of the functions is NULL */
    /*
      xmlMemSetup (dbus_free,
                   dbus_malloc,
                   dbus_realloc,
                   _dbus_strdup);
     */              
      xmlInitParser ();
      xmlSetGenericErrorFunc (NULL, xml_shut_up);
    }

  if (!_dbus_string_get_dirname (file, &dirname))
    {
      _DBUS_SET_OOM (error);
      goto failed;
    }
  
  parser = bus_config_parser_new (&dirname, is_toplevel, parent);
  if (parser == NULL)
    {
      _DBUS_SET_OOM (error);
      goto failed;
    }
  
  if (!_dbus_file_get_contents (&data, file, error))
    goto failed;

  reader = xmlReaderForMemory (_dbus_string_get_const_data (&data), 
                               _dbus_string_get_length (&data),
			       NULL, NULL, 0);
  if (reader == NULL)
    {
      _DBUS_SET_OOM (error);
      goto failed;
    }

  xmlTextReaderSetParserProp (reader, XML_PARSER_SUBST_ENTITIES, 1);

  dbus_error_init (&tmp_error);
  xmlTextReaderSetStructuredErrorHandler (reader, xml_text_reader_error, &tmp_error);

  while ((ret = xmlTextReaderRead (reader)) == 1)
    {
      int type;
      
      if (dbus_error_is_set (&tmp_error))
        goto reader_out;

      type = xmlTextReaderNodeType (reader);
      if (type == -1)
        {
          _DBUS_MAYBE_SET_OOM (&tmp_error);
          goto reader_out;
        }

      switch ((xmlReaderTypes) type) {
      case XML_READER_TYPE_ELEMENT:
	xml_text_start_element (parser, reader, &tmp_error);
	break;

      case XML_READER_TYPE_TEXT:
      case XML_READER_TYPE_CDATA:
	{
	  DBusString content;
	  const char *value;
#ifdef __SYMBIAN32__
	  value = (const char *) xmlTextReaderConstValue (reader);
#else
	  value = xmlTextReaderConstValue (reader);
#endif
	  if (value != NULL)
	    {
	      _dbus_string_init_const (&content, value);
	      bus_config_parser_content (parser, &content, &tmp_error);
	    }
          else
            _DBUS_MAYBE_SET_OOM (&tmp_error);
	  break;
	}

      case XML_READER_TYPE_DOCUMENT_TYPE:
	{
	  const char *name;
#ifdef __SYMBIAN32__
	  name = (const char *) xmlTextReaderConstName (reader);
#else
	  name = xmlTextReaderConstName (reader);
#endif
	  if (name != NULL)
	    bus_config_parser_check_doctype (parser, name, &tmp_error);
          else
            _DBUS_MAYBE_SET_OOM (&tmp_error);
	  break;
	}

      case XML_READER_TYPE_END_ELEMENT:
	{
	  const char *name;
#ifdef __SYMBIAN32__
	  name = (const char *) xmlTextReaderConstName (reader);
#else
	  name = xmlTextReaderConstName (reader);
#endif
	  if (name != NULL)
	    bus_config_parser_end_element (parser, name, &tmp_error);
          else
            _DBUS_MAYBE_SET_OOM (&tmp_error);
	  break;
	}

      case XML_READER_TYPE_DOCUMENT:
      case XML_READER_TYPE_DOCUMENT_FRAGMENT:
      case XML_READER_TYPE_PROCESSING_INSTRUCTION:
      case XML_READER_TYPE_COMMENT:
      case XML_READER_TYPE_ENTITY:
      case XML_READER_TYPE_NOTATION:
      case XML_READER_TYPE_WHITESPACE:
      case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
      case XML_READER_TYPE_END_ENTITY:
      case XML_READER_TYPE_XML_DECLARATION:
	/* nothing to do, just read on */
	break;

      case XML_READER_TYPE_NONE:
      case XML_READER_TYPE_ATTRIBUTE:
      case XML_READER_TYPE_ENTITY_REFERENCE:
	_dbus_assert_not_reached ("unexpected nodes in XML");
      }

      if (dbus_error_is_set (&tmp_error))
        goto reader_out;
    }

  if (ret == -1)
    _DBUS_MAYBE_SET_OOM (&tmp_error);

 reader_out:
  xmlFreeTextReader (reader);
  reader = NULL;
  if (dbus_error_is_set (&tmp_error))
    {
      dbus_move_error (&tmp_error, error);
      goto failed;
    }
  
  if (!bus_config_parser_finished (parser, error))
    goto failed;
  _dbus_string_free (&dirname);
  _dbus_string_free (&data);
  if (is_toplevel)
    xmlCleanupParser();
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  return parser;
  
 failed:
  _DBUS_ASSERT_ERROR_IS_SET (error);
  _dbus_string_free (&dirname);
  _dbus_string_free (&data);
  if (is_toplevel)
    xmlCleanupParser();
  if (parser)
    bus_config_parser_unref (parser);
  _dbus_assert (reader == NULL); /* must go to reader_out first */
  return NULL;
}
/**
 * Runs an "auth script" which is a script for testing the
 * authentication protocol. Scripts send and receive data, and then
 * include assertions about the state of both ends of the connection
 * after processing the data. A script succeeds if these assertions
 * hold.
 *
 * @param filename the file containing the script to run
 * @returns #TRUE if the script succeeds, #FALSE otherwise
 */
dbus_bool_t
_dbus_auth_script_run (const DBusString *filename)
{
  DBusString file;
  DBusError error = DBUS_ERROR_INIT;
  DBusString line;
  dbus_bool_t retval;
  int line_no;
  DBusAuth *auth;
  DBusString from_auth;
  DBusAuthState state;
  DBusString context;
  DBusString guid;
  
  retval = FALSE;
  auth = NULL;

  _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00");
  _dbus_string_init_const (&context, "org_freedesktop_test");
  
  if (!_dbus_string_init (&file))
    return FALSE;

  if (!_dbus_string_init (&line))
    {
      _dbus_string_free (&file);
      return FALSE;
    }

  if (!_dbus_string_init (&from_auth))
    {
      _dbus_string_free (&file);
      _dbus_string_free (&line);
      return FALSE;
    }

  if (!_dbus_file_get_contents (&file, filename, &error))    {
      _dbus_warn ("Getting contents of %s failed: %s\n",
                  _dbus_string_get_const_data (filename), error.message);
      dbus_error_free (&error);
      goto out;
    }

  state = DBUS_AUTH_STATE_NEED_DISCONNECT;
  line_no = 0;

 next_iteration:
  while (_dbus_string_pop_line (&file, &line))
    {      
      line_no += 1;

      /* _dbus_warn ("%s\n", _dbus_string_get_const_data (&line)); */
      
      _dbus_string_delete_leading_blanks (&line);

      if (auth != NULL)
        {
          while ((state = _dbus_auth_do_work (auth)) ==
                 DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
            {
              const DBusString *tmp;
              if (_dbus_auth_get_bytes_to_send (auth, &tmp))
                {
                  int count = _dbus_string_get_length (tmp);

                  if (_dbus_string_copy (tmp, 0, &from_auth,
                                         _dbus_string_get_length (&from_auth)))
                    _dbus_auth_bytes_sent (auth, count);
                }
            }
        }
      
      if (_dbus_string_get_length (&line) == 0)
        {
          /* empty line */
          goto next_iteration;
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "#"))
        {
          /* Ignore this comment */
          goto next_iteration;
        }
#ifdef DBUS_WIN
      else if (_dbus_string_starts_with_c_str (&line,
                                               "WIN_ONLY"))
        {
          /* Ignore this line */
          goto next_iteration;
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "UNIX_ONLY"))
        {
          /* skip this file */
          _dbus_warn ("skipping unix only auth script\n");
          retval = TRUE;
          goto out;
        }
#endif
#ifdef DBUS_UNIX
      else if (_dbus_string_starts_with_c_str (&line,
                                               "UNIX_ONLY"))
        {
          /* Ignore this line */
          goto next_iteration;
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "WIN_ONLY"))
        {
          /* skip this file */
          _dbus_warn ("skipping windows only auth script\n");
          retval = TRUE;
          goto out;
        }
#endif
      else if (_dbus_string_starts_with_c_str (&line,
                                               "CLIENT"))
        {
          DBusCredentials *creds;
          
          if (auth != NULL)
            {
              _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
              goto out;
            }

          auth = _dbus_auth_client_new ();
          if (auth == NULL)
            {
              _dbus_warn ("no memory to create DBusAuth\n");
              goto out;
            }

          /* test ref/unref */
          _dbus_auth_ref (auth);
          _dbus_auth_unref (auth);

          creds = _dbus_credentials_new_from_current_process ();
          if (creds == NULL)
            {
              _dbus_warn ("no memory for credentials\n");
              _dbus_auth_unref (auth);
              auth = NULL;
              goto out;
            }
              
          if (!_dbus_auth_set_credentials (auth, creds))
            {
              _dbus_warn ("no memory for setting credentials\n");
              _dbus_auth_unref (auth);
              auth = NULL;
              _dbus_credentials_unref (creds);
              goto out;
            }
          
          _dbus_credentials_unref (creds);
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "SERVER"))
        {
          DBusCredentials *creds;
          
          if (auth != NULL)
            {
              _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
              goto out;
            }

          auth = _dbus_auth_server_new (&guid);
          if (auth == NULL)
            {
              _dbus_warn ("no memory to create DBusAuth\n");
              goto out;
            }

          /* test ref/unref */
          _dbus_auth_ref (auth);
          _dbus_auth_unref (auth);

          creds = _dbus_credentials_new_from_current_process ();
          if (creds == NULL)
            {
              _dbus_warn ("no memory for credentials\n");
              _dbus_auth_unref (auth);
              auth = NULL;
              goto out;
            }
              
          if (!_dbus_auth_set_credentials (auth, creds))
            {
              _dbus_warn ("no memory for setting credentials\n");
              _dbus_auth_unref (auth);
              auth = NULL;
              _dbus_credentials_unref (creds);
              goto out;
            }
          
          _dbus_credentials_unref (creds);

          _dbus_auth_set_context (auth, &context);
        }
      else if (auth == NULL)
        {
          _dbus_warn ("must specify CLIENT or SERVER\n");
          goto out;

        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "NO_CREDENTIALS"))
        {
          auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET);
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "ROOT_CREDENTIALS"))
        {
          auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET);
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "SILLY_CREDENTIALS"))
        {
          auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET);
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "ALLOWED_MECHS"))
        {
          char **mechs;

          _dbus_string_delete_first_word (&line);
          mechs = split_string (&line);
          _dbus_auth_set_mechanisms (auth, (const char **) mechs);
          dbus_free_string_array (mechs);
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "SEND"))
        {
          DBusString to_send;
          
          _dbus_string_delete_first_word (&line);

          if (!_dbus_string_init (&to_send))
            {
              _dbus_warn ("no memory to allocate string\n");
              goto out;
            }

          if (!append_quoted_string (&to_send, &line))
            {
              _dbus_warn ("failed to append quoted string line %d\n",
                          line_no);
              _dbus_string_free (&to_send);
              goto out;
            }

          _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send));
          
          if (!_dbus_string_append (&to_send, "\r\n"))
            {
              _dbus_warn ("failed to append \r\n from line %d\n",
                          line_no);
              _dbus_string_free (&to_send);
              goto out;
            }

          /* Replace USERID_HEX with our username in hex */
          {
            int where;
            
            if (_dbus_string_find (&to_send, 0,
                                   "USERID_HEX", &where))
              {
                DBusString username;

                if (!_dbus_string_init (&username))
                  {
                    _dbus_warn ("no memory for userid\n");
                    _dbus_string_free (&to_send);
                    goto out;
                  }

                if (!_dbus_append_user_from_current_process (&username))
                  {
                    _dbus_warn ("no memory for userid\n");
                    _dbus_string_free (&username);
                    _dbus_string_free (&to_send);
                    goto out;
                  }

                _dbus_string_delete (&to_send, where, (int) strlen ("USERID_HEX"));
                
                if (!_dbus_string_hex_encode (&username, 0,
					      &to_send, where))
                  {
                    _dbus_warn ("no memory to subst USERID_HEX\n");
                    _dbus_string_free (&username);
                    _dbus_string_free (&to_send);
                    goto out;
                  }

                _dbus_string_free (&username);
              }
            else if (_dbus_string_find (&to_send, 0,
                                        "USERNAME_HEX", &where))
              {
                DBusString username;
                
                if (!_dbus_string_init (&username))
                  {
                    _dbus_warn ("no memory for username\n");
                    _dbus_string_free (&to_send);
                    goto out;
                  }

                if (!_dbus_append_user_from_current_process (&username))
                  {
                    _dbus_warn ("no memory for username\n");
                    _dbus_string_free (&username);
                    _dbus_string_free (&to_send);
                    goto out;
                  }

                _dbus_string_delete (&to_send, where, (int) strlen ("USERNAME_HEX"));
                
                if (!_dbus_string_hex_encode (&username, 0,
					      &to_send, where))
                  {
                    _dbus_warn ("no memory to subst USERNAME_HEX\n");
                    _dbus_string_free (&username);
                    _dbus_string_free (&to_send);
                    goto out;
                  }

                _dbus_string_free (&username);
              }
          }

          {
            DBusString *buffer;

            _dbus_auth_get_buffer (auth, &buffer);
            if (!_dbus_string_copy (&to_send, 0,
                                    buffer, _dbus_string_get_length (buffer)))
              {
                _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
                _dbus_string_free (&to_send);
                _dbus_auth_return_buffer (auth, buffer);
                goto out;
              }

            _dbus_auth_return_buffer (auth, buffer);
          }
          
          _dbus_string_free (&to_send);
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "EXPECT_STATE"))
        {
          DBusAuthState expected;
          
          _dbus_string_delete_first_word (&line);

          expected = auth_state_from_string (&line);
          if (expected < 0)
            {
              _dbus_warn ("bad auth state given to EXPECT_STATE\n");
              goto parse_failed;
            }

          if (expected != state)
            {
              _dbus_warn ("expected auth state %s but got %s on line %d\n",
                          auth_state_to_string (expected),
                          auth_state_to_string (state),
                          line_no);
              goto out;
            }
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "EXPECT_COMMAND"))
        {
          DBusString received;
          
          _dbus_string_delete_first_word (&line);

          if (!_dbus_string_init (&received))
            {
              _dbus_warn ("no mem to allocate string received\n");
              goto out;
            }

          if (!_dbus_string_pop_line (&from_auth, &received))
            {
              _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d\n",
                          _dbus_string_get_const_data (&line), line_no);
              _dbus_string_free (&received);
              goto out;
            }

          if (!same_first_word (&received, &line))
            {
              _dbus_warn ("line %d expected command '%s' and got '%s'\n",
                          line_no,
                          _dbus_string_get_const_data (&line),
                          _dbus_string_get_const_data (&received));
              _dbus_string_free (&received);
              goto out;
            }
          
          _dbus_string_free (&received);
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "EXPECT_UNUSED"))
        {
          DBusString expected;
          const DBusString *unused;
          
          _dbus_string_delete_first_word (&line);

          if (!_dbus_string_init (&expected))
            {
              _dbus_warn ("no mem to allocate string expected\n");
              goto out;
            }

          if (!append_quoted_string (&expected, &line))
            {
              _dbus_warn ("failed to append quoted string line %d\n",
                          line_no);
              _dbus_string_free (&expected);
              goto out;
            }

          _dbus_auth_get_unused_bytes (auth, &unused);
          
          if (_dbus_string_equal (&expected, unused))
            {
              _dbus_auth_delete_unused_bytes (auth);
              _dbus_string_free (&expected);
            }
          else
            {
              _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
                          _dbus_string_get_const_data (&expected),
                          _dbus_string_get_const_data (unused));
              _dbus_string_free (&expected);
              goto out;
            }
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "EXPECT_HAVE_NO_CREDENTIALS"))
        {
          DBusCredentials *authorized_identity;
          
          authorized_identity = _dbus_auth_get_identity (auth);
          if (!_dbus_credentials_are_anonymous (authorized_identity))
            {
              _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
              goto out;
            }
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "EXPECT_HAVE_SOME_CREDENTIALS"))
        {
          DBusCredentials *authorized_identity;
          
          authorized_identity = _dbus_auth_get_identity (auth);
          if (_dbus_credentials_are_anonymous (authorized_identity))
            {
              _dbus_warn ("Expected to have some credentials, but we don't\n");
              goto out;
            }
        }
      else if (_dbus_string_starts_with_c_str (&line,
                                               "EXPECT"))
        {
          DBusString expected;
          
          _dbus_string_delete_first_word (&line);

          if (!_dbus_string_init (&expected))
            {
              _dbus_warn ("no mem to allocate string expected\n");
              goto out;
            }

          if (!append_quoted_string (&expected, &line))
            {
              _dbus_warn ("failed to append quoted string line %d\n",
                          line_no);
              _dbus_string_free (&expected);
              goto out;
            }

          if (_dbus_string_equal_len (&expected, &from_auth,
                                      _dbus_string_get_length (&expected)))
            {
              _dbus_string_delete (&from_auth, 0,
                                   _dbus_string_get_length (&expected));
              _dbus_string_free (&expected);
            }
          else
            {
              _dbus_warn ("Expected exact string '%s' and have '%s'\n",
                          _dbus_string_get_const_data (&expected),
                          _dbus_string_get_const_data (&from_auth));
              _dbus_string_free (&expected);
              goto out;
            }
        }
      else
        goto parse_failed;

      goto next_iteration; /* skip parse_failed */
      
    parse_failed:
      {
        _dbus_warn ("couldn't process line %d \"%s\"\n",
                    line_no, _dbus_string_get_const_data (&line));
        goto out;
      }
    }

  if (auth == NULL)
    {
      _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER\n");
      goto out;
    }
  else if (state == DBUS_AUTH_STATE_AUTHENTICATED)
    {
      const DBusString *unused;

      _dbus_auth_get_unused_bytes (auth, &unused);

      if (_dbus_string_get_length (unused) > 0)
        {
          _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)\n");
          goto out;
        }
    }

  if (_dbus_string_get_length (&from_auth) > 0)
    {
      _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth\n");
      _dbus_warn ("Leftover data: %s\n", _dbus_string_get_const_data (&from_auth));
      goto out;
    }
  
  retval = TRUE;
  
 out:
  if (auth)
    _dbus_auth_unref (auth);

  _dbus_string_free (&file);
  _dbus_string_free (&line);
  _dbus_string_free (&from_auth);
  
  return retval;
}