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