s3-lib: Fix %G substitution for domain users in smbd
[gd/samba-autobuild/.git] / source3 / lib / util_sock.c
index 5b01d11bc6271b87e4d0a0dc993cec72eddf0813..a35ae97eba28faa30fc31bc7d1182e6a0601f021 100644 (file)
 #include "lib/socket/interfaces.h"
 #include "../lib/util/tevent_unix.h"
 #include "../lib/util/tevent_ntstatus.h"
-
-const char *client_name(int fd)
-{
-       return get_peer_name(fd,false);
-}
+#include "../lib/tsocket/tsocket.h"
 
 const char *client_addr(int fd, char *addr, size_t addrlen)
 {
@@ -46,26 +42,6 @@ int client_socket_port(int fd)
 }
 #endif
 
-/****************************************************************************
- Accessor functions to make thread-safe code easier later...
-****************************************************************************/
-
-void set_smb_read_error(enum smb_read_errors *pre,
-                       enum smb_read_errors newerr)
-{
-       if (pre) {
-               *pre = newerr;
-       }
-}
-
-void cond_set_smb_read_error(enum smb_read_errors *pre,
-                       enum smb_read_errors newerr)
-{
-       if (pre && *pre == SMB_READ_OK) {
-               *pre = newerr;
-       }
-}
-
 /****************************************************************************
  Determine if a file descriptor is in fact a socket.
 ****************************************************************************/
@@ -257,7 +233,7 @@ ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
         * discarding elements.
         */
 
-       iov_copy = (struct iovec *)TALLOC_MEMDUP(
+       iov_copy = (struct iovec *)talloc_memdup(
                talloc_tos(), orig_iov, sizeof(struct iovec) * iovcnt);
 
        if (iov_copy == NULL) {
@@ -319,7 +295,7 @@ bool send_keepalive(int client)
 {
        unsigned char buf[4];
 
-       buf[0] = SMBkeepalive;
+       buf[0] = NBSSkeepalive;
        buf[1] = buf[2] = buf[3] = 0;
 
        return(write_data(client,(char *)buf,4) == 4);
@@ -349,7 +325,7 @@ NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
        *len = smb_len(inbuf);
        msg_type = CVAL(inbuf,0);
 
-       if (msg_type == SMBkeepalive) {
+       if (msg_type == NBSSkeepalive) {
                DEBUG(5,("Got keepalive packet\n"));
        }
 
@@ -501,8 +477,9 @@ int open_socket_in(int type,
 
        /* now we've got a socket - we need to bind it */
        if (bind(res, (struct sockaddr *)&sock, slen) == -1 ) {
-               if( DEBUGLVL(dlevel) && (port == SMB_PORT1 ||
-                               port == SMB_PORT2 || port == NMB_PORT) ) {
+               if( DEBUGLVL(dlevel) && (port == NMB_PORT ||
+                                        port == NBT_SMB_PORT ||
+                                        port == TCP_SMB_PORT) ) {
                        char addr[INET6_ADDRSTRLEN];
                        print_sockaddr(addr, sizeof(addr),
                                        &sock);
@@ -520,7 +497,7 @@ int open_socket_in(int type,
 
 struct open_socket_out_state {
        int fd;
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct sockaddr_storage ss;
        socklen_t salen;
        uint16_t port;
@@ -542,7 +519,7 @@ static int open_socket_out_state_destructor(struct open_socket_out_state *s)
 **************************************************************************/
 
 struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
-                                       struct event_context *ev,
+                                       struct tevent_context *ev,
                                        const struct sockaddr_storage *pss,
                                        uint16_t port,
                                        int timeout)
@@ -604,7 +581,7 @@ struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
 
        subreq = async_connect_send(state, state->ev, state->fd,
                                    (struct sockaddr *)&state->ss,
-                                   state->salen);
+                                   state->salen, NULL, NULL, NULL);
        if ((subreq == NULL)
            || !tevent_req_set_endtime(
                    subreq, state->ev,
@@ -656,7 +633,7 @@ static void open_socket_out_connected(struct tevent_req *subreq)
 
                subreq = async_connect_send(state, state->ev, state->fd,
                                            (struct sockaddr *)&state->ss,
-                                           state->salen);
+                                           state->salen, NULL, NULL, NULL);
                if (tevent_req_nomem(subreq, req)) {
                        return;
                }
@@ -709,11 +686,11 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
                         int timeout, int *pfd)
 {
        TALLOC_CTX *frame = talloc_stackframe();
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-       ev = event_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
@@ -733,7 +710,7 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
 }
 
 struct open_socket_out_defer_state {
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct sockaddr_storage ss;
        uint16_t port;
        int timeout;
@@ -744,7 +721,7 @@ static void open_socket_out_defer_waited(struct tevent_req *subreq);
 static void open_socket_out_defer_connected(struct tevent_req *subreq);
 
 struct tevent_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
-                                             struct event_context *ev,
+                                             struct tevent_context *ev,
                                              struct timeval wait_time,
                                              const struct sockaddr_storage *pss,
                                              uint16_t port,
@@ -838,6 +815,7 @@ int open_udp_socket(const char *host, int port)
 {
        struct sockaddr_storage ss;
        int res;
+       socklen_t salen;
 
        if (!interpret_string_addr(&ss, host, 0)) {
                DEBUG(10,("open_udp_socket: can't resolve name %s\n",
@@ -860,15 +838,21 @@ int open_udp_socket(const char *host, int port)
                        setup_linklocal_scope_id(
                                (struct sockaddr *)&ss);
                }
-       }
+               salen = sizeof(struct sockaddr_in6);
+       } else 
 #endif
-        if (ss.ss_family == AF_INET) {
-                struct sockaddr_in *psa;
-                psa = (struct sockaddr_in *)&ss;
-                psa->sin_port = htons(port);
-        }
+       if (ss.ss_family == AF_INET) {
+               struct sockaddr_in *psa;
+               psa = (struct sockaddr_in *)&ss;
+               psa->sin_port = htons(port);
+           salen = sizeof(struct sockaddr_in);
+       } else {
+               DEBUG(1, ("unknown socket family %d", ss.ss_family));
+               close(res);
+               return -1;
+       }
 
-       if (sys_connect(res,(struct sockaddr *)&ss)) {
+       if (connect(res, (struct sockaddr *)&ss, salen)) {
                close(res);
                return -1;
        }
@@ -1039,67 +1023,97 @@ static void store_nc(const struct name_addr_pair *nc)
 }
 
 /*******************************************************************
- Return the DNS name of the remote end of a socket.
-******************************************************************/
+ Return the IP addr of the remote end of a socket as a string.
+ ******************************************************************/
 
-const char *get_peer_name(int fd, bool force_lookup)
+const char *get_peer_addr(int fd, char *addr, size_t addr_len)
+{
+       return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
+}
+
+int get_remote_hostname(const struct tsocket_address *remote_address,
+                       char **name,
+                       TALLOC_CTX *mem_ctx)
 {
-       struct name_addr_pair nc;
-       char addr_buf[INET6_ADDRSTRLEN];
-       struct sockaddr_storage ss;
-       socklen_t length = sizeof(ss);
-       const char *p;
-       int ret;
        char name_buf[MAX_DNS_NAME_LENGTH];
        char tmp_name[MAX_DNS_NAME_LENGTH];
+       struct name_addr_pair nc;
+       struct sockaddr_storage ss;
+       ssize_t len;
+       int rc;
+
+       if (!lp_hostname_lookups()) {
+               nc.name = tsocket_address_inet_addr_string(remote_address,
+                                                          mem_ctx);
+               if (nc.name == NULL) {
+                       return -1;
+               }
+
+               len = tsocket_address_bsd_sockaddr(remote_address,
+                                                  (struct sockaddr *) &nc.ss,
+                                                  sizeof(struct sockaddr_storage));
+               if (len < 0) {
+                       return -1;
+               }
 
-       /* reverse lookups can be *very* expensive, and in many
-          situations won't work because many networks don't link dhcp
-          with dns. To avoid the delay we avoid the lookup if
-          possible */
-       if (!lp_hostname_lookups() && (force_lookup == false)) {
-               length = sizeof(nc.ss);
-               nc.name = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf),
-                       (struct sockaddr *)&nc.ss, &length);
                store_nc(&nc);
                lookup_nc(&nc);
-               return nc.name ? nc.name : "UNKNOWN";
+
+               if (nc.name == NULL) {
+                       *name = talloc_strdup(mem_ctx, "UNKNOWN");
+               } else {
+                       *name = talloc_strdup(mem_ctx, nc.name);
+               }
+               return 0;
        }
 
        lookup_nc(&nc);
 
-       memset(&ss, '\0', sizeof(ss));
-       p = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf), (struct sockaddr *)&ss, &length);
+       ZERO_STRUCT(ss);
 
-       /* it might be the same as the last one - save some DNS work */
-       if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
-               return nc.name ? nc.name : "UNKNOWN";
+       len = tsocket_address_bsd_sockaddr(remote_address,
+                                          (struct sockaddr *) &ss,
+                                          sizeof(struct sockaddr_storage));
+       if (len < 0) {
+               return -1;
        }
 
-       /* Not the same. We need to lookup. */
-       if (fd == -1) {
-               return "UNKNOWN";
+       /* it might be the same as the last one - save some DNS work */
+       if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
+               if (nc.name == NULL) {
+                       *name = talloc_strdup(mem_ctx, "UNKNOWN");
+               } else {
+                       *name = talloc_strdup(mem_ctx, nc.name);
+               }
+               return 0;
        }
 
        /* Look up the remote host name. */
-       ret = sys_getnameinfo((struct sockaddr *)&ss,
-                       length,
-                       name_buf,
-                       sizeof(name_buf),
-                       NULL,
-                       0,
-                       0);
-
-       if (ret) {
-               DEBUG(1,("get_peer_name: getnameinfo failed "
-                       "for %s with error %s\n",
-                       p,
-                       gai_strerror(ret)));
+       rc = sys_getnameinfo((struct sockaddr *) &ss,
+                            len,
+                            name_buf,
+                            sizeof(name_buf),
+                            NULL,
+                            0,
+                            0);
+       if (rc < 0) {
+               char *p;
+
+               p = tsocket_address_inet_addr_string(remote_address, mem_ctx);
+               if (p == NULL) {
+                       return -1;
+               }
+
+               DEBUG(1,("getnameinfo failed for %s with error %s\n",
+                        p,
+                        gai_strerror(rc)));
                strlcpy(name_buf, p, sizeof(name_buf));
+
+               TALLOC_FREE(p);
        } else {
-               if (!matchname(name_buf, (struct sockaddr *)&ss, length)) {
-                       DEBUG(0,("Matchname failed on %s %s\n",name_buf,p));
-                       strlcpy(name_buf,"UNKNOWN",sizeof(name_buf));
+               if (!matchname(name_buf, (struct sockaddr *)&ss, len)) {
+                       DEBUG(0,("matchname failed on %s\n", name_buf));
+                       strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
                }
        }
 
@@ -1114,16 +1128,14 @@ const char *get_peer_name(int fd, bool force_lookup)
 
        store_nc(&nc);
        lookup_nc(&nc);
-       return nc.name ? nc.name : "UNKNOWN";
-}
 
-/*******************************************************************
- Return the IP addr of the remote end of a socket as a string.
- ******************************************************************/
+       if (nc.name == NULL) {
+               *name = talloc_strdup(mem_ctx, "UNKOWN");
+       } else {
+               *name = talloc_strdup(mem_ctx, nc.name);
+       }
 
-const char *get_peer_addr(int fd, char *addr, size_t addr_len)
-{
-       return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
+       return 0;
 }
 
 /*******************************************************************
@@ -1140,53 +1152,21 @@ int create_pipe_sock(const char *socket_dir,
 {
 #ifdef HAVE_UNIXSOCKET
        struct sockaddr_un sunaddr;
-       struct stat st;
-       int sock;
+       bool ok;
+       int sock = -1;
        mode_t old_umask;
        char *path = NULL;
 
        old_umask = umask(0);
 
-       /* Create the socket directory or reuse the existing one */
-
-       if (lstat(socket_dir, &st) == -1) {
-               if (errno == ENOENT) {
-                       /* Create directory */
-                       if (mkdir(socket_dir, dir_perms) == -1) {
-                               DEBUG(0, ("error creating socket directory "
-                                       "%s: %s\n", socket_dir,
-                                       strerror(errno)));
-                               goto out_umask;
-                       }
-               } else {
-                       DEBUG(0, ("lstat failed on socket directory %s: %s\n",
-                               socket_dir, strerror(errno)));
-                       goto out_umask;
-               }
-       } else {
-               /* Check ownership and permission on existing directory */
-               if (!S_ISDIR(st.st_mode)) {
-                       DEBUG(0, ("socket directory '%s' isn't a directory\n",
-                               socket_dir));
-                       goto out_umask;
-               }
-               if (st.st_uid != sec_initial_uid()) {
-                       DEBUG(0, ("invalid ownership on directory "
-                                 "'%s'\n", socket_dir));
-                       umask(old_umask);
-                       goto out_umask;
-               }
-               if ((st.st_mode & 0777) != dir_perms) {
-                       DEBUG(0, ("invalid permissions on directory "
-                                 "'%s': has 0%o should be 0%o\n", socket_dir,
-                                 (st.st_mode & 0777), dir_perms));
-                       umask(old_umask);
-                       goto out_umask;
-               }
+       ok = directory_create_or_exist_strict(socket_dir,
+                                             sec_initial_uid(),
+                                             dir_perms);
+       if (!ok) {
+               goto out_close;
        }
 
        /* Create the socket file */
-
        sock = socket(AF_UNIX, SOCK_STREAM, 0);
 
        if (sock == -1) {
@@ -1210,12 +1190,6 @@ int create_pipe_sock(const char *socket_dir,
                goto out_close;
        }
 
-       if (listen(sock, 5) == -1) {
-               DEBUG(0, ("listen failed on pipe socket %s: %s\n", path,
-                       strerror(errno)));
-               goto out_close;
-       }
-
        SAFE_FREE(path);
 
        umask(old_umask);
@@ -1226,7 +1200,6 @@ out_close:
        if (sock != -1)
                close(sock);
 
-out_umask:
        umask(old_umask);
        return -1;
 
@@ -1370,7 +1343,7 @@ bool is_myname_or_ipaddr(const char *s)
        }
 
        /* Optimize for the common case */
-       if (strequal(servername, global_myname())) {
+       if (strequal(servername, lp_netbios_name())) {
                return true;
        }
 
@@ -1521,7 +1494,7 @@ int poll_one_fd(int fd, int events, int timeout, int *revents)
        int ret;
        int saved_errno;
 
-       fds = TALLOC_ZERO_ARRAY(talloc_tos(), struct pollfd, 2);
+       fds = talloc_zero_array(talloc_tos(), struct pollfd, 1);
        if (fds == NULL) {
                errno = ENOMEM;
                return -1;
@@ -1529,7 +1502,7 @@ int poll_one_fd(int fd, int events, int timeout, int *revents)
        fds[0].fd = fd;
        fds[0].events = events;
 
-       ret = sys_poll(fds, 1, timeout);
+       ret = poll(fds, 1, timeout);
 
        /*
         * Assign whatever poll did, even in the ret<=0 case.