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