mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-08-04 03:07:07 -04:00
macOS: Switch to BearSSL
This commit is contained in:
parent
c0cf269159
commit
1de9fa76f9
File diff suppressed because it is too large
Load Diff
15
readme.md
15
readme.md
@ -60,20 +60,20 @@ Don't forget to add `-DCC_BUILD_GL11` to the compilation command line so that th
|
||||
ClassiCube runs on:
|
||||
* Windows - 95 and later
|
||||
* macOS - 10.5 or later (can be compiled for 10.3/10.4 though)
|
||||
* Linux - needs `libcurl` and `libopenal`
|
||||
* Linux - needs `libopenal`
|
||||
* Android - 2.3 or later
|
||||
* iOS - 8.0 or later
|
||||
* Most web browsers (even runs on IE11)
|
||||
|
||||
And also runs on:
|
||||
* Raspberry Pi - needs <code>libcurl</code> and <code>libopenal</code>
|
||||
* FreeBSD - needs <code>libexecinfo</code>, <code>curl</code> and <code>openal-soft</code> packages (can [download from here](https://www.classicube.net/download/#dl-fbsd))
|
||||
* NetBSD - needs <code>libexecinfo</code>, <code>curl</code> and <code>openal-soft</code> packages (can [download from here](https://www.classicube.net/download/#dl-nbsd))
|
||||
* OpenBSD - needs <code>libexecinfo</code>, <code>curl</code> and <code>openal</code> packages
|
||||
* Solaris - needs <code>curl</code> and <code>openal</code> packages
|
||||
* Raspberry Pi - needs <code>libopenal</code>
|
||||
* FreeBSD - needs <code>libexecinfo</code> and <code>openal-soft</code> packages (can [download from here](https://www.classicube.net/download/#dl-fbsd))
|
||||
* NetBSD - needs <code>libexecinfo</code> and <code>openal-soft</code> packages (can [download from here](https://www.classicube.net/download/#dl-nbsd))
|
||||
* OpenBSD - needs <code>libexecinfo</code> and <code>openal</code> packages
|
||||
* Solaris - needs <code>openal</code> packages
|
||||
* Haiku - needs <code>openal</code> package (if you have a GitHub account, can [download from here](https://github.com/ClassiCube/ClassiCube/actions/workflows/build_haiku.yml))
|
||||
* BeOS - untested on actual hardware
|
||||
* IRIX - needs <code>curl</code> and <code>openal</code> packages
|
||||
* IRIX - needs <code>openal</code> packages
|
||||
* SerenityOS - needs <code>SDL2</code>
|
||||
* Classic Mac OS (System 7 and later)
|
||||
* Dreamcast - unfinished, but usable (can [download from here](https://www.classicube.net/download/dreamcast))
|
||||
@ -427,7 +427,6 @@ Further information (e.g. style) for ClassiCube's source code can be found in th
|
||||
<details>
|
||||
<summary><h2>Open source technologies (click to expand)</h2></summary>
|
||||
|
||||
* [curl](https://curl.se/) - HTTP/HTTPS for linux and macOS
|
||||
* [FreeType](https://www.freetype.org/) - Font handling for all platforms
|
||||
* [GCC](https://gcc.gnu.org/) - Compiles client for linux
|
||||
* [MinGW-w64](http://mingw-w64.org/doku.php) - Compiles client for windows
|
||||
|
32
src/Certs.c
32
src/Certs.c
@ -186,6 +186,10 @@ int Certs_VerifyChain(struct X509CertContext* chain) {
|
||||
#include <Security/SecPolicy.h>
|
||||
#include <Security/SecTrust.h>
|
||||
#include <Security/SecCertificate.h>
|
||||
#ifdef CC_BUILD_MACOS
|
||||
#include <Security/SecPolicySearch.h>
|
||||
#include <Security/oidsalg.h>
|
||||
#endif
|
||||
#include "Errors.h"
|
||||
|
||||
void CertsBackend_Init(void) {
|
||||
@ -196,7 +200,22 @@ static SecPolicyRef policy;
|
||||
|
||||
static void CreateChain(struct X509CertContext* x509, CFMutableArrayRef chain) {
|
||||
struct X509Cert* certs = x509->certs;
|
||||
for (int i = 0; i < x509->numCerts; i++)
|
||||
int i;
|
||||
|
||||
#ifdef CC_BUILD_MACOS
|
||||
/* Use older APIs that work on macOS earlier than 10.6 */
|
||||
for (i = 0; i < x509->numCerts; i++)
|
||||
{
|
||||
CSSM_DATA data;
|
||||
data.Data = certs[i].data;
|
||||
data.Length = certs[i].offset;
|
||||
|
||||
SecCertificateRef cert = NULL;
|
||||
int res = SecCertificateCreateFromData(&data, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert);
|
||||
if (!res && cert) CFArrayAppendValue(chain, cert);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < x509->numCerts; i++)
|
||||
{
|
||||
CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, certs[i].data, certs[i].offset, kCFAllocatorNull);
|
||||
|
||||
@ -204,10 +223,21 @@ static void CreateChain(struct X509CertContext* x509, CFMutableArrayRef chain) {
|
||||
if (cert) CFArrayAppendValue(chain, cert);
|
||||
CFRelease(data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void CreateX509Policy(void) {
|
||||
#ifdef CC_BUILD_MACOS
|
||||
SecPolicySearchRef search;
|
||||
int err = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &search);
|
||||
if (err) return;
|
||||
|
||||
err = SecPolicySearchCopyNext(search, &policy);
|
||||
CFRelease(search);
|
||||
#else
|
||||
/* Use older APIs that work on macOS earlier than 10.6 */
|
||||
policy = SecPolicyCreateBasicX509();
|
||||
#endif
|
||||
}
|
||||
|
||||
int Certs_VerifyChain(struct X509CertContext* x509) {
|
||||
|
@ -275,22 +275,21 @@ typedef cc_uint8 cc_bool;
|
||||
#elif defined __APPLE__
|
||||
#define CC_BUILD_DARWIN
|
||||
#define CC_BUILD_POSIX
|
||||
#define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN
|
||||
#define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL
|
||||
#define DEFAULT_CRT_BACKEND CC_CRT_BACKEND_APPLESEC
|
||||
#define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_OPENAL
|
||||
#if defined __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
|
||||
#define CC_BUILD_MOBILE
|
||||
#define CC_BUILD_GLES
|
||||
#define CC_BUILD_IOS
|
||||
#define CC_BUILD_TOUCH
|
||||
#define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2
|
||||
#define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN
|
||||
#define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL
|
||||
#define DEFAULT_CRT_BACKEND CC_CRT_BACKEND_APPLESEC
|
||||
#else
|
||||
#define DEFAULT_NET_BACKEND CC_NET_BACKEND_LIBCURL
|
||||
#define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_COCOA
|
||||
#define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1
|
||||
#define CC_BUILD_MACOS
|
||||
#endif
|
||||
#define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_OPENAL
|
||||
#elif defined Macintosh
|
||||
#define CC_BUILD_MACCLASSIC
|
||||
#define CC_BUILD_LOWMEM
|
||||
|
@ -126,243 +126,7 @@ static cc_string* Http_GetUserAgent_UNSAFE(void) {
|
||||
}
|
||||
|
||||
|
||||
#if CC_NET_BACKEND == CC_NET_BACKEND_LIBCURL
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------libcurl backend-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#include "Errors.h"
|
||||
#include <stddef.h>
|
||||
/* === BEGIN CURL HEADERS === */
|
||||
typedef void CURL;
|
||||
struct curl_slist;
|
||||
typedef int CURLcode;
|
||||
|
||||
#define CURL_GLOBAL_DEFAULT ((1<<0) | (1<<1)) /* SSL and Win32 options */
|
||||
#define CURLOPT_WRITEDATA (10000 + 1)
|
||||
#define CURLOPT_URL (10000 + 2)
|
||||
#define CURLOPT_ERRORBUFFER (10000 + 10)
|
||||
#define CURLOPT_WRITEFUNCTION (20000 + 11)
|
||||
#define CURLOPT_POSTFIELDS (10000 + 15)
|
||||
#define CURLOPT_USERAGENT (10000 + 18)
|
||||
#define CURLOPT_HTTPHEADER (10000 + 23)
|
||||
#define CURLOPT_HEADERDATA (10000 + 29)
|
||||
#define CURLOPT_VERBOSE (0 + 41)
|
||||
#define CURLOPT_HEADER (0 + 42)
|
||||
#define CURLOPT_NOBODY (0 + 44)
|
||||
#define CURLOPT_POST (0 + 47)
|
||||
#define CURLOPT_FOLLOWLOCATION (0 + 52)
|
||||
#define CURLOPT_POSTFIELDSIZE (0 + 60)
|
||||
#define CURLOPT_SSL_VERIFYPEER (0 + 64)
|
||||
#define CURLOPT_MAXREDIRS (0 + 68)
|
||||
#define CURLOPT_HEADERFUNCTION (20000 + 79)
|
||||
#define CURLOPT_HTTPGET (0 + 80)
|
||||
#define CURLOPT_SSL_VERIFYHOST (0 + 81)
|
||||
#define CURLOPT_HTTP_VERSION (0 + 84)
|
||||
|
||||
#define CURL_HTTP_VERSION_1_1 2L /* stick to HTTP 1.1 */
|
||||
|
||||
#if defined CC_BUILD_WIN
|
||||
#define APIENTRY __cdecl
|
||||
#else
|
||||
#define APIENTRY
|
||||
#endif
|
||||
|
||||
static CURLcode (APIENTRY *_curl_global_init)(long flags);
|
||||
static void (APIENTRY *_curl_global_cleanup)(void);
|
||||
static CURL* (APIENTRY *_curl_easy_init)(void);
|
||||
static CURLcode (APIENTRY *_curl_easy_perform)(CURL *c);
|
||||
static CURLcode (APIENTRY *_curl_easy_setopt)(CURL *c, int opt, ...);
|
||||
static void (APIENTRY *_curl_easy_cleanup)(CURL* c);
|
||||
static void (APIENTRY *_curl_slist_free_all)(struct curl_slist* l);
|
||||
static struct curl_slist* (APIENTRY *_curl_slist_append)(struct curl_slist* l, const char* v);
|
||||
static const char* (APIENTRY *_curl_easy_strerror)(CURLcode res);
|
||||
/* === END CURL HEADERS === */
|
||||
|
||||
#if defined CC_BUILD_WIN
|
||||
static const cc_string curlLib = String_FromConst("libcurl.dll");
|
||||
static const cc_string curlAlt = String_FromConst("curl.dll");
|
||||
#elif defined CC_BUILD_DARWIN
|
||||
static const cc_string curlLib = String_FromConst("libcurl.4.dylib");
|
||||
static const cc_string curlAlt = String_FromConst("libcurl.dylib");
|
||||
#elif defined CC_BUILD_NETBSD
|
||||
static const cc_string curlLib = String_FromConst("libcurl.so");
|
||||
static const cc_string curlAlt = String_FromConst("/usr/pkg/lib/libcurl.so");
|
||||
#elif defined CC_BUILD_BSD
|
||||
static const cc_string curlLib = String_FromConst("libcurl.so");
|
||||
static const cc_string curlAlt = String_FromConst("libcurl.so");
|
||||
#elif defined CC_BUILD_SERENITY
|
||||
static const cc_string curlLib = String_FromConst("/usr/local/lib/libcurl.so");
|
||||
static const cc_string curlAlt = String_FromConst("/usr/local/lib/libcurl.so");
|
||||
#elif defined CC_BUILD_OS2
|
||||
static const cc_string curlLib = String_FromConst("/@unixroot/usr/lib/curl4.dll");
|
||||
static const cc_string curlAlt = String_FromConst("/@unixroot/usr/local/lib/curl4.dll");
|
||||
#else
|
||||
static const cc_string curlLib = String_FromConst("libcurl.so.4");
|
||||
static const cc_string curlAlt = String_FromConst("libcurl.so.3");
|
||||
#endif
|
||||
|
||||
static cc_bool LoadCurlFuncs(void) {
|
||||
static const struct DynamicLibSym funcs[] = {
|
||||
#if !defined CC_BUILD_OS2
|
||||
DynamicLib_ReqSym(curl_global_init), DynamicLib_ReqSym(curl_global_cleanup),
|
||||
DynamicLib_ReqSym(curl_easy_init), DynamicLib_ReqSym(curl_easy_perform),
|
||||
DynamicLib_ReqSym(curl_easy_setopt), DynamicLib_ReqSym(curl_easy_cleanup),
|
||||
DynamicLib_ReqSym(curl_slist_free_all), DynamicLib_ReqSym(curl_slist_append),
|
||||
/* Non-essential function missing in older curl versions */
|
||||
DynamicLib_OptSym(curl_easy_strerror)
|
||||
#else
|
||||
DynamicLib_ReqSymC(curl_global_init), DynamicLib_ReqSymC(curl_global_cleanup),
|
||||
DynamicLib_ReqSymC(curl_easy_init), DynamicLib_ReqSymC(curl_easy_perform),
|
||||
DynamicLib_ReqSymC(curl_easy_setopt), DynamicLib_ReqSymC(curl_easy_cleanup),
|
||||
DynamicLib_ReqSymC(curl_slist_free_all), DynamicLib_ReqSymC(curl_slist_append),
|
||||
/* Non-essential function missing in older curl versions */
|
||||
DynamicLib_OptSymC(curl_easy_strerror)
|
||||
#endif
|
||||
};
|
||||
cc_bool success;
|
||||
void* lib;
|
||||
|
||||
success = DynamicLib_LoadAll(&curlLib, funcs, Array_Elems(funcs), &lib);
|
||||
if (!lib) {
|
||||
success = DynamicLib_LoadAll(&curlAlt, funcs, Array_Elems(funcs), &lib);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
static CURL* curl;
|
||||
static cc_bool curlSupported, curlVerbose;
|
||||
|
||||
static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) {
|
||||
const char* err;
|
||||
|
||||
if (!_curl_easy_strerror) return false;
|
||||
err = _curl_easy_strerror((CURLcode)res);
|
||||
if (!err) return false;
|
||||
|
||||
String_AppendConst(dst, err);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void HttpBackend_Init(void) {
|
||||
static const cc_string msg = String_FromConst("Failed to init libcurl. All HTTP requests will therefore fail.");
|
||||
CURLcode res;
|
||||
|
||||
if (!LoadCurlFuncs()) { Logger_WarnFunc(&msg); return; }
|
||||
res = _curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
if (res) { Logger_SimpleWarn(res, "initing curl"); return; }
|
||||
curl = _curl_easy_init();
|
||||
if (!curl) { Logger_SimpleWarn(res, "initing curl_easy"); return; }
|
||||
|
||||
curlSupported = true;
|
||||
curlVerbose = Options_GetBool("curl-verbose", false);
|
||||
}
|
||||
|
||||
static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value) {
|
||||
cc_string tmp; char tmpBuffer[1024];
|
||||
String_InitArray_NT(tmp, tmpBuffer);
|
||||
String_Format2(&tmp, "%c: %s", key, value);
|
||||
|
||||
tmp.buffer[tmp.length] = '\0';
|
||||
req->meta = _curl_slist_append((struct curl_slist*)req->meta, tmp.buffer);
|
||||
}
|
||||
|
||||
/* Processes a HTTP header downloaded from the server */
|
||||
static size_t Http_ProcessHeader(char* buffer, size_t size, size_t nitems, void* userdata) {
|
||||
struct HttpRequest* req = (struct HttpRequest*)userdata;
|
||||
size_t len = nitems;
|
||||
cc_string line;
|
||||
/* line usually has \r\n at end */
|
||||
if (len && buffer[len - 1] == '\n') len--;
|
||||
if (len && buffer[len - 1] == '\r') len--;
|
||||
|
||||
line = String_Init(buffer, len, len);
|
||||
Http_ParseHeader(req, &line);
|
||||
return nitems;
|
||||
}
|
||||
|
||||
/* Processes a chunk of data downloaded from the web server */
|
||||
static size_t Http_ProcessData(char *buffer, size_t size, size_t nitems, void* userdata) {
|
||||
struct HttpRequest* req = (struct HttpRequest*)userdata;
|
||||
|
||||
int ok = Http_BufferExpand(req, nitems);
|
||||
if (!ok) Process_Abort("Out of memory for HTTP request");
|
||||
|
||||
Mem_Copy(&req->data[req->size], buffer, nitems);
|
||||
Http_BufferExpanded(req, nitems);
|
||||
return nitems;
|
||||
}
|
||||
|
||||
/* Sets general curl options for a request */
|
||||
static void Http_SetCurlOpts(struct HttpRequest* req) {
|
||||
_curl_easy_setopt(curl, CURLOPT_USERAGENT, GAME_APP_NAME);
|
||||
_curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
_curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 20L);
|
||||
_curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
|
||||
_curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, Http_ProcessHeader);
|
||||
_curl_easy_setopt(curl, CURLOPT_HEADERDATA, req);
|
||||
_curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Http_ProcessData);
|
||||
_curl_easy_setopt(curl, CURLOPT_WRITEDATA, req);
|
||||
|
||||
if (curlVerbose) _curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
|
||||
if (httpsVerify) return;
|
||||
_curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
}
|
||||
|
||||
static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) {
|
||||
char urlStr[NATIVE_STR_LEN];
|
||||
void* post_data = req->data;
|
||||
CURLcode res;
|
||||
if (!curlSupported) return ERR_NOT_SUPPORTED;
|
||||
|
||||
req->meta = NULL;
|
||||
Http_SetRequestHeaders(req);
|
||||
_curl_easy_setopt(curl, CURLOPT_HTTPHEADER, req->meta);
|
||||
|
||||
Http_SetCurlOpts(req);
|
||||
String_EncodeUtf8(urlStr, url);
|
||||
_curl_easy_setopt(curl, CURLOPT_URL, urlStr);
|
||||
|
||||
if (req->requestType == REQUEST_TYPE_HEAD) {
|
||||
_curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
||||
} else if (req->requestType == REQUEST_TYPE_POST) {
|
||||
_curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
_curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, req->size);
|
||||
_curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->data);
|
||||
|
||||
/* per curl docs, we must persist POST data until request finishes */
|
||||
req->data = NULL;
|
||||
req->size = 0;
|
||||
} else {
|
||||
/* Undo POST/HEAD state */
|
||||
_curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
|
||||
}
|
||||
|
||||
/* must be at least CURL_ERROR_SIZE (256) in size */
|
||||
req->error = Mem_TryAllocCleared(257, 1);
|
||||
_curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, req->error);
|
||||
/* TODO stackalloc instead and then copy to dynamic array later? */
|
||||
/* probably not worth the extra complexity though */
|
||||
|
||||
req->_capacity = 0;
|
||||
req->progress = HTTP_PROGRESS_FETCHING_DATA;
|
||||
res = _curl_easy_perform(curl);
|
||||
req->progress = 100;
|
||||
|
||||
/* Free error string if it isn't needed */
|
||||
if (req->error && !req->error[0]) {
|
||||
Mem_Free(req->error);
|
||||
req->error = NULL;
|
||||
}
|
||||
|
||||
_curl_slist_free_all((struct curl_slist*)req->meta);
|
||||
/* can free now that request has finished */
|
||||
Mem_Free(post_data);
|
||||
_curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, NULL);
|
||||
return res;
|
||||
}
|
||||
#elif CC_NET_BACKEND == CC_NET_BACKEND_BUILTIN
|
||||
#if CC_NET_BACKEND == CC_NET_BACKEND_BUILTIN
|
||||
#include "Errors.h"
|
||||
#include "PackedCol.h"
|
||||
#include "SSL.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user