|
static size_t | ReceiveCallback (void *buffer, size_t size, size_t nmemb, void *userp) |
|
static size_t | DownloadCallback (void *buffer, size_t size, size_t nmemb, void *userp) |
|
static int | DownloadProgressCallback (void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) |
|
static bool | ParseGameIdResponse (const ScriptInterface &scriptInterface, const std::string &responseData, int &id, std::string &err) |
| Parses the current content of m_ResponseData to extract m_GameId. More...
|
|
static bool | ParseModsResponse (const ScriptInterface &scriptInterface, const std::string &responseData, std::vector< ModIoModData > &modData, const PKStruct &pk, std::string &err) |
| Parses the current content of m_ResponseData into m_ModData. More...
|
|
static bool | ParseSignature (const std::vector< std::string > &minisigs, SigStruct &sig, const PKStruct &pk, std::string &err) |
| Parse signatures to find one that matches the public key, and has a valid global signature. More...
|
|
mod.io API interfacing code.
Overview
This class interfaces with a remote API provider that returns a list of mod files. These can then be downloaded after some cursory checking of well-formedness of the returned metadata. Downloaded files are checked for well formedness by validating that they fit the size and hash indicated by the API, then we check if the file is actually signed by a trusted key, and only if all of that is success the file is actually possible to be loaded as a mod.
Security considerations
This both distrusts the loaded JS mods, and the API as much as possible. We do not want a malicious mod to use this to download arbitrary files, nor do we want the API to make us download something we have not verified. Therefore we only allow mods to download one of the mods returned by this class (using indices).
This (mostly) necessitates parsing the API responses here, as opposed to in JS. One could alternatively parse the responses in a locked down JS context, but that would require storing that code in here, or making sure nobody can overwrite it. Also this would possibly make some of the needed accesses for downloading and verifying files a bit more complicated.
Everything downloaded from the API has its signature verified against our public key. This is a requirement, as otherwise a compromise of the API would result in users installing possibly malicious files. So a compromised API can just serve old files that we signed, so in that case there would need to be an issue in that old file that was missed.
To limit the extend to how old those files could be the signing key should be rotated regularly (e.g. every release). To allow old versions of the engine to still use the API files can be signed by both the old and the new key for some amount of time, that however only makes sense in case a mod is compatible with both engine versions.
Note that this does not prevent all possible attacks a package manager/update system should defend against. This is intentionally not an update system since proper package managers already exist. However there is some possible overlap in attack vectors and these should be evalutated whether they apply and to what extend we can fix that on our side (or how to get the API provider to help us do so). For a list of some possible issues see: https://github.com/theupdateframework/specification/blob/master/tuf-spec.md
The mod.io settings are also locked down such that only mods that have been authorized by us show up in API queries. This is both done so that all required information (dependencies) are stored for the files, and that only mods that have been checked for being ok are actually shown to users.