Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Samba utility functions
4 : Copyright (C) Andrew Tridgell 1992-1998
5 : Copyright (C) Tim Potter 2000-2001
6 : Copyright (C) Jeremy Allison 1992-2007
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 "system/filesys.h"
24 : #include "../lib/util/memcache.h"
25 : #include "../lib/async_req/async_sock.h"
26 : #include "../lib/util/select.h"
27 : #include "lib/socket/interfaces.h"
28 : #include "../lib/util/tevent_unix.h"
29 : #include "../lib/util/tevent_ntstatus.h"
30 : #include "../lib/tsocket/tsocket.h"
31 : #include "lib/util/sys_rw.h"
32 : #include "lib/util/sys_rw_data.h"
33 : #include "source3/lib/util_tsock.h"
34 :
35 : /****************************************************************************
36 : Determine if a file descriptor is in fact a socket.
37 : ****************************************************************************/
38 :
39 43 : bool is_a_socket(int fd)
40 : {
41 0 : int v;
42 0 : socklen_t l;
43 43 : l = sizeof(int);
44 43 : return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
45 : }
46 :
47 : /****************************************************************************
48 : Read data from a file descriptor with a timeout in msec.
49 : mincount = if timeout, minimum to read before returning
50 : maxcount = number to be read.
51 : time_out = timeout in milliseconds
52 : NB. This can be called with a non-socket fd, don't change
53 : sys_read() to sys_recv() or other socket call.
54 : ****************************************************************************/
55 :
56 1366120 : NTSTATUS read_fd_with_timeout(int fd, char *buf,
57 : size_t mincnt, size_t maxcnt,
58 : unsigned int time_out,
59 : size_t *size_ret)
60 : {
61 17253 : int pollrtn;
62 17253 : ssize_t readret;
63 1366120 : size_t nread = 0;
64 :
65 : /* just checking .... */
66 1366120 : if (maxcnt <= 0)
67 0 : return NT_STATUS_OK;
68 :
69 : /* Blocking read */
70 1366120 : if (time_out == 0) {
71 1366120 : if (mincnt == 0) {
72 0 : mincnt = maxcnt;
73 : }
74 :
75 2941277 : while (nread < mincnt) {
76 1581013 : readret = sys_read(fd, buf + nread, maxcnt - nread);
77 :
78 1581013 : if (readret == 0) {
79 5846 : DEBUG(5,("read_fd_with_timeout: "
80 : "blocking read. EOF from client.\n"));
81 5846 : return NT_STATUS_END_OF_FILE;
82 : }
83 :
84 1575167 : if (readret == -1) {
85 10 : return map_nt_error_from_unix(errno);
86 : }
87 1575157 : nread += readret;
88 : }
89 1360264 : goto done;
90 : }
91 :
92 : /* Most difficult - timeout read */
93 : /* If this is ever called on a disk file and
94 : mincnt is greater then the filesize then
95 : system performance will suffer severely as
96 : select always returns true on disk files */
97 :
98 0 : for (nread=0; nread < mincnt; ) {
99 0 : int revents;
100 :
101 0 : pollrtn = poll_intr_one_fd(fd, POLLIN|POLLHUP, time_out,
102 : &revents);
103 :
104 : /* Check if error */
105 0 : if (pollrtn == -1) {
106 0 : return map_nt_error_from_unix(errno);
107 : }
108 :
109 : /* Did we timeout ? */
110 0 : if ((pollrtn == 0) ||
111 0 : ((revents & (POLLIN|POLLHUP|POLLERR)) == 0)) {
112 0 : DEBUG(10,("read_fd_with_timeout: timeout read. "
113 : "select timed out.\n"));
114 0 : return NT_STATUS_IO_TIMEOUT;
115 : }
116 :
117 0 : readret = sys_read(fd, buf+nread, maxcnt-nread);
118 :
119 0 : if (readret == 0) {
120 : /* we got EOF on the file descriptor */
121 0 : DEBUG(5,("read_fd_with_timeout: timeout read. "
122 : "EOF from client.\n"));
123 0 : return NT_STATUS_END_OF_FILE;
124 : }
125 :
126 0 : if (readret == -1) {
127 0 : return map_nt_error_from_unix(errno);
128 : }
129 :
130 0 : nread += readret;
131 : }
132 :
133 0 : done:
134 : /* Return the number we got */
135 1360264 : if (size_ret) {
136 0 : *size_ret = nread;
137 : }
138 1360264 : return NT_STATUS_OK;
139 : }
140 :
141 : /****************************************************************************
142 : Read data from an fd, reading exactly N bytes.
143 : NB. This can be called with a non-socket fd, don't add dependencies
144 : on socket calls.
145 : ****************************************************************************/
146 :
147 0 : NTSTATUS read_data_ntstatus(int fd, char *buffer, size_t N)
148 : {
149 0 : return read_fd_with_timeout(fd, buffer, N, N, 0, NULL);
150 : }
151 :
152 : /****************************************************************************
153 : Read 4 bytes of a smb packet and return the smb length of the packet.
154 : Store the result in the buffer.
155 : This version of the function will return a length of zero on receiving
156 : a keepalive packet.
157 : Timeout is in milliseconds.
158 : ****************************************************************************/
159 :
160 685988 : NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
161 : unsigned int timeout,
162 : size_t *len)
163 : {
164 8693 : int msg_type;
165 8693 : NTSTATUS status;
166 :
167 685988 : status = read_fd_with_timeout(fd, inbuf, 4, 4, timeout, NULL);
168 :
169 685988 : if (!NT_STATUS_IS_OK(status)) {
170 5856 : return status;
171 : }
172 :
173 680132 : *len = smb_len(inbuf);
174 680132 : msg_type = CVAL(inbuf,0);
175 :
176 680132 : if (msg_type == NBSSkeepalive) {
177 0 : DEBUG(5,("Got keepalive packet\n"));
178 : }
179 :
180 680132 : DEBUG(10,("got smb length of %lu\n",(unsigned long)(*len)));
181 :
182 680132 : return NT_STATUS_OK;
183 : }
184 :
185 : /****************************************************************************
186 : Read an smb from a fd.
187 : The timeout is in milliseconds.
188 : This function will return on receipt of a session keepalive packet.
189 : maxlen is the max number of bytes to return, not including the 4 byte
190 : length. If zero it means buflen limit.
191 : Doesn't check the MAC on signed packets.
192 : ****************************************************************************/
193 :
194 0 : NTSTATUS receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeout,
195 : size_t maxlen, size_t *p_len)
196 : {
197 0 : size_t len;
198 0 : NTSTATUS status;
199 :
200 0 : status = read_smb_length_return_keepalive(fd,buffer,timeout,&len);
201 :
202 0 : if (!NT_STATUS_IS_OK(status)) {
203 0 : DEBUG(0, ("read_fd_with_timeout failed, read "
204 : "error = %s.\n", nt_errstr(status)));
205 0 : return status;
206 : }
207 :
208 0 : if (len > buflen) {
209 0 : DEBUG(0,("Invalid packet length! (%lu bytes).\n",
210 : (unsigned long)len));
211 0 : return NT_STATUS_INVALID_PARAMETER;
212 : }
213 :
214 0 : if(len > 0) {
215 0 : if (maxlen) {
216 0 : len = MIN(len,maxlen);
217 : }
218 :
219 0 : status = read_fd_with_timeout(
220 : fd, buffer+4, len, len, timeout, &len);
221 :
222 0 : if (!NT_STATUS_IS_OK(status)) {
223 0 : DEBUG(0, ("read_fd_with_timeout failed, read error = "
224 : "%s.\n", nt_errstr(status)));
225 0 : return status;
226 : }
227 :
228 : /* not all of samba3 properly checks for packet-termination
229 : * of strings. This ensures that we don't run off into
230 : * empty space. */
231 0 : SSVAL(buffer+4,len, 0);
232 : }
233 :
234 0 : *p_len = len;
235 0 : return NT_STATUS_OK;
236 : }
237 :
238 : /*
239 : * Open a socket of the specified type, port, and address for incoming data.
240 : *
241 : * Return sock or -errno
242 : */
243 :
244 751 : int open_socket_in(
245 : int type,
246 : const struct sockaddr_storage *paddr,
247 : uint16_t port,
248 : bool rebind)
249 : {
250 751 : struct samba_sockaddr addr = {
251 : .sa_socklen = sizeof(struct sockaddr_storage),
252 : .u.ss = *paddr,
253 : };
254 751 : int ret, sock = -1;
255 751 : int val = rebind ? 1 : 0;
256 0 : bool ok;
257 :
258 751 : switch (addr.u.sa.sa_family) {
259 80 : case AF_INET6:
260 80 : addr.sa_socklen = sizeof(struct sockaddr_in6);
261 80 : break;
262 671 : case AF_INET:
263 671 : addr.sa_socklen = sizeof(struct sockaddr_in);
264 671 : break;
265 : }
266 :
267 751 : ok = samba_sockaddr_set_port(&addr, port);
268 751 : if (!ok) {
269 0 : ret = -EINVAL;
270 0 : DBG_DEBUG("samba_sockaddr_set_port failed\n");
271 0 : goto fail;
272 : }
273 :
274 751 : sock = socket(addr.u.ss.ss_family, type, 0 );
275 751 : if (sock == -1) {
276 0 : ret = -errno;
277 0 : DBG_DEBUG("socket() failed: %s\n", strerror(errno));
278 0 : goto fail;
279 : }
280 :
281 751 : ret = setsockopt(
282 : sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
283 751 : if (ret == -1) {
284 0 : ret = -errno;
285 0 : DBG_DEBUG("setsockopt(SO_REUSEADDR) failed: %s\n",
286 : strerror(errno));
287 0 : goto fail;
288 : }
289 :
290 : #ifdef SO_REUSEPORT
291 751 : ret = setsockopt(
292 : sock, SOL_SOCKET, SO_REUSEPORT, (char *)&val, sizeof(val));
293 751 : if (ret == -1) {
294 0 : ret = -errno;
295 0 : DBG_DEBUG("setsockopt(SO_REUSEPORT) failed: %s\n",
296 : strerror(errno));
297 0 : goto fail;
298 : }
299 : #endif /* SO_REUSEPORT */
300 :
301 : #ifdef HAVE_IPV6
302 : /*
303 : * As IPV6_V6ONLY is the default on some systems,
304 : * we better try to be consistent and always use it.
305 : *
306 : * This also avoids using IPv4 via AF_INET6 sockets
307 : * and makes sure %I never resolves to a '::ffff:192.168.0.1'
308 : * string.
309 : */
310 751 : if (addr.u.ss.ss_family == AF_INET6) {
311 :
312 80 : val = 1;
313 :
314 80 : ret = setsockopt(
315 : sock,
316 : IPPROTO_IPV6,
317 : IPV6_V6ONLY,
318 : (const void *)&val,
319 : sizeof(val));
320 80 : if (ret == -1) {
321 0 : ret = -errno;
322 0 : DBG_DEBUG("setsockopt(IPV6_V6ONLY) failed: %s\n",
323 : strerror(errno));
324 0 : goto fail;
325 : }
326 : }
327 : #endif
328 :
329 : /* now we've got a socket - we need to bind it */
330 751 : ret = bind(sock, &addr.u.sa, addr.sa_socklen);
331 751 : if (ret == -1) {
332 0 : char addrstr[INET6_ADDRSTRLEN];
333 :
334 0 : ret = -errno;
335 :
336 0 : print_sockaddr(addrstr, sizeof(addrstr), &addr.u.ss);
337 0 : DBG_DEBUG("bind for %s port %"PRIu16" failed: %s\n",
338 : addrstr,
339 : port,
340 : strerror(-ret));
341 0 : goto fail;
342 : }
343 :
344 751 : DBG_DEBUG("bind succeeded on port %"PRIu16"\n", port);
345 :
346 751 : return sock;
347 :
348 0 : fail:
349 0 : if (sock != -1) {
350 0 : close(sock);
351 0 : sock = -1;
352 : }
353 0 : return ret;
354 : }
355 :
356 : struct open_socket_out_state {
357 : int fd;
358 : struct tevent_context *ev;
359 : struct sockaddr_storage ss;
360 : socklen_t salen;
361 : uint16_t port;
362 : struct tevent_req *connect_subreq;
363 : };
364 :
365 : static void open_socket_out_connected(struct tevent_req *subreq);
366 :
367 36956 : static void open_socket_out_cleanup(struct tevent_req *req,
368 : enum tevent_req_state req_state)
369 : {
370 0 : struct open_socket_out_state *state =
371 36956 : tevent_req_data(req, struct open_socket_out_state);
372 :
373 : /*
374 : * Make sure that the async_connect_send subreq has a chance to reset
375 : * fcntl before the socket goes away.
376 : */
377 36956 : TALLOC_FREE(state->connect_subreq);
378 :
379 36956 : if (req_state == TEVENT_REQ_DONE) {
380 : /*
381 : * we keep the socket open for the caller to use
382 : */
383 18474 : return;
384 : }
385 :
386 18482 : if (state->fd != -1) {
387 4 : close(state->fd);
388 4 : state->fd = -1;
389 : }
390 : }
391 :
392 : /****************************************************************************
393 : Create an outgoing socket. timeout is in milliseconds.
394 : **************************************************************************/
395 :
396 18478 : struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
397 : struct tevent_context *ev,
398 : const struct sockaddr_storage *pss,
399 : uint16_t port,
400 : int timeout)
401 : {
402 0 : char addr[INET6_ADDRSTRLEN];
403 0 : struct tevent_req *req;
404 0 : struct open_socket_out_state *state;
405 0 : NTSTATUS status;
406 :
407 18478 : req = tevent_req_create(mem_ctx, &state,
408 : struct open_socket_out_state);
409 18478 : if (req == NULL) {
410 0 : return NULL;
411 : }
412 18478 : state->ev = ev;
413 18478 : state->ss = *pss;
414 18478 : state->port = port;
415 18478 : state->salen = -1;
416 :
417 18478 : state->fd = socket(state->ss.ss_family, SOCK_STREAM, 0);
418 18478 : if (state->fd == -1) {
419 0 : status = map_nt_error_from_unix(errno);
420 0 : tevent_req_nterror(req, status);
421 0 : return tevent_req_post(req, ev);
422 : }
423 :
424 18478 : tevent_req_set_cleanup_fn(req, open_socket_out_cleanup);
425 :
426 18478 : if ((timeout != 0) &&
427 18478 : !tevent_req_set_endtime(
428 : req, ev, timeval_current_ofs_msec(timeout))) {
429 0 : tevent_req_oom(req);
430 0 : return tevent_req_post(req, ev);
431 : }
432 :
433 : #if defined(HAVE_IPV6)
434 18478 : if (pss->ss_family == AF_INET6) {
435 0 : struct sockaddr_in6 *psa6;
436 176 : psa6 = (struct sockaddr_in6 *)&state->ss;
437 176 : psa6->sin6_port = htons(port);
438 176 : if (psa6->sin6_scope_id == 0
439 176 : && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
440 0 : setup_linklocal_scope_id(
441 0 : (struct sockaddr *)&(state->ss));
442 : }
443 176 : state->salen = sizeof(struct sockaddr_in6);
444 : }
445 : #endif
446 18478 : if (pss->ss_family == AF_INET) {
447 0 : struct sockaddr_in *psa;
448 18302 : psa = (struct sockaddr_in *)&state->ss;
449 18302 : psa->sin_port = htons(port);
450 18302 : state->salen = sizeof(struct sockaddr_in);
451 : }
452 :
453 18478 : if (pss->ss_family == AF_UNIX) {
454 0 : state->salen = sizeof(struct sockaddr_un);
455 : }
456 :
457 18478 : print_sockaddr(addr, sizeof(addr), &state->ss);
458 18478 : DEBUG(3,("Connecting to %s at port %u\n", addr, (unsigned int)port));
459 :
460 36956 : state->connect_subreq = async_connect_send(
461 18478 : state, state->ev, state->fd, (struct sockaddr *)&state->ss,
462 18478 : state->salen, NULL, NULL, NULL);
463 18478 : if (tevent_req_nomem(state->connect_subreq, NULL)) {
464 0 : return tevent_req_post(req, ev);
465 : }
466 18478 : tevent_req_set_callback(state->connect_subreq,
467 : open_socket_out_connected, req);
468 18478 : return req;
469 : }
470 :
471 18478 : static void open_socket_out_connected(struct tevent_req *subreq)
472 : {
473 0 : struct tevent_req *req =
474 18478 : tevent_req_callback_data(subreq, struct tevent_req);
475 0 : struct open_socket_out_state *state =
476 18478 : tevent_req_data(req, struct open_socket_out_state);
477 0 : int ret;
478 0 : int sys_errno;
479 :
480 18478 : ret = async_connect_recv(subreq, &sys_errno);
481 18478 : TALLOC_FREE(subreq);
482 18478 : state->connect_subreq = NULL;
483 18478 : if (ret == 0) {
484 18474 : tevent_req_done(req);
485 18474 : return;
486 : }
487 :
488 4 : tevent_req_nterror(req, map_nt_error_from_unix(sys_errno));
489 : }
490 :
491 18478 : NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd)
492 : {
493 0 : struct open_socket_out_state *state =
494 18478 : tevent_req_data(req, struct open_socket_out_state);
495 0 : NTSTATUS status;
496 :
497 18478 : if (tevent_req_is_nterror(req, &status)) {
498 4 : tevent_req_received(req);
499 4 : return status;
500 : }
501 18474 : *pfd = state->fd;
502 18474 : state->fd = -1;
503 18474 : tevent_req_received(req);
504 18474 : return NT_STATUS_OK;
505 : }
506 :
507 : /**
508 : * @brief open a socket
509 : *
510 : * @param pss a struct sockaddr_storage defining the address to connect to
511 : * @param port to connect to
512 : * @param timeout in MILLISECONDS
513 : * @param pfd file descriptor returned
514 : *
515 : * @return NTSTATUS code
516 : */
517 437 : NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
518 : int timeout, int *pfd)
519 : {
520 437 : TALLOC_CTX *frame = talloc_stackframe();
521 0 : struct tevent_context *ev;
522 0 : struct tevent_req *req;
523 437 : NTSTATUS status = NT_STATUS_NO_MEMORY;
524 :
525 437 : ev = samba_tevent_context_init(frame);
526 437 : if (ev == NULL) {
527 0 : goto fail;
528 : }
529 :
530 437 : req = open_socket_out_send(frame, ev, pss, port, timeout);
531 437 : if (req == NULL) {
532 0 : goto fail;
533 : }
534 437 : if (!tevent_req_poll(req, ev)) {
535 0 : status = NT_STATUS_INTERNAL_ERROR;
536 0 : goto fail;
537 : }
538 437 : status = open_socket_out_recv(req, pfd);
539 437 : fail:
540 437 : TALLOC_FREE(frame);
541 437 : return status;
542 : }
543 :
544 : struct open_socket_out_defer_state {
545 : struct tevent_context *ev;
546 : struct sockaddr_storage ss;
547 : uint16_t port;
548 : int timeout;
549 : int fd;
550 : };
551 :
552 : static void open_socket_out_defer_waited(struct tevent_req *subreq);
553 : static void open_socket_out_defer_connected(struct tevent_req *subreq);
554 :
555 0 : struct tevent_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
556 : struct tevent_context *ev,
557 : struct timeval wait_time,
558 : const struct sockaddr_storage *pss,
559 : uint16_t port,
560 : int timeout)
561 : {
562 0 : struct tevent_req *req, *subreq;
563 0 : struct open_socket_out_defer_state *state;
564 :
565 0 : req = tevent_req_create(mem_ctx, &state,
566 : struct open_socket_out_defer_state);
567 0 : if (req == NULL) {
568 0 : return NULL;
569 : }
570 0 : state->ev = ev;
571 0 : state->ss = *pss;
572 0 : state->port = port;
573 0 : state->timeout = timeout;
574 :
575 0 : subreq = tevent_wakeup_send(
576 : state, ev,
577 0 : timeval_current_ofs(wait_time.tv_sec, wait_time.tv_usec));
578 0 : if (subreq == NULL) {
579 0 : goto fail;
580 : }
581 0 : tevent_req_set_callback(subreq, open_socket_out_defer_waited, req);
582 0 : return req;
583 0 : fail:
584 0 : TALLOC_FREE(req);
585 0 : return NULL;
586 : }
587 :
588 0 : static void open_socket_out_defer_waited(struct tevent_req *subreq)
589 : {
590 0 : struct tevent_req *req = tevent_req_callback_data(
591 : subreq, struct tevent_req);
592 0 : struct open_socket_out_defer_state *state = tevent_req_data(
593 : req, struct open_socket_out_defer_state);
594 0 : bool ret;
595 :
596 0 : ret = tevent_wakeup_recv(subreq);
597 0 : TALLOC_FREE(subreq);
598 0 : if (!ret) {
599 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
600 0 : return;
601 : }
602 :
603 0 : subreq = open_socket_out_send(state, state->ev, &state->ss,
604 0 : state->port, state->timeout);
605 0 : if (tevent_req_nomem(subreq, req)) {
606 0 : return;
607 : }
608 0 : tevent_req_set_callback(subreq, open_socket_out_defer_connected, req);
609 : }
610 :
611 0 : static void open_socket_out_defer_connected(struct tevent_req *subreq)
612 : {
613 0 : struct tevent_req *req = tevent_req_callback_data(
614 : subreq, struct tevent_req);
615 0 : struct open_socket_out_defer_state *state = tevent_req_data(
616 : req, struct open_socket_out_defer_state);
617 0 : NTSTATUS status;
618 :
619 0 : status = open_socket_out_recv(subreq, &state->fd);
620 0 : TALLOC_FREE(subreq);
621 0 : if (!NT_STATUS_IS_OK(status)) {
622 0 : tevent_req_nterror(req, status);
623 0 : return;
624 : }
625 0 : tevent_req_done(req);
626 : }
627 :
628 0 : NTSTATUS open_socket_out_defer_recv(struct tevent_req *req, int *pfd)
629 : {
630 0 : struct open_socket_out_defer_state *state = tevent_req_data(
631 : req, struct open_socket_out_defer_state);
632 0 : NTSTATUS status;
633 :
634 0 : if (tevent_req_is_nterror(req, &status)) {
635 0 : return status;
636 : }
637 0 : *pfd = state->fd;
638 0 : state->fd = -1;
639 0 : return NT_STATUS_OK;
640 : }
641 :
642 : /*******************************************************************
643 : Return the IP addr of the remote end of a socket as a string.
644 : Optionally return the struct sockaddr_storage.
645 : ******************************************************************/
646 :
647 0 : static const char *get_peer_addr_internal(int fd,
648 : char *addr_buf,
649 : size_t addr_buf_len,
650 : struct sockaddr *pss,
651 : socklen_t *plength)
652 : {
653 0 : struct sockaddr_storage ss;
654 0 : socklen_t length = sizeof(ss);
655 :
656 0 : strlcpy(addr_buf,"0.0.0.0",addr_buf_len);
657 :
658 0 : if (fd == -1) {
659 0 : return addr_buf;
660 : }
661 :
662 0 : if (pss == NULL) {
663 0 : pss = (struct sockaddr *)&ss;
664 0 : plength = &length;
665 : }
666 :
667 0 : if (getpeername(fd, (struct sockaddr *)pss, plength) < 0) {
668 0 : int level = (errno == ENOTCONN) ? 2 : 0;
669 0 : DEBUG(level, ("getpeername failed. Error was %s\n",
670 : strerror(errno)));
671 0 : return addr_buf;
672 : }
673 :
674 0 : print_sockaddr_len(addr_buf,
675 : addr_buf_len,
676 : pss,
677 : *plength);
678 0 : return addr_buf;
679 : }
680 :
681 : /*******************************************************************
682 : Matchname - determine if host name matches IP address. Used to
683 : confirm a hostname lookup to prevent spoof attacks.
684 : ******************************************************************/
685 :
686 0 : static bool matchname(const char *remotehost,
687 : const struct sockaddr *pss,
688 : socklen_t len)
689 : {
690 0 : struct addrinfo *res = NULL;
691 0 : struct addrinfo *ailist = NULL;
692 0 : char addr_buf[INET6_ADDRSTRLEN];
693 0 : bool ret = interpret_string_addr_internal(&ailist,
694 : remotehost,
695 : AI_ADDRCONFIG|AI_CANONNAME);
696 :
697 0 : if (!ret || ailist == NULL) {
698 0 : DEBUG(3,("matchname: getaddrinfo failed for "
699 : "name %s [%s]\n",
700 : remotehost,
701 : gai_strerror(ret) ));
702 0 : return false;
703 : }
704 :
705 : /*
706 : * Make sure that getaddrinfo() returns the "correct" host name.
707 : */
708 :
709 0 : if (ailist->ai_canonname == NULL ||
710 0 : (!strequal(remotehost, ailist->ai_canonname) &&
711 0 : !strequal(remotehost, "localhost"))) {
712 0 : DEBUG(0,("matchname: host name/name mismatch: %s != %s\n",
713 : remotehost,
714 : ailist->ai_canonname ?
715 : ailist->ai_canonname : "(NULL)"));
716 0 : freeaddrinfo(ailist);
717 0 : return false;
718 : }
719 :
720 : /* Look up the host address in the address list we just got. */
721 0 : for (res = ailist; res; res = res->ai_next) {
722 0 : if (!res->ai_addr) {
723 0 : continue;
724 : }
725 0 : if (sockaddr_equal((const struct sockaddr *)res->ai_addr,
726 : (const struct sockaddr *)pss)) {
727 0 : freeaddrinfo(ailist);
728 0 : return true;
729 : }
730 : }
731 :
732 : /*
733 : * The host name does not map to the original host address. Perhaps
734 : * someone has compromised a name server. More likely someone botched
735 : * it, but that could be dangerous, too.
736 : */
737 :
738 0 : DEBUG(0,("matchname: host name/address mismatch: %s != %s\n",
739 : print_sockaddr_len(addr_buf,
740 : sizeof(addr_buf),
741 : pss,
742 : len),
743 : ailist->ai_canonname ? ailist->ai_canonname : "(NULL)"));
744 :
745 0 : if (ailist) {
746 0 : freeaddrinfo(ailist);
747 : }
748 0 : return false;
749 : }
750 :
751 : /*******************************************************************
752 : Deal with the singleton cache.
753 : ******************************************************************/
754 :
755 : struct name_addr_pair {
756 : struct sockaddr_storage ss;
757 : const char *name;
758 : };
759 :
760 : /*******************************************************************
761 : Lookup a name/addr pair. Returns memory allocated from memcache.
762 : ******************************************************************/
763 :
764 33843 : static bool lookup_nc(struct name_addr_pair *nc)
765 : {
766 894 : DATA_BLOB tmp;
767 :
768 33843 : ZERO_STRUCTP(nc);
769 :
770 33843 : if (!memcache_lookup(
771 : NULL, SINGLETON_CACHE,
772 : data_blob_string_const_null("get_peer_name"),
773 : &tmp)) {
774 1174 : return false;
775 : }
776 :
777 32669 : memcpy(&nc->ss, tmp.data, sizeof(nc->ss));
778 32669 : nc->name = (const char *)tmp.data + sizeof(nc->ss);
779 32669 : return true;
780 : }
781 :
782 : /*******************************************************************
783 : Save a name/addr pair.
784 : ******************************************************************/
785 :
786 33843 : static void store_nc(const struct name_addr_pair *nc)
787 : {
788 894 : DATA_BLOB tmp;
789 33843 : size_t namelen = strlen(nc->name);
790 :
791 33843 : tmp = data_blob(NULL, sizeof(nc->ss) + namelen + 1);
792 33843 : if (!tmp.data) {
793 0 : return;
794 : }
795 33843 : memcpy(tmp.data, &nc->ss, sizeof(nc->ss));
796 33843 : memcpy(tmp.data+sizeof(nc->ss), nc->name, namelen+1);
797 :
798 33843 : memcache_add(NULL, SINGLETON_CACHE,
799 : data_blob_string_const_null("get_peer_name"),
800 : tmp);
801 33843 : data_blob_free(&tmp);
802 : }
803 :
804 : /*******************************************************************
805 : Return the IP addr of the remote end of a socket as a string.
806 : ******************************************************************/
807 :
808 0 : const char *get_peer_addr(int fd, char *addr, size_t addr_len)
809 : {
810 0 : return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
811 : }
812 :
813 33843 : int get_remote_hostname(const struct tsocket_address *remote_address,
814 : char **name,
815 : TALLOC_CTX *mem_ctx)
816 : {
817 894 : char name_buf[MAX_DNS_NAME_LENGTH];
818 894 : char tmp_name[MAX_DNS_NAME_LENGTH];
819 894 : struct name_addr_pair nc;
820 894 : struct sockaddr_storage ss;
821 894 : ssize_t len;
822 894 : int rc;
823 :
824 33843 : if (!lp_hostname_lookups()) {
825 33843 : nc.name = tsocket_address_inet_addr_string(remote_address,
826 : mem_ctx);
827 33843 : if (nc.name == NULL) {
828 0 : return -1;
829 : }
830 :
831 33843 : len = tsocket_address_bsd_sockaddr(remote_address,
832 : (struct sockaddr *) &nc.ss,
833 : sizeof(struct sockaddr_storage));
834 33843 : if (len < 0) {
835 0 : return -1;
836 : }
837 :
838 33843 : store_nc(&nc);
839 33843 : lookup_nc(&nc);
840 :
841 33843 : if (nc.name == NULL) {
842 1174 : *name = talloc_strdup(mem_ctx, "UNKNOWN");
843 : } else {
844 32669 : *name = talloc_strdup(mem_ctx, nc.name);
845 : }
846 33843 : return 0;
847 : }
848 :
849 0 : lookup_nc(&nc);
850 :
851 0 : ZERO_STRUCT(ss);
852 :
853 0 : len = tsocket_address_bsd_sockaddr(remote_address,
854 : (struct sockaddr *) &ss,
855 : sizeof(struct sockaddr_storage));
856 0 : if (len < 0) {
857 0 : return -1;
858 : }
859 :
860 : /* it might be the same as the last one - save some DNS work */
861 0 : if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
862 0 : if (nc.name == NULL) {
863 0 : *name = talloc_strdup(mem_ctx, "UNKNOWN");
864 : } else {
865 0 : *name = talloc_strdup(mem_ctx, nc.name);
866 : }
867 0 : return 0;
868 : }
869 :
870 : /* Look up the remote host name. */
871 0 : rc = sys_getnameinfo((struct sockaddr *) &ss,
872 : len,
873 : name_buf,
874 : sizeof(name_buf),
875 : NULL,
876 : 0,
877 : 0);
878 0 : if (rc < 0) {
879 0 : char *p;
880 :
881 0 : p = tsocket_address_inet_addr_string(remote_address, mem_ctx);
882 0 : if (p == NULL) {
883 0 : return -1;
884 : }
885 :
886 0 : DEBUG(1,("getnameinfo failed for %s with error %s\n",
887 : p,
888 : gai_strerror(rc)));
889 0 : strlcpy(name_buf, p, sizeof(name_buf));
890 :
891 0 : TALLOC_FREE(p);
892 : } else {
893 0 : if (!matchname(name_buf, (struct sockaddr *)&ss, len)) {
894 0 : DEBUG(0,("matchname failed on %s\n", name_buf));
895 0 : strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
896 : }
897 : }
898 :
899 0 : strlcpy(tmp_name, name_buf, sizeof(tmp_name));
900 0 : alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf));
901 0 : if (strstr(name_buf,"..")) {
902 0 : strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
903 : }
904 :
905 0 : nc.name = name_buf;
906 0 : nc.ss = ss;
907 :
908 0 : store_nc(&nc);
909 0 : lookup_nc(&nc);
910 :
911 0 : if (nc.name == NULL) {
912 0 : *name = talloc_strdup(mem_ctx, "UNKNOWN");
913 : } else {
914 0 : *name = talloc_strdup(mem_ctx, nc.name);
915 : }
916 :
917 0 : return 0;
918 : }
919 :
920 : /*******************************************************************
921 : Create protected unix domain socket.
922 :
923 : Some unixes cannot set permissions on a ux-dom-sock, so we
924 : have to make sure that the directory contains the protection
925 : permissions instead.
926 : ******************************************************************/
927 :
928 1816 : int create_pipe_sock(const char *socket_dir,
929 : const char *socket_name,
930 : mode_t dir_perms)
931 : {
932 : #ifdef HAVE_UNIXSOCKET
933 2 : struct sockaddr_un sunaddr;
934 2 : bool ok;
935 1816 : int sock = -1;
936 2 : mode_t old_umask;
937 1816 : char *path = NULL;
938 2 : size_t path_len;
939 :
940 1816 : old_umask = umask(0);
941 :
942 1816 : ok = directory_create_or_exist_strict(socket_dir,
943 : sec_initial_uid(),
944 : dir_perms);
945 1816 : if (!ok) {
946 0 : goto out_close;
947 : }
948 :
949 : /* Create the socket file */
950 1816 : sock = socket(AF_UNIX, SOCK_STREAM, 0);
951 :
952 1816 : if (sock == -1) {
953 0 : DEBUG(0, ("create_pipe_sock: socket error %s\n",
954 : strerror(errno) ));
955 0 : goto out_close;
956 : }
957 :
958 1816 : if (asprintf(&path, "%s/%s", socket_dir, socket_name) == -1) {
959 0 : goto out_close;
960 : }
961 :
962 1816 : unlink(path);
963 1816 : memset(&sunaddr, 0, sizeof(sunaddr));
964 1816 : sunaddr.sun_family = AF_UNIX;
965 :
966 1816 : path_len = strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path));
967 1816 : if (path_len > sizeof(sunaddr.sun_path)) {
968 0 : DBG_ERR("Refusing to attempt to create pipe socket "
969 : "%s. Path is longer than permitted for a "
970 : "unix domain socket. It would truncate to "
971 : "%s\n",
972 : path,
973 : sunaddr.sun_path);
974 0 : goto out_close;
975 : }
976 :
977 1816 : if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
978 0 : DEBUG(0, ("bind failed on pipe socket %s: %s\n", path,
979 : strerror(errno)));
980 0 : goto out_close;
981 : }
982 :
983 1816 : SAFE_FREE(path);
984 :
985 1816 : umask(old_umask);
986 1816 : return sock;
987 :
988 0 : out_close:
989 0 : SAFE_FREE(path);
990 0 : if (sock != -1)
991 0 : close(sock);
992 :
993 0 : umask(old_umask);
994 0 : return -1;
995 :
996 : #else
997 : DEBUG(0, ("create_pipe_sock: No Unix sockets on this system\n"));
998 : return -1;
999 : #endif /* HAVE_UNIXSOCKET */
1000 : }
1001 :
1002 : /****************************************************************************
1003 : Get my own canonical name, including domain.
1004 : ****************************************************************************/
1005 :
1006 120100 : const char *get_mydnsfullname(void)
1007 : {
1008 120100 : struct addrinfo *res = NULL;
1009 0 : char my_hostname[HOST_NAME_MAX];
1010 0 : bool ret;
1011 0 : DATA_BLOB tmp;
1012 :
1013 120100 : if (memcache_lookup(NULL, SINGLETON_CACHE,
1014 : data_blob_string_const_null("get_mydnsfullname"),
1015 : &tmp)) {
1016 96350 : SMB_ASSERT(tmp.length > 0);
1017 96350 : return (const char *)tmp.data;
1018 : }
1019 :
1020 : /* get my host name */
1021 23750 : if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
1022 0 : DEBUG(0,("get_mydnsfullname: gethostname failed\n"));
1023 0 : return NULL;
1024 : }
1025 :
1026 : /* Ensure null termination. */
1027 23750 : my_hostname[sizeof(my_hostname)-1] = '\0';
1028 :
1029 23750 : ret = interpret_string_addr_internal(&res,
1030 : my_hostname,
1031 : AI_ADDRCONFIG|AI_CANONNAME);
1032 :
1033 23750 : if (!ret || res == NULL) {
1034 0 : DEBUG(3,("get_mydnsfullname: getaddrinfo failed for "
1035 : "name %s [%s]\n",
1036 : my_hostname,
1037 : gai_strerror(ret) ));
1038 0 : return NULL;
1039 : }
1040 :
1041 : /*
1042 : * Make sure that getaddrinfo() returns the "correct" host name.
1043 : */
1044 :
1045 23750 : if (res->ai_canonname == NULL) {
1046 0 : DEBUG(3,("get_mydnsfullname: failed to get "
1047 : "canonical name for %s\n",
1048 : my_hostname));
1049 0 : freeaddrinfo(res);
1050 0 : return NULL;
1051 : }
1052 :
1053 : /* This copies the data, so we must do a lookup
1054 : * afterwards to find the value to return.
1055 : */
1056 :
1057 23750 : memcache_add(NULL, SINGLETON_CACHE,
1058 : data_blob_string_const_null("get_mydnsfullname"),
1059 23750 : data_blob_string_const_null(res->ai_canonname));
1060 :
1061 23750 : if (!memcache_lookup(NULL, SINGLETON_CACHE,
1062 : data_blob_string_const_null("get_mydnsfullname"),
1063 : &tmp)) {
1064 2392 : tmp = data_blob_talloc(talloc_tos(), res->ai_canonname,
1065 : strlen(res->ai_canonname) + 1);
1066 : }
1067 :
1068 23750 : freeaddrinfo(res);
1069 :
1070 23750 : return (const char *)tmp.data;
1071 : }
1072 :
1073 : /************************************************************
1074 : Is this my ip address ?
1075 : ************************************************************/
1076 :
1077 3037 : static bool is_my_ipaddr(const char *ipaddr_str)
1078 : {
1079 0 : struct sockaddr_storage ss;
1080 0 : struct iface_struct *nics;
1081 0 : int i, n;
1082 :
1083 3037 : if (!interpret_string_addr(&ss, ipaddr_str, AI_NUMERICHOST)) {
1084 0 : return false;
1085 : }
1086 :
1087 3037 : if (is_zero_addr(&ss)) {
1088 0 : return false;
1089 : }
1090 :
1091 3373 : if (ismyaddr((struct sockaddr *)&ss) ||
1092 336 : is_loopback_addr((struct sockaddr *)&ss)) {
1093 2701 : return true;
1094 : }
1095 :
1096 336 : n = get_interfaces(talloc_tos(), &nics);
1097 1680 : for (i=0; i<n; i++) {
1098 1344 : if (sockaddr_equal((struct sockaddr *)&nics[i].ip, (struct sockaddr *)&ss)) {
1099 0 : TALLOC_FREE(nics);
1100 0 : return true;
1101 : }
1102 : }
1103 336 : TALLOC_FREE(nics);
1104 336 : return false;
1105 : }
1106 :
1107 : /************************************************************
1108 : Is this my name ?
1109 : ************************************************************/
1110 :
1111 16061 : bool is_myname_or_ipaddr(const char *s)
1112 : {
1113 16061 : TALLOC_CTX *ctx = talloc_tos();
1114 16061 : char *name = NULL;
1115 0 : const char *dnsname;
1116 16061 : char *servername = NULL;
1117 :
1118 16061 : if (!s) {
1119 0 : return false;
1120 : }
1121 :
1122 : /* Sanitize the string from '\\name' */
1123 16061 : name = talloc_strdup(ctx, s);
1124 16061 : if (!name) {
1125 0 : return false;
1126 : }
1127 :
1128 16061 : servername = strrchr_m(name, '\\' );
1129 16061 : if (!servername) {
1130 16061 : servername = name;
1131 : } else {
1132 0 : servername++;
1133 : }
1134 :
1135 : /* Optimize for the common case */
1136 16061 : if (strequal(servername, lp_netbios_name())) {
1137 13121 : return true;
1138 : }
1139 :
1140 : /* Check for an alias */
1141 2940 : if (is_myname(servername)) {
1142 4 : return true;
1143 : }
1144 :
1145 : /* Check for loopback */
1146 5872 : if (strequal(servername, "127.0.0.1") ||
1147 2936 : strequal(servername, "::1")) {
1148 0 : return true;
1149 : }
1150 :
1151 2936 : if (strequal(servername, "localhost")) {
1152 0 : return true;
1153 : }
1154 :
1155 : /* Maybe it's my dns name */
1156 2936 : dnsname = get_mydnsfullname();
1157 2936 : if (dnsname && strequal(servername, dnsname)) {
1158 55 : return true;
1159 : }
1160 :
1161 : /* Maybe its an IP address? */
1162 2881 : if (is_ipaddress(servername)) {
1163 2701 : return is_my_ipaddr(servername);
1164 : }
1165 :
1166 : /* Handle possible CNAME records - convert to an IP addr. list. */
1167 : {
1168 : /* Use DNS to resolve the name, check all addresses. */
1169 180 : struct addrinfo *p = NULL;
1170 180 : struct addrinfo *res = NULL;
1171 :
1172 180 : if (!interpret_string_addr_internal(&res,
1173 : servername,
1174 : AI_ADDRCONFIG)) {
1175 12 : return false;
1176 : }
1177 :
1178 504 : for (p = res; p; p = p->ai_next) {
1179 0 : char addr[INET6_ADDRSTRLEN];
1180 0 : struct sockaddr_storage ss;
1181 :
1182 336 : ZERO_STRUCT(ss);
1183 336 : memcpy(&ss, p->ai_addr, p->ai_addrlen);
1184 336 : print_sockaddr(addr,
1185 : sizeof(addr),
1186 : &ss);
1187 336 : if (is_my_ipaddr(addr)) {
1188 0 : freeaddrinfo(res);
1189 0 : return true;
1190 : }
1191 : }
1192 168 : freeaddrinfo(res);
1193 : }
1194 :
1195 : /* No match */
1196 168 : return false;
1197 : }
1198 :
1199 0 : int poll_one_fd(int fd, int events, int timeout, int *revents)
1200 : {
1201 0 : struct pollfd pfd;
1202 0 : int ret;
1203 :
1204 0 : pfd.fd = fd;
1205 0 : pfd.events = events;
1206 :
1207 0 : ret = poll(&pfd, 1, timeout);
1208 :
1209 : /*
1210 : * Assign whatever poll did, even in the ret<=0 case.
1211 : */
1212 0 : *revents = pfd.revents;
1213 :
1214 0 : return ret;
1215 : }
1216 :
1217 0 : int poll_intr_one_fd(int fd, int events, int timeout, int *revents)
1218 : {
1219 0 : struct pollfd pfd;
1220 0 : int ret;
1221 :
1222 0 : pfd.fd = fd;
1223 0 : pfd.events = events;
1224 :
1225 0 : ret = sys_poll_intr(&pfd, 1, timeout);
1226 0 : if (ret <= 0) {
1227 0 : *revents = 0;
1228 0 : return ret;
1229 : }
1230 0 : *revents = pfd.revents;
1231 0 : return 1;
1232 : }
|