Created
December 18, 2015 22:58
-
-
Save yne/20d1bdadab88d13b0e0d to your computer and use it in GitHub Desktop.
Offer an active FTP interface over a passiv FTP server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h>//exit | |
#include <stdio.h> | |
#include <pthread.h> | |
#include <netdb.h> //NI_NUMERICHOST | |
#include <string.h>//strlen | |
#include <unistd.h>//read write close fork | |
#define ss2sa(ss) ((struct sockaddr *)(ss)) | |
#define $(X) if((err=(X))<0)die(__LINE__,err) | |
#define Write(A,B) write(A,B,strlen(B)) | |
#define Read(A,B) len=read(A,B,sizeof(B));buf[len]=0; | |
typedef void*(*Threadp)(void *); | |
struct addrinfo hints={AI_PASSIVE,AF_INET,SOCK_STREAM}; | |
void die(int line,int code){ | |
printf("erreur @%i -> (%i)\n",line,code); | |
exit(code); | |
} | |
void arg2addr(char*buf,char*ip,char*port,int cli){ | |
int ip1,ip2,ip3,ip4,port1,port2; | |
if(cli)sscanf(buf,"PORT %i,%i,%i,%i,%i,%i",&ip1,&ip2,&ip3,&ip4,&port1,&port2); | |
else sscanf(buf,"227 Entering Passive Mode (%i,%i,%i,%i,%i,%i)",&ip1,&ip2,&ip3,&ip4,&port1,&port2); | |
sprintf(ip,"%i.%i.%i.%i",ip1,ip2,ip3,ip4); | |
sprintf(port,"%i",(port1<<8)+port2); | |
} | |
int newSocket(char*ip,char*port,int isbind){ | |
int err,fd;struct addrinfo*res; | |
$(fd=socket(AF_INET, SOCK_STREAM, 0)); | |
$(getaddrinfo(ip,port,&hints,&res)); | |
if(isbind)bind(fd,res->ai_addr, res->ai_addrlen); | |
else connect(fd,res->ai_addr, res->ai_addrlen); | |
freeaddrinfo(res); | |
return fd; | |
} | |
void bridge(int*arg){ | |
while(1){ | |
char buf[1500]; | |
int len=read(arg[arg[2]?0:1],buf,sizeof(buf)); | |
if(write(arg[arg[2]?1:0],buf,len)<=0)break; | |
} | |
close(arg[0]); | |
close(arg[1]); | |
} | |
void proxy(int client){ | |
char buf[256],_user[48],user[32],host[32],port[6]="21"; | |
pthread_t thread1; | |
int server,err,len,arg[3];//{cli,srv,sens} | |
Write(client,"220 Bonjour\r\n"); | |
Read(client,buf); | |
sscanf(buf,"USER %31[^@]@%31[^:\r]:%5[^\r]",user,host,port);//anonymous@ftp.irit.fr:21 | |
$(server=newSocket(host,port,0)); | |
sprintf(_user,"USER %s\r\n",user); | |
Read(server,buf);//recois le 220 du serv | |
Write(server,_user); | |
while(1){//boucle principale | |
do{ | |
Read (server,buf); | |
printf("srv:%s",buf); | |
if(!Write(client,buf))exit(0); | |
}while(buf[0]=='1'); | |
do{ | |
Read(client,buf); | |
if(memcmp("PASV",buf,4))break; | |
Write(client,"500\r\n");//tu devrais etre actif toi ! | |
}while(1); | |
if(!memcmp("PORT",buf,4)){//le client veut qu'on vienne le chercher | |
arg2addr(buf,host,port,1);//printf("client <%s:%s>\n",ip,port); | |
arg[1]=newSocket(host,port,0);//client | |
Write(server,"PASV\r\n"); | |
Read (server,buf); | |
arg2addr(buf,host,port,0);//printf("server <%s:%s>\n",ip,port); | |
arg[0]=newSocket(host,port,0);//serv | |
Write(client,"200 le serv est OP\r\n"); | |
Read (client,buf);//lit la commande | |
if(!memcmp("LIST",buf,4) | |
||!memcmp("GET" ,buf,3))arg[2]=1;//le thread est en mode cli<<srv | |
if(!memcmp("STOR",buf,4))arg[2]=0;//le thread est en mode cli>>srv | |
pthread_create( &thread1, NULL,(Threadp) bridge, (void*) arg); | |
} | |
printf("cli:%s",buf); | |
if(!Write(server,buf))exit(0); | |
} | |
} | |
int main(int argc,char* argv[]){ | |
int err,client,prox=newSocket("127.0.0.1","0",1); | |
struct sockaddr_storage info,from; | |
unsigned socklen=sizeof(struct sockaddr_storage); | |
char ip[64],port[6]; | |
$(getsockname(prox,ss2sa(&info),&socklen)); | |
$(getnameinfo(ss2sa(&info),sizeof(info),ip,sizeof(ip),port,sizeof(port),3)); | |
printf("listen on %s:%s\n", ip,port); | |
$(listen(prox, 1));//attente de connection | |
while(1){ | |
$(client=accept(prox,ss2sa(&from), &socklen)); | |
if(!fork()){ | |
close(prox); | |
proxy(client); | |
}else close(client); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment