proxy-ftp/dep/server.c

366 lines
12 KiB
C
Raw Normal View History

2015-12-14 20:48:19 +00:00
#include "server.h"
void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){
if( DEBUGMOD&HDR ) printf("====== DROP_SERVER(%s, %s, %d) ======\n\n", serverHost, *givenPort, *listenSocket);
2015-12-14 20:48:19 +00:00
// FONCTIONNEMENT
struct addrinfo hints; // contiendra le filtre/format
struct addrinfo* addrinfo; // contiendra les infos du serveur
int SOCKET, BIND, LISTEN; // file_desc(s)
// INFOS
struct sockaddr_storage serverInfo; // contiendra les informations du server
socklen_t sockaddr_len = sizeof(struct sockaddr_storage);
char infoHost[maxHostLen]; // contiendra l'adresse du server
char infoPort[maxPortLen]; // contiendra le port du server
/* [1] On définit le filtre/format
=======================================================*/
memset(&hints, 0, sizeof(struct addrinfo)); // on vide le filtre
hints.ai_family = AF_UNSPEC; // Allow IPv4 ou IPv6
hints.ai_socktype = SOCK_STREAM; // TCP (SOCK_DGRAM = UDP)
hints.ai_flags = AI_PASSIVE; // mode SERVER
hints.ai_protocol = 0; // non spécifié
if( DEBUGMOD&SCK ) printf("============HINTS===========\n");
if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int
if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int
if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int
if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int
if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int
if( DEBUGMOD&SCK ) printf("\n");
2015-12-14 20:48:19 +00:00
/* [2] On récupère les infos
=======================================================*/
if( strlen(*givenPort) == 0 ) // si pas défini, port dynamique
getaddrinfo(serverHost, 0, &hints, &addrinfo);
else // sinon manuel
getaddrinfo(serverHost, *givenPort, &hints, &addrinfo);
// Remarque: port=0 donc va être défini dynamiquement
if( DEBUGMOD&SCK ) printf("=============RES============\n");
if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int
if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int
if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int
if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int
if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int
if( DEBUGMOD&SCK ) printf("\n");
2015-12-14 20:48:19 +00:00
/* [3] Création de la socket
=======================================================*/
SOCKET = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0);
if( DEBUGMOD&SCK ) printf("SOCKET = %d\n", SOCKET);
2015-12-14 20:48:19 +00:00
// si erreur
if( SOCKET == -1 ) return;
/* [4] On publie la SOCKET
=======================================================*/
BIND = bind(
SOCKET,
addrinfo->ai_addr,
addrinfo->ai_addrlen
);
if( DEBUGMOD&SCK ) printf("BIND = %d\n", BIND);
2015-12-14 20:48:19 +00:00
// si erreur
if( BIND == -1 ) return;
/* [5] On récupère les informations du serveur (host/port)
=======================================================*/
int getInfo = getsockname(SOCKET, (struct sockaddr *) &serverInfo, &sockaddr_len);
if( getInfo == -1 ) return;
getInfo = getnameinfo( // on récupère le host et le port
(struct sockaddr *) &serverInfo,
sizeof(serverInfo),
infoHost, maxHostLen,
infoPort, maxPortLen,
NI_NUMERICHOST | NI_NUMERICSERV
);
if( getInfo == -1 ) return;
if( DEBUGMOD&SCK ) printf("Server host: %s\n", infoHost);
if( DEBUGMOD&SCK ) printf("Server port: %s\n", infoPort);
2015-12-14 20:48:19 +00:00
// on a plus besoin des infos de l'adresse
freeaddrinfo(addrinfo);
/* [6] On met la socket sur écoute
=======================================================*/
LISTEN = listen(SOCKET, maxListLen);
if( DEBUGMOD&SCK ) printf("LISTEN = %d\n", LISTEN);
2015-12-14 20:48:19 +00:00
// si erreur
if( LISTEN == -1 ) return;
/* [7] On envoie les données par référence
=======================================================*/
// port
*givenPort = malloc( maxPortLen );
2015-12-14 20:48:19 +00:00
strcpy(*givenPort, infoPort);
// socket d'écoute
*listenSocket = SOCKET;
}
// CMD: CLIENT (SRV) PROXY (CLT) FTP
// DTA: CLIENT (CLT) PROXY (CLT) FTP
//
void MANAGE_REQUEST(char* pRequest, int* DUSER_SOCKET, int* DFTP_SOCKET){
if( DEBUGMOD&HDR ) printf("====== MANAGE_REQUEST(%s, %d, %d) ======\n\n", pRequest, *DUSER_SOCKET, *DFTP_SOCKET);
2015-12-14 20:48:19 +00:00
char answer[maxBuffLen]; // contiendra la réponse
int nbSend; // contiendra le nombre de données envoyées
char rCommand[10]; // contiendra les commandes (1ère partie)
char rContent[maxBuffLen]; // contiendra le contenu associé à la commande (2ème partie)
// on vide les buffers
memset(&rCommand, '\0', sizeof(rCommand));
memset(&rContent, '\0', sizeof(rContent));
memset(&answer, '\0', sizeof(answer));
/* [1] On découpe la requête en 2 parties
================================================*/
splitFtpRequest(pRequest, rCommand, rContent);
/* [2] Selection en fonction de @rCommand
================================================*/
/* (1) PORT a1,a2,a3,a4,p1,p2 => utilisateur (actif)
2015-12-14 20:48:19 +00:00
--------------------------------------------*/
if( strcmp(rCommand, "PORT") == 0 ){
int a1, a2, a3, a4 = 0;
int p1, p2 = 0;
2015-12-14 20:48:19 +00:00
char serverHost[maxHostLen] = {0};
char serverPort[maxPortLen] = {0};
char BUFFER[maxBuffLen] = {0};
2015-12-14 20:48:19 +00:00
sscanf(pRequest, "PORT %d,%d,%d,%d,%d,%d", &a1, &a2, &a3, &a4, &p1, &p2);
// on récupère l'adresse en <char*>
sprintf(serverHost, "%d.%d.%d.%d", a1, a2, a3, a4);
// on récupère le port en <char*>
sprintf(serverPort, "%d", p1*256+p2);
2015-12-14 20:48:19 +00:00
// on se connecte au client
if( DEBUGMOD&SCK ) printf("CONNECTING TO CLIENT %s:%s\n", serverHost, serverPort);
CONNECT_CLIENT(serverHost, serverPort, DUSER_SOCKET);
if( DEBUGMOD&SCK ) printf("CONNECTED TO CLIENT %s:%s\n", serverHost, serverPort);
// on envoie PASV car on veut être en mode passif entre le proxy et le serveur FTP
strcpy(pRequest, "PASV\r\n");
}
// WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER);
// xPrint("FTPLIST: %s\n", BUFFER);
2015-12-14 20:48:19 +00:00
/* [3] Envoi de la réponse
2015-12-14 20:48:19 +00:00
================================================*/
}
void MANAGE_RESPONSE(int* USER_SOCKET, int* FTP_SOCKET, char* pAnswer, int* DUSER_SOCKET, int* DFTP_SOCKET){
if( DEBUGMOD&HDR ) printf("====== MANAGE_RESPONSE(%d, %s, %d, %d) ======\n\n", *USER_SOCKET, pAnswer, *DUSER_SOCKET, *DFTP_SOCKET);
2015-12-14 20:48:19 +00:00
char response[maxBuffLen]; // contiendra la réponse
char ftpCodeStr[4]; // contiendra le code FTP (1ère partie)
char ftpText[maxBuffLen]; // contiendra le texte associé à la commande (2ème partie)
int ftpCode; // contiendra le code FTP en numérique
2015-12-14 20:48:19 +00:00
// on vide les buffers
memset(&ftpCodeStr, '\0', sizeof(ftpCode));
2015-12-14 20:48:19 +00:00
memset(&ftpText, '\0', sizeof(ftpText));
2015-12-14 21:00:05 +00:00
memset(&response, '\0', sizeof(response));
2015-12-14 20:48:19 +00:00
/* [1] On découpe la requête en 2 parties
================================================*/
splitFtpResponse(pAnswer, ftpCodeStr, ftpText);
// on met le code FTP en <int>
ftpCode = atoi( ftpCodeStr );
2015-12-14 20:48:19 +00:00
/* [2] Selection en fonction de @ftpCode
================================================*/
/* (2) Demande d'username
--------------------------------------------*/
if( ftpCode == 220 )
2015-12-14 21:00:05 +00:00
strcpy(response, WLCM_MSG);
2015-12-14 20:48:19 +00:00
/* (3) username OK -> demande MDP
--------------------------------------------*/
else if( ftpCode == 331 )
2015-12-14 21:00:05 +00:00
strcpy(response, USER_MSG);
2015-12-14 20:48:19 +00:00
/* (4) Bon mdp -> connection
2015-12-14 20:48:19 +00:00
--------------------------------------------*/
else if( ftpCode == 230 )
2015-12-14 21:00:05 +00:00
strcpy(response, PASS_BON_MSG);
2015-12-14 20:48:19 +00:00
/* (5) Mauvais mdp -> connection
2015-12-14 20:48:19 +00:00
--------------------------------------------*/
else if( ftpCode == 530 )
2015-12-14 21:00:05 +00:00
strcpy(response, PASS_BAD_MSG);
2015-12-14 20:48:19 +00:00
/* (6) Info SYST
2015-12-14 20:48:19 +00:00
--------------------------------------------*/
// else if( ftpCode == 215 )
2015-12-14 21:00:05 +00:00
// strcpy(response, "bla\n");
2015-12-14 20:48:19 +00:00
/* (7) LOGOUT => EXIT
2015-12-14 20:48:19 +00:00
--------------------------------------------*/
else if( ftpCode == 221 )
2015-12-14 21:00:05 +00:00
strcpy(response, EXIT_MSG);
2015-12-14 20:48:19 +00:00
/* (8) Mode passif => On lance les SOCKETS du BUS DE DONNEES
--------------------------------------------*/
else if( ftpCode == 227 ){ // on lance la SOCKET FTP du BUS DE DONNEES
int a1, a2, a3, a4 = 0;
int p1, p2 = 0;
char serverHost[maxHostLen];
char serverPort[maxPortLen];
sscanf(pAnswer, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)", &a1, &a2, &a3, &a4, &p1, &p2);
// on récupère l'adresse en <char*>
sprintf(serverHost, "%d.%d.%d.%d", a1, a2, a3, a4);
// on récupère le port en <char*>
sprintf(serverPort, "%d", p1*256+p2);
// on se connecte au serveur FTP
if( DEBUGMOD&SCK ) printf("CONNECTING TO FTP %s:%s\n", serverHost, serverPort);
CONNECT_CLIENT(serverHost, serverPort, DFTP_SOCKET);
if( DEBUGMOD&SCK ) printf("CONNECTED TO FTP %s:%s\n", serverHost, serverPort);
strcpy(response, LIST_DAT_MSG);
}
/* (9) On lit la SOCKET FTP du BUS DE DONNEES
--------------------------------------------*/
else if( ftpCode == 150 ){ // on lit la SOCKET FTP du BUS DE DONNEES
char BUFFER[maxBuffLen] = {0};
/* 1. Envoi au client de l'écoute de la réponse (associée) du BUS DE DONNEES */
// sread(FTP_SOCKET, BUFFER);
// if( DEBUGMOD&CMD ) xPrint("F->P: %s\n", BUFFER);
swrite(USER_SOCKET, READ_CON_MSG);
if( DEBUGMOD&CMD ) xPrint("P->C: %s\n", READ_CON_MSG);
/* 2. On lit la SOCKET FTP (BUS DE DONNEES)*/
int nbRead = WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER);
if( DEBUGMOD&DAT && nbRead == -1 ) printf("ERROR\n");
else if( DEBUGMOD&DAT ) xPrint("[BUS_IN]: %s\n", BUFFER);
/* 3. On redirige sur la SOCKET utilisateur (BUS DE DONNEES) */
int nbSend = swrite(DUSER_SOCKET, BUFFER);
if( DEBUGMOD&DAT && nbSend == -1 ) printf("ERROR\n");
else if( DEBUGMOD&DAT ) xPrint("[BUS_OUT]: %s\n", BUFFER);
if( DEBUGMOD&DAT ) xPrint("BUS_FTP->BUS_CLIENT: %s\n", BUFFER);
/* 4. On ferme les SOCKETS du BUS DE DONNEES */
close(*DFTP_SOCKET);
if( DEBUGMOD&CMD ) printf("BUS_FTP fermé (%d)\n", *DFTP_SOCKET);
close(*DUSER_SOCKET);
if( DEBUGMOD&CMD ) printf("BUS_USER fermé (%d)\n", *DUSER_SOCKET);
// on vide les SOCKET FTP des 2 BUS
// WAIT_SOCKET_UPDATE(FTP_SOCKET, BUFFER); // command
// WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER); // données
// printf("")
sread(FTP_SOCKET, BUFFER);
// fin de la transaction
strcpy(response, STOP_DAT_MSG);
}
/* (10) Fin de transfert de données
--------------------------------------------*/
else if( ftpCode == 226 ){ // on ferme les SOCKETS du BUS DE DONNEES
// strcpy(response, "226 Fin de la transaction!\r\n");
strcpy(response, "\r\n");
close(*DUSER_SOCKET);
close(*DFTP_SOCKET);
}
2015-12-14 20:48:19 +00:00
/* (n) Commande inconnue
--------------------------------------------*/
else
strcpy(response, pAnswer);
2015-12-14 20:48:19 +00:00
/* [3] Retour de la réponse
================================================*/
strcpy(pAnswer, response);
2015-12-14 20:48:19 +00:00
}
int WAIT_SOCKET_UPDATE(int* pSocket, char* pBuffer){
2015-12-14 20:48:19 +00:00
memset(pBuffer, 0, maxBuffLen); // on vide le buffer
int nbRead = 0;
do{
nbRead = sread(pSocket, pBuffer);
// si on est déconnecté, on ferme la SOCKET
if( nbRead == -1 ){
printf("Client déconnecté!\n");
return -1;
}
}while( pBuffer[nbRead-1] != '\n' && pBuffer[nbRead-2] != '\r' );
// on retourne -1 si erreur, SINON 0
return nbRead;
}
// void prefixFtpResponse(char* pBuffer, char* ftpCode){
// }