diff options
| author | Havoc Pennington <hp@redhat.com> | 2007-06-10 04:54:45 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2007-06-10 04:54:45 +0000 | 
| commit | a789b7b38cb4f4540a41444cbd64bf7ada2d60d2 (patch) | |
| tree | db5164def7f5d19266bc4ebfb4ce740f269d79e2 | |
| parent | 7be5fd95cdccdca28937804f32ca8b1308887d09 (diff) | |
2007-06-09  Havoc Pennington  <hp@redhat.com>
	* dbus/dbus-string.c (_dbus_string_pop_line): fix this not to
	think an empty line is the end of the file.
	Also, fix some whitespace.
	* dbus/dbus-string-util.c: add more tests for
	_dbus_string_pop_line() revealing that it thinks an empty line is
	the end of the file, which broke dbus-auth-script.c so
	it didn't really run the scripts
	* dbus/dbus-auth.c: add ANONYMOUS mechanism
	* dbus/dbus-auth-script.c (_dbus_auth_script_run): fix to detect
	an empty/no-op auth script; add commands to check that we have or
	don't have the expected credentials
| -rw-r--r-- | ChangeLog | 17 | ||||
| -rw-r--r-- | dbus/dbus-auth-script.c | 41 | ||||
| -rw-r--r-- | dbus/dbus-auth.c | 138 | ||||
| -rw-r--r-- | dbus/dbus-string-util.c | 112 | ||||
| -rw-r--r-- | dbus/dbus-string.c | 36 | ||||
| -rw-r--r-- | test/data/auth/anonymous-client-successful.auth-script | 16 | ||||
| -rw-r--r-- | test/data/auth/anonymous-server-successful.auth-script | 13 | ||||
| -rw-r--r-- | test/data/auth/external-failed.auth-script | 5 | ||||
| -rw-r--r-- | test/data/auth/external-root.auth-script | 3 | ||||
| -rw-r--r-- | test/data/auth/external-silly.auth-script | 6 | ||||
| -rw-r--r-- | test/data/auth/external-successful.auth-script | 5 | 
11 files changed, 334 insertions, 58 deletions
@@ -1,5 +1,22 @@  2007-06-09  Havoc Pennington  <hp@redhat.com> +	* dbus/dbus-string.c (_dbus_string_pop_line): fix this not to +	think an empty line is the end of the file. +	Also, fix some whitespace. + +	* dbus/dbus-string-util.c: add more tests for +	_dbus_string_pop_line() revealing that it thinks an empty line is +	the end of the file, which broke dbus-auth-script.c so  +	it didn't really run the scripts + +	* dbus/dbus-auth.c: add ANONYMOUS mechanism + +	* dbus/dbus-auth-script.c (_dbus_auth_script_run): fix to detect +	an empty/no-op auth script; add commands to check that we have or +	don't have the expected credentials	 + +2007-06-09  Havoc Pennington  <hp@redhat.com> +  	* bus/policy.c (bus_policy_create_client_policy): gracefully  	continue if the connection has no unix user - just don't apply   	any unix user dependent rules. diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c index 5aa17d4b..dd864ca5 100644 --- a/dbus/dbus-auth-script.c +++ b/dbus/dbus-auth-script.c @@ -218,10 +218,8 @@ auth_set_unix_credentials(DBusAuth  *auth,    credentials = _dbus_credentials_new ();    if (credentials == NULL) -    { -      _dbus_warn ("no memory\n"); -      return; -    } +    _dbus_assert_not_reached ("no memory"); +    if (uid != DBUS_UID_UNSET)      _dbus_credentials_add_unix_uid (credentials, uid);    if (pid != DBUS_PID_UNSET) @@ -288,11 +286,14 @@ _dbus_auth_script_run (const DBusString *filename)    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) @@ -659,6 +660,30 @@ _dbus_auth_script_run (const DBusString *filename)              }          }        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_empty (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_empty (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; @@ -708,8 +733,12 @@ _dbus_auth_script_run (const DBusString *filename)        }      } -  if (auth != NULL && -      state == DBUS_AUTH_STATE_AUTHENTICATED) +  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; diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index b1d57a49..657f8d3d 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -424,6 +424,10 @@ shutdown_mech (DBusAuth *auth)      }  } +/* + * DBUS_COOKIE_SHA1 mechanism + */ +  /* Returns TRUE but with an empty string hash if the   * cookie_id isn't known. As with all this code   * TRUE just means we had enough memory. @@ -982,6 +986,10 @@ handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth)    _dbus_string_set_length (&auth->challenge, 0);  } +/* + * EXTERNAL mechanism + */ +  static dbus_bool_t  handle_server_data_external_mech (DBusAuth         *auth,                                    const DBusString *data) @@ -1051,7 +1059,7 @@ handle_server_data_external_mech (DBusAuth         *auth,          }      } -  if (_dbus_credentials_are_empty(auth->desired_identity)) +  if (_dbus_credentials_are_empty (auth->desired_identity))      {        _dbus_verbose ("%s: desired user %s is no good\n",                       DBUS_AUTH_NAME (auth), @@ -1142,13 +1150,120 @@ handle_client_shutdown_external_mech (DBusAuth *auth)  } +/* + * ANONYMOUS mechanism + */ + +static dbus_bool_t +handle_server_data_anonymous_mech (DBusAuth         *auth, +                                   const DBusString *data) +{   +  if (_dbus_string_get_length (data) > 0) +    { +      /* Client is allowed to send "trace" data, the only defined +       * meaning is that if it contains '@' it is an email address, +       * and otherwise it is anything else, and it's supposed to be +       * UTF-8 +       */ +      if (!_dbus_string_validate_utf8 (data, 0, _dbus_string_get_length (data))) +        { +          _dbus_verbose ("%s: Received invalid UTF-8 trace data from ANONYMOUS client\n", +                         DBUS_AUTH_NAME (auth)); + +          { +            DBusString plaintext; +            DBusString encoded; +            _dbus_string_init_const (&plaintext, "D-Bus " VERSION); +            _dbus_string_init (&encoded); +            _dbus_string_hex_encode (&plaintext, 0, +                                     &encoded, +                                     0); +              _dbus_verbose ("%s: try '%s'\n", +                             DBUS_AUTH_NAME (auth), _dbus_string_get_const_data (&encoded)); +          } +          return send_rejected (auth); +        } +       +      _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n", +                     DBUS_AUTH_NAME (auth), +                     _dbus_string_get_const_data (data)); +    } + +  /* We want to be anonymous (clear in case some other protocol got midway through I guess) */ +  _dbus_credentials_clear (auth->desired_identity); + +  /* Anonymous is always allowed */ +  if (!send_ok (auth)) +    return FALSE; + +  _dbus_verbose ("%s: authenticated client as anonymous\n", +                 DBUS_AUTH_NAME (auth)); + +  return TRUE; +} + +static void +handle_server_shutdown_anonymous_mech (DBusAuth *auth) +{ +   +} + +static dbus_bool_t +handle_client_initial_response_anonymous_mech (DBusAuth         *auth, +                                               DBusString       *response) +{ +  /* Our initial response is a "trace" string which must be valid UTF-8 +   * and must be an email address if it contains '@'. +   * We just send the dbus implementation info, like a user-agent or +   * something, because... why not. There's nothing guaranteed here +   * though, we could change it later. +   */ +  DBusString plaintext; + +  if (!_dbus_string_init (&plaintext)) +    return FALSE; + +  if (!_dbus_string_append (&plaintext, +                            "libdbus " VERSION)) +    goto failed; + +  if (!_dbus_string_hex_encode (&plaintext, 0, +				response, +				_dbus_string_get_length (response))) +    goto failed; + +  _dbus_string_free (&plaintext); +   +  return TRUE; + + failed: +  _dbus_string_free (&plaintext); +  return FALSE;   +} + +static dbus_bool_t +handle_client_data_anonymous_mech (DBusAuth         *auth, +                                  const DBusString *data) +{ +   +  return TRUE; +} + +static void +handle_client_shutdown_anonymous_mech (DBusAuth *auth) +{ +   +} +  /* Put mechanisms here in order of preference. - * What I eventually want to have is: + * Right now we have: + * + * - EXTERNAL checks socket credentials (or in the future, other info from the OS) + * - DBUS_COOKIE_SHA1 uses a cookie in the home directory, like xauth or ICE + * - ANONYMOUS checks nothing but doesn't auth the person as a user   * - *  - a mechanism that checks UNIX domain socket credentials - *  - a simple magic cookie mechanism like X11 or ICE - *  - mechanisms that chain to Cyrus SASL, so we can use anything it - *    offers such as Kerberos, X509, whatever. + * We might ideally add a mechanism to chain to Cyrus SASL so we can + * use its mechanisms as well.   *    */  static const DBusAuthMechanismHandler @@ -1169,6 +1284,14 @@ all_mechanisms[] = {      handle_client_data_cookie_sha1_mech,      NULL, NULL,      handle_client_shutdown_cookie_sha1_mech }, +  { "ANONYMOUS", +    handle_server_data_anonymous_mech, +    NULL, NULL, +    handle_server_shutdown_anonymous_mech, +    handle_client_initial_response_anonymous_mech, +    handle_client_data_anonymous_mech, +    NULL, NULL, +    handle_client_shutdown_anonymous_mech },      { NULL, NULL }  }; @@ -1881,7 +2004,8 @@ lookup_command_from_name (DBusString *command)  }  static void -goto_state (DBusAuth *auth, const DBusAuthStateData *state) +goto_state (DBusAuth *auth, +            const DBusAuthStateData *state)  {    _dbus_verbose ("%s: going from state %s to state %s\n",                   DBUS_AUTH_NAME (auth), diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c index 16a79340..27bd23a1 100644 --- a/dbus/dbus-string-util.c +++ b/dbus/dbus-string-util.c @@ -705,43 +705,93 @@ _dbus_string_test (void)    _dbus_string_free (&str);    {                                                                                            -  int found,found_len;                                                                         -  _dbus_string_init_const (&str, "012\r\n567\n90");                                            -                                                                                            -  if (!_dbus_string_find_eol(&str, 0, &found, &found_len) || found != 3 || found_len != 2)     -     _dbus_assert_not_reached ("Did not find '\\r\\n'");                                        -  if (found != 3 || found_len != 2)                                                            -     _dbus_assert_not_reached ("invalid return values");                                        -                                                                                            -  if (!_dbus_string_find_eol(&str, 5, &found, &found_len))                                     -    _dbus_assert_not_reached ("Did not find '\\n'");                                           -  if (found != 8 || found_len != 1)                                                            -    _dbus_assert_not_reached ("invalid return values");                                        -                                                                                            -  if (_dbus_string_find_eol(&str, 9, &found, &found_len))                                      -    _dbus_assert_not_reached ("Found not expected '\\n'");                                     -  else if (found != 11 || found_len != 0)                                                      -    _dbus_assert_not_reached ("invalid return values '\\n'");                                  -                                                                                            -  _dbus_string_free (&str);                                                                    -  }                                                                                                                                                                                     -   -  return TRUE; -} - -#endif /* DBUS_BUILD_TESTS */ - - - - - - +    int found, found_len;   +    _dbus_string_init_const (&str, "012\r\n567\n90"); +     +    if (!_dbus_string_find_eol (&str, 0, &found, &found_len) || found != 3 || found_len != 2) +      _dbus_assert_not_reached ("Did not find '\\r\\n'");                                        +    if (found != 3 || found_len != 2)                                                            +      _dbus_assert_not_reached ("invalid return values");                                        +     +    if (!_dbus_string_find_eol (&str, 5, &found, &found_len))                                     +      _dbus_assert_not_reached ("Did not find '\\n'");                                           +    if (found != 8 || found_len != 1)                                                            +      _dbus_assert_not_reached ("invalid return values");                                        +     +    if (_dbus_string_find_eol (&str, 9, &found, &found_len))                                      +      _dbus_assert_not_reached ("Found not expected '\\n'");                                     +    else if (found != 11 || found_len != 0)                                                      +      _dbus_assert_not_reached ("invalid return values '\\n'");                                  + +    found = -1; +    found_len = -1; +    _dbus_string_init_const (&str, ""); +    if (_dbus_string_find_eol (&str, 0, &found, &found_len)) +      _dbus_assert_not_reached ("found an eol in an empty string"); +    _dbus_assert (found == 0); +    _dbus_assert (found_len == 0); +     +    found = -1; +    found_len = -1; +    _dbus_string_init_const (&str, "foobar"); +    if (_dbus_string_find_eol (&str, 0, &found, &found_len)) +      _dbus_assert_not_reached ("found eol in string that lacks one"); +    _dbus_assert (found == 6); +    _dbus_assert (found_len == 0); + +    found = -1; +    found_len = -1; +    _dbus_string_init_const (&str, "foobar\n"); +    if (!_dbus_string_find_eol (&str, 0, &found, &found_len)) +      _dbus_assert_not_reached ("did not find eol in string that has one at end"); +    _dbus_assert (found == 6); +    _dbus_assert (found_len == 1); +  } +  { +    DBusString line; +#define FIRST_LINE "this is a line" +#define SECOND_LINE "this is a second line" +    /* third line is empty */ +#define THIRD_LINE "" +#define FOURTH_LINE "this is a fourth line" +     +    if (!_dbus_string_init (&str)) +      _dbus_assert_not_reached ("no memory"); +    if (!_dbus_string_append (&str, FIRST_LINE "\n" SECOND_LINE "\r\n" THIRD_LINE "\n" FOURTH_LINE)) +      _dbus_assert_not_reached ("no memory"); +     +    if (!_dbus_string_init (&line)) +      _dbus_assert_not_reached ("no memory"); +     +    if (!_dbus_string_pop_line (&str, &line)) +      _dbus_assert_not_reached ("failed to pop first line"); +    _dbus_assert (_dbus_string_equal_c_str (&line, FIRST_LINE)); +     +    if (!_dbus_string_pop_line (&str, &line)) +      _dbus_assert_not_reached ("failed to pop second line"); +    _dbus_assert (_dbus_string_equal_c_str (&line, SECOND_LINE)); +     +    if (!_dbus_string_pop_line (&str, &line)) +      _dbus_assert_not_reached ("failed to pop third line"); +    _dbus_assert (_dbus_string_equal_c_str (&line, THIRD_LINE)); +     +    if (!_dbus_string_pop_line (&str, &line)) +      _dbus_assert_not_reached ("failed to pop fourth line"); +    _dbus_assert (_dbus_string_equal_c_str (&line, FOURTH_LINE)); +     +    _dbus_string_free (&str); +    _dbus_string_free (&line); +  } +   +  return TRUE; +} +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index d83a3f39..6177a751 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -1804,9 +1804,9 @@ _dbus_string_find (const DBusString *str,   */  dbus_bool_t  _dbus_string_find_eol (const DBusString *str, -                   int               start, -                   int              *found, -                   int              *found_len) +                       int               start, +                       int              *found, +                       int              *found_len)  {    int i; @@ -1843,7 +1843,7 @@ _dbus_string_find_eol (const DBusString *str,            if (found_len)              *found_len = 1;            return TRUE; -        }       +        }        ++i;      } @@ -2093,17 +2093,33 @@ _dbus_string_pop_line (DBusString *source,    _dbus_string_set_length (dest, 0);    eol = 0; +  eol_len = 0;    if (!_dbus_string_find_eol (source, 0, &eol, &eol_len)) -      eol = _dbus_string_get_length (source); +    { +      _dbus_assert (eol == _dbus_string_get_length (source)); +      if (eol == 0) +        { +          /* If there's no newline and source has zero length, we're done */ +          return FALSE; +        } +      /* otherwise, the last line of the file has no eol characters */ +    } -  if (eol == 0) -    return FALSE; /* eof */ +  /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also +   * since find_eol returned TRUE +   */    if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0)) -	  return FALSE; - +    return FALSE; +      /* remove line ending */ -  return _dbus_string_set_length(dest, eol); +  if (!_dbus_string_set_length (dest, eol)) +    { +      _dbus_assert_not_reached ("out of memory when shortening a string"); +      return FALSE; +    } + +  return TRUE;  }  #ifdef DBUS_BUILD_TESTS diff --git a/test/data/auth/anonymous-client-successful.auth-script b/test/data/auth/anonymous-client-successful.auth-script new file mode 100644 index 00000000..9a1620bc --- /dev/null +++ b/test/data/auth/anonymous-client-successful.auth-script @@ -0,0 +1,16 @@ +## this tests that a client can login anonymously + +CLIENT + +## Reject whatever mechanism the client picks first +EXPECT_COMMAND AUTH +SEND 'REJECTED DBUS_TEST_NONEXISTENT_MECH1 ANONYMOUS DBUS_TEST_NONEXISTENT_MECH2' + +## And this time we get ANONYMOUS + +EXPECT_COMMAND AUTH +## of course real DBUS_COOKIE_SHA1 would not send this here... +SEND 'OK 1234deadbeef' + +EXPECT_COMMAND BEGIN +EXPECT_STATE AUTHENTICATED diff --git a/test/data/auth/anonymous-server-successful.auth-script b/test/data/auth/anonymous-server-successful.auth-script new file mode 100644 index 00000000..172ae9de --- /dev/null +++ b/test/data/auth/anonymous-server-successful.auth-script @@ -0,0 +1,13 @@ +## this tests the server side in a successful auth of type ANONYMOUS  + +SERVER +## verify that prior to doing anything, we haven't authed as anyone +EXPECT_HAVE_NO_CREDENTIALS +SEND 'AUTH ANONYMOUS 442d42757320312e312e31' +EXPECT_COMMAND OK +EXPECT_STATE WAITING_FOR_INPUT +SEND 'BEGIN' +EXPECT_STATE AUTHENTICATED +## verify that we are still anonymous +EXPECT_HAVE_NO_CREDENTIALS + diff --git a/test/data/auth/external-failed.auth-script b/test/data/auth/external-failed.auth-script index b11ee9c5..7c4e9001 100644 --- a/test/data/auth/external-failed.auth-script +++ b/test/data/auth/external-failed.auth-script @@ -2,7 +2,10 @@  SERVER  NO_CREDENTIALS +## verify that prior to doing anything, we haven't authed as anyone +EXPECT_HAVE_NO_CREDENTIALS  SEND 'AUTH EXTERNAL USERID_HEX'  EXPECT_COMMAND REJECTED  EXPECT_STATE WAITING_FOR_INPUT - +## verify that we still haven't authed as anyone +EXPECT_HAVE_NO_CREDENTIALS diff --git a/test/data/auth/external-root.auth-script b/test/data/auth/external-root.auth-script index b0189719..ca5b94ac 100644 --- a/test/data/auth/external-root.auth-script +++ b/test/data/auth/external-root.auth-script @@ -2,7 +2,8 @@  SERVER  ROOT_CREDENTIALS -SEND 'AUTH EXTERNAL USERID_HEX' +## 30 is ASCII '0' in hex +SEND 'AUTH EXTERNAL 30'  EXPECT_COMMAND OK  EXPECT_STATE WAITING_FOR_INPUT  SEND 'BEGIN' diff --git a/test/data/auth/external-silly.auth-script b/test/data/auth/external-silly.auth-script index 8ac0688a..4e18ee8d 100644 --- a/test/data/auth/external-silly.auth-script +++ b/test/data/auth/external-silly.auth-script @@ -1,8 +1,12 @@ -## this tests we can't auth with silly credentials +## this tests we can't auth if socket reports silly credentials but we ask for our own uid  SERVER +## verify that prior to doing anything, we haven't authed as anyone +EXPECT_HAVE_NO_CREDENTIALS  SILLY_CREDENTIALS  SEND 'AUTH EXTERNAL USERID_HEX'  EXPECT_COMMAND REJECTED  EXPECT_STATE WAITING_FOR_INPUT +## verify that we still haven't authed as anyone +EXPECT_HAVE_NO_CREDENTIALS diff --git a/test/data/auth/external-successful.auth-script b/test/data/auth/external-successful.auth-script index 128d3294..222938cc 100644 --- a/test/data/auth/external-successful.auth-script +++ b/test/data/auth/external-successful.auth-script @@ -1,9 +1,12 @@  ## this tests a successful auth of type EXTERNAL  SERVER +## verify that prior to doing anything, we haven't authed as anyone +EXPECT_HAVE_NO_CREDENTIALS  SEND 'AUTH EXTERNAL USERID_HEX'  EXPECT_COMMAND OK  EXPECT_STATE WAITING_FOR_INPUT  SEND 'BEGIN'  EXPECT_STATE AUTHENTICATED - +## verify that we now have some credentials +EXPECT_HAVE_SOME_CREDENTIALS  | 
