D-Bus
1.10.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-transport-unix.c UNIX socket subclasses of DBusTransport 00003 * 00004 * Copyright (C) 2002, 2003, 2004 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 DBusSocket fd = DBUS_SOCKET_INIT; 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 if ((abstract && 00075 !_dbus_string_append (&address, "unix:abstract=")) || 00076 (!abstract && 00077 !_dbus_string_append (&address, "unix:path=")) || 00078 !_dbus_string_append (&address, path)) 00079 { 00080 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00081 goto failed_0; 00082 } 00083 00084 fd.fd = _dbus_connect_unix_socket (path, abstract, error); 00085 if (fd.fd < 0) 00086 { 00087 _DBUS_ASSERT_ERROR_IS_SET (error); 00088 goto failed_0; 00089 } 00090 00091 _dbus_verbose ("Successfully connected to unix socket %s\n", 00092 path); 00093 00094 transport = _dbus_transport_new_for_socket (fd, NULL, &address); 00095 if (transport == NULL) 00096 { 00097 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00098 goto failed_1; 00099 } 00100 00101 _dbus_string_free (&address); 00102 00103 return transport; 00104 00105 failed_1: 00106 _dbus_close_socket (fd, NULL); 00107 failed_0: 00108 _dbus_string_free (&address); 00109 return NULL; 00110 } 00111 00123 static DBusTransport* 00124 _dbus_transport_new_for_exec (const char *path, 00125 char *const argv[], 00126 DBusError *error) 00127 { 00128 DBusSocket fd = DBUS_SOCKET_INIT; 00129 DBusTransport *transport; 00130 DBusString address; 00131 unsigned i; 00132 char *escaped; 00133 00134 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00135 00136 if (!_dbus_string_init (&address)) 00137 { 00138 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00139 return NULL; 00140 } 00141 00142 escaped = dbus_address_escape_value (path); 00143 if (!escaped) 00144 { 00145 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00146 goto failed; 00147 } 00148 00149 if (!_dbus_string_append (&address, "unixexec:path=") || 00150 !_dbus_string_append (&address, escaped)) 00151 { 00152 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00153 dbus_free (escaped); 00154 goto failed; 00155 } 00156 00157 dbus_free (escaped); 00158 00159 if (argv) 00160 { 00161 for (i = 0; argv[i]; i++) 00162 { 00163 dbus_bool_t success; 00164 00165 escaped = dbus_address_escape_value (argv[i]); 00166 if (!escaped) 00167 { 00168 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00169 goto failed; 00170 } 00171 00172 success = _dbus_string_append_printf (&address, ",argv%u=%s", i, escaped); 00173 dbus_free (escaped); 00174 00175 if (!success) 00176 { 00177 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00178 goto failed; 00179 } 00180 } 00181 } 00182 00183 fd.fd = _dbus_connect_exec (path, argv, error); 00184 if (fd.fd < 0) 00185 { 00186 _DBUS_ASSERT_ERROR_IS_SET (error); 00187 goto failed; 00188 } 00189 00190 _dbus_verbose ("Successfully connected to process %s\n", 00191 path); 00192 00193 transport = _dbus_transport_new_for_socket (fd, NULL, &address); 00194 if (transport == NULL) 00195 { 00196 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00197 goto failed; 00198 } 00199 00200 _dbus_string_free (&address); 00201 00202 return transport; 00203 00204 failed: 00205 if (fd.fd >= 0) 00206 _dbus_close_socket (fd, NULL); 00207 00208 _dbus_string_free (&address); 00209 return NULL; 00210 } 00211 00220 DBusTransportOpenResult 00221 _dbus_transport_open_platform_specific (DBusAddressEntry *entry, 00222 DBusTransport **transport_p, 00223 DBusError *error) 00224 { 00225 const char *method; 00226 00227 method = dbus_address_entry_get_method (entry); 00228 _dbus_assert (method != NULL); 00229 00230 if (strcmp (method, "unix") == 0) 00231 { 00232 const char *path = dbus_address_entry_get_value (entry, "path"); 00233 const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); 00234 const char *abstract = dbus_address_entry_get_value (entry, "abstract"); 00235 00236 if (tmpdir != NULL) 00237 { 00238 _dbus_set_bad_address (error, NULL, NULL, 00239 "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on"); 00240 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 00241 } 00242 00243 if (path == NULL && abstract == NULL) 00244 { 00245 _dbus_set_bad_address (error, "unix", 00246 "path or abstract", 00247 NULL); 00248 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 00249 } 00250 00251 if (path != NULL && abstract != NULL) 00252 { 00253 _dbus_set_bad_address (error, NULL, NULL, 00254 "can't specify both \"path\" and \"abstract\" options in an address"); 00255 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 00256 } 00257 00258 if (path) 00259 *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE, 00260 error); 00261 else 00262 *transport_p = _dbus_transport_new_for_domain_socket (abstract, TRUE, 00263 error); 00264 if (*transport_p == NULL) 00265 { 00266 _DBUS_ASSERT_ERROR_IS_SET (error); 00267 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00268 } 00269 else 00270 { 00271 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00272 return DBUS_TRANSPORT_OPEN_OK; 00273 } 00274 } 00275 else if (strcmp (method, "unixexec") == 0) 00276 { 00277 const char *path; 00278 unsigned i; 00279 char **argv; 00280 00281 path = dbus_address_entry_get_value (entry, "path"); 00282 if (path == NULL) 00283 { 00284 _dbus_set_bad_address (error, NULL, NULL, 00285 "No process path specified"); 00286 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 00287 } 00288 00289 /* First count argv arguments */ 00290 for (i = 1; ; i++) 00291 { 00292 char t[4+20+1]; /* "argv" plus space for a formatted base 10 64bit integer, plus NUL */ 00293 00294 snprintf (t, sizeof(t), "argv%u", i); 00295 00296 if (!dbus_address_entry_get_value (entry, t)) 00297 break; 00298 } 00299 00300 /* Allocate string array */ 00301 argv = dbus_new0 (char*, i+1); 00302 if (!argv) 00303 { 00304 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00305 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00306 } 00307 00308 /* Fill in string array */ 00309 for (i = 0; ; i++) 00310 { 00311 char t[4+20+1]; 00312 const char *p; 00313 00314 snprintf (t, sizeof(t), "argv%u", i); 00315 00316 p = dbus_address_entry_get_value (entry, t); 00317 if (!p) 00318 { 00319 if (i == 0) 00320 /* If argv0 isn't specified, fill in the path instead */ 00321 p = path; 00322 else 00323 break; 00324 } 00325 00326 argv[i] = _dbus_strdup (p); 00327 if (!argv[i]) 00328 { 00329 dbus_free_string_array (argv); 00330 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00331 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00332 } 00333 } 00334 00335 *transport_p = _dbus_transport_new_for_exec (path, argv, error); 00336 dbus_free_string_array (argv); 00337 00338 if (*transport_p == NULL) 00339 { 00340 _DBUS_ASSERT_ERROR_IS_SET (error); 00341 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00342 } 00343 else 00344 { 00345 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00346 return DBUS_TRANSPORT_OPEN_OK; 00347 } 00348 } 00349 #ifdef DBUS_ENABLE_LAUNCHD 00350 else if (strcmp (method, "launchd") == 0) 00351 { 00352 DBusError tmp_error = DBUS_ERROR_INIT; 00353 const char *launchd_env_var = dbus_address_entry_get_value (entry, "env"); 00354 const char *launchd_socket; 00355 DBusString socket_path; 00356 dbus_bool_t valid_socket; 00357 00358 if (!_dbus_string_init (&socket_path)) 00359 { 00360 _DBUS_SET_OOM (error); 00361 return FALSE; 00362 } 00363 00364 if (launchd_env_var == NULL) 00365 { 00366 _dbus_set_bad_address (error, "launchd", "env", NULL); 00367 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 00368 } 00369 00370 valid_socket = _dbus_lookup_launchd_socket (&socket_path, launchd_env_var, error); 00371 00372 if (dbus_error_is_set(error)) 00373 { 00374 _dbus_string_free(&socket_path); 00375 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00376 } 00377 00378 if (!valid_socket) 00379 { 00380 dbus_set_error(&tmp_error, DBUS_ERROR_BAD_ADDRESS, 00381 "launchd's env var %s does not exist", launchd_env_var); 00382 dbus_error_free(error); 00383 dbus_move_error(&tmp_error, error); 00384 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00385 } 00386 00387 launchd_socket = _dbus_string_get_const_data(&socket_path); 00388 *transport_p = _dbus_transport_new_for_domain_socket (launchd_socket, FALSE, error); 00389 00390 if (*transport_p == NULL) 00391 { 00392 _DBUS_ASSERT_ERROR_IS_SET (error); 00393 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00394 } 00395 else 00396 { 00397 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00398 return DBUS_TRANSPORT_OPEN_OK; 00399 } 00400 } 00401 #endif 00402 else 00403 { 00404 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00405 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00406 } 00407 } 00408 00411 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00412 00413 dbus_bool_t 00414 _dbus_transport_unix_test (void) 00415 { 00416 DBusConnection *c; 00417 DBusError error; 00418 dbus_bool_t ret; 00419 const char *address; 00420 00421 dbus_error_init (&error); 00422 00423 c = dbus_connection_open ("unixexec:argv0=false,argv1=foobar,path=/bin/false", &error); 00424 _dbus_assert (c != NULL); 00425 _dbus_assert (!dbus_error_is_set (&error)); 00426 00427 address = _dbus_connection_get_address (c); 00428 _dbus_assert (address != NULL); 00429 00430 /* Let's see if the address got parsed, reordered and formatted correctly */ 00431 ret = strcmp (address, "unixexec:path=/bin/false,argv0=false,argv1=foobar") == 0; 00432 00433 dbus_connection_unref (c); 00434 00435 return ret; 00436 } 00437 00438 #endif