D-Bus  1.4.10
dbus-transport.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003 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-transport-protected.h"
26 #include "dbus-transport-unix.h"
27 #include "dbus-transport-socket.h"
28 #include "dbus-connection-internal.h"
29 #include "dbus-watch.h"
30 #include "dbus-auth.h"
31 #include "dbus-address.h"
32 #include "dbus-credentials.h"
33 #include "dbus-mainloop.h"
34 #include "dbus-message-private.h"
35 #include "dbus-marshal-header.h"
36 #ifdef DBUS_BUILD_TESTS
37 #include "dbus-server-debug-pipe.h"
38 #endif
39 
61 static void
62 live_messages_notify (DBusCounter *counter,
63  void *user_data)
64 {
65  DBusTransport *transport = user_data;
66 
67  _dbus_transport_ref (transport);
68 
69 #if 0
70  _dbus_verbose ("Size counter value is now %d\n",
71  (int) _dbus_counter_get_size_value (counter));
72  _dbus_verbose ("Unix FD counter value is now %d\n",
73  (int) _dbus_counter_get_unix_fd_value (counter));
74 #endif
75 
76  /* disable or re-enable the read watch for the transport if
77  * required.
78  */
79  if (transport->vtable->live_messages_changed)
80  (* transport->vtable->live_messages_changed) (transport);
81 
82  _dbus_transport_unref (transport);
83 }
84 
100  const DBusTransportVTable *vtable,
101  const DBusString *server_guid,
102  const DBusString *address)
103 {
104  DBusMessageLoader *loader;
105  DBusAuth *auth;
106  DBusCounter *counter;
107  char *address_copy;
108  DBusCredentials *creds;
109 
110  loader = _dbus_message_loader_new ();
111  if (loader == NULL)
112  return FALSE;
113 
114  if (server_guid)
115  auth = _dbus_auth_server_new (server_guid);
116  else
117  auth = _dbus_auth_client_new ();
118  if (auth == NULL)
119  {
121  return FALSE;
122  }
123 
124  counter = _dbus_counter_new ();
125  if (counter == NULL)
126  {
127  _dbus_auth_unref (auth);
129  return FALSE;
130  }
131 
132  creds = _dbus_credentials_new ();
133  if (creds == NULL)
134  {
135  _dbus_counter_unref (counter);
136  _dbus_auth_unref (auth);
138  return FALSE;
139  }
140 
141  if (server_guid)
142  {
143  _dbus_assert (address == NULL);
144  address_copy = NULL;
145  }
146  else
147  {
148  _dbus_assert (address != NULL);
149 
150  if (!_dbus_string_copy_data (address, &address_copy))
151  {
152  _dbus_credentials_unref (creds);
153  _dbus_counter_unref (counter);
154  _dbus_auth_unref (auth);
156  return FALSE;
157  }
158  }
159 
160  transport->refcount = 1;
161  transport->vtable = vtable;
162  transport->loader = loader;
163  transport->auth = auth;
164  transport->live_messages = counter;
165  transport->authenticated = FALSE;
166  transport->disconnected = FALSE;
167  transport->is_server = (server_guid != NULL);
168  transport->send_credentials_pending = !transport->is_server;
169  transport->receive_credentials_pending = transport->is_server;
170  transport->address = address_copy;
171 
172  transport->unix_user_function = NULL;
173  transport->unix_user_data = NULL;
174  transport->free_unix_user_data = NULL;
175 
176  transport->windows_user_function = NULL;
177  transport->windows_user_data = NULL;
178  transport->free_windows_user_data = NULL;
179 
180  transport->expected_guid = NULL;
181 
182  /* Try to default to something that won't totally hose the system,
183  * but doesn't impose too much of a limitation.
184  */
185  transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
186 
187  /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
188  should be more than enough */
189  transport->max_live_messages_unix_fds = 4096;
190 
191  /* credentials read from socket if any */
192  transport->credentials = creds;
193 
195  transport->max_live_messages_size,
196  transport->max_live_messages_unix_fds,
197  live_messages_notify,
198  transport);
199 
200  if (transport->address)
201  _dbus_verbose ("Initialized transport on address %s\n", transport->address);
202 
203  return TRUE;
204 }
205 
212 void
214 {
215  if (!transport->disconnected)
216  _dbus_transport_disconnect (transport);
217 
218  if (transport->free_unix_user_data != NULL)
219  (* transport->free_unix_user_data) (transport->unix_user_data);
220 
221  if (transport->free_windows_user_data != NULL)
222  (* transport->free_windows_user_data) (transport->windows_user_data);
223 
224  _dbus_message_loader_unref (transport->loader);
225  _dbus_auth_unref (transport->auth);
227  0, 0, NULL, NULL);
228  _dbus_counter_unref (transport->live_messages);
229  dbus_free (transport->address);
230  dbus_free (transport->expected_guid);
231  if (transport->credentials)
233 }
234 
235 
245 static DBusTransport*
246 check_address (const char *address, DBusError *error)
247 {
248  DBusAddressEntry **entries;
249  DBusTransport *transport = NULL;
250  int len, i;
251 
252  _dbus_assert (address != NULL);
253  _dbus_assert (*address != '\0');
254 
255  if (!dbus_parse_address (address, &entries, &len, error))
256  return NULL; /* not a valid address */
257 
258  for (i = 0; i < len; i++)
259  {
260  transport = _dbus_transport_open (entries[i], error);
261  if (transport != NULL)
262  break;
263  }
264 
265  dbus_address_entries_free (entries);
266  return transport;
267 }
268 
276 static DBusTransport*
277 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
278 {
279  DBusString address;
280  DBusTransport *result = NULL;
281 
282  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
283 
284  if (!_dbus_string_init (&address))
285  {
287  return NULL;
288  }
289 
290  if (!_dbus_get_autolaunch_address (scope, &address, error))
291  {
292  _DBUS_ASSERT_ERROR_IS_SET (error);
293  goto out;
294  }
295 
296  result = check_address (_dbus_string_get_const_data (&address), error);
297  if (result == NULL)
298  _DBUS_ASSERT_ERROR_IS_SET (error);
299  else
300  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
301 
302  out:
303  _dbus_string_free (&address);
304  return result;
305 }
306 
307 static DBusTransportOpenResult
308 _dbus_transport_open_autolaunch (DBusAddressEntry *entry,
309  DBusTransport **transport_p,
310  DBusError *error)
311 {
312  const char *method;
313 
314  method = dbus_address_entry_get_method (entry);
315  _dbus_assert (method != NULL);
316 
317  if (strcmp (method, "autolaunch") == 0)
318  {
319  const char *scope = dbus_address_entry_get_value (entry, "scope");
320 
321  *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
322 
323  if (*transport_p == NULL)
324  {
325  _DBUS_ASSERT_ERROR_IS_SET (error);
326  return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
327  }
328  else
329  {
330  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
331  return DBUS_TRANSPORT_OPEN_OK;
332  }
333  }
334  else
335  {
336  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
337  return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
338  }
339 }
340 
341 static const struct {
342  DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
343  DBusTransport **transport_p,
344  DBusError *error);
345 } open_funcs[] = {
348  { _dbus_transport_open_autolaunch }
349 #ifdef DBUS_BUILD_TESTS
350  , { _dbus_transport_open_debug_pipe }
351 #endif
352 };
353 
364  DBusError *error)
365 {
366  DBusTransport *transport;
367  const char *expected_guid_orig;
368  char *expected_guid;
369  int i;
370  DBusError tmp_error = DBUS_ERROR_INIT;
371 
372  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
373 
374  transport = NULL;
375  expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
376  expected_guid = _dbus_strdup (expected_guid_orig);
377 
378  if (expected_guid_orig != NULL && expected_guid == NULL)
379  {
380  _DBUS_SET_OOM (error);
381  return NULL;
382  }
383 
384  for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
385  {
386  DBusTransportOpenResult result;
387 
388  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
389  result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
390 
391  switch (result)
392  {
393  case DBUS_TRANSPORT_OPEN_OK:
394  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
395  goto out;
396  break;
397  case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
398  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
399  /* keep going through the loop of open funcs */
400  break;
401  case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
402  _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
403  goto out;
404  break;
405  case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
406  _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
407  goto out;
408  break;
409  }
410  }
411 
412  out:
413 
414  if (transport == NULL)
415  {
416  if (!dbus_error_is_set (&tmp_error))
417  _dbus_set_bad_address (&tmp_error,
418  NULL, NULL,
419  "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
420 
421  _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
422  dbus_move_error(&tmp_error, error);
423  dbus_free (expected_guid);
424  }
425  else
426  {
427  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
428 
429  /* In the case of autostart the initial guid is NULL
430  * and the autostart transport recursively calls
431  * _dbus_open_transport wich returns a transport
432  * with a guid. That guid is the definitive one.
433  *
434  * FIXME: if more transports are added they may have
435  * an effect on the expected_guid semantics (i.e.
436  * expected_guid and transport->expected_guid may
437  * both have values). This is very unlikely though
438  * we should either throw asserts here for those
439  * corner cases or refactor the code so it is
440  * clearer on what is expected and what is not
441  */
442  if(expected_guid)
443  transport->expected_guid = expected_guid;
444  }
445 
446  return transport;
447 }
448 
457 {
458  _dbus_assert (transport->refcount > 0);
459 
460  transport->refcount += 1;
461 
462  return transport;
463 }
464 
472 void
474 {
475  _dbus_assert (transport != NULL);
476  _dbus_assert (transport->refcount > 0);
477 
478  transport->refcount -= 1;
479  if (transport->refcount == 0)
480  {
481  _dbus_verbose ("finalizing\n");
482 
483  _dbus_assert (transport->vtable->finalize != NULL);
484 
485  (* transport->vtable->finalize) (transport);
486  }
487 }
488 
497 void
499 {
500  _dbus_verbose ("start\n");
501 
502  _dbus_assert (transport->vtable->disconnect != NULL);
503 
504  if (transport->disconnected)
505  return;
506 
507  (* transport->vtable->disconnect) (transport);
508 
509  transport->disconnected = TRUE;
510 
511  _dbus_verbose ("end\n");
512 }
513 
524 {
525  return !transport->disconnected;
526 }
527 
528 static dbus_bool_t
529 auth_via_unix_user_function (DBusTransport *transport)
530 {
531  DBusCredentials *auth_identity;
532  dbus_bool_t allow;
533  DBusConnection *connection;
534  DBusAllowUnixUserFunction unix_user_function;
535  void *unix_user_data;
536  dbus_uid_t uid;
537 
538  /* Dropping the lock here probably isn't that safe. */
539 
540  auth_identity = _dbus_auth_get_identity (transport->auth);
541  _dbus_assert (auth_identity != NULL);
542 
543  connection = transport->connection;
544  unix_user_function = transport->unix_user_function;
545  unix_user_data = transport->unix_user_data;
546  uid = _dbus_credentials_get_unix_uid (auth_identity);
547 
548  _dbus_verbose ("unlock\n");
549  _dbus_connection_unlock (connection);
550 
551  allow = (* unix_user_function) (connection,
552  uid,
553  unix_user_data);
554 
555  _dbus_verbose ("lock post unix user function\n");
556  _dbus_connection_lock (connection);
557 
558  if (allow)
559  {
560  _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
561  }
562  else
563  {
564  _dbus_verbose ("Client UID "DBUS_UID_FORMAT
565  " was rejected, disconnecting\n",
566  _dbus_credentials_get_unix_uid (auth_identity));
567  _dbus_transport_disconnect (transport);
568  }
569 
570  return allow;
571 }
572 
573 static dbus_bool_t
574 auth_via_windows_user_function (DBusTransport *transport)
575 {
576  DBusCredentials *auth_identity;
577  dbus_bool_t allow;
578  DBusConnection *connection;
579  DBusAllowWindowsUserFunction windows_user_function;
580  void *windows_user_data;
581  char *windows_sid;
582 
583  /* Dropping the lock here probably isn't that safe. */
584 
585  auth_identity = _dbus_auth_get_identity (transport->auth);
586  _dbus_assert (auth_identity != NULL);
587 
588  connection = transport->connection;
589  windows_user_function = transport->windows_user_function;
590  windows_user_data = transport->unix_user_data;
591  windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
592 
593  if (windows_sid == NULL)
594  {
595  /* OOM */
596  return FALSE;
597  }
598 
599  _dbus_verbose ("unlock\n");
600  _dbus_connection_unlock (connection);
601 
602  allow = (* windows_user_function) (connection,
603  windows_sid,
604  windows_user_data);
605 
606  _dbus_verbose ("lock post windows user function\n");
607  _dbus_connection_lock (connection);
608 
609  if (allow)
610  {
611  _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
612  }
613  else
614  {
615  _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
616  _dbus_credentials_get_windows_sid (auth_identity));
617  _dbus_transport_disconnect (transport);
618  }
619 
620  return allow;
621 }
622 
623 static dbus_bool_t
624 auth_via_default_rules (DBusTransport *transport)
625 {
626  DBusCredentials *auth_identity;
627  DBusCredentials *our_identity;
628  dbus_bool_t allow;
629 
630  auth_identity = _dbus_auth_get_identity (transport->auth);
631  _dbus_assert (auth_identity != NULL);
632 
633  /* By default, connection is allowed if the client is 1) root or 2)
634  * has the same UID as us or 3) anonymous is allowed.
635  */
636 
638  if (our_identity == NULL)
639  {
640  /* OOM */
641  return FALSE;
642  }
643 
644  if (transport->allow_anonymous ||
645  _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
646  _dbus_credentials_same_user (our_identity,
647  auth_identity))
648  {
649  if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
650  _dbus_verbose ("Client authorized as SID '%s'"
651  "matching our SID '%s'\n",
652  _dbus_credentials_get_windows_sid(auth_identity),
653  _dbus_credentials_get_windows_sid(our_identity));
654  else
655  _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
656  " matching our UID "DBUS_UID_FORMAT"\n",
657  _dbus_credentials_get_unix_uid(auth_identity),
658  _dbus_credentials_get_unix_uid(our_identity));
659  /* We have authenticated! */
660  allow = TRUE;
661  }
662  else
663  {
664  if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
665  _dbus_verbose ("Client authorized as SID '%s'"
666  " but our SID is '%s', disconnecting\n",
667  (_dbus_credentials_get_windows_sid(auth_identity) ?
668  _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
669  (_dbus_credentials_get_windows_sid(our_identity) ?
670  _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
671  else
672  _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
673  " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
674  _dbus_credentials_get_unix_uid(auth_identity),
675  _dbus_credentials_get_unix_uid(our_identity));
676  _dbus_transport_disconnect (transport);
677  allow = FALSE;
678  }
679 
680  _dbus_credentials_unref (our_identity);
681 
682  return allow;
683 }
684 
685 
698 {
699  if (transport->authenticated)
700  return TRUE;
701  else
702  {
703  dbus_bool_t maybe_authenticated;
704 
705  if (transport->disconnected)
706  return FALSE;
707 
708  /* paranoia ref since we call user callbacks sometimes */
710 
711  maybe_authenticated =
712  (!(transport->send_credentials_pending ||
713  transport->receive_credentials_pending));
714 
715  if (maybe_authenticated)
716  {
717  switch (_dbus_auth_do_work (transport->auth))
718  {
719  case DBUS_AUTH_STATE_AUTHENTICATED:
720  /* leave as maybe_authenticated */
721  break;
722  default:
723  maybe_authenticated = FALSE;
724  }
725  }
726 
727  /* If we're the client, verify the GUID
728  */
729  if (maybe_authenticated && !transport->is_server)
730  {
731  const char *server_guid;
732 
733  server_guid = _dbus_auth_get_guid_from_server (transport->auth);
734  _dbus_assert (server_guid != NULL);
735 
736  if (transport->expected_guid &&
737  strcmp (transport->expected_guid, server_guid) != 0)
738  {
739  _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
740  transport->expected_guid, server_guid);
741  _dbus_transport_disconnect (transport);
743  return FALSE;
744  }
745  }
746 
747  /* If we're the server, see if we want to allow this identity to proceed.
748  */
749  if (maybe_authenticated && transport->is_server)
750  {
751  dbus_bool_t allow;
752  DBusCredentials *auth_identity;
753 
754  auth_identity = _dbus_auth_get_identity (transport->auth);
755  _dbus_assert (auth_identity != NULL);
756 
757  /* If we have an auth'd user and a user function, delegate
758  * deciding whether auth credentials are good enough to the
759  * app; otherwise, use our default decision process.
760  */
761  if (transport->unix_user_function != NULL &&
762  _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
763  {
764  allow = auth_via_unix_user_function (transport);
765  }
766  else if (transport->windows_user_function != NULL &&
767  _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
768  {
769  allow = auth_via_windows_user_function (transport);
770  }
771  else
772  {
773  allow = auth_via_default_rules (transport);
774  }
775 
776  if (!allow)
777  maybe_authenticated = FALSE;
778  }
779 
780  transport->authenticated = maybe_authenticated;
781 
783  return maybe_authenticated;
784  }
785 }
786 
795 {
796  DBusCredentials *auth_identity;
797 
798  if (!transport->authenticated)
799  return TRUE;
800 
801  auth_identity = _dbus_auth_get_identity (transport->auth);
802 
803  if (_dbus_credentials_are_anonymous (auth_identity))
804  return TRUE;
805  else
806  return FALSE;
807 }
808 
817 {
818  return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
819 }
820 
828 const char*
830 {
831  return transport->address;
832 }
833 
841 const char*
843 {
844  if (transport->is_server)
845  return NULL;
846  else if (transport->authenticated)
847  return _dbus_auth_get_guid_from_server (transport->auth);
848  else
849  return transport->expected_guid;
850 }
851 
863  DBusWatch *watch,
864  unsigned int condition)
865 {
866  dbus_bool_t retval;
867 
868  _dbus_assert (transport->vtable->handle_watch != NULL);
869 
870  if (transport->disconnected)
871  return TRUE;
872 
873  if (dbus_watch_get_socket (watch) < 0)
874  {
875  _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
876  return TRUE;
877  }
878 
879  _dbus_watch_sanitize_condition (watch, &condition);
880 
881  _dbus_transport_ref (transport);
882  _dbus_watch_ref (watch);
883  retval = (* transport->vtable->handle_watch) (transport, watch, condition);
884  _dbus_watch_unref (watch);
885  _dbus_transport_unref (transport);
886 
887  return retval;
888 }
889 
901  DBusConnection *connection)
902 {
903  _dbus_assert (transport->vtable->connection_set != NULL);
904  _dbus_assert (transport->connection == NULL);
905 
906  transport->connection = connection;
907 
908  _dbus_transport_ref (transport);
909  if (!(* transport->vtable->connection_set) (transport))
910  transport->connection = NULL;
911  _dbus_transport_unref (transport);
912 
913  return transport->connection != NULL;
914 }
915 
925  int *fd_p)
926 {
927  dbus_bool_t retval;
928 
929  if (transport->vtable->get_socket_fd == NULL)
930  return FALSE;
931 
932  if (transport->disconnected)
933  return FALSE;
934 
935  _dbus_transport_ref (transport);
936 
937  retval = (* transport->vtable->get_socket_fd) (transport,
938  fd_p);
939 
940  _dbus_transport_unref (transport);
941 
942  return retval;
943 }
944 
956 void
958  unsigned int flags,
959  int timeout_milliseconds)
960 {
961  _dbus_assert (transport->vtable->do_iteration != NULL);
962 
963  _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
964  flags, timeout_milliseconds, !transport->disconnected);
965 
966  if ((flags & (DBUS_ITERATION_DO_WRITING |
967  DBUS_ITERATION_DO_READING)) == 0)
968  return; /* Nothing to do */
969 
970  if (transport->disconnected)
971  return;
972 
973  _dbus_transport_ref (transport);
974  (* transport->vtable->do_iteration) (transport, flags,
975  timeout_milliseconds);
976  _dbus_transport_unref (transport);
977 
978  _dbus_verbose ("end\n");
979 }
980 
981 static dbus_bool_t
982 recover_unused_bytes (DBusTransport *transport)
983 {
984  if (_dbus_auth_needs_decoding (transport->auth))
985  {
986  DBusString plaintext;
987  const DBusString *encoded;
988  DBusString *buffer;
989  int orig_len;
990 
991  if (!_dbus_string_init (&plaintext))
992  goto nomem;
993 
994  _dbus_auth_get_unused_bytes (transport->auth,
995  &encoded);
996 
997  if (!_dbus_auth_decode_data (transport->auth,
998  encoded, &plaintext))
999  {
1000  _dbus_string_free (&plaintext);
1001  goto nomem;
1002  }
1003 
1005  &buffer);
1006 
1007  orig_len = _dbus_string_get_length (buffer);
1008 
1009  if (!_dbus_string_move (&plaintext, 0, buffer,
1010  orig_len))
1011  {
1012  _dbus_string_free (&plaintext);
1013  goto nomem;
1014  }
1015 
1016  _dbus_verbose (" %d unused bytes sent to message loader\n",
1017  _dbus_string_get_length (buffer) -
1018  orig_len);
1019 
1021  buffer,
1022  _dbus_string_get_length (buffer) -
1023  orig_len);
1024 
1025  _dbus_auth_delete_unused_bytes (transport->auth);
1026 
1027  _dbus_string_free (&plaintext);
1028  }
1029  else
1030  {
1031  const DBusString *bytes;
1032  DBusString *buffer;
1033  int orig_len;
1034  dbus_bool_t succeeded;
1035 
1037  &buffer);
1038 
1039  orig_len = _dbus_string_get_length (buffer);
1040 
1041  _dbus_auth_get_unused_bytes (transport->auth,
1042  &bytes);
1043 
1044  succeeded = TRUE;
1045  if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
1046  succeeded = FALSE;
1047 
1048  _dbus_verbose (" %d unused bytes sent to message loader\n",
1049  _dbus_string_get_length (buffer) -
1050  orig_len);
1051 
1053  buffer,
1054  _dbus_string_get_length (buffer) -
1055  orig_len);
1056 
1057  if (succeeded)
1058  _dbus_auth_delete_unused_bytes (transport->auth);
1059  else
1060  goto nomem;
1061  }
1062 
1063  return TRUE;
1064 
1065  nomem:
1066  _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
1067  return FALSE;
1068 }
1069 
1079 {
1080  if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
1082  return DBUS_DISPATCH_COMPLETE; /* complete for now */
1083 
1084  if (!_dbus_transport_get_is_authenticated (transport))
1085  {
1086  if (_dbus_auth_do_work (transport->auth) ==
1087  DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
1089  else if (!_dbus_transport_get_is_authenticated (transport))
1090  return DBUS_DISPATCH_COMPLETE;
1091  }
1092 
1093  if (!transport->unused_bytes_recovered &&
1094  !recover_unused_bytes (transport))
1096 
1097  transport->unused_bytes_recovered = TRUE;
1098 
1099  if (!_dbus_message_loader_queue_messages (transport->loader))
1101 
1102  if (_dbus_message_loader_peek_message (transport->loader) != NULL)
1104  else
1105  return DBUS_DISPATCH_COMPLETE;
1106 }
1107 
1118 {
1119  DBusDispatchStatus status;
1120 
1121 #if 0
1122  _dbus_verbose ("_dbus_transport_queue_messages()\n");
1123 #endif
1124 
1125  /* Queue any messages */
1126  while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
1127  {
1128  DBusMessage *message;
1129  DBusList *link;
1130 
1131  link = _dbus_message_loader_pop_message_link (transport->loader);
1132  _dbus_assert (link != NULL);
1133 
1134  message = link->data;
1135 
1136  _dbus_verbose ("queueing received message %p\n", message);
1137 
1138  if (!_dbus_message_add_counter (message, transport->live_messages))
1139  {
1141  link);
1142  status = DBUS_DISPATCH_NEED_MEMORY;
1143  break;
1144  }
1145  else
1146  {
1147  /* pass ownership of link and message ref to connection */
1149  link);
1150  }
1151  }
1152 
1154  {
1155  _dbus_verbose ("Corrupted message stream, disconnecting\n");
1156  _dbus_transport_disconnect (transport);
1157  }
1158 
1159  return status != DBUS_DISPATCH_NEED_MEMORY;
1160 }
1161 
1168 void
1170  long size)
1171 {
1173 }
1174 
1181 void
1183  long n)
1184 {
1186 }
1187 
1194 long
1196 {
1198 }
1199 
1206 long
1208 {
1210 }
1211 
1218 void
1220  long size)
1221 {
1222  transport->max_live_messages_size = size;
1224  transport->max_live_messages_size,
1225  transport->max_live_messages_unix_fds,
1226  live_messages_notify,
1227  transport);
1228 }
1229 
1236 void
1238  long n)
1239 {
1240  transport->max_live_messages_unix_fds = n;
1242  transport->max_live_messages_size,
1243  transport->max_live_messages_unix_fds,
1244  live_messages_notify,
1245  transport);
1246 }
1247 
1254 long
1256 {
1257  return transport->max_live_messages_size;
1258 }
1259 
1266 long
1268 {
1269  return transport->max_live_messages_unix_fds;
1270 }
1271 
1281  unsigned long *uid)
1282 {
1283  DBusCredentials *auth_identity;
1284 
1285  *uid = _DBUS_INT32_MAX; /* better than some root or system user in
1286  * case of bugs in the caller. Caller should
1287  * never use this value on purpose, however.
1288  */
1289 
1290  if (!transport->authenticated)
1291  return FALSE;
1292 
1293  auth_identity = _dbus_auth_get_identity (transport->auth);
1294 
1295  if (_dbus_credentials_include (auth_identity,
1296  DBUS_CREDENTIAL_UNIX_USER_ID))
1297  {
1298  *uid = _dbus_credentials_get_unix_uid (auth_identity);
1299  return TRUE;
1300  }
1301  else
1302  return FALSE;
1303 }
1304 
1314  unsigned long *pid)
1315 {
1316  DBusCredentials *auth_identity;
1317 
1318  *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
1319  * but we set it to a safe number, INT_MAX,
1320  * just to root out possible bugs in bad callers.
1321  */
1322 
1323  if (!transport->authenticated)
1324  return FALSE;
1325 
1326  auth_identity = _dbus_auth_get_identity (transport->auth);
1327 
1328  if (_dbus_credentials_include (auth_identity,
1329  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
1330  {
1331  *pid = _dbus_credentials_get_unix_pid (auth_identity);
1332  return TRUE;
1333  }
1334  else
1335  return FALSE;
1336 }
1337 
1348  void **data,
1349  int *data_size)
1350 {
1351  DBusCredentials *auth_identity;
1352 
1353  *data = NULL;
1354  *data_size = 0;
1355 
1356  if (!transport->authenticated)
1357  return FALSE;
1358 
1359  auth_identity = _dbus_auth_get_identity (transport->auth);
1360 
1361  if (_dbus_credentials_include (auth_identity,
1362  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
1363  {
1364  *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
1365  *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
1366  return TRUE;
1367  }
1368  else
1369  return FALSE;
1370 }
1371 
1382 void
1384  DBusAllowUnixUserFunction function,
1385  void *data,
1386  DBusFreeFunction free_data_function,
1387  void **old_data,
1388  DBusFreeFunction *old_free_data_function)
1389 {
1390  *old_data = transport->unix_user_data;
1391  *old_free_data_function = transport->free_unix_user_data;
1392 
1393  transport->unix_user_function = function;
1394  transport->unix_user_data = data;
1395  transport->free_unix_user_data = free_data_function;
1396 }
1397 
1407  char **windows_sid_p)
1408 {
1409  DBusCredentials *auth_identity;
1410 
1411  *windows_sid_p = NULL;
1412 
1413  if (!transport->authenticated)
1414  return FALSE;
1415 
1416  auth_identity = _dbus_auth_get_identity (transport->auth);
1417 
1418  if (_dbus_credentials_include (auth_identity,
1419  DBUS_CREDENTIAL_WINDOWS_SID))
1420  {
1421  /* If no memory, we are supposed to return TRUE and set NULL */
1422  *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
1423 
1424  return TRUE;
1425  }
1426  else
1427  return FALSE;
1428 }
1429 
1441 void
1444  void *data,
1445  DBusFreeFunction free_data_function,
1446  void **old_data,
1447  DBusFreeFunction *old_free_data_function)
1448 {
1449  *old_data = transport->windows_user_data;
1450  *old_free_data_function = transport->free_windows_user_data;
1451 
1452  transport->windows_user_function = function;
1453  transport->windows_user_data = data;
1454  transport->free_windows_user_data = free_data_function;
1455 }
1456 
1467  const char **mechanisms)
1468 {
1469  return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
1470 }
1471 
1478 void
1480  dbus_bool_t value)
1481 {
1482  transport->allow_anonymous = value != FALSE;
1483 }
1484