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.h"
35 #ifdef DBUS_BUILD_TESTS
36 #include "dbus-server-debug-pipe.h"
37 #endif
38
39 /**
40 * @defgroup DBusTransport DBusTransport object
41 * @ingroup DBusInternals
42 * @brief "Backend" for a DBusConnection.
43 *
44 * Types and functions related to DBusTransport. A transport is an
45 * abstraction that can send and receive data via various kinds of
46 * network connections or other IPC mechanisms.
47 *
48 * @{
49 */
50
51 /**
52 * @typedef DBusTransport
53 *
54 * Opaque object representing a way message stream.
55 * DBusTransport abstracts various kinds of actual
56 * transport mechanism, such as different network protocols,
57 * or encryption schemes.
58 */
59
60 static void
live_messages_notify(DBusCounter * counter,void * user_data)61 live_messages_notify (DBusCounter *counter,
62 void *user_data)
63 {
64 DBusTransport *transport = user_data;
65
66 _dbus_transport_ref (transport);
67
68 #if 0
69 _dbus_verbose ("Size counter value is now %d\n",
70 (int) _dbus_counter_get_size_value (counter));
71 _dbus_verbose ("Unix FD counter value is now %d\n",
72 (int) _dbus_counter_get_unix_fd_value (counter));
73 #endif
74
75 /* disable or re-enable the read watch for the transport if
76 * required.
77 */
78 if (transport->vtable->live_messages_changed)
79 {
80 _dbus_connection_lock (transport->connection);
81 (* transport->vtable->live_messages_changed) (transport);
82 _dbus_connection_unlock (transport->connection);
83 }
84
85 _dbus_transport_unref (transport);
86 }
87
88 /**
89 * Initializes the base class members of DBusTransport. Chained up to
90 * by subclasses in their constructor. The server GUID is the
91 * globally unique ID for the server creating this connection
92 * and will be #NULL for the client side of a connection. The GUID
93 * is in hex format.
94 *
95 * @param transport the transport being created.
96 * @param vtable the subclass vtable.
97 * @param server_guid non-#NULL if this transport is on the server side of a connection
98 * @param address the address of the transport
99 * @returns #TRUE on success.
100 */
101 dbus_bool_t
_dbus_transport_init_base(DBusTransport * transport,const DBusTransportVTable * vtable,const DBusString * server_guid,const DBusString * address)102 _dbus_transport_init_base (DBusTransport *transport,
103 const DBusTransportVTable *vtable,
104 const DBusString *server_guid,
105 const DBusString *address)
106 {
107 DBusMessageLoader *loader;
108 DBusAuth *auth;
109 DBusCounter *counter;
110 char *address_copy;
111 DBusCredentials *creds;
112
113 loader = _dbus_message_loader_new ();
114 if (loader == NULL)
115 return FALSE;
116
117 if (server_guid)
118 auth = _dbus_auth_server_new (server_guid);
119 else
120 auth = _dbus_auth_client_new ();
121 if (auth == NULL)
122 {
123 _dbus_message_loader_unref (loader);
124 return FALSE;
125 }
126
127 counter = _dbus_counter_new ();
128 if (counter == NULL)
129 {
130 _dbus_auth_unref (auth);
131 _dbus_message_loader_unref (loader);
132 return FALSE;
133 }
134
135 creds = _dbus_credentials_new ();
136 if (creds == NULL)
137 {
138 _dbus_counter_unref (counter);
139 _dbus_auth_unref (auth);
140 _dbus_message_loader_unref (loader);
141 return FALSE;
142 }
143
144 if (server_guid)
145 {
146 _dbus_assert (address == NULL);
147 address_copy = NULL;
148 }
149 else
150 {
151 _dbus_assert (address != NULL);
152
153 if (!_dbus_string_copy_data (address, &address_copy))
154 {
155 _dbus_credentials_unref (creds);
156 _dbus_counter_unref (counter);
157 _dbus_auth_unref (auth);
158 _dbus_message_loader_unref (loader);
159 return FALSE;
160 }
161 }
162
163 transport->refcount = 1;
164 transport->vtable = vtable;
165 transport->loader = loader;
166 transport->auth = auth;
167 transport->live_messages = counter;
168 transport->authenticated = FALSE;
169 transport->disconnected = FALSE;
170 transport->is_server = (server_guid != NULL);
171 transport->send_credentials_pending = !transport->is_server;
172 transport->receive_credentials_pending = transport->is_server;
173 transport->address = address_copy;
174
175 transport->unix_user_function = NULL;
176 transport->unix_user_data = NULL;
177 transport->free_unix_user_data = NULL;
178
179 transport->windows_user_function = NULL;
180 transport->windows_user_data = NULL;
181 transport->free_windows_user_data = NULL;
182
183 transport->expected_guid = NULL;
184
185 /* Try to default to something that won't totally hose the system,
186 * but doesn't impose too much of a limitation.
187 */
188 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
189
190 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
191 should be more than enough */
192 transport->max_live_messages_unix_fds = 4096;
193
194 /* credentials read from socket if any */
195 transport->credentials = creds;
196
197 _dbus_counter_set_notify (transport->live_messages,
198 transport->max_live_messages_size,
199 transport->max_live_messages_unix_fds,
200 live_messages_notify,
201 transport);
202
203 if (transport->address)
204 _dbus_verbose ("Initialized transport on address %s\n", transport->address);
205
206 return TRUE;
207 }
208
209 /**
210 * Finalizes base class members of DBusTransport.
211 * Chained up to from subclass finalizers.
212 *
213 * @param transport the transport.
214 */
215 void
_dbus_transport_finalize_base(DBusTransport * transport)216 _dbus_transport_finalize_base (DBusTransport *transport)
217 {
218 if (!transport->disconnected)
219 _dbus_transport_disconnect (transport);
220
221 if (transport->free_unix_user_data != NULL)
222 (* transport->free_unix_user_data) (transport->unix_user_data);
223
224 if (transport->free_windows_user_data != NULL)
225 (* transport->free_windows_user_data) (transport->windows_user_data);
226
227 _dbus_message_loader_unref (transport->loader);
228 _dbus_auth_unref (transport->auth);
229 _dbus_counter_set_notify (transport->live_messages,
230 0, 0, NULL, NULL);
231 _dbus_counter_unref (transport->live_messages);
232 dbus_free (transport->address);
233 dbus_free (transport->expected_guid);
234 if (transport->credentials)
235 _dbus_credentials_unref (transport->credentials);
236 }
237
238
239 /**
240 * Verifies if a given D-Bus address is a valid address
241 * by attempting to connect to it. If it is, returns the
242 * opened DBusTransport object. If it isn't, returns #NULL
243 * and sets @p error.
244 *
245 * @param error address where an error can be returned.
246 * @returns a new transport, or #NULL on failure.
247 */
248 static DBusTransport*
check_address(const char * address,DBusError * error)249 check_address (const char *address, DBusError *error)
250 {
251 DBusAddressEntry **entries;
252 DBusTransport *transport = NULL;
253 int len, i;
254
255 _dbus_assert (address != NULL);
256
257 if (!dbus_parse_address (address, &entries, &len, error))
258 return NULL; /* not a valid address */
259
260 for (i = 0; i < len; i++)
261 {
262 transport = _dbus_transport_open (entries[i], error);
263 if (transport != NULL)
264 break;
265 }
266
267 dbus_address_entries_free (entries);
268 return transport;
269 }
270
271 /**
272 * Creates a new transport for the "autostart" method.
273 * This creates a client-side of a transport.
274 *
275 * @param error address where an error can be returned.
276 * @returns a new transport, or #NULL on failure.
277 */
278 static DBusTransport*
_dbus_transport_new_for_autolaunch(const char * scope,DBusError * error)279 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
280 {
281 DBusString address;
282 DBusTransport *result = NULL;
283
284 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
285
286 if (!_dbus_string_init (&address))
287 {
288 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
289 return NULL;
290 }
291
292 if (!_dbus_get_autolaunch_address (scope, &address, error))
293 {
294 _DBUS_ASSERT_ERROR_IS_SET (error);
295 goto out;
296 }
297
298 result = check_address (_dbus_string_get_const_data (&address), error);
299 if (result == NULL)
300 _DBUS_ASSERT_ERROR_IS_SET (error);
301 else
302 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
303
304 out:
305 _dbus_string_free (&address);
306 return result;
307 }
308
309 static DBusTransportOpenResult
_dbus_transport_open_autolaunch(DBusAddressEntry * entry,DBusTransport ** transport_p,DBusError * error)310 _dbus_transport_open_autolaunch (DBusAddressEntry *entry,
311 DBusTransport **transport_p,
312 DBusError *error)
313 {
314 const char *method;
315
316 method = dbus_address_entry_get_method (entry);
317 _dbus_assert (method != NULL);
318
319 if (strcmp (method, "autolaunch") == 0)
320 {
321 const char *scope = dbus_address_entry_get_value (entry, "scope");
322
323 *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
324
325 if (*transport_p == NULL)
326 {
327 _DBUS_ASSERT_ERROR_IS_SET (error);
328 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
329 }
330 else
331 {
332 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
333 return DBUS_TRANSPORT_OPEN_OK;
334 }
335 }
336 else
337 {
338 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
339 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
340 }
341 }
342
343 static const struct {
344 DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
345 DBusTransport **transport_p,
346 DBusError *error);
347 } open_funcs[] = {
348 { _dbus_transport_open_socket },
349 { _dbus_transport_open_platform_specific },
350 { _dbus_transport_open_autolaunch }
351 #ifdef DBUS_BUILD_TESTS
352 , { _dbus_transport_open_debug_pipe }
353 #endif
354 };
355
356 /**
357 * Try to open a new transport for the given address entry. (This
358 * opens a client-side-of-the-connection transport.)
359 *
360 * @param entry the address entry
361 * @param error location to store reason for failure.
362 * @returns new transport of #NULL on failure.
363 */
364 DBusTransport*
_dbus_transport_open(DBusAddressEntry * entry,DBusError * error)365 _dbus_transport_open (DBusAddressEntry *entry,
366 DBusError *error)
367 {
368 DBusTransport *transport;
369 const char *expected_guid_orig;
370 char *expected_guid;
371 int i;
372 DBusError tmp_error = DBUS_ERROR_INIT;
373
374 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
375
376 transport = NULL;
377 expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
378 expected_guid = _dbus_strdup (expected_guid_orig);
379
380 if (expected_guid_orig != NULL && expected_guid == NULL)
381 {
382 _DBUS_SET_OOM (error);
383 return NULL;
384 }
385
386 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
387 {
388 DBusTransportOpenResult result;
389
390 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
391 result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
392
393 switch (result)
394 {
395 case DBUS_TRANSPORT_OPEN_OK:
396 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
397 goto out;
398 break;
399 case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
400 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
401 /* keep going through the loop of open funcs */
402 break;
403 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
404 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
405 goto out;
406 break;
407 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
408 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
409 goto out;
410 break;
411 }
412 }
413
414 out:
415
416 if (transport == NULL)
417 {
418 if (!dbus_error_is_set (&tmp_error))
419 _dbus_set_bad_address (&tmp_error,
420 NULL, NULL,
421 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
422
423 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
424 dbus_move_error(&tmp_error, error);
425 dbus_free (expected_guid);
426 }
427 else
428 {
429 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
430
431 /* In the case of autostart the initial guid is NULL
432 * and the autostart transport recursively calls
433 * _dbus_open_transport wich returns a transport
434 * with a guid. That guid is the definitive one.
435 *
436 * FIXME: if more transports are added they may have
437 * an effect on the expected_guid semantics (i.e.
438 * expected_guid and transport->expected_guid may
439 * both have values). This is very unlikely though
440 * we should either throw asserts here for those
441 * corner cases or refactor the code so it is
442 * clearer on what is expected and what is not
443 */
444 if(expected_guid)
445 transport->expected_guid = expected_guid;
446 }
447
448 return transport;
449 }
450
451 /**
452 * Increments the reference count for the transport.
453 *
454 * @param transport the transport.
455 * @returns the transport.
456 */
457 DBusTransport *
_dbus_transport_ref(DBusTransport * transport)458 _dbus_transport_ref (DBusTransport *transport)
459 {
460 _dbus_assert (transport->refcount > 0);
461
462 transport->refcount += 1;
463
464 return transport;
465 }
466
467 /**
468 * Decrements the reference count for the transport.
469 * Disconnects and finalizes the transport if
470 * the reference count reaches zero.
471 *
472 * @param transport the transport.
473 */
474 void
_dbus_transport_unref(DBusTransport * transport)475 _dbus_transport_unref (DBusTransport *transport)
476 {
477 _dbus_assert (transport != NULL);
478 _dbus_assert (transport->refcount > 0);
479
480 transport->refcount -= 1;
481 if (transport->refcount == 0)
482 {
483 _dbus_verbose ("finalizing\n");
484
485 _dbus_assert (transport->vtable->finalize != NULL);
486
487 (* transport->vtable->finalize) (transport);
488 }
489 }
490
491 /**
492 * Closes our end of the connection to a remote application. Further
493 * attempts to use this transport will fail. Only the first call to
494 * _dbus_transport_disconnect() will have an effect.
495 *
496 * @param transport the transport.
497 *
498 */
499 void
_dbus_transport_disconnect(DBusTransport * transport)500 _dbus_transport_disconnect (DBusTransport *transport)
501 {
502 _dbus_verbose ("start\n");
503
504 _dbus_assert (transport->vtable->disconnect != NULL);
505
506 if (transport->disconnected)
507 return;
508
509 (* transport->vtable->disconnect) (transport);
510
511 transport->disconnected = TRUE;
512
513 _dbus_verbose ("end\n");
514 }
515
516 /**
517 * Returns #TRUE if the transport has not been disconnected.
518 * Disconnection can result from _dbus_transport_disconnect()
519 * or because the server drops its end of the connection.
520 *
521 * @param transport the transport.
522 * @returns whether we're connected
523 */
524 dbus_bool_t
_dbus_transport_get_is_connected(DBusTransport * transport)525 _dbus_transport_get_is_connected (DBusTransport *transport)
526 {
527 return !transport->disconnected;
528 }
529
530 static dbus_bool_t
auth_via_unix_user_function(DBusTransport * transport)531 auth_via_unix_user_function (DBusTransport *transport)
532 {
533 DBusCredentials *auth_identity;
534 dbus_bool_t allow;
535 DBusConnection *connection;
536 DBusAllowUnixUserFunction unix_user_function;
537 void *unix_user_data;
538 dbus_uid_t uid;
539
540 /* Dropping the lock here probably isn't that safe. */
541
542 auth_identity = _dbus_auth_get_identity (transport->auth);
543 _dbus_assert (auth_identity != NULL);
544
545 connection = transport->connection;
546 unix_user_function = transport->unix_user_function;
547 unix_user_data = transport->unix_user_data;
548 uid = _dbus_credentials_get_unix_uid (auth_identity);
549
550 _dbus_verbose ("unlock\n");
551 _dbus_connection_unlock (connection);
552
553 allow = (* unix_user_function) (connection,
554 uid,
555 unix_user_data);
556
557 _dbus_verbose ("lock post unix user function\n");
558 _dbus_connection_lock (connection);
559
560 if (allow)
561 {
562 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
563 }
564 else
565 {
566 _dbus_verbose ("Client UID "DBUS_UID_FORMAT
567 " was rejected, disconnecting\n",
568 _dbus_credentials_get_unix_uid (auth_identity));
569 _dbus_transport_disconnect (transport);
570 }
571
572 return allow;
573 }
574
575 static dbus_bool_t
auth_via_windows_user_function(DBusTransport * transport)576 auth_via_windows_user_function (DBusTransport *transport)
577 {
578 DBusCredentials *auth_identity;
579 dbus_bool_t allow;
580 DBusConnection *connection;
581 DBusAllowWindowsUserFunction windows_user_function;
582 void *windows_user_data;
583 char *windows_sid;
584
585 /* Dropping the lock here probably isn't that safe. */
586
587 auth_identity = _dbus_auth_get_identity (transport->auth);
588 _dbus_assert (auth_identity != NULL);
589
590 connection = transport->connection;
591 windows_user_function = transport->windows_user_function;
592 windows_user_data = transport->unix_user_data;
593 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
594
595 if (windows_sid == NULL)
596 {
597 /* OOM */
598 return FALSE;
599 }
600
601 _dbus_verbose ("unlock\n");
602 _dbus_connection_unlock (connection);
603
604 allow = (* windows_user_function) (connection,
605 windows_sid,
606 windows_user_data);
607
608 _dbus_verbose ("lock post windows user function\n");
609 _dbus_connection_lock (connection);
610
611 if (allow)
612 {
613 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
614 }
615 else
616 {
617 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
618 _dbus_credentials_get_windows_sid (auth_identity));
619 _dbus_transport_disconnect (transport);
620 }
621
622 return allow;
623 }
624
625 static dbus_bool_t
auth_via_default_rules(DBusTransport * transport)626 auth_via_default_rules (DBusTransport *transport)
627 {
628 DBusCredentials *auth_identity;
629 DBusCredentials *our_identity;
630 dbus_bool_t allow;
631
632 auth_identity = _dbus_auth_get_identity (transport->auth);
633 _dbus_assert (auth_identity != NULL);
634
635 /* By default, connection is allowed if the client is 1) root or 2)
636 * has the same UID as us or 3) anonymous is allowed.
637 */
638
639 our_identity = _dbus_credentials_new_from_current_process ();
640 if (our_identity == NULL)
641 {
642 /* OOM */
643 return FALSE;
644 }
645
646 if (transport->allow_anonymous ||
647 _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
648 _dbus_credentials_same_user (our_identity,
649 auth_identity))
650 {
651 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
652 _dbus_verbose ("Client authorized as SID '%s'"
653 "matching our SID '%s'\n",
654 _dbus_credentials_get_windows_sid(auth_identity),
655 _dbus_credentials_get_windows_sid(our_identity));
656 else
657 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
658 " matching our UID "DBUS_UID_FORMAT"\n",
659 _dbus_credentials_get_unix_uid(auth_identity),
660 _dbus_credentials_get_unix_uid(our_identity));
661 /* We have authenticated! */
662 allow = TRUE;
663 }
664 else
665 {
666 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
667 _dbus_verbose ("Client authorized as SID '%s'"
668 " but our SID is '%s', disconnecting\n",
669 (_dbus_credentials_get_windows_sid(auth_identity) ?
670 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
671 (_dbus_credentials_get_windows_sid(our_identity) ?
672 _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
673 else
674 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
675 " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
676 _dbus_credentials_get_unix_uid(auth_identity),
677 _dbus_credentials_get_unix_uid(our_identity));
678 _dbus_transport_disconnect (transport);
679 allow = FALSE;
680 }
681
682 _dbus_credentials_unref (our_identity);
683
684 return allow;
685 }
686
687
688 /**
689 * Returns #TRUE if we have been authenticated. Will return #TRUE
690 * even if the transport is disconnected.
691 *
692 * @todo we drop connection->mutex when calling the unix_user_function,
693 * and windows_user_function, which may not be safe really.
694 *
695 * @param transport the transport
696 * @returns whether we're authenticated
697 */
698 dbus_bool_t
_dbus_transport_get_is_authenticated(DBusTransport * transport)699 _dbus_transport_get_is_authenticated (DBusTransport *transport)
700 {
701 if (transport->authenticated)
702 return TRUE;
703 else
704 {
705 dbus_bool_t maybe_authenticated;
706
707 if (transport->disconnected)
708 return FALSE;
709
710 /* paranoia ref since we call user callbacks sometimes */
711 _dbus_connection_ref_unlocked (transport->connection);
712
713 maybe_authenticated =
714 (!(transport->send_credentials_pending ||
715 transport->receive_credentials_pending));
716
717 if (maybe_authenticated)
718 {
719 switch (_dbus_auth_do_work (transport->auth))
720 {
721 case DBUS_AUTH_STATE_AUTHENTICATED:
722 /* leave as maybe_authenticated */
723 break;
724 default:
725 maybe_authenticated = FALSE;
726 }
727 }
728
729 /* If we're the client, verify the GUID
730 */
731 if (maybe_authenticated && !transport->is_server)
732 {
733 const char *server_guid;
734
735 server_guid = _dbus_auth_get_guid_from_server (transport->auth);
736 _dbus_assert (server_guid != NULL);
737
738 if (transport->expected_guid &&
739 strcmp (transport->expected_guid, server_guid) != 0)
740 {
741 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
742 transport->expected_guid, server_guid);
743 _dbus_transport_disconnect (transport);
744 _dbus_connection_unref_unlocked (transport->connection);
745 return FALSE;
746 }
747 }
748
749 /* If we're the server, see if we want to allow this identity to proceed.
750 */
751 if (maybe_authenticated && transport->is_server)
752 {
753 dbus_bool_t allow;
754 DBusCredentials *auth_identity;
755
756 auth_identity = _dbus_auth_get_identity (transport->auth);
757 _dbus_assert (auth_identity != NULL);
758
759 /* If we have an auth'd user and a user function, delegate
760 * deciding whether auth credentials are good enough to the
761 * app; otherwise, use our default decision process.
762 */
763 if (transport->unix_user_function != NULL &&
764 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
765 {
766 allow = auth_via_unix_user_function (transport);
767 }
768 else if (transport->windows_user_function != NULL &&
769 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
770 {
771 allow = auth_via_windows_user_function (transport);
772 }
773 else
774 {
775 allow = auth_via_default_rules (transport);
776 }
777
778 if (!allow)
779 maybe_authenticated = FALSE;
780 }
781
782 transport->authenticated = maybe_authenticated;
783
784 _dbus_connection_unref_unlocked (transport->connection);
785 return maybe_authenticated;
786 }
787 }
788
789 /**
790 * See dbus_connection_get_is_anonymous().
791 *
792 * @param transport the transport
793 * @returns #TRUE if not authenticated or authenticated as anonymous
794 */
795 dbus_bool_t
_dbus_transport_get_is_anonymous(DBusTransport * transport)796 _dbus_transport_get_is_anonymous (DBusTransport *transport)
797 {
798 DBusCredentials *auth_identity;
799
800 if (!transport->authenticated)
801 return TRUE;
802
803 auth_identity = _dbus_auth_get_identity (transport->auth);
804
805 if (_dbus_credentials_are_anonymous (auth_identity))
806 return TRUE;
807 else
808 return FALSE;
809 }
810
811 /**
812 * Returns TRUE if the transport supports sending unix fds.
813 *
814 * @param transport the transport
815 * @returns #TRUE if TRUE it is possible to send unix fds across the transport.
816 */
817 dbus_bool_t
_dbus_transport_can_pass_unix_fd(DBusTransport * transport)818 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
819 {
820 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
821 }
822
823 /**
824 * Gets the address of a transport. It will be
825 * #NULL for a server-side transport.
826 *
827 * @param transport the transport
828 * @returns transport's address
829 */
830 const char*
_dbus_transport_get_address(DBusTransport * transport)831 _dbus_transport_get_address (DBusTransport *transport)
832 {
833 return transport->address;
834 }
835
836 /**
837 * Gets the id of the server we are connected to (see
838 * dbus_server_get_id()). Only works on client side.
839 *
840 * @param transport the transport
841 * @returns transport's server's id or #NULL if we are the server side
842 */
843 const char*
_dbus_transport_get_server_id(DBusTransport * transport)844 _dbus_transport_get_server_id (DBusTransport *transport)
845 {
846 if (transport->is_server)
847 return NULL;
848 else if (transport->authenticated)
849 return _dbus_auth_get_guid_from_server (transport->auth);
850 else
851 return transport->expected_guid;
852 }
853
854 /**
855 * Handles a watch by reading data, writing data, or disconnecting
856 * the transport, as appropriate for the given condition.
857 *
858 * @param transport the transport.
859 * @param watch the watch.
860 * @param condition the current state of the watched file descriptor.
861 * @returns #FALSE if not enough memory to fully handle the watch
862 */
863 dbus_bool_t
_dbus_transport_handle_watch(DBusTransport * transport,DBusWatch * watch,unsigned int condition)864 _dbus_transport_handle_watch (DBusTransport *transport,
865 DBusWatch *watch,
866 unsigned int condition)
867 {
868 dbus_bool_t retval;
869
870 _dbus_assert (transport->vtable->handle_watch != NULL);
871
872 if (transport->disconnected)
873 return TRUE;
874
875 if (dbus_watch_get_socket (watch) < 0)
876 {
877 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
878 return TRUE;
879 }
880
881 _dbus_watch_sanitize_condition (watch, &condition);
882
883 _dbus_transport_ref (transport);
884 _dbus_watch_ref (watch);
885 retval = (* transport->vtable->handle_watch) (transport, watch, condition);
886 _dbus_watch_unref (watch);
887 _dbus_transport_unref (transport);
888
889 return retval;
890 }
891
892 /**
893 * Sets the connection using this transport. Allows the transport
894 * to add watches to the connection, queue incoming messages,
895 * and pull outgoing messages.
896 *
897 * @param transport the transport.
898 * @param connection the connection.
899 * @returns #FALSE if not enough memory
900 */
901 dbus_bool_t
_dbus_transport_set_connection(DBusTransport * transport,DBusConnection * connection)902 _dbus_transport_set_connection (DBusTransport *transport,
903 DBusConnection *connection)
904 {
905 _dbus_assert (transport->vtable->connection_set != NULL);
906 _dbus_assert (transport->connection == NULL);
907
908 transport->connection = connection;
909
910 _dbus_transport_ref (transport);
911 if (!(* transport->vtable->connection_set) (transport))
912 transport->connection = NULL;
913 _dbus_transport_unref (transport);
914
915 return transport->connection != NULL;
916 }
917
918 /**
919 * Get the socket file descriptor, if any.
920 *
921 * @param transport the transport
922 * @param fd_p pointer to fill in with the descriptor
923 * @returns #TRUE if a descriptor was available
924 */
925 dbus_bool_t
_dbus_transport_get_socket_fd(DBusTransport * transport,int * fd_p)926 _dbus_transport_get_socket_fd (DBusTransport *transport,
927 int *fd_p)
928 {
929 dbus_bool_t retval;
930
931 if (transport->vtable->get_socket_fd == NULL)
932 return FALSE;
933
934 if (transport->disconnected)
935 return FALSE;
936
937 _dbus_transport_ref (transport);
938
939 retval = (* transport->vtable->get_socket_fd) (transport,
940 fd_p);
941
942 _dbus_transport_unref (transport);
943
944 return retval;
945 }
946
947 /**
948 * Performs a single poll()/select() on the transport's file
949 * descriptors and then reads/writes data as appropriate,
950 * queueing incoming messages and sending outgoing messages.
951 * This is the backend for _dbus_connection_do_iteration().
952 * See _dbus_connection_do_iteration() for full details.
953 *
954 * @param transport the transport.
955 * @param flags indicates whether to read or write, and whether to block.
956 * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
957 */
958 void
_dbus_transport_do_iteration(DBusTransport * transport,unsigned int flags,int timeout_milliseconds)959 _dbus_transport_do_iteration (DBusTransport *transport,
960 unsigned int flags,
961 int timeout_milliseconds)
962 {
963 _dbus_assert (transport->vtable->do_iteration != NULL);
964
965 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
966 flags, timeout_milliseconds, !transport->disconnected);
967
968 if ((flags & (DBUS_ITERATION_DO_WRITING |
969 DBUS_ITERATION_DO_READING)) == 0)
970 return; /* Nothing to do */
971
972 if (transport->disconnected)
973 return;
974
975 _dbus_transport_ref (transport);
976 (* transport->vtable->do_iteration) (transport, flags,
977 timeout_milliseconds);
978 _dbus_transport_unref (transport);
979
980 _dbus_verbose ("end\n");
981 }
982
983 static dbus_bool_t
recover_unused_bytes(DBusTransport * transport)984 recover_unused_bytes (DBusTransport *transport)
985 {
986 if (_dbus_auth_needs_decoding (transport->auth))
987 {
988 DBusString plaintext;
989 const DBusString *encoded;
990 DBusString *buffer;
991 int orig_len;
992
993 if (!_dbus_string_init (&plaintext))
994 goto nomem;
995
996 _dbus_auth_get_unused_bytes (transport->auth,
997 &encoded);
998
999 if (!_dbus_auth_decode_data (transport->auth,
1000 encoded, &plaintext))
1001 {
1002 _dbus_string_free (&plaintext);
1003 goto nomem;
1004 }
1005
1006 _dbus_message_loader_get_buffer (transport->loader,
1007 &buffer);
1008
1009 orig_len = _dbus_string_get_length (buffer);
1010
1011 if (!_dbus_string_move (&plaintext, 0, buffer,
1012 orig_len))
1013 {
1014 _dbus_string_free (&plaintext);
1015 goto nomem;
1016 }
1017
1018 _dbus_verbose (" %d unused bytes sent to message loader\n",
1019 _dbus_string_get_length (buffer) -
1020 orig_len);
1021
1022 _dbus_message_loader_return_buffer (transport->loader,
1023 buffer,
1024 _dbus_string_get_length (buffer) -
1025 orig_len);
1026
1027 _dbus_auth_delete_unused_bytes (transport->auth);
1028
1029 _dbus_string_free (&plaintext);
1030 }
1031 else
1032 {
1033 const DBusString *bytes;
1034 DBusString *buffer;
1035 int orig_len;
1036 dbus_bool_t succeeded;
1037
1038 _dbus_message_loader_get_buffer (transport->loader,
1039 &buffer);
1040
1041 orig_len = _dbus_string_get_length (buffer);
1042
1043 _dbus_auth_get_unused_bytes (transport->auth,
1044 &bytes);
1045
1046 succeeded = TRUE;
1047 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
1048 succeeded = FALSE;
1049
1050 _dbus_verbose (" %d unused bytes sent to message loader\n",
1051 _dbus_string_get_length (buffer) -
1052 orig_len);
1053
1054 _dbus_message_loader_return_buffer (transport->loader,
1055 buffer,
1056 _dbus_string_get_length (buffer) -
1057 orig_len);
1058
1059 if (succeeded)
1060 _dbus_auth_delete_unused_bytes (transport->auth);
1061 else
1062 goto nomem;
1063 }
1064
1065 return TRUE;
1066
1067 nomem:
1068 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
1069 return FALSE;
1070 }
1071
1072 /**
1073 * Reports our current dispatch status (whether there's buffered
1074 * data to be queued as messages, or not, or we need memory).
1075 *
1076 * @param transport the transport
1077 * @returns current status
1078 */
1079 DBusDispatchStatus
_dbus_transport_get_dispatch_status(DBusTransport * transport)1080 _dbus_transport_get_dispatch_status (DBusTransport *transport)
1081 {
1082 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
1083 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
1084 return DBUS_DISPATCH_COMPLETE; /* complete for now */
1085
1086 if (!_dbus_transport_get_is_authenticated (transport))
1087 {
1088 if (_dbus_auth_do_work (transport->auth) ==
1089 DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
1090 return DBUS_DISPATCH_NEED_MEMORY;
1091 else if (!_dbus_transport_get_is_authenticated (transport))
1092 return DBUS_DISPATCH_COMPLETE;
1093 }
1094
1095 if (!transport->unused_bytes_recovered &&
1096 !recover_unused_bytes (transport))
1097 return DBUS_DISPATCH_NEED_MEMORY;
1098
1099 transport->unused_bytes_recovered = TRUE;
1100
1101 if (!_dbus_message_loader_queue_messages (transport->loader))
1102 return DBUS_DISPATCH_NEED_MEMORY;
1103
1104 if (_dbus_message_loader_peek_message (transport->loader) != NULL)
1105 return DBUS_DISPATCH_DATA_REMAINS;
1106 else
1107 return DBUS_DISPATCH_COMPLETE;
1108 }
1109
1110 /**
1111 * Processes data we've read while handling a watch, potentially
1112 * converting some of it to messages and queueing those messages on
1113 * the connection.
1114 *
1115 * @param transport the transport
1116 * @returns #TRUE if we had enough memory to queue all messages
1117 */
1118 dbus_bool_t
_dbus_transport_queue_messages(DBusTransport * transport)1119 _dbus_transport_queue_messages (DBusTransport *transport)
1120 {
1121 DBusDispatchStatus status;
1122
1123 #if 0
1124 _dbus_verbose ("_dbus_transport_queue_messages()\n");
1125 #endif
1126
1127 /* Queue any messages */
1128 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
1129 {
1130 DBusMessage *message;
1131 DBusList *link;
1132
1133 link = _dbus_message_loader_pop_message_link (transport->loader);
1134 _dbus_assert (link != NULL);
1135
1136 message = link->data;
1137
1138 _dbus_verbose ("queueing received message %p\n", message);
1139
1140 if (!_dbus_message_add_counter (message, transport->live_messages))
1141 {
1142 _dbus_message_loader_putback_message_link (transport->loader,
1143 link);
1144 status = DBUS_DISPATCH_NEED_MEMORY;
1145 break;
1146 }
1147 else
1148 {
1149 /* We didn't call the notify function when we added the counter, so
1150 * catch up now. Since we have the connection's lock, it's desirable
1151 * that we bypass the notify function and call this virtual method
1152 * directly. */
1153 if (transport->vtable->live_messages_changed)
1154 (* transport->vtable->live_messages_changed) (transport);
1155
1156 /* pass ownership of link and message ref to connection */
1157 _dbus_connection_queue_received_message_link (transport->connection,
1158 link);
1159 }
1160 }
1161
1162 if (_dbus_message_loader_get_is_corrupted (transport->loader))
1163 {
1164 _dbus_verbose ("Corrupted message stream, disconnecting\n");
1165 _dbus_transport_disconnect (transport);
1166 }
1167
1168 return status != DBUS_DISPATCH_NEED_MEMORY;
1169 }
1170
1171 /**
1172 * See dbus_connection_set_max_message_size().
1173 *
1174 * @param transport the transport
1175 * @param size the max size of a single message
1176 */
1177 void
_dbus_transport_set_max_message_size(DBusTransport * transport,long size)1178 _dbus_transport_set_max_message_size (DBusTransport *transport,
1179 long size)
1180 {
1181 _dbus_message_loader_set_max_message_size (transport->loader, size);
1182 }
1183
1184 /**
1185 * See dbus_connection_set_max_message_unix_fds().
1186 *
1187 * @param transport the transport
1188 * @param n the max number of unix fds of a single message
1189 */
1190 void
_dbus_transport_set_max_message_unix_fds(DBusTransport * transport,long n)1191 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport,
1192 long n)
1193 {
1194 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
1195 }
1196
1197 /**
1198 * See dbus_connection_get_max_message_size().
1199 *
1200 * @param transport the transport
1201 * @returns max message size
1202 */
1203 long
_dbus_transport_get_max_message_size(DBusTransport * transport)1204 _dbus_transport_get_max_message_size (DBusTransport *transport)
1205 {
1206 return _dbus_message_loader_get_max_message_size (transport->loader);
1207 }
1208
1209 /**
1210 * See dbus_connection_get_max_message_unix_fds().
1211 *
1212 * @param transport the transport
1213 * @returns max message unix fds
1214 */
1215 long
_dbus_transport_get_max_message_unix_fds(DBusTransport * transport)1216 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport)
1217 {
1218 return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
1219 }
1220
1221 /**
1222 * See dbus_connection_set_max_received_size().
1223 *
1224 * @param transport the transport
1225 * @param size the max size of all incoming messages
1226 */
1227 void
_dbus_transport_set_max_received_size(DBusTransport * transport,long size)1228 _dbus_transport_set_max_received_size (DBusTransport *transport,
1229 long size)
1230 {
1231 transport->max_live_messages_size = size;
1232 _dbus_counter_set_notify (transport->live_messages,
1233 transport->max_live_messages_size,
1234 transport->max_live_messages_unix_fds,
1235 live_messages_notify,
1236 transport);
1237 }
1238
1239 /**
1240 * See dbus_connection_set_max_received_unix_fds().
1241 *
1242 * @param transport the transport
1243 * @param n the max unix fds of all incoming messages
1244 */
1245 void
_dbus_transport_set_max_received_unix_fds(DBusTransport * transport,long n)1246 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport,
1247 long n)
1248 {
1249 transport->max_live_messages_unix_fds = n;
1250 _dbus_counter_set_notify (transport->live_messages,
1251 transport->max_live_messages_size,
1252 transport->max_live_messages_unix_fds,
1253 live_messages_notify,
1254 transport);
1255 }
1256
1257 /**
1258 * See dbus_connection_get_max_received_size().
1259 *
1260 * @param transport the transport
1261 * @returns max bytes for all live messages
1262 */
1263 long
_dbus_transport_get_max_received_size(DBusTransport * transport)1264 _dbus_transport_get_max_received_size (DBusTransport *transport)
1265 {
1266 return transport->max_live_messages_size;
1267 }
1268
1269 /**
1270 * See dbus_connection_set_max_received_unix_fds().
1271 *
1272 * @param transport the transport
1273 * @returns max unix fds for all live messages
1274 */
1275 long
_dbus_transport_get_max_received_unix_fds(DBusTransport * transport)1276 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport)
1277 {
1278 return transport->max_live_messages_unix_fds;
1279 }
1280
1281 /**
1282 * See dbus_connection_get_unix_user().
1283 *
1284 * @param transport the transport
1285 * @param uid return location for the user ID
1286 * @returns #TRUE if uid is filled in with a valid user ID
1287 */
1288 dbus_bool_t
_dbus_transport_get_unix_user(DBusTransport * transport,unsigned long * uid)1289 _dbus_transport_get_unix_user (DBusTransport *transport,
1290 unsigned long *uid)
1291 {
1292 DBusCredentials *auth_identity;
1293
1294 *uid = _DBUS_INT32_MAX; /* better than some root or system user in
1295 * case of bugs in the caller. Caller should
1296 * never use this value on purpose, however.
1297 */
1298
1299 if (!transport->authenticated)
1300 return FALSE;
1301
1302 auth_identity = _dbus_auth_get_identity (transport->auth);
1303
1304 if (_dbus_credentials_include (auth_identity,
1305 DBUS_CREDENTIAL_UNIX_USER_ID))
1306 {
1307 *uid = _dbus_credentials_get_unix_uid (auth_identity);
1308 return TRUE;
1309 }
1310 else
1311 return FALSE;
1312 }
1313
1314 /**
1315 * See dbus_connection_get_unix_process_id().
1316 *
1317 * @param transport the transport
1318 * @param pid return location for the process ID
1319 * @returns #TRUE if uid is filled in with a valid process ID
1320 */
1321 dbus_bool_t
_dbus_transport_get_unix_process_id(DBusTransport * transport,unsigned long * pid)1322 _dbus_transport_get_unix_process_id (DBusTransport *transport,
1323 unsigned long *pid)
1324 {
1325 DBusCredentials *auth_identity;
1326
1327 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
1328 * but we set it to a safe number, INT_MAX,
1329 * just to root out possible bugs in bad callers.
1330 */
1331
1332 if (!transport->authenticated)
1333 return FALSE;
1334
1335 auth_identity = _dbus_auth_get_identity (transport->auth);
1336
1337 if (_dbus_credentials_include (auth_identity,
1338 DBUS_CREDENTIAL_UNIX_PROCESS_ID))
1339 {
1340 *pid = _dbus_credentials_get_unix_pid (auth_identity);
1341 return TRUE;
1342 }
1343 else
1344 return FALSE;
1345 }
1346
1347 /**
1348 * See dbus_connection_get_adt_audit_session_data().
1349 *
1350 * @param transport the transport
1351 * @param data return location for the ADT audit data
1352 * @param data_size return length of audit data
1353 * @returns #TRUE if audit data is filled in with a valid ucred
1354 */
1355 dbus_bool_t
_dbus_transport_get_adt_audit_session_data(DBusTransport * transport,void ** data,int * data_size)1356 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport,
1357 void **data,
1358 int *data_size)
1359 {
1360 DBusCredentials *auth_identity;
1361
1362 *data = NULL;
1363 *data_size = 0;
1364
1365 if (!transport->authenticated)
1366 return FALSE;
1367
1368 auth_identity = _dbus_auth_get_identity (transport->auth);
1369
1370 if (_dbus_credentials_include (auth_identity,
1371 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
1372 {
1373 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
1374 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
1375 return TRUE;
1376 }
1377 else
1378 return FALSE;
1379 }
1380
1381 /**
1382 * See dbus_connection_set_unix_user_function().
1383 *
1384 * @param transport the transport
1385 * @param function the predicate
1386 * @param data data to pass to the predicate
1387 * @param free_data_function function to free the data
1388 * @param old_data the old user data to be freed
1389 * @param old_free_data_function old free data function to free it with
1390 */
1391 void
_dbus_transport_set_unix_user_function(DBusTransport * transport,DBusAllowUnixUserFunction function,void * data,DBusFreeFunction free_data_function,void ** old_data,DBusFreeFunction * old_free_data_function)1392 _dbus_transport_set_unix_user_function (DBusTransport *transport,
1393 DBusAllowUnixUserFunction function,
1394 void *data,
1395 DBusFreeFunction free_data_function,
1396 void **old_data,
1397 DBusFreeFunction *old_free_data_function)
1398 {
1399 *old_data = transport->unix_user_data;
1400 *old_free_data_function = transport->free_unix_user_data;
1401
1402 transport->unix_user_function = function;
1403 transport->unix_user_data = data;
1404 transport->free_unix_user_data = free_data_function;
1405 }
1406
1407 /**
1408 * See dbus_connection_get_windows_user().
1409 *
1410 * @param transport the transport
1411 * @param windows_sid_p return location for the user ID
1412 * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
1413 */
1414 dbus_bool_t
_dbus_transport_get_windows_user(DBusTransport * transport,char ** windows_sid_p)1415 _dbus_transport_get_windows_user (DBusTransport *transport,
1416 char **windows_sid_p)
1417 {
1418 DBusCredentials *auth_identity;
1419
1420 *windows_sid_p = NULL;
1421
1422 if (!transport->authenticated)
1423 return FALSE;
1424
1425 auth_identity = _dbus_auth_get_identity (transport->auth);
1426
1427 if (_dbus_credentials_include (auth_identity,
1428 DBUS_CREDENTIAL_WINDOWS_SID))
1429 {
1430 /* If no memory, we are supposed to return TRUE and set NULL */
1431 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
1432
1433 return TRUE;
1434 }
1435 else
1436 return FALSE;
1437 }
1438
1439 /**
1440 * See dbus_connection_set_windows_user_function().
1441 *
1442 * @param transport the transport
1443 * @param function the predicate
1444 * @param data data to pass to the predicate
1445 * @param free_data_function function to free the data
1446 * @param old_data the old user data to be freed
1447 * @param old_free_data_function old free data function to free it with
1448 */
1449
1450 void
_dbus_transport_set_windows_user_function(DBusTransport * transport,DBusAllowWindowsUserFunction function,void * data,DBusFreeFunction free_data_function,void ** old_data,DBusFreeFunction * old_free_data_function)1451 _dbus_transport_set_windows_user_function (DBusTransport *transport,
1452 DBusAllowWindowsUserFunction function,
1453 void *data,
1454 DBusFreeFunction free_data_function,
1455 void **old_data,
1456 DBusFreeFunction *old_free_data_function)
1457 {
1458 *old_data = transport->windows_user_data;
1459 *old_free_data_function = transport->free_windows_user_data;
1460
1461 transport->windows_user_function = function;
1462 transport->windows_user_data = data;
1463 transport->free_windows_user_data = free_data_function;
1464 }
1465
1466 /**
1467 * Sets the SASL authentication mechanisms supported by this transport.
1468 *
1469 * @param transport the transport
1470 * @param mechanisms the #NULL-terminated array of mechanisms
1471 *
1472 * @returns #FALSE if no memory
1473 */
1474 dbus_bool_t
_dbus_transport_set_auth_mechanisms(DBusTransport * transport,const char ** mechanisms)1475 _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
1476 const char **mechanisms)
1477 {
1478 return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
1479 }
1480
1481 /**
1482 * See dbus_connection_set_allow_anonymous()
1483 *
1484 * @param transport the transport
1485 * @param value #TRUE to allow anonymous connection
1486 */
1487 void
_dbus_transport_set_allow_anonymous(DBusTransport * transport,dbus_bool_t value)1488 _dbus_transport_set_allow_anonymous (DBusTransport *transport,
1489 dbus_bool_t value)
1490 {
1491 transport->allow_anonymous = value != FALSE;
1492 }
1493
1494 #ifdef DBUS_ENABLE_STATS
1495 void
_dbus_transport_get_stats(DBusTransport * transport,dbus_uint32_t * queue_bytes,dbus_uint32_t * queue_fds,dbus_uint32_t * peak_queue_bytes,dbus_uint32_t * peak_queue_fds)1496 _dbus_transport_get_stats (DBusTransport *transport,
1497 dbus_uint32_t *queue_bytes,
1498 dbus_uint32_t *queue_fds,
1499 dbus_uint32_t *peak_queue_bytes,
1500 dbus_uint32_t *peak_queue_fds)
1501 {
1502 if (queue_bytes != NULL)
1503 *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
1504
1505 if (queue_fds != NULL)
1506 *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
1507
1508 if (peak_queue_bytes != NULL)
1509 *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
1510
1511 if (peak_queue_fds != NULL)
1512 *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
1513 }
1514 #endif /* DBUS_ENABLE_STATS */
1515
1516 /** @} */
1517