PSR SE2a4 2022/2023 G2 : Différence entre versions

De Wiki d'activités IMA
(4) Debug SMTPin -> envoyer les mails)
(5) Tester les limites de SMTPin)
Ligne 247 : Ligne 247 :
 
== 5) Tester les limites de SMTPin ==
 
== 5) Tester les limites de SMTPin ==
  
*Tester les limites de SMTPin en rentrant des syntaxes fausses (addresse mail ERONNEE ou msg faux comme RCPPT TO:)
+
*Je réussis désormais à envoyer des mails sur @polytech_lille.net mais pas sur @gmail.com (le prob se situe au niveau des MX).
 +
*On va maintenant tester les limites de SMTPin en rentrant des syntaxes fausses (addresse mail ERONNEE ou msg faux comme RCPPT TO:)
 +
 +
 
 +
 
 +
 
 +
 
 +
On peut désormais envoyer des mails ! HELO jeje MAIL FROM: goudale@lamentable.site RCPT TO: jerome.breuvart@polytech-lille.net DATA: OBJECT Bonjour, coucou. QUIT
  
 
Il faut appuyer 2 fois sur QUIT pour quitter le serveur -- to debug ???
 
Il faut appuyer 2 fois sur QUIT pour quitter le serveur -- to debug ???

Version du 7 juin 2023 à 16:03

A faire

  • un système doit être réalisé permettant au serveur SMTP sortant de mettre en file d’attente les messages non remis à destination pour cause d’erreur transitoire du serveur SMTP cible;
  • les communications peuvent ne pas être chiffrées, les communications non chiffrés sont reçues sur le port 25 ;
  • les communications peuvent être chiffrées par TLS, les communication chiffrées peuvent être négociées directement sur le port 465 ;
  • il doit être possible de basculer sur une communication chiffrée à partir du port 25 en utilisant les commandes EHLO et STARTTLS ;
  • ne doivent être stockés que les courriels à destination d’un utilisateur local ;
  • le processus de remise stocke le message dans le sous-répertoire Maildir/tmp puis le déplace dans le sous-répertoire Maildir/new, déplacement doit être fait par la primitive rename ;
  • pour assurer un nom unique aux fichiers de stockage, utilisez la date en seconde (fonction time), le PID et un compteur commun à tous les flux d’exécution (utilisation de sémaphores indispensable).

Commandes sur la VM

  • Se connecter au serveur : ssh root@capbreton.plil.info (glopglop)
  • Se connecter à la VM : ssh root@193.48.57.164 (glopglopglop)
  • Copier le projet dans la VM (à la racine) : scp - r LisaJerome/ root@193.48.57.164:/
  • Ouvrir le terminal en mode root : "su -" et vérifier si le port 25 est déjà occupé : ss -tpln
  • Arrêter le processus exim4 (qui utilise le port 25) : service exim4 stop (ou kill pid)
  • Compiler le projet (à la racine du projet) : make clean + make debug*
  • SMTPin (serveur d'envoi de mail)
    • Exécuter SMTPin sur l'interface loopback du port 25 avec strace strace ./SMTPin -l -j <logfile.txt> et s'y connecter en local nc localhost 25
  • SMTPout (serveur de réception de mail)
    • Exécuter SMTPout sur l'interface eth0 du port 25 strace ./SMTPout -i eth0 -u <carte.txt> et s'y connecter via nc 193.48.57.164 25

1) Debug SMTPin

  • Dans SMTPin ==> "mx.c" ne sert à rien (il est vide d'ailleurs), la fonction "**chercherMX" est implémentée dans "libs/Reseau/mx.c", on peut donc le supprimer.
  • Dans SMTPin ==> "in.c" -> fonction "gestionCourriel", une fois les enregistrements DNS de type MX (serveurs courriel) trouvés, on envoie le courriel au MX qui a la priorité la plus basse, si l'envoi échoue on retente avec le MX de priorité suivante jusqu'à ce que l'envoi soit un succès. Pourtant si l'envoi est un succès, on continue d'envoyer le mail aux autres MX, il faut donc rajouter l'instruction else{break;} dans le code lorsque l'envoi est un succès.
 while(*p!=NULL){
   #ifdef DEVERMINE
     printf("Serveur : %s\n",*p);
   #endif
   int ss=connexionServeur(*p,SMTP_PORT_DEFAULT);
   FILE *dialogue=fdopen(ss,"a+");
   if(dialogue==NULL){
     perror("gestionCourriel.fdopen");
     exit(EXIT_FAILURE);
   }
   char erreur[MAX_ERREUR];
   int resultat=SMTP_dialogue(dialogue,donnees,erreur,MAX_ERREUR);
   fclose(dialogue);
   if(resultat<0) ecritureJournal(JOURNIV_DEVERMINE,JOURNAL_MXHS,*p);
   // Logguer l'erreur
   else{break;}
   p++;
   }

2) Modifications SMTPout

  • On doit stocker les courriels dans la structure de répertoire MAILDIR, composée de 3 sous-répertoires : tmp, new et cur. Le processus qui récupère les courriels place les courriels dans le répertoire tmp, le nom du fichier est généré automatiquement de manière à être unique. Une fois le message complètement reçu par le serveur de courriel (MTA), il est déplacé, par un système de link/unlink dans le répertoire new. Au passage du client de messagerie qui parcourt le répertoire new, il est à nouveau déplacé et est mis dans le répertoire cur. Le message n'a toujours pas été lu.
  • Dans "outc.c" -> fonction "gestionCourriel", on déplace le sous-répertoire Maildir/tmp dans le sous-repertoire Maildir/new en utilisant la primitive rename
 char fichier[MAX_CHEMIN];
 sprintf(fichier,"%s/%s/%s/%ld_%010d_%010ld",dossier,id,MAILDIR_TMP,time(NULL),pid,messages);
 FILE *f=fopen(fichier,"w");
 if(f==NULL){
   ecritureJournal(JOURNIV_ERREUR,JOURNAL_OUVERTURE,fichier);
   return;
 }
 int nb=fwrite(donnees->corps,donnees->taille,1,f);
 if(nb!=1){
   ecritureJournal(JOURNIV_ERREUR,JOURNAL_ECRITURE,fichier);
   return;
 }
 fclose(f);
 char fichier_new[MAX_CHEMIN];
 sprintf(fichier_new,"%s/%s/%s/%ld_%010d_%010ld",dossier,id,MAILDIR_NEW,time(NULL),pid,messages);
 rename(fichier, fichier_new);

3) Exécuter les 2 serveurs sur une interface différente du port réseau 25

Après avoir créé la VM (routable sur internet) sur le serveur capbreton.plil.info et y avoir copié le prog, on s'aperçoit qu'il n'est pas possible de lancer les 2 serveurs SMTPin et SMTPout en même temps car les 2 s'exécutent sur la même interface du port 25. Il faut donc lancer les serveurs sur des interfaces diff (SMTPout : eth0, SMTPin : loopback).


  • SMPTout(args.h) => ajout d'une variable "interface" à la structure "stmp_config
struct smtp_config
 {
   char journal[CONFIG_MAX_JOURNAL];
   int niveau;
   char port[CONFIG_MAX_PORT];
   char dossier[CONFIG_MAX_CHEMIN];
   char carte[CONFIG_MAX_CHEMIN];
   unsigned char local;
   char interface[CONFIG_MAX_INTERFACE];
 };


  • SMPTout (args.c) => ajout d'un case i "interface" dans le switch
static struct option long_options[] = {
   {"local",no_argument,0,'l'},
   {"interfaces", required_argument,0, 'i'},
   {"port",required_argument,0,'p'},
   {"journal",required_argument,0,'j'},
   {"niveau",required_argument,0,'n'},
   {"dossier",required_argument,0,'d'},
   {"utilisateurs",required_argument,0,'u'},
   {0,0,0,0}
   };
 while(1){
   int c=getopt_long(argc,argv,"lp:j:n:d:u:i:",long_options,NULL);
   if(c<0) break;
   switch(c){
     case 'l':
       config->local=1;
       break;
     case 'i':
     strncpy(config->interface,optarg,sizeof(config->interface)-1);
     break;
     case 'p':
       strncpy(config->port,optarg,sizeof(config->port)-1);
       break;
     case 'j':
       strncpy(config->journal,optarg,sizeof(config->journal)-1);
       break;
     case 'd':
       strncpy(config->dossier,optarg,sizeof(config->dossier)-1);
       break;
     case 'u':
       strncpy(config->carte,optarg,sizeof(config->carte)-1);
       break;
     case 'n':
       config->niveau=atoi(optarg);
       break;
     default:
       afficheSyntaxe(argv[0]);
       break;
     }
   }


  • SMPTout (out.c) ==> main function => récupérer l'interface passée en paramètre
 char *interface=NULL;
 struct smtp_config config;
 analyseArguments(argc,argv,&config);
 if(config.journal[0]!='\0') creationJournal(config.journal);
 niveauJournal(config.niveau);
 ecritureJournal(JOURNIV_INFO,JOURNAL_DEBUT);
 if(config.port[0]=='\0') strcpy(config.port,SMTP_PORT_DEFAULT);
 if(config.local==1) interface=SMTP_LOCAL_INTERFACE;
 if(config.interface!=NULL) interface=config.interface;

4) Debug SMTPin -> envoyer les mails

Malgré le fait qu'on ait trouvé le serveur sur lequel envoyer notre mail et qu'on se soit bien connecté à celui-ci via socket grâce à la fonction "connexionserveur" dans "/libs/Reseau/reseau.c, on remarque que les mails ne s'envoient pas. On debug donc l'envoi du message.

  • libs/SMTP/smtp.c -> ajout DEBUG :
 static int retour_generique(FILE *dialogue,int succes,char *erreur,int taille){
   char ligne[MAX_LIGNE];
   #ifdef DEVERMINE
     printf("SMTP -> retour generique\n");
   #endif
   if(fgets(ligne,MAX_LIGNE,dialogue)==NULL) return -1;
   ligne[MAX_LIGNE-1]='\0';
   int code;
   int statut=sscanf(ligne,"%d",&code);
   #ifdef DEVERMINE
     printf("statut =%d\n", statut);
     printf("succes =%d\n", succes);
     printf("code =%d\n", code);
   #endif
   if(statut==1 && code!=succes){
     strncpy(erreur,ligne,taille-1);
   #ifdef DEVERMINE
     printf("retour_generique ERROR\n");
   #endif
   }
 return (statut==1 && code==succes)?0:-1;
 }

Ce qui nous donne les informations de debug suivantes:

 #0 [50/woody.escaut.net]
 Serveur : woody.escaut.net
 SMTP -> dialogue_connexion
   SMTP -> retour generique
   statut =1
   succes =250
   code =220
 SMTP -> dialogue_HELO
   SMTP -> retour generique
   statut =1
   succes =250
   code =250
 SMTP -> dialogue_MAIL
   SMTP -> retour generique
   statut =1
   succes =250
   code =250
 SMTP -> dialogue_RCPT
   SMTP -> retour generique
   statut =1
   succes =250
   code =250
 SMTP -> dialogue_DATA
   SMTP -> retour generique
   statut =1
   succes =250
   code =354
 SMTP -> dialogue_QUIT
   SMTP -> retour_generique
   statut =1
   succes =221
   code =250

On remarque donc que la fonction "dialogue_connexion" attend un code de succès 220 au lieu de 250, "dialogue_DATA" 354 au lieu de 250 et "dialogue_QUIT" 250 au lieu de 221.

  • On modifie alors les valeurs des variables globales définies dans "smtp_private.h":
 #define ACCUEIL_CODE            220
 ...
 #define SUCCES_DATA_CODE        250
 #define SUCCES_DATA_TEXTE       "Accepted"
 #define SUCCES_QUIT_CODE        250
 #define SUCCES_QUIT_TEXTE       "Bye!"
  • ainsi que les noms des variables globales dans "smtp.c":
 static int dialogue_DATA(FILE *dialogue,char *corps,char *erreur,int taille){
   #ifdef DEVERMINE
     printf("SMTP -> dialogue_DATA\n");
   #endif
   if(fprintf(dialogue,"DATA\r\n")<0) return -1;
   if(fprintf(dialogue,corps)<0) return -1;
   if(fprintf(dialogue,".\r\n")<0) return -1;
   return retour_generique(dialogue,CONTINUE_DATA_CODE,erreur,taille);
 }


+ modifier fgets dans libs/SMTP.c, gérer la gestion d'une commande à deux lignes : si présence d'un tiret dans la quatrième colonne, il faut prendre en compte la commande complète

On peut désormais envoyer des mails ! HELO jeje MAIL FROM: goudale@lamentable.site RCPT TO: jerome.breuvart@polytech-lille.net DATA: OBJECT Bonjour, coucou. QUIT

PI je réussis à envoyer un mail à @polytech_lille.net mais pas à @gmail.com (le prob se situe au niveau des MX)

5) Tester les limites de SMTPin

  • Je réussis désormais à envoyer des mails sur @polytech_lille.net mais pas sur @gmail.com (le prob se situe au niveau des MX).
  • On va maintenant tester les limites de SMTPin en rentrant des syntaxes fausses (addresse mail ERONNEE ou msg faux comme RCPPT TO:)



On peut désormais envoyer des mails ! HELO jeje MAIL FROM: goudale@lamentable.site RCPT TO: jerome.breuvart@polytech-lille.net DATA: OBJECT Bonjour, coucou. QUIT

Il faut appuyer 2 fois sur QUIT pour quitter le serveur -- to debug ???

6) Comment exécuter SMTPout ?

  • out.c -> gestionCourriel() -> on s'aperçoit que le serveur écrit le mail dans /tmp/<user>/tmp mais il ne le crée pas, il faut donc le créer manuellement.
  • out.c -> stockeInit() -> on s'apperçoit que le serveur a besoin d'une carte des utilisateur pour fonctionner, il faut donc exécuter le serveur avec cette carte contenant nos utilisateurs.

On doit aussi écrire une carte utilisateur pour que le fonctionne.

Puisqu'on exécute le serveur SMTPout sur l'interface eth0 du port 25 (au lieu de l'interface locale loopback), alors on ne peut pas se connecter au serveur en localhost (nc localhost 25) mais depuis l'extérieur de la VM (nc localhost 193.48.57.164 25).


Créer l'architecture de répertoires MAILDIR et le fichier carte.txt à lancer en argument avec -u, Tester tout ça une fois que ma VM est en ligne.

Comment me reconnecter à ma VM ? ssh ?

nc 193.48.57.164 25 RCPT TO : jean@lamentable.site