GetHTTPS.cpp 4.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 *	An demo illustrating how to retrieve a URI from a secure HTTP server.
 *
 *	Author: 	Roy Wood
 *	Date:		September 7, 1999
 *	Comments:	This relies heavily on my MacSockets library.
 *				This project is also set up so that it expects the OpenSSL source folder (0.9.4 as I write this)
 *				to live in a folder called "OpenSSL-0.9.4" in this project's parent folder.  For example:
 *
 *					Macintosh HD:
 *						Development:
 *							OpenSSL-0.9.4:
 *								(OpenSSL sources here)
 *							OpenSSL Example:
 *								(OpenSSL example junk here)
 *
 *
 *				Also-- before attempting to compile this, make sure the aliases in "OpenSSL-0.9.4:include:openssl" 
 *				are installed!  Use the AppleScript applet in the "openssl-0.9.4" folder to do this!
 */
21
/* modified to seed the PRNG */
22 23 24 25 26 27 28 29 30 31 32 33 34 35


//	Include some funky libs I've developed over time

#include "CPStringUtils.hpp"
#include "ErrorHandling.hpp"
#include "MacSocket.h"


//	We use the OpenSSL implementation of SSL....
//	This was a lot of work to finally get going, though you wouldn't know it by the results!

#include <openssl/ssl.h>
#include <openssl/err.h>
36
#include <openssl/rand.h>
37

38
#include <timer.h>
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

//	Let's try grabbing some data from here:

#define kHTTPS_DNS		"www.apache-ssl.org"
#define kHTTPS_Port		443
#define kHTTPS_URI		"/"


//	Forward-declare this

OSErr MyMacSocket_IdleWaitCallback(void *inUserRefPtr);





//	My idle-wait callback.  Doesn't do much, does it?  Silly cooperative multitasking.

OSErr MyMacSocket_IdleWaitCallback(void *inUserRefPtr)
{
#pragma unused(inUserRefPtr)

EventRecord		theEvent;

	::EventAvail(everyEvent,&theEvent);

	return(noErr);
}



//	Finally!

void main(void)
{
OSErr				errCode;
int					theSocket = -1;
int					theTimeout = 30;

SSL_CTX				*ssl_ctx = nil;
SSL					*ssl = nil;

char				tempString[256];
82
UnsignedWide		microTickCount;
83
	
84 85 86
#warning   -- USE A TRUE RANDOM SEED, AND ADD ENTROPY WHENEVER POSSIBLE. --
const char seed[] = "uyq9,7-b(VHGT^%$&^F/,876;,;./lkJHGFUY{PO*";	// Just gobbledygook

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
	printf("OpenSSL Demo by Roy Wood, roy@centricsystems.ca\n\n");
	
	BailIfError(errCode = MacSocket_Startup());



	//	Create a socket-like object
	
	BailIfError(errCode = MacSocket_socket(&theSocket,false,theTimeout * 60,MyMacSocket_IdleWaitCallback,nil));

	
	//	Set up the connect string and try to connect
	
	CopyCStrAndInsertCStrLongIntIntoCStr("%s:%ld",kHTTPS_DNS,kHTTPS_Port,tempString,sizeof(tempString));
	
	printf("Connecting to %s....\n",tempString);

	BailIfError(errCode = MacSocket_connect(theSocket,tempString));
	
	
	//	Init SSL stuff
	
	SSL_load_error_strings();
	
	SSLeay_add_ssl_algorithms();
	
	
	//	Pick the SSL method
	
//	ssl_ctx = SSL_CTX_new(SSLv2_client_method());
	ssl_ctx = SSL_CTX_new(SSLv23_client_method());
//	ssl_ctx = SSL_CTX_new(SSLv3_client_method());
			

121 122 123 124
	RAND_seed (seed, sizeof (seed));
	Microseconds (&microTickCount);
	RAND_add (&microTickCount, sizeof (microTickCount), 0);		// Entropy is actually > 0, needs an estimate

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
	//	Create an SSL thingey and try to negotiate the connection
	
	ssl = SSL_new(ssl_ctx);
	
	SSL_set_fd(ssl,theSocket);
	
	errCode = SSL_connect(ssl);
	
	if (errCode < 0)
	{
		SetErrorMessageAndLongIntAndBail("OpenSSL: Can't initiate SSL connection, SSL_connect() = ",errCode);
	}
	
	//	Request the URI from the host
	
	CopyCStrToCStr("GET ",tempString,sizeof(tempString));
	ConcatCStrToCStr(kHTTPS_URI,tempString,sizeof(tempString));
	ConcatCStrToCStr(" HTTP/1.0\r\n\r\n",tempString,sizeof(tempString));

	
	errCode = SSL_write(ssl,tempString,CStrLength(tempString));
	
	if (errCode < 0)
	{
		SetErrorMessageAndLongIntAndBail("OpenSSL: Error writing data via ssl, SSL_write() = ",errCode);
	}
	

	for (;;)
	{
	char	tempString[256];
	int		bytesRead;
		

		//	Read some bytes and dump them to the console
		
		bytesRead = SSL_read(ssl,tempString,sizeof(tempString) - 1);
		
		if (bytesRead == 0 && MacSocket_RemoteEndIsClosing(theSocket))
		{
			break;
		}
		
		else if (bytesRead < 0)
		{
			SetErrorMessageAndLongIntAndBail("OpenSSL: Error reading data via ssl, SSL_read() = ",bytesRead);
		}
		
		
		tempString[bytesRead] = '\0';
		
		printf(tempString);
	}
	
	printf("\n\n\n");
	
	//	All done!
	
	errCode = noErr;
	
	
EXITPOINT:

	//	Clean up and go home
	
	if (theSocket >= 0)
	{
		MacSocket_close(theSocket);
	}
	
	if (ssl != nil)
	{
		SSL_free(ssl);
	}
	
	if (ssl_ctx != nil)
	{
		SSL_CTX_free(ssl_ctx);
	}
	
	
	if (errCode != noErr)
	{
		printf("An error occurred:\n");
		
		printf(GetErrorMessage());
	}
	
	
	MacSocket_Shutdown();
}