I downloaded the google's certificate in linux (I am using mingw
for cross compilation and wine
for execution):
mkdir -p ./release/certificates
echo | openssl s_client -servername google.com -connect google.com:443| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > google.crt
And I attempt to verify it in my programm:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <shlwapi.h>
#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
//#pragma comment (lib, "Mswsock.lib")
//#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define FAIL -1
#define WIN32_LEAN_AND_MEAN
SOCKET OpenConnection(char* hostname, char* port)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo* result = NULL;
struct addrinfo* ptr = NULL;
struct addrinfo hints;
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
printf("\nInitializing Winsock");
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(hostname, port, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
return ConnectSocket;
}
SSL_CTX* InitCTX(void)
{
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
const SSL_METHOD* method = SSLv23_method();
SSL_CTX* ctx = SSL_CTX_new(method);
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1);
if (ctx == NULL)
{
ERR_print_errors_fp(stderr);
abort();
}
char* path = malloc(MAX_PATH);
memset(path, 0, MAX_PATH);
GetModuleFileName(0, path, MAX_PATH);
PathRemoveFileSpec(path);
sprintf(path,"%s\\%s",path,"certificates");
printf("Cert path %s\n",path);
int value = SSL_CTX_load_verify_locations(ctx,"google.crt",path);
if(value == 0) {
printf("Certificate error\n");
exit(1);
}
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("Info: No client certificates configured.\n");
}
}
void releaseSocket( SSL_CTX* ctx, int server)
{
/* close socket */
closesocket(server);
/* release context */
SSL_CTX_free(ctx);
putchar('\n');
}
int main(int argc, char* argv[])
{
printf("Initializing Connection");
char buf[1024];
SSL_library_init();
char* hostname = "google.com";
char* portnum = "443";
SSL_CTX* ctx = InitCTX();
int server = OpenConnection(hostname, portnum);
SSL* ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
if (SSL_connect(ssl) == FAIL) {
ERR_print_errors_fp(stderr);
} else {
const char* cpRequestMessage = "GET / HTTP/1.1\r\nHost: www.google.com\r\nUser-Agent: curl/7.54.0\r\nConnection: close\r\nAccept: */*\r\n\r\n";
printf("\n\nConnected with %s encryption\n", SSL_get_cipher(ssl));
/* get any certs */
ShowCerts(ssl);
/* encrypt & send message */
printf("REQUEST:\n\n%s\n",cpRequestMessage);
SSL_write(ssl, cpRequestMessage, strlen(cpRequestMessage));
/* get reply & decrypt */
int bytes = SSL_read(ssl, buf, sizeof(buf));
int error = SSL_get_error(ssl,bytes);
switch (error)
{
case SSL_ERROR_SSL:
puts("SSL ERROR SSL");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_SYSCALL:
puts("SSL ERROR SYSCALL");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_WANT_ASYNC_JOB:
puts("SSL ERROR WANT ASYNC_LOOKUP");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_WANT_ASYNC:
puts("SSL ERROR WANT X509_LOOKUP");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_WANT_X509_LOOKUP:
puts("SSL ERROR WANT X509_LOOKUP");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_WANT_WRITE:
puts("SSL ERROR WANT WRITE");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_WANT_READ:
puts("SSL ERROR WANT READ");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_ZERO_RETURN:
puts("SSL ERROR SSL_ERROR_ZERO_RETURN");
releaseSocket(ctx,server);
return 1;
case SSL_ERROR_NONE:
default:
break;
}
puts("RESPONSE\n");
for(int i=0;i<bytes;i ){
putchar(buf[i]);
}
/* release connection state */
SSL_free(ssl);
}
releaseSocket(ctx,server);
putchar('\n');
return 0;
}
For clarity in the code above I verify the certificate in InitCTX
function like this:
char* path = malloc(MAX_PATH);
memset(path, 0, MAX_PATH);
GetModuleFileName(0, path, MAX_PATH);
PathRemoveFileSpec(path);
sprintf(path,"%s\\%s",path,"certificates");
printf("Cert path %s\n",path);
int value = SSL_CTX_load_verify_locations(ctx,"google.crt",path);
if(value == 0) {
printf("Certificate error\n");
exit(1);
}
But the certificate seems not to be able to verify:
Initializing ConnectionCert path Z:\home\pcmagas\job\Kwdikas\my_win_app\release\certificates
Certificate error
As a means of diagnosis using wine's derived cmd:
wine cmd
> cd release\certificates
> dir
0009:fixme:ntdll:server_ioctl_file Unsupported ioctl 24000 (device=2 access=1 func=0 method=0)
Volume in drive Z has no label.
Volume Serial Number is 0000-0000
Directory of Z:\home\pcmagas\job\Kwdikas\my_win_app\release\certificates
15/7/2022 10:01 μμ <DIR> .
15/7/2022 10:37 μμ <DIR> ..
15/7/2022 10:01 μμ 4,860 google.crt
1 file 4,860 bytes
2 directories 24,553,922,560 bytes free
> type google.crt
-----BEGIN CERTIFICATE-----
MIIN2DCCDMCgAwIBAgIQYM9tSNNu7FgSBQMJka23FDANBgkqhkiG9w0BAQsFADBG
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMjA2MjcwODE3MzlaFw0yMjA5MTkw
ODE3MzhaMBcxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABIc IN08t8 aCMkZ8A7h8IkNd8eTW9nEZaCfoUBLrlIPq5gPL2OM
BMbh x/FqStjWaXLhlf6n0srtnqOLcAq3m6jggu6MIILtjAOBgNVHQ8BAf8EBAMC
B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU
NRZdk0ysjIh2U0LY2vwqY2/nVD8wHwYDVR0jBBgwFoAUinR/r4XN7pXNPZzQ4kYU
83E1HScwagYIKwYBBQUHAQEEXjBcMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5w
a2kuZ29vZy9ndHMxYzMwMQYIKwYBBQUHMAKGJWh0dHA6Ly9wa2kuZ29vZy9yZXBv
L2NlcnRzL2d0czFjMy5kZXIwggloBgNVHREEgglfMIIJW4IMKi5nb29nbGUuY29t
ghYqLmFwcGVuZ2luZS5nb29nbGUuY29tggkqLmJkbi5kZXaCEiouY2xvdWQuZ29v
Z2xlLmNvbYIYKi5jcm93ZHNvdXJjZS5nb29nbGUuY29tghgqLmRhdGFjb21wdXRl
Lmdvb2dsZS5jb22CCyouZ29vZ2xlLmNhggsqLmdvb2dsZS5jbIIOKi5nb29nbGUu
Y28uaW6CDiouZ29vZ2xlLmNvLmpwgg4qLmdvb2dsZS5jby51a4IPKi5nb29nbGUu
Y29tLmFygg8qLmdvb2dsZS5jb20uYXWCDyouZ29vZ2xlLmNvbS5icoIPKi5nb29n
bGUuY29tLmNvgg8qLmdvb2dsZS5jb20ubXiCDyouZ29vZ2xlLmNvbS50coIPKi5n
b29nbGUuY29tLnZuggsqLmdvb2dsZS5kZYILKi5nb29nbGUuZXOCCyouZ29vZ2xl
LmZyggsqLmdvb2dsZS5odYILKi5nb29nbGUuaXSCCyouZ29vZ2xlLm5sggsqLmdv
b2dsZS5wbIILKi5nb29nbGUucHSCEiouZ29vZ2xlYWRhcGlzLmNvbYIPKi5nb29n
bGVhcGlzLmNughEqLmdvb2dsZXZpZGVvLmNvbYIMKi5nc3RhdGljLmNughAqLmdz
dGF0aWMtY24uY29tgg9nb29nbGVjbmFwcHMuY26CESouZ29vZ2xlY25hcHBzLmNu
ghFnb29nbGVhcHBzLWNuLmNvbYITKi5nb29nbGVhcHBzLWNuLmNvbYIMZ2tlY25h
cHBzLmNugg4qLmdrZWNuYXBwcy5jboISZ29vZ2xlZG93bmxvYWRzLmNughQqLmdv
b2dsZWRvd25sb2Fkcy5jboIQcmVjYXB0Y2hhLm5ldC5jboISKi5yZWNhcHRjaGEu
bmV0LmNughByZWNhcHRjaGEtY24ubmV0ghIqLnJlY2FwdGNoYS1jbi5uZXSCC3dp
ZGV2aW5lLmNugg0qLndpZGV2aW5lLmNughFhbXBwcm9qZWN0Lm9yZy5jboITKi5h
bXBwcm9qZWN0Lm9yZy5jboIRYW1wcHJvamVjdC5uZXQuY26CEyouYW1wcHJvamVj
dC5uZXQuY26CF2dvb2dsZS1hbmFseXRpY3MtY24uY29tghkqLmdvb2dsZS1hbmFs
eXRpY3MtY24uY29tghdnb29nbGVhZHNlcnZpY2VzLWNuLmNvbYIZKi5nb29nbGVh
ZHNlcnZpY2VzLWNuLmNvbYIRZ29vZ2xldmFkcy1jbi5jb22CEyouZ29vZ2xldmFk
cy1jbi5jb22CEWdvb2dsZWFwaXMtY24uY29tghMqLmdvb2dsZWFwaXMtY24uY29t
ghVnb29nbGVvcHRpbWl6ZS1jbi5jb22CFyouZ29vZ2xlb3B0aW1pemUtY24uY29t
ghJkb3VibGVjbGljay1jbi5uZXSCFCouZG91YmxlY2xpY2stY24ubmV0ghgqLmZs
cy5kb3VibGVjbGljay1jbi5uZXSCFiouZy5kb3VibGVjbGljay1jbi5uZXSCDmRv
dWJsZWNsaWNrLmNughAqLmRvdWJsZWNsaWNrLmNughQqLmZscy5kb3VibGVjbGlj
ay5jboISKi5nLmRvdWJsZWNsaWNrLmNughFkYXJ0c2VhcmNoLWNuLm5ldIITKi5k
YXJ0c2VhcmNoLWNuLm5ldIIdZ29vZ2xldHJhdmVsYWRzZXJ2aWNlcy1jbi5jb22C
HyouZ29vZ2xldHJhdmVsYWRzZXJ2aWNlcy1jbi5jb22CGGdvb2dsZXRhZ3NlcnZp
Y2VzLWNuLmNvbYIaKi5nb29nbGV0YWdzZXJ2aWNlcy1jbi5jb22CF2dvb2dsZXRh
Z21hbmFnZXItY24uY29tghkqLmdvb2dsZXRhZ21hbmFnZXItY24uY29tghhnb29n
bGVzeW5kaWNhdGlvbi1jbi5jb22CGiouZ29vZ2xlc3luZGljYXRpb24tY24uY29t
giQqLnNhZmVmcmFtZS5nb29nbGVzeW5kaWNhdGlvbi1jbi5jb22CFmFwcC1tZWFz
dXJlbWVudC1jbi5jb22CGCouYXBwLW1lYXN1cmVtZW50LWNuLmNvbYILZ3Z0MS1j
bi5jb22CDSouZ3Z0MS1jbi5jb22CC2d2dDItY24uY29tgg0qLmd2dDItY24uY29t
ggsybWRuLWNuLm5ldIINKi4ybWRuLWNuLm5ldIIUZ29vZ2xlZmxpZ2h0cy1jbi5u
ZXSCFiouZ29vZ2xlZmxpZ2h0cy1jbi5uZXSCDGFkbW9iLWNuLmNvbYIOKi5hZG1v
Yi1jbi5jb22CDSouZ3N0YXRpYy5jb22CFCoubWV0cmljLmdzdGF0aWMuY29tggoq
Lmd2dDEuY29tghEqLmdjcGNkbi5ndnQxLmNvbYIKKi5ndnQyLmNvbYIOKi5nY3Au
Z3Z0Mi5jb22CECoudXJsLmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5j
b22CCyoueXRpbWcuY29tggthbmRyb2lkLmNvbYINKi5hbmRyb2lkLmNvbYITKi5m
bGFzaC5hbmRyb2lkLmNvbYIEZy5jboIGKi5nLmNuggRnLmNvggYqLmcuY2 CBmdv
by5nbIIKd3d3Lmdvby5nbIIUZ29vZ2xlLWFuYWx5dGljcy5jb22CFiouZ29vZ2xl
LWFuYWx5dGljcy5jb22CCmdvb2dsZS5jb22CEmdvb2dsZWNvbW1lcmNlLmNvbYIU
Ki5nb29nbGVjb21tZXJjZS5jb22CCGdncGh0LmNuggoqLmdncGh0LmNuggp1cmNo
aW4uY29tggwqLnVyY2hpbi5jb22CCHlvdXR1LmJlggt5b3V0dWJlLmNvbYINKi55
b3V0dWJlLmNvbYIUeW91dHViZWVkdWNhdGlvbi5jb22CFioueW91dHViZWVkdWNh
dGlvbi5jb22CD3lvdXR1YmVraWRzLmNvbYIRKi55b3V0dWJla2lkcy5jb22CBXl0
LmJlggcqLnl0LmJlghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYIbZGV2ZWxv
cGVyLmFuZHJvaWQuZ29vZ2xlLmNughxkZXZlbG9wZXJzLmFuZHJvaWQuZ29vZ2xl
LmNughhzb3VyY2UuYW5kcm9pZC5nb29nbGUuY24wIQYDVR0gBBowGDAIBgZngQwB
AgEwDAYKKwYBBAHWeQIFAzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3Jscy5w
a2kuZ29vZy9ndHMxYzMvemRBVHQwRXhfRmsuY3JsMIIBBgYKKwYBBAHWeQIEAgSB
9wSB9ADyAHcABZwB0yDgB4QTlYBJjRF8kDJmr69yULWvO0akPhGEDUoAAAGBpHPd
IQAABAMASDBGAiEA2WQJomYavFJzDXZDxr00uVqZD5BECioqTZoKpyAtQb8CIQDq
tTwx9sKrTe7AnT9LmXJLQkqNOOgOXC1lzWraQnTZVgB3AEalVet1 pEgMLWiiWn0
830RLEF0vv1JuIWr8vxw/m1HAAABgaRz3SEAAAQDAEgwRgIhAOrP HKPZQGYDY10
L1U5qfMeNus2Ag7I8Ad8GFKXu4N/AiEAjZ Hi1zQXLnod3/dT0RuIRIkPQvR/bBQ
lrFq1I1JJHEwDQYJKoZIhvcNAQELBQADggEBAD68OnygUK82iD2YG3fbgIfwVgcp
5VRkED36vM91B6RQVkDIBftWfWMrkRo52eCFJ9G8UT6qj4XrYwnC0KwYOUA5s3t3
haw y7qYyaILaBKTr/MNo/Q9SuGA1kRAeQc9MAZE6OD8f817OfF6exnYoEw0YMzV
nSGCh5Sudy edxjETU/mtS0eNG9ve/ydgxGq6DoIrjGb/7Vv1NvVzawtAhijFZkz
6CprociZvhLgi/oMO5RLg5zIGFW0Tfmnr0y63PyyyTvLK3bbHucnDJ9QCTbQM52k
BBABc9qm3J9EjQfYjvrZFzLVFG88x5bVJDC3bSyMsI4iwpfJAPaLO1ZNaHM=
-----END CERTIFICATE-----
As far as I can see certificate is in the appropriate position. Thereofre I have no idea why I cannot verify the certificate I downloaded from google.
CodePudding user response:
The problematic line is:
int value = SSL_CTX_load_verify_locations(ctx,"google.crt",path);
If CAfile is not NULL, it points to a file of CA certificates in PEM format.
see https://www.openssl.org/docs/manmaster/man3/SSL_CTX_load_verify_locations.html
An absolute path to this file is expected there.
You specify only the file name as the second parameter. The associated directory is specified as the third parameter. However, the third parameter is for something else. It provides an alternative CA lookup mechanism for peer certificate verification.
Since you provide the data already in the CA file google.crt
, the third parameter can simply be set to NULL.
So the line should rather look like:
int value = SSL_CTX_load_verify_locations(ctx,"/absolute/path/to/google.crt", NULL);
I briefly tested with the code from your question, with the minor adjustment mentioned regarding the absolute path, the verification was successful.
CodePudding user response:
As a complementary answer towards the one that @Stephan Schlecht provided the certificate should be verified as:
sprintf(path,"%s\\%s",path,"certificates\\google.crt");
printf("Cert path %s\n",path);
int value = SSL_CTX_load_verify_locations(ctx,path,NULL);
if(value == 0) {
printf("Certificate error\n");
exit(1);
}
In function initCTX
. The sprintf appends the cert directory from the path we get from:
GetModuleFileName(0, path, MAX_PATH);
PathRemoveFileSpec(path);
In case you want a directory full of custom certificates use this approach:
sprintf(path,"%s\\%s",path,"certificates");
printf("Cert path %s\n",path);
int value = SSL_CTX_load_verify_locations(ctx,NULL,path);
if(value == 0) {
printf("Certificate error\n");
exit(1);
}
In this approach openssl will look upon the directory certificates
where multiple certificates in pem format exists.