/*
- 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)
{
{
int msg_type = CVAL(buf,0);
int type = CVAL(buf,smb_com);
- pstring name1,name2;
+ fstring name1,name2;
unsigned x;
if (msg_type) {
/* 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;
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;
}
+/****************************************************************************
+ 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);
}
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);
}
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);
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);
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;
}