D-Bus
1.10.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-server-socket.c Server implementation for sockets 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2006 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-socket.h" 00027 #include "dbus-transport-socket.h" 00028 #include "dbus-connection-internal.h" 00029 #include "dbus-memory.h" 00030 #include "dbus-nonce.h" 00031 #include "dbus-string.h" 00032 00044 typedef struct DBusServerSocket DBusServerSocket; 00045 00050 struct DBusServerSocket 00051 { 00052 DBusServer base; 00053 int n_fds; 00054 DBusSocket *fds; 00055 DBusWatch **watch; 00056 char *socket_name; 00057 DBusNonceFile *noncefile; 00058 }; 00059 00060 static void 00061 socket_finalize (DBusServer *server) 00062 { 00063 DBusServerSocket *socket_server = (DBusServerSocket*) server; 00064 int i; 00065 00066 _dbus_server_finalize_base (server); 00067 00068 for (i = 0 ; i < socket_server->n_fds ; i++) 00069 if (socket_server->watch[i]) 00070 { 00071 _dbus_watch_unref (socket_server->watch[i]); 00072 socket_server->watch[i] = NULL; 00073 } 00074 00075 dbus_free (socket_server->fds); 00076 dbus_free (socket_server->watch); 00077 dbus_free (socket_server->socket_name); 00078 if (socket_server->noncefile) 00079 _dbus_noncefile_delete (socket_server->noncefile, NULL); 00080 dbus_free (socket_server->noncefile); 00081 dbus_free (server); 00082 } 00083 00084 /* Return value is just for memory, not other failures. */ 00085 static dbus_bool_t 00086 handle_new_client_fd_and_unlock (DBusServer *server, 00087 DBusSocket client_fd) 00088 { 00089 DBusConnection *connection; 00090 DBusTransport *transport; 00091 DBusNewConnectionFunction new_connection_function; 00092 void *new_connection_data; 00093 00094 _dbus_verbose ("Creating new client connection with fd %" DBUS_SOCKET_FORMAT "\n", 00095 _dbus_socket_printable (client_fd)); 00096 00097 HAVE_LOCK_CHECK (server); 00098 00099 if (!_dbus_set_socket_nonblocking (client_fd, NULL)) 00100 { 00101 SERVER_UNLOCK (server); 00102 return TRUE; 00103 } 00104 00105 transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, NULL); 00106 if (transport == NULL) 00107 { 00108 _dbus_close_socket (client_fd, NULL); 00109 SERVER_UNLOCK (server); 00110 return FALSE; 00111 } 00112 00113 if (!_dbus_transport_set_auth_mechanisms (transport, 00114 (const char **) server->auth_mechanisms)) 00115 { 00116 _dbus_transport_unref (transport); 00117 SERVER_UNLOCK (server); 00118 return FALSE; 00119 } 00120 00121 /* note that client_fd is now owned by the transport, and will be 00122 * closed on transport disconnection/finalization 00123 */ 00124 00125 connection = _dbus_connection_new_for_transport (transport); 00126 _dbus_transport_unref (transport); 00127 transport = NULL; /* now under the connection lock */ 00128 00129 if (connection == NULL) 00130 { 00131 SERVER_UNLOCK (server); 00132 return FALSE; 00133 } 00134 00135 /* See if someone wants to handle this new connection, self-referencing 00136 * for paranoia. 00137 */ 00138 new_connection_function = server->new_connection_function; 00139 new_connection_data = server->new_connection_data; 00140 00141 _dbus_server_ref_unlocked (server); 00142 SERVER_UNLOCK (server); 00143 00144 if (new_connection_function) 00145 { 00146 (* new_connection_function) (server, connection, 00147 new_connection_data); 00148 } 00149 dbus_server_unref (server); 00150 00151 /* If no one grabbed a reference, the connection will die. */ 00152 _dbus_connection_close_if_only_one_ref (connection); 00153 dbus_connection_unref (connection); 00154 00155 return TRUE; 00156 } 00157 00158 static dbus_bool_t 00159 socket_handle_watch (DBusWatch *watch, 00160 unsigned int flags, 00161 void *data) 00162 { 00163 DBusServer *server = data; 00164 DBusServerSocket *socket_server = data; 00165 00166 #ifndef DBUS_DISABLE_ASSERT 00167 int i; 00168 dbus_bool_t found = FALSE; 00169 #endif 00170 00171 SERVER_LOCK (server); 00172 00173 #ifndef DBUS_DISABLE_ASSERT 00174 for (i = 0 ; i < socket_server->n_fds ; i++) 00175 { 00176 if (socket_server->watch[i] == watch) 00177 found = TRUE; 00178 } 00179 _dbus_assert (found); 00180 #endif 00181 00182 _dbus_verbose ("Handling client connection, flags 0x%x\n", flags); 00183 00184 if (flags & DBUS_WATCH_READABLE) 00185 { 00186 DBusSocket client_fd; 00187 DBusSocket listen_fd; 00188 int saved_errno; 00189 00190 listen_fd = _dbus_watch_get_socket (watch); 00191 00192 if (socket_server->noncefile) 00193 client_fd = _dbus_accept_with_noncefile (listen_fd, socket_server->noncefile); 00194 else 00195 client_fd = _dbus_accept (listen_fd); 00196 00197 saved_errno = _dbus_save_socket_errno (); 00198 00199 if (!_dbus_socket_is_valid (client_fd)) 00200 { 00201 /* EINTR handled for us */ 00202 00203 if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno)) 00204 _dbus_verbose ("No client available to accept after all\n"); 00205 else 00206 _dbus_verbose ("Failed to accept a client connection: %s\n", 00207 _dbus_strerror (saved_errno)); 00208 00209 SERVER_UNLOCK (server); 00210 } 00211 else 00212 { 00213 if (!handle_new_client_fd_and_unlock (server, client_fd)) 00214 _dbus_verbose ("Rejected client connection due to lack of memory\n"); 00215 } 00216 } 00217 00218 if (flags & DBUS_WATCH_ERROR) 00219 _dbus_verbose ("Error on server listening socket\n"); 00220 00221 if (flags & DBUS_WATCH_HANGUP) 00222 _dbus_verbose ("Hangup on server listening socket\n"); 00223 00224 return TRUE; 00225 } 00226 00227 static void 00228 socket_disconnect (DBusServer *server) 00229 { 00230 DBusServerSocket *socket_server = (DBusServerSocket*) server; 00231 int i; 00232 00233 HAVE_LOCK_CHECK (server); 00234 00235 for (i = 0 ; i < socket_server->n_fds ; i++) 00236 { 00237 if (socket_server->watch[i]) 00238 { 00239 _dbus_server_remove_watch (server, 00240 socket_server->watch[i]); 00241 _dbus_watch_invalidate (socket_server->watch[i]); 00242 _dbus_watch_unref (socket_server->watch[i]); 00243 socket_server->watch[i] = NULL; 00244 } 00245 00246 _dbus_close_socket (socket_server->fds[i], NULL); 00247 _dbus_socket_invalidate (&socket_server->fds[i]); 00248 } 00249 00250 if (socket_server->socket_name != NULL) 00251 { 00252 DBusString tmp; 00253 _dbus_string_init_const (&tmp, socket_server->socket_name); 00254 _dbus_delete_file (&tmp, NULL); 00255 } 00256 00257 if (server->published_address) 00258 _dbus_daemon_unpublish_session_bus_address(); 00259 00260 HAVE_LOCK_CHECK (server); 00261 } 00262 00263 static const DBusServerVTable socket_vtable = { 00264 socket_finalize, 00265 socket_disconnect 00266 }; 00267 00284 DBusServer* 00285 _dbus_server_new_for_socket (DBusSocket *fds, 00286 int n_fds, 00287 const DBusString *address, 00288 DBusNonceFile *noncefile, 00289 DBusError *error) 00290 { 00291 DBusServerSocket *socket_server; 00292 DBusServer *server; 00293 int i; 00294 00295 socket_server = dbus_new0 (DBusServerSocket, 1); 00296 if (socket_server == NULL) 00297 goto failed_0; 00298 00299 socket_server->noncefile = noncefile; 00300 00301 socket_server->fds = dbus_new (DBusSocket, n_fds); 00302 if (!socket_server->fds) 00303 goto failed_0; 00304 00305 socket_server->watch = dbus_new0 (DBusWatch *, n_fds); 00306 if (!socket_server->watch) 00307 goto failed_1; 00308 00309 for (i = 0 ; i < n_fds ; i++) 00310 { 00311 DBusWatch *watch; 00312 00313 watch = _dbus_watch_new (_dbus_socket_get_pollable (fds[i]), 00314 DBUS_WATCH_READABLE, 00315 TRUE, 00316 socket_handle_watch, socket_server, 00317 NULL); 00318 if (watch == NULL) 00319 goto failed_2; 00320 00321 socket_server->n_fds++; 00322 socket_server->fds[i] = fds[i]; 00323 socket_server->watch[i] = watch; 00324 } 00325 00326 if (!_dbus_server_init_base (&socket_server->base, 00327 &socket_vtable, address, 00328 error)) 00329 goto failed_2; 00330 00331 server = (DBusServer*)socket_server; 00332 00333 SERVER_LOCK (server); 00334 00335 for (i = 0 ; i < n_fds ; i++) 00336 { 00337 if (!_dbus_server_add_watch (&socket_server->base, 00338 socket_server->watch[i])) 00339 { 00340 int j; 00341 for (j = 0 ; j < i ; j++) 00342 _dbus_server_remove_watch (server, 00343 socket_server->watch[j]); 00344 00345 SERVER_UNLOCK (server); 00346 _dbus_server_finalize_base (&socket_server->base); 00347 goto failed_2; 00348 } 00349 } 00350 00351 SERVER_UNLOCK (server); 00352 00353 _dbus_server_trace_ref (&socket_server->base, 0, 1, "new_for_socket"); 00354 return (DBusServer*) socket_server; 00355 00356 failed_2: 00357 for (i = 0 ; i < n_fds ; i++) 00358 { 00359 if (socket_server->watch[i] != NULL) 00360 { 00361 _dbus_watch_unref (socket_server->watch[i]); 00362 socket_server->watch[i] = NULL; 00363 } 00364 } 00365 dbus_free (socket_server->watch); 00366 00367 failed_1: 00368 dbus_free (socket_server->fds); 00369 00370 failed_0: 00371 dbus_free (socket_server); 00372 00373 if (error != NULL && !dbus_error_is_set (error)) 00374 _DBUS_SET_OOM (error); 00375 00376 return NULL; 00377 } 00378 00398 DBusServer* 00399 _dbus_server_new_for_tcp_socket (const char *host, 00400 const char *bind, 00401 const char *port, 00402 const char *family, 00403 DBusError *error, 00404 dbus_bool_t use_nonce) 00405 { 00406 DBusServer *server; 00407 DBusSocket *listen_fds = NULL; 00408 int nlisten_fds = 0, i; 00409 DBusString address; 00410 DBusString host_str; 00411 DBusString port_str; 00412 DBusNonceFile *noncefile; 00413 00414 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00415 00416 noncefile = NULL; 00417 00418 if (!_dbus_string_init (&address)) 00419 { 00420 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00421 return NULL; 00422 } 00423 00424 if (!_dbus_string_init (&port_str)) 00425 { 00426 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00427 goto failed_0; 00428 } 00429 00430 if (host == NULL) 00431 host = "localhost"; 00432 00433 if (port == NULL) 00434 port = "0"; 00435 00436 if (bind == NULL) 00437 bind = host; 00438 else if (strcmp (bind, "*") == 0) 00439 bind = NULL; 00440 00441 nlisten_fds =_dbus_listen_tcp_socket (bind, port, family, 00442 &port_str, 00443 &listen_fds, error); 00444 if (nlisten_fds <= 0) 00445 { 00446 _DBUS_ASSERT_ERROR_IS_SET(error); 00447 goto failed_1; 00448 } 00449 00450 _dbus_string_init_const (&host_str, host); 00451 if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") || 00452 !_dbus_address_append_escaped (&address, &host_str) || 00453 !_dbus_string_append (&address, ",port=") || 00454 !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str))) 00455 { 00456 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00457 goto failed_2; 00458 } 00459 if (family && 00460 (!_dbus_string_append (&address, ",family=") || 00461 !_dbus_string_append (&address, family))) 00462 { 00463 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00464 goto failed_2; 00465 } 00466 00467 if (use_nonce) 00468 { 00469 noncefile = dbus_new0 (DBusNonceFile, 1); 00470 if (noncefile == NULL) 00471 { 00472 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00473 goto failed_2; 00474 } 00475 00476 if (!_dbus_noncefile_create (noncefile, error)) 00477 goto failed_3; 00478 00479 if (!_dbus_string_append (&address, ",noncefile=") || 00480 !_dbus_address_append_escaped (&address, _dbus_noncefile_get_path (noncefile))) 00481 { 00482 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00483 goto failed_4; 00484 } 00485 00486 } 00487 00488 server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, noncefile, error); 00489 if (server == NULL) 00490 { 00491 if (noncefile != NULL) 00492 goto failed_4; 00493 else 00494 goto failed_2; 00495 } 00496 00497 _dbus_string_free (&port_str); 00498 _dbus_string_free (&address); 00499 dbus_free(listen_fds); 00500 00501 return server; 00502 00503 failed_4: 00504 _dbus_noncefile_delete (noncefile, NULL); 00505 00506 failed_3: 00507 dbus_free (noncefile); 00508 00509 failed_2: 00510 for (i = 0 ; i < nlisten_fds ; i++) 00511 _dbus_close_socket (listen_fds[i], NULL); 00512 dbus_free(listen_fds); 00513 00514 failed_1: 00515 _dbus_string_free (&port_str); 00516 00517 failed_0: 00518 _dbus_string_free (&address); 00519 00520 return NULL; 00521 } 00522 00535 DBusServerListenResult 00536 _dbus_server_listen_socket (DBusAddressEntry *entry, 00537 DBusServer **server_p, 00538 DBusError *error) 00539 { 00540 const char *method; 00541 00542 *server_p = NULL; 00543 00544 method = dbus_address_entry_get_method (entry); 00545 00546 if (strcmp (method, "tcp") == 0 || strcmp (method, "nonce-tcp") == 0) 00547 { 00548 const char *host; 00549 const char *port; 00550 const char *bind; 00551 const char *family; 00552 00553 host = dbus_address_entry_get_value (entry, "host"); 00554 bind = dbus_address_entry_get_value (entry, "bind"); 00555 port = dbus_address_entry_get_value (entry, "port"); 00556 family = dbus_address_entry_get_value (entry, "family"); 00557 00558 *server_p = _dbus_server_new_for_tcp_socket (host, bind, port, 00559 family, error, strcmp (method, "nonce-tcp") == 0 ? TRUE : FALSE); 00560 00561 if (*server_p) 00562 { 00563 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00564 return DBUS_SERVER_LISTEN_OK; 00565 } 00566 else 00567 { 00568 _DBUS_ASSERT_ERROR_IS_SET(error); 00569 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00570 } 00571 } 00572 else 00573 { 00574 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00575 return DBUS_SERVER_LISTEN_NOT_HANDLED; 00576 } 00577 } 00578 00588 void 00589 _dbus_server_socket_own_filename (DBusServer *server, 00590 char *filename) 00591 { 00592 DBusServerSocket *socket_server = (DBusServerSocket*) server; 00593 00594 socket_server->socket_name = filename; 00595 } 00596 00597