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