1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/wait.h>
#include <syslog.h>
#include <netdb.h>
int main(int argc,char *argv[]) {
unsigned char vn;//version
unsigned char cd;//command
unsigned short dstport;
unsigned int dstip;
unsigned char in;
int i;
int status;
char *name[5];
char user[256];
char sport[10];//10 is more than enough. it is converted from a short with %d
char host[256];//https://blogs.msdn.microsoft.com/oldnewthing/20120412-00/?p=7873/
read(0,&vn,1);
//fprintf(stderr,"version number: %d\n",vn);
if(vn != 4) {
//fprintf(stderr,"received wrong version number. needs to be 4.\n");
write(1,"\x00\x5b\xde\xca\xf0\xc0\xff\xee",8);//the decaf0coffee is supposed to be ignored by clients.
return 1;
}
read(0,&cd,1);
//fprintf(stderr,"command code: %d\n",cd);
if(cd != 1) {
//fprintf(stderr,"only going to implement command code 1 (connect) atm.\n");
write(1,"\x00\x5b\xde\xca\xf0\xc0\xff\xee",8);//the response is in the same format as the request. vn+cd+port+ip
return 2;
}
read(0,&dstport,2);
//fprintf(stderr,"dstport: %d\n",ntohs(dstport));
read(0,&dstip,4);
//fprintf(stderr,"dstip: %d\n",ntohl(dstip));
for(i=0;i<254;i++) {
read(0,user+i,1);
if(!user[i]) break;//we read a null, let's hop out.
}
if(user[i]) {//we didn't read the whole thing. truncate and just ignore the rest.
user[i]=0;
while(read(0,&in,1) > 0) {
if (in == 0) break;
}
}
//fprintf(stderr,"user: %s\n",user);
//do some sort of auth here...
//pass it off to a script?
if(argc>2) {//we have an argument for the script to run auth against.
//what do we need to pass? the port we're on, the port they connected from
switch(fork()) {
case -1:
return errno;
case 0://child.
name[0]=argv[2];
name[1]=user;
name[2]=0;
execv(name[0],name);
return errno;
default:
break;
}
wait(&status);
}
if(WEXITSTATUS(status)) {//anything but 0 is an error.
write(1,"\x00\x5b\xde\xca\xf0\xc0\xff\xee",8);
return 3;
}
if(ntohl(dstip) < 256) { //this should match for an address that is 0.0.0.x where x could be anything.
//do what we did for user, but with a hostname now.
for(i=0;i<254;i++) {
read(0,host+i,1);
if(!host[i]) break;
}
if(host[i]) {//we didn't read the whole thing. truncate and just ignore the rest.
host[i]=0;
while(read(0,&in,1) > 0) {
if (in == 0) break;
}
}
//fprintf(stderr,"host: %s\n",host);
}
struct sockaddr_in6 sa6;
unsigned int sl=sizeof(sa6);
char h[NI_MAXHOST], s[NI_MAXSERV];
if(getpeername(argc>1?atoi(argv[1]):0,(struct sockaddr *)&sa6,&sl) == -1) return 1;
if(getnameinfo((struct sockaddr *)&sa6,sl,h,sizeof(h),s,sizeof(s),NI_NUMERICHOST|NI_NUMERICSERV)) return 2;
syslog(LOG_WARNING,"proxy request: %s@%s:%s => %s:%d",user,h,s,host,ntohs(dstport));
//fprintf(stderr,"got passed all that shit...\n");
write(1,"\x00\x5a\xde\xca\xf0\xc0\xff\xee",8);
snprintf(sport,sizeof(sport)-1,"%u",ntohs(dstport));//%u because ports are unsigned.
name[0]=argc>1?argv[1]:"/usr/pkg/bin/nc";//if you want the arguments in a different order either change this sauce or use a script.
name[1]=host;//WARNING: these two arguments aren't sanitized. they may contain flags set by the proxy's user that could wreak havok!
name[2]=sport;//not sure how many programs can be messed up using just a number though.
name[3]=0;
//fprintf(stderr,"running: %s %s %s %s\n",name[0],name[1],name[2],name[3]);
execv(name[0],name);
//fprintf(stderr,"execv failed. :/");
//perror("execv");
return errno;//if we get here something failed so we might as well return errno.
}
|