8 #include <sys/socket.h>
13 #include <sys/types.h>
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
18 #define MAX(a,b) ((a)>(b)?(a):(b))
20 #define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
21 #define NTLMSSP_NEGOTIATE_OEM 0x00000002
22 #define NTLMSSP_REQUEST_TARGET 0x00000004
23 #define NTLMSSP_NEGOTIATE_SIGN 0x00000010 /* Message integrity */
24 #define NTLMSSP_NEGOTIATE_SEAL 0x00000020 /* Message confidentiality */
25 #define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE 0x00000040
26 #define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
27 #define NTLMSSP_NEGOTIATE_NETWARE 0x00000100
28 #define NTLMSSP_NEGOTIATE_NTLM 0x00000200
29 #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000
30 #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
31 #define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL 0x00004000
32 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
33 #define NTLMSSP_NEGOTIATE_128 0x20000000 /* 128-bit encryption */
34 #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
35 #define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
37 static void replace_str(char *buf, int n)
40 p = memmem(buf, n, "NTLMSSP", 7);
44 x = *(unsigned *)(p+12);
45 printf("flags were 0x%08x\n", x);
49 printf("replacing challenge flags with 0x%08x\n", x);
50 *(unsigned *)(p+12) = x;
54 /* open a socket to a tcp remote host with the specified port */
55 static int open_socket_out(const char *host, int port)
57 struct sockaddr_in sock_out;
62 res = socket(PF_INET, SOCK_STREAM, 0);
67 if (inet_pton(AF_INET, host, &addr) > 0) {
68 memcpy(&sock_out.sin_addr, &addr, sizeof(addr));
70 hp = gethostbyname(host);
72 fprintf(stderr,"unknown host %s\n", host);
75 memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
78 sock_out.sin_port = htons(port);
79 sock_out.sin_family = PF_INET;
81 if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)) != 0) {
83 fprintf(stderr,"failed to connect to %s (%s)\n",
84 host, strerror(errno));
93 open a socket of the specified type, port and address for incoming data
95 int open_socket_in(int port)
97 struct sockaddr_in sock;
101 memset(&sock,0,sizeof(sock));
103 #ifdef HAVE_SOCK_SIN_LEN
104 sock.sin_len = sizeof(sock);
106 sock.sin_port = htons(port);
107 sock.sin_family = AF_INET;
109 res = socket(AF_INET, SOCK_STREAM, 0);
111 fprintf(stderr, "socket failed\n"); return -1;
115 setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
117 if (bind(res, (struct sockaddr *)&sock, sizeof(sock)) < 0) {
124 /* write to a file descriptor, making sure we get all the data out or
126 static void write_all(int fd, unsigned char *s, size_t n)
139 static void main_loop(int sock1, int sock2)
141 unsigned char buf[1024];
145 char *fname1, *fname2;
146 asprintf(&fname1, "sockspy-in.%d", i);
147 asprintf(&fname2, "sockspy-out.%d", i);
148 log1 = open(fname1, O_WRONLY|O_CREAT|O_EXCL, 0644);
149 log2 = open(fname2, O_WRONLY|O_CREAT|O_EXCL, 0644);
153 } while (i<1000 && (log1 == -1 || log2 == -1));
155 if (log1 == -1 || log2 == -1) {
156 fprintf(stderr,"Failed to open log files\n");
168 ret = select(MAX(sock1, sock2)+1, &fds, NULL, NULL, NULL);
169 if (ret == -1 && errno == EINTR) continue;
172 if (FD_ISSET(sock1, &fds)) {
173 int n = read(sock1, buf, sizeof(buf));
178 write_all(sock2, buf, n);
179 write_all(log1, buf, n);
182 if (FD_ISSET(sock2, &fds)) {
183 int n = read(sock2, buf, sizeof(buf));
188 write_all(sock1, buf, n);
189 write_all(log2, buf, n);
194 int main(int argc, char *argv[])
196 int listen_port, dest_port;
201 struct sockaddr addr;
202 int in_addrlen = sizeof(addr);
205 printf("Usage: sockspy <inport> <host> <port>\n");
209 listen_port = atoi(argv[1]);
211 dest_port = atoi(argv[3]);
213 listen_fd = open_socket_in(listen_port);
215 if (listen_fd == -1) {
216 fprintf(stderr,"listen on port %d failed - %s\n",
217 listen_port, strerror(errno));
221 if (listen(listen_fd, 5) == -1) {
222 fprintf(stderr,"listen failed\n");
226 sock_in = accept(listen_fd,&addr,&in_addrlen);
229 fprintf(stderr,"accept on port %d failed - %s\n",
230 listen_port, strerror(errno));
236 sock_out = open_socket_out(host, dest_port);
237 if (sock_out == -1) {
241 main_loop(sock_in, sock_out);