dbus-auth.c revision 9f1a60dbba69844c0a04b3dd86280352736187ce
1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/* -*- mode: C; c-file-style: "gnu" -*- */ 2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/* dbus-auth.c Authentication 3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * 4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Copyright (C) 2002, 2003 Red Hat Inc. 5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * 6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * Licensed under the Academic Free License version 1.2 7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * 8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * This program is free software; you can redistribute it and/or modify 9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * it under the terms of the GNU General Public License as published by 10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * the Free Software Foundation; either version 2 of the License, or 11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * (at your option) any later version. 12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * 13ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * This program is distributed in the hope that it will be useful, 14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * GNU General Public License for more details. 17da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 18da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * You should have received a copy of the GNU General Public License 195ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * along with this program; if not, write to the Free Software 201184aebb761cbeac9124c37189a80a1a58f04b6bhkuang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 211184aebb761cbeac9124c37189a80a1a58f04b6bhkuang * 225ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include "dbus-auth.h" 24da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#include "dbus-string.h" 25da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#include "dbus-list.h" 262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include "dbus-internals.h" 27da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#include "dbus-keyring.h" 28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "dbus-sha.h" 29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "dbus-userdb.h" 30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 31ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/** 32da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @defgroup DBusAuth Authentication 33da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @ingroup DBusInternals 34da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @brief DBusAuth object 35da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 36da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * DBusAuth manages the authentication negotiation when a connection 37da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * is first established, and also manage any encryption used over a 38da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * connection. 39da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 40da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @todo some SASL profiles require sending the empty string as a 41da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * challenge/response, but we don't currently allow that in our 42ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian * protocol. 43da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 44ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian * @todo DBusAuth really needs to be rewritten as an explicit state 455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * machine. Right now it's too hard to prove to yourself by inspection 46da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * that it works. 47da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 48da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @todo right now sometimes both ends will block waiting for input 49da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * from the other end, e.g. if there's an error during 50da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * DBUS_COOKIE_SHA1. 51da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 52da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @todo the cookie keyring needs to be cached globally not just 53da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * per-auth (which raises threadsafety issues too) 54da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 55da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @todo grep FIXME in dbus-auth.c 56da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 57da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 58da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 59da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @defgroup DBusAuthInternals Authentication implementation details 60da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @ingroup DBusInternals 61da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @brief DBusAuth implementation details 62da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 63da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Private details of authentication code. 64da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * 65da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @{ 66da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 67da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 68da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 69da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Processes a command. Returns whether we had enough memory to 70da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * complete the operation. 71da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 72da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniantypedef dbus_bool_t (* DBusProcessAuthCommandFunction) (DBusAuth *auth, 73da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *command, 74da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *args); 75da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 76da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 77da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Handler for a given auth protocol command 78da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 79da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniantypedef struct 80da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 81da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const char *command; /**< Name of the command */ 82da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusProcessAuthCommandFunction func; /**< Function to handle the command */ 83da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian} DBusAuthCommandHandler; 842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian 85da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 86da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * This function appends an initial client response to the given string 8791037db265ecdd914a26e056cf69207b4f50924ehkuang */ 885ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangtypedef dbus_bool_t (* DBusInitialResponseFunction) (DBusAuth *auth, 89da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString *response); 902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian 9191037db265ecdd914a26e056cf69207b4f50924ehkuang/** 9291037db265ecdd914a26e056cf69207b4f50924ehkuang * This function processes a block of data received from the peer. 93da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * i.e. handles a DATA command. 94da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 95da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniantypedef dbus_bool_t (* DBusAuthDataFunction) (DBusAuth *auth, 96da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *data); 97da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 98da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 99da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * This function encodes a block of data from the peer. 100da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 101da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniantypedef dbus_bool_t (* DBusAuthEncodeFunction) (DBusAuth *auth, 102da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *data, 103da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString *encoded); 104da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 105da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 106da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * This function decodes a block of data from the peer. 107da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 108da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniantypedef dbus_bool_t (* DBusAuthDecodeFunction) (DBusAuth *auth, 109da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *data, 110da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString *decoded); 111da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 112da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 113da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * This function is called when the mechanism is abandoned. 114da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 115da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniantypedef void (* DBusAuthShutdownFunction) (DBusAuth *auth); 116da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 117da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 118da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Virtual table representing a particular auth mechanism. 119da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 120da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniantypedef struct 121da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 122da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const char *mechanism; /**< Name of the mechanism */ 123da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthDataFunction server_data_func; /**< Function on server side for DATA */ 124da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthEncodeFunction server_encode_func; /**< Function on server side to encode */ 125da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthDecodeFunction server_decode_func; /**< Function on server side to decode */ 126da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthShutdownFunction server_shutdown_func; /**< Function on server side to shut down */ 127da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusInitialResponseFunction client_initial_response_func; /**< Function on client side to handle initial response */ 128da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthDataFunction client_data_func; /**< Function on client side for DATA */ 129da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthEncodeFunction client_encode_func; /**< Function on client side for encode */ 130da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthDecodeFunction client_decode_func; /**< Function on client side for decode */ 131da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusAuthShutdownFunction client_shutdown_func; /**< Function on client side for shutdown */ 132da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian} DBusAuthMechanismHandler; 133da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 134da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 135da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Internal members of DBusAuth. 136da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 1375ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstruct DBusAuth 13891037db265ecdd914a26e056cf69207b4f50924ehkuang{ 1395ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang int refcount; /**< reference count */ 14091037db265ecdd914a26e056cf69207b4f50924ehkuang 14191037db265ecdd914a26e056cf69207b4f50924ehkuang DBusString incoming; /**< Incoming data buffer */ 142da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString outgoing; /**< Outgoing data buffer */ 143da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 14491037db265ecdd914a26e056cf69207b4f50924ehkuang const DBusAuthCommandHandler *handlers; /**< Handlers for commands */ 1455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 1465ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusAuthMechanismHandler *mech; /**< Current auth mechanism */ 147da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 148da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString identity; /**< Current identity we're authorizing 1495ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * as. 1505ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 1525ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusCredentials credentials; /**< Credentials read from socket, 153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * fields may be -1 1545ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 1555ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 1565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusCredentials authorized_identity; /**< Credentials that are authorized */ 157da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 158da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusCredentials desired_identity; /**< Identity client has requested */ 159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian 1605ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusString context; /**< Cookie scope */ 161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang DBusKeyring *keyring; /**< Keyring for cookie mechanism. */ 1625ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang int cookie_id; /**< ID of cookie to use */ 1635ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusString challenge; /**< Challenge sent to client */ 1645ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 1655ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang char **allowed_mechs; /**< Mechanisms we're allowed to use, 1665ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * or #NULL if we can use any 1675ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 1685ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang unsigned int needed_memory : 1; /**< We needed memory to continue since last 170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * successful getting something done 1715ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 172da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian unsigned int need_disconnect : 1; /**< We've given up, time to disconnect */ 173da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian unsigned int authenticated : 1; /**< We are authenticated */ 1745ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang unsigned int authenticated_pending_output : 1; /**< Authenticated once we clear outgoing buffer */ 1755ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang unsigned int authenticated_pending_begin : 1; /**< Authenticated once we get BEGIN */ 1765ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang unsigned int already_got_mechanisms : 1; /**< Client already got mech list */ 1775ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */ 1785ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */ 1795ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang}; 180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/** 1825ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * "Subclass" of DBusAuth for client side 183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */ 1845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangtypedef struct 185da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 1865ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusAuth base; /**< Parent class */ 187da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 188da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusList *mechs_to_try; /**< Mechanisms we got from the server that we're going to try using */ 189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian 1905ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang} DBusAuthClient; 191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 1925ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/** 1935ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * "Subclass" of DBusAuth for server side. 1945ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 1955ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangtypedef struct 1965ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang{ 1975ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusAuth base; /**< Parent class */ 1985ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 199ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int failures; /**< Number of times client has been rejected */ 200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int max_failures; /**< Number of times we reject before disconnect */ 2015ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 202da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian} DBusAuthServer; 203da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 204da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t process_auth (DBusAuth *auth, 2055ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *command, 2065ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *args); 2075ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic dbus_bool_t process_cancel (DBusAuth *auth, 2085ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *command, 2095ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *args); 210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic dbus_bool_t process_begin (DBusAuth *auth, 211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const DBusString *command, 212ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const DBusString *args); 2135ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic dbus_bool_t process_data_server (DBusAuth *auth, 2145ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *command, 2155ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *args); 2165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic dbus_bool_t process_error_server (DBusAuth *auth, 2175ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *command, 218da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *args); 219da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t process_rejected (DBusAuth *auth, 220da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *command, 221da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *args); 222da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t process_ok (DBusAuth *auth, 223da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *command, 224da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *args); 225da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t process_data_client (DBusAuth *auth, 226ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const DBusString *command, 2275ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *args); 228da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t process_error_client (DBusAuth *auth, 2295ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *command, 230da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *args); 231da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 232da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 233da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t client_try_next_mechanism (DBusAuth *auth); 234da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t send_rejected (DBusAuth *auth); 235da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 236da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic DBusAuthCommandHandler 237da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianserver_handlers[] = { 238da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { "AUTH", process_auth }, 239da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { "CANCEL", process_cancel }, 240da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { "BEGIN", process_begin }, 2415ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { "DATA", process_data_server }, 242ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang { "ERROR", process_error_server }, 243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian { NULL, NULL } 2445ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang}; 2455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 2465ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic DBusAuthCommandHandler 2475ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangclient_handlers[] = { 2485ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { "REJECTED", process_rejected }, 2495ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { "OK", process_ok }, 2505ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { "DATA", process_data_client }, 2515ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { "ERROR", process_error_client }, 2525ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { NULL, NULL } 2535ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang}; 2545ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 2555ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/** 256da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @param auth the auth conversation 257da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @returns #TRUE if the conversation is the server side 258da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 259da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#define DBUS_AUTH_IS_SERVER(auth) ((auth)->handlers == server_handlers) 260da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 261da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @param auth the auth conversation 262da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @returns #TRUE if the conversation is the client side 263da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 264da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#define DBUS_AUTH_IS_CLIENT(auth) ((auth)->handlers == client_handlers) 2655ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/** 2665ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * @param auth the auth conversation 267da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @returns auth cast to DBusAuthClient 268da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 269da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#define DBUS_AUTH_CLIENT(auth) ((DBusAuthClient*)(auth)) 270da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** 2715ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * @param auth the auth conversation 272da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * @returns auth cast to DBusAuthServer 2735ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 2745ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#define DBUS_AUTH_SERVER(auth) ((DBusAuthServer*)(auth)) 2755ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 2765ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang/** 2775ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * The name of the auth ("client" or "server") 278ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * @param auth the auth conversation 279ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * @returns a string 280da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 2815ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#define DBUS_AUTH_NAME(auth) (DBUS_AUTH_IS_SERVER(auth) ? "server" : "client") 2825ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 283ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic DBusAuth* 284da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian_dbus_auth_new (int size) 2855ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang{ 2865ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusAuth *auth; 2875ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 288ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang auth = dbus_malloc0 (size); 2895ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (auth == NULL) 2905ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang return NULL; 2915ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 2925ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang auth->refcount = 1; 293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian 2945ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_credentials_clear (&auth->credentials); 295da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_credentials_clear (&auth->authorized_identity); 296da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_credentials_clear (&auth->desired_identity); 297da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 298da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->keyring = NULL; 299da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->cookie_id = -1; 300da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 301da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* note that we don't use the max string length feature, 302da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * because you can't use that feature if you're going to 303da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * try to recover from out-of-memory (it creates 304ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * what looks like unrecoverable inability to alloc 3055ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * more space in the string). But we do handle 306da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * overlong buffers in _dbus_auth_do_work(). 3075ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 308da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 309da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&auth->incoming)) 310da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto enomem_0; 311da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 312da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&auth->outgoing)) 313da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto enomem_1; 314da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 315da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&auth->identity)) 316da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto enomem_2; 317da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 318da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&auth->context)) 319da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto enomem_3; 320da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 321ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian if (!_dbus_string_init (&auth->challenge)) 322da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto enomem_4; 323da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 324da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* default context if none is specified */ 325da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_append (&auth->context, "org_freedesktop_general")) 326da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto enomem_5; 327da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 328da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return auth; 329da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 330da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian enomem_5: 331da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&auth->challenge); 332da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian enomem_4: 333da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&auth->context); 334ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian enomem_3: 3355ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_string_free (&auth->identity); 336ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang enomem_2: 337ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian _dbus_string_free (&auth->outgoing); 3385ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang enomem_1: 339ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian _dbus_string_free (&auth->incoming); 340ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian enomem_0: 341da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_free (auth); 342da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return NULL; 343da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian} 344da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 345da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic void 346da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianshutdown_mech (DBusAuth *auth) 347da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 348da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* Cancel any auth */ 349da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->authenticated_pending_begin = FALSE; 3505ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang auth->authenticated = FALSE; 3515ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang auth->already_asked_for_initial_response = FALSE; 352da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_set_length (&auth->identity, 0); 353da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 354da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_credentials_clear (&auth->authorized_identity); 355da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_credentials_clear (&auth->desired_identity); 3565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 357da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (auth->mech != NULL) 3585ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { 3595ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_verbose ("%s: Shutting down mechanism %s\n", 3605ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBUS_AUTH_NAME (auth), auth->mech->mechanism); 3615ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 362ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian if (DBUS_AUTH_IS_CLIENT (auth)) 363ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian (* auth->mech->client_shutdown_func) (auth); 364ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian else 3655ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang (* auth->mech->server_shutdown_func) (auth); 3665ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 367da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->mech = NULL; 3685ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang } 3695ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang} 3705ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 371da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/* Returns TRUE but with an empty string hash if the 3725ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * cookie_id isn't known. As with all this code 3735ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * TRUE just means we had enough memory. 374ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian */ 375ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic dbus_bool_t 376ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramaniansha1_compute_hash (DBusAuth *auth, 377ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian int cookie_id, 378ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang const DBusString *server_challenge, 3795ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *client_challenge, 380ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang DBusString *hash) 381da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 382da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString cookie; 383da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString to_hash; 384da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_bool_t retval; 385da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 386da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_assert (auth->keyring != NULL); 387da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 388da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = FALSE; 389da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 390da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&cookie)) 391da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return FALSE; 392da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 393da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_keyring_get_hex_key (auth->keyring, cookie_id, 394da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &cookie)) 395da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_0; 396da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 397da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (_dbus_string_get_length (&cookie) == 0) 398da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 399da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 400da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_0; 401da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 402da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 403da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&to_hash)) 404da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_0; 405da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 406da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_copy (server_challenge, 0, 407da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &to_hash, _dbus_string_get_length (&to_hash))) 408da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 409da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 410da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_append (&to_hash, ":")) 411da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 412da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 413da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_copy (client_challenge, 0, 414da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &to_hash, _dbus_string_get_length (&to_hash))) 415da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 416da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 417da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_append (&to_hash, ":")) 418da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 419da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 420da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_copy (&cookie, 0, 421da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &to_hash, _dbus_string_get_length (&to_hash))) 422da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 423da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 424da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_sha_compute (&to_hash, hash)) 425da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 426da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 427da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 428da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 429da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian out_1: 430da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_zero (&to_hash); 431da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&to_hash); 432da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian out_0: 433da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_zero (&cookie); 434da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&cookie); 435da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return retval; 436da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian} 437da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 438da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/** http://www.ietf.org/rfc/rfc2831.txt suggests at least 64 bits of 439da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * entropy, we use 128. This is the number of bytes in the random 440da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * challenge. 441da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 442da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#define N_CHALLENGE_BYTES (128/8) 443da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 444da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t 445da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramaniansha1_handle_first_client_response (DBusAuth *auth, 446da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *data) 447da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 448da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* We haven't sent a challenge yet, we're expecting a desired 449da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * username from the client. 450da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 451da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString tmp; 452da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString tmp2; 453da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_bool_t retval; 454da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian int old_len; 455da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusError error; 456da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 457da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = FALSE; 458da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 459da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_set_length (&auth->challenge, 0); 460da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 461da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (_dbus_string_get_length (data) > 0) 462da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 463da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (_dbus_string_get_length (&auth->identity) > 0) 464da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 465da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* Tried to send two auth identities, wtf */ 466da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n", 467da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBUS_AUTH_NAME (auth)); 468da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return send_rejected (auth); 469da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 470da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian else 471da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 472da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* this is our auth identity */ 473da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_copy (data, 0, &auth->identity, 0)) 474da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return FALSE; 475da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 476da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 477da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 478da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_credentials_from_username (data, &auth->desired_identity)) 479da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 480da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_verbose ("%s: Did not get a valid username from client\n", 481da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBUS_AUTH_NAME (auth)); 482da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return send_rejected (auth); 483da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 484da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 485da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&tmp)) 486da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return FALSE; 487da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 488da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&tmp2)) 489da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 490da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&tmp); 491da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return FALSE; 492da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 493da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 494da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian old_len = _dbus_string_get_length (&auth->outgoing); 495da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 496da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* we cache the keyring for speed, so here we drop it if it's the 497da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * wrong one. FIXME caching the keyring here is useless since we use 498da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * a different DBusAuth for every connection. 499da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 500da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (auth->keyring && 501da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian !_dbus_keyring_is_for_user (auth->keyring, 502da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian data)) 503da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 504da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_keyring_unref (auth->keyring); 505da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->keyring = NULL; 506da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 507da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 508da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (auth->keyring == NULL) 509da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 510da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusError error; 511da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 512da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_error_init (&error); 513da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->keyring = _dbus_keyring_new_homedir (data, 514da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &auth->context, 515da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &error); 516da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 517da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (auth->keyring == NULL) 518da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 519da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (dbus_error_has_name (&error, 520da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBUS_ERROR_NO_MEMORY)) 521da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 522da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_error_free (&error); 523da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out; 5245ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang } 5255ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang else 526ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian { 527da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _DBUS_ASSERT_ERROR_IS_SET (&error); 528da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_verbose ("%s: Error loading keyring: %s\n", 5295ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBUS_AUTH_NAME (auth), error.message); 530ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (send_rejected (auth)) 5312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian retval = TRUE; /* retval is only about mem */ 5322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian dbus_error_free (&error); 533ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian goto out; 5345ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang } 5355ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang } 5365ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang else 5375ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { 5385ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_assert (!dbus_error_is_set (&error)); 5395ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang } 5405ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang } 5415ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5425ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_assert (auth->keyring != NULL); 543da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 544da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_error_init (&error); 5455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang auth->cookie_id = _dbus_keyring_get_best_key (auth->keyring, &error); 5465ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (auth->cookie_id < 0) 5475ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang { 5485ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _DBUS_ASSERT_ERROR_IS_SET (&error); 5495ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_verbose ("%s: Could not get a cookie ID to send to client: %s\n", 550da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBUS_AUTH_NAME (auth), error.message); 5515ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (send_rejected (auth)) 5525ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang retval = TRUE; 553da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_error_free (&error); 5545ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang goto out; 555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 5565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang else 557ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian { 558ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian _dbus_assert (!dbus_error_is_set (&error)); 5595ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang } 5605ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5615ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (!_dbus_string_copy (&auth->context, 0, 5625ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang &tmp2, _dbus_string_get_length (&tmp2))) 56391037db265ecdd914a26e056cf69207b4f50924ehkuang goto out; 564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 5655ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (!_dbus_string_append (&tmp2, " ")) 5665ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang goto out; 5675ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5685ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (!_dbus_string_append_int (&tmp2, auth->cookie_id)) 5695ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang goto out; 5705ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5715ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (!_dbus_string_append (&tmp2, " ")) 5725ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang goto out; 573da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 574da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES)) 575da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out; 576da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 577da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_set_length (&auth->challenge, 0); 578da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_hex_encode (&tmp, 0, &auth->challenge, 0)) 579da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out; 580da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 5812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian if (!_dbus_string_hex_encode (&tmp, 0, &tmp2, 5822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian _dbus_string_get_length (&tmp2))) 583ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian goto out; 5845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5855ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (!_dbus_string_append (&auth->outgoing, 5865ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang "DATA ")) 5875ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang goto out; 5885ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5895ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (!_dbus_string_base64_encode (&tmp2, 0, &auth->outgoing, 5905ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_string_get_length (&auth->outgoing))) 5915ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang goto out; 5925ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 593da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_append (&auth->outgoing, 594da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian "\r\n")) 5955ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang goto out; 5965ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5975ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang retval = TRUE; 5985ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 5995ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang out: 600da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_zero (&tmp); 6015ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_string_free (&tmp); 6025ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_string_zero (&tmp2); 603da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&tmp2); 6045ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (!retval) 6055ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_string_set_length (&auth->outgoing, old_len); 6065ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang return retval; 607ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian} 608ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian 6095ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic dbus_bool_t 6105ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangsha1_handle_second_client_response (DBusAuth *auth, 6115ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang const DBusString *data) 6125ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang{ 6135ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang /* We are expecting a response which is the hex-encoded client 6145ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * challenge, space, then SHA-1 hash of the concatenation of our 6155ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * challenge, ":", client challenge, ":", secret key, all 6165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang * hex-encoded. 6175ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang */ 6185ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang int i; 6195ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusString client_challenge; 6205ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusString client_hash; 6215ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang dbus_bool_t retval; 6225ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBusString correct_hash; 623da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 624da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = FALSE; 625da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 626da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_find_blank (data, 0, &i)) 627da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 628da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_verbose ("%s: no space separator in client response\n", 629da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBUS_AUTH_NAME (auth)); 630da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return send_rejected (auth); 631da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 632da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 633da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&client_challenge)) 634da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_0; 635da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 636da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&client_hash)) 637da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 638da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 639da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_copy_len (data, 0, i, &client_challenge, 640da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 0)) 641da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_2; 642da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 643da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_skip_blank (data, i, &i); 644da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 645da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_copy_len (data, i, 646da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_get_length (data) - i, 647da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &client_hash, 648da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 0)) 649da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_2; 650da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 651da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (_dbus_string_get_length (&client_challenge) == 0 || 652da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_get_length (&client_hash) == 0) 653da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 654da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_verbose ("%s: zero-length client challenge or hash\n", 6555ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBUS_AUTH_NAME (auth)); 6565ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang if (send_rejected (auth)) 657da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 658da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_2; 659da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 660da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 661da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&correct_hash)) 662da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_2; 663da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 664da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!sha1_compute_hash (auth, auth->cookie_id, 6655ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang &auth->challenge, 6665ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang &client_challenge, 6675ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang &correct_hash)) 668da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_3; 669da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 670da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* if cookie_id was invalid, then we get an empty hash */ 671da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (_dbus_string_get_length (&correct_hash) == 0) 672da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 673da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (send_rejected (auth)) 674da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 675da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_3; 676da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 677da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 678da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_equal (&client_hash, &correct_hash)) 679da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 680da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (send_rejected (auth)) 681da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 682da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_3; 683da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 684da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 685da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_append (&auth->outgoing, 686da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian "OK\r\n")) 687da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_3; 6885ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 6895ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT" using DBUS_COOKIE_SHA1\n", 6905ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang DBUS_AUTH_NAME (auth), auth->desired_identity.uid); 691da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 692da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->authorized_identity = auth->desired_identity; 693da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian auth->authenticated_pending_begin = TRUE; 694da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 695da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 6962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian out_3: 697da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_zero (&correct_hash); 6982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian _dbus_string_free (&correct_hash); 6992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian out_2: 7002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian _dbus_string_zero (&client_hash); 701da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&client_hash); 702da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian out_1: 703da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_free (&client_challenge); 704da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian out_0: 705da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return retval; 7062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian} 707da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 7082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianstatic dbus_bool_t 709da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianhandle_server_data_cookie_sha1_mech (DBusAuth *auth, 710da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *data) 711da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 712da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (auth->cookie_id < 0) 713da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return sha1_handle_first_client_response (auth, data); 7145ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang else 715da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return sha1_handle_second_client_response (auth, data); 7165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang} 7175ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang 7185ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic void 719da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianhandle_server_shutdown_cookie_sha1_mech (DBusAuth *auth) 720da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 7215ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang auth->cookie_id = -1; 7225ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang _dbus_string_set_length (&auth->challenge, 0); 7235ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang} 724da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 725da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t 726da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianhandle_client_initial_response_cookie_sha1_mech (DBusAuth *auth, 727da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString *response) 728da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 729da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *username; 730da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_bool_t retval; 731da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 732da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = FALSE; 733da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 734da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_username_from_current_process (&username)) 735da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_0; 736da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 737da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_base64_encode (username, 0, 738da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian response, 739da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_get_length (response))) 740da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_0; 741da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 742da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 743ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian 744da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian out_0: 745da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian return retval; 746da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian} 747da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 748da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianstatic dbus_bool_t 749da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianhandle_client_data_cookie_sha1_mech (DBusAuth *auth, 750da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian const DBusString *data) 751da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian{ 752da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian /* The data we get from the server should be the cookie context 753da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * name, the cookie ID, and the server challenge, separated by 754da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * spaces. We send back our challenge string and the correct hash. 755da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */ 756da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian dbus_bool_t retval; 757da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString context; 758da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString cookie_id_str; 759da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString server_challenge; 760da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString client_challenge; 761da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString correct_hash; 762da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian DBusString tmp; 763da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian int i, j; 764da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian long val; 765da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian int old_len; 766da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 767da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = FALSE; 768da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 769ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian if (!_dbus_string_find_blank (data, 0, &i)) 770ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian { 771ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian if (_dbus_string_append (&auth->outgoing, 772da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian "ERROR \"Server did not send context/ID/challenge properly\"\r\n")) 773da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian retval = TRUE; 774ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian goto out_0; 775da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian } 776da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 777da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_init (&context)) 778da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_0; 779da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 780da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_copy_len (data, 0, i, 781da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian &context, 0)) 782da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian goto out_1; 783da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian 784da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian _dbus_string_skip_blank (data, i, &i); 785da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (!_dbus_string_find_blank (data, i, &j)) 786da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian { 787da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian if (_dbus_string_append (&auth->outgoing, 788da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian "ERROR \"Server did not send context/ID/challenge properly\"\r\n")) 789ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang retval = TRUE; 790 goto out_1; 791 } 792 793 if (!_dbus_string_init (&cookie_id_str)) 794 goto out_1; 795 796 if (!_dbus_string_copy_len (data, i, j - i, 797 &cookie_id_str, 0)) 798 goto out_2; 799 800 if (!_dbus_string_init (&server_challenge)) 801 goto out_2; 802 803 i = j; 804 _dbus_string_skip_blank (data, i, &i); 805 j = _dbus_string_get_length (data); 806 807 if (!_dbus_string_copy_len (data, i, j - i, 808 &server_challenge, 0)) 809 goto out_3; 810 811 if (!_dbus_keyring_validate_context (&context)) 812 { 813 if (_dbus_string_append (&auth->outgoing, 814 "ERROR \"Server sent invalid cookie context\"\r\n")) 815 retval = TRUE; 816 goto out_3; 817 } 818 819 if (!_dbus_string_parse_int (&cookie_id_str, 0, &val, NULL)) 820 { 821 if (_dbus_string_append (&auth->outgoing, 822 "ERROR \"Could not parse cookie ID as an integer\"\r\n")) 823 retval = TRUE; 824 goto out_3; 825 } 826 827 if (_dbus_string_get_length (&server_challenge) == 0) 828 { 829 if (_dbus_string_append (&auth->outgoing, 830 "ERROR \"Empty server challenge string\"\r\n")) 831 retval = TRUE; 832 goto out_3; 833 } 834 835 if (auth->keyring == NULL) 836 { 837 DBusError error; 838 839 dbus_error_init (&error); 840 auth->keyring = _dbus_keyring_new_homedir (NULL, 841 &context, 842 &error); 843 844 if (auth->keyring == NULL) 845 { 846 if (dbus_error_has_name (&error, 847 DBUS_ERROR_NO_MEMORY)) 848 { 849 dbus_error_free (&error); 850 goto out_3; 851 } 852 else 853 { 854 _DBUS_ASSERT_ERROR_IS_SET (&error); 855 856 _dbus_verbose ("%s: Error loading keyring: %s\n", 857 DBUS_AUTH_NAME (auth), error.message); 858 859 if (_dbus_string_append (&auth->outgoing, 860 "ERROR \"Could not load cookie file\"\r\n")) 861 retval = TRUE; /* retval is only about mem */ 862 863 dbus_error_free (&error); 864 goto out_3; 865 } 866 } 867 else 868 { 869 _dbus_assert (!dbus_error_is_set (&error)); 870 } 871 } 872 873 _dbus_assert (auth->keyring != NULL); 874 875 if (!_dbus_string_init (&tmp)) 876 goto out_3; 877 878 if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES)) 879 goto out_4; 880 881 if (!_dbus_string_init (&client_challenge)) 882 goto out_4; 883 884 if (!_dbus_string_hex_encode (&tmp, 0, &client_challenge, 0)) 885 goto out_5; 886 887 if (!_dbus_string_init (&correct_hash)) 888 goto out_5; 889 890 if (!sha1_compute_hash (auth, val, 891 &server_challenge, 892 &client_challenge, 893 &correct_hash)) 894 goto out_6; 895 896 if (_dbus_string_get_length (&correct_hash) == 0) 897 { 898 /* couldn't find the cookie ID or something */ 899 if (_dbus_string_append (&auth->outgoing, 900 "ERROR \"Don't have the requested cookie ID\"\r\n")) 901 retval = TRUE; 902 goto out_6; 903 } 904 905 _dbus_string_set_length (&tmp, 0); 906 907 if (!_dbus_string_copy (&client_challenge, 0, &tmp, 908 _dbus_string_get_length (&tmp))) 909 goto out_6; 910 911 if (!_dbus_string_append (&tmp, " ")) 912 goto out_6; 913 914 if (!_dbus_string_copy (&correct_hash, 0, &tmp, 915 _dbus_string_get_length (&tmp))) 916 goto out_6; 917 918 old_len = _dbus_string_get_length (&auth->outgoing); 919 if (!_dbus_string_append (&auth->outgoing, "DATA ")) 920 goto out_6; 921 922 if (!_dbus_string_base64_encode (&tmp, 0, 923 &auth->outgoing, 924 _dbus_string_get_length (&auth->outgoing))) 925 { 926 _dbus_string_set_length (&auth->outgoing, old_len); 927 goto out_6; 928 } 929 930 if (!_dbus_string_append (&auth->outgoing, "\r\n")) 931 { 932 _dbus_string_set_length (&auth->outgoing, old_len); 933 goto out_6; 934 } 935 936 retval = TRUE; 937 938 out_6: 939 _dbus_string_zero (&correct_hash); 940 _dbus_string_free (&correct_hash); 941 out_5: 942 _dbus_string_free (&client_challenge); 943 out_4: 944 _dbus_string_zero (&tmp); 945 _dbus_string_free (&tmp); 946 out_3: 947 _dbus_string_free (&server_challenge); 948 out_2: 949 _dbus_string_free (&cookie_id_str); 950 out_1: 951 _dbus_string_free (&context); 952 out_0: 953 return retval; 954} 955 956static void 957handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth) 958{ 959 auth->cookie_id = -1; 960 _dbus_string_set_length (&auth->challenge, 0); 961} 962 963static dbus_bool_t 964handle_server_data_external_mech (DBusAuth *auth, 965 const DBusString *data) 966{ 967 if (auth->credentials.uid == DBUS_UID_UNSET) 968 { 969 _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n", 970 DBUS_AUTH_NAME (auth)); 971 return send_rejected (auth); 972 } 973 974 if (_dbus_string_get_length (data) > 0) 975 { 976 if (_dbus_string_get_length (&auth->identity) > 0) 977 { 978 /* Tried to send two auth identities, wtf */ 979 _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n", 980 DBUS_AUTH_NAME (auth)); 981 return send_rejected (auth); 982 } 983 else 984 { 985 /* this is our auth identity */ 986 if (!_dbus_string_copy (data, 0, &auth->identity, 0)) 987 return FALSE; 988 } 989 } 990 991 /* Poke client for an auth identity, if none given */ 992 if (_dbus_string_get_length (&auth->identity) == 0 && 993 !auth->already_asked_for_initial_response) 994 { 995 if (_dbus_string_append (&auth->outgoing, 996 "DATA\r\n")) 997 { 998 _dbus_verbose ("%s: sending empty challenge asking client for auth identity\n", 999 DBUS_AUTH_NAME (auth)); 1000 auth->already_asked_for_initial_response = TRUE; 1001 return TRUE; 1002 } 1003 else 1004 return FALSE; 1005 } 1006 1007 _dbus_credentials_clear (&auth->desired_identity); 1008 1009 /* If auth->identity is still empty here, then client 1010 * responded with an empty string after we poked it for 1011 * an initial response. This means to try to auth the 1012 * identity provided in the credentials. 1013 */ 1014 if (_dbus_string_get_length (&auth->identity) == 0) 1015 { 1016 auth->desired_identity.uid = auth->credentials.uid; 1017 } 1018 else 1019 { 1020 if (!_dbus_uid_from_string (&auth->identity, 1021 &auth->desired_identity.uid)) 1022 { 1023 _dbus_verbose ("%s: could not get credentials from uid string\n", 1024 DBUS_AUTH_NAME (auth)); 1025 return send_rejected (auth); 1026 } 1027 } 1028 1029 if (auth->desired_identity.uid == DBUS_UID_UNSET) 1030 { 1031 _dbus_verbose ("%s: desired user %s is no good\n", 1032 DBUS_AUTH_NAME (auth), 1033 _dbus_string_get_const_data (&auth->identity)); 1034 return send_rejected (auth); 1035 } 1036 1037 if (_dbus_credentials_match (&auth->desired_identity, 1038 &auth->credentials)) 1039 { 1040 /* client has authenticated */ 1041 if (!_dbus_string_append (&auth->outgoing, 1042 "OK\r\n")) 1043 return FALSE; 1044 1045 _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT 1046 " matching socket credentials UID "DBUS_UID_FORMAT"\n", 1047 DBUS_AUTH_NAME (auth), 1048 auth->desired_identity.uid, 1049 auth->credentials.uid); 1050 1051 auth->authorized_identity.uid = auth->desired_identity.uid; 1052 1053 auth->authenticated_pending_begin = TRUE; 1054 1055 return TRUE; 1056 } 1057 else 1058 { 1059 _dbus_verbose ("%s: credentials uid="DBUS_UID_FORMAT 1060 " gid="DBUS_GID_FORMAT 1061 " do not allow uid="DBUS_UID_FORMAT 1062 " gid="DBUS_GID_FORMAT"\n", 1063 DBUS_AUTH_NAME (auth), 1064 auth->credentials.uid, auth->credentials.gid, 1065 auth->desired_identity.uid, auth->desired_identity.gid); 1066 return send_rejected (auth); 1067 } 1068} 1069 1070static void 1071handle_server_shutdown_external_mech (DBusAuth *auth) 1072{ 1073 1074} 1075 1076static dbus_bool_t 1077handle_client_initial_response_external_mech (DBusAuth *auth, 1078 DBusString *response) 1079{ 1080 /* We always append our UID as an initial response, so the server 1081 * doesn't have to send back an empty challenge to check whether we 1082 * want to specify an identity. i.e. this avoids a round trip that 1083 * the spec for the EXTERNAL mechanism otherwise requires. 1084 */ 1085 DBusString plaintext; 1086 1087 if (!_dbus_string_init (&plaintext)) 1088 return FALSE; 1089 1090 if (!_dbus_string_append_uint (&plaintext, 1091 _dbus_getuid ())) 1092 goto failed; 1093 1094 if (!_dbus_string_base64_encode (&plaintext, 0, 1095 response, 1096 _dbus_string_get_length (response))) 1097 goto failed; 1098 1099 _dbus_string_free (&plaintext); 1100 1101 return TRUE; 1102 1103 failed: 1104 _dbus_string_free (&plaintext); 1105 return FALSE; 1106} 1107 1108static dbus_bool_t 1109handle_client_data_external_mech (DBusAuth *auth, 1110 const DBusString *data) 1111{ 1112 1113 return TRUE; 1114} 1115 1116static void 1117handle_client_shutdown_external_mech (DBusAuth *auth) 1118{ 1119 1120} 1121 1122/* Put mechanisms here in order of preference. 1123 * What I eventually want to have is: 1124 * 1125 * - a mechanism that checks UNIX domain socket credentials 1126 * - a simple magic cookie mechanism like X11 or ICE 1127 * - mechanisms that chain to Cyrus SASL, so we can use anything it 1128 * offers such as Kerberos, X509, whatever. 1129 * 1130 */ 1131static const DBusAuthMechanismHandler 1132all_mechanisms[] = { 1133 { "EXTERNAL", 1134 handle_server_data_external_mech, 1135 NULL, NULL, 1136 handle_server_shutdown_external_mech, 1137 handle_client_initial_response_external_mech, 1138 handle_client_data_external_mech, 1139 NULL, NULL, 1140 handle_client_shutdown_external_mech }, 1141 { "DBUS_COOKIE_SHA1", 1142 handle_server_data_cookie_sha1_mech, 1143 NULL, NULL, 1144 handle_server_shutdown_cookie_sha1_mech, 1145 handle_client_initial_response_cookie_sha1_mech, 1146 handle_client_data_cookie_sha1_mech, 1147 NULL, NULL, 1148 handle_client_shutdown_cookie_sha1_mech }, 1149 { NULL, NULL } 1150}; 1151 1152static const DBusAuthMechanismHandler* 1153find_mech (const DBusString *name, 1154 char **allowed_mechs) 1155{ 1156 int i; 1157 1158 if (allowed_mechs != NULL && 1159 !_dbus_string_array_contains ((const char**) allowed_mechs, 1160 _dbus_string_get_const_data (name))) 1161 return NULL; 1162 1163 i = 0; 1164 while (all_mechanisms[i].mechanism != NULL) 1165 { 1166 if (_dbus_string_equal_c_str (name, 1167 all_mechanisms[i].mechanism)) 1168 1169 return &all_mechanisms[i]; 1170 1171 ++i; 1172 } 1173 1174 return NULL; 1175} 1176 1177static dbus_bool_t 1178send_rejected (DBusAuth *auth) 1179{ 1180 DBusString command; 1181 DBusAuthServer *server_auth; 1182 int i; 1183 1184 if (!_dbus_string_init (&command)) 1185 return FALSE; 1186 1187 if (!_dbus_string_append (&command, 1188 "REJECTED")) 1189 goto nomem; 1190 1191 i = 0; 1192 while (all_mechanisms[i].mechanism != NULL) 1193 { 1194 if (!_dbus_string_append (&command, 1195 " ")) 1196 goto nomem; 1197 1198 if (!_dbus_string_append (&command, 1199 all_mechanisms[i].mechanism)) 1200 goto nomem; 1201 1202 ++i; 1203 } 1204 1205 if (!_dbus_string_append (&command, "\r\n")) 1206 goto nomem; 1207 1208 if (!_dbus_string_copy (&command, 0, &auth->outgoing, 1209 _dbus_string_get_length (&auth->outgoing))) 1210 goto nomem; 1211 1212 shutdown_mech (auth); 1213 1214 _dbus_assert (DBUS_AUTH_IS_SERVER (auth)); 1215 server_auth = DBUS_AUTH_SERVER (auth); 1216 server_auth->failures += 1; 1217 1218 _dbus_string_free (&command); 1219 1220 return TRUE; 1221 1222 nomem: 1223 _dbus_string_free (&command); 1224 return FALSE; 1225} 1226 1227static dbus_bool_t 1228process_auth (DBusAuth *auth, 1229 const DBusString *command, 1230 const DBusString *args) 1231{ 1232 if (auth->mech) 1233 { 1234 /* We are already using a mechanism, client is on crack */ 1235 if (!_dbus_string_append (&auth->outgoing, 1236 "ERROR \"Sent AUTH while another AUTH in progress\"\r\n")) 1237 return FALSE; 1238 1239 return TRUE; 1240 } 1241 else if (_dbus_string_get_length (args) == 0) 1242 { 1243 /* No args to the auth, send mechanisms */ 1244 if (!send_rejected (auth)) 1245 return FALSE; 1246 1247 return TRUE; 1248 } 1249 else 1250 { 1251 int i; 1252 DBusString mech; 1253 DBusString base64_response; 1254 DBusString decoded_response; 1255 1256 _dbus_string_find_blank (args, 0, &i); 1257 1258 if (!_dbus_string_init (&mech)) 1259 return FALSE; 1260 1261 if (!_dbus_string_init (&base64_response)) 1262 { 1263 _dbus_string_free (&mech); 1264 return FALSE; 1265 } 1266 1267 if (!_dbus_string_init (&decoded_response)) 1268 { 1269 _dbus_string_free (&mech); 1270 _dbus_string_free (&base64_response); 1271 return FALSE; 1272 } 1273 1274 if (!_dbus_string_copy_len (args, 0, i, &mech, 0)) 1275 goto failed; 1276 1277 if (!_dbus_string_copy (args, i, &base64_response, 0)) 1278 goto failed; 1279 1280 if (!_dbus_string_base64_decode (&base64_response, 0, 1281 &decoded_response, 0)) 1282 goto failed; 1283 1284 auth->mech = find_mech (&mech, auth->allowed_mechs); 1285 if (auth->mech != NULL) 1286 { 1287 _dbus_verbose ("%s: Trying mechanism %s with initial response of %d bytes\n", 1288 DBUS_AUTH_NAME (auth), 1289 auth->mech->mechanism, 1290 _dbus_string_get_length (&decoded_response)); 1291 1292 if (!(* auth->mech->server_data_func) (auth, 1293 &decoded_response)) 1294 goto failed; 1295 } 1296 else 1297 { 1298 /* Unsupported mechanism */ 1299 if (!send_rejected (auth)) 1300 goto failed; 1301 } 1302 1303 _dbus_string_free (&mech); 1304 _dbus_string_free (&base64_response); 1305 _dbus_string_free (&decoded_response); 1306 1307 return TRUE; 1308 1309 failed: 1310 auth->mech = NULL; 1311 _dbus_string_free (&mech); 1312 _dbus_string_free (&base64_response); 1313 _dbus_string_free (&decoded_response); 1314 return FALSE; 1315 } 1316} 1317 1318static dbus_bool_t 1319process_cancel (DBusAuth *auth, 1320 const DBusString *command, 1321 const DBusString *args) 1322{ 1323 if (!send_rejected (auth)) 1324 return FALSE; 1325 1326 return TRUE; 1327} 1328 1329static dbus_bool_t 1330process_begin (DBusAuth *auth, 1331 const DBusString *command, 1332 const DBusString *args) 1333{ 1334 if (auth->authenticated_pending_begin) 1335 auth->authenticated = TRUE; 1336 else 1337 { 1338 auth->need_disconnect = TRUE; /* client trying to send data before auth, 1339 * kick it 1340 */ 1341 shutdown_mech (auth); 1342 } 1343 1344 return TRUE; 1345} 1346 1347static dbus_bool_t 1348process_data_server (DBusAuth *auth, 1349 const DBusString *command, 1350 const DBusString *args) 1351{ 1352 if (auth->mech != NULL) 1353 { 1354 DBusString decoded; 1355 1356 if (!_dbus_string_init (&decoded)) 1357 return FALSE; 1358 1359 if (!_dbus_string_base64_decode (args, 0, &decoded, 0)) 1360 { 1361 _dbus_string_free (&decoded); 1362 return FALSE; 1363 } 1364 1365#ifdef DBUS_ENABLE_VERBOSE_MODE 1366 if (_dbus_string_validate_ascii (&decoded, 0, 1367 _dbus_string_get_length (&decoded))) 1368 _dbus_verbose ("%s: data: '%s'\n", 1369 DBUS_AUTH_NAME (auth), 1370 _dbus_string_get_const_data (&decoded)); 1371#endif 1372 1373 if (!(* auth->mech->server_data_func) (auth, &decoded)) 1374 { 1375 _dbus_string_free (&decoded); 1376 return FALSE; 1377 } 1378 1379 _dbus_string_free (&decoded); 1380 } 1381 else 1382 { 1383 if (!_dbus_string_append (&auth->outgoing, 1384 "ERROR \"Not currently in an auth conversation\"\r\n")) 1385 return FALSE; 1386 } 1387 1388 return TRUE; 1389} 1390 1391static dbus_bool_t 1392process_error_server (DBusAuth *auth, 1393 const DBusString *command, 1394 const DBusString *args) 1395{ 1396 /* Server got error from client, reject the auth, 1397 * as we don't have anything more intelligent to do. 1398 */ 1399 if (!send_rejected (auth)) 1400 return FALSE; 1401 1402 return TRUE; 1403} 1404 1405/* return FALSE if no memory, TRUE if all OK */ 1406static dbus_bool_t 1407get_word (const DBusString *str, 1408 int *start, 1409 DBusString *word) 1410{ 1411 int i; 1412 1413 _dbus_string_skip_blank (str, *start, start); 1414 _dbus_string_find_blank (str, *start, &i); 1415 1416 if (i > *start) 1417 { 1418 if (!_dbus_string_copy_len (str, *start, i - *start, word, 0)) 1419 return FALSE; 1420 1421 *start = i; 1422 } 1423 1424 return TRUE; 1425} 1426 1427static dbus_bool_t 1428record_mechanisms (DBusAuth *auth, 1429 const DBusString *command, 1430 const DBusString *args) 1431{ 1432 int next; 1433 int len; 1434 1435 if (auth->already_got_mechanisms) 1436 return TRUE; 1437 1438 len = _dbus_string_get_length (args); 1439 1440 next = 0; 1441 while (next < len) 1442 { 1443 DBusString m; 1444 const DBusAuthMechanismHandler *mech; 1445 1446 if (!_dbus_string_init (&m)) 1447 goto nomem; 1448 1449 if (!get_word (args, &next, &m)) 1450 { 1451 _dbus_string_free (&m); 1452 goto nomem; 1453 } 1454 1455 mech = find_mech (&m, auth->allowed_mechs); 1456 1457 if (mech != NULL) 1458 { 1459 /* FIXME right now we try mechanisms in the order 1460 * the server lists them; should we do them in 1461 * some more deterministic order? 1462 * 1463 * Probably in all_mechanisms order, our order of 1464 * preference. Of course when the server is us, 1465 * it lists things in that order anyhow. 1466 */ 1467 1468 _dbus_verbose ("%s: Adding mechanism %s to list we will try\n", 1469 DBUS_AUTH_NAME (auth), mech->mechanism); 1470 1471 if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try, 1472 (void*) mech)) 1473 { 1474 _dbus_string_free (&m); 1475 goto nomem; 1476 } 1477 } 1478 else 1479 { 1480 _dbus_verbose ("%s: Server offered mechanism \"%s\" that we don't know how to use\n", 1481 DBUS_AUTH_NAME (auth), 1482 _dbus_string_get_const_data (&m)); 1483 } 1484 1485 _dbus_string_free (&m); 1486 } 1487 1488 auth->already_got_mechanisms = TRUE; 1489 1490 return TRUE; 1491 1492 nomem: 1493 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try); 1494 1495 return FALSE; 1496} 1497 1498static dbus_bool_t 1499client_try_next_mechanism (DBusAuth *auth) 1500{ 1501 const DBusAuthMechanismHandler *mech; 1502 DBusString auth_command; 1503 DBusAuthClient *client; 1504 1505 client = DBUS_AUTH_CLIENT (auth); 1506 1507 /* Pop any mechs not in the list of allowed mechanisms */ 1508 mech = NULL; 1509 while (client->mechs_to_try != NULL) 1510 { 1511 mech = client->mechs_to_try->data; 1512 1513 if (auth->allowed_mechs != NULL && 1514 !_dbus_string_array_contains ((const char**) auth->allowed_mechs, 1515 mech->mechanism)) 1516 { 1517 /* don't try this one after all */ 1518 _dbus_verbose ("%s: Mechanism %s isn't in the list of allowed mechanisms\n", 1519 DBUS_AUTH_NAME (auth), mech->mechanism); 1520 mech = NULL; 1521 _dbus_list_pop_first (& client->mechs_to_try); 1522 } 1523 else 1524 break; /* we'll try this one */ 1525 } 1526 1527 if (mech == NULL) 1528 return FALSE; 1529 1530 if (!_dbus_string_init (&auth_command)) 1531 return FALSE; 1532 1533 if (!_dbus_string_append (&auth_command, 1534 "AUTH ")) 1535 { 1536 _dbus_string_free (&auth_command); 1537 return FALSE; 1538 } 1539 1540 if (!_dbus_string_append (&auth_command, 1541 mech->mechanism)) 1542 { 1543 _dbus_string_free (&auth_command); 1544 return FALSE; 1545 } 1546 1547 if (mech->client_initial_response_func != NULL) 1548 { 1549 if (!_dbus_string_append (&auth_command, " ")) 1550 { 1551 _dbus_string_free (&auth_command); 1552 return FALSE; 1553 } 1554 1555 if (!(* mech->client_initial_response_func) (auth, &auth_command)) 1556 { 1557 _dbus_string_free (&auth_command); 1558 return FALSE; 1559 } 1560 } 1561 1562 if (!_dbus_string_append (&auth_command, 1563 "\r\n")) 1564 { 1565 _dbus_string_free (&auth_command); 1566 return FALSE; 1567 } 1568 1569 if (!_dbus_string_copy (&auth_command, 0, 1570 &auth->outgoing, 1571 _dbus_string_get_length (&auth->outgoing))) 1572 { 1573 _dbus_string_free (&auth_command); 1574 return FALSE; 1575 } 1576 1577 auth->mech = mech; 1578 _dbus_list_pop_first (& DBUS_AUTH_CLIENT (auth)->mechs_to_try); 1579 1580 _dbus_verbose ("%s: Trying mechanism %s\n", 1581 DBUS_AUTH_NAME (auth), 1582 auth->mech->mechanism); 1583 1584 _dbus_string_free (&auth_command); 1585 1586 return TRUE; 1587} 1588 1589static dbus_bool_t 1590process_rejected (DBusAuth *auth, 1591 const DBusString *command, 1592 const DBusString *args) 1593{ 1594 shutdown_mech (auth); 1595 1596 if (!auth->already_got_mechanisms) 1597 { 1598 if (!record_mechanisms (auth, command, args)) 1599 return FALSE; 1600 } 1601 1602 if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL) 1603 { 1604 if (!client_try_next_mechanism (auth)) 1605 return FALSE; 1606 } 1607 else 1608 { 1609 /* Give up */ 1610 auth->need_disconnect = TRUE; 1611 } 1612 1613 return TRUE; 1614} 1615 1616static dbus_bool_t 1617process_ok (DBusAuth *auth, 1618 const DBusString *command, 1619 const DBusString *args) 1620{ 1621 if (!_dbus_string_append (&auth->outgoing, 1622 "BEGIN\r\n")) 1623 return FALSE; 1624 1625 auth->authenticated_pending_output = TRUE; 1626 1627 return TRUE; 1628} 1629 1630static dbus_bool_t 1631process_data_client (DBusAuth *auth, 1632 const DBusString *command, 1633 const DBusString *args) 1634{ 1635 if (auth->mech != NULL) 1636 { 1637 DBusString decoded; 1638 1639 if (!_dbus_string_init (&decoded)) 1640 return FALSE; 1641 1642 if (!_dbus_string_base64_decode (args, 0, &decoded, 0)) 1643 { 1644 _dbus_string_free (&decoded); 1645 return FALSE; 1646 } 1647 1648#ifdef DBUS_ENABLE_VERBOSE_MODE 1649 if (_dbus_string_validate_ascii (&decoded, 0, 1650 _dbus_string_get_length (&decoded))) 1651 { 1652 _dbus_verbose ("%s: data: '%s'\n", 1653 DBUS_AUTH_NAME (auth), 1654 _dbus_string_get_const_data (&decoded)); 1655 } 1656#endif 1657 1658 if (!(* auth->mech->client_data_func) (auth, &decoded)) 1659 { 1660 _dbus_string_free (&decoded); 1661 return FALSE; 1662 } 1663 1664 _dbus_string_free (&decoded); 1665 } 1666 else 1667 { 1668 if (!_dbus_string_append (&auth->outgoing, 1669 "ERROR \"Got DATA when not in an auth exchange\"\r\n")) 1670 return FALSE; 1671 } 1672 1673 return TRUE; 1674} 1675 1676static dbus_bool_t 1677process_error_client (DBusAuth *auth, 1678 const DBusString *command, 1679 const DBusString *args) 1680{ 1681 /* Cancel current mechanism, as we don't have anything 1682 * more clever to do. 1683 */ 1684 if (!_dbus_string_append (&auth->outgoing, 1685 "CANCEL\r\n")) 1686 return FALSE; 1687 1688 return TRUE; 1689} 1690 1691static dbus_bool_t 1692process_unknown (DBusAuth *auth, 1693 const DBusString *command, 1694 const DBusString *args) 1695{ 1696 if (!_dbus_string_append (&auth->outgoing, 1697 "ERROR \"Unknown command\"\r\n")) 1698 return FALSE; 1699 1700 return TRUE; 1701} 1702 1703/* returns whether to call it again right away */ 1704static dbus_bool_t 1705process_command (DBusAuth *auth) 1706{ 1707 DBusString command; 1708 DBusString args; 1709 int eol; 1710 int i, j; 1711 dbus_bool_t retval; 1712 1713 /* _dbus_verbose ("%s: trying process_command()\n"); */ 1714 1715 retval = FALSE; 1716 1717 eol = 0; 1718 if (!_dbus_string_find (&auth->incoming, 0, "\r\n", &eol)) 1719 return FALSE; 1720 1721 if (!_dbus_string_init (&command)) 1722 { 1723 auth->needed_memory = TRUE; 1724 return FALSE; 1725 } 1726 1727 if (!_dbus_string_init (&args)) 1728 { 1729 _dbus_string_free (&command); 1730 auth->needed_memory = TRUE; 1731 return FALSE; 1732 } 1733 1734 if (eol > _DBUS_ONE_MEGABYTE) 1735 { 1736 /* This is a giant line, someone is trying to hose us. */ 1737 if (!_dbus_string_append (&auth->outgoing, "ERROR \"Command too long\"\r\n")) 1738 goto out; 1739 else 1740 goto next_command; 1741 } 1742 1743 if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &command, 0)) 1744 goto out; 1745 1746 if (!_dbus_string_validate_ascii (&command, 0, 1747 _dbus_string_get_length (&command))) 1748 { 1749 _dbus_verbose ("%s: Command contained non-ASCII chars or embedded nul\n", 1750 DBUS_AUTH_NAME (auth)); 1751 if (!_dbus_string_append (&auth->outgoing, "ERROR \"Command contained non-ASCII\"\r\n")) 1752 goto out; 1753 else 1754 goto next_command; 1755 } 1756 1757 _dbus_verbose ("%s: got command \"%s\"\n", 1758 DBUS_AUTH_NAME (auth), 1759 _dbus_string_get_const_data (&command)); 1760 1761 _dbus_string_find_blank (&command, 0, &i); 1762 _dbus_string_skip_blank (&command, i, &j); 1763 1764 if (j > i) 1765 _dbus_string_delete (&command, i, j - i); 1766 1767 if (!_dbus_string_move (&command, i, &args, 0)) 1768 goto out; 1769 1770 i = 0; 1771 while (auth->handlers[i].command != NULL) 1772 { 1773 if (_dbus_string_equal_c_str (&command, 1774 auth->handlers[i].command)) 1775 { 1776 _dbus_verbose ("%s: Processing auth command %s\n", 1777 DBUS_AUTH_NAME (auth), 1778 auth->handlers[i].command); 1779 1780 if (!(* auth->handlers[i].func) (auth, &command, &args)) 1781 goto out; 1782 1783 break; 1784 } 1785 ++i; 1786 } 1787 1788 if (auth->handlers[i].command == NULL) 1789 { 1790 if (!process_unknown (auth, &command, &args)) 1791 goto out; 1792 } 1793 1794 next_command: 1795 1796 /* We've succeeded in processing the whole command so drop it out 1797 * of the incoming buffer and return TRUE to try another command. 1798 */ 1799 1800 _dbus_string_delete (&auth->incoming, 0, eol); 1801 1802 /* kill the \r\n */ 1803 _dbus_string_delete (&auth->incoming, 0, 2); 1804 1805 retval = TRUE; 1806 1807 out: 1808 _dbus_string_free (&args); 1809 _dbus_string_free (&command); 1810 1811 if (!retval) 1812 auth->needed_memory = TRUE; 1813 else 1814 auth->needed_memory = FALSE; 1815 1816 return retval; 1817} 1818 1819 1820/** @} */ 1821 1822/** 1823 * @addtogroup DBusAuth 1824 * @{ 1825 */ 1826 1827/** 1828 * Creates a new auth conversation object for the server side. 1829 * See doc/dbus-sasl-profile.txt for full details on what 1830 * this object does. 1831 * 1832 * @returns the new object or #NULL if no memory 1833 */ 1834DBusAuth* 1835_dbus_auth_server_new (void) 1836{ 1837 DBusAuth *auth; 1838 DBusAuthServer *server_auth; 1839 1840 auth = _dbus_auth_new (sizeof (DBusAuthServer)); 1841 if (auth == NULL) 1842 return NULL; 1843 1844 auth->handlers = server_handlers; 1845 1846 server_auth = DBUS_AUTH_SERVER (auth); 1847 1848 /* perhaps this should be per-mechanism with a lower 1849 * max 1850 */ 1851 server_auth->failures = 0; 1852 server_auth->max_failures = 6; 1853 1854 return auth; 1855} 1856 1857/** 1858 * Creates a new auth conversation object for the client side. 1859 * See doc/dbus-sasl-profile.txt for full details on what 1860 * this object does. 1861 * 1862 * @returns the new object or #NULL if no memory 1863 */ 1864DBusAuth* 1865_dbus_auth_client_new (void) 1866{ 1867 DBusAuth *auth; 1868 1869 auth = _dbus_auth_new (sizeof (DBusAuthClient)); 1870 if (auth == NULL) 1871 return NULL; 1872 1873 auth->handlers = client_handlers; 1874 1875 /* Add a default mechanism to try */ 1876 if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try, 1877 (void*) &all_mechanisms[0])) 1878 { 1879 _dbus_auth_unref (auth); 1880 return NULL; 1881 } 1882 1883 /* Now try the mechanism we just added */ 1884 if (!client_try_next_mechanism (auth)) 1885 { 1886 _dbus_auth_unref (auth); 1887 return NULL; 1888 } 1889 1890 return auth; 1891} 1892 1893/** 1894 * Increments the refcount of an auth object. 1895 * 1896 * @param auth the auth conversation 1897 * @returns the auth conversation 1898 */ 1899DBusAuth * 1900_dbus_auth_ref (DBusAuth *auth) 1901{ 1902 _dbus_assert (auth != NULL); 1903 1904 auth->refcount += 1; 1905 1906 return auth; 1907} 1908 1909/** 1910 * Decrements the refcount of an auth object. 1911 * 1912 * @param auth the auth conversation 1913 */ 1914void 1915_dbus_auth_unref (DBusAuth *auth) 1916{ 1917 _dbus_assert (auth != NULL); 1918 _dbus_assert (auth->refcount > 0); 1919 1920 auth->refcount -= 1; 1921 if (auth->refcount == 0) 1922 { 1923 shutdown_mech (auth); 1924 1925 if (DBUS_AUTH_IS_CLIENT (auth)) 1926 { 1927 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try); 1928 } 1929 1930 if (auth->keyring) 1931 _dbus_keyring_unref (auth->keyring); 1932 1933 _dbus_string_free (&auth->context); 1934 _dbus_string_free (&auth->challenge); 1935 _dbus_string_free (&auth->identity); 1936 _dbus_string_free (&auth->incoming); 1937 _dbus_string_free (&auth->outgoing); 1938 1939 dbus_free_string_array (auth->allowed_mechs); 1940 1941 dbus_free (auth); 1942 } 1943} 1944 1945/** 1946 * Sets an array of authentication mechanism names 1947 * that we are willing to use. 1948 * 1949 * @param auth the auth conversation 1950 * @param mechanisms #NULL-terminated array of mechanism names 1951 * @returns #FALSE if no memory 1952 */ 1953dbus_bool_t 1954_dbus_auth_set_mechanisms (DBusAuth *auth, 1955 const char **mechanisms) 1956{ 1957 char **copy; 1958 1959 if (mechanisms != NULL) 1960 { 1961 copy = _dbus_dup_string_array (mechanisms); 1962 if (copy == NULL) 1963 return FALSE; 1964 } 1965 else 1966 copy = NULL; 1967 1968 dbus_free_string_array (auth->allowed_mechs); 1969 1970 auth->allowed_mechs = copy; 1971 1972 return TRUE; 1973} 1974 1975/** 1976 * @param auth the auth conversation object 1977 * @returns #TRUE if we're in a final state 1978 */ 1979#define DBUS_AUTH_IN_END_STATE(auth) ((auth)->need_disconnect || (auth)->authenticated) 1980 1981/** 1982 * Analyzes buffered input and moves the auth conversation forward, 1983 * returning the new state of the auth conversation. 1984 * 1985 * @param auth the auth conversation 1986 * @returns the new state 1987 */ 1988DBusAuthState 1989_dbus_auth_do_work (DBusAuth *auth) 1990{ 1991 auth->needed_memory = FALSE; 1992 1993 /* Max amount we'll buffer up before deciding someone's on crack */ 1994#define MAX_BUFFER (16 * _DBUS_ONE_KILOBYTE) 1995 1996 do 1997 { 1998 if (DBUS_AUTH_IN_END_STATE (auth)) 1999 break; 2000 2001 if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER || 2002 _dbus_string_get_length (&auth->outgoing) > MAX_BUFFER) 2003 { 2004 auth->need_disconnect = TRUE; 2005 _dbus_verbose ("%s: Disconnecting due to excessive data buffered in auth phase\n", 2006 DBUS_AUTH_NAME (auth)); 2007 break; 2008 } 2009 2010 if (auth->mech == NULL && 2011 auth->already_got_mechanisms && 2012 DBUS_AUTH_CLIENT (auth)->mechs_to_try == NULL) 2013 { 2014 auth->need_disconnect = TRUE; 2015 _dbus_verbose ("%s: Disconnecting because we are out of mechanisms to try using\n", 2016 DBUS_AUTH_NAME (auth)); 2017 break; 2018 } 2019 } 2020 while (process_command (auth)); 2021 2022 if (DBUS_AUTH_IS_SERVER (auth) && 2023 DBUS_AUTH_SERVER (auth)->failures >= 2024 DBUS_AUTH_SERVER (auth)->max_failures) 2025 auth->need_disconnect = TRUE; 2026 2027 if (auth->need_disconnect) 2028 return DBUS_AUTH_STATE_NEED_DISCONNECT; 2029 else if (auth->authenticated) 2030 { 2031 if (_dbus_string_get_length (&auth->incoming) > 0) 2032 return DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES; 2033 else 2034 return DBUS_AUTH_STATE_AUTHENTICATED; 2035 } 2036 else if (auth->needed_memory) 2037 return DBUS_AUTH_STATE_WAITING_FOR_MEMORY; 2038 else if (_dbus_string_get_length (&auth->outgoing) > 0) 2039 return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND; 2040 else 2041 return DBUS_AUTH_STATE_WAITING_FOR_INPUT; 2042} 2043 2044/** 2045 * Gets bytes that need to be sent to the peer we're conversing with. 2046 * After writing some bytes, _dbus_auth_bytes_sent() must be called 2047 * to notify the auth object that they were written. 2048 * 2049 * @param auth the auth conversation 2050 * @param str return location for a ref to the buffer to send 2051 * @returns #FALSE if nothing to send 2052 */ 2053dbus_bool_t 2054_dbus_auth_get_bytes_to_send (DBusAuth *auth, 2055 const DBusString **str) 2056{ 2057 _dbus_assert (auth != NULL); 2058 _dbus_assert (str != NULL); 2059 2060 *str = NULL; 2061 2062 if (DBUS_AUTH_IN_END_STATE (auth)) 2063 return FALSE; 2064 2065 if (_dbus_string_get_length (&auth->outgoing) == 0) 2066 return FALSE; 2067 2068 *str = &auth->outgoing; 2069 2070 return TRUE; 2071} 2072 2073/** 2074 * Notifies the auth conversation object that 2075 * the given number of bytes of the outgoing buffer 2076 * have been written out. 2077 * 2078 * @param auth the auth conversation 2079 * @param bytes_sent number of bytes written out 2080 */ 2081void 2082_dbus_auth_bytes_sent (DBusAuth *auth, 2083 int bytes_sent) 2084{ 2085 _dbus_verbose ("%s: Sent %d bytes of: %s\n", 2086 DBUS_AUTH_NAME (auth), 2087 bytes_sent, 2088 _dbus_string_get_const_data (&auth->outgoing)); 2089 2090 _dbus_string_delete (&auth->outgoing, 2091 0, bytes_sent); 2092 2093 if (auth->authenticated_pending_output && 2094 _dbus_string_get_length (&auth->outgoing) == 0) 2095 auth->authenticated = TRUE; 2096} 2097 2098/** 2099 * Get a buffer to be used for reading bytes from the peer we're conversing 2100 * with. Bytes should be appended to this buffer. 2101 * 2102 * @param auth the auth conversation 2103 * @param buffer return location for buffer to append bytes to 2104 */ 2105void 2106_dbus_auth_get_buffer (DBusAuth *auth, 2107 DBusString **buffer) 2108{ 2109 _dbus_assert (auth != NULL); 2110 _dbus_assert (!auth->buffer_outstanding); 2111 2112 *buffer = &auth->incoming; 2113 2114 auth->buffer_outstanding = TRUE; 2115} 2116 2117/** 2118 * Returns a buffer with new data read into it. 2119 * 2120 * @param auth the auth conversation 2121 * @param buffer the buffer being returned 2122 * @param bytes_read number of new bytes added 2123 */ 2124void 2125_dbus_auth_return_buffer (DBusAuth *auth, 2126 DBusString *buffer, 2127 int bytes_read) 2128{ 2129 _dbus_assert (buffer == &auth->incoming); 2130 _dbus_assert (auth->buffer_outstanding); 2131 2132 auth->buffer_outstanding = FALSE; 2133} 2134 2135/** 2136 * Returns leftover bytes that were not used as part of the auth 2137 * conversation. These bytes will be part of the message stream 2138 * instead. This function may not be called until authentication has 2139 * succeeded. 2140 * 2141 * @param auth the auth conversation 2142 * @param str return location for pointer to string of unused bytes 2143 */ 2144void 2145_dbus_auth_get_unused_bytes (DBusAuth *auth, 2146 const DBusString **str) 2147{ 2148 if (!DBUS_AUTH_IN_END_STATE (auth)) 2149 return; 2150 2151 *str = &auth->incoming; 2152} 2153 2154 2155/** 2156 * Gets rid of unused bytes returned by _dbus_auth_get_unused_bytes() 2157 * after we've gotten them and successfully moved them elsewhere. 2158 * 2159 * @param auth the auth conversation 2160 */ 2161void 2162_dbus_auth_delete_unused_bytes (DBusAuth *auth) 2163{ 2164 if (!DBUS_AUTH_IN_END_STATE (auth)) 2165 return; 2166 2167 _dbus_string_set_length (&auth->incoming, 0); 2168} 2169 2170/** 2171 * Called post-authentication, indicates whether we need to encode 2172 * the message stream with _dbus_auth_encode_data() prior to 2173 * sending it to the peer. 2174 * 2175 * @param auth the auth conversation 2176 * @returns #TRUE if we need to encode the stream 2177 */ 2178dbus_bool_t 2179_dbus_auth_needs_encoding (DBusAuth *auth) 2180{ 2181 if (!auth->authenticated) 2182 return FALSE; 2183 2184 if (auth->mech != NULL) 2185 { 2186 if (DBUS_AUTH_IS_CLIENT (auth)) 2187 return auth->mech->client_encode_func != NULL; 2188 else 2189 return auth->mech->server_encode_func != NULL; 2190 } 2191 else 2192 return FALSE; 2193} 2194 2195/** 2196 * Called post-authentication, encodes a block of bytes for sending to 2197 * the peer. If no encoding was negotiated, just copies the bytes 2198 * (you can avoid this by checking _dbus_auth_needs_encoding()). 2199 * 2200 * @param auth the auth conversation 2201 * @param plaintext the plain text data 2202 * @param encoded initialized string to where encoded data is appended 2203 * @returns #TRUE if we had enough memory and successfully encoded 2204 */ 2205dbus_bool_t 2206_dbus_auth_encode_data (DBusAuth *auth, 2207 const DBusString *plaintext, 2208 DBusString *encoded) 2209{ 2210 _dbus_assert (plaintext != encoded); 2211 2212 if (!auth->authenticated) 2213 return FALSE; 2214 2215 if (_dbus_auth_needs_encoding (auth)) 2216 { 2217 if (DBUS_AUTH_IS_CLIENT (auth)) 2218 return (* auth->mech->client_encode_func) (auth, plaintext, encoded); 2219 else 2220 return (* auth->mech->server_encode_func) (auth, plaintext, encoded); 2221 } 2222 else 2223 { 2224 return _dbus_string_copy (plaintext, 0, encoded, 2225 _dbus_string_get_length (encoded)); 2226 } 2227} 2228 2229/** 2230 * Called post-authentication, indicates whether we need to decode 2231 * the message stream with _dbus_auth_decode_data() after 2232 * receiving it from the peer. 2233 * 2234 * @param auth the auth conversation 2235 * @returns #TRUE if we need to encode the stream 2236 */ 2237dbus_bool_t 2238_dbus_auth_needs_decoding (DBusAuth *auth) 2239{ 2240 if (!auth->authenticated) 2241 return FALSE; 2242 2243 if (auth->mech != NULL) 2244 { 2245 if (DBUS_AUTH_IS_CLIENT (auth)) 2246 return auth->mech->client_decode_func != NULL; 2247 else 2248 return auth->mech->server_decode_func != NULL; 2249 } 2250 else 2251 return FALSE; 2252} 2253 2254 2255/** 2256 * Called post-authentication, decodes a block of bytes received from 2257 * the peer. If no encoding was negotiated, just copies the bytes (you 2258 * can avoid this by checking _dbus_auth_needs_decoding()). 2259 * 2260 * @todo We need to be able to distinguish "out of memory" error 2261 * from "the data is hosed" error. 2262 * 2263 * @param auth the auth conversation 2264 * @param encoded the encoded data 2265 * @param plaintext initialized string where decoded data is appended 2266 * @returns #TRUE if we had enough memory and successfully decoded 2267 */ 2268dbus_bool_t 2269_dbus_auth_decode_data (DBusAuth *auth, 2270 const DBusString *encoded, 2271 DBusString *plaintext) 2272{ 2273 _dbus_assert (plaintext != encoded); 2274 2275 if (!auth->authenticated) 2276 return FALSE; 2277 2278 if (_dbus_auth_needs_decoding (auth)) 2279 { 2280 if (DBUS_AUTH_IS_CLIENT (auth)) 2281 return (* auth->mech->client_decode_func) (auth, encoded, plaintext); 2282 else 2283 return (* auth->mech->server_decode_func) (auth, encoded, plaintext); 2284 } 2285 else 2286 { 2287 return _dbus_string_copy (encoded, 0, plaintext, 2288 _dbus_string_get_length (plaintext)); 2289 } 2290} 2291 2292/** 2293 * Sets credentials received via reliable means from the operating 2294 * system. 2295 * 2296 * @param auth the auth conversation 2297 * @param credentials the credentials received 2298 */ 2299void 2300_dbus_auth_set_credentials (DBusAuth *auth, 2301 const DBusCredentials *credentials) 2302{ 2303 auth->credentials = *credentials; 2304} 2305 2306/** 2307 * Gets the identity we authorized the client as. Apps may have 2308 * different policies as to what identities they allow. 2309 * 2310 * @param auth the auth conversation 2311 * @param credentials the credentials we've authorized 2312 */ 2313void 2314_dbus_auth_get_identity (DBusAuth *auth, 2315 DBusCredentials *credentials) 2316{ 2317 if (auth->authenticated) 2318 *credentials = auth->authorized_identity; 2319 else 2320 _dbus_credentials_clear (credentials); 2321} 2322 2323/** 2324 * Sets the "authentication context" which scopes cookies 2325 * with the DBUS_COOKIE_SHA1 auth mechanism for example. 2326 * 2327 * @param auth the auth conversation 2328 * @param context the context 2329 * @returns #FALSE if no memory 2330 */ 2331dbus_bool_t 2332_dbus_auth_set_context (DBusAuth *auth, 2333 const DBusString *context) 2334{ 2335 return _dbus_string_replace_len (context, 0, _dbus_string_get_length (context), 2336 &auth->context, 0, _dbus_string_get_length (context)); 2337} 2338 2339/** @} */ 2340 2341#ifdef DBUS_BUILD_TESTS 2342#include "dbus-test.h" 2343#include "dbus-auth-script.h" 2344#include <stdio.h> 2345 2346static dbus_bool_t 2347process_test_subdir (const DBusString *test_base_dir, 2348 const char *subdir) 2349{ 2350 DBusString test_directory; 2351 DBusString filename; 2352 DBusDirIter *dir; 2353 dbus_bool_t retval; 2354 DBusError error; 2355 2356 retval = FALSE; 2357 dir = NULL; 2358 2359 if (!_dbus_string_init (&test_directory)) 2360 _dbus_assert_not_reached ("didn't allocate test_directory\n"); 2361 2362 _dbus_string_init_const (&filename, subdir); 2363 2364 if (!_dbus_string_copy (test_base_dir, 0, 2365 &test_directory, 0)) 2366 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory"); 2367 2368 if (!_dbus_concat_dir_and_file (&test_directory, &filename)) 2369 _dbus_assert_not_reached ("couldn't allocate full path"); 2370 2371 _dbus_string_free (&filename); 2372 if (!_dbus_string_init (&filename)) 2373 _dbus_assert_not_reached ("didn't allocate filename string\n"); 2374 2375 dbus_error_init (&error); 2376 dir = _dbus_directory_open (&test_directory, &error); 2377 if (dir == NULL) 2378 { 2379 _dbus_warn ("Could not open %s: %s\n", 2380 _dbus_string_get_const_data (&test_directory), 2381 error.message); 2382 dbus_error_free (&error); 2383 goto failed; 2384 } 2385 2386 printf ("Testing %s:\n", subdir); 2387 2388 next: 2389 while (_dbus_directory_get_next_file (dir, &filename, &error)) 2390 { 2391 DBusString full_path; 2392 2393 if (!_dbus_string_init (&full_path)) 2394 _dbus_assert_not_reached ("couldn't init string"); 2395 2396 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0)) 2397 _dbus_assert_not_reached ("couldn't copy dir to full_path"); 2398 2399 if (!_dbus_concat_dir_and_file (&full_path, &filename)) 2400 _dbus_assert_not_reached ("couldn't concat file to dir"); 2401 2402 if (!_dbus_string_ends_with_c_str (&filename, ".auth-script")) 2403 { 2404 _dbus_verbose ("Skipping non-.auth-script file %s\n", 2405 _dbus_string_get_const_data (&filename)); 2406 _dbus_string_free (&full_path); 2407 goto next; 2408 } 2409 2410 printf (" %s\n", _dbus_string_get_const_data (&filename)); 2411 2412 if (!_dbus_auth_script_run (&full_path)) 2413 { 2414 _dbus_string_free (&full_path); 2415 goto failed; 2416 } 2417 else 2418 _dbus_string_free (&full_path); 2419 } 2420 2421 if (dbus_error_is_set (&error)) 2422 { 2423 _dbus_warn ("Could not get next file in %s: %s\n", 2424 _dbus_string_get_const_data (&test_directory), error.message); 2425 dbus_error_free (&error); 2426 goto failed; 2427 } 2428 2429 retval = TRUE; 2430 2431 failed: 2432 2433 if (dir) 2434 _dbus_directory_close (dir); 2435 _dbus_string_free (&test_directory); 2436 _dbus_string_free (&filename); 2437 2438 return retval; 2439} 2440 2441static dbus_bool_t 2442process_test_dirs (const char *test_data_dir) 2443{ 2444 DBusString test_directory; 2445 dbus_bool_t retval; 2446 2447 retval = FALSE; 2448 2449 _dbus_string_init_const (&test_directory, test_data_dir); 2450 2451 if (!process_test_subdir (&test_directory, "auth")) 2452 goto failed; 2453 2454 retval = TRUE; 2455 2456 failed: 2457 2458 _dbus_string_free (&test_directory); 2459 2460 return retval; 2461} 2462 2463dbus_bool_t 2464_dbus_auth_test (const char *test_data_dir) 2465{ 2466 2467 if (test_data_dir == NULL) 2468 return TRUE; 2469 2470 if (!process_test_dirs (test_data_dir)) 2471 return FALSE; 2472 2473 return TRUE; 2474} 2475 2476#endif /* DBUS_BUILD_TESTS */ 2477