added demo of signal/uid handling feature
[tridge/junkcode.git] / sockspy-rpc.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 <sys/socket.h>
9 #include <netdb.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <fcntl.h>
13 #include <sys/types.h>
14 #include <sys/time.h>
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
17
18 #define MAX(a,b) ((a)>(b)?(a):(b))
19
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
36
37 static void replace_str(char *buf, int n)
38 {
39         char *p;
40         p = memmem(buf, n, "NTLMSSP", 7);
41         if (p && p[8] == 1) {
42                 unsigned x;
43
44                 x = *(unsigned *)(p+12);
45                 printf("flags were 0x%08x\n", x);
46
47                 x = 0x00000011;
48
49                 printf("replacing challenge flags with 0x%08x\n", x);
50                 *(unsigned *)(p+12) = x;
51         }
52 }
53
54 /* open a socket to a tcp remote host with the specified port */
55 static int open_socket_out(const char *host, int port)
56 {
57         struct sockaddr_in sock_out;
58         int res;
59         struct hostent *hp;  
60         struct in_addr addr;
61
62         res = socket(PF_INET, SOCK_STREAM, 0);
63         if (res == -1) {
64                 return -1;
65         }
66
67         if (inet_pton(AF_INET, host, &addr) > 0) {
68                 memcpy(&sock_out.sin_addr, &addr, sizeof(addr));
69         } else {
70                 hp = gethostbyname(host);
71                 if (!hp) {
72                         fprintf(stderr,"unknown host %s\n", host);
73                         return -1;
74                 }
75                 memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
76         }
77
78         sock_out.sin_port = htons(port);
79         sock_out.sin_family = PF_INET;
80
81         if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)) != 0) {
82                 close(res);
83                 fprintf(stderr,"failed to connect to %s (%s)\n", 
84                         host, strerror(errno));
85                 return -1;
86         }
87
88         return res;
89 }
90
91
92 /*
93   open a socket of the specified type, port and address for incoming data
94 */
95 int open_socket_in(int port)
96 {
97         struct sockaddr_in sock;
98         int res;
99         int one=1;
100
101         memset(&sock,0,sizeof(sock));
102
103 #ifdef HAVE_SOCK_SIN_LEN
104         sock.sin_len = sizeof(sock);
105 #endif
106         sock.sin_port = htons(port);
107         sock.sin_family = AF_INET;
108
109         res = socket(AF_INET, SOCK_STREAM, 0);
110         if (res == -1) { 
111                 fprintf(stderr, "socket failed\n"); return -1; 
112                 return -1;
113         }
114
115         setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
116
117         if (bind(res, (struct sockaddr *)&sock, sizeof(sock)) < 0) { 
118                 return(-1); 
119         }
120
121         return res;
122 }
123
124 /* write to a file descriptor, making sure we get all the data out or
125  * die trying */
126 static void write_all(int fd, unsigned char *s, size_t n)
127 {
128         while (n) {
129                 int r;
130                 r = write(fd, s, n);
131                 if (r <= 0) {
132                         exit(1);
133                 }
134                 s += r;
135                 n -= r;
136         }
137 }
138
139 static void main_loop(int sock1, int sock2)
140 {
141         unsigned char buf[1024];
142         int log1, log2, i=0;
143
144         do {
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);
150                 free(fname1);
151                 free(fname2);
152                 i++;
153         } while (i<1000 && (log1 == -1 || log2 == -1));
154
155         if (log1 == -1 || log2 == -1) {
156                 fprintf(stderr,"Failed to open log files\n");
157                 return;
158         }
159
160         while (1) {
161                 fd_set fds;
162                 int ret;
163
164                 FD_ZERO(&fds);
165                 FD_SET(sock1, &fds);
166                 FD_SET(sock2, &fds);
167
168                 ret = select(MAX(sock1, sock2)+1, &fds, NULL, NULL, NULL);
169                 if (ret == -1 && errno == EINTR) continue;
170                 if (ret <= 0) break;
171
172                 if (FD_ISSET(sock1, &fds)) {
173                         int n = read(sock1, buf, sizeof(buf));
174                         if (n <= 0) break;
175
176                         replace_str(buf, n);
177
178                         write_all(sock2, buf, n);
179                         write_all(log1, buf, n);
180                 }
181
182                 if (FD_ISSET(sock2, &fds)) {
183                         int n = read(sock2, buf, sizeof(buf));
184                         if (n <= 0) break;
185
186                         replace_str(buf, n);
187
188                         write_all(sock1, buf, n);
189                         write_all(log2, buf, n);
190                 }
191         }       
192 }
193
194 int main(int argc, char *argv[])
195 {
196         int listen_port, dest_port;
197         char *host;
198         int sock_in;
199         int sock_out;
200         int listen_fd;
201         struct sockaddr addr;
202         int in_addrlen = sizeof(addr);
203
204         if (argc < 4) {
205                 printf("Usage: sockspy <inport> <host> <port>\n");
206                 exit(1);
207         }
208
209         listen_port = atoi(argv[1]);
210         host = argv[2];
211         dest_port = atoi(argv[3]);
212
213         listen_fd = open_socket_in(listen_port);
214
215         if (listen_fd == -1) {
216                 fprintf(stderr,"listen on port %d failed - %s\n", 
217                         listen_port, strerror(errno));
218                 exit(1);
219         }
220
221         if (listen(listen_fd, 5) == -1) {
222                 fprintf(stderr,"listen failed\n");
223                 exit(1);
224         }
225
226         sock_in = accept(listen_fd,&addr,&in_addrlen);
227
228         if (sock_in == -1) {
229                 fprintf(stderr,"accept on port %d failed - %s\n", 
230                         listen_port, strerror(errno));
231                 exit(1);
232         }
233
234         close(listen_fd);
235
236         sock_out = open_socket_out(host, dest_port);
237         if (sock_out == -1) {
238                 exit(1);
239         }
240
241         main_loop(sock_in, sock_out);
242         return 0;
243 }