651 lines
20 KiB
C
651 lines
20 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <sys/ioctl.h>
|
|
#include "errno.h"
|
|
#include <arpa/inet.h>
|
|
#include <openssl/ssl.h>
|
|
|
|
/* compilation : gcc -o api api.c -Wall -lssl -lcrypto */
|
|
|
|
/* ./apid 50000 cert.pem server.key 0 */
|
|
|
|
char * flog = NULL;
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
char * certificat;
|
|
char * cleprivee;
|
|
|
|
// comm ssl
|
|
long mSockServeur; // 1 socket serveur mere en ecoute, 0 socket serveur fille connectee
|
|
int mSocket; // socket creee
|
|
int mSecu; // si comm securise (TLS OpenSSL)
|
|
unsigned int mIpClient; // ip du client qui se connecte (socket type 1 uniquement)
|
|
char mIp[16];
|
|
long mDateExpirationCert; // aaaammjjhhmmss
|
|
|
|
sigset_t mOldBlockSig,mBlockSig; // gestion des signaux sur socket serveur en ecoute
|
|
|
|
SSL_CTX * mSslCtx; /* contexte SSL */
|
|
SSL * mClientSsl; /* etat SSL du client */
|
|
|
|
|
|
// process
|
|
int mServeur; // TRUE si serveur, FALSE si client ou fork fils du serveur
|
|
int mFin; // pour arret du process
|
|
int mSignal; // indique si fin demandee par un signal (kill ou dmd arret depuis le serveur)
|
|
long mNbFils; // > 0 si serveur
|
|
long mPid; // pid du process
|
|
|
|
// -----------------------------------------------------------
|
|
void trace(const char * fmt, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
if(flog)
|
|
{
|
|
if(*flog == '0') return; // si fichier log = "0" : ne rien afficher ni logguer
|
|
//
|
|
FILE * f = fopen(flog, "a+");
|
|
if(f)
|
|
{
|
|
fprintf(f, "%s%d%s", mServeur ? "Serveur " : "Cnx ", getpid(), ": ");
|
|
vfprintf(f, fmt, args);
|
|
fclose(f);
|
|
}
|
|
else
|
|
{
|
|
printf("%s%d%s", mServeur ? "Serveur " : "Cnx ", getpid(), ": ");
|
|
vprintf(fmt, args);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("%s%d%s", mServeur ? "Serveur " : "Cnx ", getpid(), ": ");
|
|
vprintf(fmt, args);
|
|
}
|
|
va_end(args);
|
|
}
|
|
|
|
// -----------------------------------------------------------
|
|
void libereSecu()
|
|
{
|
|
if(!mSecu)
|
|
return;
|
|
// libere les ressources d'OpenSSL
|
|
if(mClientSsl != NULL)
|
|
{
|
|
SSL_shutdown(mClientSsl);
|
|
/* liberation liee a openssl */
|
|
SSL_free(mClientSsl);
|
|
}
|
|
//
|
|
if(mSslCtx != NULL)
|
|
SSL_CTX_free(mSslCtx);
|
|
/* EVP_cleanup(); */ /* ?? */
|
|
mSecu = FALSE;
|
|
}
|
|
|
|
void arret(int socket, int forceShutdown)
|
|
{
|
|
if(mSecu)
|
|
libereSecu();
|
|
if(0)
|
|
shutdown(socket, 2);
|
|
close(socket);
|
|
}
|
|
|
|
int ssl_verify(int ok, X509_STORE_CTX * ctx)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int secuSocket()
|
|
{
|
|
int cr;
|
|
if((mClientSsl = SSL_new(mSslCtx)) == NULL)
|
|
{
|
|
trace("Erreur SSL_new\n");
|
|
/* erreur gestion etat SSL */
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
if(!SSL_set_fd(mClientSsl, mSocket))
|
|
{
|
|
trace("Erreur SSL_set_fd\n");
|
|
/* erreur assoc socket */
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
if((cr = SSL_accept(mClientSsl)) <= 0) /* accept pour la partie "serveur" */
|
|
{
|
|
int sslcr, cpt = 0;
|
|
/* erreur acceptation requetes SSL */
|
|
sslcr = SSL_get_error(mClientSsl, cr);
|
|
while(cr != 1 && sslcr == 2 && cpt < 3)
|
|
{
|
|
/* */
|
|
cpt++;
|
|
cr = SSL_accept(mClientSsl);
|
|
sslcr = SSL_get_error(mClientSsl, cr);
|
|
}
|
|
if(cr != 1)
|
|
{
|
|
trace("Erreur SSL_accept, code %d error %d\n", sslcr, errno);
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int securise(char * certificat, char * privateKey, int socket)
|
|
{
|
|
mSslCtx = NULL;
|
|
mClientSsl = NULL;
|
|
if(1)
|
|
{
|
|
if((mSslCtx = SSL_CTX_new(TLS_server_method())) == NULL)
|
|
{
|
|
trace("Erreur SSL_CTX_new\n");
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
SSL_CTX_set_options(mSslCtx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_COMPRESSION);
|
|
/* pas de controle du client ici par certificat (login/mdp ou sso) */
|
|
SSL_CTX_set_verify(mSslCtx, SSL_VERIFY_NONE, NULL); // NULL a la place de "ssl_verify" ??
|
|
/* pas de reutilisation de session (mode par defaut normalement) */
|
|
SSL_CTX_set_session_cache_mode(mSslCtx, SSL_SESS_CACHE_OFF);
|
|
/* */
|
|
SSL_CTX_set_ecdh_auto(mSslCtx, 1);
|
|
/* */
|
|
if (SSL_CTX_use_certificate_file(mSslCtx, certificat, SSL_FILETYPE_PEM) <= 0)
|
|
{
|
|
trace("Erreur SSL_CTX_use_certificate_file\n");
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
if (SSL_CTX_use_PrivateKey_file(mSslCtx, privateKey, SSL_FILETYPE_PEM) <= 0)
|
|
{
|
|
trace("Erreur SSL_CTX_use_PrivateKey_file\n");
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
if (!SSL_CTX_check_private_key(mSslCtx))
|
|
{
|
|
trace("Erreur SSL_CTX_check_private_key\n");
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
mSecu = TRUE;
|
|
if(socket)
|
|
{
|
|
return secuSocket();
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* client */
|
|
/* option "non bloquant" empeche le bon fonctionnement en securise : remettre bloquant */
|
|
int ret, arg = 0;
|
|
ioctl(mSocket, FIONBIO, &arg); /* socket bloquant (arg = 0) */
|
|
if((mSslCtx = SSL_CTX_new(TLS_client_method())) == NULL)
|
|
{
|
|
libereSecu();
|
|
return FALSE; /* erreur creation contexte SSL */
|
|
}
|
|
if((mClientSsl = SSL_new(mSslCtx)) == NULL)
|
|
{
|
|
/* erreur gestion etat SSL */
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
SSL_set_fd(mClientSsl, mSocket);
|
|
if((ret = SSL_connect(mClientSsl)) != 1) /* connect pour partie "client" */
|
|
{
|
|
/* erreur connexion a un serveur TLS/SSL */
|
|
libereSecu();
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
int creerServeur(long port)
|
|
{
|
|
struct sockaddr_in addr;
|
|
struct linger l_s; /* Structure pour setsockopt */
|
|
int sockopt, sock, buf = 64000; /* taille buffer send/rec = 64 ko environ */
|
|
int arg = 1; /* pour ioctl */
|
|
// cree une socket serveur prete a ecouter
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
addr.sin_port = htons(port);
|
|
/* mise en place de la socket serveur d'ecoute */
|
|
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
|
{
|
|
trace("Erreur creation socket\n");
|
|
return FALSE; // erreur
|
|
}
|
|
ioctl(sock, FIONBIO, &arg); /* socket non bloquant (sys/ioctl.h) */
|
|
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int))) /* pour eliminer une erreur : permet de rouvrir des socket suite a fermeture avec des clients encore connectes */
|
|
{
|
|
trace("Erreur setsockopt SO_REUSEADDR\n");
|
|
/* erreur */
|
|
close(sock);
|
|
return FALSE;
|
|
}
|
|
if(setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&buf, sizeof(buf)))
|
|
{
|
|
trace("Erreur setsockopt SO_RCVBUF\n");
|
|
/* erreur */
|
|
close(sock);
|
|
return FALSE;
|
|
}
|
|
if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&buf, sizeof(buf)))
|
|
{
|
|
trace("Erreur setsockopt SO_SNDBUF\n");
|
|
/* erreur */
|
|
close(sock);
|
|
return FALSE;
|
|
}
|
|
// linger n'impacte QUE le close de la socket
|
|
l_s.l_onoff = 1;
|
|
l_s.l_linger = 0; // les 2 valeurs provoquent un close avec retour immediat, sans traiter les donnees eventuelles en attente d'envoi et envoi RST au client s'il est connecte en TCP
|
|
if(setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&l_s, sizeof (l_s)))
|
|
{
|
|
trace("Erreur setsockopt SO_LINGER\n");
|
|
/* erreur */
|
|
close(sock);
|
|
return FALSE;
|
|
}
|
|
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
|
{
|
|
trace("Erreur bind, errno %d\n", errno);
|
|
close(sock);
|
|
return FALSE;
|
|
}
|
|
else
|
|
if(listen(sock, 10) < 0)
|
|
{
|
|
trace("Erreur listen\n");
|
|
close(sock);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
mSocket = sock;
|
|
sigemptyset(&mOldBlockSig);
|
|
sigfillset(&mBlockSig);
|
|
return TRUE; // ok
|
|
}
|
|
}
|
|
|
|
long attente(long timeOut)
|
|
{
|
|
fd_set masque; /* struct sur aix */
|
|
struct timeval delai;
|
|
long cr;
|
|
// attend une activite sur la socket, timeOut en 1/10 de sec.
|
|
delai.tv_sec = timeOut / 10; /* x sec */
|
|
delai.tv_usec = (timeOut % 10) * 100000; /* y µsec */
|
|
FD_ZERO(&masque);
|
|
FD_SET(mSocket, &masque);
|
|
//
|
|
if(mSockServeur)
|
|
{
|
|
/* pour que le select() fonctionne a chaque fois (a chaque time-out), il faut remettre à jour */
|
|
/* les variables "delai" et "masque fd" ; il faut aussi imperativement */
|
|
/* bloquer les signaux !! la socket peut etre bloquante (mais il vaut mieux la mettre non bloquante) */
|
|
//sigprocmask(SIG_SETMASK, &mBlockSig, &mOldBlockSig);
|
|
cr = select(mSocket + 1, &masque, NULL, NULL, &delai);
|
|
//sigprocmask(SIG_SETMASK, &mOldBlockSig, NULL);
|
|
}
|
|
else
|
|
{
|
|
while((cr=select(mSocket + 1, &masque, NULL, NULL, &delai)) < 0 && errno == EINTR) errno = 0;
|
|
if(cr > 0)
|
|
cr = FD_ISSET(mSocket, &masque);
|
|
}
|
|
return cr; // si > 0 : ok pour continuer et lire la socket
|
|
}
|
|
|
|
int lireConnexion(char * data)
|
|
{
|
|
int nblu = 0, arg = 1;
|
|
int flagInProgress = FALSE;
|
|
int pas = 2000;
|
|
// lire par paquets de longueur fixe et s'arrêter dès que plus rien à lire
|
|
// lecture par paquets de <pas> octets
|
|
ioctl(mSocket, FIONBIO, &arg); // socket non bloquant (sys/ioctl.h) necessaire quand la longueur n'est pas connue (sinon lire sur la longueur et laisser(?) la socket bloquante)
|
|
do
|
|
{
|
|
//if(!data.ctrl(data.getLen() + pas, TRUE))
|
|
// return FALSE; // erreur mem
|
|
int lg = strlen(data);
|
|
if(lg + pas >= 64000)
|
|
; // TODO : taille maxi du buffer atteinte : quid ??
|
|
while((nblu = SSL_read(mClientSsl, data + lg, pas)) < 0 && errno == EWOULDBLOCK && (strlen(data) == 0 || flagInProgress)) ;
|
|
if(errno == EINPROGRESS) // 115
|
|
flagInProgress = TRUE; // indique un envoi en plusieurs parties : ne plus sortir quand getLen # 0 car lecture pas finie !
|
|
else if(nblu > 0)
|
|
data[lg + nblu] = 0; //data.setLen(data.getLen() + nblu);
|
|
else
|
|
{
|
|
int err = SSL_get_error(mClientSsl, nblu);
|
|
if(err == SSL_ERROR_ZERO_RETURN || err == SSL_ERROR_SYSCALL)
|
|
{
|
|
trace("Fermeture de la connexion par le client\n");
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
//
|
|
} while(nblu > 0);
|
|
return TRUE;
|
|
}
|
|
|
|
int ecrireConnexion(char * data)
|
|
{
|
|
int nbecrit = 0;
|
|
int retSsl;
|
|
do
|
|
{
|
|
nbecrit = SSL_write(mClientSsl, data, strlen(data));
|
|
retSsl = SSL_get_error(mClientSsl, nbecrit);
|
|
// pour gerer les envois partiels de SSLwrite
|
|
} while(retSsl == SSL_ERROR_WANT_WRITE || retSsl == SSL_ERROR_WANT_READ);
|
|
return (nbecrit == strlen(data));
|
|
}
|
|
|
|
void setFin(int fin, int depuisSignal)
|
|
{
|
|
mFin = fin;
|
|
mSignal = depuisSignal;
|
|
}
|
|
|
|
void attenteFinFils()
|
|
{
|
|
if(mNbFils)
|
|
{
|
|
while(waitpid(-1, NULL, WNOHANG) > 0)
|
|
mNbFils--; /* compte tous les fils terminés "en meme temps" (si un fils se termine quand le pere est dans ce handler) */
|
|
}
|
|
}
|
|
|
|
void demandeArretFilsEtAttente()
|
|
{
|
|
/* demander aux fils de s'arrêter */
|
|
kill(0, SIGUSR1); // 0 = tous les process du groupe : tous les fils
|
|
// attente fin fils
|
|
while(mNbFils)
|
|
{
|
|
while(waitpid(-1, NULL, WNOHANG) > 0)
|
|
mNbFils--;
|
|
}
|
|
}
|
|
|
|
void verifierFinFils()
|
|
{
|
|
waitpid(-1, NULL, WNOHANG);
|
|
}
|
|
|
|
void trt_exit()
|
|
{
|
|
// comment sortir ?
|
|
demandeArretFilsEtAttente();
|
|
arret(mSocket, TRUE);
|
|
exit(-2);
|
|
}
|
|
|
|
void trt_sig(int sig)
|
|
{
|
|
switch(sig)
|
|
{
|
|
case SIGCHLD:
|
|
if(mServeur)
|
|
{
|
|
//un process fils se termine (forcement recu par le pere/le serveur)
|
|
attenteFinFils();
|
|
}
|
|
else
|
|
{
|
|
// fin depuis un fils (session client) d'un module/batch : waitpid ?
|
|
}
|
|
break;
|
|
//
|
|
case SIGINT:
|
|
case SIGHUP:
|
|
case SIGQUIT:
|
|
case SIGTERM: // (kill pid)
|
|
mFin = TRUE;
|
|
mSignal = TRUE;
|
|
break;
|
|
//
|
|
case SIGSEGV:
|
|
trt_exit();
|
|
//
|
|
case SIGTTOU:
|
|
break; // ignorer si sortie terminal depuis arriere plan
|
|
//
|
|
case SIGUSR1:
|
|
if(! mServeur)
|
|
{
|
|
mFin = TRUE;
|
|
mSignal = TRUE;
|
|
} // arret des fils a reception de ce signal
|
|
break;
|
|
// pour lister les numeros de signaux, taper "kill -l"
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------
|
|
char data[64000], rep[64000]; // buffer de lecture/ecriture sur la socket securisee
|
|
void trt_connexion()
|
|
{
|
|
FILE * fp;
|
|
//Dynamic req, methode, uri, rep, tmp, fld;
|
|
//long meth, cr, nb;
|
|
int keepAlive;
|
|
//
|
|
*data = 0;
|
|
keepAlive = TRUE;
|
|
while(keepAlive)
|
|
{
|
|
//tmp.let("GET;HEAD;POST");
|
|
//// lire les donnees entrantes sur la socket // pbm ici bloquant : sans doute pbm de longueur attendue !? a tester
|
|
//trace("debut boucle\n");
|
|
if ( ! lireConnexion(data))
|
|
break; // fin du client
|
|
trace("lu:\n%s\n", data);
|
|
if(strstr(data,"keep-alive") == NULL)
|
|
keepAlive = FALSE;
|
|
//
|
|
//strcpy(data, "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Type:text/html\r\nContent-Length:35\r\n\r\n<html><h2>Hello World !</h2></html>");
|
|
remove("/tmp/ttyd.txt");
|
|
system("/root/create_ttyd_session.sh > /tmp/ttyd.txt");
|
|
if((fp = fopen("/tmp/ttyd.txt", "r")) == NULL)
|
|
strcpy(data, "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Type:text/html\r\nContent-Length:97\r\n\r\n<html><h2>Erreur, console de test non disponible, veuillez contacter l'administrateur</h2></html>");
|
|
else
|
|
{
|
|
*data = 0;
|
|
*rep = 0;
|
|
fseek(fp, 0, SEEK_END);
|
|
long lg = ftell(fp);
|
|
fseek(fp, 0, SEEK_SET);
|
|
fread(rep, lg, 1, fp);
|
|
rep[lg] = 0;
|
|
fclose(fp);
|
|
//
|
|
sprintf(data, "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Type:text/html\r\nContent-Length:%ld", lg);
|
|
strcat(data, "\r\n\r\n");
|
|
strncat(data, rep, lg);
|
|
}
|
|
//
|
|
trace("Reponse:\n%s\n", data);
|
|
ecrireConnexion(data);
|
|
*data = 0;
|
|
//// faire une attente passive ici (sinon consomme trop de CPU)
|
|
//trace("Attente fin boucle\n");
|
|
while(attente(10) <= 0 && ! mFin) ;
|
|
//if ( ! lireConnexion(data))
|
|
// break;
|
|
if(mFin)
|
|
break; // sortie sur signal
|
|
}
|
|
trace("fin cnx client\n");
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if(argc != 4 && argc != 5)
|
|
{
|
|
trace("Usage : %s <port> <certificat> <cleprivee> [<fichierlog>]\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
int demon = (argv[0][strlen(argv[0]) - 1] == 'd');
|
|
if(argc == 5)
|
|
{
|
|
flog = argv[4];
|
|
if(*flog != '0')
|
|
remove(flog);
|
|
}
|
|
/* */
|
|
int port = atoi(argv[1]);
|
|
certificat = argv[2];
|
|
cleprivee = argv[3];
|
|
/* */
|
|
mServeur = TRUE;
|
|
mFin = FALSE;
|
|
mSignal = FALSE;
|
|
mPid = getpid();
|
|
mNbFils = 0;
|
|
signal(SIGHUP, trt_sig);
|
|
signal(SIGSEGV, trt_sig);
|
|
signal(SIGINT, trt_sig); /* ctrl-C */
|
|
signal(SIGQUIT, trt_sig);
|
|
signal(SIGTERM, trt_sig);
|
|
signal(SIGTTOU, trt_sig); /* ecriture terminal arriere plan */
|
|
signal(SIGCHLD, trt_sig); /* prevenu quand un process fils se termine */
|
|
signal(SIGUSR1, trt_sig); /* sert a demander au fils de s'arrêter suite arrêt du pere */
|
|
signal(SIGUSR2, trt_sig); /* sert a avertir un fils qu'une requête asynchrone est terminee */
|
|
signal(SIGPIPE, SIG_IGN); /* ignorer ce signal pour eviter une erreur lors du sock.write */
|
|
//
|
|
mSocket = 0;
|
|
mSockServeur = 1;
|
|
mSslCtx = NULL;
|
|
mClientSsl = NULL;
|
|
//
|
|
if(demon)
|
|
{
|
|
if((mPid = fork()) != 0)
|
|
{
|
|
trace("Lancement en tache de fond du process pid %ld\n", mPid);
|
|
exit(0); /* sortie du pere */
|
|
}
|
|
mPid = getpid();
|
|
//chdir("/"); // permet de ne pas bloquer un filesystem avec ce process
|
|
setsid();
|
|
//for(int i=0;i < FOPEN_MAX; i++) /* OPEN_MAX sous AIX */
|
|
// close(i);
|
|
}
|
|
//
|
|
trace("Demarrage serveur, port %d pid %d mode %d bits\n", port, getpid(), sizeof(long)==4?32:64);
|
|
/* initialisations internes openssl */
|
|
SSL_load_error_strings();
|
|
OpenSSL_add_ssl_algorithms();
|
|
// verification du contexte securise avant de continuer
|
|
if( ! securise(certificat, cleprivee, FALSE))
|
|
{
|
|
trace("Erreur lors de la mise en place du contexte securise SSL/TLS\n");
|
|
exit(4);
|
|
}
|
|
else
|
|
{
|
|
libereSecu();
|
|
}
|
|
if(creerServeur(port))
|
|
{
|
|
while( ! mFin)
|
|
{
|
|
if(attente(10) > 0 && ! mFin) // 10 = 1 seconde
|
|
{
|
|
struct sockaddr_in addr_cnx;
|
|
unsigned int size_addr_cnx = sizeof(addr_cnx);
|
|
int sock_fils;
|
|
if((sock_fils = accept(mSocket, (struct sockaddr *)&addr_cnx, &size_addr_cnx)) > 0)
|
|
{
|
|
unsigned int ipClient = htonl(addr_cnx.sin_addr.s_addr);
|
|
long pid_fils = fork();
|
|
if(pid_fils > 0)
|
|
{
|
|
// dans le pere
|
|
mNbFils++;
|
|
signal(SIGCHLD, trt_sig); /* SIGCHLD : prevenu quand un process fils se termine */
|
|
trace("Connexion depuis ip %d.%d.%d.%d : creation process pid %ld\n", (ipClient >> 24) & 0xFF, (ipClient >> 16) & 0xFF, (ipClient >> 8) & 0xFF, (ipClient & 0xFF), pid_fils);
|
|
arret(sock_fils, TRUE);
|
|
}
|
|
else if(pid_fils == 0)
|
|
{
|
|
// dans le fils
|
|
mServeur = FALSE;
|
|
mNbFils = 0;
|
|
mPid = getpid();
|
|
trace("Connexion entrante pid %ld socket %d\n", mPid, sock_fils);
|
|
close(mSocket); // le fils n'a pas besoin de la socket serveur mere
|
|
mSocket = sock_fils;
|
|
mSockServeur = 0;
|
|
int arg = 0;
|
|
ioctl(mSocket, FIONBIO, &arg); // mettre bloquant : ok en secu SSL
|
|
//
|
|
if( ! securise(certificat, cleprivee, TRUE))
|
|
{
|
|
// erreur : handshake securise SSL/TLS ko avec le client
|
|
trace("Erreur de handshake securise SSL/TLS\n");
|
|
break;
|
|
}
|
|
//
|
|
trt_connexion();
|
|
//
|
|
break;
|
|
}
|
|
else
|
|
trace("Erreur de fork() creation fils - demande non traitee\n");
|
|
}
|
|
verifierFinFils();
|
|
}
|
|
else
|
|
trace("Attente... %d\n", mSocket);
|
|
}
|
|
// arret socket en cours
|
|
arret(mSocket, TRUE);
|
|
if(mServeur)
|
|
{
|
|
demandeArretFilsEtAttente();
|
|
trace("Arret du serveur\n");
|
|
}
|
|
else
|
|
trace("Arret du client\n");
|
|
}
|
|
else
|
|
{
|
|
trace("Erreur d'initialisation du socket serveur - ARRET\n");
|
|
}
|
|
return(0);
|
|
}
|