Added prefer_ipv4 bool parameter to resolve_name().
[ira/wip.git] / source3 / utils / smbfilter.c
index 833221b10bf4fc76fa81a781299014584f02a1b0..83de0c4c37482662075a2007074bde51fdbee893 100644 (file)
@@ -1,12 +1,11 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 2
+   Unix SMB/CIFS implementation.
    SMB filter/socket plugin
    Copyright (C) Andrew Tridgell 1999
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "smb.h"
 
 #define SECURITY_MASK 0
 #define SECURITY_SET  0
 
 /* this forces non-unicode */
-#define CAPABILITY_MASK (CAP_NT_SMBS | CAP_RPC_REMOTE_APIS)
+#define CAPABILITY_MASK 0
 #define CAPABILITY_SET  0
 
 /* and non-unicode for the client too */
 static char *netbiosname;
 static char packet[BUFFER_SIZE];
 
-extern int DEBUGLEVEL;
+static void save_file(const char *fname, void *ppacket, size_t length)
+{
+       int fd;
+       fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+       if (fd == -1) {
+               perror(fname);
+               return;
+       }
+       if (write(fd, ppacket, length) != length) {
+               fprintf(stderr,"Failed to write %s\n", fname);
+               return;
+       }
+       close(fd);
+       printf("Wrote %ld bytes to %s\n", (unsigned long)length, fname);
+}
 
 static void filter_reply(char *buf)
 {
@@ -67,7 +78,7 @@ static void filter_request(char *buf)
 {
        int msg_type = CVAL(buf,0);
        int type = CVAL(buf,smb_com);
-       pstring name1,name2;
+       fstring name1,name2;
        unsigned x;
 
        if (msg_type) {
@@ -77,11 +88,18 @@ static void filter_request(char *buf)
                        /* session request */
                        name_extract(buf,4,name1);
                        name_extract(buf,4 + name_len(buf + 4),name2);
-                       DEBUG(0,("sesion_request: %s -> %s\n",
-                                name1, name2));
+                       d_printf("sesion_request: %s -> %s\n",
+                                name1, name2);
                        if (netbiosname) {
-                               /* replace the destination netbios name */
-                               name_mangle(netbiosname, buf+4, 0x20);
+                               char *mangled = name_mangle(
+                                       talloc_tos(), netbiosname, 0x20);
+                               if (mangled != NULL) {
+                                       /* replace the destination netbios
+                                        * name */
+                                       memcpy(buf+4, mangled,
+                                              name_len(mangled));
+                                       TALLOC_FREE(mangled);
+                               }
                        }
                }
                return;
@@ -92,6 +110,10 @@ static void filter_request(char *buf)
        case SMBsesssetupX:
                /* force the client capabilities */
                x = IVAL(buf,smb_vwv11);
+               d_printf("SMBsesssetupX cap=0x%08x\n", x);
+               d_printf("pwlen=%d/%d\n", SVAL(buf, smb_vwv7), SVAL(buf, smb_vwv8));
+               system("mv sessionsetup.dat sessionsetup1.dat");
+               save_file("sessionsetup.dat", smb_buf(buf), SVAL(buf, smb_vwv7));
                x = (x | CLI_CAPABILITY_SET) & ~CLI_CAPABILITY_MASK;
                SIVAL(buf, smb_vwv11, x);
                break;
@@ -99,16 +121,47 @@ static void filter_request(char *buf)
 
 }
 
+/****************************************************************************
+ Send an smb to a fd.
+****************************************************************************/
 
-static void filter_child(int c, struct in_addr dest_ip)
+static bool send_smb(int fd, char *buffer)
 {
-       int s;
+       size_t len;
+       size_t nwritten=0;
+       ssize_t ret;
+
+        len = smb_len(buffer) + 4;
+
+       while (nwritten < len) {
+               ret = write_data(fd,buffer+nwritten,len - nwritten);
+               if (ret <= 0) {
+                       DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+                               (int)len,(int)ret, strerror(errno) ));
+                       return false;
+               }
+               nwritten += ret;
+       }
+
+       return true;
+}
+
+static void filter_child(int c, struct sockaddr_storage *dest_ss)
+{
+       NTSTATUS status;
+       int s = -1;
 
        /* we have a connection from a new client, now connect to the server */
-       s = open_socket_out(SOCK_STREAM, &dest_ip, 139, LONG_CONNECT_TIMEOUT);
+       status = open_socket_out(dest_ss, 445, LONG_CONNECT_TIMEOUT, &s);
 
        if (s == -1) {
-               DEBUG(0,("Unable to connect to %s\n", inet_ntoa(dest_ip)));
+               char addr[INET6_ADDRSTRLEN];
+               if (dest_ss) {
+                       print_sockaddr(addr, sizeof(addr), dest_ss);
+               }
+
+               d_printf("Unable to connect to %s (%s)\n",
+                        dest_ss?addr:"NULL",strerror(errno));
                exit(1);
        }
 
@@ -120,33 +173,39 @@ static void filter_child(int c, struct in_addr dest_ip)
                if (s != -1) FD_SET(s, &fds);
                if (c != -1) FD_SET(c, &fds);
 
-               num = sys_select_intr(MAX(s+1, c+1),&fds,NULL);
+               num = sys_select_intr(MAX(s+1, c+1),&fds,NULL,NULL,NULL);
                if (num <= 0) continue;
                
                if (c != -1 && FD_ISSET(c, &fds)) {
-                       if (!receive_smb(c, packet, 0)) {
-                               DEBUG(0,("client closed connection\n"));
+                       size_t len;
+                       if (!NT_STATUS_IS_OK(receive_smb_raw(
+                                                       c, packet, sizeof(packet),
+                                                       0, 0, &len))) {
+                               d_printf("client closed connection\n");
                                exit(0);
                        }
                        filter_request(packet);
                        if (!send_smb(s, packet)) {
-                               DEBUG(0,("server is dead\n"));
+                               d_printf("server is dead\n");
                                exit(1);
                        }                       
                }
                if (s != -1 && FD_ISSET(s, &fds)) {
-                       if (!receive_smb(s, packet, 0)) {
-                               DEBUG(0,("server closed connection\n"));
+                       size_t len;
+                       if (!NT_STATUS_IS_OK(receive_smb_raw(
+                                                       s, packet, sizeof(packet),
+                                                       0, 0, &len))) {
+                               d_printf("server closed connection\n");
                                exit(0);
                        }
                        filter_reply(packet);
                        if (!send_smb(c, packet)) {
-                               DEBUG(0,("client is dead\n"));
+                               d_printf("client is dead\n");
                                exit(1);
                        }                       
                }
        }
-       DEBUG(0,("Connection closed\n"));
+       d_printf("Connection closed\n");
        exit(0);
 }
 
@@ -154,43 +213,46 @@ static void filter_child(int c, struct in_addr dest_ip)
 static void start_filter(char *desthost)
 {
        int s, c;
-       struct in_addr dest_ip;
+       struct sockaddr_storage dest_ss;
+       struct sockaddr_storage my_ss;
 
        CatchChild();
 
-       /* start listening on port 139 locally */
-       s = open_socket_in(SOCK_STREAM, 139, 0, 0, True);
+       /* start listening on port 445 locally */
+
+       zero_sockaddr(&my_ss);
+       s = open_socket_in(SOCK_STREAM, 445, 0, &my_ss, True);
        
        if (s == -1) {
-               DEBUG(0,("bind failed\n"));
+               d_printf("bind failed\n");
                exit(1);
        }
 
        if (listen(s, 5) == -1) {
-               DEBUG(0,("listen failed\n"));
+               d_printf("listen failed\n");
        }
 
-       if (!resolve_name(desthost, &dest_ip, 0x20)) {
-               DEBUG(0,("Unable to resolve host %s\n", desthost));
+       if (!resolve_name(desthost, &dest_ss, 0x20, false)) {
+               d_printf("Unable to resolve host %s\n", desthost);
                exit(1);
        }
 
        while (1) {
                fd_set fds;
                int num;
-               struct sockaddr addr;
-               int in_addrlen = sizeof(addr);
+               struct sockaddr_storage ss;
+               socklen_t in_addrlen = sizeof(ss);
                
                FD_ZERO(&fds);
                FD_SET(s, &fds);
 
-               num = sys_select_intr(s+1,&fds,NULL);
+               num = sys_select_intr(s+1,&fds,NULL,NULL,NULL);
                if (num > 0) {
-                       c = accept(s, &addr, &in_addrlen);
+                       c = accept(s, (struct sockaddr *)&ss, &in_addrlen);
                        if (c != -1) {
                                if (fork() == 0) {
                                        close(s);
-                                       filter_child(c, dest_ip);
+                                       filter_child(c, &dest_ss);
                                        exit(0);
                                } else {
                                        close(c);
@@ -204,16 +266,15 @@ static void start_filter(char *desthost)
 int main(int argc, char *argv[])
 {
        char *desthost;
-       pstring configfile;
+       const char *configfile;
+       TALLOC_CTX *frame = talloc_stackframe();
 
-       TimeInit();
+       load_case_tables();
 
        setup_logging(argv[0],True);
-  
-       charset_initialise();
 
-       pstrcpy(configfile,CONFIGFILE);
+       configfile = get_dyn_CONFIGFILE();
+
        if (argc < 2) {
                fprintf(stderr,"smbfilter <desthost> <netbiosname>\n");
                exit(1);
@@ -224,10 +285,11 @@ int main(int argc, char *argv[])
                netbiosname = argv[2];
        }
 
-       if (!lp_load(configfile,True,False,False)) {
-               DEBUG(0,("Unable to load config file\n"));
+       if (!lp_load(configfile,True,False,False,True)) {
+               d_printf("Unable to load config file\n");
        }
 
        start_filter(desthost);
+       TALLOC_FREE(frame);
        return 0;
 }