D-Bus
1.10.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-server-unix.c Server implementation for Unix network protocols. 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 #include "dbus-internals.h" 00026 #include "dbus-server-unix.h" 00027 #include "dbus-server-socket.h" 00028 #include "dbus-server-launchd.h" 00029 #include "dbus-transport-unix.h" 00030 #include "dbus-connection-internal.h" 00031 #include "dbus-sysdeps-unix.h" 00032 #include "dbus-string.h" 00033 00053 DBusServerListenResult 00054 _dbus_server_listen_platform_specific (DBusAddressEntry *entry, 00055 DBusServer **server_p, 00056 DBusError *error) 00057 { 00058 const char *method; 00059 00060 *server_p = NULL; 00061 00062 method = dbus_address_entry_get_method (entry); 00063 00064 if (strcmp (method, "unix") == 0) 00065 { 00066 const char *path = dbus_address_entry_get_value (entry, "path"); 00067 const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); 00068 const char *abstract = dbus_address_entry_get_value (entry, "abstract"); 00069 const char *runtime = dbus_address_entry_get_value (entry, "runtime"); 00070 int mutually_exclusive_modes = 0; 00071 00072 mutually_exclusive_modes = (path != NULL) + (tmpdir != NULL) + 00073 (abstract != NULL) + (runtime != NULL); 00074 00075 if (mutually_exclusive_modes < 1) 00076 { 00077 _dbus_set_bad_address(error, "unix", 00078 "path or tmpdir or abstract or runtime", 00079 NULL); 00080 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00081 } 00082 00083 if (mutually_exclusive_modes > 1) 00084 { 00085 _dbus_set_bad_address(error, NULL, NULL, 00086 "cannot specify two of \"path\", \"tmpdir\", \"abstract\" and \"runtime\" at the same time"); 00087 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00088 } 00089 00090 if (runtime != NULL) 00091 { 00092 DBusString full_path; 00093 DBusString filename; 00094 const char *runtimedir; 00095 00096 if (strcmp (runtime, "yes") != 0) 00097 { 00098 _dbus_set_bad_address(error, NULL, NULL, 00099 "if given, the only value allowed for \"runtime\" is \"yes\""); 00100 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00101 } 00102 00103 runtimedir = _dbus_getenv ("XDG_RUNTIME_DIR"); 00104 00105 if (runtimedir == NULL) 00106 { 00107 dbus_set_error (error, 00108 DBUS_ERROR_NOT_SUPPORTED, "\"XDG_RUNTIME_DIR\" is not set"); 00109 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00110 } 00111 00112 _dbus_string_init_const (&filename, "bus"); 00113 00114 if (!_dbus_string_init (&full_path)) 00115 { 00116 _DBUS_SET_OOM (error); 00117 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00118 } 00119 00120 if (!_dbus_string_append (&full_path, runtimedir) || 00121 !_dbus_concat_dir_and_file (&full_path, &filename)) 00122 { 00123 _dbus_string_free (&full_path); 00124 _DBUS_SET_OOM (error); 00125 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00126 } 00127 00128 /* We can safely use filesystem sockets in the runtime directory, 00129 * and they are preferred because they can be bind-mounted between 00130 * Linux containers. */ 00131 *server_p = _dbus_server_new_for_domain_socket ( 00132 _dbus_string_get_const_data (&full_path), 00133 FALSE, error); 00134 00135 _dbus_string_free (&full_path); 00136 } 00137 else if (tmpdir != NULL) 00138 { 00139 DBusString full_path; 00140 DBusString filename; 00141 00142 if (!_dbus_string_init (&full_path)) 00143 { 00144 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00145 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00146 } 00147 00148 if (!_dbus_string_init (&filename)) 00149 { 00150 _dbus_string_free (&full_path); 00151 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00152 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00153 } 00154 00155 if (!_dbus_string_append (&filename, "dbus-")) 00156 { 00157 _dbus_string_free (&full_path); 00158 _dbus_string_free (&filename); 00159 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00160 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00161 } 00162 00163 if (!_dbus_generate_random_ascii (&filename, 10, error)) 00164 { 00165 _dbus_string_free (&full_path); 00166 _dbus_string_free (&filename); 00167 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00168 } 00169 00170 if (!_dbus_string_append (&full_path, tmpdir) || 00171 !_dbus_concat_dir_and_file (&full_path, &filename)) 00172 { 00173 _dbus_string_free (&full_path); 00174 _dbus_string_free (&filename); 00175 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00176 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00177 } 00178 00179 /* Always use abstract namespace if possible with tmpdir */ 00180 00181 *server_p = 00182 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path), 00183 #ifdef HAVE_ABSTRACT_SOCKETS 00184 TRUE, 00185 #else 00186 FALSE, 00187 #endif 00188 error); 00189 00190 _dbus_string_free (&full_path); 00191 _dbus_string_free (&filename); 00192 } 00193 else 00194 { 00195 if (path) 00196 *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error); 00197 else 00198 *server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error); 00199 } 00200 00201 if (*server_p != NULL) 00202 { 00203 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00204 return DBUS_SERVER_LISTEN_OK; 00205 } 00206 else 00207 { 00208 _DBUS_ASSERT_ERROR_IS_SET(error); 00209 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00210 } 00211 } 00212 else if (strcmp (method, "systemd") == 0) 00213 { 00214 int i, n; 00215 DBusSocket *fds; 00216 DBusString address; 00217 00218 n = _dbus_listen_systemd_sockets (&fds, error); 00219 if (n < 0) 00220 { 00221 _DBUS_ASSERT_ERROR_IS_SET (error); 00222 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00223 } 00224 00225 if (!_dbus_string_init (&address)) 00226 goto systemd_oom; 00227 00228 for (i = 0; i < n; i++) 00229 { 00230 if (i > 0) 00231 { 00232 if (!_dbus_string_append (&address, ";")) 00233 goto systemd_oom; 00234 } 00235 if (!_dbus_append_address_from_socket (fds[i], &address, error)) 00236 goto systemd_err; 00237 } 00238 00239 *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL, error); 00240 if (*server_p == NULL) 00241 goto systemd_err; 00242 00243 dbus_free (fds); 00244 00245 return DBUS_SERVER_LISTEN_OK; 00246 00247 systemd_oom: 00248 _DBUS_SET_OOM (error); 00249 systemd_err: 00250 for (i = 0; i < n; i++) 00251 { 00252 _dbus_close_socket (fds[i], NULL); 00253 } 00254 dbus_free (fds); 00255 _dbus_string_free (&address); 00256 00257 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00258 } 00259 #ifdef DBUS_ENABLE_LAUNCHD 00260 else if (strcmp (method, "launchd") == 0) 00261 { 00262 const char *launchd_env_var = dbus_address_entry_get_value (entry, "env"); 00263 if (launchd_env_var == NULL) 00264 { 00265 _dbus_set_bad_address (error, "launchd", "env", NULL); 00266 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00267 } 00268 *server_p = _dbus_server_new_for_launchd (launchd_env_var, error); 00269 00270 if (*server_p != NULL) 00271 { 00272 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00273 return DBUS_SERVER_LISTEN_OK; 00274 } 00275 else 00276 { 00277 _DBUS_ASSERT_ERROR_IS_SET(error); 00278 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00279 } 00280 } 00281 #endif 00282 else 00283 { 00284 /* If we don't handle the method, we return NULL with the 00285 * error unset 00286 */ 00287 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00288 return DBUS_SERVER_LISTEN_NOT_HANDLED; 00289 } 00290 } 00291 00300 DBusServer* 00301 _dbus_server_new_for_domain_socket (const char *path, 00302 dbus_bool_t abstract, 00303 DBusError *error) 00304 { 00305 DBusServer *server; 00306 DBusSocket listen_fd; 00307 DBusString address; 00308 char *path_copy; 00309 DBusString path_str; 00310 00311 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00312 00313 if (!_dbus_string_init (&address)) 00314 { 00315 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00316 return NULL; 00317 } 00318 00319 _dbus_string_init_const (&path_str, path); 00320 if ((abstract && 00321 !_dbus_string_append (&address, "unix:abstract=")) || 00322 (!abstract && 00323 !_dbus_string_append (&address, "unix:path=")) || 00324 !_dbus_address_append_escaped (&address, &path_str)) 00325 { 00326 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00327 goto failed_0; 00328 } 00329 00330 if (abstract) 00331 { 00332 path_copy = NULL; 00333 } 00334 else 00335 { 00336 path_copy = _dbus_strdup (path); 00337 if (path_copy == NULL) 00338 { 00339 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00340 goto failed_0; 00341 } 00342 } 00343 00344 listen_fd.fd = _dbus_listen_unix_socket (path, abstract, error); 00345 00346 if (listen_fd.fd < 0) 00347 { 00348 _DBUS_ASSERT_ERROR_IS_SET (error); 00349 goto failed_1; 00350 } 00351 00352 server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0, error); 00353 if (server == NULL) 00354 { 00355 goto failed_2; 00356 } 00357 00358 if (path_copy != NULL) 00359 _dbus_server_socket_own_filename(server, path_copy); 00360 00361 _dbus_string_free (&address); 00362 00363 return server; 00364 00365 failed_2: 00366 _dbus_close_socket (listen_fd, NULL); 00367 failed_1: 00368 dbus_free (path_copy); 00369 failed_0: 00370 _dbus_string_free (&address); 00371 00372 return NULL; 00373 } 00374