nicer formatting
[tridge/junkcode.git] / sockspy-ntlm2.c
1 #define _GNU_SOURCE
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <time.h>
7 #include <errno.h>
8 #include <ctype.h>
9 #include <sys/socket.h>
10 #include <netdb.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <fcntl.h>
14 #include <sys/types.h>
15 #include <sys/time.h>
16 #include <arpa/inet.h>
17 #include <netinet/in.h>
18
19 #define MAX(a,b) ((a)>(b)?(a):(b))
20
21 #define NTLMSSP_NEGOTIATE_UNICODE          0x00000001
22 #define NTLMSSP_NEGOTIATE_OEM              0x00000002
23 #define NTLMSSP_REQUEST_TARGET             0x00000004
24 #define NTLMSSP_NEGOTIATE_SIGN             0x00000010 /* Message integrity */
25 #define NTLMSSP_NEGOTIATE_SEAL             0x00000020 /* Message confidentiality */
26 #define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE   0x00000040
27 #define NTLMSSP_NEGOTIATE_LM_KEY           0x00000080
28 #define NTLMSSP_NEGOTIATE_NETWARE          0x00000100
29 #define NTLMSSP_NEGOTIATE_NTLM             0x00000200
30 #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED  0x00001000
31 #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
32 #define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL  0x00004000
33 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN      0x00008000
34 #define NTLMSSP_NEGOTIATE_128              0x20000000 /* 128-bit encryption */
35 #define NTLMSSP_NEGOTIATE_KEY_EXCH         0x40000000
36 #define NTLMSSP_NEGOTIATE_NTLM2            0x00080000
37
38 void dump_data(int level, const char *buf1,int len)
39 {
40 #define DEBUGADD(lvl, x) printf x
41 #define MIN(a,b) ((a)<(b)?(a):(b))
42         void print_asc(int level, const uint8_t *buf,int len) {
43                 int i;
44                 for (i=0;i<len;i++)
45                         DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.'));
46         }
47         const uint8_t *buf = (const uint8_t *)buf1;
48         int i=0;
49         if (len<=0) return;
50
51
52         DEBUGADD(level,("[%03X] ",i));
53         for (i=0;i<len;) {
54                 DEBUGADD(level,("%02X ",(int)buf[i]));
55                 i++;
56                 if (i%8 == 0) DEBUGADD(level,(" "));
57                 if (i%16 == 0) {      
58                         print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
59                         print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
60                         if (i<len) DEBUGADD(level,("[%03X] ",i));
61                 }
62         }
63         if (i%16) {
64                 int n;
65                 n = 16 - (i%16);
66                 DEBUGADD(level,(" "));
67                 if (n>8) DEBUGADD(level,(" "));
68                 while (n--) DEBUGADD(level,("   "));
69                 n = MIN(8,i%16);
70                 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
71                 n = (i%16) - n;
72                 if (n>0) print_asc(level,&buf[i-n],n); 
73                 DEBUGADD(level,("\n"));    
74         }       
75 }
76
77 static void replace_str(char *buf, int n)
78 {
79         static int count;
80         printf("Packet %d\n", count++);
81         dump_data(0, buf, n);
82         if (0 && n == 0x40) {
83                 unsigned *x = (buf+0x10);
84                 printf("Changing 0x%x\n", *x);
85                 memcpy(x, "mnbv", 4);
86         }
87 }
88
89 /* open a socket to a tcp remote host with the specified port */
90 static int open_socket_out(const char *host, int port)
91 {
92         struct sockaddr_in sock_out;
93         int res;
94         struct hostent *hp;  
95         struct in_addr addr;
96
97         res = socket(PF_INET, SOCK_STREAM, 0);
98         if (res == -1) {
99                 return -1;
100         }
101
102         if (inet_pton(AF_INET, host, &addr) > 0) {
103                 memcpy(&sock_out.sin_addr, &addr, sizeof(addr));
104         } else {
105                 hp = gethostbyname(host);
106                 if (!hp) {
107                         fprintf(stderr,"unknown host %s\n", host);
108                         return -1;
109                 }
110                 memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
111         }
112
113         sock_out.sin_port = htons(port);
114         sock_out.sin_family = PF_INET;
115
116         if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)) != 0) {
117                 close(res);
118                 fprintf(stderr,"failed to connect to %s (%s)\n", 
119                         host, strerror(errno));
120                 return -1;
121         }
122
123         return res;
124 }
125
126
127 /*
128   open a socket of the specified type, port and address for incoming data
129 */
130 int open_socket_in(int port)
131 {
132         struct sockaddr_in sock;
133         int res;
134         int one=1;
135
136         memset(&sock,0,sizeof(sock));
137
138 #ifdef HAVE_SOCK_SIN_LEN
139         sock.sin_len = sizeof(sock);
140 #endif
141         sock.sin_port = htons(port);
142         sock.sin_family = AF_INET;
143
144         res = socket(AF_INET, SOCK_STREAM, 0);
145         if (res == -1) { 
146                 fprintf(stderr, "socket failed\n"); return -1; 
147                 return -1;
148         }
149
150         setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
151
152         if (bind(res, (struct sockaddr *)&sock, sizeof(sock)) < 0) { 
153                 return(-1); 
154         }
155
156         return res;
157 }
158
159 /* write to a file descriptor, making sure we get all the data out or
160  * die trying */
161 static void write_all(int fd, unsigned char *s, size_t n)
162 {
163         while (n) {
164                 int r;
165                 r = write(fd, s, n);
166                 if (r <= 0) {
167                         exit(1);
168                 }
169                 s += r;
170                 n -= r;
171         }
172 }
173
174 static void main_loop(int sock1, int sock2)
175 {
176         unsigned char buf[1024];
177         int log1, log2, i=0;
178
179         do {
180                 char *fname1, *fname2;
181                 asprintf(&fname1, "sockspy-in.%d", i);
182                 asprintf(&fname2, "sockspy-out.%d", i);
183                 log1 = open(fname1, O_WRONLY|O_CREAT|O_EXCL, 0644);
184                 log2 = open(fname2, O_WRONLY|O_CREAT|O_EXCL, 0644);
185                 free(fname1);
186                 free(fname2);
187                 i++;
188         } while (i<1000 && (log1 == -1 || log2 == -1));
189
190         if (log1 == -1 || log2 == -1) {
191                 fprintf(stderr,"Failed to open log files\n");
192                 return;
193         }
194
195         while (1) {
196                 fd_set fds;
197                 int ret;
198
199                 FD_ZERO(&fds);
200                 FD_SET(sock1, &fds);
201                 FD_SET(sock2, &fds);
202
203                 ret = select(MAX(sock1, sock2)+1, &fds, NULL, NULL, NULL);
204                 if (ret == -1 && errno == EINTR) continue;
205                 if (ret <= 0) break;
206
207                 if (FD_ISSET(sock1, &fds)) {
208                         int n = read(sock1, buf, sizeof(buf));
209                         if (n <= 0) break;
210
211                         replace_str(buf, n);
212
213                         write_all(sock2, buf, n);
214                         write_all(log1, buf, n);
215                 }
216
217                 if (FD_ISSET(sock2, &fds)) {
218                         int n = read(sock2, buf, sizeof(buf));
219                         if (n <= 0) break;
220
221                         replace_str(buf, n);
222
223                         write_all(sock1, buf, n);
224                         write_all(log2, buf, n);
225                 }
226         }       
227 }
228
229 static char *get_socket_addr(int fd)
230 {
231         struct sockaddr sa;
232         struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
233         socklen_t length = sizeof(sa);
234         static char addr_buf[200];
235
236         strcpy(addr_buf,"0.0.0.0");
237
238         if (fd == -1) {
239                 return addr_buf;
240         }
241         
242         if (getsockname(fd, &sa, &length) < 0) {
243                 printf("getpeername failed. Error was %s\n", strerror(errno) );
244                 return addr_buf;
245         }
246         
247         strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
248         
249         return addr_buf;
250 }
251
252 int main(int argc, char *argv[])
253 {
254         int listen_port, dest_port;
255         char *host;
256         int sock_in;
257         int sock_out;
258         int listen_fd;
259         struct sockaddr addr;
260         int in_addrlen = sizeof(addr);
261
262         if (argc < 4) {
263                 printf("Usage: sockspy <inport> <host> <port>\n");
264                 exit(1);
265         }
266
267         listen_port = atoi(argv[1]);
268         host = argv[2];
269         dest_port = atoi(argv[3]);
270
271         listen_fd = open_socket_in(listen_port);
272
273         if (listen_fd == -1) {
274                 fprintf(stderr,"listen on port %d failed - %s\n", 
275                         listen_port, strerror(errno));
276                 exit(1);
277         }
278
279         if (listen(listen_fd, 5) == -1) {
280                 fprintf(stderr,"listen failed\n");
281                 exit(1);
282         }
283
284         sock_in = accept(listen_fd,&addr,&in_addrlen);
285
286         if (sock_in == -1) {
287                 fprintf(stderr,"accept on port %d failed - %s\n", 
288                         listen_port, strerror(errno));
289                 exit(1);
290         }
291
292         printf("Connection from %s\n", get_socket_addr(sock_in));
293
294         close(listen_fd);
295
296         sock_out = open_socket_out(host, dest_port);
297         if (sock_out == -1) {
298                 exit(1);
299         }
300
301         main_loop(sock_in, sock_out);
302         return 0;
303 }