Programme passerelle dans le cadre du projet Prosecco
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

347 lignes
9.4 KiB

  1. /* notre passerelle TCP IPv4 */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdint.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <sys/socket.h>
  11. #include <arpa/inet.h>
  12. #include <signal.h>
  13. #include <sys/wait.h>
  14. #include <netdb.h>
  15. #include <pthread.h>
  16. #include "pass.h"
  17. #include "chiffrePF.h"
  18. /* les variables globales */
  19. int RUN=1; /* Indice qui permet de stopper en le mettant a zero */
  20. int Chiff=0; /* =0 rien; =1 chiff. distant =-1 chiff. local */
  21. in_port_t PORTL, PORTD; /* au format du reseau !! */
  22. uint32_t ADDRD; /* adressse distante au format du reseau */
  23. long long CLE = 0xABCD1276FA8745EC;
  24. void interrupt(int S)
  25. {
  26. switch(S) {
  27. case SIGCHLD :
  28. while (waitpid(-1,NULL,WNOHANG) != -1);
  29. break;
  30. case SIGINT:
  31. case SIGTERM:
  32. fprintf(stderr,"Arret de la passerelle !\n");
  33. exit(0);
  34. default:
  35. fprintf(stderr,"Recu signal %d !?!?\n",S);
  36. }
  37. return;
  38. }
  39. /* la structure sockaddr_in */
  40. struct sockaddr_in Sin = { AF_INET }; /* Le reste de egal à 0 !! */
  41. /* fct qui fabrique un IP v4 au format reseau
  42. exemple : makip4(127,0,0,1); */
  43. uint32_t makip4(int a, int b, int c, int d)
  44. {
  45. uint32_t A;
  46. char *p;
  47. p = (char *)&A;
  48. *p++ = (unsigned char)a;
  49. *p++ = (unsigned char)b;
  50. *p++ = (unsigned char)c;
  51. *p = (unsigned char)d;
  52. //return htonl(A);
  53. return A;
  54. }
  55. /* fct qui traduit une adresse IP V4 en chaine de caractere xxx.xxx.xxx.xxx */
  56. char * adip(uint32_t A)
  57. {
  58. static char b[16];
  59. sprintf(b,"%d.%d.%d.%d", (int)((A>>24)& 0xFF), (int)((A>>16)& 0xFF), (int)((A>>8)& 0xFF), (int)(A & 0xFF));
  60. return b;
  61. }
  62. int readNbc(int fd, char*b, int t)
  63. {
  64. char * d;
  65. int n, T=t;
  66. #ifdef TRACESP
  67. printf(" readNbc %d octets !\n",t);
  68. #endif
  69. d=b;
  70. while(T>0) {
  71. if ((n=read(fd,d,T)) == -1) return -1;
  72. d+=n;
  73. T-=n;
  74. }
  75. return 0;
  76. }
  77. int SidLoc, SidDist; /* variables globales des 2 taches de transfert */
  78. /* gestion des cles a partir d'un fichier externe */
  79. char *NFCLE="/tmp/clepass";
  80. /* ATTENTION choisir LCLE tel que = 8*n !!! */
  81. #define LCLE 8192 /* 8 ko => cle de 65536 bits !! */
  82. char BCLE[LCLE]; /* buffer contenant la cle */
  83. /* fchiffre3 utilise les fonction PF */
  84. void fchiffre3(char * b, int l, int ori)
  85. {
  86. if (ori) PF_chiffreD(b,l);
  87. else PF_dechiffreD(b,l);
  88. }
  89. /* on suppose dans tout le code que la fct de chiffrement est telle que
  90. fchiffre(fchiffre(buf)) = buf !! autrement dit qu'elle est involutive ! */
  91. void fchiffre2(char * b, int l, int ori) /* travaille avec BCLE */
  92. {
  93. long long *d, *f, *c, *fc;
  94. d=(long long*)b;
  95. f=(long long*)(b+l);
  96. c=(long long *)BCLE;
  97. fc=(long long *)(BCLE+LCLE);
  98. /* le chiffrement avec xor */
  99. while (d<f) {
  100. *d++ ^= *c++; /* equiv. *d ^= *c; d++; c++; */
  101. if (c==fc) c=(long long *)BCLE;
  102. }
  103. return; /* pour l'instant ne fait rien !! */
  104. }
  105. int initCle(void)
  106. {
  107. PF_init("Salut");
  108. /* si on utilise fchiffre2() !!
  109. int fd;
  110. if ((fd = open(NFCLE,O_RDONLY)) == -1) return -1;
  111. if (read(fd,BCLE, LCLE) != LCLE) return -1;
  112. close(fd);
  113. *******************/
  114. return 0;
  115. }
  116. void fchiffre(char * b, int l, int ori) /* travaille avec CLE de 64 bits */
  117. {
  118. long long *d, *f;
  119. d=(long long*)b;
  120. f=(long long*)(b+l);
  121. /* le chiffrement avec xor */
  122. while (d<f) *d++ ^= CLE;
  123. #ifdef TRACECH
  124. if (ori==0) { /* le thread L -> D */
  125. if (Chiff==1) printf("Chiffrement l=%d vers %d !\n",l,ntohs(PORTD));
  126. else printf("Dechiffrement l=%d depuis %d !\n",l,ntohs(PORTL));
  127. } else { /* le fils D -> L */
  128. if (Chiff==1) printf("Dechiffrement l=%d depuis %d !\n",l,ntohs(PORTD));
  129. else printf("Chiffrement l=%d vers %d !\n",l,ntohs(PORTL));
  130. }
  131. #endif
  132. return; /* pour l'instant ne fait rien !! */
  133. }
  134. /* la fonction du thread qui lit le port local et ecrit vers le port distant */
  135. void * fct_th(void * p)
  136. {
  137. int n;
  138. uint16_t lb;
  139. char buf[LBUF];
  140. /* on s'occupe du transfert L -> D */
  141. while (1) {
  142. /* lecture cote LOCAL */
  143. if (Chiff == -1) { /* chiffrement cote local */
  144. if (read(SidLoc,&lb,2)!=2) n=-1;
  145. else {
  146. n = (int)ntohs(lb);
  147. if (readNbc(SidLoc,buf,n) == -1) n=-1;
  148. /* on pourrait faire varier le chiffrement dans le code en faisant :
  149. #ifdef CHIF_V1
  150. fchiffre(buf,n,0);
  151. #endif
  152. #ifdef CHIF_V2
  153. fchiffre2(buf,n,0);
  154. #endif
  155. etc .... *************************************************/
  156. /* on dechiffre */
  157. fchiffre3(buf,n,0);
  158. }
  159. } else
  160. n=read(SidLoc,buf,LBUF);
  161. if (n > 0) {
  162. /* ecriture cote DISTANT */
  163. if (Chiff == 1) {
  164. #ifdef TRACESP
  165. printf(" writeNbc %d octets !\n",n);
  166. #endif
  167. /* on chiffre */
  168. fchiffre3(buf,n,1);
  169. lb = htons((uint16_t)n);
  170. write(SidDist,&lb,2); /* on envoie le nb d'octets du paquet */
  171. }
  172. write(SidDist,buf,n);
  173. }
  174. if (n==-1) break;
  175. }
  176. return NULL;
  177. }
  178. int liaison(int fd) /* il faut creer la passerelle pour le client */
  179. {
  180. int sid,n ;
  181. uint16_t lb;
  182. struct sockaddr_in Sin = { AF_INET };
  183. pthread_t thid;
  184. char buf[LBUF];
  185. /* on est dans le cas du client qui veut se connecter au serveur */
  186. /* fabrication de l'interface reseau en IP V4 */
  187. SidLoc = fd; /* pour que le thread l'utilise */
  188. if ((sid = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  189. perror("socket"); return 1;
  190. }
  191. Sin.sin_port = PORTD;
  192. Sin.sin_addr.s_addr = ADDRD;
  193. /* on fait la connexion */
  194. if (connect(sid, (struct sockaddr*)&Sin, sizeof(Sin)) < 0) {
  195. perror("connect"); return 2;
  196. }
  197. /* on masque le signal SIGPIPE */
  198. signal(SIGPIPE,SIG_IGN);
  199. /* la connexion est faite ! */
  200. SidDist = sid; /* pour que le thread l'utilise */
  201. /* creation du thread qui va se charger du transfert L -> D */
  202. if (pthread_create(&thid,NULL,fct_th,NULL) !=0) {
  203. fprintf(stderr,"Erreur creation thread !\n");
  204. close(fd);
  205. close(sid);
  206. return 3;
  207. }
  208. /* on s'occupe du transfert D -> L */
  209. while (1) {
  210. if (Chiff == 1) { /* chiffrement cote distant */
  211. if (read(sid,&lb,2)!=2) n=-1;
  212. else {
  213. n = (int)ntohs(lb);
  214. if (readNbc(sid,buf,n) == -1) n=-1;
  215. /* on dechiffre */
  216. fchiffre3(buf,n,0);
  217. }
  218. } else n=read(sid,buf,LBUF);
  219. if (n > 0) {
  220. if (Chiff==-1) {
  221. #ifdef TRACESP
  222. printf(" writeNbc %d octets !\n",n);
  223. #endif
  224. /* on chiffre */
  225. fchiffre3(buf,n,1);
  226. lb = htons((uint16_t)n);
  227. write(fd,&lb,2); /* on envoie le nb d'octets du paquet */
  228. }
  229. write(fd,buf,n);
  230. }
  231. if (n==-1) break;
  232. }
  233. close(fd);
  234. return 0;
  235. }
  236. void finerr(char * N, int err)
  237. {
  238. fprintf(stderr,"%s : version %s\n",N,Version);
  239. fprintf(stderr,"Utilisation : %s -d|-l|-s port_local nom_ou_ip_serveur port_distant !\n",N);
  240. exit(err);
  241. }
  242. int main(int N, char *P[])
  243. {
  244. int sid, newsid, err; /* socket id = file descriptor */
  245. struct sockaddr_in Srec;
  246. struct hostent *h;
  247. pid_t pid;
  248. long lg;
  249. signal(SIGCHLD,interrupt);
  250. signal(SIGINT,interrupt);
  251. signal(SIGTERM,interrupt);
  252. if (initCle()) {
  253. fprintf(stderr,"Erreur lecture ficher cle %s !!\n", NFCLE);
  254. return 1;
  255. }
  256. /* verification que l'on a bien 4 parametres et seult 4 ! */
  257. if (N != 5) finerr(P[0],1);
  258. /* verification du 1er parametres */
  259. if (P[1][0] != '-') finerr(P[0],2);
  260. if (strlen(P[1]) != 2) finerr(P[0],2);
  261. switch(P[1][1]) {
  262. case 'l':
  263. Chiff = -1;
  264. break;
  265. case 'd':
  266. Chiff = 1;
  267. break;
  268. case 's':
  269. Chiff = 0;
  270. break;
  271. default :
  272. finerr(P[0],2);
  273. }
  274. PORTL = htons(atoi(P[2]));
  275. PORTD = htons(atoi(P[4]));
  276. if ((h=gethostbyname(P[3])) == NULL) {
  277. fprintf(stderr,"Erreur gethostbyname no %d !\n",h_errno);
  278. return 2;
  279. }
  280. bcopy((void*)(h->h_addr),(void*)(&ADDRD),h->h_length);
  281. /* fabrication de l'interface reseau en IP V4 */
  282. if ((sid = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  283. perror("socket"); return 5;
  284. }
  285. /* initialiser la structure sockaddr_in pour dire quel port on veut */
  286. Sin.sin_port = PORTL;
  287. /* Sin.sin_addr.s_addr = makip4(127,0,0,1); */
  288. Sin.sin_addr.s_addr = makip4(0,0,0,0);
  289. /* puis faire un bind() pour s'attacher a ce port */
  290. if (bind(sid,(struct sockaddr *)&Sin,sizeof(Sin)) == -1) {
  291. perror("bind"); return 3;
  292. }
  293. /* on definit le nombre d'ecoutes simultannees */
  294. if (listen(sid, NBCLI) == -1) {
  295. perror("listen"); return 4;
  296. }
  297. while(RUN) { /* on attend le clients locaux pour transmettre les donnees */
  298. lg = sizeof(Sin);
  299. if ((newsid=accept(sid,(struct sockaddr *)&Srec, (socklen_t*)&lg))<0){
  300. perror("accept");
  301. } else {
  302. /* message pour informer qui se connecte */
  303. #ifdef TRACE_1
  304. printf("Connexion de %s !\n",adip(ntohl(Srec.sin_addr.s_addr)));
  305. #endif
  306. /* creation du processus dedie au client */
  307. if ((pid = fork()) == -1) {
  308. perror("fork");
  309. write(newsid,"Erreur passerelle !\n",18);
  310. } else {
  311. if (pid==0) { /* code du fils */
  312. err=liaison(newsid);/* creation passerelle privee pour client */
  313. if (err) printf("Erreur liaison %d !\n",err);
  314. return err;
  315. }
  316. /* suite du pere : ie passerelle principale */
  317. }
  318. close(newsid);
  319. }
  320. }
  321. return 0; /* fin OK */
  322. }