00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025
00026 #include <stdio.h>
00027
00028 #include "dbus-internals.h"
00029 #include "dbus-connection-internal.h"
00030 #include "dbus-transport-unix.h"
00031 #include "dbus-transport-socket.h"
00032 #include "dbus-transport-protected.h"
00033 #include "dbus-watch.h"
00034 #include "dbus-sysdeps-unix.h"
00035 #include "dbus-test.h"
00036
00057 DBusTransport*
00058 _dbus_transport_new_for_domain_socket (const char *path,
00059 dbus_bool_t abstract,
00060 DBusError *error)
00061 {
00062 int fd;
00063 DBusTransport *transport;
00064 DBusString address;
00065
00066 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00067
00068 if (!_dbus_string_init (&address))
00069 {
00070 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00071 return NULL;
00072 }
00073
00074 fd = -1;
00075
00076 if ((abstract &&
00077 !_dbus_string_append (&address, "unix:abstract=")) ||
00078 (!abstract &&
00079 !_dbus_string_append (&address, "unix:path=")) ||
00080 !_dbus_string_append (&address, path))
00081 {
00082 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00083 goto failed_0;
00084 }
00085
00086 fd = _dbus_connect_unix_socket (path, abstract, error);
00087 if (fd < 0)
00088 {
00089 _DBUS_ASSERT_ERROR_IS_SET (error);
00090 goto failed_0;
00091 }
00092
00093 _dbus_verbose ("Successfully connected to unix socket %s\n",
00094 path);
00095
00096 transport = _dbus_transport_new_for_socket (fd, NULL, &address);
00097 if (transport == NULL)
00098 {
00099 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00100 goto failed_1;
00101 }
00102
00103 _dbus_string_free (&address);
00104
00105 return transport;
00106
00107 failed_1:
00108 _dbus_close_socket (fd, NULL);
00109 failed_0:
00110 _dbus_string_free (&address);
00111 return NULL;
00112 }
00113
00125 static DBusTransport*
00126 _dbus_transport_new_for_exec (const char *path,
00127 char *const argv[],
00128 DBusError *error)
00129 {
00130 int fd;
00131 DBusTransport *transport;
00132 DBusString address;
00133 unsigned i;
00134 char *escaped;
00135
00136 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00137
00138 if (!_dbus_string_init (&address))
00139 {
00140 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00141 return NULL;
00142 }
00143
00144 fd = -1;
00145
00146 escaped = dbus_address_escape_value (path);
00147 if (!escaped)
00148 {
00149 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00150 goto failed;
00151 }
00152
00153 if (!_dbus_string_append (&address, "unixexec:path=") ||
00154 !_dbus_string_append (&address, escaped))
00155 {
00156 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00157 dbus_free (escaped);
00158 goto failed;
00159 }
00160
00161 dbus_free (escaped);
00162
00163 if (argv)
00164 {
00165 for (i = 0; argv[i]; i++)
00166 {
00167 dbus_bool_t success;
00168
00169 escaped = dbus_address_escape_value (argv[i]);
00170 if (!escaped)
00171 {
00172 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00173 goto failed;
00174 }
00175
00176 success = _dbus_string_append_printf (&address, ",argv%u=%s", i, escaped);
00177 dbus_free (escaped);
00178
00179 if (!success)
00180 {
00181 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00182 goto failed;
00183 }
00184 }
00185 }
00186
00187 fd = _dbus_connect_exec (path, argv, error);
00188 if (fd < 0)
00189 {
00190 _DBUS_ASSERT_ERROR_IS_SET (error);
00191 goto failed;
00192 }
00193
00194 _dbus_verbose ("Successfully connected to process %s\n",
00195 path);
00196
00197 transport = _dbus_transport_new_for_socket (fd, NULL, &address);
00198 if (transport == NULL)
00199 {
00200 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00201 goto failed;
00202 }
00203
00204 _dbus_string_free (&address);
00205
00206 return transport;
00207
00208 failed:
00209 if (fd >= 0)
00210 _dbus_close_socket (fd, NULL);
00211
00212 _dbus_string_free (&address);
00213 return NULL;
00214 }
00215
00224 DBusTransportOpenResult
00225 _dbus_transport_open_platform_specific (DBusAddressEntry *entry,
00226 DBusTransport **transport_p,
00227 DBusError *error)
00228 {
00229 const char *method;
00230
00231 method = dbus_address_entry_get_method (entry);
00232 _dbus_assert (method != NULL);
00233
00234 if (strcmp (method, "unix") == 0)
00235 {
00236 const char *path = dbus_address_entry_get_value (entry, "path");
00237 const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
00238 const char *abstract = dbus_address_entry_get_value (entry, "abstract");
00239
00240 if (tmpdir != NULL)
00241 {
00242 _dbus_set_bad_address (error, NULL, NULL,
00243 "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on");
00244 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00245 }
00246
00247 if (path == NULL && abstract == NULL)
00248 {
00249 _dbus_set_bad_address (error, "unix",
00250 "path or abstract",
00251 NULL);
00252 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00253 }
00254
00255 if (path != NULL && abstract != NULL)
00256 {
00257 _dbus_set_bad_address (error, NULL, NULL,
00258 "can't specify both \"path\" and \"abstract\" options in an address");
00259 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00260 }
00261
00262 if (path)
00263 *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE,
00264 error);
00265 else
00266 *transport_p = _dbus_transport_new_for_domain_socket (abstract, TRUE,
00267 error);
00268 if (*transport_p == NULL)
00269 {
00270 _DBUS_ASSERT_ERROR_IS_SET (error);
00271 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00272 }
00273 else
00274 {
00275 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00276 return DBUS_TRANSPORT_OPEN_OK;
00277 }
00278 }
00279 else if (strcmp (method, "unixexec") == 0)
00280 {
00281 const char *path;
00282 unsigned i;
00283 char **argv;
00284
00285 path = dbus_address_entry_get_value (entry, "path");
00286 if (path == NULL)
00287 {
00288 _dbus_set_bad_address (error, NULL, NULL,
00289 "No process path specified");
00290 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00291 }
00292
00293
00294 for (i = 1; ; i++)
00295 {
00296 char t[4+20+1];
00297
00298 snprintf (t, sizeof(t), "argv%u", i);
00299
00300 if (!dbus_address_entry_get_value (entry, t))
00301 break;
00302 }
00303
00304
00305 argv = dbus_new0 (char*, i+1);
00306 if (!argv)
00307 {
00308 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00309 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00310 }
00311
00312
00313 for (i = 0; ; i++)
00314 {
00315 char t[4+20+1];
00316 const char *p;
00317
00318 snprintf (t, sizeof(t), "argv%u", i);
00319
00320 p = dbus_address_entry_get_value (entry, t);
00321 if (!p)
00322 {
00323 if (i == 0)
00324
00325 p = path;
00326 else
00327 break;
00328 }
00329
00330 argv[i] = _dbus_strdup (p);
00331 if (!argv[i])
00332 {
00333 dbus_free_string_array (argv);
00334 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00335 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00336 }
00337 }
00338
00339 *transport_p = _dbus_transport_new_for_exec (path, argv, error);
00340 dbus_free_string_array (argv);
00341
00342 if (*transport_p == NULL)
00343 {
00344 _DBUS_ASSERT_ERROR_IS_SET (error);
00345 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00346 }
00347 else
00348 {
00349 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00350 return DBUS_TRANSPORT_OPEN_OK;
00351 }
00352 }
00353 #ifdef DBUS_ENABLE_LAUNCHD
00354 else if (strcmp (method, "launchd") == 0)
00355 {
00356 DBusError tmp_error = DBUS_ERROR_INIT;
00357 const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
00358 const char *launchd_socket;
00359 DBusString socket_path;
00360 dbus_bool_t valid_socket;
00361
00362 if (!_dbus_string_init (&socket_path))
00363 {
00364 _DBUS_SET_OOM (error);
00365 return FALSE;
00366 }
00367
00368 if (launchd_env_var == NULL)
00369 {
00370 _dbus_set_bad_address (error, "launchd", "env", NULL);
00371 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00372 }
00373
00374 valid_socket = _dbus_lookup_launchd_socket (&socket_path, launchd_env_var, error);
00375
00376 if (dbus_error_is_set(error))
00377 {
00378 _dbus_string_free(&socket_path);
00379 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00380 }
00381
00382 if (!valid_socket)
00383 {
00384 dbus_set_error(&tmp_error, DBUS_ERROR_BAD_ADDRESS,
00385 "launchd's env var %s does not exist", launchd_env_var);
00386 dbus_error_free(error);
00387 dbus_move_error(&tmp_error, error);
00388 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00389 }
00390
00391 launchd_socket = _dbus_string_get_const_data(&socket_path);
00392 *transport_p = _dbus_transport_new_for_domain_socket (launchd_socket, FALSE, error);
00393
00394 if (*transport_p == NULL)
00395 {
00396 _DBUS_ASSERT_ERROR_IS_SET (error);
00397 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00398 }
00399 else
00400 {
00401 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00402 return DBUS_TRANSPORT_OPEN_OK;
00403 }
00404 }
00405 #endif
00406 else
00407 {
00408 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00409 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00410 }
00411 }
00412
00415 #ifdef DBUS_BUILD_TESTS
00416
00417 dbus_bool_t
00418 _dbus_transport_unix_test (void)
00419 {
00420 DBusConnection *c;
00421 DBusError error;
00422 dbus_bool_t ret;
00423 const char *address;
00424
00425 dbus_error_init (&error);
00426
00427 c = dbus_connection_open ("unixexec:argv0=false,argv1=foobar,path=/bin/false", &error);
00428 _dbus_assert (c != NULL);
00429 _dbus_assert (!dbus_error_is_set (&error));
00430
00431 address = _dbus_connection_get_address (c);
00432 _dbus_assert (address != NULL);
00433
00434
00435 ret = strcmp (address, "unixexec:path=/bin/false,argv0=false,argv1=foobar") == 0;
00436
00437 dbus_connection_unref (c);
00438
00439 return ret;
00440 }
00441
00442 #endif