auth: Generate a human readable Authentication log message.
[amitay/samba.git] / source3 / rpc_server / rpc_sock_helper.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  RPC Socket Helper
5  *
6  *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "ntdomain.h"
24
25 #include "../lib/tsocket/tsocket.h"
26 #include "librpc/rpc/dcerpc_ep.h"
27 #include "rpc_server/rpc_server.h"
28 #include "rpc_server/rpc_sock_helper.h"
29
30 NTSTATUS rpc_create_tcpip_sockets(const struct ndr_interface_table *iface,
31                                   struct dcerpc_binding_vector *bvec,
32                                   uint16_t port,
33                                   int *listen_fd,
34                                   int *listen_fd_size)
35 {
36         uint32_t num_ifs = iface_count();
37         uint32_t i;
38         uint16_t p = port;
39         TALLOC_CTX *tmp_ctx;
40         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
41         int rc;
42
43         tmp_ctx = talloc_stackframe();
44         if (tmp_ctx == NULL) {
45                 return NT_STATUS_NO_MEMORY;
46         }
47
48         if (lp_interfaces() && lp_bind_interfaces_only()) {
49                 /*
50                  * We have been given an interfaces line, and been told to only
51                  * bind to those interfaces. Create a socket per interface and
52                  * bind to only these.
53                  */
54
55                 /* Now open a listen socket for each of the interfaces. */
56                 for (i = 0; i < num_ifs; i++) {
57                         const struct sockaddr_storage *ifss =
58                                         iface_n_sockaddr_storage(i);
59                         struct tsocket_address *bind_addr;
60                         const char *addr;
61                         int fd;
62
63                         fd = create_tcpip_socket(ifss, &p);
64                         if (fd < 0 || p == 0) {
65                                 status = NT_STATUS_UNSUCCESSFUL;
66                                 if (fd != -1) {
67                                         close(fd);
68                                 }
69                                 goto done;
70                         }
71                         listen_fd[*listen_fd_size] = fd;
72                         (*listen_fd_size)++;
73
74                         if (bvec != NULL) {
75                                 rc = tsocket_address_bsd_from_sockaddr(tmp_ctx,
76                                                                        (const struct sockaddr *)ifss,
77                                                                        sizeof(struct sockaddr_storage),
78                                                                        &bind_addr);
79                                 if (rc < 0) {
80                                         close(fd);
81                                         status = NT_STATUS_NO_MEMORY;
82                                         goto done;
83                                 }
84
85                                 addr = tsocket_address_inet_addr_string(bind_addr,
86                                                                         tmp_ctx);
87                                 if (addr == NULL) {
88                                         close(fd);
89                                         status = NT_STATUS_NO_MEMORY;
90                                         goto done;
91                                 }
92
93                                 status = dcerpc_binding_vector_add_port(iface,
94                                                                         bvec,
95                                                                         addr,
96                                                                         p);
97                                 if (!NT_STATUS_IS_OK(status)) {
98                                         close(fd);
99                                         goto done;
100                                 }
101                         }
102                 }
103         } else {
104                 const char *sock_addr;
105                 const char *sock_ptr;
106                 char *sock_tok;
107
108 #if HAVE_IPV6
109                 sock_addr = "::,0.0.0.0";
110 #else
111                 sock_addr = "0.0.0.0";
112 #endif
113
114                 for (sock_ptr = sock_addr;
115                      next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
116                     ) {
117                         struct sockaddr_storage ss;
118                         int fd;
119
120                         /* open an incoming socket */
121                         if (!interpret_string_addr(&ss,
122                                                    sock_tok,
123                                                    AI_NUMERICHOST|AI_PASSIVE)) {
124                                 continue;
125                         }
126
127                         fd = create_tcpip_socket(&ss, &p);
128                         if (fd < 0 || p == 0) {
129                                 status = NT_STATUS_UNSUCCESSFUL;
130                                 if (fd != -1) {
131                                         close(fd);
132                                 }
133                                 goto done;
134                         }
135                         listen_fd[*listen_fd_size] = fd;
136                         (*listen_fd_size)++;
137
138                         if (bvec != NULL) {
139                                 status = dcerpc_binding_vector_add_port(iface,
140                                                                         bvec,
141                                                                         sock_tok,
142                                                                         p);
143                                 if (!NT_STATUS_IS_OK(status)) {
144                                         close(fd);
145                                         goto done;
146                                 }
147                         }
148                 }
149         }
150
151         status = NT_STATUS_OK;
152 done:
153         talloc_free(tmp_ctx);
154         return status;
155 }
156
157 NTSTATUS rpc_setup_tcpip_sockets(struct tevent_context *ev_ctx,
158                                  struct messaging_context *msg_ctx,
159                                  const struct ndr_interface_table *iface,
160                                  struct dcerpc_binding_vector *bvec,
161                                  uint16_t port)
162 {
163         uint32_t num_ifs = iface_count();
164         uint32_t i;
165         uint16_t p = 0;
166         TALLOC_CTX *tmp_ctx;
167         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
168         int rc;
169
170         tmp_ctx = talloc_stackframe();
171         if (tmp_ctx == NULL) {
172                 return NT_STATUS_NO_MEMORY;
173         }
174
175         if (lp_interfaces() && lp_bind_interfaces_only()) {
176                 /*
177                  * We have been given an interfaces line, and been told to only
178                  * bind to those interfaces. Create a socket per interface and
179                  * bind to only these.
180                  */
181
182                 /* Now open a listen socket for each of the interfaces. */
183                 for (i = 0; i < num_ifs; i++) {
184                         const struct sockaddr_storage *ifss =
185                                         iface_n_sockaddr_storage(i);
186                         struct tsocket_address *bind_addr;
187                         const char *addr;
188
189                         p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
190                                                             msg_ctx,
191                                                             ifss,
192                                                             port);
193                         if (p == 0) {
194                                 status = NT_STATUS_UNSUCCESSFUL;
195                                 goto done;
196                         }
197
198                         if (bvec != NULL) {
199                                 rc = tsocket_address_bsd_from_sockaddr(tmp_ctx,
200                                                                        (const struct sockaddr*)ifss,
201                                                                        sizeof(struct sockaddr_storage),
202                                                                        &bind_addr);
203                                 if (rc < 0) {
204                                         status = NT_STATUS_NO_MEMORY;
205                                         goto done;
206                                 }
207
208                                 addr = tsocket_address_inet_addr_string(bind_addr,
209                                                                         tmp_ctx);
210                                 if (addr == NULL) {
211                                         status = NT_STATUS_NO_MEMORY;
212                                         goto done;
213                                 }
214
215                                 status = dcerpc_binding_vector_add_port(iface,
216                                                                         bvec,
217                                                                         addr,
218                                                                         p);
219                                 if (!NT_STATUS_IS_OK(status)) {
220                                         goto done;
221                                 }
222                         }
223                 }
224         } else {
225                 const char *sock_addr;
226                 const char *sock_ptr;
227                 char *sock_tok;
228
229 #if HAVE_IPV6
230                 sock_addr = "::,0.0.0.0";
231 #else
232                 sock_addr = "0.0.0.0";
233 #endif
234
235                 for (sock_ptr = sock_addr;
236                      next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
237                     ) {
238                         struct sockaddr_storage ss;
239
240                         /* open an incoming socket */
241                         if (!interpret_string_addr(&ss,
242                                                    sock_tok,
243                                                    AI_NUMERICHOST|AI_PASSIVE)) {
244                                 continue;
245                         }
246
247                         p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
248                                                             msg_ctx,
249                                                             &ss,
250                                                             port);
251                         if (p == 0) {
252                                 status = NT_STATUS_UNSUCCESSFUL;
253                                 goto done;
254                         }
255
256                         if (bvec != NULL) {
257                                 status = dcerpc_binding_vector_add_port(iface,
258                                                                         bvec,
259                                                                         sock_tok,
260                                                                         p);
261                                 if (!NT_STATUS_IS_OK(status)) {
262                                         goto done;
263                                 }
264                         }
265                 }
266         }
267
268         status = NT_STATUS_OK;
269 done:
270         talloc_free(tmp_ctx);
271         return status;
272 }
273
274 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */