J'essaie d'utiliser un exemple de client/serveur SSL à partir de: http://simplestcodings.blogspot.com.br/2010/08/secure-server-client-using-openssl-in-c.html = pour créer une connexion sécurisée à l'aide de SSLv3. J'ai fait quelques changements pour demander le certificat côté serveur, la communication fonctionne bien et est comprise des deux côtés. Ainsi, mon problème est que lorsque le client se connecte au serveur, la communication de protocole SSLv3 ne fonctionne pas, j'ai vérifié en utilisant le wirkeshark et dans le champ de protocole montre simplement TCP ou IPA (RSL Malformed Packet) quelqu'un peut m'aider? Merci!
J'ai créé mes certificats en suivant le tutoriel https://help.ubuntu.com/community/OpenSSL .
Voici mon code client:
//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;
}
Et le serveur:
//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 */
}
Avec les programmes serveur et client ci-dessus, j'obtenais l'erreur suivante:
140671281543104: erreur: 140890B2: routines SSL: SSL3_GET_CLIENT_CERTIFICATE: aucun certificat renvoyé: s3_srvr.c: 3292:
J'avais généré des certificats auto-signés en utilisant la procédure mentionnée dans https://help.ubuntu.com/community/OpenSSL .
Après avoir jonglé avec l'erreur pendant une journée, j'ai constaté que l'erreur était due au fait que l'autorité de certification auto-générée n'était pas dans la chaîne de confiance de la machine que j'utilisais.
Pour ajouter l'autorité de certification à la chaîne de confiance dans RHEL-7, on peut suivre la procédure ci-dessous:
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.
Je pense que la procédure ci-dessus peut également être suivie pour Fedora. Si cela ne fonctionne pas, il pourrait être utile d'explorer les commandes comme "update-ca-certificate". J'espère que cela sera utile à quelqu'un.
vous devez modifier votre code (côté serveur): votre code:
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];**
à la place, vous devez utiliser ceci:
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
J'ai obtenu cette sortie (client):
toc@UnixServer:~$ ./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>
"
Et cette sortie (serveur):
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???"
Lorsque vous utilisez un outil comme ssldump (http://www.rtfm.com/ssldump/) (sur la boîte Unix), vous pouvez voir clairement ce qui se passe:
toc@UnixServer:~$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
Cordialement.
Comme je le disais dans les commentaires à ne de vos questions précédentes , le fait que vous obteniez " Paquet mal formé: GSM sur IP" ou quelque chose d'étrange ici est normal.
Vous utilisez le port 5000, qui est normalement réservé au protocole commplex-main
. Par conséquent, sans aucune information supplémentaire, Wireshark essaie d'analyser le trafic qu'il voit avec le commplex-main
décodeurs.
Bien sûr, puisque les données que vous échangez sur ce port sont en fait SSL/TLS (parce que vous utilisez un port qui n'est pas normalement utilisé pour cela), le décoder comme s'il s'agissait de commplex-main
conduit à un certain nombre de messages étranges concernant les paquets mal formés.
Wireshark ne devine le protocole qu'en utilisant le numéro de port qu'il voit. Vous devez lui dire d'essayer un décodeur différent, si vous n'utilisez pas le port standard pour ce protocole.
Plus précisément, faites un clic droit sur un paquet et choisissez Décoder comme ... -> Transport -> SSL.