2017-03-28 16:45:18 +00:00
|
|
|
|
#include "server.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int MANAGE_REQUEST(char* pRequest, int* USER_SOCKET, int* FTP_SOCKET, int* DUSER_SOCKET, int* DFTP_SOCKET){
|
|
|
|
|
if( DEBUGMOD&HDR ) printf("====== MANAGE_REQUEST(%s, %d, %d, %d, %d) ======\n\n", pRequest, *USER_SOCKET, *FTP_SOCKET, *DUSER_SOCKET, *DFTP_SOCKET);
|
|
|
|
|
|
|
|
|
|
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char response[MAX_BUF_LEN]; // contiendra la réponse (2*taille buffer pour strcat(BUFLEN, BUFLEN))
|
2017-03-28 16:45:18 +00:00
|
|
|
|
int nbSend; // contiendra le nombre de données envoyées
|
|
|
|
|
char rCommand[5]; // contiendra les commandes (1ère partie)
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char rContent[MAX_BUF_LEN]; // contiendra le contenu associé à la commande (2ème partie)
|
2017-03-28 16:45:18 +00:00
|
|
|
|
|
|
|
|
|
// on vide les buffers
|
|
|
|
|
memset(&rCommand, '\0', sizeof(rCommand));
|
|
|
|
|
memset(&rContent, '\0', sizeof(rContent));
|
|
|
|
|
memset(&response, '\0', sizeof(response));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* [1] On découpe la requête en 2 parties
|
|
|
|
|
================================================*/
|
|
|
|
|
splitFtpRequest(pRequest, rCommand, rContent);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* [2] Selection en fonction de @rCommand
|
|
|
|
|
================================================*/
|
|
|
|
|
|
|
|
|
|
/* (1) USER username@serveur => connection FTP (commande)
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
if( strcmp(rCommand, "USER") == 0 && indexOf(rContent, '@') >= 0 ){
|
|
|
|
|
char userName[100] = {0};
|
|
|
|
|
char hostName[maxHostLen] = {0};
|
|
|
|
|
// pour l'envoi de la séquence d'initialisation
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char* ftp_response; ftp_response = malloc(MAX_BUF_LEN);
|
|
|
|
|
memset(ftp_response, 0, MAX_BUF_LEN);
|
2017-03-28 16:45:18 +00:00
|
|
|
|
|
|
|
|
|
/* 1. On extrait @username et @hostname */
|
|
|
|
|
sscanf(rContent, "%[^@]@%s\r\n", userName, hostName);
|
|
|
|
|
|
|
|
|
|
if( DEBUGMOD&BUF ) printf("USERNAME [[%s]]\n", userName);
|
|
|
|
|
if( DEBUGMOD&BUF ) printf("HOSTNAME [[%s]]\n", hostName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 2. On se connecte au serveur FTP (commandes) */
|
|
|
|
|
int error = CONNECT_CLIENT(hostName, FTP_PORT, FTP_SOCKET);
|
|
|
|
|
|
|
|
|
|
if( error == -1 || *FTP_SOCKET == -1 ){ // si erreur
|
|
|
|
|
printf("Impossible de se connecter au serveur (%s:%s)\n", hostName, FTP_PORT);
|
|
|
|
|
strcpy(pRequest, "421 ERREUR: impossible de se connecter au serveur!!\r\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( DEBUGMOD&SCK ) printf("FTP SOCKET CONNECTED AT %s:%s\n", hostName, FTP_PORT);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 3. On envoie la séquence d'initialisation */
|
|
|
|
|
CLIENT_SEND(FTP_SOCKET, "", &ftp_response);
|
2017-04-01 15:01:36 +00:00
|
|
|
|
|
2017-03-28 16:45:18 +00:00
|
|
|
|
if( DEBUGMOD&CMD ) xPrint("P->F: %s\n\n", "\r\n");
|
|
|
|
|
if( DEBUGMOD&CMD ) xPrint("F->P: %s\n", ftp_response);
|
2017-04-01 15:01:36 +00:00
|
|
|
|
|
2017-03-28 16:45:18 +00:00
|
|
|
|
|
|
|
|
|
/* 4. On envoie la requête USER au serveur FTP auquel on vient de se connecter */
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char newRequest[MAX_BUF_LEN];
|
2017-03-28 16:45:18 +00:00
|
|
|
|
strcat(newRequest, "USER ");
|
|
|
|
|
strcat(newRequest, userName);
|
|
|
|
|
strcat(newRequest, "\r\n");
|
|
|
|
|
strcpy(response, "USER xdrm\r\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if( strcmp(rCommand, "USER") == 0 ) // si oubli serveur
|
|
|
|
|
strcpy(response, "421 'username@FTPserver' attendu\n");
|
|
|
|
|
|
|
|
|
|
/* (2) PORT a1,a2,a3,a4,p1,p2 => utilisateur (actif)
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
else if( strcmp(rCommand, "PORT") == 0 ){
|
|
|
|
|
int a1, a2, a3, a4 = 0;
|
|
|
|
|
int p1, p2 = 0;
|
|
|
|
|
|
|
|
|
|
char serverHost[maxHostLen] = {0};
|
|
|
|
|
char serverPort[maxPortLen] = {0};
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char BUFFER[MAX_BUF_LEN] = {0};
|
2017-03-28 16:45:18 +00:00
|
|
|
|
|
|
|
|
|
/* 1. On récupère l'ip et le port de la réponse */
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 2. 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);
|
2017-04-01 15:01:36 +00:00
|
|
|
|
|
2017-03-28 16:45:18 +00:00
|
|
|
|
/* 3. Envoi de "PASV" car on veut être en mode passif entre le proxy et le serveur FTP */
|
|
|
|
|
strcpy(response, "PASV\r\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* (n) Si aucun traitement on recopie la requête telquel
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
else
|
|
|
|
|
strcpy(response, pRequest);
|
|
|
|
|
|
|
|
|
|
/* [3] Retour de la réponse
|
|
|
|
|
================================================*/
|
|
|
|
|
strcpy(pRequest, response);
|
|
|
|
|
printf("RESP: %s\n", pRequest);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MANAGE_RESPONSE(char* pAnswer, int* USER_SOCKET, int* FTP_SOCKET, int* DUSER_SOCKET, int* DFTP_SOCKET){
|
|
|
|
|
if( DEBUGMOD&HDR ) printf("====== MANAGE_RESPONSE(%s, %d, %d, %d, %d) ======\n\n", pAnswer, *USER_SOCKET, *FTP_SOCKET, *DUSER_SOCKET, *DFTP_SOCKET);
|
|
|
|
|
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char response[MAX_BUF_LEN]; // contiendra la réponse
|
2017-03-28 16:45:18 +00:00
|
|
|
|
char ftpCodeStr[4]; // contiendra le code FTP (1ère partie)
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char ftpText[MAX_BUF_LEN]; // contiendra le texte associé à la commande (2ème partie)
|
2017-03-28 16:45:18 +00:00
|
|
|
|
int ftpCode; // contiendra le code FTP en numérique
|
|
|
|
|
|
|
|
|
|
// on vide les buffers
|
|
|
|
|
memset(&ftpCodeStr, '\0', sizeof(ftpCode));
|
|
|
|
|
memset(&ftpText, '\0', sizeof(ftpText));
|
|
|
|
|
memset(&response, '\0', sizeof(response));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* [1] On découpe la requête en 2 parties
|
|
|
|
|
================================================*/
|
|
|
|
|
splitFtpResponse(pAnswer, ftpCodeStr, ftpText);
|
|
|
|
|
|
|
|
|
|
// on met le code FTP en <int>
|
2017-04-01 15:01:36 +00:00
|
|
|
|
ftpCode = atoi( ftpCodeStr );
|
2017-03-28 16:45:18 +00:00
|
|
|
|
|
|
|
|
|
// mise à disposition de variables temporaires
|
|
|
|
|
int tmp[6] = {0};
|
|
|
|
|
char serverHost[maxHostLen];
|
|
|
|
|
char serverPort[maxPortLen];
|
2017-04-01 15:01:36 +00:00
|
|
|
|
char BUFFER[MAX_BUF_LEN] = {0};
|
2017-03-28 16:45:18 +00:00
|
|
|
|
|
|
|
|
|
/* [2] Selection en fonction de @ftpCode
|
|
|
|
|
================================================*/
|
|
|
|
|
switch(ftpCode){
|
|
|
|
|
/* (1) Demande d'username
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 220:
|
|
|
|
|
strcpy(response, WLCM_MSG);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* (2) username OK -> demande MDP
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 331:
|
|
|
|
|
strcpy(response, USER_MSG);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* (3) Bon mdp -> connection
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 230:
|
|
|
|
|
strcpy(response, PASS_BON_MSG);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* (4) Mauvais mdp -> message erreur
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 530:
|
|
|
|
|
strcpy(response, PASS_BAD_MSG);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* (5) Info SYST
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
// case 215:
|
|
|
|
|
// strcpy(response, "bla\n");
|
|
|
|
|
// break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* (6) LOGOUT => EXIT
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 221:
|
|
|
|
|
strcpy(response, EXIT_MSG);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* (7) Mode passif => On lance les SOCKETS du BUS DE DONNEES
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 227: // on lance la SOCKET FTP du BUS DE DONNEES
|
|
|
|
|
|
|
|
|
|
/* 1. On récupère l'ip et le port de la réponse */
|
|
|
|
|
sscanf(pAnswer, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
|
|
|
|
|
// on récupère l'adresse en <char*>
|
|
|
|
|
sprintf(serverHost, "%d.%d.%d.%d", tmp[0], tmp[1], tmp[2], tmp[3]);
|
|
|
|
|
// on récupère le port en <char*>
|
|
|
|
|
sprintf(serverPort, "%d", tmp[4]*256+tmp[5]);
|
|
|
|
|
|
|
|
|
|
/* 2. Connexion 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);
|
|
|
|
|
|
|
|
|
|
/* 3. Envoi du message de code 200 */
|
|
|
|
|
strcpy(response, LIST_DAT_MSG);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* (8) On lit la SOCKET FTP du BUS DE DONNEES
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 150:
|
|
|
|
|
|
|
|
|
|
/* 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) */
|
|
|
|
|
tmp[0] = WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER);
|
|
|
|
|
|
|
|
|
|
if( DEBUGMOD&DAT && tmp[0] == -1 ) printf("ERROR\n");
|
|
|
|
|
else if( DEBUGMOD&DAT ) xPrint("[BUS_IN]: %s\n", BUFFER);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 3. On redirige sur la SOCKET utilisateur (BUS DE DONNEES) */
|
|
|
|
|
tmp[1] = swrite(DUSER_SOCKET, BUFFER);
|
|
|
|
|
|
|
|
|
|
if( DEBUGMOD&DAT && tmp[1] == -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("")
|
2017-04-01 15:01:36 +00:00
|
|
|
|
|
2017-03-28 16:45:18 +00:00
|
|
|
|
/* 5. On vide le BUS DE COMMANDE du serveur FTP */
|
|
|
|
|
/* A. On définit un TIMEOUT (1 sec) */
|
|
|
|
|
setSocketTimeout(FTP_SOCKET, 0, 50);
|
|
|
|
|
|
|
|
|
|
/* B. On attends une réponse */
|
|
|
|
|
tmp[2] = sread(FTP_SOCKET, BUFFER);
|
2017-04-01 15:01:36 +00:00
|
|
|
|
|
2017-03-28 16:45:18 +00:00
|
|
|
|
/* C. On enlève le TIMEOUT (default) */
|
|
|
|
|
setSocketTimeout(FTP_SOCKET, SOCKET_TIMEOUT);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 6. On transmet le message de fin de la transaction (226) */
|
|
|
|
|
strcpy(response, STOP_DAT_MSG);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* (9) Fin de transfert de données (fermeture SOCKETS du BUS DE DONNEES)
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
case 226:
|
|
|
|
|
strcpy(response, "226 Fin de la transaction!\r\n");
|
|
|
|
|
close(*DUSER_SOCKET);
|
|
|
|
|
close(*DFTP_SOCKET);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* (n) Commande inconnue
|
|
|
|
|
--------------------------------------------*/
|
|
|
|
|
default:
|
|
|
|
|
strcpy(response, pAnswer);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* [3] Retour de la réponse
|
|
|
|
|
================================================*/
|
|
|
|
|
strcpy(pAnswer, response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int WAIT_SOCKET_UPDATE(int* pSocket, char* pBuffer){
|
2017-04-01 15:01:36 +00:00
|
|
|
|
memset(pBuffer, 0, MAX_BUF_LEN); // on vide le buffer
|
2017-03-28 16:45:18 +00:00
|
|
|
|
|
|
|
|
|
int nbRead = 0;
|
|
|
|
|
|
|
|
|
|
do{
|
|
|
|
|
nbRead = sread(pSocket, pBuffer);
|
|
|
|
|
|
|
|
|
|
// si on est déconnecté, on renvoie une erreur
|
|
|
|
|
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;
|
|
|
|
|
}
|