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_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_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_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           return send_rejected (auth);
   1206         }
   1207 
   1208       _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n",
   1209                      DBUS_AUTH_NAME (auth),
   1210                      _dbus_string_get_const_data (data));
   1211     }
   1212 
   1213   /* We want to be anonymous (clear in case some other protocol got midway through I guess) */
   1214   _dbus_credentials_clear (auth->desired_identity);
   1215 
   1216   /* Copy process ID from the socket credentials
   1217    */
   1218   if (!_dbus_credentials_add_credential (auth->authorized_identity,
   1219                                          DBUS_CREDENTIAL_UNIX_PROCESS_ID,
   1220                                          auth->credentials))
   1221     return FALSE;
   1222 
   1223   /* Anonymous is always allowed */
   1224   if (!send_ok (auth))
   1225     return FALSE;
   1226 
   1227   _dbus_verbose ("%s: authenticated client as anonymous\n",
   1228                  DBUS_AUTH_NAME (auth));
   1229 
   1230   return TRUE;
   1231 }
   1232 
   1233 static void
   1234 handle_server_shutdown_anonymous_mech (DBusAuth *auth)
   1235 {
   1236 
   1237 }
   1238 
   1239 static dbus_bool_t
   1240 handle_client_initial_response_anonymous_mech (DBusAuth         *auth,
   1241                                                DBusString       *response)
   1242 {
   1243   /* Our initial response is a "trace" string which must be valid UTF-8
   1244    * and must be an email address if it contains '@'.
   1245    * We just send the dbus implementation info, like a user-agent or
   1246    * something, because... why not. There's nothing guaranteed here
   1247    * though, we could change it later.
   1248    */
   1249   DBusString plaintext;
   1250 
   1251   if (!_dbus_string_init (&plaintext))
   1252     return FALSE;
   1253 
   1254   if (!_dbus_string_append (&plaintext,
   1255                             "libdbus " DBUS_VERSION_STRING))
   1256     goto failed;
   1257 
   1258   if (!_dbus_string_hex_encode (&plaintext, 0,
   1259 				response,
   1260 				_dbus_string_get_length (response)))
   1261     goto failed;
   1262 
   1263   _dbus_string_free (&plaintext);
   1264 
   1265   return TRUE;
   1266 
   1267  failed:
   1268   _dbus_string_free (&plaintext);
   1269   return FALSE;
   1270 }
   1271 
   1272 static dbus_bool_t
   1273 handle_client_data_anonymous_mech (DBusAuth         *auth,
   1274                                   const DBusString *data)
   1275 {
   1276 
   1277   return TRUE;
   1278 }
   1279 
   1280 static void
   1281 handle_client_shutdown_anonymous_mech (DBusAuth *auth)
   1282 {
   1283 
   1284 }
   1285 
   1286 /* Put mechanisms here in order of preference.
   1287  * Right now we have:
   1288  *
   1289  * - EXTERNAL checks socket credentials (or in the future, other info from the OS)
   1290  * - DBUS_COOKIE_SHA1 uses a cookie in the home directory, like xauth or ICE
   1291  * - ANONYMOUS checks nothing but doesn't auth the person as a user
   1292  *
   1293  * We might ideally add a mechanism to chain to Cyrus SASL so we can
   1294  * use its mechanisms as well.
   1295  *
   1296  */
   1297 static const DBusAuthMechanismHandler
   1298 all_mechanisms[] = {
   1299   { "EXTERNAL",
   1300     handle_server_data_external_mech,
   1301     NULL, NULL,
   1302     handle_server_shutdown_external_mech,
   1303     handle_client_initial_response_external_mech,
   1304     handle_client_data_external_mech,
   1305     NULL, NULL,
   1306     handle_client_shutdown_external_mech },
   1307   { "DBUS_COOKIE_SHA1",
   1308     handle_server_data_cookie_sha1_mech,
   1309     NULL, NULL,
   1310     handle_server_shutdown_cookie_sha1_mech,
   1311     handle_client_initial_response_cookie_sha1_mech,
   1312     handle_client_data_cookie_sha1_mech,
   1313     NULL, NULL,
   1314     handle_client_shutdown_cookie_sha1_mech },
   1315   { "ANONYMOUS",
   1316     handle_server_data_anonymous_mech,
   1317     NULL, NULL,
   1318     handle_server_shutdown_anonymous_mech,
   1319     handle_client_initial_response_anonymous_mech,
   1320     handle_client_data_anonymous_mech,
   1321     NULL, NULL,
   1322     handle_client_shutdown_anonymous_mech },
   1323   { NULL, NULL }
   1324 };
   1325 
   1326 static const DBusAuthMechanismHandler*
   1327 find_mech (const DBusString  *name,
   1328            char             **allowed_mechs)
   1329 {
   1330   int i;
   1331 
   1332   if (allowed_mechs != NULL &&
   1333       !_dbus_string_array_contains ((const char**) allowed_mechs,
   1334                                     _dbus_string_get_const_data (name)))
   1335     return NULL;
   1336 
   1337   i = 0;
   1338   while (all_mechanisms[i].mechanism != NULL)
   1339     {
   1340       if (_dbus_string_equal_c_str (name,
   1341                                     all_mechanisms[i].mechanism))
   1342 
   1343         return &all_mechanisms[i];
   1344 
   1345       ++i;
   1346     }
   1347 
   1348   return NULL;
   1349 }
   1350 
   1351 static dbus_bool_t
   1352 send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech)
   1353 {
   1354   DBusString auth_command;
   1355 
   1356   if (!_dbus_string_init (&auth_command))
   1357     return FALSE;
   1358 
   1359   if (!_dbus_string_append (&auth_command,
   1360                             "AUTH "))
   1361     {
   1362       _dbus_string_free (&auth_command);
   1363       return FALSE;
   1364     }
   1365 
   1366   if (!_dbus_string_append (&auth_command,
   1367                             mech->mechanism))
   1368     {
   1369       _dbus_string_free (&auth_command);
   1370       return FALSE;
   1371     }
   1372 
   1373   if (mech->client_initial_response_func != NULL)
   1374     {
   1375       if (!_dbus_string_append (&auth_command, " "))
   1376         {
   1377           _dbus_string_free (&auth_command);
   1378           return FALSE;
   1379         }
   1380 
   1381       if (!(* mech->client_initial_response_func) (auth, &auth_command))
   1382         {
   1383           _dbus_string_free (&auth_command);
   1384           return FALSE;
   1385         }
   1386     }
   1387 
   1388   if (!_dbus_string_append (&auth_command,
   1389                             "\r\n"))
   1390     {
   1391       _dbus_string_free (&auth_command);
   1392       return FALSE;
   1393     }
   1394 
   1395   if (!_dbus_string_copy (&auth_command, 0,
   1396                           &auth->outgoing,
   1397                           _dbus_string_get_length (&auth->outgoing)))
   1398     {
   1399       _dbus_string_free (&auth_command);
   1400       return FALSE;
   1401     }
   1402 
   1403   _dbus_string_free (&auth_command);
   1404   shutdown_mech (auth);
   1405   auth->mech = mech;
   1406   goto_state (auth, &client_state_waiting_for_data);
   1407 
   1408   return TRUE;
   1409 }
   1410 
   1411 static dbus_bool_t
   1412 send_data (DBusAuth *auth, DBusString *data)
   1413 {
   1414   int old_len;
   1415 
   1416   if (data == NULL || _dbus_string_get_length (data) == 0)
   1417     return _dbus_string_append (&auth->outgoing, "DATA\r\n");
   1418   else
   1419     {
   1420       old_len = _dbus_string_get_length (&auth->outgoing);
   1421       if (!_dbus_string_append (&auth->outgoing, "DATA "))
   1422         goto out;
   1423 
   1424       if (!_dbus_string_hex_encode (data, 0, &auth->outgoing,
   1425                                     _dbus_string_get_length (&auth->outgoing)))
   1426         goto out;
   1427 
   1428       if (!_dbus_string_append (&auth->outgoing, "\r\n"))
   1429         goto out;
   1430 
   1431       return TRUE;
   1432 
   1433     out:
   1434       _dbus_string_set_length (&auth->outgoing, old_len);
   1435 
   1436       return FALSE;
   1437     }
   1438 }
   1439 
   1440 static dbus_bool_t
   1441 send_rejected (DBusAuth *auth)
   1442 {
   1443   DBusString command;
   1444   DBusAuthServer *server_auth;
   1445   int i;
   1446 
   1447   if (!_dbus_string_init (&command))
   1448     return FALSE;
   1449 
   1450   if (!_dbus_string_append (&command,
   1451                             "REJECTED"))
   1452     goto nomem;
   1453 
   1454   i = 0;
   1455   while (all_mechanisms[i].mechanism != NULL)
   1456     {
   1457       if (!_dbus_string_append (&command,
   1458                                 " "))
   1459         goto nomem;
   1460 
   1461       if (!_dbus_string_append (&command,
   1462                                 all_mechanisms[i].mechanism))
   1463         goto nomem;
   1464 
   1465       ++i;
   1466     }
   1467 
   1468   if (!_dbus_string_append (&command, "\r\n"))
   1469     goto nomem;
   1470 
   1471   if (!_dbus_string_copy (&command, 0, &auth->outgoing,
   1472                           _dbus_string_get_length (&auth->outgoing)))
   1473     goto nomem;
   1474 
   1475   shutdown_mech (auth);
   1476 
   1477   _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
   1478   server_auth = DBUS_AUTH_SERVER (auth);
   1479   server_auth->failures += 1;
   1480 
   1481   if (server_auth->failures >= server_auth->max_failures)
   1482     goto_state (auth, &common_state_need_disconnect);
   1483   else
   1484     goto_state (auth, &server_state_waiting_for_auth);
   1485 
   1486   _dbus_string_free (&command);
   1487 
   1488   return TRUE;
   1489 
   1490  nomem:
   1491   _dbus_string_free (&command);
   1492   return FALSE;
   1493 }
   1494 
   1495 static dbus_bool_t
   1496 send_error (DBusAuth *auth, const char *message)
   1497 {
   1498   return _dbus_string_append_printf (&auth->outgoing,
   1499                                      "ERROR \"%s\"\r\n", message);
   1500 }
   1501 
   1502 static dbus_bool_t
   1503 send_ok (DBusAuth *auth)
   1504 {
   1505   int orig_len;
   1506 
   1507   orig_len = _dbus_string_get_length (&auth->outgoing);
   1508 
   1509   if (_dbus_string_append (&auth->outgoing, "OK ") &&
   1510       _dbus_string_copy (& DBUS_AUTH_SERVER (auth)->guid,
   1511                          0,
   1512                          &auth->outgoing,
   1513                          _dbus_string_get_length (&auth->outgoing)) &&
   1514       _dbus_string_append (&auth->outgoing, "\r\n"))
   1515     {
   1516       goto_state (auth, &server_state_waiting_for_begin);
   1517       return TRUE;
   1518     }
   1519   else
   1520     {
   1521       _dbus_string_set_length (&auth->outgoing, orig_len);
   1522       return FALSE;
   1523     }
   1524 }
   1525 
   1526 static dbus_bool_t
   1527 send_begin (DBusAuth         *auth)
   1528 {
   1529 
   1530   if (!_dbus_string_append (&auth->outgoing,
   1531                             "BEGIN\r\n"))
   1532     return FALSE;
   1533 
   1534   goto_state (auth, &common_state_authenticated);
   1535   return TRUE;
   1536 }
   1537 
   1538 static dbus_bool_t
   1539 process_ok(DBusAuth *auth,
   1540           const DBusString *args_from_ok) {
   1541 
   1542   int end_of_hex;
   1543 
   1544   /* "args_from_ok" should be the GUID, whitespace already pulled off the front */
   1545   _dbus_assert (_dbus_string_get_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server) == 0);
   1546 
   1547   /* We decode the hex string to binary, using guid_from_server as scratch... */
   1548 
   1549   end_of_hex = 0;
   1550   if (!_dbus_string_hex_decode (args_from_ok, 0, &end_of_hex,
   1551                                 & DBUS_AUTH_CLIENT (auth)->guid_from_server, 0))
   1552     return FALSE;
   1553 
   1554   /* now clear out the scratch */
   1555   _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
   1556 
   1557   if (end_of_hex != _dbus_string_get_length (args_from_ok) ||
   1558       end_of_hex == 0)
   1559     {
   1560       _dbus_verbose ("Bad GUID from server, parsed %d bytes and had %d bytes from server\n",
   1561                      end_of_hex, _dbus_string_get_length (args_from_ok));
   1562       goto_state (auth, &common_state_need_disconnect);
   1563       return TRUE;
   1564     }
   1565 
   1566   if (!_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) {
   1567       _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
   1568       return FALSE;
   1569   }
   1570 
   1571   _dbus_verbose ("Got GUID '%s' from the server\n",
   1572                  _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
   1573 
   1574   if (auth->unix_fd_possible)
   1575     return send_negotiate_unix_fd(auth);
   1576 
   1577   _dbus_verbose("Not negotiating unix fd passing, since not possible\n");
   1578   return send_begin (auth);
   1579 }
   1580 
   1581 static dbus_bool_t
   1582 send_cancel (DBusAuth *auth)
   1583 {
   1584   if (_dbus_string_append (&auth->outgoing, "CANCEL\r\n"))
   1585     {
   1586       goto_state (auth, &client_state_waiting_for_reject);
   1587       return TRUE;
   1588     }
   1589   else
   1590     return FALSE;
   1591 }
   1592 
   1593 static dbus_bool_t
   1594 process_data (DBusAuth             *auth,
   1595               const DBusString     *args,
   1596               DBusAuthDataFunction  data_func)
   1597 {
   1598   int end;
   1599   DBusString decoded;
   1600 
   1601   if (!_dbus_string_init (&decoded))
   1602     return FALSE;
   1603 
   1604   if (!_dbus_string_hex_decode (args, 0, &end, &decoded, 0))
   1605     {
   1606       _dbus_string_free (&decoded);
   1607       return FALSE;
   1608     }
   1609 
   1610   if (_dbus_string_get_length (args) != end)
   1611     {
   1612       _dbus_string_free (&decoded);
   1613       if (!send_error (auth, "Invalid hex encoding"))
   1614         return FALSE;
   1615 
   1616       return TRUE;
   1617     }
   1618 
   1619 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1620   if (_dbus_string_validate_ascii (&decoded, 0,
   1621                                    _dbus_string_get_length (&decoded)))
   1622     _dbus_verbose ("%s: data: '%s'\n",
   1623                    DBUS_AUTH_NAME (auth),
   1624                    _dbus_string_get_const_data (&decoded));
   1625 #endif
   1626 
   1627   if (!(* data_func) (auth, &decoded))
   1628     {
   1629       _dbus_string_free (&decoded);
   1630       return FALSE;
   1631     }
   1632 
   1633   _dbus_string_free (&decoded);
   1634   return TRUE;
   1635 }
   1636 
   1637 static dbus_bool_t
   1638 send_negotiate_unix_fd (DBusAuth *auth)
   1639 {
   1640   if (!_dbus_string_append (&auth->outgoing,
   1641                             "NEGOTIATE_UNIX_FD\r\n"))
   1642     return FALSE;
   1643 
   1644   goto_state (auth, &client_state_waiting_for_agree_unix_fd);
   1645   return TRUE;
   1646 }
   1647 
   1648 static dbus_bool_t
   1649 send_agree_unix_fd (DBusAuth *auth)
   1650 {
   1651   _dbus_assert(auth->unix_fd_possible);
   1652 
   1653   auth->unix_fd_negotiated = TRUE;
   1654   _dbus_verbose("Agreed to UNIX FD passing\n");
   1655 
   1656   if (!_dbus_string_append (&auth->outgoing,
   1657                             "AGREE_UNIX_FD\r\n"))
   1658     return FALSE;
   1659 
   1660   goto_state (auth, &server_state_waiting_for_begin);
   1661   return TRUE;
   1662 }
   1663 
   1664 static dbus_bool_t
   1665 handle_auth (DBusAuth *auth, const DBusString *args)
   1666 {
   1667   if (_dbus_string_get_length (args) == 0)
   1668     {
   1669       /* No args to the auth, send mechanisms */
   1670       if (!send_rejected (auth))
   1671         return FALSE;
   1672 
   1673       return TRUE;
   1674     }
   1675   else
   1676     {
   1677       int i;
   1678       DBusString mech;
   1679       DBusString hex_response;
   1680 
   1681       _dbus_string_find_blank (args, 0, &i);
   1682 
   1683       if (!_dbus_string_init (&mech))
   1684         return FALSE;
   1685 
   1686       if (!_dbus_string_init (&hex_response))
   1687         {
   1688           _dbus_string_free (&mech);
   1689           return FALSE;
   1690         }
   1691 
   1692       if (!_dbus_string_copy_len (args, 0, i, &mech, 0))
   1693         goto failed;
   1694 
   1695       _dbus_string_skip_blank (args, i, &i);
   1696       if (!_dbus_string_copy (args, i, &hex_response, 0))
   1697         goto failed;
   1698 
   1699       auth->mech = find_mech (&mech, auth->allowed_mechs);
   1700       if (auth->mech != NULL)
   1701         {
   1702           _dbus_verbose ("%s: Trying mechanism %s\n",
   1703                          DBUS_AUTH_NAME (auth),
   1704                          auth->mech->mechanism);
   1705 
   1706           if (!process_data (auth, &hex_response,
   1707                              auth->mech->server_data_func))
   1708             goto failed;
   1709         }
   1710       else
   1711         {
   1712           /* Unsupported mechanism */
   1713           _dbus_verbose ("%s: Unsupported mechanism %s\n",
   1714                          DBUS_AUTH_NAME (auth),
   1715                          _dbus_string_get_const_data (&mech));
   1716 
   1717           if (!send_rejected (auth))
   1718             goto failed;
   1719         }
   1720 
   1721       _dbus_string_free (&mech);
   1722       _dbus_string_free (&hex_response);
   1723 
   1724       return TRUE;
   1725 
   1726     failed:
   1727       auth->mech = NULL;
   1728       _dbus_string_free (&mech);
   1729       _dbus_string_free (&hex_response);
   1730       return FALSE;
   1731     }
   1732 }
   1733 
   1734 static dbus_bool_t
   1735 handle_server_state_waiting_for_auth  (DBusAuth         *auth,
   1736                                        DBusAuthCommand   command,
   1737                                        const DBusString *args)
   1738 {
   1739   switch (command)
   1740     {
   1741     case DBUS_AUTH_COMMAND_AUTH:
   1742       return handle_auth (auth, args);
   1743 
   1744     case DBUS_AUTH_COMMAND_CANCEL:
   1745     case DBUS_AUTH_COMMAND_DATA:
   1746       return send_error (auth, "Not currently in an auth conversation");
   1747 
   1748     case DBUS_AUTH_COMMAND_BEGIN:
   1749       goto_state (auth, &common_state_need_disconnect);
   1750       return TRUE;
   1751 
   1752     case DBUS_AUTH_COMMAND_ERROR:
   1753       return send_rejected (auth);
   1754 
   1755     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   1756       return send_error (auth, "Need to authenticate first");
   1757 
   1758     case DBUS_AUTH_COMMAND_REJECTED:
   1759     case DBUS_AUTH_COMMAND_OK:
   1760     case DBUS_AUTH_COMMAND_UNKNOWN:
   1761     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   1762     default:
   1763       return send_error (auth, "Unknown command");
   1764     }
   1765 }
   1766 
   1767 static dbus_bool_t
   1768 handle_server_state_waiting_for_data  (DBusAuth         *auth,
   1769                                        DBusAuthCommand   command,
   1770                                        const DBusString *args)
   1771 {
   1772   switch (command)
   1773     {
   1774     case DBUS_AUTH_COMMAND_AUTH:
   1775       return send_error (auth, "Sent AUTH while another AUTH in progress");
   1776 
   1777     case DBUS_AUTH_COMMAND_CANCEL:
   1778     case DBUS_AUTH_COMMAND_ERROR:
   1779       return send_rejected (auth);
   1780 
   1781     case DBUS_AUTH_COMMAND_DATA:
   1782       return process_data (auth, args, auth->mech->server_data_func);
   1783 
   1784     case DBUS_AUTH_COMMAND_BEGIN:
   1785       goto_state (auth, &common_state_need_disconnect);
   1786       return TRUE;
   1787 
   1788     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   1789       return send_error (auth, "Need to authenticate first");
   1790 
   1791     case DBUS_AUTH_COMMAND_REJECTED:
   1792     case DBUS_AUTH_COMMAND_OK:
   1793     case DBUS_AUTH_COMMAND_UNKNOWN:
   1794     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   1795     default:
   1796       return send_error (auth, "Unknown command");
   1797     }
   1798 }
   1799 
   1800 static dbus_bool_t
   1801 handle_server_state_waiting_for_begin (DBusAuth         *auth,
   1802                                        DBusAuthCommand   command,
   1803                                        const DBusString *args)
   1804 {
   1805   switch (command)
   1806     {
   1807     case DBUS_AUTH_COMMAND_AUTH:
   1808       return send_error (auth, "Sent AUTH while expecting BEGIN");
   1809 
   1810     case DBUS_AUTH_COMMAND_DATA:
   1811       return send_error (auth, "Sent DATA while expecting BEGIN");
   1812 
   1813     case DBUS_AUTH_COMMAND_BEGIN:
   1814       goto_state (auth, &common_state_authenticated);
   1815       return TRUE;
   1816 
   1817     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   1818       if (auth->unix_fd_possible)
   1819         return send_agree_unix_fd(auth);
   1820       else
   1821         return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible");
   1822 
   1823     case DBUS_AUTH_COMMAND_REJECTED:
   1824     case DBUS_AUTH_COMMAND_OK:
   1825     case DBUS_AUTH_COMMAND_UNKNOWN:
   1826     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   1827     default:
   1828       return send_error (auth, "Unknown command");
   1829 
   1830     case DBUS_AUTH_COMMAND_CANCEL:
   1831     case DBUS_AUTH_COMMAND_ERROR:
   1832       return send_rejected (auth);
   1833     }
   1834 }
   1835 
   1836 /* return FALSE if no memory, TRUE if all OK */
   1837 static dbus_bool_t
   1838 get_word (const DBusString *str,
   1839           int              *start,
   1840           DBusString       *word)
   1841 {
   1842   int i;
   1843 
   1844   _dbus_string_skip_blank (str, *start, start);
   1845   _dbus_string_find_blank (str, *start, &i);
   1846 
   1847   if (i > *start)
   1848     {
   1849       if (!_dbus_string_copy_len (str, *start, i - *start, word, 0))
   1850         return FALSE;
   1851 
   1852       *start = i;
   1853     }
   1854 
   1855   return TRUE;
   1856 }
   1857 
   1858 static dbus_bool_t
   1859 record_mechanisms (DBusAuth         *auth,
   1860                    const DBusString *args)
   1861 {
   1862   int next;
   1863   int len;
   1864 
   1865   if (auth->already_got_mechanisms)
   1866     return TRUE;
   1867 
   1868   len = _dbus_string_get_length (args);
   1869 
   1870   next = 0;
   1871   while (next < len)
   1872     {
   1873       DBusString m;
   1874       const DBusAuthMechanismHandler *mech;
   1875 
   1876       if (!_dbus_string_init (&m))
   1877         goto nomem;
   1878 
   1879       if (!get_word (args, &next, &m))
   1880         {
   1881           _dbus_string_free (&m);
   1882           goto nomem;
   1883         }
   1884 
   1885       mech = find_mech (&m, auth->allowed_mechs);
   1886 
   1887       if (mech != NULL)
   1888         {
   1889           /* FIXME right now we try mechanisms in the order
   1890            * the server lists them; should we do them in
   1891            * some more deterministic order?
   1892            *
   1893            * Probably in all_mechanisms order, our order of
   1894            * preference. Of course when the server is us,
   1895            * it lists things in that order anyhow.
   1896            */
   1897 
   1898           if (mech != &all_mechanisms[0])
   1899             {
   1900               _dbus_verbose ("%s: Adding mechanism %s to list we will try\n",
   1901                              DBUS_AUTH_NAME (auth), mech->mechanism);
   1902 
   1903               if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
   1904                                       (void*) mech))
   1905                 {
   1906                   _dbus_string_free (&m);
   1907                   goto nomem;
   1908                 }
   1909             }
   1910           else
   1911             {
   1912               _dbus_verbose ("%s: Already tried mechanism %s; not adding to list we will try\n",
   1913                              DBUS_AUTH_NAME (auth), mech->mechanism);
   1914             }
   1915         }
   1916       else
   1917         {
   1918           _dbus_verbose ("%s: Server offered mechanism \"%s\" that we don't know how to use\n",
   1919                          DBUS_AUTH_NAME (auth),
   1920                          _dbus_string_get_const_data (&m));
   1921         }
   1922 
   1923       _dbus_string_free (&m);
   1924     }
   1925 
   1926   auth->already_got_mechanisms = TRUE;
   1927 
   1928   return TRUE;
   1929 
   1930  nomem:
   1931   _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
   1932 
   1933   return FALSE;
   1934 }
   1935 
   1936 static dbus_bool_t
   1937 process_rejected (DBusAuth *auth, const DBusString *args)
   1938 {
   1939   const DBusAuthMechanismHandler *mech;
   1940   DBusAuthClient *client;
   1941 
   1942   client = DBUS_AUTH_CLIENT (auth);
   1943 
   1944   if (!auth->already_got_mechanisms)
   1945     {
   1946       if (!record_mechanisms (auth, args))
   1947         return FALSE;
   1948     }
   1949 
   1950   if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL)
   1951     {
   1952       mech = client->mechs_to_try->data;
   1953 
   1954       if (!send_auth (auth, mech))
   1955         return FALSE;
   1956 
   1957       _dbus_list_pop_first (&client->mechs_to_try);
   1958 
   1959       _dbus_verbose ("%s: Trying mechanism %s\n",
   1960                      DBUS_AUTH_NAME (auth),
   1961                      mech->mechanism);
   1962     }
   1963   else
   1964     {
   1965       /* Give up */
   1966       _dbus_verbose ("%s: Disconnecting because we are out of mechanisms to try using\n",
   1967                      DBUS_AUTH_NAME (auth));
   1968       goto_state (auth, &common_state_need_disconnect);
   1969     }
   1970 
   1971   return TRUE;
   1972 }
   1973 
   1974 
   1975 static dbus_bool_t
   1976 handle_client_state_waiting_for_data (DBusAuth         *auth,
   1977                                       DBusAuthCommand   command,
   1978                                       const DBusString *args)
   1979 {
   1980   _dbus_assert (auth->mech != NULL);
   1981 
   1982   switch (command)
   1983     {
   1984     case DBUS_AUTH_COMMAND_DATA:
   1985       return process_data (auth, args, auth->mech->client_data_func);
   1986 
   1987     case DBUS_AUTH_COMMAND_REJECTED:
   1988       return process_rejected (auth, args);
   1989 
   1990     case DBUS_AUTH_COMMAND_OK:
   1991       return process_ok(auth, args);
   1992 
   1993     case DBUS_AUTH_COMMAND_ERROR:
   1994       return send_cancel (auth);
   1995 
   1996     case DBUS_AUTH_COMMAND_AUTH:
   1997     case DBUS_AUTH_COMMAND_CANCEL:
   1998     case DBUS_AUTH_COMMAND_BEGIN:
   1999     case DBUS_AUTH_COMMAND_UNKNOWN:
   2000     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2001     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2002     default:
   2003       return send_error (auth, "Unknown command");
   2004     }
   2005 }
   2006 
   2007 static dbus_bool_t
   2008 handle_client_state_waiting_for_ok (DBusAuth         *auth,
   2009                                     DBusAuthCommand   command,
   2010                                     const DBusString *args)
   2011 {
   2012   switch (command)
   2013     {
   2014     case DBUS_AUTH_COMMAND_REJECTED:
   2015       return process_rejected (auth, args);
   2016 
   2017     case DBUS_AUTH_COMMAND_OK:
   2018       return process_ok(auth, args);
   2019 
   2020     case DBUS_AUTH_COMMAND_DATA:
   2021     case DBUS_AUTH_COMMAND_ERROR:
   2022       return send_cancel (auth);
   2023 
   2024     case DBUS_AUTH_COMMAND_AUTH:
   2025     case DBUS_AUTH_COMMAND_CANCEL:
   2026     case DBUS_AUTH_COMMAND_BEGIN:
   2027     case DBUS_AUTH_COMMAND_UNKNOWN:
   2028     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2029     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2030     default:
   2031       return send_error (auth, "Unknown command");
   2032     }
   2033 }
   2034 
   2035 static dbus_bool_t
   2036 handle_client_state_waiting_for_reject (DBusAuth         *auth,
   2037                                         DBusAuthCommand   command,
   2038                                         const DBusString *args)
   2039 {
   2040   switch (command)
   2041     {
   2042     case DBUS_AUTH_COMMAND_REJECTED:
   2043       return process_rejected (auth, args);
   2044 
   2045     case DBUS_AUTH_COMMAND_AUTH:
   2046     case DBUS_AUTH_COMMAND_CANCEL:
   2047     case DBUS_AUTH_COMMAND_DATA:
   2048     case DBUS_AUTH_COMMAND_BEGIN:
   2049     case DBUS_AUTH_COMMAND_OK:
   2050     case DBUS_AUTH_COMMAND_ERROR:
   2051     case DBUS_AUTH_COMMAND_UNKNOWN:
   2052     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2053     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2054     default:
   2055       goto_state (auth, &common_state_need_disconnect);
   2056       return TRUE;
   2057     }
   2058 }
   2059 
   2060 static dbus_bool_t
   2061 handle_client_state_waiting_for_agree_unix_fd(DBusAuth         *auth,
   2062                                               DBusAuthCommand   command,
   2063                                               const DBusString *args)
   2064 {
   2065   switch (command)
   2066     {
   2067     case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
   2068       _dbus_assert(auth->unix_fd_possible);
   2069       auth->unix_fd_negotiated = TRUE;
   2070       _dbus_verbose("Successfully negotiated UNIX FD passing\n");
   2071       return send_begin (auth);
   2072 
   2073     case DBUS_AUTH_COMMAND_ERROR:
   2074       _dbus_assert(auth->unix_fd_possible);
   2075       auth->unix_fd_negotiated = FALSE;
   2076       _dbus_verbose("Failed to negotiate UNIX FD passing\n");
   2077       return send_begin (auth);
   2078 
   2079     case DBUS_AUTH_COMMAND_OK:
   2080     case DBUS_AUTH_COMMAND_DATA:
   2081     case DBUS_AUTH_COMMAND_REJECTED:
   2082     case DBUS_AUTH_COMMAND_AUTH:
   2083     case DBUS_AUTH_COMMAND_CANCEL:
   2084     case DBUS_AUTH_COMMAND_BEGIN:
   2085     case DBUS_AUTH_COMMAND_UNKNOWN:
   2086     case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
   2087     default:
   2088       return send_error (auth, "Unknown command");
   2089     }
   2090 }
   2091 
   2092 /**
   2093  * Mapping from command name to enum
   2094  */
   2095 typedef struct {
   2096   const char *name;        /**< Name of the command */
   2097   DBusAuthCommand command; /**< Corresponding enum */
   2098 } DBusAuthCommandName;
   2099 
   2100 static const DBusAuthCommandName auth_command_names[] = {
   2101   { "AUTH",              DBUS_AUTH_COMMAND_AUTH },
   2102   { "CANCEL",            DBUS_AUTH_COMMAND_CANCEL },
   2103   { "DATA",              DBUS_AUTH_COMMAND_DATA },
   2104   { "BEGIN",             DBUS_AUTH_COMMAND_BEGIN },
   2105   { "REJECTED",          DBUS_AUTH_COMMAND_REJECTED },
   2106   { "OK",                DBUS_AUTH_COMMAND_OK },
   2107   { "ERROR",             DBUS_AUTH_COMMAND_ERROR },
   2108   { "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD },
   2109   { "AGREE_UNIX_FD",     DBUS_AUTH_COMMAND_AGREE_UNIX_FD }
   2110 };
   2111 
   2112 static DBusAuthCommand
   2113 lookup_command_from_name (DBusString *command)
   2114 {
   2115   int i;
   2116 
   2117   for (i = 0; i < _DBUS_N_ELEMENTS (auth_command_names); i++)
   2118     {
   2119       if (_dbus_string_equal_c_str (command,
   2120                                     auth_command_names[i].name))
   2121         return auth_command_names[i].command;
   2122     }
   2123 
   2124   return DBUS_AUTH_COMMAND_UNKNOWN;
   2125 }
   2126 
   2127 static void
   2128 goto_state (DBusAuth *auth,
   2129             const DBusAuthStateData *state)
   2130 {
   2131   _dbus_verbose ("%s: going from state %s to state %s\n",
   2132                  DBUS_AUTH_NAME (auth),
   2133                  auth->state->name,
   2134                  state->name);
   2135 
   2136   auth->state = state;
   2137 }
   2138 
   2139 /* returns whether to call it again right away */
   2140 static dbus_bool_t
   2141 process_command (DBusAuth *auth)
   2142 {
   2143   DBusAuthCommand command;
   2144   DBusString line;
   2145   DBusString args;
   2146   int eol;
   2147   int i, j;
   2148   dbus_bool_t retval;
   2149 
   2150   /* _dbus_verbose ("%s:   trying process_command()\n"); */
   2151 
   2152   retval = FALSE;
   2153 
   2154   eol = 0;
   2155   if (!_dbus_string_find (&auth->incoming, 0, "\r\n", &eol))
   2156     return FALSE;
   2157 
   2158   if (!_dbus_string_init (&line))
   2159     {
   2160       auth->needed_memory = TRUE;
   2161       return FALSE;
   2162     }
   2163 
   2164   if (!_dbus_string_init (&args))
   2165     {
   2166       _dbus_string_free (&line);
   2167       auth->needed_memory = TRUE;
   2168       return FALSE;
   2169     }
   2170 
   2171   if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &line, 0))
   2172     goto out;
   2173 
   2174   if (!_dbus_string_validate_ascii (&line, 0,
   2175                                     _dbus_string_get_length (&line)))
   2176     {
   2177       _dbus_verbose ("%s: Command contained non-ASCII chars or embedded nul\n",
   2178                      DBUS_AUTH_NAME (auth));
   2179       if (!send_error (auth, "Command contained non-ASCII"))
   2180         goto out;
   2181       else
   2182         goto next_command;
   2183     }
   2184 
   2185   _dbus_verbose ("%s: got command \"%s\"\n",
   2186                  DBUS_AUTH_NAME (auth),
   2187                  _dbus_string_get_const_data (&line));
   2188 
   2189   _dbus_string_find_blank (&line, 0, &i);
   2190   _dbus_string_skip_blank (&line, i, &j);
   2191 
   2192   if (j > i)
   2193     _dbus_string_delete (&line, i, j - i);
   2194 
   2195   if (!_dbus_string_move (&line, i, &args, 0))
   2196     goto out;
   2197 
   2198   /* FIXME 1.0 we should probably validate that only the allowed
   2199    * chars are in the command name
   2200    */
   2201 
   2202   command = lookup_command_from_name (&line);
   2203   if (!(* auth->state->handler) (auth, command, &args))
   2204     goto out;
   2205 
   2206  next_command:
   2207 
   2208   /* We've succeeded in processing the whole command so drop it out
   2209    * of the incoming buffer and return TRUE to try another command.
   2210    */
   2211 
   2212   _dbus_string_delete (&auth->incoming, 0, eol);
   2213 
   2214   /* kill the \r\n */
   2215   _dbus_string_delete (&auth->incoming, 0, 2);
   2216 
   2217   retval = TRUE;
   2218 
   2219  out:
   2220   _dbus_string_free (&args);
   2221   _dbus_string_free (&line);
   2222 
   2223   if (!retval)
   2224     auth->needed_memory = TRUE;
   2225   else
   2226     auth->needed_memory = FALSE;
   2227 
   2228   return retval;
   2229 }
   2230 
   2231 
   2232 /** @} */
   2233 
   2234 /**
   2235  * @addtogroup DBusAuth
   2236  * @{
   2237  */
   2238 
   2239 /**
   2240  * Creates a new auth conversation object for the server side.
   2241  * See doc/dbus-sasl-profile.txt for full details on what
   2242  * this object does.
   2243  *
   2244  * @returns the new object or #NULL if no memory
   2245  */
   2246 DBusAuth*
   2247 _dbus_auth_server_new (const DBusString *guid)
   2248 {
   2249   DBusAuth *auth;
   2250   DBusAuthServer *server_auth;
   2251   DBusString guid_copy;
   2252 
   2253   if (!_dbus_string_init (&guid_copy))
   2254     return NULL;
   2255 
   2256   if (!_dbus_string_copy (guid, 0, &guid_copy, 0))
   2257     {
   2258       _dbus_string_free (&guid_copy);
   2259       return NULL;
   2260     }
   2261 
   2262   auth = _dbus_auth_new (sizeof (DBusAuthServer));
   2263   if (auth == NULL)
   2264     {
   2265       _dbus_string_free (&guid_copy);
   2266       return NULL;
   2267     }
   2268 
   2269   auth->side = auth_side_server;
   2270   auth->state = &server_state_waiting_for_auth;
   2271 
   2272   server_auth = DBUS_AUTH_SERVER (auth);
   2273 
   2274   server_auth->guid = guid_copy;
   2275 
   2276   /* perhaps this should be per-mechanism with a lower
   2277    * max
   2278    */
   2279   server_auth->failures = 0;
   2280   server_auth->max_failures = 6;
   2281 
   2282   return auth;
   2283 }
   2284 
   2285 /**
   2286  * Creates a new auth conversation object for the client side.
   2287  * See doc/dbus-sasl-profile.txt for full details on what
   2288  * this object does.
   2289  *
   2290  * @returns the new object or #NULL if no memory
   2291  */
   2292 DBusAuth*
   2293 _dbus_auth_client_new (void)
   2294 {
   2295   DBusAuth *auth;
   2296   DBusString guid_str;
   2297 
   2298   if (!_dbus_string_init (&guid_str))
   2299     return NULL;
   2300 
   2301   auth = _dbus_auth_new (sizeof (DBusAuthClient));
   2302   if (auth == NULL)
   2303     {
   2304       _dbus_string_free (&guid_str);
   2305       return NULL;
   2306     }
   2307 
   2308   DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str;
   2309 
   2310   auth->side = auth_side_client;
   2311   auth->state = &client_state_need_send_auth;
   2312 
   2313   /* Start the auth conversation by sending AUTH for our default
   2314    * mechanism */
   2315   if (!send_auth (auth, &all_mechanisms[0]))
   2316     {
   2317       _dbus_auth_unref (auth);
   2318       return NULL;
   2319     }
   2320 
   2321   return auth;
   2322 }
   2323 
   2324 /**
   2325  * Increments the refcount of an auth object.
   2326  *
   2327  * @param auth the auth conversation
   2328  * @returns the auth conversation
   2329  */
   2330 DBusAuth *
   2331 _dbus_auth_ref (DBusAuth *auth)
   2332 {
   2333   _dbus_assert (auth != NULL);
   2334 
   2335   auth->refcount += 1;
   2336 
   2337   return auth;
   2338 }
   2339 
   2340 /**
   2341  * Decrements the refcount of an auth object.
   2342  *
   2343  * @param auth the auth conversation
   2344  */
   2345 void
   2346 _dbus_auth_unref (DBusAuth *auth)
   2347 {
   2348   _dbus_assert (auth != NULL);
   2349   _dbus_assert (auth->refcount > 0);
   2350 
   2351   auth->refcount -= 1;
   2352   if (auth->refcount == 0)
   2353     {
   2354       shutdown_mech (auth);
   2355 
   2356       if (DBUS_AUTH_IS_CLIENT (auth))
   2357         {
   2358           _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
   2359           _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
   2360         }
   2361       else
   2362         {
   2363           _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
   2364 
   2365           _dbus_string_free (& DBUS_AUTH_SERVER (auth)->guid);
   2366         }
   2367 
   2368       if (auth->keyring)
   2369         _dbus_keyring_unref (auth->keyring);
   2370 
   2371       _dbus_string_free (&auth->context);
   2372       _dbus_string_free (&auth->challenge);
   2373       _dbus_string_free (&auth->identity);
   2374       _dbus_string_free (&auth->incoming);
   2375       _dbus_string_free (&auth->outgoing);
   2376 
   2377       dbus_free_string_array (auth->allowed_mechs);
   2378 
   2379       _dbus_credentials_unref (auth->credentials);
   2380       _dbus_credentials_unref (auth->authorized_identity);
   2381       _dbus_credentials_unref (auth->desired_identity);
   2382 
   2383       dbus_free (auth);
   2384     }
   2385 }
   2386 
   2387 /**
   2388  * Sets an array of authentication mechanism names
   2389  * that we are willing to use.
   2390  *
   2391  * @param auth the auth conversation
   2392  * @param mechanisms #NULL-terminated array of mechanism names
   2393  * @returns #FALSE if no memory
   2394  */
   2395 dbus_bool_t
   2396 _dbus_auth_set_mechanisms (DBusAuth    *auth,
   2397                            const char **mechanisms)
   2398 {
   2399   char **copy;
   2400 
   2401   if (mechanisms != NULL)
   2402     {
   2403       copy = _dbus_dup_string_array (mechanisms);
   2404       if (copy == NULL)
   2405         return FALSE;
   2406     }
   2407   else
   2408     copy = NULL;
   2409 
   2410   dbus_free_string_array (auth->allowed_mechs);
   2411 
   2412   auth->allowed_mechs = copy;
   2413 
   2414   return TRUE;
   2415 }
   2416 
   2417 /**
   2418  * @param auth the auth conversation object
   2419  * @returns #TRUE if we're in a final state
   2420  */
   2421 #define DBUS_AUTH_IN_END_STATE(auth) ((auth)->state->handler == NULL)
   2422 
   2423 /**
   2424  * Analyzes buffered input and moves the auth conversation forward,
   2425  * returning the new state of the auth conversation.
   2426  *
   2427  * @param auth the auth conversation
   2428  * @returns the new state
   2429  */
   2430 DBusAuthState
   2431 _dbus_auth_do_work (DBusAuth *auth)
   2432 {
   2433   auth->needed_memory = FALSE;
   2434 
   2435   /* Max amount we'll buffer up before deciding someone's on crack */
   2436 #define MAX_BUFFER (16 * _DBUS_ONE_KILOBYTE)
   2437 
   2438   do
   2439     {
   2440       if (DBUS_AUTH_IN_END_STATE (auth))
   2441         break;
   2442 
   2443       if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER ||
   2444           _dbus_string_get_length (&auth->outgoing) > MAX_BUFFER)
   2445         {
   2446           goto_state (auth, &common_state_need_disconnect);
   2447           _dbus_verbose ("%s: Disconnecting due to excessive data buffered in auth phase\n",
   2448                          DBUS_AUTH_NAME (auth));
   2449           break;
   2450         }
   2451     }
   2452   while (process_command (auth));
   2453 
   2454   if (auth->needed_memory)
   2455     return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
   2456   else if (_dbus_string_get_length (&auth->outgoing) > 0)
   2457     return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
   2458   else if (auth->state == &common_state_need_disconnect)
   2459     return DBUS_AUTH_STATE_NEED_DISCONNECT;
   2460   else if (auth->state == &common_state_authenticated)
   2461     return DBUS_AUTH_STATE_AUTHENTICATED;
   2462   else return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
   2463 }
   2464 
   2465 /**
   2466  * Gets bytes that need to be sent to the peer we're conversing with.
   2467  * After writing some bytes, _dbus_auth_bytes_sent() must be called
   2468  * to notify the auth object that they were written.
   2469  *
   2470  * @param auth the auth conversation
   2471  * @param str return location for a ref to the buffer to send
   2472  * @returns #FALSE if nothing to send
   2473  */
   2474 dbus_bool_t
   2475 _dbus_auth_get_bytes_to_send (DBusAuth          *auth,
   2476                               const DBusString **str)
   2477 {
   2478   _dbus_assert (auth != NULL);
   2479   _dbus_assert (str != NULL);
   2480 
   2481   *str = NULL;
   2482 
   2483   if (_dbus_string_get_length (&auth->outgoing) == 0)
   2484     return FALSE;
   2485 
   2486   *str = &auth->outgoing;
   2487 
   2488   return TRUE;
   2489 }
   2490 
   2491 /**
   2492  * Notifies the auth conversation object that
   2493  * the given number of bytes of the outgoing buffer
   2494  * have been written out.
   2495  *
   2496  * @param auth the auth conversation
   2497  * @param bytes_sent number of bytes written out
   2498  */
   2499 void
   2500 _dbus_auth_bytes_sent (DBusAuth *auth,
   2501                        int       bytes_sent)
   2502 {
   2503   _dbus_verbose ("%s: Sent %d bytes of: %s\n",
   2504                  DBUS_AUTH_NAME (auth),
   2505                  bytes_sent,
   2506                  _dbus_string_get_const_data (&auth->outgoing));
   2507 
   2508   _dbus_string_delete (&auth->outgoing,
   2509                        0, bytes_sent);
   2510 }
   2511 
   2512 /**
   2513  * Get a buffer to be used for reading bytes from the peer we're conversing
   2514  * with. Bytes should be appended to this buffer.
   2515  *
   2516  * @param auth the auth conversation
   2517  * @param buffer return location for buffer to append bytes to
   2518  */
   2519 void
   2520 _dbus_auth_get_buffer (DBusAuth     *auth,
   2521                        DBusString **buffer)
   2522 {
   2523   _dbus_assert (auth != NULL);
   2524   _dbus_assert (!auth->buffer_outstanding);
   2525 
   2526   *buffer = &auth->incoming;
   2527 
   2528   auth->buffer_outstanding = TRUE;
   2529 }
   2530 
   2531 /**
   2532  * Returns a buffer with new data read into it.
   2533  *
   2534  * @param auth the auth conversation
   2535  * @param buffer the buffer being returned
   2536  * @param bytes_read number of new bytes added
   2537  */
   2538 void
   2539 _dbus_auth_return_buffer (DBusAuth               *auth,
   2540                           DBusString             *buffer,
   2541                           int                     bytes_read)
   2542 {
   2543   _dbus_assert (buffer == &auth->incoming);
   2544   _dbus_assert (auth->buffer_outstanding);
   2545 
   2546   auth->buffer_outstanding = FALSE;
   2547 }
   2548 
   2549 /**
   2550  * Returns leftover bytes that were not used as part of the auth
   2551  * conversation.  These bytes will be part of the message stream
   2552  * instead. This function may not be called until authentication has
   2553  * succeeded.
   2554  *
   2555  * @param auth the auth conversation
   2556  * @param str return location for pointer to string of unused bytes
   2557  */
   2558 void
   2559 _dbus_auth_get_unused_bytes (DBusAuth           *auth,
   2560                              const DBusString **str)
   2561 {
   2562   if (!DBUS_AUTH_IN_END_STATE (auth))
   2563     return;
   2564 
   2565   *str = &auth->incoming;
   2566 }
   2567 
   2568 
   2569 /**
   2570  * Gets rid of unused bytes returned by _dbus_auth_get_unused_bytes()
   2571  * after we've gotten them and successfully moved them elsewhere.
   2572  *
   2573  * @param auth the auth conversation
   2574  */
   2575 void
   2576 _dbus_auth_delete_unused_bytes (DBusAuth *auth)
   2577 {
   2578   if (!DBUS_AUTH_IN_END_STATE (auth))
   2579     return;
   2580 
   2581   _dbus_string_set_length (&auth->incoming, 0);
   2582 }
   2583 
   2584 /**
   2585  * Called post-authentication, indicates whether we need to encode
   2586  * the message stream with _dbus_auth_encode_data() prior to
   2587  * sending it to the peer.
   2588  *
   2589  * @param auth the auth conversation
   2590  * @returns #TRUE if we need to encode the stream
   2591  */
   2592 dbus_bool_t
   2593 _dbus_auth_needs_encoding (DBusAuth *auth)
   2594 {
   2595   if (auth->state != &common_state_authenticated)
   2596     return FALSE;
   2597 
   2598   if (auth->mech != NULL)
   2599     {
   2600       if (DBUS_AUTH_IS_CLIENT (auth))
   2601         return auth->mech->client_encode_func != NULL;
   2602       else
   2603         return auth->mech->server_encode_func != NULL;
   2604     }
   2605   else
   2606     return FALSE;
   2607 }
   2608 
   2609 /**
   2610  * Called post-authentication, encodes a block of bytes for sending to
   2611  * the peer. If no encoding was negotiated, just copies the bytes
   2612  * (you can avoid this by checking _dbus_auth_needs_encoding()).
   2613  *
   2614  * @param auth the auth conversation
   2615  * @param plaintext the plain text data
   2616  * @param encoded initialized string to where encoded data is appended
   2617  * @returns #TRUE if we had enough memory and successfully encoded
   2618  */
   2619 dbus_bool_t
   2620 _dbus_auth_encode_data (DBusAuth         *auth,
   2621                         const DBusString *plaintext,
   2622                         DBusString       *encoded)
   2623 {
   2624   _dbus_assert (plaintext != encoded);
   2625 
   2626   if (auth->state != &common_state_authenticated)
   2627     return FALSE;
   2628 
   2629   if (_dbus_auth_needs_encoding (auth))
   2630     {
   2631       if (DBUS_AUTH_IS_CLIENT (auth))
   2632         return (* auth->mech->client_encode_func) (auth, plaintext, encoded);
   2633       else
   2634         return (* auth->mech->server_encode_func) (auth, plaintext, encoded);
   2635     }
   2636   else
   2637     {
   2638       return _dbus_string_copy (plaintext, 0, encoded,
   2639                                 _dbus_string_get_length (encoded));
   2640     }
   2641 }
   2642 
   2643 /**
   2644  * Called post-authentication, indicates whether we need to decode
   2645  * the message stream with _dbus_auth_decode_data() after
   2646  * receiving it from the peer.
   2647  *
   2648  * @param auth the auth conversation
   2649  * @returns #TRUE if we need to encode the stream
   2650  */
   2651 dbus_bool_t
   2652 _dbus_auth_needs_decoding (DBusAuth *auth)
   2653 {
   2654   if (auth->state != &common_state_authenticated)
   2655     return FALSE;
   2656 
   2657   if (auth->mech != NULL)
   2658     {
   2659       if (DBUS_AUTH_IS_CLIENT (auth))
   2660         return auth->mech->client_decode_func != NULL;
   2661       else
   2662         return auth->mech->server_decode_func != NULL;
   2663     }
   2664   else
   2665     return FALSE;
   2666 }
   2667 
   2668 
   2669 /**
   2670  * Called post-authentication, decodes a block of bytes received from
   2671  * the peer. If no encoding was negotiated, just copies the bytes (you
   2672  * can avoid this by checking _dbus_auth_needs_decoding()).
   2673  *
   2674  * @todo 1.0? We need to be able to distinguish "out of memory" error
   2675  * from "the data is hosed" error.
   2676  *
   2677  * @param auth the auth conversation
   2678  * @param encoded the encoded data
   2679  * @param plaintext initialized string where decoded data is appended
   2680  * @returns #TRUE if we had enough memory and successfully decoded
   2681  */
   2682 dbus_bool_t
   2683 _dbus_auth_decode_data (DBusAuth         *auth,
   2684                         const DBusString *encoded,
   2685                         DBusString       *plaintext)
   2686 {
   2687   _dbus_assert (plaintext != encoded);
   2688 
   2689   if (auth->state != &common_state_authenticated)
   2690     return FALSE;
   2691 
   2692   if (_dbus_auth_needs_decoding (auth))
   2693     {
   2694       if (DBUS_AUTH_IS_CLIENT (auth))
   2695         return (* auth->mech->client_decode_func) (auth, encoded, plaintext);
   2696       else
   2697         return (* auth->mech->server_decode_func) (auth, encoded, plaintext);
   2698     }
   2699   else
   2700     {
   2701       return _dbus_string_copy (encoded, 0, plaintext,
   2702                                 _dbus_string_get_length (plaintext));
   2703     }
   2704 }
   2705 
   2706 /**
   2707  * Sets credentials received via reliable means from the operating
   2708  * system.
   2709  *
   2710  * @param auth the auth conversation
   2711  * @param credentials the credentials received
   2712  * @returns #FALSE on OOM
   2713  */
   2714 dbus_bool_t
   2715 _dbus_auth_set_credentials (DBusAuth               *auth,
   2716                             DBusCredentials        *credentials)
   2717 {
   2718   _dbus_credentials_clear (auth->credentials);
   2719   return _dbus_credentials_add_credentials (auth->credentials,
   2720                                             credentials);
   2721 }
   2722 
   2723 /**
   2724  * Gets the identity we authorized the client as.  Apps may have
   2725  * different policies as to what identities they allow.
   2726  *
   2727  * Returned credentials are not a copy and should not be modified
   2728  *
   2729  * @param auth the auth conversation
   2730  * @returns the credentials we've authorized BY REFERENCE do not modify
   2731  */
   2732 DBusCredentials*
   2733 _dbus_auth_get_identity (DBusAuth               *auth)
   2734 {
   2735   if (auth->state == &common_state_authenticated)
   2736     {
   2737       return auth->authorized_identity;
   2738     }
   2739   else
   2740     {
   2741       /* FIXME instead of this, keep an empty credential around that
   2742        * doesn't require allocation or something
   2743        */
   2744       /* return empty credentials */
   2745       _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity));
   2746       return auth->authorized_identity;
   2747     }
   2748 }
   2749 
   2750 /**
   2751  * Gets the GUID from the server if we've authenticated; gets
   2752  * #NULL otherwise.
   2753  * @param auth the auth object
   2754  * @returns the GUID in ASCII hex format
   2755  */
   2756 const char*
   2757 _dbus_auth_get_guid_from_server (DBusAuth *auth)
   2758 {
   2759   _dbus_assert (DBUS_AUTH_IS_CLIENT (auth));
   2760 
   2761   if (auth->state == &common_state_authenticated)
   2762     return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
   2763   else
   2764     return NULL;
   2765 }
   2766 
   2767 /**
   2768  * Sets the "authentication context" which scopes cookies
   2769  * with the DBUS_COOKIE_SHA1 auth mechanism for example.
   2770  *
   2771  * @param auth the auth conversation
   2772  * @param context the context
   2773  * @returns #FALSE if no memory
   2774  */
   2775 dbus_bool_t
   2776 _dbus_auth_set_context (DBusAuth               *auth,
   2777                         const DBusString       *context)
   2778 {
   2779   return _dbus_string_replace_len (context, 0, _dbus_string_get_length (context),
   2780                                    &auth->context, 0, _dbus_string_get_length (context));
   2781 }
   2782 
   2783 /**
   2784  * Sets whether unix fd passing is potentially on the transport and
   2785  * hence shall be negotiated.
   2786  *
   2787  * @param auth the auth conversation
   2788  * @param b TRUE when unix fd passing shall be negotiated, otherwise FALSE
   2789  */
   2790 void
   2791 _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b)
   2792 {
   2793   auth->unix_fd_possible = b;
   2794 }
   2795 
   2796 /**
   2797  * Queries whether unix fd passing was successfully negotiated.
   2798  *
   2799  * @param auth the auth conversion
   2800  * @returns #TRUE when unix fd passing was negotiated.
   2801  */
   2802 dbus_bool_t
   2803 _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth)
   2804 {
   2805   return auth->unix_fd_negotiated;
   2806 }
   2807 
   2808 /** @} */
   2809 
   2810 /* tests in dbus-auth-util.c */
   2811