SSL(Sockets Secure Layer)

Started by
8 comments, last by Diego Mendieta 20 years, 4 months ago
please consider the following code, I can't establish a SSL connection with the server nexus.passport.com:443, dont know why. It seems that the server waits for more data after the first package is send, and after a while it kills the conection. please help me thx Diego Mendieta

#include "stdafx.h"
#include<Winsock2.h>
#include<string.h>

//Sockets and conection stuff

WSADATA WsaData;
SOCKET Socket; 
SOCKADDR_IN SockAddr;
int gErrorBuffer;

bool conectar(char* XRF)//if XRF==NULL, this function conects to nexus.passport.com:443

{
	if((gErrorBuffer=WSAStartup(MAKEWORD(1, 1), &WsaData)))
	{
		switch(gErrorBuffer)
		{
			case WSASYSNOTREADY:
				MessageBox(NULL,"Error, la capa inferior del sub-sistema de red no esta lista para comunicaciones de red.","ERROR",MB_OK);
				break;
			case WSAVERNOTSUPPORTED:
				MessageBox(NULL,"Error, la Version de Sockets usada para la implementacion de red no es compatible con la version otorgada por esta version de windows.","ERROR",MB_OK);
				break;
			case WSAEINPROGRESS:
				MessageBox(NULL,"Error, un bloqueo de red esta en proceso.","ERROR",MB_OK);
				break;
			case WSAEPROCLIM:
				MessageBox(NULL,"Error, el limite de tareas de red a sido alcanzado.","ERROR",MB_OK);
				break;
			default:
				MessageBox(NULL,"Error desconocido al iniciar procesos de red.","ERROR",MB_OK);
				break;
		}
		return false;
	}
	Socket = socket(AF_INET, SOCK_STREAM, 0);
	if (Socket == INVALID_SOCKET)
	{
		MessageBox(NULL,"Error en la inicializacion de Sockets.","ERROR",MB_OK);
		return false;
	}
	if(XRF)
	{
		int b1,b2,b3,b4,p;
		sscanf(XRF,"%d %d %d %d %d",&b1,&b2,&b3,&b4,&p);
		SockAddr.sin_port = htons(p);
		SockAddr.sin_family = AF_INET; 

		SockAddr.sin_addr.S_un.S_un_b.s_b1 = (unsigned char) b1;
		SockAddr.sin_addr.S_un.S_un_b.s_b2 = (unsigned char) b2;
		SockAddr.sin_addr.S_un.S_un_b.s_b3 = (unsigned char) b3;
		SockAddr.sin_addr.S_un.S_un_b.s_b4 = (unsigned char) b4;
		
	}
	else
	{
        SockAddr.sin_port = htons(443);
		SockAddr.sin_family = AF_INET; 
		HOSTENT *HostInfo;
		HostInfo = gethostbyname("nexus.passport.com");
		if (!HostInfo) 
		{
			MessageBox(NULL,"Error, no se encuentra al servidor.","ERROR",MB_OK);
			return false;
		}
		SockAddr.sin_addr.S_un.S_un_b.s_b1 =(unsigned char)HostInfo->h_addr_list[0][0]; 
		SockAddr.sin_addr.S_un.S_un_b.s_b2 =(unsigned char)HostInfo->h_addr_list[0][1]; 
		SockAddr.sin_addr.S_un.S_un_b.s_b3 =(unsigned char)HostInfo->h_addr_list[0][2]; 
		SockAddr.sin_addr.S_un.S_un_b.s_b4 =(unsigned char)HostInfo->h_addr_list[0][3]; 
	}

	if (connect(Socket, (SOCKADDR *)(&SockAddr), sizeof(SockAddr)))
	{
		MessageBox(NULL,"Error, los servidores de microsoft estan en reparacion o fuera de servicio.","ERROR",MB_OK);
		return false;
	}
	return true;
}


//Here is where I build my SSL pack1:

#define uint8	unsigned char
#define uint16	long
#define uint32	unsigned int

#pragma pack(1) //Tells MSVC to pack structs to 1 byte alignements rather than the default 4


struct ProtocolVersion { uint8 major, minor; };
struct Random {	uint32 gmt_unix_time; uint8 random_bytes[32]; };

struct ClientHello {
	ProtocolVersion client_version;
	Random random;
	uint32 session_id;
	uint8 cipher_suites[2];//{ 0x00,0x01 };		//CompressionMethod compression_methods

	uint8 compression_methods;//0

};

struct Handshake {	
	uint8 msg_type;
	uint8 length[3];
	ClientHello var;
};

struct SSLPlainText {
	uint8 type;
	ProtocolVersion version;
	uint16 length;
	Handshake fragment;
};

struct SSLCompressed {
	uint8 type;
	ProtocolVersion version;
	uint16 length;
	SSLPlainText fragment;
};

struct CipherSpec {
	uint8 bulk_cipher_algorithm;
	uint8 mac_algorithm;
	uint8 cipher_type;
	uint8 is_exportable;
	uint8 hash_size;
	uint8 key_material;
	uint8 IV_size;
};

struct GenericStreamCipher {
	SSLCompressed content;
};

struct SSLCiphertext {
	uint8 type;
	ProtocolVersion version;
	uint16 lenght;
	GenericStreamCipher fragment;
};

//this is the first (and only) package that's going to be send to the server

SSLCiphertext pack1;

#pragma pack() //Tells MSVC to use it's default packing method (4 bytes).


//This function Initializes all the data that I need to send, in the first package:

void init()
{
	pack1.fragment.content.fragment.fragment.var.client_version.major=3;
	pack1.fragment.content.fragment.fragment.var.client_version.minor=0;
	pack1.fragment.content.fragment.fragment.var.random.gmt_unix_time=240;
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[0]='q';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[1]='w';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[2]='g';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[3]='g';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[4]='h';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[5]='y';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[6]='i';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[7]='7';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[8]='t';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[9]='d';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[10]='g';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[11]='g';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[12]='y';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[13]='o'; 
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[14]='p';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[15]='2';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[16]='x';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[17]='d';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[18]='t';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[19]='h';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[20]='j';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[21]='i';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[22]='7';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[23]='e';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[24]='|';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[25]='c';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[26]='f';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[27]='6';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[28]='y';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[29]='u';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[30]='i';
	pack1.fragment.content.fragment.fragment.var.random.random_bytes[31]='5';

	pack1.fragment.content.fragment.fragment.var.compression_methods=0;
	pack1.fragment.content.fragment.fragment.var.session_id=0;
	pack1.fragment.content.fragment.fragment.var.cipher_suites[0]=0x00;
	pack1.fragment.content.fragment.fragment.var.cipher_suites[1]=0x01;

	pack1.fragment.content.fragment.fragment.length[0]=0;
	pack1.fragment.content.fragment.fragment.length[1]=0;
	pack1.fragment.content.fragment.fragment.length[2]=sizeof(ClientHello);

	pack1.fragment.content.fragment.fragment.msg_type=1;//clienthello;


	pack1.fragment.content.fragment.type=22;//handshake;

	pack1.fragment.content.fragment.length=sizeof(Handshake);
	pack1.fragment.content.fragment.version=pack1.fragment.content.fragment.fragment.var.client_version;

	pack1.fragment.content.length=sizeof(SSLPlainText);
	pack1.fragment.content.type=pack1.fragment.content.fragment.type;
	pack1.fragment.content.version=pack1.fragment.content.fragment.version;
	
	pack1.lenght=sizeof(GenericStreamCipher);
	pack1.type=pack1.fragment.content.type;
	pack1.version=pack1.fragment.content.version;
}

//Main

int main(int argc, _TCHAR* argv[])
{
	char buffer[1024]="";	//buffer, for recv

	init();					//sets all data in pack1

	conectar(NULL);			//conects to nexus


	send(Socket,(char *)&pack1,sizeof(pack1),0); //sends pack1

	int error = recv(Socket,buffer,1023,0);		//tryies to recieve what should be a server hello structure

	error=WSAGetLastError();					//indentifies the error, which is WSAECONNRESET

	/* MSDN says about it:
	The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket as it is no longer usable. On a UPD-datagram socket this error would indicate that a previous send operation resulted in an ICMP "Port Unreachable" message.*/
	shutdown(Socket,0);


	return 0;
}
[edited by - Diego Mendieta on December 17, 2003 2:39:53 PM]
Advertisement
I can''t help you make it work directly, but a hint:

The line:
pack1.fragment.content.fragment.fragment.length[2]=0; 

is called three times, i assume you mean length[0]/[1] respectively.

But that still don''t work.

I''m working on a SSL connector right now too, and had the same problem (no or empty answer from host). I used a packet sniffer and looked at the request IE sent to the address. I noticed that in the "CONNECT" request before the client hello (i''m behind a proxy) i sent one byte too much. When i removed that byte everything worked, i got a server hello response.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

thx,
I'll already changed it to:
	pack1.fragment.content.fragment.fragment.length[0]=0;	pack1.fragment.content.fragment.fragment.length[1]=0;	pack1.fragment.content.fragment.fragment.length[2]=sizeof(ClientHello);

but I still have the same problem

quote:
I'm working on a SSL connector right now too, and had the same problem (no or empty answer from host). I used a packet sniffer and looked at the request IE sent to the address. I noticed that in the "CONNECT" request before the client hello (i'm behind a proxy) i sent one byte too much. When i removed that byte everything worked, i got a server hello response.

I'm not behind a proxy, how can I fix my connect request,
it will be better if we can chat my msn is d_iego@msn.com and my #ICQ is 148687884,
please contact me, thx

[edited by - Diego Mendieta on December 17, 2003 2:45:24 PM]
Sorry, no IM for me.

Your best bet will be to install a port sniffer like Ethereal and let IE connect to a ssl protected site. Examine the packet and compare.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

A little off topic...
You call shutdown(), but never closesocket(), so you have a resource leak. Its not related to your problem though - No idea how to fix that, sorry.
I downloaded and installed Ethereal, but I get the folloing error while trying to capture packets:

The capture session could not be initiated (Error opening adapter: The system cannot open the file.).
Please check that you have the proper interface specified.

Note that the driver Ethereal uses for packet capture on Windows doesn''t support capturing on PPP/WAN interfaces in Windows NT/2000/XP/.Net Server.

I tried with the only 2 interfaces avaible and I get the same error. I''m running windows XP with a modem connection, what should I do?

thx for all the help so far.
Diego Mendieta
hmm, strange.

I have only one interface availabe in Ethereal (my network card) and it works ok. This sounds like a problem with Ethereal though.

This is the packet i send, it works with nexus too. It's quite glued together from various sources, but it works. BTW, there's a complete trace sample on http://wp.netscape.com/eng/ssl3/traces/trc-clnt-ex.html.

    pData[0] = 0x80;      // Size    pData[1] = 0x1f;      // Size Pt.2    // Client says Hello!    pData[2] = 0x01;    // Client wishes to use Version 2.0 later    pData[3] = 0x03;    pData[4] = 0x00;    // Cipher Specs Length = 6    pData[5] = 0x00;    pData[6] = 0x06;    // Session ID = 0    pData[7] = 0x00;    pData[8] = 0x00;    // Challenge Length = 16    pData[9] = 0x00;    pData[10] = 0x10;    // Challenge Specs Data    pData[11] = 0x00;    pData[12] = 0x00;    pData[13] = 0x03;     pData[14] = 0x00;    pData[15] = 0x00;    pData[16] = 0x06;    pData[17] = 0x90;    pData[18] = 0x06;    pData[19] = 0x46;    pData[20] = 0x69;    pData[21] = 0x20;    pData[22] = 0x81;    pData[23] = 0x64;    pData[24] = 0x08;    pData[25] = 0xba;    pData[26] = 0xb4;    pData[27] = 0x3f;    pData[28] = 0x9f;    pData[29] = 0x81;    pData[30] = 0xfa;    pData[31] = 0x5b;    pData[32] = 0x20;


[edit:dang, why do they have different source tags on every board]

[edited by - Endurion on December 19, 2003 3:40:34 AM]

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

ok, it works, but as the netscape documentations says, its a SSL V 2.0 protocol
quote:
This differs from an ordinary SSL V2 client_hello message in one aspect, the version number field indicates version 3, not version 2. An SSl server that supports both versions 2 and 3 will reply to such a message with a version 3 server_hello, as seen below.


I want to do it with pure ssl v3.0
Ok, I found many errors in my code, and I organized it differently, here is the new code for the first message send to nexus(client_hello):

	//handshake:	sData[0]=0x16;	//version:	sData[1]=0x03;	sData[2]=0x00;	//rec package length:	sData[3]=0x00;	sData[4]=0x2d;	//type= client_hello	sData[5]=0x01;	//package length:	sData[6]=0x00;	sData[7]=0x00;	sData[8]=0x29;	//version:	sData[9]=0x03;	sData[10]=0x00;	//Random data:	sData[11]=0x00;//Random 1	sData[12]=0x00;//Random 2	sData[13]=0x00;//Random 3	sData[14]=0xf0;//Random 4	sData[15]=0x13;//Random 5	sData[16]=0x43;//Random 6	sData[17]=0xf4;//Random 7	sData[18]=0xe5;//Random 8	sData[19]=0xc5;//Random 9	sData[42]=0xf6;//Random 10	sData[20]=0x54;//Random 11	sData[21]=0x18;//Random 12	sData[22]=0xe4;//Random 13	sData[23]=0xa5;//Random 14	sData[24]=0x65;//Random 15	sData[25]=0x2d;//Random 16	sData[26]=0x56;//Random 17	sData[27]=0x6b;//Random 18	sData[28]=0x2d;//Random 19	sData[29]=0xb2;//Random 20	sData[30]=0x1b;//Random 21	sData[31]=0x1c;//Random 22	sData[32]=0x2a;//Random 23	sData[33]=0xa2;//Random 24	sData[34]=0xa2;//Random 25	sData[35]=0xb2;//Random 26	sData[36]=0x46;//Random 27	sData[37]=0xc6;//Random 28	sData[38]=0x1c;//Random 29	sData[39]=0x19;//Random 30	sData[40]=0xb2;//Random 31	sData[41]=0x1a;//Random 32	//sessionid_length:	sData[43]=0x00;	//cipher_suites_length:	sData[44]=0x00;	sData[45]=0x02;	//cipher_suites:	sData[46]=0x00;	sData[47]=0x00;	//compression_methods_length:	sData[48]=0x01;	//compression_methods:	sData[49]=0x00;


after sending this first package, I get "gracefully" disconected
I finally acomplished a communication with nexus, using ssl, thx for all the help

This topic is closed to new replies.

Advertisement