Allow manifests to provide signatures for packages. Restart the menus when a package with a menu.dat is enabled.

This commit is contained in:
Shpoike 2023-02-20 07:47:16 +00:00
parent c5f837d468
commit a5232cfecd
3 changed files with 99 additions and 7 deletions

View File

@ -2093,26 +2093,26 @@ void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const cha
pri = maxpri;
for (p = availablepackages; p; p = p->next)
{
if ((p->flags & DPF_ENABLED) && p->qhash && p->priority>=minpri&&p->priority<pri && !Q_strcasecmp(parent_pure, p->gamedir))
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->qhash && p->priority>=minpri&&p->priority<pri && !Q_strcasecmp(parent_pure, p->gamedir))
pri = p->priority;
}
minpri = pri+1;
for (p = availablepackages; p; p = p->next)
{
if ((p->flags & DPF_ENABLED) && p->qhash && p->priority==pri && !Q_strcasecmp(parent_pure, p->gamedir))
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->qhash && p->priority==pri && !Q_strcasecmp(parent_pure, p->gamedir))
{
for (d = p->deps; d; d = d->next)
{
if (d->dtype == DEP_FILE)
{
Q_snprintfz(temp, sizeof(temp), "%s/%s", p->gamedir, d->name);
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, search, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|SPF_UNTRUSTED);
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, search, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|((p->flags & DPF_SIGNATUREACCEPTED)?0:SPF_UNTRUSTED));
}
else if (d->dtype == DEP_CACHEFILE)
{
Q_snprintfz(temp, sizeof(temp), "downloads/%s", d->name);
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, NULL, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|SPF_UNTRUSTED);
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, NULL, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|((p->flags & DPF_SIGNATUREACCEPTED)?0:SPF_UNTRUSTED));
}
}
}
@ -3270,6 +3270,7 @@ static void PM_PackageEnabled(package_t *p)
if (dep->dtype != DEP_FILE && dep->dtype != DEP_CACHEFILE)
continue;
COM_FileExtension(dep->name, ext, sizeof(ext));
if (!pm_packagesinstalled)
if (!stricmp(ext, "pak") || !stricmp(ext, "pk3") || !stricmp(ext, "zip"))
{
if (pm_packagesinstalled)
@ -3420,6 +3421,10 @@ static qboolean PM_Download_Got_Extract(package_t *p, searchpathfuncs_t *archive
archive->ReadFile(archive, &loc, f);
if (FS_WriteFile(destname, f, loc.len, p->fsroot))
{
if (!FS_NativePath(destname, p->fsroot, native, sizeof(native)))
Q_strncpyz(native, destname, sizeof(native));
Con_Printf("Extracted %s (to %s)\n", p->name, native);
p->flags = nfl;
success = true;
continue;
@ -4672,6 +4677,17 @@ void PM_Command_f(void)
Con_Printf(" ^[[Add]\\type\\pkg add %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
if ((p->flags&DPF_MARKED) && p == PM_MarkedPackage(p->name, DPF_MARKED))
Con_Printf(" ^[[Remove]\\type\\pkg rem %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
if (p->flags & DPF_SIGNATUREACCEPTED)
Con_Printf(" ^&02Trusted");
else if (p->flags & DPF_SIGNATUREREJECTED)
Con_Printf(" ^&04Untrusted");
else if (p->flags & DPF_SIGNATUREUNKNOWN)
Con_Printf(" ^&0EUnverified");
else
Con_Printf(" ^&0EUnsigned");
Con_Printf("\n");
}
Z_Free(sorted);
@ -5041,6 +5057,15 @@ void PM_AddManifestPackages(ftemanifest_t *man)
p->flags = DPF_FORGETONUNINSTALL|DPF_MANIFEST|DPF_GUESSED;
p->qhash = pack->crcknown?Z_StrDupf("%#x", pack->crc):NULL;
//note that this signs the hash(validated with size) with an separately trusted authority and is thus not dependant upon trusting the manifest itself...
//that said, we can't necessarily trust any overrides the manifest might include - those parts do not form part of the signature.
if (!pack->prefix && pack->crcknown && strchr(p->name, '/'))
{
p->signature = pack->signature?Z_StrDup(pack->signature):NULL;
p->filesha512 = pack->sha512?Z_StrDup(pack->sha512):NULL;
p->filesize = pack->filesize;
}
{
char *c = p->name;
for (c=p->name; *c; c++) //don't get confused.
@ -5106,6 +5131,8 @@ void PM_AddManifestPackages(ftemanifest_t *man)
}
PM_AddDep(p, DEP_FILE, path);
PM_ValidateAuthenticity(p, VH_UNSUPPORTED);
m = PM_InsertPackage(p);
if (!m)
continue;

View File

@ -797,6 +797,9 @@ typedef struct
unsigned int crc; //the public crc
char *mirrors[8]; //a randomized (prioritized-on-load) list of mirrors to use. (may be 'prompt:game,package', 'unzip:file,url', 'xz:url', 'gz:url'
char *condition; //only downloaded if this cvar is set | delimited allows multiple cvars.
char *sha512; //package must match this hash, if specified
char *signature; //signs the hash
qofs_t filesize;
int mirrornum; //the index we last tried to download from, so we still work even if mirrors are down.
} package[64];
} ftemanifest_t;

View File

@ -189,7 +189,7 @@ qboolean Sys_ResolveFileURL(const char *inurl, int inlen, char *out, int outlen)
{ //has an authority field...
i+=2;
//except we don't support authorities other than ourself...
if (i < inend || *i != '/')
if (i >= inend || *i != '/')
return false; //must be an absolute path...
#ifdef _WIN32
i++; //on windows, (full)absolute paths start with a drive name...
@ -320,6 +320,8 @@ void FS_Manifest_Free(ftemanifest_t *man)
Z_Free(man->package[i].path);
Z_Free(man->package[i].prefix);
Z_Free(man->package[i].condition);
Z_Free(man->package[i].sha512);
Z_Free(man->package[i].signature);
for (j = 0; j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
Z_Free(man->package[i].mirrors[j]);
}
@ -372,12 +374,20 @@ static ftemanifest_t *FS_Manifest_Clone(ftemanifest_t *oldm)
}
for (i = 0; i < sizeof(newm->package) / sizeof(newm->package[0]); i++)
{
newm->package[i].type = oldm->package[i].type;
newm->package[i].crc = oldm->package[i].crc;
newm->package[i].crcknown = oldm->package[i].crcknown;
if (oldm->package[i].path)
newm->package[i].path = Z_StrDup(oldm->package[i].path);
if (oldm->package[i].prefix)
newm->package[i].prefix = Z_StrDup(oldm->package[i].prefix);
if (oldm->package[i].condition)
newm->package[i].condition = Z_StrDup(oldm->package[i].condition);
if (oldm->package[i].sha512)
newm->package[i].sha512 = Z_StrDup(oldm->package[i].sha512);
if (oldm->package[i].signature)
newm->package[i].signature = Z_StrDup(oldm->package[i].signature);
newm->package[i].filesize = oldm->package[i].filesize;
for (j = 0; j < sizeof(newm->package[i].mirrors) / sizeof(newm->package[i].mirrors[0]); j++)
if (oldm->package[i].mirrors[j])
newm->package[i].mirrors[j] = Z_StrDup(oldm->package[i].mirrors[j]);
@ -483,10 +493,16 @@ static void FS_Manifest_Print(ftemanifest_t *man)
else
Con_Printf("package ");
Con_Printf("%s", COM_QuotedString(man->package[i].path, buffer, sizeof(buffer), false));
if (man->package[i].condition)
Con_Printf(" prefix %s", COM_QuotedString(man->package[i].condition, buffer, sizeof(buffer), false));
if (man->package[i].prefix)
Con_Printf(" prefix %s", COM_QuotedString(man->package[i].prefix, buffer, sizeof(buffer), false));
if (man->package[i].condition)
Con_Printf(" condition %s", COM_QuotedString(man->package[i].condition, buffer, sizeof(buffer), false));
if (man->package[i].filesize)
Con_Printf(" filesize %"PRIuQOFS, man->package[i].filesize);
if (man->package[i].sha512)
Con_Printf(" sha512 %s", COM_QuotedString(man->package[i].sha512, buffer, sizeof(buffer), false));
if (man->package[i].signature)
Con_Printf(" signature %s", COM_QuotedString(man->package[i].signature, buffer, sizeof(buffer), false));
if (man->package[i].crcknown)
Con_Printf(" crc 0x%x", man->package[i].crc);
for (j = 0; j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
@ -552,6 +568,9 @@ static qboolean FS_Manifest_ParsePackage(ftemanifest_t *man, int packagetype)
char *condition = NULL;
char *prefix = NULL;
char *arch = NULL;
char *signature = NULL;
char *sha512 = NULL;
qofs_t filesize = 0;
unsigned int arg = 1;
unsigned int mirrors = 0;
char *mirror[countof(man->package[0].mirrors)];
@ -598,6 +617,12 @@ static qboolean FS_Manifest_ParsePackage(ftemanifest_t *man, int packagetype)
prefix = Cmd_Argv(arg++);
else if (!strcmp(a, "arch"))
arch = Cmd_Argv(arg++);
else if (!strcmp(a, "signature"))
signature = Cmd_Argv(arg++);
else if (!strcmp(a, "sha512"))
sha512 = Cmd_Argv(arg++);
else if (!strcmp(a, "filesize")||!strcmp(a, "size"))
filesize = strtoull(Cmd_Argv(arg++), NULL, 0);
else if (!strcmp(a, "mirror"))
{
a = Cmd_Argv(arg++);
@ -642,6 +667,9 @@ mirror:
man->package[i].path = Z_StrDup(path);
man->package[i].prefix = prefix?Z_StrDup(prefix):NULL;
man->package[i].condition = condition?Z_StrDup(condition):NULL;
man->package[i].sha512 = sha512?Z_StrDup(sha512):NULL;
man->package[i].signature = signature?Z_StrDup(signature):NULL;
man->package[i].filesize = filesize;
man->package[i].crcknown = crcknown;
man->package[i].crc = crc;
for (j = 0; j < mirrors; j++)
@ -3529,6 +3557,7 @@ void FS_AddHashedPackage(searchpath_t **oldpaths, const char *parentpath, const
static void FS_AddManifestPackages(searchpath_t **oldpaths, const char *purepath, const char *logicalpaths, searchpath_t *search, unsigned int loadstuff)
{
#ifndef PACKAGEMANAGER
int i;
int ptlen, palen;
@ -3552,6 +3581,7 @@ static void FS_AddManifestPackages(searchpath_t **oldpaths, const char *purepath
);
}
}
#endif
}
static void FS_AddDownloadManifestPackages(searchpath_t **oldpaths, unsigned int loadstuff)//, const char *purepath, searchpath_t *search, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc))
@ -6141,6 +6171,8 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
char *vidfile[] = {"gfx.wad", "gfx/conback.lmp", //misc stuff
"gfx/palette.lmp", "pics/colormap.pcx", "gfx/conchars.png"}; //palettes
searchpathfuncs_t *vidpath[countof(vidfile)];
char *menufile[] = {"menu.dat"/*mods*/, "gfx/ttl_main.lmp"/*q1*/, "pics/m_main_quit.pcx"/*q2*/, "gfx/menu/title0.lmp"/*h2*/};
searchpathfuncs_t *menupath[countof(menufile)];
#endif
//if any of these files change location, the configs will be re-execed.
@ -6159,6 +6191,16 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
else
vidpath[i] = NULL;
}
for (i = 0; i < countof(menufile); i++)
{
if (allowreloadconfigs)
{
FS_FLocateFile(menufile[i], FSLF_IFFOUND|FSLF_SECUREONLY, &loc);
menupath[i] = loc.search?loc.search->handle:NULL;
}
else
menupath[i] = NULL;
}
#endif
if (allowreloadconfigs && fs_noreexec.ival)
@ -6439,6 +6481,12 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
}
#endif
//our basic filesystem should be okay, but no packages loaded yet.
#ifdef MANIFESTDOWNLOADS
//make sure the package manager knows what its meant to know...
PM_AddManifestPackages(man);
#endif
if (Sys_LockMutex(fs_thread_mutex))
{
#ifdef HAVE_CLIENT
@ -6537,6 +6585,20 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
vidrestart = false;
}
if (qrenderer != QR_NONE && allowreloadconfigs)
{
for (i = 0; i < countof(menufile); i++)
{
FS_FLocateFile(menufile[i], FSLF_IFFOUND, &loc);
if (menupath[i] != (loc.search?loc.search->handle:NULL))
{
Cbuf_AddText ("menu_restart\n", RESTRICT_LOCAL);
break;
}
}
}
#endif
//rebuild the cache now, should be safe to waste some cycles on it