Home | History | Annotate | Download | only in dbus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-auth.c Authentication
      3  *
      4  * Copyright (C) 2002, 2003, 2004 Red Hat Inc.
      5  *
      6  * Licensed under the Academic Free License version 2.1
      7  *
      8  * This program is free software; you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation; either version 2 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #include <config.h>
     25 #include "dbus-auth.h"
     26 #include "dbus-string.h"
     27 #include "dbus-list.h"
     28 #include "dbus-internals.h"
     29 #include "dbus-keyring.h"
     30 #include "dbus-sha.h"
     31 #include "dbus-protocol.h"
     32 #include "dbus-credentials.h"
     33 
     34 /**
     35  * @defgroup DBusAuth Authentication
     36  * @ingroup  DBusInternals
     37  * @brief DBusAuth object
     38  *
     39  * DBusAuth manages the authentication negotiation when a connection
     40  * is first established, and also manage any encryption used over a
     41  * connection.
     42  *
     43  * @todo some SASL profiles require sending the empty string as a
     44  * challenge/response, but we don't currently allow that in our
     45  * protocol.
     46  *
     47  * @todo right now sometimes both ends will block waiting for input
     48  * from the other end, e.g. if there's an error during
     49  * DBUS_COOKIE_SHA1.
     50  *
     51  * @todo the cookie keyring needs to be cached globally not just
     52  * per-auth (which raises threadsafety issues too)
     53  *
     54  * @todo grep FIXME in dbus-auth.c
     55  */
     56 
     57 /**
     58  * @defgroup DBusAuthInternals Authentication implementation details
     59  * @ingroup  DBusInternals
     60  * @brief DBusAuth implementation details
     61  *
     62  * Private details of authentication code.
     63  *
     64  * @{
     65  */
     66 
     67 /**
     68  * This function appends an initial client response to the given string
     69  */
     70 typedef dbus_bool_t (* DBusInitialResponseFunction)  (DBusAuth         *auth,
     71                                                       DBusString       *response);
     72 
     73 /**
     74  * This function processes a block of data received from the peer.
     75  * i.e. handles a DATA command.
     76  */
     77 typedef dbus_bool_t (* DBusAuthDataFunction)     (DBusAuth         *auth,
     78                                                   const DBusString *data);
     79 
     80 /**
     81  * This function encodes a block of data from the peer.
     82  */
     83 typedef dbus_bool_t (* DBusAuthEncodeFunction)   (DBusAuth         *auth,
     84                                                   const DBusString *data,
     85                                                   DBusString       *encoded);
     86 
     87 /**
     88  * This function decodes a block of data from the peer.
     89  */
     90 typedef dbus_bool_t (* DBusAuthDecodeFunction)   (DBusAuth         *auth,
     91                                                   const DBusString *data,
     92                                                   DBusString       *decoded);
     93 
     94 /**
     95  * This function is called when the mechanism is abandoned.
     96  */
     97 typedef void        (* DBusAuthShutdownFunction) (DBusAuth       *auth);
     98 
     99 /**
    100  * Virtual table representing a particular auth mechanism.
    101  */
    102 typedef struct
    103 {
    104   const char *mechanism; /**< Name of the mechanism */
    105   DBusAuthDataFunction server_data_func; /**< Function on server side for DATA */
    106   DBusAuthEncodeFunction server_encode_func; /**< Function on server side to encode */
    107   DBusAuthDecodeFunction server_decode_func; /**< Function on server side to decode */
    108   DBusAuthShutdownFunction server_shutdown_func; /**< Function on server side to shut down */
    109   DBusInitialResponseFunction client_initial_response_func; /**< Function on client side to handle initial response */
    110   DBusAuthDataFunction client_data_func; /**< Function on client side for DATA */
    111   DBusAuthEncodeFunction client_encode_func; /**< Function on client side for encode */
    112   DBusAuthDecodeFunction client_decode_func; /**< Function on client side for decode */
    113   DBusAuthShutdownFunction client_shutdown_func; /**< Function on client side for shutdown */
    114 } DBusAuthMechanismHandler;
    115 
    116 /**
    117  * Enumeration for the known authentication commands.
    118  */
    119 typedef enum {
    120   DBUS_AUTH_COMMAND_AUTH,
    121   DBUS_AUTH_COMMAND_CANCEL,
    122   DBUS_AUTH_COMMAND_DATA,
    123   DBUS_AUTH_COMMAND_BEGIN,
    124   DBUS_AUTH_COMMAND_REJECTED,
    125   DBUS_AUTH_COMMAND_OK,
    126   DBUS_AUTH_COMMAND_ERROR,
    127   DBUS_AUTH_COMMAND_UNKNOWN,
    128   DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD,
    129   DBUS_AUTH_COMMAND_AGREE_UNIX_FD
    130 } DBusAuthCommand;
    131 
    132 /**
    133  * Auth state function, determines the reaction to incoming events for
    134  * a particular state. Returns whether we had enough memory to
    135  * complete the operation.
    136  */
    137 typedef dbus_bool_t (* DBusAuthStateFunction) (DBusAuth         *auth,
    138                                                DBusAuthCommand   command,
    139                                                const DBusString *args);
    140 
    141 /**
    142  * Information about a auth state.
    143  */
    144 typedef struct
    145 {
    146   const char *name;               /**< Name of the state */
    147   DBusAuthStateFunction handler;  /**< State function for this state */
    148 } DBusAuthStateData;
    149 
    150 /**
    151  * Internal members of DBusAuth.
    152  */
    153 struct DBusAuth
    154 {
    155   int refcount;           /**< reference count */
    156   const char *side;       /**< Client or server */
    157 
    158   DBusString incoming;    /**< Incoming data buffer */
    159   DBusString outgoing;    /**< Outgoing data buffer */
    160 
    161   const DBusAuthStateData *state;         /**< Current protocol state */
    162 
    163   const DBusAuthMechanismHandler *mech;   /**< Current auth mechanism */
    164 
    165   DBusString identity;                   /**< Current identity we're authorizing
    166                                           *   as.
    167                                           */
    168 
    169   DBusCredentials *credentials;          /**< Credentials read from socket
    170                                           */
    171 
    172   DBusCredentials *authorized_identity; /**< Credentials that are authorized */
    173 
    174   DBusCredentials *desired_identity;    /**< Identity client has requested */
    175 
    176   DBusString context;               /**< Cookie scope */
    177   DBusKeyring *keyring;             /**< Keyring for cookie mechanism. */
    178   int cookie_id;                    /**< ID of cookie to use */
    179   DBusString challenge;             /**< Challenge sent to client */
    180 
    181   char **allowed_mechs;             /**< Mechanisms we're allowed to use,
    182                                      * or #NULL if we can use any
    183                                      */
    184 
    185   unsigned int needed_memory : 1;   /**< We needed memory to continue since last
    186                                      * successful getting something done
    187                                      */
    188   unsigned int already_got_mechanisms : 1;       /**< Client already got mech list */
    189   unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */
    190   unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */
    191 
    192   unsigned int unix_fd_possible : 1;  /**< This side could do unix fd passing */
    193   unsigned int unix_fd_negotiated : 1; /**< Unix fd was successfully negotiated */
    194 };
    195 
    196 /**
    197  * "Subclass" of DBusAuth for client side
    198  */
    199 typedef struct
    200 {
    201   DBusAuth base;    /**< Parent class */
    202 
    203   DBusList *mechs_to_try; /**< Mechanisms we got from the server that we're going to try using */
    204 
    205   DBusString guid_from_server; /**< GUID received from server */
    206 
    207 } DBusAuthClient;
    208 
    209 /**
    210  * "Subclass" of DBusAuth for server side.
    211  */
    212 typedef struct
    213 {
    214   DBusAuth base;    /**< Parent class */
    215 
    216   int failures;     /**< Number of times client has been rejected */
    217   int max_failures; /**< Number of times we reject before disconnect */
    218 
    219   DBusString guid;  /**< Our globally unique ID in hex encoding */
    220 
    221 } DBusAuthServer;
    222 
    223 static void        goto_state                (DBusAuth                       *auth,
    224                                               const DBusAuthStateData        *new_state);
    225 static dbus_bool_t send_auth                 (DBusAuth *auth,
    226                                               const DBusAuthMechanismHandler *mech);
    227 static dbus_bool_t send_data                 (DBusAuth *auth,
    228                                               DBusString *data);
    229 static dbus_bool_t send_rejected             (DBusAuth *auth);
    230 static dbus_bool_t send_error                (DBusAuth *auth,
    231                                               const char *message);
    232 static dbus_bool_t send_ok                   (DBusAuth *auth);
    233 static dbus_bool_t send_begin                (DBusAuth *auth);
    234 static dbus_bool_t send_cancel               (DBusAuth *auth);
    235 static dbus_bool_t send_negotiate_unix_fd    (DBusAuth *auth);
    236 static dbus_bool_t send_agree_unix_fd        (DBusAuth *auth);
    237 
    238 /**
    239  * Client states
    240  */
    241 
    242 static dbus_bool_t handle_server_state_waiting_for_auth  (DBusAuth         *auth,
    243                                                           DBusAuthCommand   command,
    244                                                           const DBusString *args);
    245 static dbus_bool_t handle_server_state_waiting_for_data  (DBusAuth         *auth,
    246                                                           DBusAuthCommand   command,
    247                                                           const DBusString *args);
    248 static dbus_bool_t handle_server_state_waiting_for_begin (DBusAuth         *auth,
    249                                                           DBusAuthCommand   command,
    250                                                           const DBusString *args);
    251 
    252 static const DBusAuthStateData server_state_waiting_for_auth = {
    253   "WaitingForAuth", handle_server_state_waiting_for_auth
    254 };
    255 static const DBusAuthStateData server_state_waiting_for_data = {
    256   "WaitingForData", handle_server_state_waiting_for_data
    257 };
    258 static const DBusAuthStateData server_state_waiting_for_begin = {
    259   "WaitingForBegin", handle_server_state_waiting_for_begin
    260 };
    261 
    262 /**
    263  * Client states
    264  */
    265 
    266 static dbus_bool_t handle_client_state_waiting_for_data   (DBusAuth         *auth,
    267                                                            DBusAuthCommand   command,
    268                                                            const DBusString *args);
    269 static dbus_bool_t handle_client_state_waiting_for_ok     (DBusAuth         *auth,
    270                                                            DBusAuthCommand   command,
    271                                                            const DBusString *args);
    272 static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth         *auth,
    273                                                            DBusAuthCommand   command,
    274                                                            const DBusString *args);
    275 static dbus_bool_t handle_client_state_waiting_for_agree_unix_fd (DBusAuth         *auth,
    276                                                            DBusAuthCommand   command,
    277                                                            const DBusString *args);
    278 
    279 static const DBusAuthStateData client_state_need_send_auth = {
    280   "NeedSendAuth", NULL
    281 };
    282 static const DBusAuthStateData client_state_waiting_for_data = {
    283   "WaitingForData", handle_client_state_waiting_for_data
    284 };
    285 static const DBusAuthStateData client_state_waiting_for_ok = {
    286   "WaitingForOK", handle_client_state_waiting_for_ok
    287 };
    288 static const DBusAuthStateData client_state_waiting_for_reject = {
    289   "WaitingForReject", handle_client_state_waiting_for_reject
    290 };
    291 static const DBusAuthStateData client_state_waiting_for_agree_unix_fd = {
    292   "WaitingForAgreeUnixFD", handle_client_state_waiting_for_agree_unix_fd
    293 };
    294 
    295 /**
    296  * Common terminal states.  Terminal states have handler == NULL.
    297  */
    298 
    299 static const DBusAuthStateData common_state_authenticated = {
    300   "Authenticated",  NULL
    301 };
    302 
    303 static const DBusAuthStateData common_state_need_disconnect = {
    304   "NeedDisconnect",  NULL
    305 };
    306 
    307 static const char auth_side_client[] = "client";
    308 static const char auth_side_server[] = "server";
    309 /**
    310  * @param auth the auth conversation
    311  * @returns #TRUE if the conversation is the server side
    312  */
    313 #define DBUS_AUTH_IS_SERVER(auth) ((auth)->side == auth_side_server)
    314 /**
    315  * @param auth the auth conversation
    316  * @returns #TRUE if the conversation is the client side
    317  */
    318 #define DBUS_AUTH_IS_CLIENT(auth) ((auth)->side == auth_side_client)
    319 /**
    320  * @param auth the auth conversation
    321  * @returns auth cast to DBusAuthClient
    322  */
    323 #define DBUS_AUTH_CLIENT(auth)    ((DBusAuthClient*)(auth))
    324 /**
    325  * @param auth the auth conversation
    326  * @returns auth cast to DBusAuthServer
    327  */
    328 #define DBUS_AUTH_SERVER(auth)    ((DBusAuthServer*)(auth))
    329 
    330 /**
    331  * The name of the auth ("client" or "server")
    332  * @param auth the auth conversation
    333  * @returns a string
    334  */
    335 #define DBUS_AUTH_NAME(auth)      ((auth)->side)
    336 
    337 static DBusAuth*
    338 _dbus_auth_new (int size)
    339 {
    340   DBusAuth *auth;
    341 
    342   auth = dbus_malloc0 (size);
    343   if (auth == NULL)
    344     return NULL;
    345 
    346   auth->refcount = 1;
    347 
    348   auth->keyring = NULL;
    349   auth->cookie_id = -1;
    350 
    351   /* note that we don't use the max string length feature,
    352    * because you can't use that feature if you're going to
    353    * try to recover from out-of-memory (it creates
    354    * what looks like unrecoverable inability to alloc
    355    * more space in the string). But we do handle
    356    * overlong buffers in _dbus_auth_do_work().
    357    */
    358 
    359   if (!_dbus_string_init (&auth->incoming))
    360     goto enomem_0;
    361 
    362   if (!_dbus_string_init (&auth->outgoing))
    363     goto enomem_1;
    364 
    365   if (!_dbus_string_init (&auth->identity))
    366     goto enomem_2;
    367 
    368   if (!_dbus_string_init (&auth->context))
    369     goto enomem_3;
    370 
    371   if (!_dbus_string_init (&auth->challenge))
    372     goto enomem_4;
    373 
    374   /* default context if none is specified */
    375   if (!_dbus_string_append (&auth->context, "org_freedesktop_general"))
    376     goto enomem_5;
    377 
    378   auth->credentials = _dbus_credentials_new ();
    379   if (auth->credentials == NULL)
    380     goto enomem_6;
    381 
    382   auth->authorized_identity = _dbus_credentials_new ();
    383   if (auth->authorized_identity == NULL)
    384     goto enomem_7;
    385 
    386   auth->desired_identity = _dbus_credentials_new ();
    387   if (auth->desired_identity == NULL)
    388     goto enomem_8;
    389 
    390   return auth;
    391 
    392 #if 0
    393  enomem_9:
    394   _dbus_credentials_unref (auth->desired_identity);
    395 #endif
    396  enomem_8:
    397   _dbus_credentials_unref (auth->authorized_identity);
    398  enomem_7:
    399   _dbus_credentials_unref (auth->credentials);
    400  enomem_6:
    401  /* last alloc was an append to context, which is freed already below */ ;
    402  enomem_5:
    403   _dbus_string_free (&auth->challenge);
    404  enomem_4:
    405   _dbus_string_free (&auth->context);
    406  enomem_3:
    407   _dbus_string_free (&auth->identity);
    408  enomem_2:
    409   _dbus_string_free (&auth->outgoing);
    410  enomem_1:
    411   _dbus_string_free (&auth->incoming);
    412  enomem_0:
    413   dbus_free (auth);
    414   return NULL;
    415 }
    416 
    417 static void
    418 shutdown_mech (DBusAuth *auth)
    419 {
    420   /* Cancel any auth */
    421   auth->already_asked_for_initial_response = FALSE;
    422   _dbus_string_set_length (&auth->identity, 0);
    423 
    424   _dbus_credentials_clear (auth->authorized_identity);
    425   _dbus_credentials_clear (auth->desired_identity);
    426 
    427   if (auth->mech != NULL)
    428     {
    429       _dbus_verbose ("%s: Shutting down mechanism %s\n",
    430                      DBUS_AUTH_NAME (auth), auth->mech->mechanism);
    431 
    432       if (DBUS_AUTH_IS_CLIENT (auth))
    433         (* auth->mech->client_shutdown_func) (auth);
    434       else
    435         (* auth->mech->server_shutdown_func) (auth);
    436 
    437       auth->mech = NULL;
    438     }
    439 }
    440 
    441 /*
    442  * DBUS_COOKIE_SHA1 mechanism
    443  */
    444 
    445 /* Returns TRUE but with an empty string hash if the
    446  * cookie_id isn't known. As with all this code
    447  * TRUE just means we had enough memory.
    448  */
    449 static dbus_bool_t
    450 sha1_compute_hash (DBusAuth         *auth,
    451                    int               cookie_id,
    452                    const DBusString *server_challenge,
    453                    const DBusString *client_challenge,
    454                    DBusString       *hash)
    455 {
    456   DBusString cookie;
    457   DBusString to_hash;
    458   dbus_bool_t retval;
    459 
    460   _dbus_assert (auth->keyring != NULL);
    461 
    462   retval = FALSE;
    463 
    464   if (!_dbus_string_init (&cookie))
    465     return FALSE;
    466 
    467   if (!_dbus_keyring_get_hex_key (auth->keyring, cookie_id,
    468                                   &cookie))
    469     goto out_0;
    470 
    471   if (_dbus_string_get_length (&cookie) == 0)
    472     {
    473       retval = TRUE;
    474       goto out_0;
    475     }
    476 
    477   if (!_dbus_string_init (&to_hash))
    478     goto out_0;
    479 
    480   if (!_dbus_string_copy (server_challenge, 0,
    481                           &to_hash, _dbus_string_get_length (&to_hash)))
    482     goto out_1;
    483 
    484   if (!_dbus_string_append (&to_hash, ":"))
    485     goto out_1;
    486 
    487   if (!_dbus_string_copy (client_challenge, 0,
    488                           &to_hash, _dbus_string_get_length (&to_hash)))
    489     goto out_1;
    490 
    491   if (!_dbus_string_append (&to_hash, ":"))
    492     goto out_1;
    493 
    494   if (!_dbus_string_copy (&cookie, 0,
    495                           &to_hash, _dbus_string_get_length (&to_hash)))
    496     goto out_1;
    497 
    498   if (!_dbus_sha_compute (&to_hash, hash))
    499     goto out_1;
    500 
    501   retval = TRUE;
    502 
    503  out_1:
    504   _dbus_string_zero (&to_hash);
    505   _dbus_string_free (&to_hash);
    506  out_0:
    507   _dbus_string_zero (&cookie);
    508   _dbus_string_free (&cookie);
    509   return retval;
    510 }
    511 
    512 /** http://www.ietf.org/rfc/rfc2831.txt suggests at least 64 bits of
    513  * entropy, we use 128. This is the number of bytes in the random
    514  * challenge.
    515  */
    516 #define N_CHALLENGE_BYTES (128/8)
    517 
    518 static dbus_bool_t
    519 sha1_handle_first_client_response (DBusAuth         *auth,
    520                                    const DBusString *data)
    521 {
    522   /* We haven't sent a challenge yet, we're expecting a desired
    523    * username from the client.
    524    */
    525   DBusString tmp;
    526   DBusString tmp2;
    527   dbus_bool_t retval;
    528   DBusError error;
    529 
    530   retval = FALSE;
    531 
    532   _dbus_string_set_length (&auth->challenge, 0);
    533 
    534   if (_dbus_string_get_length (data) > 0)
    535     {
    536       if (_dbus_string_get_length (&auth->identity) > 0)
    537         {
    538           /* Tried to send two auth identities, wtf */
    539           _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
    540                          DBUS_AUTH_NAME (auth));
    541           return send_rejected (auth);
    542         }
    543       else
    544         {
    545           /* this is our auth identity */
    546           if (!_dbus_string_copy (data, 0, &auth->identity, 0))
    547             return FALSE;
    548         }
    549     }
    550 
    551   if (!_dbus_credentials_add_from_user (auth->desired_identity, data))
    552     {
    553       _dbus_verbose ("%s: Did not get a valid username from client\n",
    554                      DBUS_AUTH_NAME (auth));
    555       return send_rejected (auth);
    556     }
    557 
    558   if (!_dbus_string_init (&tmp))
    559     return FALSE;
    560 
    561   if (!_dbus_string_init (&tmp2))
    562     {
    563       _dbus_string_free (&tmp);
    564       return FALSE;
    565     }
    566 
    567   /* we cache the keyring for speed, so here we drop it if it's the
    568    * wrong one. FIXME caching the keyring here is useless since we use
    569    * a different DBusAuth for every connection.
    570    */
    571   if (auth->keyring &&
    572       !_dbus_keyring_is_for_credentials (auth->keyring,
    573                                          auth->desired_identity))
    574     {
    575       _dbus_keyring_unref (auth->keyring);
    576       auth->keyring = NULL;
    577     }
    578 
    579   if (auth->keyring == NULL)
    580     {
    581       dbus_error_init (&error);
    582       auth->keyring = _dbus_keyring_new_for_credentials (auth->desired_identity,
    583                                                          &auth->context,
    584                                                          &error);
    585 
    586       if (auth->keyring == NULL)
    587         {
    588           if (dbus_error_has_name (&error,
    589                                    DBUS_ERROR_NO_MEMORY))
    590             {
    591               dbus_error_free (&error);
    592               goto out;
    593             }
    594           else
    595             {
    596               _DBUS_ASSERT_ERROR_CONTENT_IS_SET (&error);
    597               _dbus_verbose ("%s: Error loading keyring: %s\n",
    598                              DBUS_AUTH_NAME (auth), error.message);
    599               if (send_rejected (auth))
    600                 retval = TRUE; /* retval is only about mem */
    601               dbus_error_free (&error);
    602               goto out;
    603             }
    604         }
    605       else
    606         {
    607           _dbus_assert (!dbus_error_is_set (&error));
    608         }
    609     }
    610 
    611   _dbus_assert (auth->keyring != NULL);
    612 
    613   dbus_error_init (&error);
    614   auth->cookie_id = _dbus_keyring_get_best_key (auth->keyring, &error);
    615   if (auth->cookie_id < 0)
    616     {
    617       _DBUS_ASSERT_ERROR_CONTENT_IS_SET (&error);
    618       _dbus_verbose ("%s: Could not get a cookie ID to send to client: %s\n",
    619                      DBUS_AUTH_NAME (auth), error.message);
    620       if (send_rejected (auth))
    621         retval = TRUE;
    622       dbus_error_free (&error);
    623       goto out;
    624     }
    625   else
    626     {
    627       _dbus_assert (!dbus_error_is_set (&error));
    628     }
    629 
    630   if (!_dbus_string_copy (&auth->context, 0,
    631                           &tmp2, _dbus_string_get_length (&tmp2)))
    632     goto out;
    633 
    634   if (!_dbus_string_append (&tmp2, " "))
    635     goto out;
    636 
    637   if (!_dbus_string_append_int (&tmp2, auth->cookie_id))
    638     goto out;
    639 
    640   if (!_dbus_string_append (&tmp2, " "))
    641     goto out;
    642 
    643   if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES))
    644     goto out;
    645 
    646   _dbus_string_set_length (&auth->challenge, 0);
    647   if (!_dbus_string_hex_encode (&tmp, 0, &auth->challenge, 0))
    648     goto out;
    649 
    650   if (!_dbus_string_hex_encode (&tmp, 0, &tmp2,
    651                                 _dbus_string_get_length (&tmp2)))
    652     goto out;
    653 
    654   if (!send_data (auth, &tmp2))
    655     goto out;
    656 
    657   goto_state (auth, &server_state_waiting_for_data);
    658   retval = TRUE;
    659 
    660  out:
    661   _dbus_string_zero (&tmp);
    662   _dbus_string_free (&tmp);
    663   _dbus_string_zero (&tmp2);
    664   _dbus_string_free (&tmp2);
    665 
    666   return retval;
    667 }
    668 
    669 static dbus_bool_t
    670 sha1_handle_second_client_response (DBusAuth         *auth,
    671                                     const DBusString *data)
    672 {
    673   /* We are expecting a response which is the hex-encoded client
    674    * challenge, space, then SHA-1 hash of the concatenation of our
    675    * challenge, ":", client challenge, ":", secret key, all
    676    * hex-encoded.
    677    */
    678   int i;
    679   DBusString client_challenge;
    680   DBusString client_hash;
    681   dbus_bool_t retval;
    682   DBusString correct_hash;
    683 
    684   retval = FALSE;
    685 
    686   if (!_dbus_string_find_blank (data, 0, &i))
    687     {
    688       _dbus_verbose ("%s: no space separator in client response\n",
    689                      DBUS_AUTH_NAME (auth));
    690       return send_rejected (auth);
    691     }
    692 
    693   if (!_dbus_string_init (&client_challenge))
    694     goto out_0;
    695 
    696   if (!_dbus_string_init (&client_hash))
    697     goto out_1;
    698 
    699   if (!_dbus_string_copy_len (data, 0, i, &client_challenge,
    700                               0))
    701     goto out_2;
    702 
    703   _dbus_string_skip_blank (data, i, &i);
    704 
    705   if (!_dbus_string_copy_len (data, i,
    706                               _dbus_string_get_length (data) - i,
    707                               &client_hash,
    708                               0))
    709     goto out_2;
    710 
    711   if (_dbus_string_get_length (&client_challenge) == 0 ||
    712       _dbus_string_get_length (&client_hash) == 0)
    713     {
    714       _dbus_verbose ("%s: zero-length client challenge or hash\n",
    715                      DBUS_AUTH_NAME (auth));
    716       if (send_rejected (auth))
    717         retval = TRUE;
    718       goto out_2;
    719     }
    720 
    721   if (!_dbus_string_init (&correct_hash))
    722     goto out_2;
    723 
    724   if (!sha1_compute_hash (auth, auth->cookie_id,
    725                           &auth->challenge,
    726                           &client_challenge,
    727                           &correct_hash))
    728     goto out_3;
    729 
    730   /* if cookie_id was invalid, then we get an empty hash */
    731   if (_dbus_string_get_length (&correct_hash) == 0)
    732     {
    733       if (send_rejected (auth))
    734         retval = TRUE;
    735       goto out_3;
    736     }
    737 
    738   if (!_dbus_string_equal (&client_hash, &correct_hash))
    739     {
    740       if (send_rejected (auth))
    741         retval = TRUE;
    742       goto out_3;
    743     }
    744 
    745   if (!_dbus_credentials_add_credentials (auth->authorized_identity,
    746                                           auth->desired_identity))
    747     goto out_3;
    748 
    749   /* Copy process ID from the socket credentials if it's there
    750    */
    751   if (!_dbus_credentials_add_credential (auth->authorized_identity,
    752                                          DBUS_CREDENTIAL_UNIX_PROCESS_ID,
    753                                          auth->credentials))
    754     goto out_3;
    755 
    756   if (!send_ok (auth))
    757     goto out_3;
    758 
    759   _dbus_verbose ("%s: authenticated client using DBUS_COOKIE_SHA1\n",
    760                  DBUS_AUTH_NAME (auth));
    761 
    762   retval = TRUE;
    763 
    764  out_3:
    765   _dbus_string_zero (&correct_hash);
    766   _dbus_string_free (&correct_hash);
    767  out_2:
    768   _dbus_string_zero (&client_hash);
    769   _dbus_string_free (&client_hash);
    770  out_1:
    771   _dbus_string_free (&client_challenge);
    772  out_0:
    773   return retval;
    774 }
    775 
    776 static dbus_bool_t
    777 handle_server_data_cookie_sha1_mech (DBusAuth         *auth,
    778                                      const DBusString *data)
    779 {
    780   if (auth->cookie_id < 0)
    781     return sha1_handle_first_client_response (auth, data);
    782   else
    783     return sha1_handle_second_client_response (auth, data);
    784 }
    785 
    786 static void
    787 handle_server_shutdown_cookie_sha1_mech (DBusAuth *auth)
    788 {
    789   auth->cookie_id = -1;
    790   _dbus_string_set_length (&auth->challenge, 0);
    791 }
    792 
    793 static dbus_bool_t
    794 handle_client_initial_response_cookie_sha1_mech (DBusAuth   *auth,
    795                                                  DBusString *response)
    796 {
    797   DBusString username;
    798   dbus_bool_t retval;
    799 
    800   retval = FALSE;
    801 
    802   if (!_dbus_string_init (&username))
    803     return FALSE;
    804 
    805   if (!_dbus_append_user_from_current_process (&username))
    806     goto out_0;
    807 
    808   if (!_dbus_string_hex_encode (&username, 0,
    809 				response,
    810 				_dbus_string_get_length (response)))
    811     goto out_0;
    812 
    813   retval = TRUE;
    814 
    815  out_0:
    816   _dbus_string_free (&username);
    817 
    818   return retval;
    819 }
    820 
    821 static dbus_bool_t
    822 handle_client_data_cookie_sha1_mech (DBusAuth         *auth,
    823                                      const DBusString *data)
    824 {
    825   /* The data we get from the server should be the cookie context
    826    * name, the cookie ID, and the server challenge, separated by
    827    * spaces. We send back our challenge string and the correct hash.
    828    */
    829   dbus_bool_t retval;
    830   DBusString context;
    831   DBusString cookie_id_str;
    832   DBusString server_challenge;
    833   DBusString client_challenge;
    834   DBusString correct_hash;
    835   DBusString tmp;
    836   int i, j;
    837   long val;
    838 
    839   retval = FALSE;
    840 
    841   if (!_dbus_string_find_blank (data, 0, &i))
    842     {
    843       if (send_error (auth,
    844                       "Server did not send context/ID/challenge properly"))
    845         retval = TRUE;
    846       goto out_0;
    847     }
    848 
    849   if (!_dbus_string_init (&context))
    850     goto out_0;
    851 
    852   if (!_dbus_string_copy_len (data, 0, i,
    853                               &context, 0))
    854     goto out_1;
    855 
    856   _dbus_string_skip_blank (data, i, &i);
    857   if (!_dbus_string_find_blank (data, i, &j))
    858     {
    859       if (send_error (auth,
    860                       "Server did not send context/ID/challenge properly"))
    861         retval = TRUE;
    862       goto out_1;
    863     }
    864 
    865   if (!_dbus_string_init (&cookie_id_str))
    866     goto out_1;
    867 
    868   if (!_dbus_string_copy_len (data, i, j - i,
    869                               &cookie_id_str, 0))
    870     goto out_2;
    871 
    872   if (!_dbus_string_init (&server_challenge))
    873     goto out_2;
    874 
    875   i = j;
    876   _dbus_string_skip_blank (data, i, &i);
    877   j = _dbus_string_get_length (data);
    878 
    879   if (!_dbus_string_copy_len (data, i, j - i,
    880                               &server_challenge, 0))
    881     goto out_3;
    882 
    883   if (!_dbus_keyring_validate_context (&context))
    884     {
    885       if (send_error (auth, "Server sent invalid cookie context"))
    886         retval = TRUE;
    887       goto out_3;
    888     }
    889 
    890   if (!_dbus_string_parse_int (&cookie_id_str, 0, &val, NULL))
    891     {
    892       if (send_error (auth, "Could not parse cookie ID as an integer"))
    893         retval = TRUE;
    894       goto out_3;
    895     }
    896 
    897   if (_dbus_string_get_length (&server_challenge) == 0)
    898     {
    899       if (send_error (auth, "Empty server challenge string"))
    900         retval = TRUE;
    901       goto out_3;
    902     }
    903 
    904   if (auth->keyring == NULL)
    905     {
    906       DBusError error;
    907 
    908       dbus_error_init (&error);
    909       auth->keyring = _dbus_keyring_new_for_credentials (NULL,
    910                                                          &context,
    911                                                          &error);
    912 
    913       if (auth->keyring == NULL)
    914         {
    915           if (dbus_error_has_name (&error,
    916                                    DBUS_ERROR_NO_MEMORY))
    917             {
    918               dbus_error_free (&error);
    919               goto out_3;
    920             }
    921           else
    922             {
    923               _DBUS_ASSERT_ERROR_CONTENT_IS_SET (&error);
    924 
    925               _dbus_verbose ("%s: Error loading keyring: %s\n",
    926                              DBUS_AUTH_NAME (auth), error.message);
    927 
    928               if (send_error (auth, "Could not load cookie file"))
    929                 retval = TRUE; /* retval is only about mem */
    930 
    931               dbus_error_free (&error);
    932               goto out_3;
    933             }
    934         }
    935       else
    936         {
    937           _dbus_assert (!dbus_error_is_set (&error));
    938         }
    939     }
    940 
    941   _dbus_assert (auth->keyring != NULL);
    942 
    943   if (!_dbus_string_init (&tmp))
    944     goto out_3;
    945 
    946   if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES))
    947     goto out_4;
    948 
    949   if (!_dbus_string_init (&client_challenge))
    950     goto out_4;
    951 
    952   if (!_dbus_string_hex_encode (&tmp, 0, &client_challenge, 0))
    953     goto out_5;
    954 
    955   if (!_dbus_string_init (&correct_hash))
    956     goto out_5;
    957 
    958   if (!sha1_compute_hash (auth, val,
    959                           &server_challenge,
    960                           &client_challenge,
    961                           &correct_hash))
    962     goto out_6;
    963 
    964   if (_dbus_string_get_length (&correct_hash) == 0)
    965     {
    966       /* couldn't find the cookie ID or something */
    967       if (send_error (auth, "Don't have the requested cookie ID"))
    968         retval = TRUE;
    969       goto out_6;
    970     }
    971 
    972   _dbus_string_set_length (&tmp, 0);
    973 
    974   if (!_dbus_string_copy (&client_challenge, 0, &tmp,
    975                           _dbus_string_get_length (&tmp)))
    976     goto out_6;
    977 
    978   if (!_dbus_string_append (&tmp, " "))
    979     goto out_6;
    980 
    981   if (!_dbus_string_copy (&correct_hash, 0, &tmp,
    982                           _dbus_string_get_length (&tmp)))
    983     goto out_6;
    984 
    985   if (!send_data (auth, &tmp))
    986     goto out_6;
    987 
    988   retval = TRUE;
    989 
    990  out_6:
    991   _dbus_string_zero (&correct_hash);
    992   _dbus_string_free (&correct_hash);
    993  out_5:
    994   _dbus_string_free (&client_challenge);
    995  out_4:
    996   _dbus_string_zero (&tmp);
    997   _dbus_string_free (&tmp);
    998  out_3:
    999   _dbus_string_free (&server_challenge);
   1000  out_2:
   1001   _dbus_string_free (&cookie_id_str);
   1002  out_1:
   1003   _dbus_string_free (&context);
   1004  out_0:
   1005   return retval;
   1006 }
   1007 
   1008 static void
   1009 handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth)
   1010 {
   1011   auth->cookie_id = -1;
   1012   _dbus_string_set_length (&auth->challenge, 0);
   1013 }
   1014 
   1015 /*
   1016  * EXTERNAL mechanism
   1017  */
   1018 
   1019 static dbus_bool_t
   1020 handle_server_data_external_mech (DBusAuth         *auth,
   1021                                   const DBusString *data)
   1022 {
   1023   if (_dbus_credentials_are_anonymous (auth->credentials))
   1024     {
   1025       _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
   1026                      DBUS_AUTH_NAME (auth));
   1027       return send_rejected (auth);
   1028     }
   1029 
   1030   if (_dbus_string_get_length (data) > 0)
   1031     {
   1032       if (_dbus_string_get_length (&auth->identity) > 0)
   1033         {
   1034           /* Tried to send two auth identities, wtf */
   1035           _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
   1036                          DBUS_AUTH_NAME (auth));
   1037           return send_rejected (auth);
   1038         }
   1039       else
   1040         {
   1041           /* this is our auth identity */
   1042           if (!_dbus_string_copy (data, 0, &auth->identity, 0))
   1043             return FALSE;
   1044         }
   1045     }
   1046 
   1047   /* Poke client for an auth identity, if none given */
   1048   if (_dbus_string_get_length (&auth->identity) == 0 &&
   1049       !auth->already_asked_for_initial_response)
   1050     {
   1051       if (send_data (auth, NULL))
   1052         {
   1053           _dbus_verbose ("%s: sending empty challenge asking client for auth identity\n",
   1054                          DBUS_AUTH_NAME (auth));
   1055           auth->already_asked_for_initial_response = TRUE;
   1056           goto_state (auth, &server_state_waiting_for_data);
   1057           return TRUE;
   1058         }
   1059       else
   1060         return FALSE;
   1061     }
   1062 
   1063   _dbus_credentials_clear (auth->desired_identity);
   1064 
   1065   /* If auth->identity is still empty here, then client
   1066    * responded with an empty string after we poked it for
   1067    * an initial response. This means to try to auth the
   1068    * identity provided in the credentials.
   1069    */
   1070   if (_dbus_string_get_length (&auth->identity) == 0)
   1071     {
   1072       if (!_dbus_credentials_add_credentials (auth->desired_identity,
   1073                                               auth->credentials))
   1074         {
   1075           return FALSE; /* OOM */
   1076         }
   1077     }
   1078   else
   1079     {
   1080       if (!_dbus_credentials_add_from_user (auth->desired_identity,
   1081                                             &auth->identity))
   1082         {
   1083           _dbus_verbose ("%s: could not get credentials from uid string\n",
   1084                          DBUS_AUTH_NAME (auth));
   1085           return send_rejected (auth);
   1086         }
   1087     }
   1088 
   1089   if (_dbus_credentials_are_anonymous (auth->desired_identity))
   1090     {
   1091       _dbus_verbose ("%s: desired user %s is no good\n",
   1092                      DBUS_AUTH_NAME (auth),
   1093                      _dbus_string_get_const_data (&auth->identity));
   1094       return send_rejected (auth);
   1095     }
   1096 
   1097   if (_dbus_credentials_are_superset (auth->credentials,
   1098                                       auth->desired_identity))
   1099     {
   1100       /* client has authenticated */
   1101       if (!_dbus_credentials_add_credentials (auth->authorized_identity,
   1102                                               auth->desired_identity))
   1103         return FALSE;
   1104 
   1105       /* also copy process ID from the socket credentials
   1106        */
   1107       if (!_dbus_credentials_add_credential (auth->authorized_identity,
   1108                                              DBUS_CREDENTIAL_UNIX_PROCESS_ID,
   1109                                              auth->credentials))
   1110         return FALSE;
   1111 
   1112       /* also copy audit data from the socket credentials
   1113        */
   1114       if (!_dbus_credentials_add_credential (auth->authorized_identity,
   1115                                              DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
   1116                                              auth->credentials))
   1117         return FALSE;
   1118 
   1119       if (!send_ok (auth))
   1120         return FALSE;
   1121 
   1122       _dbus_verbose ("%s: authenticated client based on socket credentials\n",
   1123                      DBUS_AUTH_NAME (auth));
   1124 
   1125       return TRUE;
   1126     }
   1127   else
   1128     {
   1129       _dbus_verbose ("%s: desired identity not found in socket credentials\n",
   1130                      DBUS_AUTH_NAME (auth));
   1131       return send_rejected (auth);
   1132     }
   1133 }
   1134 
   1135 static void
   1136 handle_server_shutdown_external_mech (DBusAuth *auth)
   1137 {
   1138 
   1139 }
   1140 
   1141 static dbus_bool_t
   1142 handle_client_initial_response_external_mech (DBusAuth         *auth,
   1143                                               DBusString       *response)
   1144 {
   1145   /* We always append our UID as an initial response, so the server
   1146    * doesn't have to send back an empty challenge to check whether we
   1147    * want to specify an identity. i.e. this avoids a round trip that
   1148    * the spec for the EXTERNAL mechanism otherwise requires.
   1149    */
   1150   DBusString plaintext;
   1151 
   1152   if (!_dbus_string_init (&plaintext))
   1153     return FALSE;
   1154 
   1155   if (!_dbus_append_user_from_current_process (&plaintext))
   1156     goto failed;
   1157 
   1158   if (!_dbus_string_hex_encode (&plaintext, 0,
   1159 				response,
   1160 				_dbus_string_get_length (response)))
   1161     goto failed;
   1162 
   1163   _dbus_string_free (&plaintext);
   1164 
   1165   return TRUE;
   1166 
   1167  failed:
   1168   _dbus_string_free (&plaintext);
   1169   return FALSE;
   1170 }
   1171 
   1172 static dbus_bool_t
   1173 handle_client_data_external_mech (DBusAuth         *auth,
   1174                                   const DBusString *data)
   1175 {
   1176 
   1177   return TRUE;
   1178 }
   1179 
   1180 static void
   1181 handle_client_shutdown_external_mech (DBusAuth *auth)
   1182 {
   1183 
   1184 }
   1185 
   1186 /*
   1187  * ANONYMOUS mechanism
   1188  */
   1189 
   1190 static dbus_bool_t
   1191 handle_server_data_anonymous_mech (DBusAuth         *auth,
   1192                                    const DBusString *data)
   1193 {
   1194   if (_dbus_string_get_length (data) > 0)
   1195     {
   1196       /* Client is allowed to send "trace" data, the only defined
   1197        * meaning is that if it contains '@' it is an email address,
   1198        * and otherwise it is anything else, and it's supposed to be
   1199        * UTF-8
   1200        */
   1201       if (!_dbus_string_validate_utf8 (data, 0, _dbus_string_get_length (data)))
   1202         {
   1203           _dbus_verbose ("%s: Received invalid UTF-8 trace data from ANONYMOUS client\n",
   1204                          DBUS_AUTH_NAME (auth));
   1205 
   1206           {
   1207             DBusString plaintext;
   1208             DBusString encoded;
   1209             _dbus_string_init_const (&plaintext, "D-Bus " DBUS_VERSION_STRING);
   1210             _dbus_string_init (&encoded);
   1211             _dbus_string_hex_encode (&plaintext, 0,
   1212                                      &encoded,
   1213                                      0);
   1214               _dbus_verbose ("%s: try '%s'\n",
   1215                              DBUS_AUTH_NAME (auth), _dbus_string_get_const_data (&encoded));
   1216           }
   1217           return send_rejected (auth);
   1218         }
   1219 
   1220       _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n",
   1221                      DBUS_AUTH_NAME (auth),
   1222                      _dbus_string_get_const_data (data));
   1223     }
   1224 
   1225   /* We want to be anonymous (clear in case some other protocol got midway through I guess) */
   1226   _dbus_credentials_clear (auth->desired_identity);
   1227 
   1228   /* Copy process ID from the socket credentials
   1229    */
   1230   if (!_dbus_credentials_add_credential (auth->authorized_identity,
   1231                                          DBUS_CREDENTIAL_UNIX_PROCESS_ID,
   1232                                          auth->credentials))
   1233     return FALSE;
   1234 
   1235   /* Anonymous is always allowed */
   1236   if (!send_ok (auth))
   1237     return FALSE;
   1238 
   1239   _dbus_verbose ("%s: authenticated client as anonymous\n",
   1240                  DBUS_AUTH_NAME (auth));
   1241 
   1242   return TRUE;
   1243 }
   1244 
   1245 static void
   1246 handle_server_shutdown_anonymous_mech (DBusAuth *auth)
   1247 {
   1248 
   1249 }
   1250 
   1251 static dbus_bool_t
   1252 handle_client_initial_response_anonymous_mech (DBusAuth         *auth,
   1253                                                DBusString       *response)
   1254 {
   1255   /* Our initial response is a "trace" string which must be valid UTF-8
   1256    * and must be an email address if it contains '@'.
   1257    * We just send the dbus implementation info, like a user-agent or
   1258    * something, because... why not. There's nothing guaranteed here
   1259    * though, we could change it later.
   1260    */
   1261   DBusString plaintext;
   1262 
   1263   if (!_dbus_string_init (&plaintext))
   1264     return FALSE;
   1265 
   1266   if (!_dbus_string_append (&plaintext,
   1267                             "libdbus " DBUS_VERSION_STRING))
   1268     goto failed;
   1269 
   1270   if (!_dbus_string_hex_encode (&plaintext, 0,
   1271 				response,
   1272 				_dbus_string_get_length (response)))
   1273     goto failed;
   1274 
   1275   _dbus_string_free (&plaintext);
   1276 
   1277   return TRUE;
   1278 
   1279  failed:
   1280   _dbus_string_free (&plaintext);
   1281   return FALSE;
   1282 }
   1283 
   1284 static dbus_bool_t
   1285 handle_client_data_anonymous_mech (DBusAuth         *auth,
   1286                                   const DBusString *data)
   1287 {
   1288 
   1289   return TRUE;
   1290 }
   1291 
   1292 static void
   1293 handle_client_shutdown_anonymous_mech (DBusAuth *auth)
   1294 {
   1295 
   1296 }
   1297 
   1298 /* Put mechanisms here in order of preference.
   1299  * Right now we have:
   1300  *
   1301  * - EXTERNAL checks socket credentials (or in the future, other info from the OS)
   1302  * - DBUS_COOKIE_SHA1 uses a cookie in the home directory, like xauth or ICE
   1303  * - ANONYMOUS checks nothing but doesn't auth the person as a user
   1304  *
   1305  * We might ideally add a mechanism to chain to Cyrus SASL so we can
   1306  * use its mechanisms as well.
   1307  *
   1308  */
   1309 static const DBusAuthMechanismHandler
   1310 all_mechanisms[] = {
   1311   { "EXTERNAL",
   1312     handle_server_data_external_mech,
   1313     NULL, NULL,
   1314     handle_server_shutdown_external_mech,
   1315     handle_client_initial_response_external_mech,
   1316     handle_client_data_external_mech,
   1317     NULL, NULL,
   1318     handle_client_shutdown_external_mech },
   1319   { "DBUS_COOKIE_SHA1",
   1320     handle_server_data_cookie_sha1_mech,
   1321     NULL, NULL,
   1322     handle_server_shutdown_cookie_sha1_mech,
   1323     handle_client_initial_response_cookie_sha1_mech,
   1324     handle_client_data_cookie_sha1_mech,
   1325     NULL, NULL,
   1326     handle_client_shutdown_cookie_sha1_mech },
   1327   { "ANONYMOUS",
   1328     handle_server_data_anonymous_mech,
   1329     NULL, NULL,
   1330     handle_server_shutdown_anonymous_mech,
   1331     handle_client_initial_response_anonymous_mech,
   1332     handle_client_data_anonymous_mech,
   1333     NULL, NULL,
   1334     handle_client_shutdown_anonymous_mech },
   1335   { NULL, NULL }
   1336 };
   1337 
   1338 static const DBusAuthMechanismHandler*
   1339 find_mech (const DBusString  *name,
   1340            char             **allowed_mechs)
   1341 {
   1342   int i;
   1343 
   1344   if (allowed_mechs != NULL &&
   1345       !_dbus_string_array_contains ((const char**) allowed_mechs,
   1346                                     _dbus_string_get_const_data (name)))
   1347     return NULL;
   1348 
   1349   i = 0;
   1350   while (all_mechanisms[i].mechanism != NULL)
   1351     {
   1352       if (_dbus_string_equal_c_str (name,
   1353                                     all_mechanisms[i].mechanism))
   1354 
   1355         return &all_mechanisms[i];
   1356 
   1357       ++i;
   1358     }
   1359 
   1360   return NULL;
   1361 }
   1362 
   1363 static dbus_bool_t
   1364 send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech)
   1365 {
   1366   DBusString auth_command;
   1367 
   1368   if (!_dbus_string_init (&auth_command))
   1369     return FALSE;
   1370 
   1371   if (!_dbus_string_append (&auth_command,
   1372                             "AUTH "))
   1373     {
   1374       _dbus_string_free (&auth_command);
   1375       return FALSE;
   1376     }
   1377 
   1378   if (!_dbus_string_append (&auth_command,
   1379                             mech->mechanism))
   1380     {
   1381       _dbus_string_free (&auth_command);
   1382       return FALSE;
   1383     }
   1384 
   1385   if (mech->client_initial_response_func != NULL)
   1386     {
   1387       if (!_dbus_string_append (&auth_command, " "))
   1388         {
   1389           _dbus_string_free (&auth_command);
   1390           return FALSE;
   1391         }
   1392 
   1393       if (!(* mech->client_initial_response_func) (auth, &auth_command))
   1394         {
   1395           _dbus_string_free (&auth_command);
   1396           return FALSE;
   1397         }
   1398     }
   1399 
   1400   if (!_dbus_string_append (&auth_command,
   1401                             "\r\n"))
   1402     {
   1403       _dbus_string_free (&auth_command);
   1404       return FALSE;
   1405     }
   1406 
   1407   if (!_dbus_string_copy (&auth_command, 0,
   1408                           &auth->outgoing,
   1409                           _dbus_string_get_length (&auth->outgoing)))
   1410     {
   1411       _dbus_string_free (&auth_command);
   1412       return FALSE;
   1413     }
   1414 
   1415   _dbus_string_free (&auth_command);
   1416   shutdown_mech (auth);
   1417   auth->mech = mech;
   1418   goto_state (auth, &client_state_waiting_for_data);
   1419 
   1420   return TRUE;
   1421 }
   1422 
   1423 static dbus_bool_t
   1424 send_data (DBusAuth *auth, DBusString *data)
   1425 {
   1426   int old_len;
   1427 
   1428   if (data == NULL || _dbus_string_get_length (data) == 0)
   1429     return _dbus_string_append (&auth->outgoing, "DATA\r\n");
   1430   else
   1431     {
   1432       old_len = _dbus_string_get_length (&auth->outgoing);
   1433       if (!_dbus_string_append (&auth->outgoing, "DATA "))
   1434         goto out;
   1435 
   1436       if (!_dbus_string_hex_encode (data, 0, &auth->outgoing,
   1437                                     _dbus_string_get_length (&auth->outgoing)))
   1438         goto out;
   1439 
   1440       if (!_dbus_string_append (&auth->outgoing, "\r\n"))
   1441         goto out;
   1442 
   1443       return TRUE;
   1444 
   1445     out:
   1446       _dbus_string_set_length (&auth->outgoing, old_len);
   1447 
   1448       return FALSE;
   1449     }
   1450 }
   1451 
   1452 static dbus_bool_t
   1453 send_rejected (DBusAuth *auth)
   1454 {
   1455   DBusString command;
   1456   DBusAuthServer *server_auth;
   1457   int i;
   1458 
   1459   if (!_dbus_string_init (&command))
   1460     return FALSE;
   1461 
   1462   if (!_dbus_string_append (&command,
   1463                             "REJECTED"))
   1464     goto nomem;
   1465 
   1466   i = 0;
   1467   while (all_mechanisms[i].mechanism != NULL)
   1468     {
   1469       if (!_dbus_string_append (&command,
   1470                                 " "))
   1471         goto nomem;
   1472 
   1473       if (!_dbus_string_append (&command,
   1474                                 all_mechanisms[i].mechanism))
   1475         goto nomem;
   1476 
   1477       ++i;
   1478     }
   1479 
   1480   if (!_dbus_string_append (&command, "\r\n"))
   1481     goto nomem;
   1482 
   1483   if (!_dbus_string_copy (&command, 0, &auth->outgoing,
   1484                           _dbus_string_get_length (&auth->outgoing)))
   1485     goto nomem;
   1486 
   1487   shutdown_mech (auth);
   1488 
   1489   _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
   1490   server_auth = DBUS_AUTH_SERVER (auth);
   1491   server_auth->failures += 1;
   1492 
   1493   if (server_auth->failures >= server_auth->max_failures)
   1494     goto_state (auth, &common_state_need_disconnect);
   1495   else
   1496     goto_state (auth, &server_state_waiting_for_auth);
   1497 
   1498   _dbus_string_free (&command);
   1499 
   1500   return TRUE;
   1501 
   1502  nomem:
   1503   _dbus_string_free (&command);
   1504   return FALSE;
   1505 }
   1506 
   1507 static dbus_bool_t
   1508 send_error (DBusAuth *auth, const char *message)
   1509 {
   1510   return _dbus_string_append_printf (&auth->outgoing,
   1511                                      "ERROR \"%s\"\r\n", message);
   1512 }
   1513 
   1514 static dbus_bool_t
   1515 send_ok (DBusAuth *auth)
   1516 {
   1517   int orig_len;
   1518 
   1519   orig_len = _dbus_string_get_length (&auth->outgoing);
   1520 
   1521   if (_dbus_string_append (&auth->outgoing, "OK ") &&
   1522       _dbus_string_copy (& DBUS_AUTH_SERVER (auth)->guid,
   1523                          0,
   1524                          &auth->outgoing,
   1525                          _dbus_string_get_length (&auth->outgoing)) &&
   1526       _dbus_string_append (&auth->outgoing, "\r\n"))
   1527     {
   1528       goto_state (auth, &server_state_waiting_for_begin);
   1529       return TRUE;
   1530     }
   1531   else
   1532     {
   1533       _dbus_string_set_length (&auth->outgoing, orig_len);
   1534       return FALSE;
   1535     }
   1536 }
   1537 
   1538 static dbus_bool_t
   1539 send_begin (DBusAuth         *auth)
   1540 {
   1541 
   1542   if (!_dbus_string_append (&auth->outgoing,
   1543                             "BEGIN\r\n"))
   1544     return FALSE;
   1545 
   1546   goto_state (auth, &common_state_authenticated);
   1547   return TRUE;
   1548 }
   1549 
   1550 static dbus_bool_t
   1551 process_ok(DBusAuth *auth,
   1552           const DBusString *args_from_ok) {
   1553 
   1554   int end_of_hex;
   1555 
   1556   /* "args_from_ok" should be the GUID, whitespace already pulled off the front */
   1557   _dbus_assert (_dbus_string_get_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server) == 0);
   1558 
   1559   /* We decode the hex string to binary, using guid_from_server as scratch... */
   1560 
   1561   end_of_hex = 0;
   1562   if (!_dbus_string_hex_decode (args_from_ok, 0, &end_of_hex,
   1563                                 & DBUS_AUTH_CLIENT (auth)->guid_from_server, 0))
   1564     return FALSE;
   1565 
   1566   /* now clear out the scratch */
   1567   _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
   1568 
   1569   if (end_of_hex != _dbus_string_get_length (args_from_ok) ||
   1570       end_of_hex == 0)
   1571     {
   1572       _dbus_verbose ("Bad GUID from server, parsed %d bytes and had %d bytes from server\n",
   1573                      end_of_hex, _dbus_string_get_length (args_from_ok));
   1574       goto_state (auth, &common_state_need_disconnect);
   1575       return TRUE;
   1576     }
   1577 
   1578   if (!_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) {
   1579       _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
   1580       return FALSE;
   1581   }
   1582 
   1583   _dbus_verbose ("Got GUID '%s' from the server\n",
   1584                  _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
   1585 
   1586   if (auth->unix_fd_possible)
   1587     return send_negotiate_unix_fd(auth);
   1588 
   1589   _dbus_verbose("Not negotiating unix fd passing, since not possible\n");
   1590   return send_begin (auth);
   1591 }
   1592 
   1593 static dbus_bool_t
   1594 send_cancel (DBusAuth *auth)
   1595 {
   1596   if (_dbus_string_append (&auth->outgoing, "CANCEL\r\n"))
   1597     {
   1598       goto_state (auth, &client_state_waiting_for_reject);
   1599       return TRUE;
   1600     }
   1601   else
   1602     return FALSE;
   1603 }
   1604 
   1605 static dbus_bool_t
   1606 process_data (DBusAuth             *auth,
   1607               const DBusString     *args,
   1608               DBusAuthDataFunction  data_func)
   1609 {
   1610   int end;
   1611   DBusString decoded;
   1612 
   1613   if (!_dbus_string_init (&decoded))
   1614     return FALSE;
   1615 
   1616   if (!_dbus_string_hex_decode (args, 0, &end, &decoded, 0))
   1617     {
   1618       _dbus_string_free (&decoded);
   1619       return FALSE;
   1620     }
   1621 
   1622   if (_dbus_string_get_length (args) != end)
   1623     {
   1624       _dbus_string_free (&decoded);
   1625       if (!send_error (auth, "Invalid hex encoding"))
   1626         return FALSE;
   1627 
   1628       return TRUE;
   1629     }
   1630 
   1631 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1632   if (_dbus_string_validate_ascii (&decoded, 0,
   1633                                    _dbus_string_get_length (&decoded)))
   1634     _dbus_verbose ("%s: data: '%s'\n",
   1635                    DBUS_AUTH_NAME (auth),
   1636                    _dbus_string_get_const_data (&decoded));
   1637 #endif
   1638 
   1639   if (!(* data_func) (auth, &decoded))
   1640     {
   1641       _dbus_string_free (&decoded);
   1642       return FALSE;
   1643     }
   1644 
   1645   _dbus_string_free (&decoded);
   1646   return TRUE;
   1647 }
   1648 
   1649 static dbus_bool_t
   1650 send_negotiate_unix_fd (DBusAuth *auth)
   1651 {
   1652   if (!_dbus_string_append (&auth->outgoing,
   1653                             "NEGOTIATE_UNIX_FD\r\n"))
   1654     return FALSE;
   1655 
   1656   goto_state (auth, &client_state_waiting_for_agree_unix_fd);
   1657   return TRUE;
   1658 }
   1659 
   1660 static dbus_bool_t
   1661 send_agree_unix_fd (DBusAuth *auth)
   1662 {
   1663   _dbus_assert(auth->unix_fd_possible);
   1664 
   1665   auth->unix_fd_negotiated = TRUE;
   1666   _dbus_verbose("Agreed to UNIX FD passing\n");
   1667 
   1668   if (!_dbus_string_append (&auth->outgoing,
   1669                             "AGREE_UNIX_FD\r\n"))
   1670     return FALSE;
   1671 
   1672   goto_state (auth, &server_state_waiting_for_begin);
   1673   return TRUE;
   1674 }
   1675 
   1676 static dbus_bool_t
   1677 handle_auth (DBusAuth *auth, const DBusString *args)
   1678 {
   1679   if (_dbus_string_get_length (args) == 0)
   1680     {
   1681       /* No args to the auth, send mechanisms */
   1682       if (!send_rejected (auth))
   1683         return FALSE;
   1684 
   1685       return TRUE;
   1686     }
   1687   else
   1688     {
   1689       int i;
   1690       DBusString mech;
   1691       DBusString hex_response;
   1692 
   1693       _dbus_string_find_blank (args, 0, &i);
   1694 
   1695       if (!_dbus_string_init (&mech))
   1696         return FALSE;
   1697 
   1698       if (!_dbus_string_init (&hex_response))
   1699         {
   1700           _dbus_string_free (&mech);
   1701           return FALSE;
   1702         }
   1703 
   1704       if (!_dbus_string_copy_len (args, 0, i, &mech, 0))
   1705         goto failed;
   1706 
   1707       _dbus_string_skip_blank (args, i, &i);
   1708       if (!_dbus_string_copy (args, i, &hex_response, 0))
   1709         goto failed;
   1710 
   1711       auth->mech = find_mech (&mech, auth->allowed_mechs);
   1712       if (auth->mech != NULL)
   1713         {
   1714           _dbus_verbose ("%s: Trying mechanism %s\n",
   1715                          DBUS_AUTH_NAME (auth),
   1716                          auth->mech->mechanism);
   1717 
   1718           if (!process_data (auth, &hex_response,
   1719                              auth->mech->server_data_func))
   1720             goto failed;
   1721         }
   1722       else
   1723         {
   1724           /* Unsupported mechanism */
   1725           _dbus_verbose ("%s: Unsupported mechanism %s\n",
   1726                          DBUS_AUTH_NAME (auth),
   1727                          _dbus_string_get_const_data (&mech));
   1728 
   1729           if (!send_rejected (auth))
   1730             goto failed;
   1731         }
   1732 
   1733       _dbus_string_free (&mech);
   1734       _dbus_string_free (&hex_response);
   1735 
   1736       return TRUE;
   1737 
   1738     failed:
   1739       auth->mech = NULL;
   1740       _dbus_string_free (&mech);
   1741       _dbus_string_free (&hex_response);
   1742       return FALSE;
   1743     }
   1744 }
   1745 
   1746 static dbus_bool_t
   1747 handle_server_state_waiting_for_auth  (DBusAuth         *auth,
   1748                                        DBusAuthCommand   command,
   1749                                        const DBusString *args)
   1750 {
   1751   switch (command)
   1752     {
   1753     case DBUS_AUTH_COMMAND_AUTH:
   1754       return handle_auth (auth, args);
   1755 
   1756     case DBUS_AUTH_COMMAND_CANCEL:
   1757     case DBUS_AUTH_COMMAND_DATA:
   1758       return send_error (auth, "Not currently in an auth conversation");
   1759 
   1760     case DBUS_AUTH_COMMAND_BEGIN:
   1761       goto_state (auth, &common_state_need_disconnect);
   1762       return TRUE;
   1763 
   1764     case DBUS_AUTH_COMMAND_ERROR:
   1765       return send_rejected (auth);
   1766 
   1767     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   1768       return send_error (auth, "Need to authenticate first");
   1769 
   1770     case DBUS_AUTH_COMMAND_REJECTED:
   1771     case DBUS_AUTH_COMMAND_OK:
   1772     case DBUS_AUTH_COMMAND_UNKNOWN:
   1773     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   1774     default:
   1775       return send_error (auth, "Unknown command");
   1776     }
   1777 }
   1778 
   1779 static dbus_bool_t
   1780 handle_server_state_waiting_for_data  (DBusAuth         *auth,
   1781                                        DBusAuthCommand   command,
   1782                                        const DBusString *args)
   1783 {
   1784   switch (command)
   1785     {
   1786     case DBUS_AUTH_COMMAND_AUTH:
   1787       return send_error (auth, "Sent AUTH while another AUTH in progress");
   1788 
   1789     case DBUS_AUTH_COMMAND_CANCEL:
   1790     case DBUS_AUTH_COMMAND_ERROR:
   1791       return send_rejected (auth);
   1792 
   1793     case DBUS_AUTH_COMMAND_DATA:
   1794       return process_data (auth, args, auth->mech->server_data_func);
   1795 
   1796     case DBUS_AUTH_COMMAND_BEGIN:
   1797       goto_state (auth, &common_state_need_disconnect);
   1798       return TRUE;
   1799 
   1800     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   1801       return send_error (auth, "Need to authenticate first");
   1802 
   1803     case DBUS_AUTH_COMMAND_REJECTED:
   1804     case DBUS_AUTH_COMMAND_OK:
   1805     case DBUS_AUTH_COMMAND_UNKNOWN:
   1806     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   1807     default:
   1808       return send_error (auth, "Unknown command");
   1809     }
   1810 }
   1811 
   1812 static dbus_bool_t
   1813 handle_server_state_waiting_for_begin (DBusAuth         *auth,
   1814                                        DBusAuthCommand   command,
   1815                                        const DBusString *args)
   1816 {
   1817   switch (command)
   1818     {
   1819     case DBUS_AUTH_COMMAND_AUTH:
   1820       return send_error (auth, "Sent AUTH while expecting BEGIN");
   1821 
   1822     case DBUS_AUTH_COMMAND_DATA:
   1823       return send_error (auth, "Sent DATA while expecting BEGIN");
   1824 
   1825     case DBUS_AUTH_COMMAND_BEGIN:
   1826       goto_state (auth, &common_state_authenticated);
   1827       return TRUE;
   1828 
   1829     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   1830       if (auth->unix_fd_possible)
   1831         return send_agree_unix_fd(auth);
   1832       else
   1833         return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible");
   1834 
   1835     case DBUS_AUTH_COMMAND_REJECTED:
   1836     case DBUS_AUTH_COMMAND_OK:
   1837     case DBUS_AUTH_COMMAND_UNKNOWN:
   1838     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   1839     default:
   1840       return send_error (auth, "Unknown command");
   1841 
   1842     case DBUS_AUTH_COMMAND_CANCEL:
   1843     case DBUS_AUTH_COMMAND_ERROR:
   1844       return send_rejected (auth);
   1845     }
   1846 }
   1847 
   1848 /* return FALSE if no memory, TRUE if all OK */
   1849 static dbus_bool_t
   1850 get_word (const DBusString *str,
   1851           int              *start,
   1852           DBusString       *word)
   1853 {
   1854   int i;
   1855 
   1856   _dbus_string_skip_blank (str, *start, start);
   1857   _dbus_string_find_blank (str, *start, &i);
   1858 
   1859   if (i > *start)
   1860     {
   1861       if (!_dbus_string_copy_len (str, *start, i - *start, word, 0))
   1862         return FALSE;
   1863 
   1864       *start = i;
   1865     }
   1866 
   1867   return TRUE;
   1868 }
   1869 
   1870 static dbus_bool_t
   1871 record_mechanisms (DBusAuth         *auth,
   1872                    const DBusString *args)
   1873 {
   1874   int next;
   1875   int len;
   1876 
   1877   if (auth->already_got_mechanisms)
   1878     return TRUE;
   1879 
   1880   len = _dbus_string_get_length (args);
   1881 
   1882   next = 0;
   1883   while (next < len)
   1884     {
   1885       DBusString m;
   1886       const DBusAuthMechanismHandler *mech;
   1887 
   1888       if (!_dbus_string_init (&m))
   1889         goto nomem;
   1890 
   1891       if (!get_word (args, &next, &m))
   1892         {
   1893           _dbus_string_free (&m);
   1894           goto nomem;
   1895         }
   1896 
   1897       mech = find_mech (&m, auth->allowed_mechs);
   1898 
   1899       if (mech != NULL)
   1900         {
   1901           /* FIXME right now we try mechanisms in the order
   1902            * the server lists them; should we do them in
   1903            * some more deterministic order?
   1904            *
   1905            * Probably in all_mechanisms order, our order of
   1906            * preference. Of course when the server is us,
   1907            * it lists things in that order anyhow.
   1908            */
   1909 
   1910           if (mech != &all_mechanisms[0])
   1911             {
   1912               _dbus_verbose ("%s: Adding mechanism %s to list we will try\n",
   1913                              DBUS_AUTH_NAME (auth), mech->mechanism);
   1914 
   1915               if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
   1916                                       (void*) mech))
   1917                 {
   1918                   _dbus_string_free (&m);
   1919                   goto nomem;
   1920                 }
   1921             }
   1922           else
   1923             {
   1924               _dbus_verbose ("%s: Already tried mechanism %s; not adding to list we will try\n",
   1925                              DBUS_AUTH_NAME (auth), mech->mechanism);
   1926             }
   1927         }
   1928       else
   1929         {
   1930           _dbus_verbose ("%s: Server offered mechanism \"%s\" that we don't know how to use\n",
   1931                          DBUS_AUTH_NAME (auth),
   1932                          _dbus_string_get_const_data (&m));
   1933         }
   1934 
   1935       _dbus_string_free (&m);
   1936     }
   1937 
   1938   auth->already_got_mechanisms = TRUE;
   1939 
   1940   return TRUE;
   1941 
   1942  nomem:
   1943   _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
   1944 
   1945   return FALSE;
   1946 }
   1947 
   1948 static dbus_bool_t
   1949 process_rejected (DBusAuth *auth, const DBusString *args)
   1950 {
   1951   const DBusAuthMechanismHandler *mech;
   1952   DBusAuthClient *client;
   1953 
   1954   client = DBUS_AUTH_CLIENT (auth);
   1955 
   1956   if (!auth->already_got_mechanisms)
   1957     {
   1958       if (!record_mechanisms (auth, args))
   1959         return FALSE;
   1960     }
   1961 
   1962   if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL)
   1963     {
   1964       mech = client->mechs_to_try->data;
   1965 
   1966       if (!send_auth (auth, mech))
   1967         return FALSE;
   1968 
   1969       _dbus_list_pop_first (&client->mechs_to_try);
   1970 
   1971       _dbus_verbose ("%s: Trying mechanism %s\n",
   1972                      DBUS_AUTH_NAME (auth),
   1973                      mech->mechanism);
   1974     }
   1975   else
   1976     {
   1977       /* Give up */
   1978       _dbus_verbose ("%s: Disconnecting because we are out of mechanisms to try using\n",
   1979                      DBUS_AUTH_NAME (auth));
   1980       goto_state (auth, &common_state_need_disconnect);
   1981     }
   1982 
   1983   return TRUE;
   1984 }
   1985 
   1986 
   1987 static dbus_bool_t
   1988 handle_client_state_waiting_for_data (DBusAuth         *auth,
   1989                                       DBusAuthCommand   command,
   1990                                       const DBusString *args)
   1991 {
   1992   _dbus_assert (auth->mech != NULL);
   1993 
   1994   switch (command)
   1995     {
   1996     case DBUS_AUTH_COMMAND_DATA:
   1997       return process_data (auth, args, auth->mech->client_data_func);
   1998 
   1999     case DBUS_AUTH_COMMAND_REJECTED:
   2000       return process_rejected (auth, args);
   2001 
   2002     case DBUS_AUTH_COMMAND_OK:
   2003       return process_ok(auth, args);
   2004 
   2005     case DBUS_AUTH_COMMAND_ERROR:
   2006       return send_cancel (auth);
   2007 
   2008     case DBUS_AUTH_COMMAND_AUTH:
   2009     case DBUS_AUTH_COMMAND_CANCEL:
   2010     case DBUS_AUTH_COMMAND_BEGIN:
   2011     case DBUS_AUTH_COMMAND_UNKNOWN:
   2012     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2013     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2014     default:
   2015       return send_error (auth, "Unknown command");
   2016     }
   2017 }
   2018 
   2019 static dbus_bool_t
   2020 handle_client_state_waiting_for_ok (DBusAuth         *auth,
   2021                                     DBusAuthCommand   command,
   2022                                     const DBusString *args)
   2023 {
   2024   switch (command)
   2025     {
   2026     case DBUS_AUTH_COMMAND_REJECTED:
   2027       return process_rejected (auth, args);
   2028 
   2029     case DBUS_AUTH_COMMAND_OK:
   2030       return process_ok(auth, args);
   2031 
   2032     case DBUS_AUTH_COMMAND_DATA:
   2033     case DBUS_AUTH_COMMAND_ERROR:
   2034       return send_cancel (auth);
   2035 
   2036     case DBUS_AUTH_COMMAND_AUTH:
   2037     case DBUS_AUTH_COMMAND_CANCEL:
   2038     case DBUS_AUTH_COMMAND_BEGIN:
   2039     case DBUS_AUTH_COMMAND_UNKNOWN:
   2040     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2041     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2042     default:
   2043       return send_error (auth, "Unknown command");
   2044     }
   2045 }
   2046 
   2047 static dbus_bool_t
   2048 handle_client_state_waiting_for_reject (DBusAuth         *auth,
   2049                                         DBusAuthCommand   command,
   2050                                         const DBusString *args)
   2051 {
   2052   switch (command)
   2053     {
   2054     case DBUS_AUTH_COMMAND_REJECTED:
   2055       return process_rejected (auth, args);
   2056 
   2057     case DBUS_AUTH_COMMAND_AUTH:
   2058     case DBUS_AUTH_COMMAND_CANCEL:
   2059     case DBUS_AUTH_COMMAND_DATA:
   2060     case DBUS_AUTH_COMMAND_BEGIN:
   2061     case DBUS_AUTH_COMMAND_OK:
   2062     case DBUS_AUTH_COMMAND_ERROR:
   2063     case DBUS_AUTH_COMMAND_UNKNOWN:
   2064     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2065     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2066     default:
   2067       goto_state (auth, &common_state_need_disconnect);
   2068       return TRUE;
   2069     }
   2070 }
   2071 
   2072 static dbus_bool_t
   2073 handle_client_state_waiting_for_agree_unix_fd(DBusAuth         *auth,
   2074                                               DBusAuthCommand   command,
   2075                                               const DBusString *args)
   2076 {
   2077   switch (command)
   2078     {
   2079     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2080       _dbus_assert(auth->unix_fd_possible);
   2081       auth->unix_fd_negotiated = TRUE;
   2082       _dbus_verbose("Sucessfully negotiated UNIX FD passing\n");
   2083       return send_begin (auth);
   2084 
   2085     case DBUS_AUTH_COMMAND_ERROR:
   2086       _dbus_assert(auth->unix_fd_possible);
   2087       auth->unix_fd_negotiated = FALSE;
   2088       _dbus_verbose("Failed to negotiate UNIX FD passing\n");
   2089       return send_begin (auth);
   2090 
   2091     case DBUS_AUTH_COMMAND_OK:
   2092     case DBUS_AUTH_COMMAND_DATA:
   2093     case DBUS_AUTH_COMMAND_REJECTED:
   2094     case DBUS_AUTH_COMMAND_AUTH:
   2095     case DBUS_AUTH_COMMAND_CANCEL:
   2096     case DBUS_AUTH_COMMAND_BEGIN:
   2097     case DBUS_AUTH_COMMAND_UNKNOWN:
   2098     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2099     default:
   2100       return send_error (auth, "Unknown command");
   2101     }
   2102 }
   2103 
   2104 /**
   2105  * Mapping from command name to enum
   2106  */
   2107 typedef struct {
   2108   const char *name;        /**< Name of the command */
   2109   DBusAuthCommand command; /**< Corresponding enum */
   2110 } DBusAuthCommandName;
   2111 
   2112 static const DBusAuthCommandName auth_command_names[] = {
   2113   { "AUTH",              DBUS_AUTH_COMMAND_AUTH },
   2114   { "CANCEL",            DBUS_AUTH_COMMAND_CANCEL },
   2115   { "DATA",              DBUS_AUTH_COMMAND_DATA },
   2116   { "BEGIN",             DBUS_AUTH_COMMAND_BEGIN },
   2117   { "REJECTED",          DBUS_AUTH_COMMAND_REJECTED },
   2118   { "OK",                DBUS_AUTH_COMMAND_OK },
   2119   { "ERROR",             DBUS_AUTH_COMMAND_ERROR },
   2120   { "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD },
   2121   { "AGREE_UNIX_FD",     DBUS_AUTH_COMMAND_AGREE_UNIX_FD }
   2122 };
   2123 
   2124 static DBusAuthCommand
   2125 lookup_command_from_name (DBusString *command)
   2126 {
   2127   int i;
   2128 
   2129   for (i = 0; i < _DBUS_N_ELEMENTS (auth_command_names); i++)
   2130     {
   2131       if (_dbus_string_equal_c_str (command,
   2132                                     auth_command_names[i].name))
   2133         return auth_command_names[i].command;
   2134     }
   2135 
   2136   return DBUS_AUTH_COMMAND_UNKNOWN;
   2137 }
   2138 
   2139 static void
   2140 goto_state (DBusAuth *auth,
   2141             const DBusAuthStateData *state)
   2142 {
   2143   _dbus_verbose ("%s: going from state %s to state %s\n",
   2144                  DBUS_AUTH_NAME (auth),
   2145                  auth->state->name,
   2146                  state->name);
   2147 
   2148   auth->state = state;
   2149 }
   2150 
   2151 /* returns whether to call it again right away */
   2152 static dbus_bool_t
   2153 process_command (DBusAuth *auth)
   2154 {
   2155   DBusAuthCommand command;
   2156   DBusString line;
   2157   DBusString args;
   2158   int eol;
   2159   int i, j;
   2160   dbus_bool_t retval;
   2161 
   2162   /* _dbus_verbose ("%s:   trying process_command()\n"); */
   2163 
   2164   retval = FALSE;
   2165 
   2166   eol = 0;
   2167   if (!_dbus_string_find (&auth->incoming, 0, "\r\n", &eol))
   2168     return FALSE;
   2169 
   2170   if (!_dbus_string_init (&line))
   2171     {
   2172       auth->needed_memory = TRUE;
   2173       return FALSE;
   2174     }
   2175 
   2176   if (!_dbus_string_init (&args))
   2177     {
   2178       _dbus_string_free (&line);
   2179       auth->needed_memory = TRUE;
   2180       return FALSE;
   2181     }
   2182 
   2183   if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &line, 0))
   2184     goto out;
   2185 
   2186   if (!_dbus_string_validate_ascii (&line, 0,
   2187                                     _dbus_string_get_length (&line)))
   2188     {
   2189       _dbus_verbose ("%s: Command contained non-ASCII chars or embedded nul\n",
   2190                      DBUS_AUTH_NAME (auth));
   2191       if (!send_error (auth, "Command contained non-ASCII"))
   2192         goto out;
   2193       else
   2194         goto next_command;
   2195     }
   2196 
   2197   _dbus_verbose ("%s: got command \"%s\"\n",
   2198                  DBUS_AUTH_NAME (auth),
   2199                  _dbus_string_get_const_data (&line));
   2200 
   2201   _dbus_string_find_blank (&line, 0, &i);
   2202   _dbus_string_skip_blank (&line, i, &j);
   2203 
   2204   if (j > i)
   2205     _dbus_string_delete (&line, i, j - i);
   2206 
   2207   if (!_dbus_string_move (&line, i, &args, 0))
   2208     goto out;
   2209 
   2210   /* FIXME 1.0 we should probably validate that only the allowed
   2211    * chars are in the command name
   2212    */
   2213 
   2214   command = lookup_command_from_name (&line);
   2215   if (!(* auth->state->handler) (auth, command, &args))
   2216     goto out;
   2217 
   2218  next_command:
   2219 
   2220   /* We've succeeded in processing the whole command so drop it out
   2221    * of the incoming buffer and return TRUE to try another command.
   2222    */
   2223 
   2224   _dbus_string_delete (&auth->incoming, 0, eol);
   2225 
   2226   /* kill the \r\n */
   2227   _dbus_string_delete (&auth->incoming, 0, 2);
   2228 
   2229   retval = TRUE;
   2230 
   2231  out:
   2232   _dbus_string_free (&args);
   2233   _dbus_string_free (&line);
   2234 
   2235   if (!retval)
   2236     auth->needed_memory = TRUE;
   2237   else
   2238     auth->needed_memory = FALSE;
   2239 
   2240   return retval;
   2241 }
   2242 
   2243 
   2244 /** @} */
   2245 
   2246 /**
   2247  * @addtogroup DBusAuth
   2248  * @{
   2249  */
   2250 
   2251 /**
   2252  * Creates a new auth conversation object for the server side.
   2253  * See doc/dbus-sasl-profile.txt for full details on what
   2254  * this object does.
   2255  *
   2256  * @returns the new object or #NULL if no memory
   2257  */
   2258 DBusAuth*
   2259 _dbus_auth_server_new (const DBusString *guid)
   2260 {
   2261   DBusAuth *auth;
   2262   DBusAuthServer *server_auth;
   2263   DBusString guid_copy;
   2264 
   2265   if (!_dbus_string_init (&guid_copy))
   2266     return NULL;
   2267 
   2268   if (!_dbus_string_copy (guid, 0, &guid_copy, 0))
   2269     {
   2270       _dbus_string_free (&guid_copy);
   2271       return NULL;
   2272     }
   2273 
   2274   auth = _dbus_auth_new (sizeof (DBusAuthServer));
   2275   if (auth == NULL)
   2276     {
   2277       _dbus_string_free (&guid_copy);
   2278       return NULL;
   2279     }
   2280 
   2281   auth->side = auth_side_server;
   2282   auth->state = &server_state_waiting_for_auth;
   2283 
   2284   server_auth = DBUS_AUTH_SERVER (auth);
   2285 
   2286   server_auth->guid = guid_copy;
   2287 
   2288   /* perhaps this should be per-mechanism with a lower
   2289    * max
   2290    */
   2291   server_auth->failures = 0;
   2292   server_auth->max_failures = 6;
   2293 
   2294   return auth;
   2295 }
   2296 
   2297 /**
   2298  * Creates a new auth conversation object for the client side.
   2299  * See doc/dbus-sasl-profile.txt for full details on what
   2300  * this object does.
   2301  *
   2302  * @returns the new object or #NULL if no memory
   2303  */
   2304 DBusAuth*
   2305 _dbus_auth_client_new (void)
   2306 {
   2307   DBusAuth *auth;
   2308   DBusString guid_str;
   2309 
   2310   if (!_dbus_string_init (&guid_str))
   2311     return NULL;
   2312 
   2313   auth = _dbus_auth_new (sizeof (DBusAuthClient));
   2314   if (auth == NULL)
   2315     {
   2316       _dbus_string_free (&guid_str);
   2317       return NULL;
   2318     }
   2319 
   2320   DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str;
   2321 
   2322   auth->side = auth_side_client;
   2323   auth->state = &client_state_need_send_auth;
   2324 
   2325   /* Start the auth conversation by sending AUTH for our default
   2326    * mechanism */
   2327   if (!send_auth (auth, &all_mechanisms[0]))
   2328     {
   2329       _dbus_auth_unref (auth);
   2330       return NULL;
   2331     }
   2332 
   2333   return auth;
   2334 }
   2335 
   2336 /**
   2337  * Increments the refcount of an auth object.
   2338  *
   2339  * @param auth the auth conversation
   2340  * @returns the auth conversation
   2341  */
   2342 DBusAuth *
   2343 _dbus_auth_ref (DBusAuth *auth)
   2344 {
   2345   _dbus_assert (auth != NULL);
   2346 
   2347   auth->refcount += 1;
   2348 
   2349   return auth;
   2350 }
   2351 
   2352 /**
   2353  * Decrements the refcount of an auth object.
   2354  *
   2355  * @param auth the auth conversation
   2356  */
   2357 void
   2358 _dbus_auth_unref (DBusAuth *auth)
   2359 {
   2360   _dbus_assert (auth != NULL);
   2361   _dbus_assert (auth->refcount > 0);
   2362 
   2363   auth->refcount -= 1;
   2364   if (auth->refcount == 0)
   2365     {
   2366       shutdown_mech (auth);
   2367 
   2368       if (DBUS_AUTH_IS_CLIENT (auth))
   2369         {
   2370           _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
   2371           _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
   2372         }
   2373       else
   2374         {
   2375           _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
   2376 
   2377           _dbus_string_free (& DBUS_AUTH_SERVER (auth)->guid);
   2378         }
   2379 
   2380       if (auth->keyring)
   2381         _dbus_keyring_unref (auth->keyring);
   2382 
   2383       _dbus_string_free (&auth->context);
   2384       _dbus_string_free (&auth->challenge);
   2385       _dbus_string_free (&auth->identity);
   2386       _dbus_string_free (&auth->incoming);
   2387       _dbus_string_free (&auth->outgoing);
   2388 
   2389       dbus_free_string_array (auth->allowed_mechs);
   2390 
   2391       _dbus_credentials_unref (auth->credentials);
   2392       _dbus_credentials_unref (auth->authorized_identity);
   2393       _dbus_credentials_unref (auth->desired_identity);
   2394 
   2395       dbus_free (auth);
   2396     }
   2397 }
   2398 
   2399 /**
   2400  * Sets an array of authentication mechanism names
   2401  * that we are willing to use.
   2402  *
   2403  * @param auth the auth conversation
   2404  * @param mechanisms #NULL-terminated array of mechanism names
   2405  * @returns #FALSE if no memory
   2406  */
   2407 dbus_bool_t
   2408 _dbus_auth_set_mechanisms (DBusAuth    *auth,
   2409                            const char **mechanisms)
   2410 {
   2411   char **copy;
   2412 
   2413   if (mechanisms != NULL)
   2414     {
   2415       copy = _dbus_dup_string_array (mechanisms);
   2416       if (copy == NULL)
   2417         return FALSE;
   2418     }
   2419   else
   2420     copy = NULL;
   2421 
   2422   dbus_free_string_array (auth->allowed_mechs);
   2423 
   2424   auth->allowed_mechs = copy;
   2425 
   2426   return TRUE;
   2427 }
   2428 
   2429 /**
   2430  * @param auth the auth conversation object
   2431  * @returns #TRUE if we're in a final state
   2432  */
   2433 #define DBUS_AUTH_IN_END_STATE(auth) ((auth)->state->handler == NULL)
   2434 
   2435 /**
   2436  * Analyzes buffered input and moves the auth conversation forward,
   2437  * returning the new state of the auth conversation.
   2438  *
   2439  * @param auth the auth conversation
   2440  * @returns the new state
   2441  */
   2442 DBusAuthState
   2443 _dbus_auth_do_work (DBusAuth *auth)
   2444 {
   2445   auth->needed_memory = FALSE;
   2446 
   2447   /* Max amount we'll buffer up before deciding someone's on crack */
   2448 #define MAX_BUFFER (16 * _DBUS_ONE_KILOBYTE)
   2449 
   2450   do
   2451     {
   2452       if (DBUS_AUTH_IN_END_STATE (auth))
   2453         break;
   2454 
   2455       if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER ||
   2456           _dbus_string_get_length (&auth->outgoing) > MAX_BUFFER)
   2457         {
   2458           goto_state (auth, &common_state_need_disconnect);
   2459           _dbus_verbose ("%s: Disconnecting due to excessive data buffered in auth phase\n",
   2460                          DBUS_AUTH_NAME (auth));
   2461           break;
   2462         }
   2463     }
   2464   while (process_command (auth));
   2465 
   2466   if (auth->needed_memory)
   2467     return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
   2468   else if (_dbus_string_get_length (&auth->outgoing) > 0)
   2469     return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
   2470   else if (auth->state == &common_state_need_disconnect)
   2471     return DBUS_AUTH_STATE_NEED_DISCONNECT;
   2472   else if (auth->state == &common_state_authenticated)
   2473     return DBUS_AUTH_STATE_AUTHENTICATED;
   2474   else return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
   2475 }
   2476 
   2477 /**
   2478  * Gets bytes that need to be sent to the peer we're conversing with.
   2479  * After writing some bytes, _dbus_auth_bytes_sent() must be called
   2480  * to notify the auth object that they were written.
   2481  *
   2482  * @param auth the auth conversation
   2483  * @param str return location for a ref to the buffer to send
   2484  * @returns #FALSE if nothing to send
   2485  */
   2486 dbus_bool_t
   2487 _dbus_auth_get_bytes_to_send (DBusAuth          *auth,
   2488                               const DBusString **str)
   2489 {
   2490   _dbus_assert (auth != NULL);
   2491   _dbus_assert (str != NULL);
   2492 
   2493   *str = NULL;
   2494 
   2495   if (_dbus_string_get_length (&auth->outgoing) == 0)
   2496     return FALSE;
   2497 
   2498   *str = &auth->outgoing;
   2499 
   2500   return TRUE;
   2501 }
   2502 
   2503 /**
   2504  * Notifies the auth conversation object that
   2505  * the given number of bytes of the outgoing buffer
   2506  * have been written out.
   2507  *
   2508  * @param auth the auth conversation
   2509  * @param bytes_sent number of bytes written out
   2510  */
   2511 void
   2512 _dbus_auth_bytes_sent (DBusAuth *auth,
   2513                        int       bytes_sent)
   2514 {
   2515   _dbus_verbose ("%s: Sent %d bytes of: %s\n",
   2516                  DBUS_AUTH_NAME (auth),
   2517                  bytes_sent,
   2518                  _dbus_string_get_const_data (&auth->outgoing));
   2519 
   2520   _dbus_string_delete (&auth->outgoing,
   2521                        0, bytes_sent);
   2522 }
   2523 
   2524 /**
   2525  * Get a buffer to be used for reading bytes from the peer we're conversing
   2526  * with. Bytes should be appended to this buffer.
   2527  *
   2528  * @param auth the auth conversation
   2529  * @param buffer return location for buffer to append bytes to
   2530  */
   2531 void
   2532 _dbus_auth_get_buffer (DBusAuth     *auth,
   2533                        DBusString **buffer)
   2534 {
   2535   _dbus_assert (auth != NULL);
   2536   _dbus_assert (!auth->buffer_outstanding);
   2537 
   2538   *buffer = &auth->incoming;
   2539 
   2540   auth->buffer_outstanding = TRUE;
   2541 }
   2542 
   2543 /**
   2544  * Returns a buffer with new data read into it.
   2545  *
   2546  * @param auth the auth conversation
   2547  * @param buffer the buffer being returned
   2548  * @param bytes_read number of new bytes added
   2549  */
   2550 void
   2551 _dbus_auth_return_buffer (DBusAuth               *auth,
   2552                           DBusString             *buffer,
   2553                           int                     bytes_read)
   2554 {
   2555   _dbus_assert (buffer == &auth->incoming);
   2556   _dbus_assert (auth->buffer_outstanding);
   2557 
   2558   auth->buffer_outstanding = FALSE;
   2559 }
   2560 
   2561 /**
   2562  * Returns leftover bytes that were not used as part of the auth
   2563  * conversation.  These bytes will be part of the message stream
   2564  * instead. This function may not be called until authentication has
   2565  * succeeded.
   2566  *
   2567  * @param auth the auth conversation
   2568  * @param str return location for pointer to string of unused bytes
   2569  */
   2570 void
   2571 _dbus_auth_get_unused_bytes (DBusAuth           *auth,
   2572                              const DBusString **str)
   2573 {
   2574   if (!DBUS_AUTH_IN_END_STATE (auth))
   2575     return;
   2576 
   2577   *str = &auth->incoming;
   2578 }
   2579 
   2580 
   2581 /**
   2582  * Gets rid of unused bytes returned by _dbus_auth_get_unused_bytes()
   2583  * after we've gotten them and successfully moved them elsewhere.
   2584  *
   2585  * @param auth the auth conversation
   2586  */
   2587 void
   2588 _dbus_auth_delete_unused_bytes (DBusAuth *auth)
   2589 {
   2590   if (!DBUS_AUTH_IN_END_STATE (auth))
   2591     return;
   2592 
   2593   _dbus_string_set_length (&auth->incoming, 0);
   2594 }
   2595 
   2596 /**
   2597  * Called post-authentication, indicates whether we need to encode
   2598  * the message stream with _dbus_auth_encode_data() prior to
   2599  * sending it to the peer.
   2600  *
   2601  * @param auth the auth conversation
   2602  * @returns #TRUE if we need to encode the stream
   2603  */
   2604 dbus_bool_t
   2605 _dbus_auth_needs_encoding (DBusAuth *auth)
   2606 {
   2607   if (auth->state != &common_state_authenticated)
   2608     return FALSE;
   2609 
   2610   if (auth->mech != NULL)
   2611     {
   2612       if (DBUS_AUTH_IS_CLIENT (auth))
   2613         return auth->mech->client_encode_func != NULL;
   2614       else
   2615         return auth->mech->server_encode_func != NULL;
   2616     }
   2617   else
   2618     return FALSE;
   2619 }
   2620 
   2621 /**
   2622  * Called post-authentication, encodes a block of bytes for sending to
   2623  * the peer. If no encoding was negotiated, just copies the bytes
   2624  * (you can avoid this by checking _dbus_auth_needs_encoding()).
   2625  *
   2626  * @param auth the auth conversation
   2627  * @param plaintext the plain text data
   2628  * @param encoded initialized string to where encoded data is appended
   2629  * @returns #TRUE if we had enough memory and successfully encoded
   2630  */
   2631 dbus_bool_t
   2632 _dbus_auth_encode_data (DBusAuth         *auth,
   2633                         const DBusString *plaintext,
   2634                         DBusString       *encoded)
   2635 {
   2636   _dbus_assert (plaintext != encoded);
   2637 
   2638   if (auth->state != &common_state_authenticated)
   2639     return FALSE;
   2640 
   2641   if (_dbus_auth_needs_encoding (auth))
   2642     {
   2643       if (DBUS_AUTH_IS_CLIENT (auth))
   2644         return (* auth->mech->client_encode_func) (auth, plaintext, encoded);
   2645       else
   2646         return (* auth->mech->server_encode_func) (auth, plaintext, encoded);
   2647     }
   2648   else
   2649     {
   2650       return _dbus_string_copy (plaintext, 0, encoded,
   2651                                 _dbus_string_get_length (encoded));
   2652     }
   2653 }
   2654 
   2655 /**
   2656  * Called post-authentication, indicates whether we need to decode
   2657  * the message stream with _dbus_auth_decode_data() after
   2658  * receiving it from the peer.
   2659  *
   2660  * @param auth the auth conversation
   2661  * @returns #TRUE if we need to encode the stream
   2662  */
   2663 dbus_bool_t
   2664 _dbus_auth_needs_decoding (DBusAuth *auth)
   2665 {
   2666   if (auth->state != &common_state_authenticated)
   2667     return FALSE;
   2668 
   2669   if (auth->mech != NULL)
   2670     {
   2671       if (DBUS_AUTH_IS_CLIENT (auth))
   2672         return auth->mech->client_decode_func != NULL;
   2673       else
   2674         return auth->mech->server_decode_func != NULL;
   2675     }
   2676   else
   2677     return FALSE;
   2678 }
   2679 
   2680 
   2681 /**
   2682  * Called post-authentication, decodes a block of bytes received from
   2683  * the peer. If no encoding was negotiated, just copies the bytes (you
   2684  * can avoid this by checking _dbus_auth_needs_decoding()).
   2685  *
   2686  * @todo 1.0? We need to be able to distinguish "out of memory" error
   2687  * from "the data is hosed" error.
   2688  *
   2689  * @param auth the auth conversation
   2690  * @param encoded the encoded data
   2691  * @param plaintext initialized string where decoded data is appended
   2692  * @returns #TRUE if we had enough memory and successfully decoded
   2693  */
   2694 dbus_bool_t
   2695 _dbus_auth_decode_data (DBusAuth         *auth,
   2696                         const DBusString *encoded,
   2697                         DBusString       *plaintext)
   2698 {
   2699   _dbus_assert (plaintext != encoded);
   2700 
   2701   if (auth->state != &common_state_authenticated)
   2702     return FALSE;
   2703 
   2704   if (_dbus_auth_needs_decoding (auth))
   2705     {
   2706       if (DBUS_AUTH_IS_CLIENT (auth))
   2707         return (* auth->mech->client_decode_func) (auth, encoded, plaintext);
   2708       else
   2709         return (* auth->mech->server_decode_func) (auth, encoded, plaintext);
   2710     }
   2711   else
   2712     {
   2713       return _dbus_string_copy (encoded, 0, plaintext,
   2714                                 _dbus_string_get_length (plaintext));
   2715     }
   2716 }
   2717 
   2718 /**
   2719  * Sets credentials received via reliable means from the operating
   2720  * system.
   2721  *
   2722  * @param auth the auth conversation
   2723  * @param credentials the credentials received
   2724  * @returns #FALSE on OOM
   2725  */
   2726 dbus_bool_t
   2727 _dbus_auth_set_credentials (DBusAuth               *auth,
   2728                             DBusCredentials        *credentials)
   2729 {
   2730   _dbus_credentials_clear (auth->credentials);
   2731   return _dbus_credentials_add_credentials (auth->credentials,
   2732                                             credentials);
   2733 }
   2734 
   2735 /**
   2736  * Gets the identity we authorized the client as.  Apps may have
   2737  * different policies as to what identities they allow.
   2738  *
   2739  * Returned credentials are not a copy and should not be modified
   2740  *
   2741  * @param auth the auth conversation
   2742  * @returns the credentials we've authorized BY REFERENCE do not modify
   2743  */
   2744 DBusCredentials*
   2745 _dbus_auth_get_identity (DBusAuth               *auth)
   2746 {
   2747   if (auth->state == &common_state_authenticated)
   2748     {
   2749       return auth->authorized_identity;
   2750     }
   2751   else
   2752     {
   2753       /* FIXME instead of this, keep an empty credential around that
   2754        * doesn't require allocation or something
   2755        */
   2756       /* return empty credentials */
   2757       _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity));
   2758       return auth->authorized_identity;
   2759     }
   2760 }
   2761 
   2762 /**
   2763  * Gets the GUID from the server if we've authenticated; gets
   2764  * #NULL otherwise.
   2765  * @param auth the auth object
   2766  * @returns the GUID in ASCII hex format
   2767  */
   2768 const char*
   2769 _dbus_auth_get_guid_from_server (DBusAuth *auth)
   2770 {
   2771   _dbus_assert (DBUS_AUTH_IS_CLIENT (auth));
   2772 
   2773   if (auth->state == &common_state_authenticated)
   2774     return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
   2775   else
   2776     return NULL;
   2777 }
   2778 
   2779 /**
   2780  * Sets the "authentication context" which scopes cookies
   2781  * with the DBUS_COOKIE_SHA1 auth mechanism for example.
   2782  *
   2783  * @param auth the auth conversation
   2784  * @param context the context
   2785  * @returns #FALSE if no memory
   2786  */
   2787 dbus_bool_t
   2788 _dbus_auth_set_context (DBusAuth               *auth,
   2789                         const DBusString       *context)
   2790 {
   2791   return _dbus_string_replace_len (context, 0, _dbus_string_get_length (context),
   2792                                    &auth->context, 0, _dbus_string_get_length (context));
   2793 }
   2794 
   2795 /**
   2796  * Sets whether unix fd passing is potentially on the transport and
   2797  * hence shall be negotiated.
   2798  *
   2799  * @param auth the auth conversation
   2800  * @param b TRUE when unix fd passing shall be negotiated, otherwise FALSE
   2801  */
   2802 void
   2803 _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b)
   2804 {
   2805   auth->unix_fd_possible = b;
   2806 }
   2807 
   2808 /**
   2809  * Queries whether unix fd passing was sucessfully negotiated.
   2810  *
   2811  * @param auth the auth conversion
   2812  * @returns #TRUE when unix fd passing was negotiated.
   2813  */
   2814 dbus_bool_t
   2815 _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth)
   2816 {
   2817   return auth->unix_fd_negotiated;
   2818 }
   2819 
   2820 /** @} */
   2821 
   2822 /* tests in dbus-auth-util.c */
   2823