1 /*
2  * Copyright (c) 2002-2013 Balabit
3  * Copyright (c) 1998-2013 Balázs Scheidler
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published
7  * by the Free Software Foundation, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * As an additional exemption you are allowed to compile & link against the
19  * OpenSSL libraries as published by the OpenSSL project. See the file
20  * COPYING for details.
21  *
22  */
23 
24 #include "transport-mapper.h"
25 #include "gprocess.h"
26 #include "gsockaddr.h"
27 #include "gsocket.h"
28 #include "messages.h"
29 #include "fdhelpers.h"
30 #include "transport/transport-socket.h"
31 
32 #include <errno.h>
33 #include <unistd.h>
34 
35 static gboolean
transport_mapper_privileged_bind(gint sock,GSockAddr * bind_addr)36 transport_mapper_privileged_bind(gint sock, GSockAddr *bind_addr)
37 {
38   cap_t saved_caps;
39   GIOStatus status;
40 
41   saved_caps = g_process_cap_save();
42   g_process_enable_cap("cap_net_bind_service");
43   g_process_enable_cap("cap_dac_override");
44 
45   status = g_bind(sock, bind_addr);
46 
47   g_process_cap_restore(saved_caps);
48   return status == G_IO_STATUS_NORMAL;
49 }
50 
51 gboolean
transport_mapper_open_socket(TransportMapper * self,SocketOptions * socket_options,GSockAddr * bind_addr,GSockAddr * peer_addr,AFSocketDirection dir,int * fd)52 transport_mapper_open_socket(TransportMapper *self,
53                              SocketOptions *socket_options,
54                              GSockAddr *bind_addr,
55                              GSockAddr *peer_addr,
56                              AFSocketDirection dir,
57                              int *fd)
58 {
59   gint sock;
60 
61   sock = socket(self->address_family, self->sock_type, self->sock_proto);
62   if (sock < 0)
63     {
64       msg_error("Error creating socket",
65                 evt_tag_error(EVT_TAG_OSERROR));
66       goto error;
67     }
68 
69   g_fd_set_nonblock(sock, TRUE);
70   g_fd_set_cloexec(sock, TRUE);
71 
72   if (!socket_options_setup_socket(socket_options, sock, peer_addr, dir))
73     goto error_close;
74 
75   if (!transport_mapper_privileged_bind(sock, bind_addr))
76     {
77       gchar buf[256];
78 
79       msg_error("Error binding socket",
80                 evt_tag_str("addr", g_sockaddr_format(bind_addr, buf, sizeof(buf), GSA_FULL)),
81                 evt_tag_error(EVT_TAG_OSERROR));
82       goto error_close;
83     }
84 
85   *fd = sock;
86   return TRUE;
87 
88 error_close:
89   close(sock);
90 error:
91   *fd = -1;
92   return FALSE;
93 }
94 
95 gboolean
transport_mapper_apply_transport_method(TransportMapper * self,GlobalConfig * cfg)96 transport_mapper_apply_transport_method(TransportMapper *self, GlobalConfig *cfg)
97 {
98   return TRUE;
99 }
100 
101 void
transport_mapper_set_transport(TransportMapper * self,const gchar * transport)102 transport_mapper_set_transport(TransportMapper *self, const gchar *transport)
103 {
104   g_free(self->transport);
105   self->transport = g_strdup(transport);
106 }
107 
108 void
transport_mapper_set_address_family(TransportMapper * self,gint address_family)109 transport_mapper_set_address_family(TransportMapper *self, gint address_family)
110 {
111   self->address_family = address_family;
112 }
113 
114 void
transport_mapper_free_method(TransportMapper * self)115 transport_mapper_free_method(TransportMapper *self)
116 {
117   g_free(self->transport);
118 }
119 
120 void
transport_mapper_init_instance(TransportMapper * self,const gchar * transport)121 transport_mapper_init_instance(TransportMapper *self, const gchar *transport)
122 {
123   self->transport = g_strdup(transport);
124   self->address_family = -1;
125   self->sock_type = -1;
126   self->free_fn = transport_mapper_free_method;
127   self->apply_transport = transport_mapper_apply_transport_method;
128 }
129 
130 void
transport_mapper_free(TransportMapper * self)131 transport_mapper_free(TransportMapper *self)
132 {
133   if (self->free_fn)
134     self->free_fn(self);
135 
136   g_free(self);
137 }
138