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