D-Bus  1.10.12
dbus-server-socket.c
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