Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

C++ smtp serwer z tls/ssl z openssl i STARTTLS - BarracudaSMTP

Ostatnio zmodyfikowano 2017-10-06 14:09
Autor Wiadomość
Breakermind
Temat założony przez niniejszego użytkownika
C++ smtp serwer z tls/ssl z openssl i STARTTLS - BarracudaSMTP
» 2017-10-02 21:30:58
Witam,
jak przechwycić socket error gdy client się rozłączy?

I też się zamyka gdy pojedyńczy klien sie rozłącza, dlaczego?

C/C++
// smtp server test
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// fork, read
#include <unistd.h>
// sockets
#include <sys/socket.h>
#include <netinet/in.h>
// pid kill
#include <signal.h>
#include <string>
#include <iostream>

using namespace std;

#define PORT 5555

bool Contain( std::string str, std::string search ) {
    std::size_t found = str.find( search );
    if( found != std::string::npos ) {
        return 1;
    }
    return 0;
}

int main( int argc, char const * argv[] )
{
    int server_fd, new_socket, valread;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof( address );
    char buffer[ 1024 ] = { 0 };
   
   
    // Creating socket file descriptor
    if(( server_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == 0 )
    {
        perror( "socket failed" );
        exit( EXIT_FAILURE );
    }
   
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons( PORT );
   
    //set master socket to allow multiple connections
    if( setsockopt( server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,( char * ) & opt, sizeof( opt ) ) < 0 )
    {
        perror( "setsockopt" );
        exit( EXIT_FAILURE );
    }
   
    // Forcefully attaching socket to the port 25
    if( bind( server_fd,( struct sockaddr * ) & address, sizeof( address ) ) < 0 )
    {
        perror( "bind failed" );
        exit( EXIT_FAILURE );
    }
    if( listen( server_fd, 100 ) < 0 )
    {
        perror( "listen" );
        exit( EXIT_FAILURE );
    }
   
    while( 1 ) {
        // fork pid
        pid_t pid;
        int currpid = 0;
       
        if(( new_socket = accept( server_fd,( struct sockaddr * ) & address,( socklen_t * ) & addrlen ) ) < 0 )
        {
            perror( "accept" );
            exit( EXIT_FAILURE );
        }
       
        // create child proccess with fork() for new client
        pid = fork();
       
        if( pid > 0 ) {
            currpid = pid;
            fprintf( stderr, "Mam mowego klienta, pid=%d\n", currpid );
            // continue;
        }
        if( new_socket < 0 ) {
            perror( "Unable to accept" );
            exit( EXIT_FAILURE );
        }
       
        char * welcome =( char * ) "220 Hello ESMTP\r\n";
        char * ehlo =( char * ) "250-bobo.pp at your service\r\n250-SIZE 157286400\r\n250 250-STARTTLS\r\n";
        char * ok =( char * ) "250 Ok\r\n";
        char * data =( char * ) "354 send data\r\n";
        char * end =( char * ) "250 email was send\r\n";
        char * bye =( char * ) "221 Bye...\r\n";
        char * tls =( char * ) "220 Ready to start TLS\r\n";
       
        // Clear buffer
        buffer[ 0 ] = '\0';
        memset( buffer, 0, sizeof( buffer ) );
       
        // socket helo1
        send( new_socket, welcome, strlen( welcome ), 0 );
        // printf("Hello message sent %s\n",hello1);
       
        // ehlo
        valread = read( new_socket, buffer, 1024 );
        printf( "Client send %s\n", buffer );
        memset( buffer, 0, sizeof( buffer ) );
        send( new_socket, ehlo, strlen( ehlo ), 0 );
        // printf("Hello message sent %s\n",hello1);
       
        // mail from:
        valread = read( new_socket, buffer, 1024 );
        printf( "Client send %s\n", buffer );
        memset( buffer, 0, sizeof( buffer ) );
        send( new_socket, ok, strlen( ok ), 0 );
        // printf("Hello message sent %s\n",hello1);
       
        // rcpt to:
        valread = read( new_socket, buffer, 1024 );
        printf( "Client send %s\n", buffer );
        memset( buffer, 0, sizeof( buffer ) );
        send( new_socket, ok, strlen( ok ), 0 );
        // printf("Hello message sent %s\n",hello1);
       
        // DATA
        valread = read( new_socket, buffer, 1024 );
        printf( "Client send %s\n", buffer );
        memset( buffer, 0, sizeof( buffer ) );
        send( new_socket, data, strlen( data ), 0 );
        // printf("Hello message sent %s\n",hello1);
       
        // DATA CONTENT   
        while( 1 ) {
            valread = read( new_socket, buffer, 1024 );
            printf( "Client send %s\n", buffer );
            if( Contain( std::string( buffer ), ".\r\n" ) ) {
                break;
            }
        }
        memset( buffer, 0, sizeof( buffer ) );
        send( new_socket, end, strlen( end ), 0 );
       
        // QUIT
        valread = read( new_socket, buffer, 1024 );
        printf( "Client send %s\n", buffer );
        memset( buffer, 0, sizeof( buffer ) );
        send( new_socket, bye, strlen( bye ), 0 );
        // printf("Hello message sent %s\n",hello1);
       
        // end connection
        close( new_socket );
        // kill(getpid(), SIGKILL);
        // kill(pid, SIGTERM);
    }
    // return 0;
}

P-165416
Gravity
» 2017-10-02 23:40:39
Nie jestem pewny ale chyba nie ma SOCKET_ERRORA jeśli client się rozłączy. Natomiast możesz w pętli while sprawdzać ile bajtów zwróciła funkcja recv i jeśli ona jest równa 0 to możesz wtedy zamknąć połączenie na serwerze.
P-165424
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-03 09:12:57
Dzięki, coś jeszcze o funkcji select() wyczytałem (działanie na podobnej zasadzie). Posprawdzam jak tak.

C/C++
if( valread < 0 ) error( "ERROR reading from socket" );


http://man7.org/linux/man-pages/man2/read.2.html
http://man7.org/linux/man-pages/man3/errno.3.html

Lub:
C/C++
bzero( bufor, sizeof( bufor ) );
if(( recv( gniazdo, bufor, sizeof( bufor ), 0 ) ) <= 0 )
{
    perror( "recv() ERROR" );
    exit( - 1 );
}
printf( "|Wiadomosc z serwera|: %s \n", bufor );

shutdown( gniazdo, SHUT_RDWR );

Jest napisane: http://cpp0x.pl/artykuly/?id=66
P-165427
j23
» 2017-10-03 10:20:11
Tak nawiasem, popraw pętlę na:
C/C++
// DATA CONTENT  
while(( valread = read( new_socket, buffer, 1024 - 1 ) ) > 0 )
{
    buffer[ valread ] = 0;
    printf( "Client send %s\n", buffer );
    if( Contain( std::string( buffer ), ".\r\n" ) )
    {
        break;
    }
}
P-165429
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-03 10:29:55
Ok, jest jeszcze jeden problem w tym przykładzie: drugi i kolejny klient [telnet localhost 5555] nie chciał odbierać i wysyłać danych a jest fork() i nie wiem dlaczego?
P-165430
mateczek
» 2017-10-03 12:29:55
Tą pętlę która jest umieszczona w kursie na stronie http://cpp0x.pl/kursy​/Kurs-WinSock-C++​/Tlo-Klient-Serwer/276jeszcze ogarniam logicznie. Jest wyraźnie rozdzielone co robi proces główny(serwera) a co robi proces dziecko dziecko
1.  Dziekcko kasuje port nasłuchowy Dziecko to już nie serwer !!!! 
2. A proces główny nie gada z klientem tylko robi accept i tworzy nowe sockety. 
3 dziecko zawsze kończy proces, nie obróci pętlą while;
C/C++
while( 1 ) { // głowna pętla accept()
    sin_size = sizeof( struct sockaddr_in );
    if(( new_fd = accept( sockfd,( struct sockaddr * ) & their_addr,
    & sin_size ) ) == - 1 ) {
        perror( "accept" );
        continue;
    }
    printf( "server: got connection from %s\n",
    inet_ntoa( their_addr.sin_addr ) );
    if( !fork() ) { // to jest proces-dziecko
        close( sockfd ); // dziecko nie potrzebuje gniazda nasłuchującego    !!!!!!!!!!!!!
        if( send( new_fd, "Hello, world!\n", 14, 0 ) == - 1 )
             perror( "send" );
       
        close( new_fd );
        exit( 0 ); //dziecko nie ma możliwości by obrócić pętlą dziecko nie stworzy potomka tylko zamyka program exit( 0 );
    }
    close( new_fd ); // rodzic nie potrzebuje tego
}
P-165431
Breakermind
Temat założony przez niniejszego użytkownika
C++ smtp serwer z tls/ssl z openssl i STARTTLS - BarracudaSMTP
» 2017-10-05 21:13:38
Dzieki za help ;)

I coś takiego małego stworzyłem, przykład serwera smtp z ssl na socket openssl z odpalaniem STARTTLS.
Czyli server zaczyna jako serwer bez ssl po komendzie STARTTLS przechodzi w stan TLS/SSL i odbiera dane z innego serwera smtp lub z klienta.
To tylko przykład i zapewne nie doskonały czyli nie zapisuje wiadomości i nie sprawdza poprawności nadawcy i odbiorcy,
lecz wiadomości dochodzą z microsoft live, yahoo, ovh, opessl client, gmail ma jakieś wonty na ssl ale bez daje radę ;)
może się jeszcze nauczy.

I właśnie chodzi o sprawdzenie dlaczego google nie wysyła wiadomości na ssl a utyka po STARTTLS i wysłaniu EHLO do serwera (jakby się rozłączał)?

https://github.com/breakermind​/BarracudaSMTP

Certyfikaty tls pobieram z https://www.sslforfree.com/ czyli testowałem na wpełni funkcjonalnych i dobrych ustawieniach revdns, mx, dkim i spf.

Pozdrawiam



 
P-165468
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-06 14:09:49
Jednak działa i na gmail :).
P-165478
« 1 »
  Strona 1 z 1