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