How to enforce the server to use only TLSv1.2? - gsoap

I have a server that processes the soap requests. It uses gSOAP 2.8.14. Currently it allows only TLSv1 connections. I need to enforced it to allow only TLSv1.2 connection.
if (soap_ssl_server_context(&soap,
SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION | SOAP_TLSv1,
keyfile, // keyfile: required when server must authenticate to clients
keyfilepass, // password to read the key file
NULL, // optional cacert file to store trusted certificates
capath, // optional capath to directory with trusted certificates
dhfile, // DH file name or DH key len bits
NULL, // if randfile!=NULL: use a file with random data
serverId // server identification for SSL session cache
))
{
printf("SSL Failed to initialize.\n");
soap_print_fault(&soap, stderr);
return;
}
According to gSOAP changelog, flags for TLSv1.1 and TLSv1.2 were added in gSOAP 2.8.24. So, I've updated my gSOAP to the latest available version (2.8.27). As described in gSOAP source in stdsoap2.h, to use only TLSv1.2 I need to use SOAP_TLSv1_2 flag:
#define SOAP_TLSv1 0x0000 /* enable TLS v1.0/1.1/1.2 only (default) */
#define SOAP_SSLv3_TLSv1 0x0040 /* enable SSL v3 and TLS v1.0/1.1/1.2 */
#define SOAP_SSLv3 0x0080 /* only SSL v3 */
#define SOAP_TLSv1_0 0x0100 /* only TLS v1.0 */
#define SOAP_TLSv1_1 0x0200 /* only TLS v1.1 */
#define SOAP_TLSv1_2 0x0400 /* only TLS v1.2 */
I've replaced SOAP_TLSv1 by SOAP_TLSv1_2 in my soap_ssl_server_context function.
if (soap_ssl_server_context(&soap,
SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION | SOAP_TLSv1_2,
...))
{
printf("SSL Failed to initialize.\n");
soap_print_fault(&soap, stderr);
return;
}
But during testing I've found that server still accept requests over TLSv1.
So, my question is how to force the sever to process soap requests only over TLSv1.2?

To force TLS restriction to TLSv1.2 only with gSOAP, you will need:
OpenSSL 1.0.1 or later (otherwise you may default back to SSLv3/TLS);
it is recommended to upgrade to gSOAP version 2.8.27 or later.
With gsoap 2.8.27 use option SOAP_TLSv1_2 to set the soap_ssl_client_context() and soap_ssl_server_context(). I found the answer at http://www.genivia.com/tutorials.html

Related

Secure ESPAsyncWebServer with esp32

I am successfully using the ESPAsyncWebServer library with an ESP32
(https://github.com/me-no-dev/ESPAsyncWebServer).
I would like to use the secure route. The lib offers (ESPAsyncWebServer.h):
#if ASYNC_TCP_SSL_ENABLED
void onSslFileRequest(AcSSlFileHandler cb, void* arg);
void beginSecure(const char *cert, const char *private_key_file, const char *password);
endif
I could not find any information about cert, private_key_file and password.
Does anybody has experience with such a secure route, e.g. where is cert, private_key_file and password defined? Why do I need a password?
Where do I define ASYNC_TCP_SSL_ENABLED?
Thanks.
You should write #define ASYNC_TCP_SSL_ENABLED true
before including libraries.
But more explained there:
https://www.uonfu.com/q/me-no-dev/ESPAsyncWebServer/899/745660419

Determine attributes of an Schannel connection -> returns unknown value

After successfully Creating a Secure Connection Using Schannel, I am obtaining its connection attributes using QueryContextAttributes(), passing SECPKG_ATTR_CONNECTION_INFO.
The returned structure SecPkgContext_ConnectionInfo contains the field aiExch, which holds the information I am looking for - namely the used key exchange algorithm.
I am using this for months, and it always returned one of the two predefined values CALG_RSA_KEYX or CALG_DH_EPHEM. But since a couple of weeks (when I believe a Schannel update patch was issued by Microsoft) it returns an unknown value: 0x0000ae06
Using these macros, the ALG_ID can be split into its components:
#define GET_ALG_CLASS(x) (x & (7 << 13))
#define GET_ALG_TYPE(x) (x & (15 << 9))
#define GET_ALG_SID(x) (x & (511))
According to that, 0x0000ae06 would mean:
Class: ALG_CLASS_KEY_EXCHANGE
Type: (7 << 9) -> which is undefined
SID: 6 -> whose meaning depends on the type of algorithm
Anyone ran into the same issue? Can anyone explain what happened, or what 0x0000ae06 stands for?
Have a look at the code found here http://pastebin.com/TKQJ85Z9 notice that, the ID was added to the schannel library but apparently the VC headers weren't update, at any rate, as you can see from the above code (see pastebin URL), that ID corresponds to "ECDHE", that is Elliptic Curve DH with Ephemeral key exchange
[edit]
The real problem is that the value is unofficial and can only be found by some internet search, that's why I posted the link to some sample code; see, it just happened to me to find the answer by looking at this twit https://twitter.com/ericlaw/status/301083494203928576
At any rate, it sounds like the latest version of the Microsoft CNG SDK contains updated headers and libraries which add a new constant for the "QueryContextAttributes" API call, that is SECPKG_ATTR_CIPHER_INFO such a call returns a structure (see definition in code below) whose member named "szCipherSuite" reports the full string for the cipher in use, for example "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384"
Here's some sample code for such a call
/*
// -- http://www.microsoft.com/en-us/download/details.aspx?id=1251
typedef struct _SecPkgContext_CipherInfo
{
DWORD dwVersion;
DWORD dwProtocol;
DWORD dwCipherSuite;
DWORD dwBaseCipherSuite;
WCHAR szCipherSuite[SZ_ALG_MAX_SIZE];
WCHAR szCipher[SZ_ALG_MAX_SIZE];
DWORD dwCipherLen;
DWORD dwCipherBlockLen; // in bytes
WCHAR szHash[SZ_ALG_MAX_SIZE];
DWORD dwHashLen;
WCHAR szExchange[SZ_ALG_MAX_SIZE];
DWORD dwMinExchangeLen;
DWORD dwMaxExchangeLen;
WCHAR szCertificate[SZ_ALG_MAX_SIZE];
DWORD dwKeyType;
} SecPkgContext_CipherInfo, *PSecPkgContext_CipherInfo;
*/
static void DisplayConnectionInfo(CtxtHandle *phContext)
{
SECURITY_STATUS Status;
SecPkgContext_CipherInfo CipherInfo = { SECPKGCONTEXT_CIPHERINFO_V1 };
Status = QueryContextAttributes( phContext, SECPKG_ATTR_CIPHER_INFO, &CipherInfo);
if(Status != SEC_E_OK)
{
printf("Error 0x%x querying cipher info\n", Status);
return;
}
printf("%S\n", CipherInfo.szCipherSuite);
}
for further infos, please get the MS CNG SDK and have a look at the included help and headers.

Opposite CertAddEncodedCertificateToSystemStore to get ASN1 certificate out of windows certificate store?

I need to programmatically retrieve all of the CA certificates in the Windows certificate store for use in OpenSSL. Win32 has a function called CertAddEncodedCertificateToSystemStore which does the exact opposite of what I need:
BOOL WINAPI CertAddEncodedCertificateToSystemStore(
_In_ LPCSTR szCertStoreName,
_In_ const BYTE *pbCertEncoded,
_In_ DWORD cbCertEncoded
);
CertAddEncodedCertificateToSystemStore creates a PCCERT_CONTEXT from an X509 ASN1 data buffer and adds it to a system certificate store. I need to go through a system certificate store, converting PCCERT_CONTEXTs to X509 ASN1 data buffers.
It looks as though CertSerializeCertificateStoreElement is very close to what I want:
BOOL WINAPI CertSerializeCertificateStoreElement(
_In_ PCCERT_CONTEXT pCertContext,
_In_ DWORD dwFlags,
_Out_ BYTE *pbElement,
_Inout_ DWORD *pcbElement
);
...but apparently the data buffer returned by CertSerializeCertificateStoreElement() isn't a proper DER ASN encoding - it has extra 'stuff' - some sort of windows certificate store properties - and I wouldn't be able to use this for converting to OpenSSL X509's.
Any ideas?
Here's what I was able to use to dump certificates from the System Store. The cleanup objects don't do anything special. They just close handles, free memory, etc. I also yanked out the error checking to keep the size down.
HCERTSTORE hCertStore = CertOpenSystemStore(NULL, _T("ROOT"));
CertStoreCleanup cleanup1(hCertStore);
PCCERT_CONTEXT pCertContext = NULL;
CertContextCleanup cleanup2(pCertContext);
while(pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext))
{
CHAR filename[256] = {0};
INT rc = sprintf_s(filename, sizeof(filename), "cert-%02d.der", i);
FILE* fp = NULL;
errno_t et = fopen_s(&fp, filename, "w");
FileCleanup cleanup3(fp);
BYTE* pCert = pCertContext->pbCertEncoded;
DWORD dwSize = pCertContext->cbCertEncoded;
fwrite(pCert, (size_t)dwSize, 1, fp);
}
Unfortunately, neither Gutmann's dumpasn1 or OpenSSL's asn1parse can handle them. Humorously, Microsoft's own Certificates snap-in cannot parse it. There's a bug report on Microsoft Connect: CertEnumCertificatesInStore and friends provide a malformed certifcate.
They start out looking normal, but they break midway through parsing. For example, here's Gutmann's dumpasn1 on the Microsoft Root Certificate:
OpenSSL's asn1parse has the same complaint:
Finally, Microsoft has a few examples at Using Certificates.

sendto: Destination becomes 0.0.0.0 regardless of address passed

I'm writing a ping clone to practice socket programming. I'm able to send ICMP packets, but the destination address is 0.0.0.0 regardless of what I pass to sendto. Here is the most pertinent snip of code:
struct sockaddr_in dest;
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
if (0 == inet_aton(argv[1], &dest.sin_addr)) {
puts("could not parse address\n");
exit(EXIT_FAILURE);
}
ssize_t nbytes = sendto(sock, &hdr, ICMP_MINLEN, /*flags=*/0,
(struct sockaddr*)&dest, sizeof(dest));
The full program is on GitHub. I'm compiling on and for Mac OS X 10.6.8, and I'm using Wireshark 1.8.4 to verify the packets.
I have verified the value of dest.sin_addr.s_addr with a call to printf("%X"), and inet_aton is working as expected. I have even deliberately set it to 0x08080808 (Google's name server), and it still doesn't work.
What might I be doing wrong here?
There's one (copy-paste) bug in your full program on github:
struct sockaddr_in src;
memset(&dest, 0, sizeof(dest));
After declaring src, you memset dest again. This means that dest's sin_addr member is now 0 so you're requesting a destination address of 0.0.0.0.
As an aside, src's sin_port is left uninitialised so you may sometimes get other errors if you end up requesting a local port that is already in use.

Capturing packets on Windows 7

I am trying to capture all of transferred packets on a computer. My code works fine in Windows XP but it only captures outgoing packets on Windows 7 and cannot see incoming packets.
Here is a version of the code which just calculate the size of received packets (it seems big but most of it is just definitions). This code works correctly on Windows XP but nothing happens on Windows 7 (it stuck at recvfrom) (the code is complete and you could give a try on Win7):
#include <Winsock2.h>
#include <Mstcpip.h>
#include <iostream>
#include <string>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
struct SIP4HEADER
{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short ident; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
u_short crc; // Header checksum
u_long saddr; // Source address
u_long daddr; // Destination address
u_int op_pad; // Option + Padding
};
// Error handling parts is removed for clarity
void main()
{
WSAData wsa={0};
WSAStartup(MAKEWORD(2,2),&wsa);
string strIPAddress;
cout << "Enter a local IP address to monitor: ";
cin >> strIPAddress;
SOCKET ListenSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
sockaddr_in sa_in;
sa_in.sin_family = AF_INET;
sa_in.sin_addr.s_addr = inet_addr( strIPAddress.c_str() ); //My local IP address
sa_in.sin_port = htons(0);
bind(ListenSocket,(SOCKADDR *) &sa_in, sizeof(sa_in));
int rcv=RCVALL_IPLEVEL;
DWORD b=0;
WSAIoctl(ListenSocket,SIO_RCVALL,&rcv,sizeof(rcv),0,0,&b,0,0);
char buf[2000];
SIP4HEADER* ih = (SIP4HEADER*)buf;
DWORD ReceivedKBytes = 0;
DWORD t = 0;
while( recvfrom(ListenSocket,buf,_countof(buf),0,NULL,NULL)!=-1 )
{
if(sa_in.sin_addr.s_addr == ih->daddr)
t += ntohs(ih->tlen) ;
// update each 20KB
if(t > 20*1024)
{
t=0;
ReceivedKBytes += 20;
cout << "Received KBs: " << ReceivedKBytes << endl;
}
}
}
The only thing made me suspect was this article on MSDN who says:
A call to the bind function with a raw
socket for the IPPROTO_TCP protocol is
not allowed
but i am using IPPROTO_IP, and bind function documentation also says:
The bind function may also be used to
bind to a raw socket (the socket was
created by calling the socket function
with the type parameter set to
SOCK_RAW)
So it seems this is not the problem. Despite this, I don't get any error from calling bind and other functions in this code. I also omitted calling bind function which causes recvfrom make error 10022 Invalid argument. I also replaced IPPROTO_IP with IPPROTO_TCP but it doesn't help neither.
I am not sure whether I am doing it right or not, but this code works without any problem on Windows XP. Anyway, I am looking for a way to get received and sent packets related to a local IP address on Windows XP/7.
Also:
I am running this code on privileged (admin) mode in Windows 7.
The Winpcap or other third-party libraries is not an available option for me.
I had the same problem. Turned out it was Windows 7 Firewall that stopped the sniffer from seeing inbound data. Turned it off and finally, the code worked.
I run your code on my Win7 and it works. I do see following lines printed out:
Received KBs: 20
Received KBs: 40
Received KBs: 60
Received KBs: 80
Received KBs: 100
Probably check your firewall?

Resources