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