2012-07-29 15 views
16

Próbuję użyć przykładu klienta/serwera SSL z: http://simplestcodings.blogspot.com.br/2010/08/secure-server-client-using-openssl-in-c.html, aby utworzyć bezpieczne połączenie przy użyciu protokołu SSLv3. Wprowadziłem pewne zmiany na żądanie certyfikatu po stronie serwera, komunikacja działa dobrze i jest zrozumiała dla obu stron. Tak więc, moim problemem jest to, że gdy klient łączy się z serwerem, protokół komunikacji SSLv3 nie działa, zweryfikowałem, używając wirkeshark iw polu protokołu pokazuje się tylko TCP, lub IPA (RSL Malformed Packet) ktoś może mi pomóc? Dzięki!Komunikacja klienta i serwera przy użyciu protokołu SSL/C++ - protokół SSL nie działa.

Utworzone przeze mnie certyfikaty są zgodne z samouczkiem https://help.ubuntu.com/community/OpenSSL.

Oto mój kod klienta:

//SSL-Client.c 
#include <stdio.h> 
#include <errno.h> 
#include <unistd.h> 
#include <malloc.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <resolv.h> 
#include <netdb.h> 
#include <openssl/ssl.h> 
#include <openssl/err.h> 

#define FAIL -1 

    //Added the LoadCertificates how in the server-side makes.  
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile) 
{ 
/* set the local certificate from CertFile */ 
    if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    /* set the private key from KeyFile (may be the same as CertFile) */ 
    if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    /* verify private key */ 
    if (!SSL_CTX_check_private_key(ctx)) 
    { 
     fprintf(stderr, "Private key does not match the public certificate\n"); 
     abort(); 
    } 
} 

int OpenConnection(const char *hostname, int port) 
{ int sd; 
    struct hostent *host; 
    struct sockaddr_in addr; 

    if ((host = gethostbyname(hostname)) == NULL) 
    { 
     perror(hostname); 
     abort(); 
    } 
    sd = socket(PF_INET, SOCK_STREAM, 0); 
    bzero(&addr, sizeof(addr)); 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(port); 
    addr.sin_addr.s_addr = *(long*)(host->h_addr); 
    if (connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0) 
    { 
     close(sd); 
     perror(hostname); 
     abort(); 
    } 
    return sd; 
} 

SSL_CTX* InitCTX(void) 
{ SSL_METHOD *method; 
    SSL_CTX *ctx; 

    OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */ 
    SSL_load_error_strings(); /* Bring in and register error messages */ 
    method = SSLv3_client_method(); /* Create new client-method instance */ 
    ctx = SSL_CTX_new(method); /* Create new context */ 
    if (ctx == NULL) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    return ctx; 
} 

void ShowCerts(SSL* ssl) 
{ X509 *cert; 
    char *line; 

    cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */ 
    if (cert != NULL) 
    { 
     printf("Server certificates:\n"); 
     line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 
     printf("Subject: %s\n", line); 
     free(line);  /* free the malloc'ed string */ 
     line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 
     printf("Issuer: %s\n", line); 
     free(line);  /* free the malloc'ed string */ 
     X509_free(cert);  /* free the malloc'ed certificate copy */ 
    } 
    else 
     printf("No certificates.\n"); 
} 

int main() 
{ SSL_CTX *ctx; 
    int server; 
    SSL *ssl; 
    char buf[1024]; 
    int bytes; 
    char hostname[]="127.0.0.1"; 
    char portnum[]="5000"; 
    char CertFile[] = "/home/myCA/cacert.pem"; 
    char KeyFile[] = "/home/myCA/private/cakey.pem"; 

    SSL_library_init(); 

    ctx = InitCTX(); 
    LoadCertificates(ctx, CertFile, KeyFile); 
    server = OpenConnection(hostname, atoi(portnum)); 
    ssl = SSL_new(ctx);  /* create new SSL connection state */ 
    SSL_set_fd(ssl, server); /* attach the socket descriptor */ 
    if (SSL_connect(ssl) == FAIL) /* perform the connection */ 
     ERR_print_errors_fp(stderr); 
    else 
    { char *msg = "Hello???"; 

     printf("Connected with %s encryption\n", SSL_get_cipher(ssl)); 
     ShowCerts(ssl);  /* get any certs */ 
     SSL_write(ssl, msg, strlen(msg)); /* encrypt & send message */ 
     bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */ 
     buf[bytes] = 0; 
     printf("Received: \"%s\"\n", buf); 
     SSL_free(ssl);  /* release connection state */ 
    } 
    close(server);   /* close socket */ 
    SSL_CTX_free(ctx);  /* release context */ 
    return 0; 
} 

a serwerem:

//SSL-Server.c 
#include <errno.h> 
#include <unistd.h> 
#include <malloc.h> 
#include <string.h> 
#include <arpa/inet.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <resolv.h> 
#include "openssl/ssl.h" 
#include "openssl/err.h" 

#define FAIL -1 

int OpenListener(int port) 
{ int sd; 
    struct sockaddr_in addr; 

    sd = socket(PF_INET, SOCK_STREAM, 0); 
    bzero(&addr, sizeof(addr)); 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(port); 
    addr.sin_addr.s_addr = INADDR_ANY; 
    if (bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0) 
    { 
     perror("can't bind port"); 
     abort(); 
    } 
    if (listen(sd, 10) != 0) 
    { 
     perror("Can't configure listening port"); 
     abort(); 
    } 
    return sd; 
} 

SSL_CTX* InitServerCTX(void) 
{ SSL_METHOD *method; 
    SSL_CTX *ctx; 

    OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */ 
    SSL_load_error_strings(); /* load all error messages */ 
    method = SSLv3_server_method(); /* create new server-method instance */ 
    ctx = SSL_CTX_new(method); /* create new context from method */ 
    if (ctx == NULL) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    return ctx; 
} 

void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile) 
{ 
    //New lines 
    if (SSL_CTX_load_verify_locations(ctx, CertFile, KeyFile) != 1) 
     ERR_print_errors_fp(stderr); 

    if (SSL_CTX_set_default_verify_paths(ctx) != 1) 
     ERR_print_errors_fp(stderr); 
    //End new lines 

    /* set the local certificate from CertFile */ 
    if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    /* set the private key from KeyFile (may be the same as CertFile) */ 
    if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    /* verify private key */ 
    if (!SSL_CTX_check_private_key(ctx)) 
    { 
     fprintf(stderr, "Private key does not match the public certificate\n"); 
     abort(); 
    } 

    //New lines - Force the client-side have a certificate 
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); 
    SSL_CTX_set_verify_depth(ctx, 4); 
    //End new lines 
} 

void ShowCerts(SSL* ssl) 
{ X509 *cert; 
    char *line; 

    cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */ 
    if (cert != NULL) 
    { 
     printf("Server certificates:\n"); 
     line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 
     printf("Subject: %s\n", line); 
     free(line); 
     line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 
     printf("Issuer: %s\n", line); 
     free(line); 
     X509_free(cert); 
    } 
    else 
     printf("No certificates.\n"); 
} 

void Servlet(SSL* ssl) /* Serve the connection -- threadable */ 
{ char buf[1024]; 
    char reply[1024]; 
    int sd, bytes; 
    const char* HTMLecho="<html><body><pre>%s</pre></body></html>\n\n"; 

    if (SSL_accept(ssl) == FAIL)  /* do SSL-protocol accept */ 
     ERR_print_errors_fp(stderr); 
    else 
    { 
     ShowCerts(ssl);  /* get any certificates */ 
     bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */ 
     if (bytes > 0) 
     { 
      buf[bytes] = 0; 
      printf("Client msg: \"%s\"\n", buf); 
      sprintf(reply, HTMLecho, buf); /* construct reply */ 
      SSL_write(ssl, reply, strlen(reply)); /* send reply */ 
     } 
     else 
      ERR_print_errors_fp(stderr); 
    } 
    sd = SSL_get_fd(ssl);  /* get socket connection */ 
    SSL_free(ssl);   /* release SSL state */ 
    close(sd);   /* close connection */ 
} 

int main() 
{ SSL_CTX *ctx; 
    int server; 
    char portnum[]="5000"; 

     char CertFile[] = "/home/myCA/mycert.pem"; 
     char KeyFile[] = "/home/myCA/mycert.pem"; 

    SSL_library_init(); 

    ctx = InitServerCTX();  /* initialize SSL */ 
    LoadCertificates(ctx, CertFile, KeyFile); /* load certs */ 
    server = OpenListener(atoi(portnum)); /* create server socket */ 
    while (1) 
    { struct sockaddr_in addr; 
     socklen_t len = sizeof(addr); 
     SSL *ssl; 

     int client = accept(server, (struct sockaddr*)&addr, &len); /* accept connection as usual */ 
     printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 
     ssl = SSL_new(ctx);    /* get new SSL state with context */ 
     SSL_set_fd(ssl, client);  /* set connection socket to SSL state */ 
     Servlet(ssl);   /* service connection */ 
    } 
    close(server);   /* close server socket */ 
    SSL_CTX_free(ctx);   /* release context */ 
} 
+0

Musisz poinformować Wireshark, jaki protokół działa na jakim porcie, ponieważ używasz niestandardowego portu. Umożliwi to uruchomienie właściwego narzędzia. Zobacz [Rozproszenie protokołu kontroli] (https://www.wireshark.org/docs/wsug_html_chunked/ChCustProtocolDissectionSection.html) w dokumentach Wiresharka. – jww

+0

przyjmuje domyślny zestaw algorytmów szyfrowania AES256-SHA? dla TLS 1.2, w moim programie zajmuje AES256-GCM-SHA384? jak to możliwe? – lucifer

Odpowiedz

4

musisz zmodyfikować kod (po stronie serwera): kod:

int main() 
{ SSL_CTX *ctx; 
    int server; 
    **char portnum[]="5000";** 

     char CertFile[] = "/home/myCA/mycert.pem"; 
     char KeyFile[] = "/home/myCA/mycert.pem"; 

    SSL_library_init(); 

    **portnum = strings[1];** 

zamiast tego powinieneś użyć tego:

int main(int argc, char **argv) 
{ SSL_CTX *ctx; 
    int server; 
    //char portnum[]="5000"; ---> You can pass it as an argument 

     char CertFile[] = "/home/myCA/mycert.pem"; 
     char KeyFile[] = "/home/myCA/mycert.pem"; 

    SSL_library_init(); 

    //portnum = strings[1]; 
    portnum = argv[1]; // ---> You can pass port number here, instead of put it in the code 

mam to wyjście (klient):

[email protected]:~$ ./ssl_client 
Connected with AES256-SHA encryption 
Server certificates: 
Subject: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/[email protected] 
Issuer: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/[email protected] 
Received: "<html><body><pre>Hello???</pre></body></html> 

" 

i wyjście (serwer):

Connection: 127.0.0.1:59066 
Server certificates: 
Subject: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/[email protected] 
Issuer: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/[email protected] 
Client msg: "Hello???" 

Podczas korzystania z narzędzia takie jak ssldump (http: //www.rtfm. com/ssldump /) (na unixie), możesz wyraźnie zobaczyć, co się dzieje:

[email protected]:~$sudo ssldump -i lo port 5000 
New TCP connection #1: localhost(59071) <-> localhost(5000) 
1 1 0.0012 (0.0012) C>S Handshake 
     ClientHello 
     Version 3.0 
     cipher suites 
     Unknown value 0xc014 
     Unknown value 0xc00a 
     SSL_DHE_RSA_WITH_AES_256_CBC_SHA 
     SSL_DHE_DSS_WITH_AES_256_CBC_SHA 
     Unknown value 0x88 
     Unknown value 0x87 
     Unknown value 0xc00f 
     Unknown value 0xc005 
     SSL_RSA_WITH_AES_256_CBC_SHA 
     Unknown value 0x84 
     Unknown value 0xc012 
     Unknown value 0xc008 
     SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 
     SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA 
     Unknown value 0xc00d 
     Unknown value 0xc003 
     SSL_RSA_WITH_3DES_EDE_CBC_SHA 
     Unknown value 0xc013 
     Unknown value 0xc009 
     SSL_DHE_RSA_WITH_AES_128_CBC_SHA 
     SSL_DHE_DSS_WITH_AES_128_CBC_SHA 
     Unknown value 0x9a 
     Unknown value 0x99 
     Unknown value 0x45 
     Unknown value 0x44 
     Unknown value 0xc00e 
     Unknown value 0xc004 
     SSL_RSA_WITH_AES_128_CBC_SHA 
     Unknown value 0x96 
     Unknown value 0x41 
     Unknown value 0xc011 
     Unknown value 0xc007 
     Unknown value 0xc00c 
     Unknown value 0xc002 
     SSL_RSA_WITH_RC4_128_SHA 
     SSL_RSA_WITH_RC4_128_MD5 
     SSL_DHE_RSA_WITH_DES_CBC_SHA 
     SSL_DHE_DSS_WITH_DES_CBC_SHA 
     SSL_RSA_WITH_DES_CBC_SHA 
     SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 
     SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 
     SSL_RSA_EXPORT_WITH_DES40_CBC_SHA 
     SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 
     SSL_RSA_EXPORT_WITH_RC4_40_MD5 
     Unknown value 0xff 
     compression methods 
       unknown value 
        NULL 
1 2 0.0019 (0.0006) S>C Handshake 
     ServerHello 
     Version 3.0 
     session_id[32]= 
      13 e2 5a f0 10 93 18 56 c8 66 54 94 29 ab 8b 2d 
      7b c6 9c 3b 7b ea c7 54 e6 86 7d 3a 56 8c 96 14 
     cipherSuite   SSL_RSA_WITH_AES_256_CBC_SHA 
     compressionMethod     unknown value 
1 3 0.0019 (0.0000) S>C Handshake 
     Certificate 
1 4 0.0019 (0.0000) S>C Handshake 
     CertificateRequest 
     certificate_types     rsa_sign 
     certificate_types     dss_sign 
     ServerHelloDone 
1 5 0.0155 (0.0136) C>S Handshake 
     Certificate 
1 6 0.0155 (0.0000) C>S Handshake 
     ClientKeyExchange 
1 7 0.0155 (0.0000) C>S Handshake 
     CertificateVerify 
     Signature[128]= 
      ac 94 31 89 64 75 20 5f 4f 00 73 4e e8 de 51 b7 
      f1 bb 16 da 63 b1 8d e9 15 9b af f8 32 d7 84 f5 
      b5 7d 4f 48 1c 2b 41 58 81 d3 a8 50 40 25 90 95 
      44 de 9d bb c4 79 5c 64 a8 a9 28 f4 16 7c 0e 17 
      b2 77 cf b0 8c a9 90 50 34 a5 76 a2 57 39 8d 37 
      12 d8 a5 8d f4 08 3a 1e 83 7e 6c 0a e9 75 ec 85 
      3d 56 f2 2e 4a 7d 71 88 29 26 99 40 43 4e f3 29 
      26 bf eb 15 be 36 22 72 f3 d9 be 4a e3 c9 0b cc 
1 8 0.0155 (0.0000) C>S ChangeCipherSpec 
1 9 0.0155 (0.0000) C>S Handshake 
1 10 0.0245 (0.0089) S>C ChangeCipherSpec 
1 11 0.0245 (0.0000) S>C Handshake 
1 12 0.0250 (0.0005) C>S application_data 
1 13 0.0250 (0.0000) C>S application_data 
1 14 0.0258 (0.0007) S>C application_data 
1 15 0.0258 (0.0000) S>C application_data 
1 0.0261 (0.0002) C>S TCP FIN 
1 0.0275 (0.0013) S>C TCP FIN 

Pozdrawiam.

+0

Przepraszam, ale test polega na naprawieniu portu 5000. Potrzebuję komentarza, kiedy zmieniam tutaj, zapomnij o komentarzu "// portnum = string [1];" - Dziękuję, ale błąd nie dotyczy portu. –

+0

@DavidViana: Wpisz tutaj swój błąd, ponieważ przetestowałem kod i nie ma pb! – TOC

+0

Tak ... wyjścia są w porządku .. ale protokół, kiedy ustanowione jest połączenie SSL/TLS, musi być SSLvX, ale kiedy weryfikuję protokół, protokół jest protokołem TCP lub IPA (RSL Malformed Packet). Wiadomość jest zaszyfrowana, ale moje wątpliwości dotyczą pola protokołu, które nie jest protokołem SSL. Dziękuję Ci! –

0

Tak jak mówiłem w komentarzach do one of your previous question, fakt, że otrzymałeś "zniekształcony pakiet: GSM przez IP" lub coś dziwnego tutaj jest normalne.

Używasz portu 5000, który zwykle jest zarezerwowany dla protokołu commplex-main. Dlatego bez dodatkowych informacji Wireshark próbuje przeanalizować ruch, który widzi z dekoderami commplex-main.

Oczywiście, ponieważ dane, które wymieniasz na tym porcie, to w rzeczywistości SSL/TLS (ponieważ używasz portu, który normalnie nie jest do tego używany), dekodowanie go tak, jakby to było commplex-main prowadzi do liczby nieparzystych wiadomości dotyczących zniekształconych pakietów.

Wireshark zgrywa tylko protokół za pomocą numeru portu, który widzi. Musisz powiedzieć, żeby wypróbować inny dekoder, jeśli nie używasz standardowego portu dla tego protokołu.

Dokładniej prawym przyciskiem myszy na pakiet i wybrać Decode jako ... -> Transport -> SSL.

+0

Używam portu 5555 lub 7000, a komunikat "Malformed Packet: GSM over IP" nie jest wyświetlany. Ale protokółem informacyjnym jest TCP, a nie SSL lub TLS. Informacje są kryptą i ja bezpieczeństwa, ale nie wiem, dlaczego za pomocą protokołu SSL/TLS na gnieździe informacja o protokole nie jest SSL/TCP. Stosuję dekodowanie "Dekoduj jako ... -> Transport -> SSL" i nie mam zmian. Ale jest ok, dzięki! –

5

Z powyższych programów serwerowych i klienckich, ja otrzymuję następujący błąd:

140671281543104: Błąd: 140890B2: SSL podprogramów: SSL3_GET_CLIENT_CERTIFICATE: Bez certyfikatu powrócił: s3_srvr.c: 3292:

Wygenerowałem samopodpisane certyfikaty, korzystając z procedury wymienionej w https://help.ubuntu.com/community/OpenSSL.

Po żonglowaniu z błędem przez jeden dzień, stwierdziłem, że błąd był spowodowany tym, że samopowstały urząd certyfikacji nie znajdował się w łańcuchu zaufania urządzenia, z którego korzystałem.

Aby dodać urząd certyfikacji do łańcucha zaufania w RHEL-7, można postępować zgodnie z poniższą procedurą:

 To add a certificate in the simple PEM or DER file formats to the 
     list of CAs trusted on the system: 

     Copy it to the 
       /etc/pki/ca-trust/source/anchors/ 
     subdirectory, and run the 
       update-ca-trust 
     command. 

     If your certificate is in the extended BEGIN TRUSTED file format, 
     then place it into the main source/ directory instead. 

myślę, że powyższa procedura może być stosowana dla Fedory też. Jeśli to nie zadziała, może być przydatne zbadanie komend, takich jak "update-ca-certificates". Mam nadzieję, że przyda się to komuś.

Powiązane problemy